// Copyright 2019 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.skyframe.config;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.util.AnalysisMock;
import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.Label.RepoContext;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.skyframe.config.PlatformMappingFunction.Mappings;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.util.SkyframeExecutorTestUtils;
import com.google.devtools.build.skyframe.ErrorInfo;
import com.google.devtools.build.skyframe.EvaluationResult;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.Objects;
import javax.annotation.Nullable;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Unit tests for {@link PlatformMappingFunction}. */
@RunWith(JUnit4.class)
public class PlatformMappingFunctionParserTest extends AnalysisTestCase {

  private static final Label PLATFORM1 = Label.parseCanonicalUnchecked("//platforms:one");
  private static final Label PLATFORM2 = Label.parseCanonicalUnchecked("//platforms:two");
  private static final Label EXTERNAL_PLATFORM =
      Label.parseCanonicalUnchecked("@dep~1.0//platforms:two");

  @Test
  public void testParse() throws Exception {
    PlatformMappingFunction.Mappings mappings =
        parse(
            "platforms:",
            "  //platforms:one",
            "    --cpu=one",
            "  //platforms:two",
            "    --cpu=two",
            "flags:",
            "  --cpu=one",
            "    //platforms:one",
            "  --cpu=two",
            "    //platforms:two");

    assertThat(mappings.platformsToFlags.keySet()).containsExactly(PLATFORM1, PLATFORM2);
    assertThat(mappings.platformsToFlags.get(PLATFORM1).nativeFlags()).containsExactly("--cpu=one");
    assertThat(mappings.platformsToFlags.get(PLATFORM2).nativeFlags()).containsExactly("--cpu=two");

    assertThat(mappings.flagsToPlatforms.keySet())
        .containsExactly(ImmutableList.of("--cpu=one"), ImmutableList.of("--cpu=two"));
    assertThat(mappings.flagsToPlatforms.get(ImmutableList.of("--cpu=one"))).isEqualTo(PLATFORM1);
    assertThat(mappings.flagsToPlatforms.get(ImmutableList.of("--cpu=two"))).isEqualTo(PLATFORM2);
  }

  @Test
  public void testParseWithRepoMapping() throws Exception {
    PlatformMappingFunction.Mappings mappings =
        parse(
            RepositoryMapping.create(
                ImmutableMap.of(
                    "foo", RepositoryName.MAIN, "dep", RepositoryName.create("dep~1.0")),
                RepositoryName.MAIN),
            "platforms:",
            "  @foo//platforms:one",
            "    --cpu=one",
            "  @dep//platforms:two",
            "    --cpu=two",
            "flags:",
            "  --cpu=one",
            "    @foo//platforms:one",
            "  --cpu=two",
            "    @dep//platforms:two");

    assertThat(mappings.platformsToFlags.keySet()).containsExactly(PLATFORM1, EXTERNAL_PLATFORM);
    assertThat(mappings.platformsToFlags.get(PLATFORM1).nativeFlags()).containsExactly("--cpu=one");
    assertThat(mappings.platformsToFlags.get(EXTERNAL_PLATFORM).nativeFlags())
        .containsExactly("--cpu=two");

    assertThat(mappings.flagsToPlatforms.keySet())
        .containsExactly(ImmutableList.of("--cpu=one"), ImmutableList.of("--cpu=two"));
    assertThat(mappings.flagsToPlatforms.get(ImmutableList.of("--cpu=one"))).isEqualTo(PLATFORM1);
    assertThat(mappings.flagsToPlatforms.get(ImmutableList.of("--cpu=two")))
        .isEqualTo(EXTERNAL_PLATFORM);
  }

  @Test
  public void testParseComment() throws Exception {
    PlatformMappingFunction.Mappings mappings =
        parse(
            "# A mapping file!",
            "platforms:",
            "  # comment1",
            "  //platforms:one",
            "# comment2",
            "    --cpu=one",
            "  //platforms:two",
            "    --cpu=two",
            "flags:",
            "# another comment",
            "  --cpu=one",
            "    //platforms:one",
            "  --cpu=two",
            "    //platforms:two");

    assertThat(mappings.platformsToFlags.keySet()).containsExactly(PLATFORM1, PLATFORM2);
    assertThat(mappings.platformsToFlags.get(PLATFORM1).nativeFlags()).containsExactly("--cpu=one");
    assertThat(mappings.platformsToFlags.get(PLATFORM2).nativeFlags()).containsExactly("--cpu=two");

    assertThat(mappings.flagsToPlatforms.keySet())
        .containsExactly(ImmutableList.of("--cpu=one"), ImmutableList.of("--cpu=two"));
    assertThat(mappings.flagsToPlatforms.get(ImmutableList.of("--cpu=one"))).isEqualTo(PLATFORM1);
    assertThat(mappings.flagsToPlatforms.get(ImmutableList.of("--cpu=two"))).isEqualTo(PLATFORM2);
  }

