// Copyright 2018 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.remote;

import static com.google.common.truth.Truth.assertThat;

import build.bazel.remote.execution.v2.ActionCacheUpdateCapabilities;
import build.bazel.remote.execution.v2.CacheCapabilities;
import build.bazel.remote.execution.v2.CapabilitiesGrpc.CapabilitiesImplBase;
import build.bazel.remote.execution.v2.DigestFunction;
import build.bazel.remote.execution.v2.ExecutionCapabilities;
import build.bazel.remote.execution.v2.GetCapabilitiesRequest;
import build.bazel.remote.execution.v2.PriorityCapabilities;
import build.bazel.remote.execution.v2.PriorityCapabilities.PriorityRange;
import build.bazel.remote.execution.v2.RequestMetadata;
import build.bazel.remote.execution.v2.ServerCapabilities;
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions;
import com.google.devtools.build.lib.authandtls.GoogleAuthUtils;
import com.google.devtools.build.lib.remote.RemoteRetrier.ExponentialBackoff;
import com.google.devtools.build.lib.remote.options.RemoteOptions;
import com.google.devtools.build.lib.remote.util.TestUtils;
import com.google.devtools.build.lib.remote.util.TracingMetadataUtils;
import com.google.devtools.common.options.Options;
import io.grpc.CallCredentials;
import io.grpc.Metadata;
import io.grpc.Server;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
import io.grpc.ServerInterceptors;
import io.grpc.Status;
import io.grpc.inprocess.InProcessChannelBuilder;
import io.grpc.inprocess.InProcessServerBuilder;
import io.grpc.stub.StreamObserver;
import io.grpc.util.MutableHandlerRegistry;
import java.util.concurrent.Executors;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link RemoteServerCapabilities}. */
@RunWith(JUnit4.class)
public class RemoteServerCapabilitiesTest {

  private final MutableHandlerRegistry serviceRegistry = new MutableHandlerRegistry();
  private final String fakeServerName = "fake server for " + getClass();
  private Server fakeServer;
  private static ListeningScheduledExecutorService retryService;

  @BeforeClass
  public static void beforeEverything() {
    retryService = MoreExecutors.listeningDecorator(Executors.newScheduledThreadPool(1));
  }

  @Before
  public final void setUp() throws Exception {
    fakeServer =
        InProcessServerBuilder.forName(fakeServerName)
            .fallbackHandlerRegistry(serviceRegistry)
            .directExecutor()
            .build()
            .start();
  }

  @After
  public void tearDown() throws Exception {
    fakeServer.shutdownNow();
    fakeServer.awaitTermination();
  }

  @AfterClass
  public static void afterEverything() {
    retryService.shutdownNow();
  }

