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

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.ServerDirectories;
import com.google.devtools.build.lib.exec.BinTools;
import com.google.devtools.build.lib.exec.util.SpawnBuilder;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.testutil.Scratch;
import com.google.devtools.build.lib.testutil.TestConstants;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.common.options.Converters;
import com.google.devtools.common.options.OptionsParsingException;
import com.google.devtools.common.options.OptionsParsingResult;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link com.google.devtools.build.lib.dynamic.DynamicExecutionModule}. */
@RunWith(JUnit4.class)
public class DynamicExecutionModuleTest {
  private static final PathFragment OUTPUT_BASE = PathFragment.create("blaze-out");

  private DynamicExecutionModule module;
  private DynamicExecutionOptions options;
  private BlazeRuntime blazeRuntime;

  @Before
  public void setUp() throws IOException, AbruptExitException {
    module = new DynamicExecutionModule(Executors.newCachedThreadPool());
    options = new DynamicExecutionOptions();
    options.dynamicLocalStrategy = Collections.emptyList(); // default
    options.dynamicRemoteStrategy = Collections.emptyList(); // default
  }

  @Test
  public void testGetLocalStrategies_getsDefaultWithNoOptions()
      throws AbruptExitException, OptionsParsingException {
    assertThat(module.getLocalStrategies(options)).isEqualTo(parseStrategies("worker,sandboxed"));
  }

  @Test
  public void testGetLocalStrategies_genericOptionOverridesFallbacks()
      throws AbruptExitException, OptionsParsingException {
    options.dynamicLocalStrategy = parseStrategiesToOptions("local,worker");
    assertThat(module.getLocalStrategies(options)).isEqualTo(parseStrategies("local,worker"));
  }

  @Test
  public void testGetLocalStrategies_specificOptionKeepsFallbacks()
      throws AbruptExitException, OptionsParsingException {
    options.dynamicLocalStrategy = parseStrategiesToOptions("Foo=local,worker");
    assertThat(module.getLocalStrategies(options))
        .isEqualTo(parseStrategies("Foo=local,worker", "worker,sandboxed"));
  }

  @Test
  public void testGetLocalStrategies_canMixSpecificsAndGenericOptions()
      throws AbruptExitException, OptionsParsingException {
    options.dynamicLocalStrategy = parseStrategiesToOptions("Foo=local,worker", "worker");
    assertThat(module.getLocalStrategies(options))
        .isEqualTo(parseStrategies("Foo=local,worker", "worker"));
  }

  @Test
  public void canIgnoreFailure_simpleCases() throws IOException, AbruptExitException {
    setupRuntime();
    Spawn spawn = new SpawnBuilder().withOutput("output").build();
    CommandEnvironment mockCommandEnvironment = mock(CommandEnvironment.class);
    OptionsParsingResult mockOptions = mock(OptionsParsingResult.class);
    when(mockCommandEnvironment.getOptions()).thenReturn(mockOptions);
    EventBus mockEventBus = mock(EventBus.class);
    when(mockCommandEnvironment.getEventBus()).thenReturn(mockEventBus);
    when(mockCommandEnvironment.getBlazeWorkspace()).thenReturn(blazeRuntime.getWorkspace());
    DynamicExecutionOptions options = new DynamicExecutionOptions();
    when(mockOptions.getOptions(DynamicExecutionOptions.class)).thenReturn(options);
    ActionExecutionContext context = mock(ActionExecutionContext.class);

    options.ignoreLocalSignals = ImmutableSet.of();
    module.beforeCommand(mockCommandEnvironment);
    assertThat(module.canIgnoreFailure(spawn, context, 130, "Failed", null, true)).isFalse();

    options.ignoreLocalSignals = ImmutableSet.of(9);
    module.beforeCommand(mockCommandEnvironment);
    assertThat(module.canIgnoreFailure(spawn, context, 130, "Failed", null, true)).isFalse();

    options.ignoreLocalSignals = ImmutableSet.of(2, 9);
    module.beforeCommand(mockCommandEnvironment);
    assertThat(module.canIgnoreFailure(spawn, context, 130, "Failed", null, false)).isFalse();
    assertThat(module.canIgnoreFailure(spawn, context, 0, "Failed", null, true)).isFalse();
    assertThat(module.canIgnoreFailure(spawn, context, 130, "Failed", null, true)).isTrue();
    assertThat(module.canIgnoreFailure(spawn, context, 137, "Failed", null, true)).isTrue();
  }

  private void setupRuntime() throws IOException, AbruptExitException {
    Scratch scratch = new Scratch();
    Path execDir = scratch.dir("/foo");
    Root root = Root.fromPath(execDir);
    ServerDirectories serverDirectories =
        new ServerDirectories(
            scratch.dir("/installBase"),
            root.getRelative(OUTPUT_BASE),
            scratch.dir("/output-user"));
    blazeRuntime =
        new BlazeRuntime.Builder()
            .setFileSystem(scratch.getFileSystem())
            .setProductName(TestConstants.PRODUCT_NAME)
            .setServerDirectories(serverDirectories)
            .setStartupOptionsProvider(mock(OptionsParsingResult.class))
            .build();
    BinTools binTools = BinTools.forUnitTesting(execDir, ImmutableList.of());
    blazeRuntime.initWorkspace(
        new BlazeDirectories(
            serverDirectories,
            scratch.dir(TestConstants.WORKSPACE_NAME),
            null,
            TestConstants.PRODUCT_NAME),
        binTools);
  }

  private static List<Map.Entry<String, List<String>>> parseStrategiesToOptions(
      String... strategies) throws OptionsParsingException {
    Map<String, List<String>> result = parseStrategies(strategies);
    return Lists.newArrayList(result.entrySet());
  }

  private static Map<String, List<String>> parseStrategies(String... strategies)
      throws OptionsParsingException {
    Map<String, List<String>> result = new LinkedHashMap<>();
    Converters.StringToStringListConverter converter = new Converters.StringToStringListConverter();
    for (String s : strategies) {
      Map.Entry<String, List<String>> converted = converter.convert(s);
      // Have to avoid using Immutable* to allow overwriting elements.
      result.put(converted.getKey(), Lists.newArrayList(converted.getValue()));
    }
    return result;
  }

}