  @Test
  public void testParseWhitespace() throws Exception {
    PlatformMappingFunction.Mappings mappings =
        parse(
            "",
            "platforms:",
            "  ",
            "  //platforms:one",
            "",
            "    --cpu=one",
            "    //platforms:two    ",
            "      --cpu=two ",
            "flags:",
            "           ",
            "",
            "--cpu=one",
            "  //platforms:one",
            "  --cpu=two",
            "  //platforms:two");

    assertThat(mappings.platformsToFlags.keySet()).containsExactly(PLATFORM1, PLATFORM2);
    assertThat(mappings.platformsToFlags.get(PLATFORM1).nativeFlags()).containsExactly("--cpu=one");
    assertThat(mappings.platformsToFlags.get(PLATFORM2).nativeFlags()).containsExactly("--cpu=two");

    assertThat(mappings.flagsToPlatforms.keySet())
        .containsExactly(ImmutableList.of("--cpu=one"), ImmutableList.of("--cpu=two"));
    assertThat(mappings.flagsToPlatforms.get(ImmutableList.of("--cpu=one"))).isEqualTo(PLATFORM1);
    assertThat(mappings.flagsToPlatforms.get(ImmutableList.of("--cpu=two"))).isEqualTo(PLATFORM2);
  }

  @Test
  public void testParseMultipleFlagsInPlatform() throws Exception {
    PlatformMappingFunction.Mappings mappings =
        parse(
            "platforms:",
            "  //platforms:one",
            "    --cpu=one",
            "    --compilation_mode=dbg",
            "  //platforms:two",
            "    --cpu=two");

    assertThat(mappings.platformsToFlags.keySet()).containsExactly(PLATFORM1, PLATFORM2);
    assertThat(mappings.platformsToFlags.get(PLATFORM1).nativeFlags())
        .containsExactly("--cpu=one", "--compilation_mode=dbg");
  }

  @Test
  public void testParseMultipleFlagsInFlags() throws Exception {
    PlatformMappingFunction.Mappings mappings =
        parse(
            "flags:",
            "  --compilation_mode=dbg",
            "  --cpu=one",
            "    //platforms:one",
            "  --cpu=two",
            "    //platforms:two");

    assertThat(mappings.flagsToPlatforms.keySet())
        .containsExactly(
            ImmutableList.of("--compilation_mode=dbg", "--cpu=one"), ImmutableList.of("--cpu=two"));
    assertThat(
            mappings.flagsToPlatforms.get(ImmutableList.of("--compilation_mode=dbg", "--cpu=one")))
        .isEqualTo(PLATFORM1);
  }

  @Test
  public void testParseOnlyPlatforms() throws Exception {
    PlatformMappingFunction.Mappings mappings =
        parse(
            "platforms:", // Force line break
            "  //platforms:one", // Force line break
            "    --cpu=one" // Force line break
            );

    assertThat(mappings.platformsToFlags.keySet()).containsExactly(PLATFORM1);
    assertThat(mappings.platformsToFlags.get(PLATFORM1).nativeFlags()).containsExactly("--cpu=one");
    assertThat(mappings.flagsToPlatforms).isEmpty();
  }

  @Test
  public void testParseOnlyFlags() throws Exception {
    PlatformMappingFunction.Mappings mappings =
        parse(
            "flags:", // Force line break
            "  --cpu=one", // Force line break
            "    //platforms:one" // Force line break
            );

    assertThat(mappings.flagsToPlatforms.keySet()).containsExactly(ImmutableList.of("--cpu=one"));
    assertThat(mappings.flagsToPlatforms.get(ImmutableList.of("--cpu=one"))).isEqualTo(PLATFORM1);
    assertThat(mappings.platformsToFlags).isEmpty();
  }

  @Test
  public void testParseEmpty() throws Exception {
    PlatformMappingFunction.Mappings mappings = parse();

    assertThat(mappings.flagsToPlatforms).isEmpty();
    assertThat(mappings.platformsToFlags).isEmpty();
  }

  @Test
  public void testParseEmptySections() throws Exception {
    PlatformMappingFunction.Mappings mappings = parse("platforms:", "flags:");

    assertThat(mappings.flagsToPlatforms).isEmpty();
    assertThat(mappings.platformsToFlags).isEmpty();
  }

