// 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.runtime.commands;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.Streams.stream;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.analysis.config.FragmentOptions;
import com.google.devtools.build.lib.buildtool.util.BuildIntegrationTestCase;
import com.google.devtools.build.lib.runtime.BlazeCommandDispatcher;
import com.google.devtools.build.lib.runtime.commands.ConfigCommand.ConfigurationDiffForOutput;
import com.google.devtools.build.lib.runtime.commands.ConfigCommand.ConfigurationForOutput;
import com.google.devtools.build.lib.runtime.commands.ConfigCommand.FragmentDiffForOutput;
import com.google.devtools.build.lib.testutil.TestConstants;
import com.google.devtools.build.lib.util.Pair;
import com.google.devtools.build.lib.util.io.RecordingOutErr;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for {@link ConfigCommand} ("<code>$ blaze config</code>").
 *
 * <p>These tests assume all important testable properties are determined in {@link ConfigCommand},
 * so the output formatter used doesn't affect those properties. We test with <code>--output=json
 * </code> for easy parsing.
 */
@RunWith(JUnit4.class)
public class ConfigCommandTest extends BuildIntegrationTestCase {
  private BlazeCommandDispatcher dispatcher;

  @Before
  public final void init() throws Exception {
    getRuntime().overrideCommands(ImmutableList.of(new BuildCommand(), new ConfigCommand()));
    dispatcher = new BlazeCommandDispatcher(getRuntime());
    write(
        "tools/allowlists/function_transition_allowlist/BUILD",
        "package_group(",
        "    name = 'function_transition_allowlist',",
        "    packages = ['//...'],",
        ")");
    write(
        "test/defs.bzl",
        "def _simple_rule_impl(ctx):",
        "  pass",
        "simple_rule = rule(",
        "  implementation = _simple_rule_impl,",
        "  attrs = {},",
        ")",
        "def _sometransition_impl(settings, attr):",
        "  _ignore = (settings, attr)",
        "  return {'//command_line_option:platform_suffix': 'transitioned'}",
        "_sometransition = transition(",
        "  implementation = _sometransition_impl,",
        "  inputs = [],",
        "  outputs = ['//command_line_option:platform_suffix'],",
        ")",
        "rule_with_transition = rule(",
        "  implementation = _simple_rule_impl,",
        "  cfg = _sometransition,",
        "  attrs = {",
        "    '_allowlist_function_transition': attr.label(",
        "        default = '//tools/allowlists/function_transition_allowlist'),",
        "  },",
        ")");
    write(
        "test/BUILD",
        "load('//test:defs.bzl', 'simple_rule', 'rule_with_transition')",
        "simple_rule(name='buildme')",
        "rule_with_transition(name='buildme_with_transition')");
  }

  /**
   * Performs loading and analysis on the fixed rule <code>//test:buildme</code> with the given
   * build options (as they'd appear on the command line).
   */
  private void analyzeTarget(String... args) throws Exception {
    List<String> params = Lists.newArrayList("build");
    // Basic flags required to make any build work. Ideally we'd go through BlazeRuntimeWrapper,
    // which does the same setup. But that's explicitly documented as not supported command
    // invocations, which is exactly what we we need here.
    params.addAll(TestConstants.PRODUCT_SPECIFIC_FLAGS);
    params.add("//test:buildme");
    params.add("--nobuild"); // Execution phase isn't necessary to collect configurations.
    // TODO: Enable Bzlmod for this test
    // https://github.com/bazelbuild/bazel/issues/19823
    params.add("--noenable_bzlmod");
    Collections.addAll(params, args);
    dispatcher.exec(params, "my client", outErr);
  }

  /**
   * Performs loading and analysis on the fixed rule <code>//test:buildme</code> with the given
   * build options (as they'd appear on the command line).
   */
  private void analyzeTargetWithTransition(String... args) throws Exception {
    List<String> params = Lists.newArrayList("build");
    // Basic flags required to make any build work. Ideally we'd go through BlazeRuntimeWrapper,
    // which does the same setup. But that's explicitly documented as not supported command
    // invocations, which is exactly what we we need here.
    params.addAll(TestConstants.PRODUCT_SPECIFIC_FLAGS);
    params.add("//test:buildme_with_transition");
    params.add("--nobuild"); // Execution phase isn't necessary to collect configurations.
    // TODO: Enable Bzlmod for this test
    // https://github.com/bazelbuild/bazel/issues/19823
    params.add("--noenable_bzlmod");
    Collections.addAll(params, args);
    dispatcher.exec(params, "my client", outErr);
  }

