// Copyright 2017 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.vfs;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;

import com.google.common.testing.EqualsTester;
import com.google.devtools.build.lib.vfs.WindowsOsPathPolicy.ShortPathResolver;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests windows-specific parts of {@link Path} */
@RunWith(JUnit4.class)
public class WindowsPathTest extends PathAbstractTest {

  private static final class MockShortPathResolver implements ShortPathResolver {
    // Full path to resolved child mapping.
    private Map<String, String> resolutions = new HashMap<>();

    @Override
    public String resolveShortPath(String path) {
      String[] segments = path.split("[\\\\/]+");
      String result = "";
      for (int i = 0; i < segments.length; ) {
        String segment = segments[i];
        String queryString = (result + segment).toLowerCase();
        segment = resolutions.getOrDefault(queryString, segment);
        result = result + segment;
        ++i;
        if (i != segments.length) {
          result += "/";
        }
      }
      return result;
    }
  }

  @Test
  public void testEqualsAndHashcodeWindows() {
    new EqualsTester()
        .addEqualityGroup(create("/a/b"), create("/A/B"))
        .addEqualityGroup(create("c:/a/b"), create("C:\\A\\B"))
        .addEqualityGroup(create("C:/something/else"))
        .testEquals();
  }

  @Test
  public void testCaseIsPreserved() {
    assertThat(create("C:/a/B").getPathString()).isEqualTo("C:/a/B");
  }

  @Test
  public void testNormalizeWindows() {
    assertThat(create("C:/")).isEqualTo(create("C:/"));
    assertThat(create("c:/")).isEqualTo(create("C:/"));
    assertThat(create("c:\\")).isEqualTo(create("C:/"));
    assertThat(create("c:\\foo\\..\\bar\\")).isEqualTo(create("C:/bar"));
  }

  @Test
  public void testStartsWithWindows() {
    assertThat(create("C:/").startsWith(create("C:/"))).isTrue();
    assertThat(create("C:/foo").startsWith(create("C:/"))).isTrue();
    assertThat(create("C:/foo").startsWith(create("D:/"))).isFalse();

    // Case insensitivity test
    assertThat(create("C:/foo/bar").startsWith(create("C:/FOO"))).isTrue();
  }

  @Test
  public void testGetParentDirectoryWindows() {
    assertThat(create("C:/foo").getParentDirectory()).isEqualTo(create("C:/"));
    assertThat(create("C:/").getParentDirectory()).isNull();
    assertThat(create("/").getParentDirectory()).isNull();
  }

  @Test
  public void testParentOfRootIsRootWindows() {
    assertThat(create("C:/..")).isEqualTo(create("C:/"));
    assertThat(create("C:/../../../../../..")).isEqualTo(create("C:/"));
    assertThat(create("C:/../../../foo")).isEqualTo(create("C:/foo"));
  }

  @Test
  public void testRelativeToWindows() {
    assertThat(create("C:/foo").relativeTo(create("C:/")).getPathString()).isEqualTo("foo");
    // Case insensitivity test
    assertThat(create("C:/foo/bar").relativeTo(create("C:/FOO")).getPathString()).isEqualTo("bar");
    assertThrows(IllegalArgumentException.class, () -> create("D:/foo").relativeTo(create("C:/")));
  }

  @Test
  public void testResolvesShortenedPaths() {
    MockShortPathResolver shortPathResolver = new MockShortPathResolver();
    WindowsOsPathPolicy osPathPolicy = new WindowsOsPathPolicy(shortPathResolver);
    shortPathResolver.resolutions.put("d:/progra~1", "program files");
    shortPathResolver.resolutions.put("d:/program files/micros~1", "microsoft something");
    shortPathResolver.resolutions.put(
        "d:/program files/microsoft something/foo/~bar~1", "~bar_hello");

    // Assert normal shortpath resolution.
    assertThat(normalize(osPathPolicy, "d:/progra~1/micros~1/foo/~bar~1/baz"))
        .isEqualTo("D:/program files/microsoft something/foo/~bar_hello/baz");
    assertThat(normalize(osPathPolicy, "d:/progra~1/micros~1/foo/will~1.exi/bar"))
        .isEqualTo("D:/program files/microsoft something/foo/will~1.exi/bar");

    assertThat(normalize(osPathPolicy, "d:/progra~1/micros~1"))
        .isEqualTo("D:/program files/microsoft something");

    // Pretend that a path we already failed to resolve once came into existence.
    shortPathResolver.resolutions.put(
        "d:/program files/microsoft something/foo/will~1.exi", "will.exist");

    // Assert that this time we can resolve the previously non-existent path.
    // The path string has an upper-case drive letter because that's how path printing works.
    assertThat(normalize(osPathPolicy, "d:/progra~1/micros~1/foo/will~1.exi/bar"))
        .isEqualTo("D:/program files/microsoft something/foo/will.exist/bar");

    // Check needsToNormalized
    assertThat(osPathPolicy.needsToNormalize("d:/progra~1/micros~1/foo/will~1.exi/bar"))
        .isEqualTo(WindowsOsPathPolicy.NEEDS_SHORT_PATH_NORMALIZATION);
    assertThat(osPathPolicy.needsToNormalize("will~1.exi"))
        .isEqualTo(WindowsOsPathPolicy.NEEDS_SHORT_PATH_NORMALIZATION);
    assertThat(osPathPolicy.needsToNormalize("d:/no-normalization"))
        .isEqualTo(WindowsOsPathPolicy.NORMALIZED); // Sanity check
  }

  private static String normalize(OsPathPolicy osPathPolicy, String str) {
    return osPathPolicy.normalize(str, osPathPolicy.needsToNormalize(str));
  }
}