  @Test
  public void testParseCommentOnly() throws Exception {
    PlatformMappingFunction.Mappings mappings = parse("#No mappings");

    assertThat(mappings.flagsToPlatforms).isEmpty();
    assertThat(mappings.platformsToFlags).isEmpty();
  }

  @Test
  public void testParseExtraPlatformInFlags() throws Exception {
    PlatformMappingParsingException exception =
        assertThrows(
            PlatformMappingParsingException.class,
            () ->
                parse(
                    "flags:", // Force line break
                    "  --cpu=one", // Force line break
                    "    //platforms:one", // Force line break
                    "    //platforms:two" // Force line break
                    ));

    assertThat(exception).hasMessageThat().contains("//platforms:two");
  }

  @Test
  public void testParsePlatformWithoutFlags() throws Exception {
    PlatformMappingParsingException exception =
        assertThrows(
            PlatformMappingParsingException.class,
            () ->
                parse(
                    "platforms:", // Force line break
                    "  //platforms:one" // Force line break
                    ));

    assertThat(exception).hasMessageThat().contains("end of file");
  }

  @Test
  public void testParseFlagsWithoutPlatform() throws Exception {
    PlatformMappingParsingException exception =
        assertThrows(
            PlatformMappingParsingException.class,
            () ->
                parse(
                    "flags:", // Force line break
                    "  --cpu=one" // Force line break
                    ));

    assertThat(exception).hasMessageThat().contains("end of file");
  }

  @Test
  public void testParseCommentEndOfFile() throws Exception {
    PlatformMappingFunction.Mappings mappings =
        parse(
            "platforms:", // Force line break
            "  //platforms:one", // Force line break
            "    --cpu=one", // Force line break
            "# No more mappings" // Force line break
            );

    assertThat(mappings.platformsToFlags).isNotEmpty();
  }

  @Test
  public void testParseUnknownSection() throws Exception {
    PlatformMappingParsingException exception =
        assertThrows(
            PlatformMappingParsingException.class,
            () ->
                parse(
                    "platform:", // Force line break
                    "  //platforms:one", // Force line break
                    "    --cpu=one" // Force line break
                    ));

    assertThat(exception).hasMessageThat().contains("platform:");

    exception =
        assertThrows(
            PlatformMappingParsingException.class,
            () ->
                parse(
                    "platforms:",
                    "  //platforms:one",
                    "    --cpu=one",
                    "flag:",
                    "  --cpu=one",
                    "    //platforms:one"));

    assertThat(exception).hasMessageThat().contains("platform");
  }

  @Test
  public void testParsePlatformsInvalidPlatformLabel() throws Exception {
    PlatformMappingParsingException exception =
        assertThrows(
            PlatformMappingParsingException.class,
            () ->
                parse(
                    "platforms:", // Force line break
                    "  @@@", // Force line break
                    "    --cpu=one"));

    assertThat(exception).hasMessageThat().contains("@@@");
  }

  @Test
  public void testParseFlagsInvalidPlatformLabel() throws Exception {
    PlatformMappingParsingException exception =
        assertThrows(
            PlatformMappingParsingException.class,
            () ->
                parse(
                    "flags:", // Force line break
                    "  --cpu=one", // Force line break
                    "    @@@"));

    assertThat(exception).hasMessageThat().contains("@@@");
  }

  @Test
  public void testParsePlatformsInvalidFlag() throws Exception {
    PlatformMappingParsingException exception =
        assertThrows(
            PlatformMappingParsingException.class,
            () ->
                parse(
                    "platforms:", // Force line break
                    "  //platforms:one", // Force line break
                    "    -cpu=one"));

    assertThat(exception).hasMessageThat().contains("-cpu");
  }

  @Test
  public void testParseFlagsInvalidFlag() throws Exception {
    PlatformMappingParsingException exception =
        assertThrows(
            PlatformMappingParsingException.class,
            () ->
                parse(
                    "flags:", // Force line break
                    "  -cpu=one", // Force line breakPlatformMappingFunction
                    "    //platforms:one"));

    assertThat(exception).hasMessageThat().contains("-cpu");
  }

  @Test
  public void testParsePlatformsDuplicatePlatform() throws Exception {
    PlatformMappingParsingException exception =
        assertThrows(
            PlatformMappingParsingException.class,
            () ->
                parse(
                    "platforms:", // Force line break
                    "  //platforms:one", // Force line break
                    "    --cpu=one", // Force line break
                    "  //platforms:one", // Force line break
                    "    --cpu=two"));

    assertThat(exception).hasMessageThat().contains("duplicate");
  }

