// 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.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.when;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.analysis.ServerDirectories;
import com.google.devtools.build.lib.buildtool.BuildRequestOptions;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.BlazeServerStartupOptions;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.runtime.commands.TargetPatternsHelper.TargetPatternsHelperException;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.server.FailureDetails.TargetPatterns;
import com.google.devtools.build.lib.server.FailureDetails.TargetPatterns.Code;
import com.google.devtools.build.lib.testutil.Scratch;
import com.google.devtools.build.lib.testutil.TestConstants;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mockito;

/** Tests {@link TargetPatternsHelper}. */
@RunWith(JUnit4.class)
public class TargetPatternsHelperTest {

  private CommandEnvironment env;
  private Scratch scratch;
  private OptionsParser options;

  @Before
  public void setUp() throws Exception {
    options = OptionsParser.builder().optionsClasses(BuildRequestOptions.class).build();
    scratch = new Scratch();
    BlazeRuntime runtime =
        new BlazeRuntime.Builder()
            .setFileSystem(scratch.getFileSystem())
            .setProductName(TestConstants.PRODUCT_NAME)
            .setServerDirectories(
                new ServerDirectories(
                    scratch.resolve("/install"),
                    scratch.resolve("/base"),
                    scratch.resolve("/userRoot")))
            .setStartupOptionsProvider(
                OptionsParser.builder().optionsClasses(BlazeServerStartupOptions.class).build())
            .build();
    env = Mockito.mock(CommandEnvironment.class);
    when(env.getWorkingDirectory()).thenReturn(scratch.resolve("wd"));
    when(env.getRuntime()).thenReturn(runtime);
  }

  @Test
  public void testEmpty() throws TargetPatternsHelperException {
    // tests when no residue and no --target_pattern_file are set
    assertThat(TargetPatternsHelper.readFrom(env, options)).isEmpty();
  }

  @Test
  public void testTargetPatternFile() throws Exception {
    scratch.file("/wd/patterns.txt", "//some/...\n//patterns");
    options.parse("--target_pattern_file=patterns.txt");

    assertThat(TargetPatternsHelper.readFrom(env, options))
        .isEqualTo(ImmutableList.of("//some/...", "//patterns"));
  }

  @Test
  public void testNoTargetPatternFile() throws TargetPatternsHelperException {
    ImmutableList<String> patterns = ImmutableList.of("//some/...", "//patterns");
    options.setResidue(patterns, ImmutableList.of());

    assertThat(TargetPatternsHelper.readFrom(env, options)).isEqualTo(patterns);
  }

  @Test
  public void testSpecifyPatternAndFileThrows() throws OptionsParsingException {
    options.parse("--target_pattern_file=patterns.txt");
    options.setResidue(ImmutableList.of("//some:pattern"), ImmutableList.of());

    TargetPatternsHelperException expected =
        assertThrows(
            TargetPatternsHelperException.class, () -> TargetPatternsHelper.readFrom(env, options));

    String message =
        "Command-line target pattern and --target_pattern_file cannot both be specified";
    assertThat(expected).hasMessageThat().isEqualTo(message);
    assertThat(expected.getFailureDetail())
        .isEqualTo(
            FailureDetail.newBuilder()
                .setMessage(message)
                .setTargetPatterns(
                    TargetPatterns.newBuilder()
                        .setCode(Code.TARGET_PATTERN_FILE_WITH_COMMAND_LINE_PATTERN))
                .build());
  }

  @Test
  public void testSpecifyNonExistingFileThrows() throws OptionsParsingException {
    options.parse("--target_pattern_file=patterns.txt");

    TargetPatternsHelperException expected =
        assertThrows(
            TargetPatternsHelperException.class, () -> TargetPatternsHelper.readFrom(env, options));

    String regex = "I/O error reading from .*patterns.txt.*\\(No such file or directory\\)";
    assertThat(expected).hasMessageThat().matches(regex);
    assertThat(expected.getFailureDetail().getMessage()).matches(regex);
    assertThat(expected.getFailureDetail().hasTargetPatterns()).isTrue();
    assertThat(expected.getFailureDetail().getTargetPatterns().getCode())
        .isEqualTo(Code.TARGET_PATTERN_FILE_READ_FAILURE);
  }
}