  /**
   * Calls <cod>blaze config --output=json</code> with the given flags and returns the raw output.
   *
   * <p>Should be called after {@link #analyzeTarget} so there are actual configs to read.
   */
  private RecordingOutErr callConfigCommand(String... args) throws Exception {
    List<String> params = Lists.newArrayList("config");
    params.add("--output=json");
    // TODO: Enable Bzlmod for this test
    // https://github.com/bazelbuild/bazel/issues/19823
    params.add("--noenable_bzlmod");
    Collections.addAll(params, args);
    RecordingOutErr recordingOutErr = new RecordingOutErr();
    dispatcher.exec(params, "my client", recordingOutErr);
    return recordingOutErr;
  }

  /**
   * Returns the value of an option under a configuration's {@link FragmentOptions}.
   *
   * <p>Throws {@link NoSuchElementException} if it can't be found.
   */
  private static String getOptionValue(
      ConfigurationForOutput config, String fragmentOptions, String optionName) {
    List<String> ans =
        config.fragmentOptions.stream()
            .filter(fragment -> fragment.name.endsWith(fragmentOptions))
            .flatMap(fragment -> fragment.options.entrySet().stream())
            .filter(setting -> setting.getKey().equals(optionName))
            .map(Map.Entry::getValue)
            .collect(Collectors.toList());
    if (ans.size() > 1) {
      throw new NoSuchElementException(
          String.format(
              "Multiple matches for fragment=%s, option=%s", fragmentOptions, optionName));
    } else if (ans.isEmpty()) {
      throw new NoSuchElementException(
          String.format("No matches for fragment=%s, option=%s", fragmentOptions, optionName));
    }
    return ans.get(0);
  }

  private static boolean isTargetConfig(ConfigurationForOutput config) {
    if (config.mnemonic.endsWith("-noconfig")) {
      return false;
    }
    return !Boolean.parseBoolean(getOptionValue(config, "CoreOptions", "is exec configuration"));
  }

  /** Converts {@code a.b.d} to {@code d}. */
  private static String getBaseName(String str) {
    return str.substring(str.lastIndexOf(".") + 1);
  }

  /** Converts a list of {@code a.b.d} strings to {@code d} form. */
  private static List<String> getBaseNames(List<String> list) {
    return list.stream().map(ConfigCommandTest::getBaseName).collect(Collectors.toList());
  }

  @Test
  public void showConfigIds() throws Exception {
    analyzeTarget();
    JsonObject fullJson =
        JsonParser.parseString(callConfigCommand().outAsLatin1()).getAsJsonObject();
    // Should be: target configuration, target configuration without test.
    assertThat(fullJson).isNotNull();
    assertThat(fullJson.has("configuration-IDs")).isTrue();
    assertThat(fullJson.get("configuration-IDs").getAsJsonArray().size()).isEqualTo(3);
  }

  private boolean skipNoConfig(JsonElement configHash) {
    try {
      return !new Gson()
          .fromJson(
              callConfigCommand(configHash.getAsString()).outAsLatin1(),
              ConfigurationForOutput.class)
          .mnemonic
          .contains("-noconfig");
    } catch (Exception e) {
      assertWithMessage("Failed to retrieve %s: %s", configHash.getAsString(), e.getMessage())
          .fail();
      return false;
    }
  }

  /**
   * Calls the config command to return all config hashes currently available.
   *
   * @param includeNoConfig if true, include the "noconfig" configuration (see {@link
   *     com.google.devtools.build.lib.analysis.config.transitions.NoConfigTransition}. Else filter
   *     it out.
   */
  private ImmutableList<String> getConfigHashes(boolean includeNoConfig) throws Exception {
    return stream(
            JsonParser.parseString(callConfigCommand().outAsLatin1())
                .getAsJsonObject()
                .get("configuration-IDs")
                .getAsJsonArray()
                .iterator())
        .filter(includeNoConfig ? Predicates.alwaysTrue() : this::skipNoConfig)
        .map(c -> c.getAsString())
        .collect(toImmutableList());
  }

  @Test
  public void showSingleConfig() throws Exception {
    analyzeTarget();
    // Find the first non-noconfig configuration (see NoConfigTransition). noconfig is a special
    // configuration that strips away most of its structure, so not a good candidate for this test.
    String configHash = getConfigHashes(/* includeNoConfig= */ false).get(0);
    ConfigurationForOutput config =
        new Gson()
            .fromJson(callConfigCommand(configHash).outAsLatin1(), ConfigurationForOutput.class);

    assertThat(config).isNotNull();
    // Verify config metadata:
    assertThat(config.configHash).isEqualTo(configHash);
    assertThat(config.skyKey).isEqualTo(String.format("BuildConfigurationKey[%s]", configHash));
    // Verify the existence of a couple of expected fragments:
    assertThat(
            config.fragments.stream()
                .map(
                    fragment ->
                        Pair.of(getBaseName(fragment.name), getBaseNames(fragment.fragmentOptions)))
                .collect(Collectors.toList()))
        .containsAtLeast(
            Pair.of("PlatformConfiguration", ImmutableList.of("PlatformOptions")),
            Pair.of("TestConfiguration", ImmutableList.of("TestConfiguration$TestOptions")));
    // Verify the existence of a couple of expected fragment options:
    assertThat(
            config.fragmentOptions.stream()
                .map(fragment -> getBaseName(fragment.name))
                .collect(Collectors.toList()))
        .containsAtLeast("PlatformOptions", "CoreOptions", "user-defined");
    // Verify the existence of a couple of expected option names:
    assertThat(
            config.fragmentOptions.stream()
                .filter(fragment -> fragment.name.endsWith("CoreOptions"))
                .flatMap(fragment -> fragment.options.keySet().stream())
                .collect(Collectors.toList()))
        .containsAtLeast("run_under", "check_visibility", "stamp");
  }

