// Copyright 2018 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.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.testing.EqualsTester;
import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.skyframe.serialization.AutoRegistry;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodecRegistry;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodecs;
import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import java.util.Comparator;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link RootTest}. */
@RunWith(JUnit4.class)
public class RootTest {
  private FileSystem fs;

  @Before
  public final void initializeFileSystem() throws Exception {
    fs = new InMemoryFileSystem(BlazeClock.instance());
  }

  @Test
  public void testEqualsAndHashCodeContract() throws Exception {
    FileSystem otherFs = new InMemoryFileSystem(BlazeClock.instance());
    new EqualsTester()
        .addEqualityGroup(Root.absoluteRoot(fs), Root.absoluteRoot(fs))
        .addEqualityGroup(Root.absoluteRoot(otherFs), Root.absoluteRoot(otherFs))
        .addEqualityGroup(Root.fromPath(fs.getPath("/foo")), Root.fromPath(fs.getPath("/foo")))
        .testEquals();
  }

  @Test
  public void testPathRoot() throws Exception {
    Root root = Root.fromPath(fs.getPath("/foo"));
    assertThat(root.asPath()).isEqualTo(fs.getPath("/foo"));
    assertThat(root.contains(fs.getPath("/foo/bar"))).isTrue();
    assertThat(root.contains(fs.getPath("/boo/bar"))).isFalse();
    assertThat(root.contains(PathFragment.create("/foo/bar"))).isTrue();
    assertThat(root.contains(PathFragment.create("foo/bar"))).isFalse();
    assertThat(root.getRelative(PathFragment.create("bar"))).isEqualTo(fs.getPath("/foo/bar"));
    assertThat(root.getRelative("bar")).isEqualTo(fs.getPath("/foo/bar"));
    assertThat(root.getRelative(PathFragment.create("/bar"))).isEqualTo(fs.getPath("/bar"));
    assertThat(root.relativize(fs.getPath("/foo/bar"))).isEqualTo(PathFragment.create("bar"));
    assertThat(root.relativize(PathFragment.create("/foo/bar")))
        .isEqualTo(PathFragment.create("bar"));
    assertThrows(IllegalArgumentException.class, () -> root.relativize(PathFragment.create("foo")));
  }

  @Test
  public void testFilesystemTransform() throws Exception {
    FileSystem fs2 = new InMemoryFileSystem(BlazeClock.instance());
    Root root = Root.fromPath(fs.getPath("/foo"));
    Root root2 = Root.toFileSystem(root, fs2);
    assertThat(root2.asPath().getFileSystem()).isSameInstanceAs(fs2);
    assertThat(root2.asPath().asFragment()).isEqualTo(PathFragment.create("/foo"));
    assertThat(root.isAbsolute()).isFalse();
  }

  @Test
  public void testFileSystemAbsoluteRoot() throws Exception {
    Root root = Root.absoluteRoot(fs);
    assertThat(root.asPath()).isNull();
    assertThat(root.contains(fs.getPath("/foo"))).isTrue();
    assertThat(root.contains(PathFragment.create("/foo/bar"))).isTrue();
    assertThat(root.contains(PathFragment.create("foo/bar"))).isFalse();
    assertThat(root.getRelative("/foo")).isEqualTo(fs.getPath("/foo"));
    assertThat(root.relativize(fs.getPath("/foo"))).isEqualTo(PathFragment.create("/foo"));
    assertThat(root.relativize(PathFragment.create("/foo"))).isEqualTo(PathFragment.create("/foo"));

    assertThrows(
        IllegalArgumentException.class, () -> root.getRelative(PathFragment.create("foo")));
    assertThrows(
        IllegalArgumentException.class, () -> root.getRelative(PathFragment.create("foo")));
    assertThrows(IllegalArgumentException.class, () -> root.relativize(PathFragment.create("foo")));
  }

  @Test
  public void testCompareTo() throws Exception {
    Root a = Root.fromPath(fs.getPath("/a"));
    Root b = Root.fromPath(fs.getPath("/b"));
    Root root = Root.absoluteRoot(fs);
    List<Root> list = Lists.newArrayList(a, root, b);
    list.sort(Comparator.naturalOrder());
    assertThat(list).containsExactly(root, a, b).inOrder();
  }

  @Test
  public void testSerialization_Simple() throws Exception {
    Root fooPathRoot = Root.fromPath(fs.getPath("/foo"));
    Root barPathRoot = Root.fromPath(fs.getPath("/bar"));
    new SerializationTester(Root.absoluteRoot(fs), fooPathRoot, barPathRoot)
        .addDependency(FileSystem.class, fs)
        .addDependency(
            Root.RootCodecDependencies.class,
            new Root.RootCodecDependencies(/*likelyPopularRoot=*/ fooPathRoot))
        .runTests();
  }

  @Test
  public void testSerialization_LikelyPopularRootIsCanonicalized() throws Exception {
    Root fooPathRoot = Root.fromPath(fs.getPath("/foo"));
    Root otherFooPathRoot = Root.fromPath(fs.getPath("/foo"));
    Root barPathRoot = Root.fromPath(fs.getPath("/bar"));
    Root fsAabsoluteRoot = Root.absoluteRoot(fs);

    assertThat(fooPathRoot).isNotSameInstanceAs(otherFooPathRoot);
    assertThat(fooPathRoot).isEqualTo(otherFooPathRoot);

    ObjectCodecRegistry registry = AutoRegistry.get();
    ImmutableMap<Class<?>, Object> dependencies =
        ImmutableMap.<Class<?>, Object>builder()
            .put(FileSystem.class, fs)
            .put(
                Root.RootCodecDependencies.class,
                new Root.RootCodecDependencies(/*likelyPopularRoot=*/ fooPathRoot))
            .build();
    ObjectCodecRegistry.Builder registryBuilder = registry.getBuilder();
    for (Object val : dependencies.values()) {
      registryBuilder.addReferenceConstant(val);
    }
    ObjectCodecs objectCodecs = new ObjectCodecs(registryBuilder.build(), dependencies);

    Root fooPathRootDeserialized =
        (Root) objectCodecs.deserialize(objectCodecs.serialize(fooPathRoot));
    Root otherFooPathRootDeserialized =
        (Root) objectCodecs.deserialize(objectCodecs.serialize(otherFooPathRoot));
    assertThat(fooPathRootDeserialized).isSameInstanceAs(fooPathRoot);
    assertThat(otherFooPathRootDeserialized).isSameInstanceAs(fooPathRoot);

    Root barPathRootDeserialized =
        (Root) objectCodecs.deserialize(objectCodecs.serialize(barPathRoot));
    assertThat(barPathRootDeserialized).isNotSameInstanceAs(barPathRoot);
    assertThat(barPathRootDeserialized).isEqualTo(barPathRoot);

    Root fsAabsoluteRootDeserialized =
        (Root) objectCodecs.deserialize(objectCodecs.serialize(fsAabsoluteRoot));
    assertThat(fsAabsoluteRootDeserialized).isNotSameInstanceAs(fsAabsoluteRoot);
    assertThat(fsAabsoluteRootDeserialized).isEqualTo(fsAabsoluteRoot);
  }
}
