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

import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertThrows;

import com.google.common.collect.ImmutableList;
import com.google.common.io.CharStreams;
import com.google.devtools.build.lib.actions.ParamFileInfo;
import com.google.devtools.build.lib.actions.ParameterFile;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.util.ShellEscaper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStreamReader;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Mutability;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkList;
import net.starlark.java.eval.StarlarkThread;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Each test method checks the intermediate argument string list generated from the same {@link
 * Args} with a different param file format. The param file would be generated by writing one
 * argument per line, possibly after filtering out the positional args.
 */
@RunWith(JUnit4.class)
public class ArgsParamFileTest extends BuildViewTestCase {

  private Args args;

  /** Initializes args with a mix of "flags" and "positional arguments. */
  // TODO(bazel-team): Consider rewriting this setup as Starlark code
  @Before
  public void initArgs() throws Exception {
    args = Args.newArgs(Mutability.create(), getStarlarkSemantics());
    StarlarkThread thread = new StarlarkThread(Mutability.create(), getStarlarkSemantics());
    args.addJoined(
        "--a",
        StarlarkList.of(/* mutability= */ null, "b", "c"),
        /* joinWith= */ ",",
        Starlark.NONE,
        Starlark.NONE,
        Starlark.NONE,
        false,
        false,
        false,
        false,
        thread);
    args.addArgument("--nod", Starlark.UNBOUND, /* format= */ Starlark.NONE, thread);
    args.addArgument("pos1", Starlark.UNBOUND, /* format= */ Starlark.NONE, thread);
    args.addAll(
        "--foo",
        StarlarkList.of(/* mutability= */ null, "bar1", "bar2", "bar3"),
        Starlark.NONE,
        Starlark.NONE,
        Starlark.NONE,
        false,
        false,
        false,
        Starlark.NONE,
        false,
        thread);
    args.addArgument("--e", "'f'", /* format= */ Starlark.NONE, thread);
    args.addArgument("pos2", Starlark.UNBOUND, /* format= */ Starlark.NONE, thread);
    // Ensure a ParamFileInfo will be returned
    args.useParamsFile("%s", true);
  }

  @Test
  public void badParamFileFormat() throws Exception {
    assertThrows(EvalException.class, () -> args.setParamFileFormat("punch_cards"));
  }

  @Test
  public void setParamFileFormatTwice() throws Exception {
    args.setParamFileFormat("shell");
    assertThrows(EvalException.class, () -> args.setParamFileFormat("shell"));
  }

  @Test
  public void shell() throws Exception {
    args.setParamFileFormat("shell");
    assertThat(toParamFile(args))
        .containsExactly(
            "--a",
            "b,c",
            "--nod",
            "pos1",
            "--foo",
            "bar1",
            "bar2",
            "bar3",
            "--e",
            ShellEscaper.escapeString("'f'"),
            "pos2")
        .inOrder();
    assertThat(args.getParamFileInfo().flagsOnly()).isFalse();
  }

  @Test
  public void multiline() throws Exception {
    args.setParamFileFormat("multiline");
    assertThat(toParamFile(args))
        .containsExactly(
            "--a", "b,c", "--nod", "pos1", "--foo", "bar1", "bar2", "bar3", "--e", "'f'", "pos2")
        .inOrder();
    assertThat(args.getParamFileInfo().flagsOnly()).isFalse();
  }

  @Test
  public void flagPerLine() throws Exception {
    args.setParamFileFormat("flag_per_line");
    assertThat(toParamFile(args))
        .containsExactly("--a=b,c", "--nod", "pos1", "--foo=bar1 bar2 bar3", "--e='f'", "pos2")
        .inOrder();
    assertThat(args.getParamFileInfo().flagsOnly()).isTrue();
  }

  /**
   * Writes out the Args using ParameterFile, returns the output broken down as lines. Note, this
   * does not respect {@link ParamFileInfo#flagsOnly()}.
   */
  private static ImmutableList<String> toParamFile(Args args) throws Exception {
    byte[] bytes;
    try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
      ParameterFile.writeParameterFile(
          outputStream,
          args.build(() -> RepositoryMapping.ALWAYS_FALLBACK).arguments(),
          args.getParameterFileType(),
          UTF_8);
      bytes = outputStream.toByteArray();
    }
    try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
        InputStreamReader reader = new InputStreamReader(inputStream, UTF_8)) {
      return ImmutableList.copyOf(CharStreams.readLines(reader));
    }
  }
}
