// Copyright 2022 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.query2.cquery;

import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.OutputGroupInfo.ValidationMode;
import com.google.devtools.build.lib.analysis.TopLevelArtifactContext;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.query2.PostAnalysisQueryEnvironment;
import com.google.devtools.build.lib.query2.engine.QueryExpression;
import com.google.devtools.build.lib.query2.engine.QueryParser;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Test;

/** Tests cquery's {@link --output=files} format. */
public class FilesOutputFormatterCallbackTest extends ConfiguredTargetQueryTest {

  private CqueryOptions options;
  private Reporter reporter;
  private final List<Event> events = new ArrayList<>();

  @Before
  public final void defineSimpleRule() throws Exception {
    writeFile(
        "defs/rules.bzl",
        "def _r_impl(ctx):",
        "    default_file = ctx.actions.declare_file(ctx.attr.name + '_default_file')",
        "    output_group_only = ctx.actions.declare_file(ctx.attr.name + '_output_group_only')",
        "    runfile = ctx.actions.declare_file(ctx.attr.name + '_runfile')",
        "    executable_only = ctx.actions.declare_file(ctx.attr.name + '_executable')",
        "    files = [default_file, output_group_only, runfile, executable_only]",
        "    ctx.actions.run_shell(",
        "        outputs = files,",
        "        command = '\\n'.join(['touch %s' % file.path for file in files]),",
        "    )",
        "    return [",
        "        DefaultInfo(",
        "            executable = executable_only,",
        "            files = depset(",
        "                direct = [",
        "                    default_file,",
        "                    ctx.file._implicit_source_dep,",
        "                    ctx.file.explicit_source_dep,",
        "                ],",
        "                transitive = [info[DefaultInfo].files for info in ctx.attr.deps]",
        "            ),",
        "            runfiles = ctx.runfiles([runfile]),",
        "        ),",
        "        OutputGroupInfo(",
        "            foobar = [output_group_only, ctx.file.explicit_source_dep],",
        "        ),",
        "    ]",
        "r = rule(",
        "    implementation = _r_impl,",
        "    executable = True,",
        "    attrs = {",
        "        'deps': attr.label_list(),",
        "        '_implicit_source_dep': attr.label(default = 'rules.bzl', allow_single_file ="
            + " True),",
        "        'explicit_source_dep': attr.label(allow_single_file = True),",
        "    },",
        ")");
    writeFile("defs/BUILD", "exports_files(['rules.bzl'])");
    writeFile(
        "pkg/BUILD",
        "load('//defs:rules.bzl', 'r')",
        "r(",
        "    name = 'main',",
        "    explicit_source_dep = 'BUILD',",
        ")",
        "r(",
        "    name = 'other',",
        "    deps = [':main'],",
        "    explicit_source_dep = 'BUILD',",
        ")");
  }

  @Before
  public final void setUpCqueryOptions() {
    this.options = new CqueryOptions();
    this.reporter = new Reporter(new EventBus(), events::add);
  }

  private List<String> getOutput(String queryExpression, List<String> outputGroups)
      throws Exception {
    QueryExpression expression = QueryParser.parse(queryExpression, getDefaultFunctions());
    Set<String> targetPatternSet = new LinkedHashSet<>();
    expression.collectTargetPatterns(targetPatternSet);
    PostAnalysisQueryEnvironment<ConfiguredTarget> env =
        ((ConfiguredTargetQueryHelper) helper).getPostAnalysisQueryEnvironment(targetPatternSet);

    ByteArrayOutputStream output = new ByteArrayOutputStream();
    FilesOutputFormatterCallback callback =
        new FilesOutputFormatterCallback(
            reporter,
            options,
            new PrintStream(output),
            getHelper().getSkyframeExecutor(),
            env.getAccessor(),
            // Based on BuildRequest#getTopLevelArtifactContext.
            new TopLevelArtifactContext(
                false,
                false,
                false,
                OutputGroupInfo.determineOutputGroups(outputGroups, ValidationMode.OFF, false)));
    env.evaluateQuery(expression, callback);
    return Arrays.asList(output.toString(UTF_8).split(System.lineSeparator()));
  }

  @Test
  public void basicQuery_defaultOutputGroup() throws Exception {
    List<String> output = getOutput("//pkg:all", ImmutableList.of());
    var sourceAndGeneratedFiles =
        output.stream()
            .collect(Collectors.<String>partitioningBy(path -> path.matches("^[^/]*-out/.*")));
    assertThat(sourceAndGeneratedFiles.get(false)).containsExactly("pkg/BUILD", "defs/rules.bzl");
    assertContainsExactlyWithBinDirPrefix(
        sourceAndGeneratedFiles.get(true), "pkg/main_default_file", "pkg/other_default_file");
  }

  @Test
  public void basicQuery_defaultAndCustomOutputGroup() throws Exception {
    List<String> output = getOutput("//pkg:main", ImmutableList.of("+foobar"));
    var sourceAndGeneratedFiles =
        output.stream()
            .collect(Collectors.<String>partitioningBy(path -> path.matches("^[^/]*-out/.*")));
    assertThat(sourceAndGeneratedFiles.get(false)).containsExactly("pkg/BUILD", "defs/rules.bzl");
    assertContainsExactlyWithBinDirPrefix(
        sourceAndGeneratedFiles.get(true), "pkg/main_default_file", "pkg/main_output_group_only");
  }

  @Test
  public void basicQuery_customOutputGroupOnly() throws Exception {
    List<String> output = getOutput("//pkg:other", ImmutableList.of("foobar"));
    var sourceAndGeneratedFiles =
        output.stream()
            .collect(Collectors.<String>partitioningBy(path -> path.matches("^[^/]*-out/.*")));
    assertThat(sourceAndGeneratedFiles.get(false)).containsExactly("pkg/BUILD");
    assertContainsExactlyWithBinDirPrefix(
        sourceAndGeneratedFiles.get(true), "pkg/other_output_group_only");
  }

  private void assertContainsExactlyWithBinDirPrefix(
      List<String> output, String... binDirRelativePaths) {
    if (binDirRelativePaths.length == 0) {
      assertThat(output).isEmpty();
      return;
    }

    // Extract the configuration-dependent bin dir from the first output.
    assertThat(output).isNotEmpty();
    String firstPath = output.get(0);
    String binDir = firstPath.substring(0, firstPath.indexOf("bin/") + "bin/".length());

    assertThat(output)
        .containsExactly(
            Arrays.stream(binDirRelativePaths)
                .map(binDirRelativePath -> binDir + binDirRelativePath)
                .toArray());
  }
}
