Reorganize the //src/test/java/com/google/devtools/build/lib/remote package.

PiperOrigin-RevId: 568156390
Change-Id: If390f8535e3c574debac68ce96c3e451f1599d98
diff --git a/.bazelci/postsubmit.yml b/.bazelci/postsubmit.yml
index 6b13128..f961fc7 100644
--- a/.bazelci/postsubmit.yml
+++ b/.bazelci/postsubmit.yml
@@ -328,7 +328,7 @@
       - "-//src/test/java/com/google/devtools/build/lib/query2/engine/..."
       - "-//src/test/java/com/google/devtools/build/lib/versioning/..."
       - "-//src/test/java/com/google/devtools/build/lib/worker/..."
-      - "-//src/test/java/com/google/devtools/build/lib/remote:remote"
+      - "-//src/test/java/com/google/devtools/build/lib/remote:RemoteTests"
       - "-//src/test/shell/bazel/remote/..."
       - "-//tools/python:pywrapper_test"
     include_json_profile:
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index af9981d..5cbd96f 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -389,7 +389,7 @@
       - "-//src/test/java/com/google/devtools/build/lib/query2/engine/..."
       - "-//src/test/java/com/google/devtools/build/lib/versioning/..."
       - "-//src/test/java/com/google/devtools/build/lib/worker/..."
-      - "-//src/test/java/com/google/devtools/build/lib/remote:remote"
+      - "-//src/test/java/com/google/devtools/build/lib/remote:RemoteTests"
       - "-//src/test/shell/bazel/remote/..."
       - "-//tools/python:pywrapper_test"
     include_json_profile:
diff --git a/src/test/java/com/google/devtools/build/lib/remote/BUILD b/src/test/java/com/google/devtools/build/lib/remote/BUILD
index e49e166..2496f99 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/remote/BUILD
@@ -1,6 +1,7 @@
-load("@rules_java//java:defs.bzl", "java_test")
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = 1,
     default_visibility = ["//src:__subpackages__"],
 )
@@ -19,32 +20,49 @@
         "//src/test/java/com/google/devtools/build/lib/remote/util:srcs",
         "//src/test/java/com/google/devtools/build/lib/remote/zstd:srcs",
     ],
-    visibility = ["//src/test/java/com/google/devtools/build/lib:__pkg__"],
+    visibility = ["//src:__subpackages__"],
 )
 
-# Do not run NativeSslTest on platforms where native SSL is not available.
+java_library(
+    name = "action_input_prefetcher_test_base",
+    srcs = ["ActionInputPrefetcherTestBase.java"],
+    deps = [
+        "//src/main/java/com/google/devtools/build/lib/actions",
+        "//src/main/java/com/google/devtools/build/lib/actions:artifacts",
+        "//src/main/java/com/google/devtools/build/lib/actions:file_metadata",
+        "//src/main/java/com/google/devtools/build/lib/remote:abstract_action_input_prefetcher",
+        "//src/main/java/com/google/devtools/build/lib/remote/util",
+        "//src/main/java/com/google/devtools/build/lib/skyframe:tree_artifact_value",
+        "//src/main/java/com/google/devtools/build/lib/testing/vfs:spied_filesystem",
+        "//src/main/java/com/google/devtools/build/lib/util",
+        "//src/main/java/com/google/devtools/build/lib/vfs",
+        "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
+        "//src/test/java/com/google/devtools/build/lib/actions/util",
+        "//third_party:guava",
+        "//third_party:jsr305",
+        "//third_party:junit4",
+        "//third_party:mockito",
+        "//third_party:truth",
+    ],
+)
 
