// Copyright 2020 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.bazel.rules.ninja;

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

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.bazel.rules.ninja.actions.NinjaPhonyTargetsUtil;
import com.google.devtools.build.lib.bazel.rules.ninja.actions.PhonyTarget;
import com.google.devtools.build.lib.bazel.rules.ninja.file.ByteBufferFragment;
import com.google.devtools.build.lib.bazel.rules.ninja.file.GenericParsingException;
import com.google.devtools.build.lib.bazel.rules.ninja.lexer.NinjaLexer;
import com.google.devtools.build.lib.bazel.rules.ninja.parser.NinjaParserStep;
import com.google.devtools.build.lib.bazel.rules.ninja.parser.NinjaScope;
import com.google.devtools.build.lib.bazel.rules.ninja.parser.NinjaTarget;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for {@link com.google.devtools.build.lib.bazel.rules.ninja.actions.NinjaPhonyTargetsUtil}.
 */
@RunWith(JUnit4.class)
public class NinjaPhonyTargetsUtilTest {
  @Test
  public void testPathsTree() throws Exception {
    ImmutableList<String> targetTexts =
        ImmutableList.of(
            "build alias9: phony alias2 alias3 direct1 direct2",
            "build alias2: phony direct3 direct4",
            "build alias3: phony alias4 direct4 direct5",
            "build alias4: phony alias2");

    ImmutableSortedMap<PathFragment, PhonyTarget> pathsMap =
        NinjaPhonyTargetsUtil.getPhonyPathsMap(buildPhonyTargets(targetTexts));

    assertThat(pathsMap).hasSize(4);
    checkMapping(pathsMap, "alias9", "direct1", "direct2", "direct3", "direct4", "direct5");
    checkMapping(pathsMap, "alias2", "direct3", "direct4");
    checkMapping(pathsMap, "alias3", "direct3", "direct4", "direct5");
    checkMapping(pathsMap, "alias4", "direct3", "direct4");
  }

  @Test
  public void testDag() throws Exception {
    ImmutableList<String> targetTexts =
        ImmutableList.of(
            "build _alias9: phony alias1 alias2",
            "build alias1: phony deep1",
            "build alias2: phony deep2",
            "build deep1: phony leaf1",
            "build deep2: phony leaf2 alias1");

    ImmutableSortedMap<PathFragment, PhonyTarget> pathsMap =
        NinjaPhonyTargetsUtil.getPhonyPathsMap(buildPhonyTargets(targetTexts));

    assertThat(pathsMap).hasSize(5);
    checkMapping(pathsMap, "_alias9", "leaf1", "leaf2");
    checkMapping(pathsMap, "alias1", "leaf1");
    checkMapping(pathsMap, "alias2", "leaf1", "leaf2");
    checkMapping(pathsMap, "deep1", "leaf1");
    checkMapping(pathsMap, "deep2", "leaf1", "leaf2");
  }

  @Test
  public void testAlwaysDirty() throws Exception {
    ImmutableList<String> targetTexts =
        ImmutableList.of(
            "build alias9: phony alias2 alias3 direct1 direct2",
            "build alias2: phony direct3 direct4",
            "build alias3: phony alias4 direct4 direct5",
            // alias4 is always-dirty
            "build alias4: phony");

    ImmutableSortedMap<PathFragment, PhonyTarget> pathsMap =
        NinjaPhonyTargetsUtil.getPhonyPathsMap(buildPhonyTargets(targetTexts));

    assertThat(pathsMap).hasSize(4);
    // alias4 and its transitive closure is always-dirty
    checkMapping(pathsMap, "alias9", true, "direct1", "direct2", "direct3", "direct4", "direct5");
    checkMapping(pathsMap, "alias2", false, "direct3", "direct4");
    checkMapping(pathsMap, "alias3", true, "direct4", "direct5");
    checkMapping(pathsMap, "alias4", true);
  }

  private static void checkMapping(
      ImmutableSortedMap<PathFragment, PhonyTarget> pathsMap, String key, String... values) {
    checkMapping(pathsMap, key, false, values);
  }

  private static void checkMapping(
      ImmutableSortedMap<PathFragment, PhonyTarget> pathsMap,
      String key,
      boolean isAlwaysDirty,
      String... values) {
    Set<PathFragment> expectedPaths =
        Arrays.stream(values).map(PathFragment::create).collect(Collectors.toSet());
    PhonyTarget phonyTarget = pathsMap.get(PathFragment.create(key));
    assertThat(phonyTarget).isNotNull();
    assertThat(phonyTarget.isAlwaysDirty()).isEqualTo(isAlwaysDirty);

    ImmutableSortedSet.Builder<PathFragment> paths = ImmutableSortedSet.naturalOrder();
    pathsMap.get(PathFragment.create(key)).visitUsualInputs(pathsMap, paths::addAll);
    assertThat(paths.build()).containsExactlyElementsIn(expectedPaths);
  }

  private static ImmutableSortedMap<PathFragment, NinjaTarget> buildPhonyTargets(
      ImmutableList<String> targetTexts) throws Exception {
    ImmutableSortedMap.Builder<PathFragment, NinjaTarget> builder =
        ImmutableSortedMap.naturalOrder();
    for (String text : targetTexts) {
      NinjaTarget ninjaTarget = parseNinjaTarget(text);
      builder.put(Iterables.getOnlyElement(ninjaTarget.getAllOutputs()), ninjaTarget);
    }
    return builder.build();
  }

  @Test
  public void testEmptyMap() throws Exception {
    assertThat(NinjaPhonyTargetsUtil.getPhonyPathsMap(ImmutableSortedMap.of())).isEmpty();
  }

  @Test
  public void testCycle() {
    ImmutableList<String> targetTexts =
        ImmutableList.of(
            "build alias1: phony alias2 direct1", "build alias2: phony alias1 direct2");

    GenericParsingException exception =
        assertThrows(
            GenericParsingException.class,
            () -> NinjaPhonyTargetsUtil.getPhonyPathsMap(buildPhonyTargets(targetTexts)));
    assertThat(exception)
        .hasMessageThat()
        .isEqualTo("Detected a dependency cycle involving the phony target 'alias1'");
  }

  private static NinjaTarget parseNinjaTarget(String text) throws Exception {
    NinjaScope fileScope = new NinjaScope();
    return createParser(text).parseNinjaTarget(fileScope, 0);
  }

  private static NinjaParserStep createParser(String text) {
    ByteBuffer buffer = ByteBuffer.wrap(text.getBytes(StandardCharsets.ISO_8859_1));
    NinjaLexer lexer = new NinjaLexer(new ByteBufferFragment(buffer, 0, buffer.limit()));
    return new NinjaParserStep(lexer);
  }
}
