// 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.starlark;

import static com.google.common.truth.Truth.assertThat;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.AbstractAction;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.AnalysisResult;
import com.google.devtools.build.lib.analysis.ConfiguredAspect;
import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.StarlarkProvider;
import com.google.devtools.build.lib.packages.StructImpl;
import java.util.List;
import java.util.stream.Collectors;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.Sequence;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for the Starlark-accessible actions provider on rule configured targets. */
@RunWith(JUnit4.class)
public class StarlarkActionProviderTest extends AnalysisTestCase {

  @Test
  public void aspectGetsActionProviderForNativeRule() throws Exception {
    scratch.file(
        "test/aspect.bzl",
        "foo = provider()",
        "def _impl(target, ctx):",
        "   return [foo(actions = target.actions)]",
        "MyAspect = aspect(implementation=_impl)");
    scratch.file(
        "test/BUILD",
        "genrule(",
        "   name = 'xxx',",
        "   cmd = 'echo \"hello\" > $@',",
        "   outs = ['mygen.out']",
        ")");

    AnalysisResult analysisResult =
        update(ImmutableList.of("test/aspect.bzl%MyAspect"), "//test:xxx");

    ConfiguredAspect configuredAspect =
        Iterables.getOnlyElement(analysisResult.getAspectsMap().values());

    StarlarkProvider.Key fooKey =
        new StarlarkProvider.Key(
            Label.parseAbsolute("//test:aspect.bzl", ImmutableMap.of()), "foo");

    StructImpl fooProvider = (StructImpl) configuredAspect.get(fooKey);
    assertThat(fooProvider.getValue("actions")).isNotNull();
    @SuppressWarnings("unchecked")
    Sequence<ActionAnalysisMetadata> actions =
        (Sequence<ActionAnalysisMetadata>) fooProvider.getValue("actions");
    assertThat(actions).isNotEmpty();

    ActionAnalysisMetadata action = actions.get(0);
    assertThat(action.getMnemonic()).isEqualTo("Genrule");
    assertThat(action).isInstanceOf(AbstractAction.class);
  }

  @Test
  @SuppressWarnings("unchecked")
  public void aspectGetsActionProviderForStarlarkRule() throws Exception {
    scratch.file(
        "test/aspect.bzl",
        "foo = provider()",
        "def _impl(target, ctx):",
        "   mnemonics = [a.mnemonic for a in target.actions]",
        "   envs = [a.env for a in target.actions]",
        "   execution_info = [a.execution_info for a in target.actions]",
        "   inputs = [a.inputs.to_list() for a in target.actions]",
        "   outputs = [a.outputs.to_list() for a in target.actions]",
        "   argv = [a.argv for a in target.actions]",
        "   return [foo(",
        "       actions = target.actions,",
        "       mnemonics = mnemonics,",
        "       envs = envs,",
        "       execution_info = execution_info,",
        "       inputs = inputs,",
        "       outputs = outputs,",
        "       argv = argv",
        "    )]",
        "MyAspect = aspect(implementation=_impl)");
    scratch.file(
        "test/rule.bzl",
        "def impl(ctx):",
        "  output_file0 = ctx.actions.declare_file('myfile0')",
        "  output_file1 = ctx.actions.declare_file('myfile1')",
        "  executable = ctx.actions.declare_file('executable')",
        "  ctx.actions.run(outputs=[output_file0], executable=executable,",
        "      mnemonic='MyAction0', env={'foo':'bar', 'pet':'puppy'})",
        "  ctx.actions.run_shell(outputs=[executable, output_file1],",
        "      command='fakecmd', mnemonic='MyAction1', env={'pet':'bunny'})",
        "  return None",
        "my_rule = rule(impl)");
    scratch.file(
        "test/BUILD", "load('//test:rule.bzl', 'my_rule')", "my_rule(", "   name = 'xxx',", ")");

    useConfiguration("--experimental_google_legacy_api");
    AnalysisResult analysisResult =
        update(ImmutableList.of("test/aspect.bzl%MyAspect"), "//test:xxx");

    ConfiguredAspect configuredAspect =
        Iterables.getOnlyElement(analysisResult.getAspectsMap().values());

    StarlarkProvider.Key fooKey =
        new StarlarkProvider.Key(
            Label.parseAbsolute("//test:aspect.bzl", ImmutableMap.of()), "foo");
    StructImpl fooProvider = (StructImpl) configuredAspect.get(fooKey);
    assertThat(fooProvider.getValue("actions")).isNotNull();

    Sequence<ActionAnalysisMetadata> actions =
        (Sequence<ActionAnalysisMetadata>) fooProvider.getValue("actions");
    assertThat(actions).hasSize(2);

    Sequence<String> mnemonics = (Sequence<String>) fooProvider.getValue("mnemonics");
    assertThat(mnemonics).containsExactly("MyAction0", "MyAction1");

    Sequence<Dict<String, String>> envs =
        (Sequence<Dict<String, String>>) fooProvider.getValue("envs");
    assertThat(envs)
        .containsExactly(
            Dict.builder().put("foo", "bar").put("pet", "puppy").buildImmutable(),
            Dict.builder().put("pet", "bunny").buildImmutable());

    Sequence<Dict<String, String>> executionInfo =
        (Sequence<Dict<String, String>>) fooProvider.getValue("execution_info");
    assertThat(executionInfo).isNotNull();

    Sequence<Sequence<Artifact>> inputs =
        (Sequence<Sequence<Artifact>>) fooProvider.getValue("inputs");
    assertThat(flattenArtifactNames(inputs)).containsExactly("executable");

    Sequence<Sequence<Artifact>> outputs =
        (Sequence<Sequence<Artifact>>) fooProvider.getValue("outputs");
    assertThat(flattenArtifactNames(outputs)).containsExactly("myfile0", "executable", "myfile1");

    Sequence<Sequence<String>> argv = (Sequence<Sequence<String>>) fooProvider.getValue("argv");
    assertThat(argv.get(0)).hasSize(1);
    assertThat(argv.get(0).get(0)).endsWith("executable");
    assertThat(argv.get(1)).contains("fakecmd");
  }

  private static List<String> flattenArtifactNames(Sequence<Sequence<Artifact>> artifactLists) {
    return artifactLists.stream()
        .flatMap(artifacts -> artifacts.stream())
        .map(artifact -> artifact.getFilename())
        .collect(Collectors.toList());
  }
}