-NATIVE_SSL_TEST = ["NativeSslTest.java"]
-
-NATIVE_SSL_TEST_MAYBE = select({
-    "//src/conditions:windows": NATIVE_SSL_TEST,
-    "//src/conditions:darwin": NATIVE_SSL_TEST,
-    "//src/conditions:linux": NATIVE_SSL_TEST,
-    "//conditions:default": [],
-})
-
-java_test(
-    name = "remote",
+java_library(
+    name = "RemoteTests_lib",
     srcs = glob(
-        ["**/*.java"],
-        exclude = NATIVE_SSL_TEST + [
+        [
+            "*.java",
+        ],
+        exclude = [
+            "ActionInputPrefetcherTestBase.java",
+            "RemoteActionFileSystemTestBase.java",
             "BuildWithoutTheBytesIntegrationTest.java",
             "BuildWithoutTheBytesIntegrationTestBase.java",
             "DiskCacheIntegrationTest.java",
         ],
-    ) + NATIVE_SSL_TEST_MAYBE,
-    test_class = "com.google.devtools.build.lib.AllTests",
+    ),
     deps = [
+        ":action_input_prefetcher_test_base",
+        ":remote_action_file_system_test_base",
         "//src/main/java/com/google/devtools/build/lib:runtime",
         "//src/main/java/com/google/devtools/build/lib:runtime/command_line_path_factory",
         "//src/main/java/com/google/devtools/build/lib/actions",
@@ -81,17 +99,15 @@
         "//src/main/java/com/google/devtools/build/lib/remote/common:bulk_transfer_exception",
         "//src/main/java/com/google/devtools/build/lib/remote/common:cache_not_found_exception",
         "//src/main/java/com/google/devtools/build/lib/remote/disk",
-        "//src/main/java/com/google/devtools/build/lib/remote/grpc",
         "//src/main/java/com/google/devtools/build/lib/remote/http",
         "//src/main/java/com/google/devtools/build/lib/remote/merkletree",
         "//src/main/java/com/google/devtools/build/lib/remote/options",
         "//src/main/java/com/google/devtools/build/lib/remote/util",
         "//src/main/java/com/google/devtools/build/lib/runtime/commands",
         "//src/main/java/com/google/devtools/build/lib/skyframe:tree_artifact_value",
-        "//src/main/java/com/google/devtools/build/lib/testing/vfs:spied_filesystem",
-        "//src/main/java/com/google/devtools/build/lib/util",
         "//src/main/java/com/google/devtools/build/lib/util:abrupt_exit_exception",
         "//src/main/java/com/google/devtools/build/lib/util:exit_code",
+        "//src/main/java/com/google/devtools/build/lib/util:os",
         "//src/main/java/com/google/devtools/build/lib/util/io",
         "//src/main/java/com/google/devtools/build/lib/vfs",
         "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
@@ -99,19 +115,18 @@
         "//src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs",
         "//src/main/java/com/google/devtools/common/options",
         "//src/main/protobuf:failure_details_java_proto",
-        "//src/main/protobuf:remote_execution_log_java_proto",
         "//src/main/protobuf:spawn_java_proto",
-        "//src/test/java/com/google/devtools/build/lib:test_runner",
         "//src/test/java/com/google/devtools/build/lib/actions/util",
-        "//src/test/java/com/google/devtools/build/lib/analysis/util",
         "//src/test/java/com/google/devtools/build/lib/exec/util",
         "//src/test/java/com/google/devtools/build/lib/remote/util",
         "//src/test/java/com/google/devtools/build/lib/testutil",
         "//src/test/java/com/google/devtools/build/lib/testutil:TestUtils",
-        "//third_party:api_client",
         "//third_party:auth",
         "//third_party:caffeine",
+        "//third_party:error_prone_annotations",
+        "//third_party:gson",
         "//third_party:guava",
+        "//third_party:jsr305",
         "//third_party:junit4",
         "//third_party:mockito",
         "//third_party:netty",
@@ -130,7 +145,32 @@
         "@remoteapis//:build_bazel_remote_execution_v2_remote_execution_java_grpc",
         "@remoteapis//:build_bazel_remote_execution_v2_remote_execution_java_proto",
         "@remoteapis//:build_bazel_semver_semver_java_proto",
-        "@zstd-jni//:zstd-jni",
+        "@zstd-jni",
+    ],
+)
+
+java_library(
+    name = "remote_action_file_system_test_base",
+    srcs = ["RemoteActionFileSystemTestBase.java"],
+    deps = [
+        "//src/main/java/com/google/devtools/build/lib/actions",
+        "//src/main/java/com/google/devtools/build/lib/actions:artifacts",
+        "//src/main/java/com/google/devtools/build/lib/actions:file_metadata",
+        "//src/main/java/com/google/devtools/build/lib/remote/util",
+        "//src/main/java/com/google/devtools/build/lib/vfs",
+        "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
+        "//third_party:guava",
+        "//third_party:junit4",
+        "//third_party:truth",
+    ],
+)
+
+java_test(
+    name = "RemoteTests",
+    test_class = "com.google.devtools.build.lib.AllTests",
+    runtime_deps = [
+        ":RemoteTests_lib",
+        "//src/test/java/com/google/devtools/build/lib:test_runner",
     ],
 )
 
diff --git a/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTest.java b/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTest.java
index d0377e2..1f089b4 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTest.java
@@ -16,6 +16,7 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.devtools.build.lib.remote.util.Utils.getFromFuture;
 import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.fail;
 import static org.mockito.AdditionalAnswers.answerVoid;
@@ -36,8 +37,11 @@
 import build.bazel.remote.execution.v2.FindMissingBlobsRequest;
 import build.bazel.remote.execution.v2.FindMissingBlobsResponse;
 import build.bazel.remote.execution.v2.GetActionResultRequest;
+import build.bazel.remote.execution.v2.RequestMetadata;
+import build.bazel.remote.execution.v2.ServerCapabilities;
 import build.bazel.remote.execution.v2.Tree;
 import build.bazel.remote.execution.v2.UpdateActionResultRequest;
+import com.github.luben.zstd.Zstd;
 import com.google.bytestream.ByteStreamGrpc.ByteStreamImplBase;
 import com.google.bytestream.ByteStreamProto.QueryWriteStatusRequest;
 import com.google.bytestream.ByteStreamProto.QueryWriteStatusResponse;
@@ -50,36 +54,74 @@
 import com.google.common.collect.ImmutableSortedMap;
 import com.google.common.collect.Maps;
 import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningScheduledExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
 import com.google.devtools.build.lib.actions.ActionInputHelper;
 import com.google.devtools.build.lib.actions.ArtifactPathResolver;
 import com.google.devtools.build.lib.actions.cache.VirtualActionInput;
 import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions;
+import com.google.devtools.build.lib.authandtls.CallCredentialsProvider;
+import com.google.devtools.build.lib.authandtls.GoogleAuthUtils;
+import com.google.devtools.build.lib.clock.JavaClock;
 import com.google.devtools.build.lib.events.NullEventHandler;
+import com.google.devtools.build.lib.remote.RemoteRetrier.ExponentialBackoff;
 import com.google.devtools.build.lib.remote.Retrier.Backoff;
+import com.google.devtools.build.lib.remote.common.RemoteActionExecutionContext;
 import com.google.devtools.build.lib.remote.common.RemoteCacheClient.ActionKey;
+import com.google.devtools.build.lib.remote.common.RemotePathResolver;
 import com.google.devtools.build.lib.remote.merkletree.MerkleTree;
 import com.google.devtools.build.lib.remote.options.RemoteOptions;
+import com.google.devtools.build.lib.remote.util.DigestUtil;
+import com.google.devtools.build.lib.remote.util.TestUtils;
+import com.google.devtools.build.lib.remote.util.TracingMetadataUtils;
+import com.google.devtools.build.lib.testutil.Scratch;
+import com.google.devtools.build.lib.util.io.FileOutErr;
+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.PathFragment;
+import com.google.devtools.build.lib.vfs.SyscallCache;
+import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
 import com.google.devtools.common.options.Options;
+import com.google.gson.JsonObject;
 import com.google.protobuf.ByteString;
 import io.grpc.BindableService;
+import io.grpc.CallCredentials;
+import io.grpc.CallOptions;
+import io.grpc.Channel;
+import io.grpc.ClientCall;
+import io.grpc.ClientInterceptor;
+import io.grpc.ManagedChannel;
 import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+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.ServerCallStreamObserver;
 import io.grpc.stub.StreamObserver;
+import io.grpc.util.MutableHandlerRegistry;
+import io.reactivex.rxjava3.core.Single;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Supplier;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -90,11 +132,146 @@
 
 /** Tests for {@link GrpcCacheClient}. */
 @RunWith(JUnit4.class)
-public class GrpcCacheClientTest extends GrpcCacheClientTestBase {
+public class GrpcCacheClientTest {
+  private static final DigestUtil DIGEST_UTIL =
+      new DigestUtil(SyscallCache.NO_CACHE, DigestHashFunction.SHA256);
+
+  private FileSystem fs;
+  private Path execRoot;
+  private FileOutErr outErr;
+  private FakeActionInputFileCache fakeFileCache;
+  private final MutableHandlerRegistry serviceRegistry = new MutableHandlerRegistry();
+  private final String fakeServerName = "fake server for " + getClass();
+  private Server fakeServer;
+  private RemoteActionExecutionContext context;
+  private RemotePathResolver remotePathResolver;
+  private ListeningScheduledExecutorService retryService;
+  private final ArrayList<ReferenceCountedChannel> channels = new ArrayList<>();
+
   private GrpcCacheClient newClient() throws IOException {
     return newClient(Options.getDefaults(RemoteOptions.class));
   }
 
+  private GrpcCacheClient newClient(RemoteOptions remoteOptions) throws IOException {
+    return newClient(remoteOptions, () -> new ExponentialBackoff(remoteOptions));
+  }
+
+  private GrpcCacheClient newClient(RemoteOptions remoteOptions, Supplier<Backoff> backoffSupplier)
+      throws IOException {
+    AuthAndTLSOptions authTlsOptions = Options.getDefaults(AuthAndTLSOptions.class);
+    authTlsOptions.useGoogleDefaultCredentials = true;
+    authTlsOptions.googleCredentials = "/execroot/main/creds.json";
+    authTlsOptions.googleAuthScopes = ImmutableList.of("dummy.scope");
+
+    JsonObject json = new JsonObject();
+    json.addProperty("type", "authorized_user");
+    json.addProperty("client_id", "some_client");
+    json.addProperty("client_secret", "foo");
+    json.addProperty("refresh_token", "bar");
+    Scratch scratch = new Scratch();
+    scratch.file(authTlsOptions.googleCredentials, json.toString());
+
+    CallCredentialsProvider callCredentialsProvider;
+    try (InputStream in = scratch.resolve(authTlsOptions.googleCredentials).getInputStream()) {
+      callCredentialsProvider =
+          GoogleAuthUtils.newCallCredentialsProvider(
+              GoogleAuthUtils.newGoogleCredentialsFromFile(in, authTlsOptions.googleAuthScopes));
+    }
+    CallCredentials creds = callCredentialsProvider.getCallCredentials();
+
+    RemoteRetrier retrier =
+        TestUtils.newRemoteRetrier(
+            backoffSupplier, RemoteRetrier.RETRIABLE_GRPC_ERRORS, retryService);
+    ReferenceCountedChannel channel =
+        new ReferenceCountedChannel(
+            new ChannelConnectionWithServerCapabilitiesFactory() {
+              @Override
+              public Single<ChannelConnectionWithServerCapabilities> create() {
+                ManagedChannel ch =
+                    InProcessChannelBuilder.forName(fakeServerName)
+                        .directExecutor()
+                        .intercept(new CallCredentialsInterceptor(creds))
+                        .intercept(TracingMetadataUtils.newCacheHeadersInterceptor(remoteOptions))
+                        .build();
+                return Single.just(
+                    new ChannelConnectionWithServerCapabilities(
+                        ch, ServerCapabilities.getDefaultInstance()));
+              }
+
+              @Override
+              public int maxConcurrency() {
+                return 100;
+              }
+            });
+    channels.add(channel);
+    return new GrpcCacheClient(
+        channel, callCredentialsProvider, remoteOptions, retrier, DIGEST_UTIL);
+  }
+
+  private static byte[] downloadBlob(
+      RemoteActionExecutionContext context, GrpcCacheClient cacheClient, Digest digest)
+      throws IOException, InterruptedException {
+    try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+      getFromFuture(cacheClient.downloadBlob(context, digest, out));
+      return out.toByteArray();
+    }
+  }
+
+  private static class CallCredentialsInterceptor implements ClientInterceptor {
+    private final CallCredentials credentials;
+
+    public CallCredentialsInterceptor(CallCredentials credentials) {
+      this.credentials = credentials;
+    }
+
+    @Override
+    public <RequestT, ResponseT> ClientCall<RequestT, ResponseT> interceptCall(
+        MethodDescriptor<RequestT, ResponseT> method, CallOptions callOptions, Channel next) {
+      assertThat(callOptions.getCredentials()).isEqualTo(credentials);
+      // Remove the call credentials to allow testing with dummy ones.
+      return next.newCall(method, callOptions.withCallCredentials(null));
+    }
+  }
+
+  @Before
+  public final void setUp() throws Exception {
+    // Use a mutable service registry for later registering the service impl for each test case.
+    fakeServer =
+        InProcessServerBuilder.forName(fakeServerName)
+            .fallbackHandlerRegistry(serviceRegistry)
+            .directExecutor()
+            .build()
+            .start();
+    Chunker.setDefaultChunkSizeForTesting(1000); // Enough for everything to be one chunk.
+    fs = new InMemoryFileSystem(new JavaClock(), DigestHashFunction.SHA256);
+    execRoot = fs.getPath("/execroot/main");
+    execRoot.createDirectoryAndParents();
+    fakeFileCache = new FakeActionInputFileCache(execRoot);
+    remotePathResolver = RemotePathResolver.createDefault(execRoot);
+
+    Path stdout = fs.getPath("/tmp/stdout");
+    Path stderr = fs.getPath("/tmp/stderr");
+    stdout.getParentDirectory().createDirectoryAndParents();
+    stderr.getParentDirectory().createDirectoryAndParents();
+    outErr = new FileOutErr(stdout, stderr);
+    RequestMetadata metadata =
+        TracingMetadataUtils.buildMetadata(
+            "none", "none", Digest.getDefaultInstance().getHash(), null);
+    context = RemoteActionExecutionContext.create(metadata);
+    retryService = MoreExecutors.listeningDecorator(Executors.newScheduledThreadPool(1));
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    channels.forEach(ReferenceCountedChannel::release);
+    retryService.shutdownNow();
+    retryService.awaitTermination(
+        com.google.devtools.build.lib.testutil.TestUtils.WAIT_TIMEOUT_SECONDS, SECONDS);
+
+    fakeServer.shutdownNow();
+    fakeServer.awaitTermination();
+  }
+
   @Test
   public void testVirtualActionInputSupport() throws Exception {
     RemoteOptions options = Options.getDefaults(RemoteOptions.class);
@@ -1020,6 +1197,86 @@
   }
 
   @Test
+  public void compressedDownloadBlobIsRetriedWithProgress()
+      throws IOException, InterruptedException {
+    RemoteOptions options = Options.getDefaults(RemoteOptions.class);
+    options.cacheCompression = true;
+    final GrpcCacheClient client = newClient(options);
+    final Digest digest = DIGEST_UTIL.computeAsUtf8("abcdefg");
+    ByteString chunk1 = ByteString.copyFrom(Zstd.compress("abc".getBytes(UTF_8)));
+    ByteString chunk2 = ByteString.copyFrom(Zstd.compress("def".getBytes(UTF_8)));
+    ByteString chunk3 = ByteString.copyFrom(Zstd.compress("g".getBytes(UTF_8)));
+    serviceRegistry.addService(
+        new ByteStreamImplBase() {
+          private boolean first = true;
+
+          @Override
+          public void read(ReadRequest request, StreamObserver<ReadResponse> responseObserver) {
+            assertThat(request.getResourceName()).contains(digest.getHash());
+            if (first) {
+              first = false;
+              responseObserver.onError(Status.DEADLINE_EXCEEDED.asException());
+              return;
+            }
+            switch (Math.toIntExact(request.getReadOffset())) {
+              case 0:
+                responseObserver.onNext(ReadResponse.newBuilder().setData(chunk1).build());
+                break;
+              case 3:
+                responseObserver.onNext(ReadResponse.newBuilder().setData(chunk2).build());
+                break;
+              case 6:
+                responseObserver.onNext(ReadResponse.newBuilder().setData(chunk3).build());
+                responseObserver.onCompleted();
+                return;
+              default:
+                throw new IllegalStateException("unexpected offset " + request.getReadOffset());
+            }
+            responseObserver.onError(Status.DEADLINE_EXCEEDED.asException());
+          }
+        });
+    assertThat(new String(downloadBlob(context, client, digest), UTF_8)).isEqualTo("abcdefg");
+  }
+
+  @Test
+  public void testCompressedDownload() throws IOException, InterruptedException {
+    RemoteOptions options = Options.getDefaults(RemoteOptions.class);
+    options.cacheCompression = true;
+    final GrpcCacheClient client = newClient(options);
+    final byte[] data = "abcdefg".getBytes(UTF_8);
+    final Digest digest = DIGEST_UTIL.compute(data);
+    final byte[] compressed = Zstd.compress(data);
+
+    serviceRegistry.addService(
+        new ByteStreamImplBase() {
+          @Override
+          public void read(ReadRequest request, StreamObserver<ReadResponse> responseObserver) {
+            assertThat(request.getResourceName()).contains(digest.getHash());
+            responseObserver.onNext(
+                ReadResponse.newBuilder()
+                    .setData(ByteString.copyFrom(Arrays.copyOf(compressed, compressed.length / 3)))
+                    .build());
+            responseObserver.onNext(
+                ReadResponse.newBuilder()
+                    .setData(
+                        ByteString.copyFrom(
+                            Arrays.copyOfRange(
+                                compressed, compressed.length / 3, compressed.length / 3 * 2)))
+                    .build());
+            responseObserver.onNext(
+                ReadResponse.newBuilder()
+                    .setData(
+                        ByteString.copyFrom(
+                            Arrays.copyOfRange(
+                                compressed, compressed.length / 3 * 2, compressed.length)))
+                    .build());
+            responseObserver.onCompleted();
+          }
+        });
+    assertThat(downloadBlob(context, client, digest)).isEqualTo(data);
+  }
+
+  @Test
   public void isRemoteCacheOptionsWhenGrpcEnabled() {
     RemoteOptions options = Options.getDefaults(RemoteOptions.class);
     options.remoteCache = "grpc://some-host.com";
diff --git a/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTestBase.java b/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTestBase.java
deleted file mode 100644
index b674065..0000000
--- a/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTestBase.java
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2022 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 static com.google.devtools.build.lib.remote.util.Utils.getFromFuture;
-
-import build.bazel.remote.execution.v2.Digest;
-import build.bazel.remote.execution.v2.RequestMetadata;
-import build.bazel.remote.execution.v2.ServerCapabilities;
-import com.google.api.client.json.GenericJson;
-import com.google.api.client.json.gson.GsonFactory;
-import com.google.common.collect.ImmutableList;
-import com.google.common.util.concurrent.ListeningScheduledExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions;
-import com.google.devtools.build.lib.authandtls.CallCredentialsProvider;
-import com.google.devtools.build.lib.authandtls.GoogleAuthUtils;
-import com.google.devtools.build.lib.clock.JavaClock;
-import com.google.devtools.build.lib.remote.RemoteRetrier.ExponentialBackoff;
-import com.google.devtools.build.lib.remote.Retrier.Backoff;
-import com.google.devtools.build.lib.remote.common.RemoteActionExecutionContext;
-import com.google.devtools.build.lib.remote.common.RemotePathResolver;
-import com.google.devtools.build.lib.remote.options.RemoteOptions;
-import com.google.devtools.build.lib.remote.util.DigestUtil;
-import com.google.devtools.build.lib.remote.util.TestUtils;
-import com.google.devtools.build.lib.remote.util.TracingMetadataUtils;
-import com.google.devtools.build.lib.testutil.Scratch;
-import com.google.devtools.build.lib.util.io.FileOutErr;
-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.SyscallCache;
-import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
-import com.google.devtools.common.options.Options;
-import io.grpc.CallCredentials;
-import io.grpc.CallOptions;
-import io.grpc.Channel;
-import io.grpc.ClientCall;
-import io.grpc.ClientInterceptor;
-import io.grpc.ManagedChannel;
-import io.grpc.MethodDescriptor;
-import io.grpc.Server;
-import io.grpc.inprocess.InProcessChannelBuilder;
-import io.grpc.inprocess.InProcessServerBuilder;
-import io.grpc.util.MutableHandlerRegistry;
-import io.reactivex.rxjava3.core.Single;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Supplier;
-import org.junit.After;
-import org.junit.Before;
-
-class GrpcCacheClientTestBase {
-  protected static final DigestUtil DIGEST_UTIL =
-      new DigestUtil(SyscallCache.NO_CACHE, DigestHashFunction.SHA256);
-
-  protected FileSystem fs;
-  protected Path execRoot;
-  protected FileOutErr outErr;
-  protected FakeActionInputFileCache fakeFileCache;
-  protected final MutableHandlerRegistry serviceRegistry = new MutableHandlerRegistry();
-  protected final String fakeServerName = "fake server for " + getClass();
-  protected Server fakeServer;
-  protected RemoteActionExecutionContext context;
-  protected RemotePathResolver remotePathResolver;
-  protected ListeningScheduledExecutorService retryService;
-  private final ArrayList<ReferenceCountedChannel> channels = new ArrayList<>();
-
-  @Before
-  public final void setUp() throws Exception {
-    // Use a mutable service registry for later registering the service impl for each test case.
-    fakeServer =
-        InProcessServerBuilder.forName(fakeServerName)
-            .fallbackHandlerRegistry(serviceRegistry)
-            .directExecutor()
-            .build()
-            .start();
-    Chunker.setDefaultChunkSizeForTesting(1000); // Enough for everything to be one chunk.
-    fs = new InMemoryFileSystem(new JavaClock(), DigestHashFunction.SHA256);
-    execRoot = fs.getPath("/execroot/main");
-    execRoot.createDirectoryAndParents();
-    fakeFileCache = new FakeActionInputFileCache(execRoot);
-    remotePathResolver = RemotePathResolver.createDefault(execRoot);
-
-    Path stdout = fs.getPath("/tmp/stdout");
-    Path stderr = fs.getPath("/tmp/stderr");
-    stdout.getParentDirectory().createDirectoryAndParents();
-    stderr.getParentDirectory().createDirectoryAndParents();
-    outErr = new FileOutErr(stdout, stderr);
-    RequestMetadata metadata =
-        TracingMetadataUtils.buildMetadata(
-            "none", "none", Digest.getDefaultInstance().getHash(), null);
-    context = RemoteActionExecutionContext.create(metadata);
-    retryService = MoreExecutors.listeningDecorator(Executors.newScheduledThreadPool(1));
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    channels.forEach(ReferenceCountedChannel::release);
-    retryService.shutdownNow();
-    retryService.awaitTermination(
-        com.google.devtools.build.lib.testutil.TestUtils.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
-
-    fakeServer.shutdownNow();
-    fakeServer.awaitTermination();
-  }
-
-  protected GrpcCacheClient newClient(RemoteOptions remoteOptions) throws IOException {
-    return newClient(remoteOptions, () -> new ExponentialBackoff(remoteOptions));
-  }
-
-  protected GrpcCacheClient newClient(
-      RemoteOptions remoteOptions, Supplier<Backoff> backoffSupplier) throws IOException {
-    AuthAndTLSOptions authTlsOptions = Options.getDefaults(AuthAndTLSOptions.class);
-    authTlsOptions.useGoogleDefaultCredentials = true;
-    authTlsOptions.googleCredentials = "/execroot/main/creds.json";
-    authTlsOptions.googleAuthScopes = ImmutableList.of("dummy.scope");
-
-    GenericJson json = new GenericJson();
-    json.put("type", "authorized_user");
-    json.put("client_id", "some_client");
-    json.put("client_secret", "foo");
-    json.put("refresh_token", "bar");
-    Scratch scratch = new Scratch();
-    scratch.file(authTlsOptions.googleCredentials, new GsonFactory().toString(json));
-
-    CallCredentialsProvider callCredentialsProvider;
-    try (InputStream in = scratch.resolve(authTlsOptions.googleCredentials).getInputStream()) {
-      callCredentialsProvider =
-          GoogleAuthUtils.newCallCredentialsProvider(
-              GoogleAuthUtils.newGoogleCredentialsFromFile(in, authTlsOptions.googleAuthScopes));
-    }
-    CallCredentials creds = callCredentialsProvider.getCallCredentials();
-
-    RemoteRetrier retrier =
-        TestUtils.newRemoteRetrier(
-            backoffSupplier, RemoteRetrier.RETRIABLE_GRPC_ERRORS, retryService);
-    ReferenceCountedChannel channel =
-        new ReferenceCountedChannel(
-            new ChannelConnectionWithServerCapabilitiesFactory() {
-              @Override
-              public Single<ChannelConnectionWithServerCapabilities> create() {
-                ManagedChannel ch =
-                    InProcessChannelBuilder.forName(fakeServerName)
-                        .directExecutor()
-                        .intercept(new CallCredentialsInterceptor(creds))
-                        .intercept(TracingMetadataUtils.newCacheHeadersInterceptor(remoteOptions))
-                        .build();
-                return Single.just(
-                    new ChannelConnectionWithServerCapabilities(
-                        ch, ServerCapabilities.getDefaultInstance()));
-              }
-
-              @Override
-              public int maxConcurrency() {
-                return 100;
-              }
-            });
-    channels.add(channel);
-    return new GrpcCacheClient(
-        channel, callCredentialsProvider, remoteOptions, retrier, DIGEST_UTIL);
-  }
-
-  protected static byte[] downloadBlob(
-      RemoteActionExecutionContext context, GrpcCacheClient cacheClient, Digest digest)
-      throws IOException, InterruptedException {
-    try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
-      getFromFuture(cacheClient.downloadBlob(context, digest, out));
-      return out.toByteArray();
-    }
-  }
-
-  private static class CallCredentialsInterceptor implements ClientInterceptor {
-    private final CallCredentials credentials;
-
-    public CallCredentialsInterceptor(CallCredentials credentials) {
-      this.credentials = credentials;
-    }
-
-    @Override
-    public <RequestT, ResponseT> ClientCall<RequestT, ResponseT> interceptCall(
-        MethodDescriptor<RequestT, ResponseT> method, CallOptions callOptions, Channel next) {
-      assertThat(callOptions.getCredentials()).isEqualTo(credentials);
-      // Remove the call credentials to allow testing with dummy ones.
-      return next.newCall(method, callOptions.withCallCredentials(null));
-    }
-  }
-}
diff --git a/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTestExtra.java b/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTestExtra.java
deleted file mode 100644
index b840907..0000000
--- a/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTestExtra.java
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2021 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 static java.nio.charset.StandardCharsets.UTF_8;
-
-import build.bazel.remote.execution.v2.Digest;
-import com.github.luben.zstd.Zstd;
-import com.google.bytestream.ByteStreamGrpc.ByteStreamImplBase;
-import com.google.bytestream.ByteStreamProto.ReadRequest;
-import com.google.bytestream.ByteStreamProto.ReadResponse;
-import com.google.devtools.build.lib.remote.options.RemoteOptions;
-import com.google.devtools.common.options.Options;
-import com.google.protobuf.ByteString;
-import io.grpc.Status;
-import io.grpc.stub.StreamObserver;
-import java.io.IOException;
-import java.util.Arrays;
-import org.junit.Test;
-
-/** Extra tests for {@link GrpcCacheClient} that are not tested internally. */
-public class GrpcCacheClientTestExtra extends GrpcCacheClientTestBase {
-
-  @Test
-  public void compressedDownloadBlobIsRetriedWithProgress()
-      throws IOException, InterruptedException {
-    RemoteOptions options = Options.getDefaults(RemoteOptions.class);
-    options.cacheCompression = true;
-    final GrpcCacheClient client = newClient(options);
-    final Digest digest = DIGEST_UTIL.computeAsUtf8("abcdefg");
-    ByteString chunk1 = ByteString.copyFrom(Zstd.compress("abc".getBytes(UTF_8)));
-    ByteString chunk2 = ByteString.copyFrom(Zstd.compress("def".getBytes(UTF_8)));
-    ByteString chunk3 = ByteString.copyFrom(Zstd.compress("g".getBytes(UTF_8)));
-    serviceRegistry.addService(
-        new ByteStreamImplBase() {
-          private boolean first = true;
-
-          @Override
-          public void read(ReadRequest request, StreamObserver<ReadResponse> responseObserver) {
-            assertThat(request.getResourceName().contains(digest.getHash())).isTrue();
-            if (first) {
-              first = false;
-              responseObserver.onError(Status.DEADLINE_EXCEEDED.asException());
-              return;
-            }
-            switch (Math.toIntExact(request.getReadOffset())) {
-              case 0:
-                responseObserver.onNext(ReadResponse.newBuilder().setData(chunk1).build());
-                break;
-              case 3:
-                responseObserver.onNext(ReadResponse.newBuilder().setData(chunk2).build());
-                break;
-              case 6:
-                responseObserver.onNext(ReadResponse.newBuilder().setData(chunk3).build());
-                responseObserver.onCompleted();
-                return;
-              default:
-                throw new IllegalStateException("unexpected offset " + request.getReadOffset());
-            }
-            responseObserver.onError(Status.DEADLINE_EXCEEDED.asException());
-          }
-        });
-    assertThat(new String(downloadBlob(context, client, digest), UTF_8)).isEqualTo("abcdefg");
-  }
-
-  @Test
-  public void testCompressedDownload() throws IOException, InterruptedException {
-    RemoteOptions options = Options.getDefaults(RemoteOptions.class);
-    options.cacheCompression = true;
-    final GrpcCacheClient client = newClient(options);
-    final byte[] data = "abcdefg".getBytes(UTF_8);
-    final Digest digest = DIGEST_UTIL.compute(data);
-    final byte[] compressed = Zstd.compress(data);
-
-    serviceRegistry.addService(
-        new ByteStreamImplBase() {
-          @Override
-          public void read(ReadRequest request, StreamObserver<ReadResponse> responseObserver) {
-            assertThat(request.getResourceName().contains(digest.getHash())).isTrue();
-            responseObserver.onNext(
-                ReadResponse.newBuilder()
-                    .setData(
-                        ByteString.copyFrom(
-                            Arrays.copyOfRange(compressed, 0, compressed.length / 3)))
-                    .build());
-            responseObserver.onNext(
-                ReadResponse.newBuilder()
-                    .setData(
-                        ByteString.copyFrom(
-                            Arrays.copyOfRange(
-                                compressed, compressed.length / 3, compressed.length / 3 * 2)))
-                    .build());
-            responseObserver.onNext(
-                ReadResponse.newBuilder()
-                    .setData(
-                        ByteString.copyFrom(
-                            Arrays.copyOfRange(
-                                compressed, compressed.length / 3 * 2, compressed.length)))
-                    .build());
-            responseObserver.onCompleted();
-          }
-        });
-    assertThat(downloadBlob(context, client, digest)).isEqualTo(data);
-  }
-}
diff --git a/src/test/java/com/google/devtools/build/lib/remote/NativeSslTest.java b/src/test/java/com/google/devtools/build/lib/remote/NativeSslTest.java
index 05da702..217b6ca 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/NativeSslTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/NativeSslTest.java
@@ -13,6 +13,10 @@
 // limitations under the License.
 package com.google.devtools.build.lib.remote;
 
+import static org.junit.Assume.assumeTrue;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.util.OS;
 import io.netty.handler.ssl.SslContextBuilder;
 import io.netty.handler.ssl.SslProvider;
 import org.junit.Test;
@@ -22,8 +26,14 @@
 /** Tests that we use OpenSSL instead of a Java implementation. */
 @RunWith(JUnit4.class)
 public class NativeSslTest {
+  private static final ImmutableSet<OS> OS_WITH_NATIVE_SSL =
+      ImmutableSet.of(OS.LINUX, OS.DARWIN, OS.WINDOWS);
+
   @Test
   public void nativeSslPresent() throws Exception {
+    // Skip the test on platforms where native SSL is not available.
+    assumeTrue(OS_WITH_NATIVE_SSL.contains(OS.getCurrent()));
+
     SslContextBuilder.forClient().sslProvider(SslProvider.OPENSSL).build();
   }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/remote/downloader/BUILD b/src/test/java/com/google/devtools/build/lib/remote/downloader/BUILD
index 8e2cae2..d49a5aa 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/downloader/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/remote/downloader/BUILD
@@ -28,7 +28,6 @@
         "//src/main/java/com/google/devtools/build/lib/remote",
         "//src/main/java/com/google/devtools/build/lib/remote/common",
         "//src/main/java/com/google/devtools/build/lib/remote/downloader",
-        "//src/main/java/com/google/devtools/build/lib/remote/grpc",
         "//src/main/java/com/google/devtools/build/lib/remote/options",
         "//src/main/java/com/google/devtools/build/lib/remote/util",
         "//src/main/java/com/google/devtools/build/lib/vfs",
diff --git a/src/test/java/com/google/devtools/build/lib/remote/zstd/BUILD b/src/test/java/com/google/devtools/build/lib/remote/zstd/BUILD
index 58647b4..4f80374 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/zstd/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/remote/zstd/BUILD
@@ -1,12 +1,11 @@
 load("@rules_java//java:defs.bzl", "java_test")
 
 package(
+    default_applicable_licenses = ["//:license"],
     default_testonly = 1,
     default_visibility = ["//src:__subpackages__"],
 )
 
-licenses(["notice"])
-
 filegroup(
     name = "srcs",
     testonly = 0,
@@ -24,6 +23,6 @@
         "//third_party:guava",
         "//third_party:junit4",
         "//third_party:truth",
-        "@zstd-jni//:zstd-jni",
+        "@zstd-jni",
     ],
 )
diff --git a/src/test/java/com/google/devtools/build/lib/remote/zstd/ZstdDecompressingOutputStreamTest.java b/src/test/java/com/google/devtools/build/lib/remote/zstd/ZstdDecompressingOutputStreamTest.java
index 377bb41..4768d9f 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/zstd/ZstdDecompressingOutputStreamTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/zstd/ZstdDecompressingOutputStreamTest.java
@@ -14,8 +14,10 @@
 package com.google.devtools.build.lib.remote.zstd;
 
 import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
 
 import com.github.luben.zstd.Zstd;
+import com.github.luben.zstd.ZstdOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.Random;
@@ -41,4 +43,48 @@
 
     assertThat(baos.toByteArray()).isEqualTo(data);
   }
+
+  @Test
+  public void streamCanBeDecompressedOneByteAtATime() throws IOException {
+    Random rand = new Random();
+    byte[] data = new byte[50];
+    rand.nextBytes(data);
+    byte[] compressed = Zstd.compress(data);
+
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    try (ZstdDecompressingOutputStream zdos = new ZstdDecompressingOutputStream(baos)) {
+      for (byte b : compressed) {
+        zdos.write(b);
+      }
+      zdos.flush();
+    }
+
+    assertThat(baos.toByteArray()).isEqualTo(data);
+  }
+
+  @Test
+  public void bytesWrittenMatchesDecompressedBytes() throws IOException {
+    byte[] data = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".getBytes(UTF_8);
+
+    ByteArrayOutputStream compressed = new ByteArrayOutputStream();
+    try (ZstdOutputStream zos = new ZstdOutputStream(compressed)) {
+      zos.setCloseFrameOnFlush(true);
+      for (int i = 0; i < data.length; i++) {
+        zos.write(data[i]);
+        if (i % 5 == 0) {
+          // Create multiple frames of 5 bytes each.
+          zos.flush();
+        }
+      }
+    }
+
+    ByteArrayOutputStream decompressed = new ByteArrayOutputStream();
+    try (ZstdDecompressingOutputStream zdos = new ZstdDecompressingOutputStream(decompressed)) {
+      for (byte b : compressed.toByteArray()) {
+        zdos.write(b);
+        zdos.flush();
+      }
+    }
+    assertThat(decompressed.toByteArray()).isEqualTo(data);
+  }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/remote/zstd/ZstdDecompressingOutputStreamTestExtra.java b/src/test/java/com/google/devtools/build/lib/remote/zstd/ZstdDecompressingOutputStreamTestExtra.java
deleted file mode 100644
index d5511ee..0000000
--- a/src/test/java/com/google/devtools/build/lib/remote/zstd/ZstdDecompressingOutputStreamTestExtra.java
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2021 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.zstd;
-
-import static com.google.common.truth.Truth.assertThat;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.github.luben.zstd.Zstd;
-import com.github.luben.zstd.ZstdOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.util.Random;
-import org.junit.Test;
-
-/** Extra tests for {@link ZstdDecompressingOutputStream} that are not tested internally. */
-public class ZstdDecompressingOutputStreamTestExtra {
-  @Test
-  public void streamCanBeDecompressedOneByteAtATime() throws IOException {
-    Random rand = new Random();
-    byte[] data = new byte[50];
-    rand.nextBytes(data);
-    byte[] compressed = Zstd.compress(data);
-
-    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-    try (ZstdDecompressingOutputStream zdos = new ZstdDecompressingOutputStream(baos)) {
-      for (byte b : compressed) {
-        zdos.write(b);
-      }
-      zdos.flush();
-    }
-
-    assertThat(baos.toByteArray()).isEqualTo(data);
-  }
-
-  @Test
-  public void bytesWrittenMatchesDecompressedBytes() throws IOException {
-    byte[] data = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".getBytes(UTF_8);
-
-    ByteArrayOutputStream compressed = new ByteArrayOutputStream();
-    try (ZstdOutputStream zos = new ZstdOutputStream(compressed)) {
-      zos.setCloseFrameOnFlush(true);
-      for (int i = 0; i < data.length; i++) {
-        zos.write(data[i]);
-        if (i % 5 == 0) {
-          // Create multiple frames of 5 bytes each.
-          zos.flush();
-        }
-      }
-    }
-
-    ByteArrayOutputStream decompressed = new ByteArrayOutputStream();
-    try (ZstdDecompressingOutputStream zdos = new ZstdDecompressingOutputStream(decompressed)) {
-      for (byte b : compressed.toByteArray()) {
-        zdos.write(b);
-        zdos.flush();
-      }
-    }
-    assertThat(decompressed.toByteArray()).isEqualTo(data);
-  }
-}