// Copyright 2017 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.worker;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.hash.HashCode;
import com.google.devtools.build.lib.actions.ExecutionRequirements.WorkerProtocolFormat;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import java.io.IOException;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link WorkerFactory}. */
@RunWith(JUnit4.class)
public class WorkerFactoryTest {

  final FileSystem fs = new InMemoryFileSystem(DigestHashFunction.SHA256);

  @After
  public void tearDown() {
    WorkerMultiplexerManager.resetForTesting();
  }

  /**
   * Regression test for b/64689608: The execroot of the sandboxed worker process must end with the
   * workspace name, just like the normal execroot does.
   */
  @Test
  public void sandboxedWorkerPathEndsWithWorkspaceName() throws Exception {
    Path workerBaseDir = fs.getPath("/outputbase/bazel-workers");
    WorkerFactory workerFactory = new WorkerFactory(workerBaseDir);
    WorkerKey workerKey = createWorkerKey(/* mustBeSandboxed= */ true, /* multiplex= */ false);
    Path sandboxedWorkerPath = workerFactory.getSandboxedWorkerPath(workerKey, 1);

    assertThat(sandboxedWorkerPath.getBaseName()).isEqualTo("workspace");
  }

  /** WorkerFactory should create correct worker type based on WorkerKey. */
  @Test
  public void workerCreationTypeCheck() throws Exception {
    Path workerBaseDir = fs.getPath("/outputbase/bazel-workers");
    WorkerFactory workerFactory = new WorkerFactory(workerBaseDir);
    WorkerKey sandboxedWorkerKey =
        createWorkerKey(/* mustBeSandboxed= */ true, /* multiplex= */ false);
    Worker sandboxedWorker = workerFactory.create(sandboxedWorkerKey);
    assertThat(sandboxedWorker.getClass()).isEqualTo(SandboxedWorker.class);

    WorkerKey nonProxiedWorkerKey =
        createWorkerKey(/* mustBeSandboxed= */ false, /* multiplex= */ false);
    Worker nonProxiedWorker = workerFactory.create(nonProxiedWorkerKey);
    assertThat(nonProxiedWorker.getClass()).isEqualTo(SingleplexWorker.class);

    WorkerKey proxiedWorkerKey =
        createWorkerKey(/* mustBeSandboxed= */ false, /* multiplex= */ true);
    Worker proxiedWorker = workerFactory.create(proxiedWorkerKey);
    // If proxied = true, WorkerProxy is created along with a WorkerMultiplexer.
    // Destroy WorkerMultiplexer to avoid unexpected behavior in WorkerMultiplexerManagerTest.
    WorkerMultiplexerManager.removeInstance(proxiedWorkerKey);
    assertThat(proxiedWorker.getClass()).isEqualTo(WorkerProxy.class);
  }

  /** Proxied workers with the same WorkerKey should share the log file. */
  @Test
  public void testMultiplexWorkersShareLogfiles() throws Exception {
    Path workerBaseDir = fs.getPath("/outputbase/bazel-workers");
    WorkerFactory workerFactory = new WorkerFactory(workerBaseDir);

    WorkerKey workerKey1 =
        createWorkerKey(/* mustBeSandboxed= */ false, /* multiplex= */ true, "arg1");
    Worker proxiedWorker1a = workerFactory.create(workerKey1);
    Worker proxiedWorker1b = workerFactory.create(workerKey1);
    WorkerKey workerKey2 =
        createWorkerKey(/* mustBeSandboxed= */ false, /* multiplex= */ true, "arg2");
    Worker proxiedWorker2 = workerFactory.create(workerKey2);
    assertThat(proxiedWorker1a.getLogFile()).isEqualTo(proxiedWorker1b.getLogFile());
    assertThat(proxiedWorker1a.getLogFile()).isNotEqualTo(proxiedWorker2.getLogFile());
  }

  /** WorkerFactory should create the base dir if needed and fail if that's impossible. */
  @Test
  public void testCreate_createsWorkerDirectory() throws Exception {
    Path workerBaseDir = fs.getPath("/outputbase/bazel-workers");
    WorkerFactory workerFactory = new WorkerFactory(workerBaseDir);
    WorkerKey sandboxedWorkerKey = createWorkerKey(/* mustBeSandboxed */ true, /* proxied */ false);
    assertThat(workerBaseDir.isDirectory()).isFalse();
    workerFactory.create(sandboxedWorkerKey);
    assertThat(workerBaseDir.isDirectory()).isTrue();

    workerBaseDir.delete();
    workerBaseDir.createSymbolicLink(workerBaseDir.getRelative("whatevs"));
    assertThat(workerBaseDir.isDirectory()).isFalse();
    assertThrows(IOException.class, () -> workerFactory.create(sandboxedWorkerKey));
  }

  protected WorkerKey createWorkerKey(boolean mustBeSandboxed, boolean multiplex, String... args) {
    return new WorkerKey(
        /* args= */ ImmutableList.copyOf(args),
        /* env= */ ImmutableMap.of(),
        /* execRoot= */ fs.getPath("/outputbase/execroot/workspace"),
        /* mnemonic= */ "dummy",
        /* workerFilesCombinedHash= */ HashCode.fromInt(0),
        /* workerFilesWithHashes= */ ImmutableSortedMap.of(),
        /* sandboxed= */ mustBeSandboxed,
        /* multiplex= */ multiplex,
        /* cancellable= */ false,
        WorkerProtocolFormat.PROTO);
  }
}