  /** Capture the request headers from a client. Useful for testing metadata propagation. */
  private static class RequestHeadersValidator implements ServerInterceptor {
    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
        ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
      RequestMetadata meta = headers.get(TracingMetadataUtils.METADATA_KEY);
      assertThat(meta.getCorrelatedInvocationsId()).isEqualTo("build-req-id");
      assertThat(meta.getToolInvocationId()).isEqualTo("command-id");
      assertThat(meta.getActionId()).isNotEmpty();
      assertThat(meta.getToolDetails().getToolName()).isEqualTo("bazel");
      assertThat(meta.getToolDetails().getToolVersion())
          .isEqualTo(BlazeVersionInfo.instance().getVersion());
      return next.startCall(call, headers);
    }
  }

  @Test
  public void testGetCapabilitiesWithRetries() throws Exception {
    ServerCapabilities caps =
        ServerCapabilities.newBuilder()
            .setExecutionCapabilities(
                ExecutionCapabilities.newBuilder().setExecEnabled(true).build())
            .build();
    serviceRegistry.addService(
        ServerInterceptors.intercept(
            new CapabilitiesImplBase() {
              private int numErrors = 0;
              private static final int MAX_ERRORS = 3;

              @Override
              public void getCapabilities(
                  GetCapabilitiesRequest request,
                  StreamObserver<ServerCapabilities> responseObserver) {
                if (numErrors < MAX_ERRORS) {
                  numErrors++;
                  responseObserver.onError(
                      Status.UNAVAILABLE.asRuntimeException()); // Retriable error.
                } else {
                  responseObserver.onNext(caps);
                  responseObserver.onCompleted();
                }
              }
            },
            new RequestHeadersValidator()));

    RemoteOptions remoteOptions = Options.getDefaults(RemoteOptions.class);
    RemoteRetrier retrier =
        TestUtils.newRemoteRetrier(
            () -> new ExponentialBackoff(remoteOptions),
            RemoteRetrier.RETRIABLE_GRPC_ERRORS,
            retryService);
    ReferenceCountedChannel channel =
        new ReferenceCountedChannel(
            InProcessChannelBuilder.forName(fakeServerName).directExecutor().build());
    CallCredentials creds =
        GoogleAuthUtils.newCallCredentials(Options.getDefaults(AuthAndTLSOptions.class));
    RemoteServerCapabilities client =
        new RemoteServerCapabilities("instance", channel.retain(), creds, 3, retrier);

    assertThat(client.get("build-req-id", "command-id")).isEqualTo(caps);
  }

  @Test
  public void testCheckClientServerCompatibility_NoChecks() throws Exception {
    RemoteServerCapabilities.ClientServerCompatibilityStatus st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            ServerCapabilities.getDefaultInstance(),
            Options.getDefaults(RemoteOptions.class),
            DigestFunction.Value.SHA256);
    assertThat(st.isOk()).isTrue();
  }

  @Test
  public void testCheckClientServerCompatibility_ApiVersionDeprecated() throws Exception {
    ServerCapabilities caps =
        ServerCapabilities.newBuilder()
            .setDeprecatedApiVersion(ApiVersion.current.toSemVer())
            .setLowApiVersion(new ApiVersion(100, 0, 0, "").toSemVer())
            .setHighApiVersion(new ApiVersion(100, 0, 0, "").toSemVer())
            .setCacheCapabilities(
                CacheCapabilities.newBuilder()
                    .addDigestFunction(DigestFunction.Value.SHA256)
                    .setActionCacheUpdateCapabilities(
                        ActionCacheUpdateCapabilities.newBuilder().setUpdateEnabled(true).build())
                    .build())
            .build();
    RemoteOptions remoteOptions = Options.getDefaults(RemoteOptions.class);
    remoteOptions.remoteCache = "server:port";
    RemoteServerCapabilities.ClientServerCompatibilityStatus st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.getErrors()).isEmpty();
    assertThat(st.getWarnings()).hasSize(1);
    assertThat(st.getWarnings().get(0)).containsMatch("API.*deprecated.*100.0");
  }

  @Test
  public void testCheckClientServerCompatibility_ApiVersionUnsupported() throws Exception {
    ServerCapabilities caps =
        ServerCapabilities.newBuilder()
            .setLowApiVersion(new ApiVersion(100, 0, 0, "").toSemVer())
            .setHighApiVersion(new ApiVersion(100, 0, 0, "").toSemVer())
            .setCacheCapabilities(
                CacheCapabilities.newBuilder()
                    .addDigestFunction(DigestFunction.Value.SHA256)
                    .setActionCacheUpdateCapabilities(
                        ActionCacheUpdateCapabilities.newBuilder().setUpdateEnabled(true).build())
                    .build())
            .build();
    RemoteOptions remoteOptions = Options.getDefaults(RemoteOptions.class);
    remoteOptions.remoteCache = "server:port";
    RemoteServerCapabilities.ClientServerCompatibilityStatus st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.getErrors()).hasSize(1);
    assertThat(st.getErrors().get(0)).containsMatch("API.*not supported.*100.0");
  }

  @Test
  public void testCheckClientServerCompatibility_RemoteCacheDoesNotSupportDigestFunction()
      throws Exception {
    ServerCapabilities caps =
        ServerCapabilities.newBuilder()
            .setLowApiVersion(ApiVersion.current.toSemVer())
            .setHighApiVersion(ApiVersion.current.toSemVer())
            .setCacheCapabilities(
                CacheCapabilities.newBuilder()
                    .addDigestFunction(DigestFunction.Value.MD5)
                    .setActionCacheUpdateCapabilities(
                        ActionCacheUpdateCapabilities.newBuilder().setUpdateEnabled(true).build())
                    .build())
            .build();
    RemoteOptions remoteOptions = Options.getDefaults(RemoteOptions.class);
    remoteOptions.remoteCache = "server:port";
    RemoteServerCapabilities.ClientServerCompatibilityStatus st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.getErrors()).hasSize(1);
    assertThat(st.getErrors().get(0)).containsMatch("Cannot use hash function");
  }

  @Test
  public void testCheckClientServerCompatibility_RemoteCacheDoesNotSupportUpdate()
      throws Exception {
    ServerCapabilities caps =
        ServerCapabilities.newBuilder()
            .setLowApiVersion(ApiVersion.current.toSemVer())
            .setHighApiVersion(ApiVersion.current.toSemVer())
            .setCacheCapabilities(
                CacheCapabilities.newBuilder()
                    .addDigestFunction(DigestFunction.Value.SHA256)
                    .build())
            .build();
    RemoteOptions remoteOptions = Options.getDefaults(RemoteOptions.class);
    remoteOptions.remoteCache = "server:port";
    RemoteServerCapabilities.ClientServerCompatibilityStatus st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.getErrors()).hasSize(1);
    assertThat(st.getErrors().get(0))
        .containsMatch("not authorized to write local results to the remote cache");

    // Ignored when no local upload.
    remoteOptions.remoteUploadLocalResults = false;
    st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.isOk()).isTrue();
  }

  @Test
  public void testCheckClientServerCompatibility_RemoteExecutionIsDisabled() throws Exception {
    ServerCapabilities caps =
        ServerCapabilities.newBuilder()
            .setLowApiVersion(ApiVersion.current.toSemVer())
            .setHighApiVersion(ApiVersion.current.toSemVer())
            .setCacheCapabilities(
                CacheCapabilities.newBuilder()
                    .addDigestFunction(DigestFunction.Value.SHA256)
                    .setActionCacheUpdateCapabilities(
                        ActionCacheUpdateCapabilities.newBuilder().setUpdateEnabled(true).build())
                    .build())
            .setExecutionCapabilities(
                ExecutionCapabilities.newBuilder()
                    .setDigestFunction(DigestFunction.Value.SHA256)
                    .build())
            .build();
    RemoteOptions remoteOptions = Options.getDefaults(RemoteOptions.class);
    remoteOptions.remoteExecutor = "server:port";
    RemoteServerCapabilities.ClientServerCompatibilityStatus st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.getErrors()).hasSize(1);
    assertThat(st.getErrors().get(0)).containsMatch("Remote execution is not supported");
    assertThat(st.getErrors().get(0)).containsMatch("not authorized to use remote execution");
  }

  @Test
  public void testCheckClientServerCompatibility_RemoteExecutionDoesNotSupportDigestFunction()
      throws Exception {
    ServerCapabilities caps =
        ServerCapabilities.newBuilder()
            .setLowApiVersion(ApiVersion.current.toSemVer())
            .setHighApiVersion(ApiVersion.current.toSemVer())
            .setCacheCapabilities(
                CacheCapabilities.newBuilder()
                    .addDigestFunction(DigestFunction.Value.SHA256)
                    .setActionCacheUpdateCapabilities(
                        ActionCacheUpdateCapabilities.newBuilder().setUpdateEnabled(true).build())
                    .build())
            .setExecutionCapabilities(
                ExecutionCapabilities.newBuilder()
                    .setDigestFunction(DigestFunction.Value.MD5)
                    .setExecEnabled(true)
                    .build())
            .build();
    RemoteOptions remoteOptions = Options.getDefaults(RemoteOptions.class);
    remoteOptions.remoteExecutor = "server:port";
    RemoteServerCapabilities.ClientServerCompatibilityStatus st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.getErrors()).hasSize(1);
    assertThat(st.getErrors().get(0)).containsMatch("Cannot use hash function");
  }

  @Test
  public void testCheckClientServerCompatibility_LocalFallbackNoRemoteCacheUpdate()
      throws Exception {
    ServerCapabilities caps =
        ServerCapabilities.newBuilder()
            .setLowApiVersion(ApiVersion.current.toSemVer())
            .setHighApiVersion(ApiVersion.current.toSemVer())
            .setCacheCapabilities(
                CacheCapabilities.newBuilder()
                    .addDigestFunction(DigestFunction.Value.SHA256)
                    .build())
            .setExecutionCapabilities(
                ExecutionCapabilities.newBuilder()
                    .setDigestFunction(DigestFunction.Value.SHA256)
                    .setExecEnabled(true)
                    .build())
            .build();
    RemoteOptions remoteOptions = Options.getDefaults(RemoteOptions.class);
    remoteOptions.remoteExecutor = "server:port";
    remoteOptions.remoteLocalFallback = true;
    RemoteServerCapabilities.ClientServerCompatibilityStatus st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.getErrors()).hasSize(1);
    assertThat(st.getErrors().get(0))
        .containsMatch("not authorized to write local results to the remote cache");

    // Ignored when no fallback.
    remoteOptions.remoteLocalFallback = false;
    st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.isOk()).isTrue();

    // Ignored when no uploading local results.
    remoteOptions.remoteLocalFallback = true;
    remoteOptions.remoteUploadLocalResults = false;
    st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.isOk()).isTrue();
  }

  @Test
  public void testCheckClientServerCompatibility_CachePriority() throws Exception {
    ServerCapabilities caps =
        ServerCapabilities.newBuilder()
            .setLowApiVersion(ApiVersion.current.toSemVer())
            .setHighApiVersion(ApiVersion.current.toSemVer())
            .setCacheCapabilities(
                CacheCapabilities.newBuilder()
                    .addDigestFunction(DigestFunction.Value.SHA256)
                    .setCachePriorityCapabilities(
                        PriorityCapabilities.newBuilder()
                            .addPriorities(
                                PriorityRange.newBuilder().setMinPriority(1).setMaxPriority(2))
                            .addPriorities(
                                PriorityRange.newBuilder().setMinPriority(5).setMaxPriority(10)))
                    .build())
            .build();
    RemoteOptions remoteOptions = Options.getDefaults(RemoteOptions.class);
    remoteOptions.remoteCache = "server:port";
    remoteOptions.remoteUploadLocalResults = false;
    remoteOptions.remoteResultCachePriority = 11;
    RemoteServerCapabilities.ClientServerCompatibilityStatus st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.getErrors()).hasSize(1);
    assertThat(st.getErrors().get(0)).containsMatch("remote_result_cache_priority");

    // Valid value in range.
    remoteOptions.remoteResultCachePriority = 10;
    st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.isOk()).isTrue();

    // Check not performed if the value is 0.
    remoteOptions.remoteResultCachePriority = 0;
    st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.isOk()).isTrue();
  }

  @Test
  public void testCheckClientServerCompatibility_ExecutionPriority() throws Exception {
    ServerCapabilities caps =
        ServerCapabilities.newBuilder()
            .setLowApiVersion(ApiVersion.current.toSemVer())
            .setHighApiVersion(ApiVersion.current.toSemVer())
            .setCacheCapabilities(
                CacheCapabilities.newBuilder()
                    .addDigestFunction(DigestFunction.Value.SHA256)
                    .build())
            .setExecutionCapabilities(
                ExecutionCapabilities.newBuilder()
                    .setDigestFunction(DigestFunction.Value.SHA256)
                    .setExecEnabled(true)
                    .setExecutionPriorityCapabilities(
                        PriorityCapabilities.newBuilder()
                            .addPriorities(
                                PriorityRange.newBuilder().setMinPriority(1).setMaxPriority(2))
                            .addPriorities(
                                PriorityRange.newBuilder().setMinPriority(5).setMaxPriority(10)))
                    .build())
            .build();
    RemoteOptions remoteOptions = Options.getDefaults(RemoteOptions.class);
    remoteOptions.remoteExecutor = "server:port";
    remoteOptions.remoteUploadLocalResults = false;
    remoteOptions.remoteExecutionPriority = 11;
    RemoteServerCapabilities.ClientServerCompatibilityStatus st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.getErrors()).hasSize(1);
    assertThat(st.getErrors().get(0)).containsMatch("remote_execution_priority");

    // Valid value in range.
    remoteOptions.remoteExecutionPriority = 10;
    st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.isOk()).isTrue();

    // Check not performed if the value is 0.
    remoteOptions.remoteExecutionPriority = 0;
    st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.isOk()).isTrue();

    // Ignored when no remote execution requested.
    remoteOptions.remoteExecutionPriority = 11;
    remoteOptions.remoteExecutor = "";
    remoteOptions.remoteCache = "server:port";
    st =
        RemoteServerCapabilities.checkClientServerCompatibility(
            caps, remoteOptions, DigestFunction.Value.SHA256);
    assertThat(st.isOk()).isTrue();
  }
}
