Skip to content

Commit

Permalink
Add unit tests for GoogleCloudStorageClient createBuckets method. (#1093
Browse files Browse the repository at this point in the history
)
  • Loading branch information
shilpi23pandey committed Dec 21, 2023
1 parent c208df4 commit 2f79ae3
Show file tree
Hide file tree
Showing 3 changed files with 291 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2023 Google LLC
*
* 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.cloud.hadoop.gcsio.testing;

import com.google.cloud.NoCredentials;
import com.google.cloud.storage.GrpcStorageOptions;
import com.google.cloud.storage.StorageOptions;
import com.google.storage.v2.StorageGrpc;
import io.grpc.Server;
import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

public final class FakeServer implements AutoCloseable {

private final Server server;
private final GrpcStorageOptions grpcStorageOptions;

FakeServer(Server server, GrpcStorageOptions grpcStorageOptions) {
this.server = server;
this.grpcStorageOptions = grpcStorageOptions;
}

public GrpcStorageOptions getGrpcStorageOptions() {
return grpcStorageOptions;
}

@Override
public void close() throws InterruptedException {
server.shutdownNow().awaitTermination(10, TimeUnit.SECONDS);
}

public static FakeServer of(StorageGrpc.StorageImplBase service) throws IOException {
InetSocketAddress address = new InetSocketAddress("localhost", 0);
Server server = NettyServerBuilder.forAddress(address).addService(service).build();
server.start();
String endpoint = String.format("%s:%d", address.getHostString(), server.getPort());
GrpcStorageOptions grpcStorageOptions =
StorageOptions.grpc()
.setHost("http://" + endpoint)
.setProjectId("test-proj")
.setCredentials(NoCredentials.getInstance())
.build();
return new FakeServer(server, grpcStorageOptions);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2023 Google LLC
*
* 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.cloud.hadoop.gcsio.testing;

import com.google.protobuf.AbstractMessage;
import com.google.storage.v2.Bucket;
import com.google.storage.v2.CreateBucketRequest;
import com.google.storage.v2.StorageGrpc.StorageImplBase;
import io.grpc.stub.StreamObserver;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public final class MockStorage extends StorageImplBase {

private List<AbstractMessage> requests;
private Queue<Object> responses;

public MockStorage() {
requests = new ArrayList<>();
responses = new LinkedList<>();
}

public List<AbstractMessage> getRequests() {
return requests;
}

public void addResponse(AbstractMessage response) {
responses.add(response);
}

public void addException(Exception exception) {
responses.add(exception);
}

public void reset() {
requests = new ArrayList<>();
responses = new LinkedList<>();
}

@Override
public void createBucket(CreateBucketRequest request, StreamObserver<Bucket> responseObserver) {
java.lang.Object response = responses.poll();
if (response instanceof Bucket) {
requests.add(request);
responseObserver.onNext(((Bucket) response));
responseObserver.onCompleted();
} else if (response instanceof Exception) {
responseObserver.onError(((Exception) response));
} else {
responseObserver.onError(
new IllegalArgumentException(
String.format(
"Unrecognized response type %s for method CreateBucket, expected %s or %s",
response == null ? "null" : response.getClass().getName(),
Bucket.class.getName(),
Exception.class.getName())));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* Copyright 2023 Google LLC
*
* 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.cloud.hadoop.gcsio;

import static com.google.cloud.hadoop.gcsio.MockGoogleCloudStorageImplFactory.mockedGcsClientImpl;
import static com.google.cloud.hadoop.util.testing.MockHttpTransportHelper.mockTransport;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;

import com.google.api.client.testing.http.MockHttpTransport;
import com.google.cloud.hadoop.gcsio.testing.FakeServer;
import com.google.cloud.hadoop.gcsio.testing.MockStorage;
import com.google.cloud.storage.StorageException;
import com.google.storage.v2.Bucket;
import com.google.storage.v2.Bucket.Lifecycle;
import com.google.storage.v2.Bucket.Lifecycle.Rule;
import com.google.storage.v2.Bucket.Lifecycle.Rule.Action;
import com.google.storage.v2.Bucket.Lifecycle.Rule.Condition;
import com.google.storage.v2.CreateBucketRequest;
import io.grpc.Status;
import io.grpc.StatusException;
import io.grpc.StatusRuntimeException;
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.time.Duration;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Unit tests for {@link GoogleCloudStorageClientImpl} */
@RunWith(JUnit4.class)
public class GoogleCloudStorageClientTest {

private static final String BUCKET_NAME = "foo-bucket";

private static final MockHttpTransport transport = mockTransport();

private static final MockStorage mockStorage = new MockStorage();

@Before
public void setUp() {
mockStorage.reset();
}

@Test
public void createBucket_succeeds() throws Exception {
mockStorage.addResponse(Bucket.newBuilder().setName(BUCKET_NAME).build());

try (FakeServer fakeServer = FakeServer.of(mockStorage)) {
GoogleCloudStorage gcs =
mockedGcsClientImpl(transport, fakeServer.getGrpcStorageOptions().getService());
gcs.createBucket(BUCKET_NAME);
}

assertEquals(mockStorage.getRequests().size(), 1);

CreateBucketRequest bucketRequest = (CreateBucketRequest) mockStorage.getRequests().get(0);
assertEquals(bucketRequest.getBucketId(), BUCKET_NAME);
}

@Test
public void createBucket_withOptions_succeeds() throws Exception {
String location = "some-location";
String storageClass = "STANDARD";
int ttlDays = 10;

mockStorage.addResponse(
Bucket.newBuilder()
.setName(BUCKET_NAME)
.setStorageClass(storageClass)
.setLocation(location)
.setLifecycle(
Lifecycle.newBuilder()
.addRule(
Rule.newBuilder()
.setAction(Action.newBuilder().setType("Delete"))
.setCondition(Condition.newBuilder().setAgeDays(ttlDays).build())
.build())
.build())
.build());

CreateBucketOptions bucketOptions =
CreateBucketOptions.builder()
.setLocation(location)
.setStorageClass(storageClass)
.setTtl(Duration.ofDays(ttlDays))
.build();

try (FakeServer fakeServer = FakeServer.of(mockStorage)) {
GoogleCloudStorage gcs =
mockedGcsClientImpl(transport, fakeServer.getGrpcStorageOptions().getService());
gcs.createBucket(BUCKET_NAME, bucketOptions);
}

assertEquals(mockStorage.getRequests().size(), 1);

CreateBucketRequest bucketRequest = (CreateBucketRequest) mockStorage.getRequests().get(0);
// Assert correct fields were set in request.
assertEquals(bucketRequest.getBucketId(), BUCKET_NAME);
assertEquals(bucketRequest.getBucket().getLocation(), location);
assertEquals(bucketRequest.getBucket().getStorageClass(), storageClass);
assertEquals(
bucketRequest.getBucket().getLifecycle().getRule(0).getAction().getType(), "Delete");
assertEquals(
bucketRequest.getBucket().getLifecycle().getRule(0).getCondition().getAgeDays(), ttlDays);
}

@Test
public void createBucket_throwsFileAlreadyExistsException() throws Exception {
mockStorage.addException(new StatusRuntimeException(Status.ALREADY_EXISTS));
try (FakeServer fakeServer = FakeServer.of(mockStorage)) {
GoogleCloudStorage gcs =
mockedGcsClientImpl(transport, fakeServer.getGrpcStorageOptions().getService());
assertThrows(FileAlreadyExistsException.class, () -> gcs.createBucket(BUCKET_NAME));
}
}

@Test
public void createBucket_throwsIOException() throws Exception {
mockStorage.addException(
new StorageException(0, "Some exception", new StatusException(Status.INVALID_ARGUMENT)));

try (FakeServer fakeServer = FakeServer.of(mockStorage)) {
GoogleCloudStorage gcs =
mockedGcsClientImpl(transport, fakeServer.getGrpcStorageOptions().getService());
assertThrows(IOException.class, () -> gcs.createBucket(BUCKET_NAME));
}
}

@Test
public void createBucket_illegalArguments() throws Exception {
try (FakeServer fakeServer = FakeServer.of(mockStorage)) {
GoogleCloudStorage gcs =
mockedGcsClientImpl(transport, fakeServer.getGrpcStorageOptions().getService());

assertThrows(IllegalArgumentException.class, () -> gcs.createBucket(null));
assertThrows(IllegalArgumentException.class, () -> gcs.createBucket(""));
}
}
}

0 comments on commit 2f79ae3

Please sign in to comment.