  @Test
  public void showSingleConfigHashPrefix() throws Exception {
    analyzeTarget();
    String configHash =
        JsonParser.parseString(callConfigCommand().outAsLatin1())
            .getAsJsonObject()
            .get("configuration-IDs")
            .getAsJsonArray()
            .get(0)
            .getAsString();
    String hashPrefix = configHash.substring(0, configHash.length() / 2);
    ConfigurationForOutput config =
        new Gson()
            .fromJson(callConfigCommand(hashPrefix).outAsLatin1(), ConfigurationForOutput.class);
    assertThat(config).isNotNull();
    assertThat(config.configHash).startsWith(hashPrefix);
  }

  @Test
  public void unknownHashPrefix() throws Exception {
    analyzeTarget();
    String configHash =
        JsonParser.parseString(callConfigCommand().outAsLatin1())
            .getAsJsonObject()
            .get("configuration-IDs")
            .getAsJsonArray()
            .get(0)
            .getAsString();
    // No valid hash has spaces.
    String hashPrefix = configHash.substring(0, configHash.length() / 2) + " ";
    assertThat(callConfigCommand(hashPrefix).errAsLatin1())
        .contains("No configuration found with ID prefix " + hashPrefix);
  }

  @Test
  public void showAllConfigs() throws Exception {
    analyzeTarget();

    int numConfigs = 0;
    for (JsonElement configJson :
        JsonParser.parseString(callConfigCommand("--dump_all").outAsLatin1()).getAsJsonArray()) {
      ConfigurationForOutput config = new Gson().fromJson(configJson, ConfigurationForOutput.class);
      assertThat(config).isNotNull();
      numConfigs++;
    }
    assertThat(numConfigs).isEqualTo(3); // Target + target w/o test + nonConfig.
  }

  @Test
  public void compareConfigs() throws Exception {
    // Do not trim test configuration for now to make 'finding' the configurations easier.
    analyzeTargetWithTransition("--platform_suffix=pure", "--notrim_test_configuration");
    String targetConfig1Hash = getTargetConfig().configHash;
    String targetConfig2Hash =
        getTargetConfig(/*excludedHashes=*/ ImmutableSet.of(targetConfig1Hash)).configHash;

    // Get their diff.
    String result = callConfigCommand(targetConfig1Hash, targetConfig2Hash).outAsLatin1();
    ConfigurationDiffForOutput diff = new Gson().fromJson(result, ConfigurationDiffForOutput.class);
    assertThat(diff).isNotNull();
    assertThat(diff.configHash1).isEqualTo(targetConfig1Hash);
    assertThat(diff.configHash2).isEqualTo(targetConfig2Hash);
    FragmentDiffForOutput fragmentDiff = Iterables.getOnlyElement(diff.fragmentsDiff);
    assertThat(fragmentDiff.name).endsWith("CoreOptions");
    Map.Entry<String, Pair<String, String>> optionDiff =
        Iterators.getOnlyElement(
            fragmentDiff.optionsDiff.entrySet().stream()
                .filter(x -> !x.getKey().equals("affected by starlark transition"))
                .iterator());
    assertThat(optionDiff.getKey()).isEqualTo("platform_suffix");
    // Convert from Pair<firstVal, secondVal> to an ImmutableList because the ordering of the
    // difference depends on which configuration comes first, which depends on the configuration
    // hash name, which we can't predict statically.
    assertThat(ImmutableList.of(optionDiff.getValue().first, optionDiff.getValue().second))
        .containsExactly("pure", "transitioned");
  }

  @Test
  public void compareConfigsHashPrefix() throws Exception {
    // Do not trim test configuration for now to make 'finding' the configurations easier.
    analyzeTargetWithTransition("--platform_suffix=pure", "--notrim_test_configuration");
    String targetConfig1Hash = getTargetConfig().configHash;
    String targetConfig2Hash =
        getTargetConfig(/*excludedHashes=*/ ImmutableSet.of(targetConfig1Hash)).configHash;

    String hashPrefix1 = targetConfig1Hash.substring(0, targetConfig1Hash.length() / 2);
    String hashPrefix2 = targetConfig2Hash.substring(0, targetConfig2Hash.length() / 2);

    ConfigurationDiffForOutput diff =
        new Gson()
            .fromJson(
                callConfigCommand(hashPrefix1, hashPrefix2).outAsLatin1(),
                ConfigurationDiffForOutput.class);
    assertThat(diff).isNotNull();
    assertThat(diff.configHash1).startsWith(hashPrefix1);
    assertThat(diff.configHash2).startsWith(hashPrefix2);
  }