  @Test
  public void testParseFlagsDuplicateFlags() throws Exception {
    PlatformMappingParsingException exception =
        assertThrows(
            PlatformMappingParsingException.class,
            () ->
                parse(
                    "flags:", // Force line break
                    "  --compilation_mode=dbg", // Force line break
                    "  --cpu=one", // Force line break:242
                    "    //platforms:one", // Force line break
                    "  --compilation_mode=dbg", // Force line break
                    "  --cpu=one", // Force line break
                    "    //platforms:two"));

    assertThat(exception).hasMessageThat().contains("duplicate");
  }

  private PlatformMappingFunction.Mappings parse(String... lines)
      throws PlatformMappingParsingException, InterruptedException {
    return parse(RepositoryMapping.ALWAYS_FALLBACK, lines);
  }

  private PlatformMappingFunction.Mappings parse(RepositoryMapping mainRepoMapping, String... lines)
      throws InterruptedException, PlatformMappingParsingException {
    Key key = Key.create(mainRepoMapping, ImmutableList.copyOf(lines));
    try {
      // Must re-enable analysis for Skyframe functions that create configured targets.
      skyframeExecutor.getSkyframeBuildView().enableAnalysis(true);
      EvaluationResult<Value> evalResult =
          SkyframeExecutorTestUtils.evaluate(
              skyframeExecutor, key, /* keepGoing= */ false, reporter);
      if (evalResult.hasError()) {
        ErrorInfo errorInfo = evalResult.getError(key);
        PlatformMappingParsingException exception =
            (PlatformMappingParsingException) errorInfo.getException();
        throw exception;
      }
      return evalResult.get(key).mappings();
    } finally {
      skyframeExecutor.getSkyframeBuildView().enableAnalysis(false);
    }
  }

  static final SkyFunctionName SKYFUNCTION_NAME = SkyFunctionName.createHermetic("PARSE_MAPPINGS");

  @AutoCodec
  static final class Key implements SkyKey {
    static Key create(RepositoryMapping mainRepoMapping, ImmutableList<String> lines) {
      return new Key(mainRepoMapping, lines);
    }

    private final RepositoryMapping mainRepoMapping;
    private final ImmutableList<String> lines;

    public Key(RepositoryMapping mainRepoMapping, ImmutableList<String> lines) {
      this.mainRepoMapping = mainRepoMapping;
      this.lines = lines;
    }

    RepositoryMapping mainRepoMapping() {
      return mainRepoMapping;
    }

    ImmutableList<String> lines() {
      return lines;
    }

    @Override
    public int hashCode() {
      return Objects.hash(mainRepoMapping, lines);
    }

    @Override
    public boolean equals(Object o) {
      if (o == null || !(o instanceof Key)) {
        return false;
      }
      Key other = (Key) o;
      return Objects.equals(mainRepoMapping, other.mainRepoMapping)
          && Objects.equals(lines, other.lines);
    }

    @Override
    public SkyFunctionName functionName() {
      return SKYFUNCTION_NAME;
    }
  }

  static final class Value implements SkyValue {
    static Value create(Mappings mappings) {
      return new Value(mappings);
    }

    private final Mappings mappings;

    Value(Mappings mappings) {
      this.mappings = mappings;
    }

    Mappings mappings() {
      return mappings;
    }
  }

  private static final class ParseMappingsFunction implements SkyFunction {

    @Nullable
    @Override
    public Value compute(SkyKey skyKey, Environment env)
        throws InterruptedException, EvalException {
      Key key = (Key) skyKey.argument();
      try {
        Mappings mappings =
            PlatformMappingFunction.parse(
                env, key.lines(), RepoContext.of(RepositoryName.MAIN, key.mainRepoMapping()));
        if (mappings == null) {
          return null;
        }
        return Value.create(mappings);
      } catch (PlatformMappingParsingException e) {
        throw new EvalException(e);
      }
    }

    private static final class EvalException extends SkyFunctionException {
      EvalException(Exception cause) {
        super(cause, Transience.PERSISTENT); // We can generalize the transience if/when needed.
      }
    }
  }

  private static final class CustomAnalysisMock extends AnalysisMock.Delegate {

    CustomAnalysisMock() {
      super(AnalysisMock.get());
    }

    @Override
    public ImmutableMap<SkyFunctionName, SkyFunction> getSkyFunctions(
        BlazeDirectories directories) {
      return ImmutableMap.<SkyFunctionName, SkyFunction>builder()
          .putAll(super.getSkyFunctions(directories))
          .put(SKYFUNCTION_NAME, new ParseMappingsFunction())
          .buildOrThrow();
    }
  }

  @Override
  protected AnalysisMock getAnalysisMock() {
    return new CustomAnalysisMock();
  }
}
