// 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 org.junit.Assert.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));
  }
}