  private ConfigurationForOutput getTargetConfig() throws Exception {
    return getTargetConfig(ImmutableSet.of());
  }

  private ConfigurationForOutput getTargetConfig(ImmutableSet<String> excludedHashes)
      throws Exception {
    // Find a target configuration hash.
    for (JsonElement element :
        JsonParser.parseString(callConfigCommand().outAsLatin1())
            .getAsJsonObject()
            .get("configuration-IDs")
            .getAsJsonArray()) {
      String configHash = element.getAsString();
      if (excludedHashes.contains(configHash)) {
        continue;
      }
      ConfigurationForOutput config =
          new Gson()
              .fromJson(callConfigCommand(configHash).outAsLatin1(), ConfigurationForOutput.class);
      if (isTargetConfig(config)) {
        return config;
      }
    }
    throw new AssertionError("Should have found config hash");
  }

  @Test
  public void starlarkFlagsInUserDefinedFragment() throws Exception {
    write(
        "test/flagdef.bzl",
        "def _rule_impl(ctx):",
        "    return []",
        "string_flag = rule(",
        "    implementation = _rule_impl,",
        "    build_setting = config.string(flag = True)",
        ")",
        "simple_rule = rule(",
        "    implementation = _rule_impl,",
        "    attrs = {}",
        ")");
    write(
        "custom_flags/BUILD",
        "load('//test:flagdef.bzl', 'string_flag')",
        "string_flag(",
        "    name = 'my_flag',",
        "    build_setting_default = '')");

    analyzeTarget("--//custom_flags:my_flag=hello");

    ConfigurationForOutput targetConfig = null;
    String result = callConfigCommand("--dump_all").outAsLatin1();
    for (JsonElement configJson : JsonParser.parseString(result).getAsJsonArray()) {
      ConfigurationForOutput config = new Gson().fromJson(configJson, ConfigurationForOutput.class);
      if (isTargetConfig(config)) {
        targetConfig = config;
        break;
      }
    }

    assertThat(targetConfig).isNotNull();
    assertThat(getOptionValue(targetConfig, "user-defined", "//custom_flags:my_flag"))
        .isEqualTo("hello");
  }

  @Test
  public void defineFlagsIndividuallyListedInUserDefinedFragment() throws Exception {
    analyzeTarget("--define", "a=1", "--define", "b=2");

    ConfigurationForOutput targetConfig = null;
    for (JsonElement configJson :
        JsonParser.parseString(callConfigCommand("--dump_all").outAsLatin1()).getAsJsonArray()) {
      ConfigurationForOutput config = new Gson().fromJson(configJson, ConfigurationForOutput.class);
      if (isTargetConfig(config)) {
        targetConfig = config;
        break;
      }
    }

    assertThat(targetConfig).isNotNull();
    assertThat(getOptionValue(targetConfig, "user-defined", "--define:a")).isEqualTo("1");
    assertThat(getOptionValue(targetConfig, "user-defined", "--define:b")).isEqualTo("2");
    assertThat(
            targetConfig.fragmentOptions.stream()
                .filter(fragment -> fragment.name.endsWith("CoreOptions"))
                .flatMap(fragment -> fragment.options.keySet().stream())
                .filter(name -> name.equals("define"))
                .collect(Collectors.toList()))
        .isEmpty();
  }

  @Test
  public void conflictingDefinesLastWins() throws Exception {
    analyzeTarget("--define", "a=1", "--define", "a=2");

    ConfigurationForOutput targetConfig = null;
    for (JsonElement configJson :
        JsonParser.parseString(callConfigCommand("--dump_all").outAsLatin1()).getAsJsonArray()) {
      ConfigurationForOutput config = new Gson().fromJson(configJson, ConfigurationForOutput.class);
      if (isTargetConfig(config)) {
        targetConfig = config;
        break;
      }
    }

    assertThat(targetConfig).isNotNull();
    assertThat(getOptionValue(targetConfig, "user-defined", "--define:a")).isEqualTo("2");
    assertThat(
            targetConfig.fragmentOptions.stream()
                .filter(fragment -> fragment.name.endsWith("CoreOptions"))
                .flatMap(fragment -> fragment.options.keySet().stream())
                .filter(name -> name.equals("define"))
                .collect(Collectors.toList()))
        .isEmpty();
  }
}
