sourceOptions() {
}
/**
- * Returns the rewrite target.
+ * Returns the {@link BlobInfo} for the target blob.
*/
public BlobInfo target() {
return target;
@@ -1058,7 +1316,7 @@ private static void checkContentType(BlobInfo blobInfo) throws IllegalArgumentEx
/**
* Delete the requested bucket.
*
- * @return true if bucket was deleted
+ * @return {@code true} if bucket was deleted, {@code false} if it was not found
* @throws StorageException upon failure
*/
boolean delete(String bucket, BucketSourceOption... options);
@@ -1066,7 +1324,7 @@ private static void checkContentType(BlobInfo blobInfo) throws IllegalArgumentEx
/**
* Delete the requested blob.
*
- * @return true if blob was deleted
+ * @return {@code true} if blob was deleted, {@code false} if it was not found
* @throws StorageException upon failure
*/
boolean delete(String bucket, String blob, BlobSourceOption... options);
@@ -1074,7 +1332,7 @@ private static void checkContentType(BlobInfo blobInfo) throws IllegalArgumentEx
/**
* Delete the requested blob.
*
- * @return true if blob was deleted
+ * @return {@code true} if blob was deleted, {@code false} if it was not found
* @throws StorageException upon failure
*/
boolean delete(BlobId blob, BlobSourceOption... options);
@@ -1082,7 +1340,7 @@ private static void checkContentType(BlobInfo blobInfo) throws IllegalArgumentEx
/**
* Delete the requested blob.
*
- * @return true if blob was deleted
+ * @return {@code true} if blob was deleted, {@code false} if it was not found
* @throws StorageException upon failure
*/
boolean delete(BlobId blob);
@@ -1147,14 +1405,29 @@ private static void checkContentType(BlobInfo blobInfo) throws IllegalArgumentEx
BatchResponse apply(BatchRequest batchRequest);
/**
- * Return a channel for reading the blob's content.
+ * Return a channel for reading the blob's content. The blob's latest generation is read. If the
+ * blob changes while reading (i.e. {@link BlobInfo#etag()} changes), subsequent calls to
+ * {@code blobReadChannel.read(ByteBuffer)} may throw {@link StorageException}.
+ *
+ * The {@link BlobSourceOption#generationMatch(long)} option can be provided to ensure that
+ * {@code blobReadChannel.read(ByteBuffer)} calls will throw {@link StorageException} if blob`s
+ * generation differs from the expected one.
*
* @throws StorageException upon failure
*/
BlobReadChannel reader(String bucket, String blob, BlobSourceOption... options);
/**
- * Return a channel for reading the blob's content.
+ * Return a channel for reading the blob's content. If {@code blob.generation()} is set
+ * data corresponding to that generation is read. If {@code blob.generation()} is {@code null}
+ * the blob's latest generation is read. If the blob changes while reading (i.e.
+ * {@link BlobInfo#etag()} changes), subsequent calls to {@code blobReadChannel.read(ByteBuffer)}
+ * may throw {@link StorageException}.
+ *
+ *
The {@link BlobSourceOption#generationMatch()} and
+ * {@link BlobSourceOption#generationMatch(long)} options can be used to ensure that
+ * {@code blobReadChannel.read(ByteBuffer)} calls will throw {@link StorageException} if the
+ * blob`s generation differs from the expected one.
*
* @throws StorageException upon failure
*/
@@ -1220,8 +1493,8 @@ private static void checkContentType(BlobInfo blobInfo) throws IllegalArgumentEx
*
* @param blobIds blobs to delete
* @return an immutable list of booleans. If a blob has been deleted the corresponding item in the
- * list is {@code true}. If deletion failed or access to the resource was denied the item is
- * {@code false}.
+ * list is {@code true}. If a blob was not found, deletion failed or access to the resource
+ * was denied the corresponding item is {@code false}.
* @throws StorageException upon failure
*/
List delete(BlobId... blobIds);
diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java
index 4c85113e940e..d1535c92dfdb 100644
--- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java
+++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java
@@ -28,10 +28,10 @@
import static com.google.gcloud.spi.StorageRpc.Option.IF_SOURCE_GENERATION_NOT_MATCH;
import static com.google.gcloud.spi.StorageRpc.Option.IF_SOURCE_METAGENERATION_MATCH;
import static com.google.gcloud.spi.StorageRpc.Option.IF_SOURCE_METAGENERATION_NOT_MATCH;
-import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.api.services.storage.model.StorageObject;
+import com.google.auth.oauth2.ServiceAccountCredentials;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableList;
@@ -39,17 +39,16 @@
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
import com.google.common.hash.Hashing;
import com.google.common.io.BaseEncoding;
import com.google.common.primitives.Ints;
import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials;
-import com.google.gcloud.PageImpl;
import com.google.gcloud.BaseService;
import com.google.gcloud.ExceptionHandler;
import com.google.gcloud.ExceptionHandler.Interceptor;
-import com.google.gcloud.RetryHelper.RetryHelperException;
import com.google.gcloud.Page;
+import com.google.gcloud.PageImpl;
+import com.google.gcloud.RetryHelper.RetryHelperException;
import com.google.gcloud.spi.StorageRpc;
import com.google.gcloud.spi.StorageRpc.RewriteResponse;
import com.google.gcloud.spi.StorageRpc.Tuple;
@@ -70,7 +69,6 @@
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
@@ -175,14 +173,7 @@ public BucketInfo get(String bucket, BucketGetOption... options) {
new Callable() {
@Override
public com.google.api.services.storage.model.Bucket call() {
- try {
- return storageRpc.get(bucketPb, optionsMap);
- } catch (StorageException ex) {
- if (ex.code() == HTTP_NOT_FOUND) {
- return null;
- }
- throw ex;
- }
+ return storageRpc.get(bucketPb, optionsMap);
}
}, options().retryParams(), EXCEPTION_HANDLER);
return answer == null ? null : BucketInfo.fromPb(answer);
@@ -199,19 +190,12 @@ public BlobInfo get(String bucket, String blob, BlobGetOption... options) {
@Override
public BlobInfo get(BlobId blob, BlobGetOption... options) {
final StorageObject storedObject = blob.toPb();
- final Map optionsMap = optionMap(options);
+ final Map optionsMap = optionMap(blob, options);
try {
StorageObject storageObject = runWithRetries(new Callable() {
@Override
public StorageObject call() {
- try {
- return storageRpc.get(storedObject, optionsMap);
- } catch (StorageException ex) {
- if (ex.code() == HTTP_NOT_FOUND) {
- return null;
- }
- throw ex;
- }
+ return storageRpc.get(storedObject, optionsMap);
}
}, options().retryParams(), EXCEPTION_HANDLER);
return storageObject == null ? null : BlobInfo.fromPb(storageObject);
@@ -405,7 +389,7 @@ public boolean delete(String bucket, String blob, BlobSourceOption... options) {
@Override
public boolean delete(BlobId blob, BlobSourceOption... options) {
final StorageObject storageObject = blob.toPb();
- final Map optionsMap = optionMap(options);
+ final Map optionsMap = optionMap(blob, options);
try {
return runWithRetries(new Callable() {
@Override
@@ -428,8 +412,9 @@ public BlobInfo compose(final ComposeRequest composeRequest) {
final List sources =
Lists.newArrayListWithCapacity(composeRequest.sourceBlobs().size());
for (ComposeRequest.SourceBlob sourceBlob : composeRequest.sourceBlobs()) {
- sources.add(BlobInfo.builder(composeRequest.target().bucket(), sourceBlob.name())
- .generation(sourceBlob.generation()).build().toPb());
+ sources.add(BlobInfo.builder(
+ BlobId.of(composeRequest.target().bucket(), sourceBlob.name(), sourceBlob.generation()))
+ .build().toPb());
}
final StorageObject target = composeRequest.target().toPb();
final Map targetOptions = optionMap(composeRequest.target().generation(),
@@ -450,7 +435,7 @@ public StorageObject call() {
public CopyWriter copy(final CopyRequest copyRequest) {
final StorageObject source = copyRequest.source().toPb();
final Map sourceOptions =
- optionMap(null, null, copyRequest.sourceOptions(), true);
+ optionMap(copyRequest.source().generation(), null, copyRequest.sourceOptions(), true);
final StorageObject target = copyRequest.target().toPb();
final Map targetOptions = optionMap(copyRequest.target().generation(),
copyRequest.target().metageneration(), copyRequest.targetOptions());
@@ -476,7 +461,7 @@ public byte[] readAllBytes(String bucket, String blob, BlobSourceOption... optio
@Override
public byte[] readAllBytes(BlobId blob, BlobSourceOption... options) {
final StorageObject storageObject = blob.toPb();
- final Map optionsMap = optionMap(options);
+ final Map optionsMap = optionMap(blob, options);
try {
return runWithRetries(new Callable() {
@Override
@@ -495,7 +480,7 @@ public BatchResponse apply(BatchRequest batchRequest) {
Lists.newArrayListWithCapacity(batchRequest.toDelete().size());
for (Map.Entry> entry : batchRequest.toDelete().entrySet()) {
BlobId blob = entry.getKey();
- Map optionsMap = optionMap(null, null, entry.getValue());
+ Map optionsMap = optionMap(blob.generation(), null, entry.getValue());
StorageObject storageObject = blob.toPb();
toDelete.add(Tuple.>of(storageObject, optionsMap));
}
@@ -512,7 +497,7 @@ public BatchResponse apply(BatchRequest batchRequest) {
Lists.newArrayListWithCapacity(batchRequest.toGet().size());
for (Map.Entry> entry : batchRequest.toGet().entrySet()) {
BlobId blob = entry.getKey();
- Map optionsMap = optionMap(null, null, entry.getValue());
+ Map optionsMap = optionMap(blob.generation(), null, entry.getValue());
toGet.add(Tuple.>of(blob.toPb(), optionsMap));
}
StorageRpc.BatchResponse response =
@@ -522,28 +507,23 @@ public BatchResponse apply(BatchRequest batchRequest) {
List> updates = transformBatchResult(
toUpdate, response.updates, BlobInfo.FROM_PB_FUNCTION);
List> gets = transformBatchResult(
- toGet, response.gets, BlobInfo.FROM_PB_FUNCTION, HTTP_NOT_FOUND);
+ toGet, response.gets, BlobInfo.FROM_PB_FUNCTION);
return new BatchResponse(deletes, updates, gets);
}
private List> transformBatchResult(
Iterable>> request,
- Map> results, Function transform,
- int... nullOnErrorCodes) {
- Set nullOnErrorCodesSet = Sets.newHashSet(Ints.asList(nullOnErrorCodes));
+ Map> results, Function transform) {
List> response = Lists.newArrayListWithCapacity(results.size());
for (Tuple tuple : request) {
Tuple result = results.get(tuple.x());
- if (result.x() != null) {
- response.add(BatchResponse.Result.of(transform.apply(result.x())));
+ I object = result.x();
+ StorageException exception = result.y();
+ if (exception != null) {
+ response.add(new BatchResponse.Result(exception));
} else {
- StorageException exception = result.y();
- if (nullOnErrorCodesSet.contains(exception.code())) {
- //noinspection unchecked
- response.add(BatchResponse.Result.empty());
- } else {
- response.add(new BatchResponse.Result(exception));
- }
+ response.add(object != null
+ ? BatchResponse.Result.of(transform.apply(object)) : BatchResponse.Result.empty());
}
}
return response;
@@ -557,7 +537,7 @@ public BlobReadChannel reader(String bucket, String blob, BlobSourceOption... op
@Override
public BlobReadChannel reader(BlobId blob, BlobSourceOption... options) {
- Map optionsMap = optionMap(options);
+ Map optionsMap = optionMap(blob, options);
return new BlobReadChannelImpl(options(), blob, optionsMap);
}
@@ -580,12 +560,15 @@ public URL signUrl(BlobInfo blobInfo, long duration, TimeUnit unit, SignUrlOptio
for (SignUrlOption option : options) {
optionMap.put(option.option(), option.value());
}
- ServiceAccountAuthCredentials cred =
+ ServiceAccountAuthCredentials authCred =
(ServiceAccountAuthCredentials) optionMap.get(SignUrlOption.Option.SERVICE_ACCOUNT_CRED);
- if (cred == null) {
- checkArgument(options().authCredentials() instanceof ServiceAccountAuthCredentials,
+ ServiceAccountCredentials cred = authCred != null ? authCred.credentials() : null;
+ if (authCred == null) {
+ checkArgument(
+ this.options().authCredentials() != null
+ && this.options().authCredentials().credentials() instanceof ServiceAccountCredentials,
"Signing key was not provided and could not be derived");
- cred = (ServiceAccountAuthCredentials) this.options().authCredentials();
+ cred = (ServiceAccountCredentials) this.options().authCredentials().credentials();
}
// construct signature - see https://cloud.google.com/storage/docs/access-control#Signed-URLs
StringBuilder stBuilder = new StringBuilder();
@@ -621,12 +604,12 @@ public URL signUrl(BlobInfo blobInfo, long duration, TimeUnit unit, SignUrlOptio
stBuilder.append(path);
try {
Signature signer = Signature.getInstance("SHA256withRSA");
- signer.initSign(cred.privateKey());
+ signer.initSign(cred.getPrivateKey());
signer.update(stBuilder.toString().getBytes(UTF_8));
String signature =
URLEncoder.encode(BaseEncoding.base64().encode(signer.sign()), UTF_8.name());
stBuilder = new StringBuilder("https://storage.googleapis.com").append(path);
- stBuilder.append("?GoogleAccessId=").append(cred.account());
+ stBuilder.append("?GoogleAccessId=").append(cred.getClientEmail());
stBuilder.append("&Expires=").append(expiration);
stBuilder.append("&Signature=").append(signature);
return new URL(stBuilder.toString());
@@ -741,4 +724,8 @@ private static void addToOptionMap(StorageRpc.Option getOption, StorageRpc.O
private Map optionMap(BlobInfo blobInfo, Option... options) {
return optionMap(blobInfo.generation(), blobInfo.metageneration(), options);
}
+
+ private Map optionMap(BlobId blobId, Option... options) {
+ return optionMap(blobId.generation(), null, options);
+ }
}
diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java
index 16c17c3e8d98..9ec743c079e7 100644
--- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java
+++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java
@@ -89,11 +89,13 @@ private StorageOptions(Builder builder) {
pathDelimiter = MoreObjects.firstNonNull(builder.pathDelimiter, DEFAULT_PATH_DELIMITER);
}
+ @SuppressWarnings("unchecked")
@Override
protected StorageFactory defaultServiceFactory() {
return DefaultStorageFactory.INSTANCE;
}
+ @SuppressWarnings("unchecked")
@Override
protected StorageRpcFactory defaultRpcFactory() {
return DefaultStorageRpcFactory.INSTANCE;
@@ -111,6 +113,14 @@ public String pathDelimiter() {
return pathDelimiter;
}
+ /**
+ * Returns a default {@code StorageOptions} instance.
+ */
+ public static StorageOptions defaultInstance() {
+ return builder().build();
+ }
+
+ @SuppressWarnings("unchecked")
@Override
public Builder toBuilder() {
return new Builder(this);
diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/package-info.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/package-info.java
index 2a09631be40a..137afd38b6ae 100644
--- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/package-info.java
+++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/package-info.java
@@ -17,10 +17,9 @@
/**
* A client to Google Cloud Storage.
*
- * A simple usage example:
+ *
Here's a simple usage example for using gcloud-java from App/Compute Engine:
*
{@code
- * StorageOptions options = StorageOptions.builder().projectId("project").build();
- * Storage storage = options.service();
+ * Storage storage = StorageOptions.defaultInstance().service();
* BlobId blobId = BlobId.of("bucket", "blob_name");
* Blob blob = Blob.load(storage, blobId);
* if (blob == null) {
@@ -35,6 +34,11 @@
* channel.close();
* }}
*
+ * When using gcloud-java from outside of App/Compute Engine, you have to specify a
+ * project ID and
+ * provide
+ * credentials.
* @see Google Cloud Storage
*/
package com.google.gcloud.storage;
diff --git a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/testing/RemoteGcsHelper.java b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/testing/RemoteGcsHelper.java
index b15768cffa98..f5cdae83f999 100644
--- a/gcloud-java-storage/src/main/java/com/google/gcloud/storage/testing/RemoteGcsHelper.java
+++ b/gcloud-java-storage/src/main/java/com/google/gcloud/storage/testing/RemoteGcsHelper.java
@@ -45,8 +45,6 @@ public class RemoteGcsHelper {
private static final Logger log = Logger.getLogger(RemoteGcsHelper.class.getName());
private static final String BUCKET_NAME_PREFIX = "gcloud-test-bucket-temp-";
- private static final String PROJECT_ID_ENV_VAR = "GCLOUD_TESTS_PROJECT_ID";
- private static final String PRIVATE_KEY_ENV_VAR = "GCLOUD_TESTS_KEY";
private final StorageOptions options;
private RemoteGcsHelper(StorageOptions options) {
@@ -107,13 +105,7 @@ public static RemoteGcsHelper create(String projectId, InputStream keyStream)
StorageOptions storageOptions = StorageOptions.builder()
.authCredentials(AuthCredentials.createForJson(keyStream))
.projectId(projectId)
- .retryParams(RetryParams.builder()
- .retryMaxAttempts(10)
- .retryMinAttempts(6)
- .maxRetryDelayMillis(30000)
- .totalRetryPeriodMillis(120000)
- .initialRetryDelayMillis(250)
- .build())
+ .retryParams(retryParams())
.connectTimeout(60000)
.readTimeout(60000)
.build();
@@ -145,41 +137,30 @@ public static RemoteGcsHelper create(String projectId, String keyPath)
log.log(Level.WARNING, ex.getMessage());
}
throw GcsHelperException.translate(ex);
- } catch (IOException ex) {
- if (log.isLoggable(Level.WARNING)) {
- log.log(Level.WARNING, ex.getMessage());
- }
- throw GcsHelperException.translate(ex);
}
}
/**
- * Creates a {@code RemoteGcsHelper} object. Project id and path to JSON key are read from two
- * environment variables: {@code GCLOUD_TESTS_PROJECT_ID} and {@code GCLOUD_TESTS_KEY}.
- *
- * @return A {@code RemoteGcsHelper} object for the provided options.
- * @throws com.google.gcloud.storage.testing.RemoteGcsHelper.GcsHelperException if environment
- * variables {@code GCLOUD_TESTS_PROJECT_ID} and {@code GCLOUD_TESTS_KEY} are not set or if
- * the file pointed by {@code GCLOUD_TESTS_KEY} does not exist
+ * Creates a {@code RemoteGcsHelper} object using default project id and authentication
+ * credentials.
*/
public static RemoteGcsHelper create() throws GcsHelperException {
- String projectId = System.getenv(PROJECT_ID_ENV_VAR);
- String keyPath = System.getenv(PRIVATE_KEY_ENV_VAR);
- if (projectId == null) {
- String message = "Environment variable " + PROJECT_ID_ENV_VAR + " not set";
- if (log.isLoggable(Level.WARNING)) {
- log.log(Level.WARNING, message);
- }
- throw new GcsHelperException(message);
- }
- if (keyPath == null) {
- String message = "Environment variable " + PRIVATE_KEY_ENV_VAR + " not set";
- if (log.isLoggable(Level.WARNING)) {
- log.log(Level.WARNING, message);
- }
- throw new GcsHelperException(message);
- }
- return create(projectId, keyPath);
+ StorageOptions storageOptions = StorageOptions.builder()
+ .retryParams(retryParams())
+ .connectTimeout(60000)
+ .readTimeout(60000)
+ .build();
+ return new RemoteGcsHelper(storageOptions);
+ }
+
+ private static RetryParams retryParams() {
+ return RetryParams.builder()
+ .retryMaxAttempts(10)
+ .retryMinAttempts(6)
+ .maxRetryDelayMillis(30000)
+ .totalRetryPeriodMillis(120000)
+ .initialRetryDelayMillis(250)
+ .build();
}
private static class DeleteBucketTask implements Callable {
diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BatchRequestTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BatchRequestTest.java
index 600c8af0d554..63972ff85dfd 100644
--- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BatchRequestTest.java
+++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BatchRequestTest.java
@@ -37,12 +37,12 @@ public class BatchRequestTest {
@Test
public void testBatchRequest() {
BatchRequest request = BatchRequest.builder()
- .delete("b1", "o1")
+ .delete(BlobId.of("b1", "o1", 1L), BlobSourceOption.generationMatch())
.delete("b1", "o2", BlobSourceOption.generationMatch(1),
BlobSourceOption.metagenerationMatch(2))
.update(BlobInfo.builder("b2", "o1").build(), BlobTargetOption.predefinedAcl(PUBLIC_READ))
.update(BlobInfo.builder("b2", "o2").build())
- .get("b3", "o1")
+ .get(BlobId.of("b3", "o1", 1L), BlobGetOption.generationMatch())
.get("b3", "o2", BlobGetOption.generationMatch(1))
.get("b3", "o3")
.build();
@@ -50,11 +50,15 @@ public void testBatchRequest() {
Iterator>> deletes = request
.toDelete().entrySet().iterator();
Entry> delete = deletes.next();
- assertEquals(BlobId.of("b1", "o1"), delete.getKey());
- assertTrue(Iterables.isEmpty(delete.getValue()));
+ assertEquals(BlobId.of("b1", "o1", 1L), delete.getKey());
+ assertEquals(1, Iterables.size(delete.getValue()));
+ assertEquals(BlobSourceOption.generationMatch(), Iterables.getFirst(delete.getValue(), null));
delete = deletes.next();
assertEquals(BlobId.of("b1", "o2"), delete.getKey());
assertEquals(2, Iterables.size(delete.getValue()));
+ assertEquals(BlobSourceOption.generationMatch(1L), Iterables.getFirst(delete.getValue(), null));
+ assertEquals(BlobSourceOption.metagenerationMatch(2L),
+ Iterables.get(delete.getValue(), 1, null));
assertFalse(deletes.hasNext());
Iterator>> updates = request
@@ -71,8 +75,9 @@ public void testBatchRequest() {
Iterator>> gets = request.toGet().entrySet().iterator();
Entry> get = gets.next();
- assertEquals(BlobId.of("b3", "o1"), get.getKey());
- assertTrue(Iterables.isEmpty(get.getValue()));
+ assertEquals(BlobId.of("b3", "o1", 1L), get.getKey());
+ assertEquals(1, Iterables.size(get.getValue()));
+ assertEquals(BlobGetOption.generationMatch(), Iterables.getFirst(get.getValue(), null));
get = gets.next();
assertEquals(BlobId.of("b3", "o2"), get.getKey());
assertEquals(1, Iterables.size(get.getValue()));
diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobInfoTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobInfoTest.java
index 70560b0c9a9e..36b027dc7278 100644
--- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobInfoTest.java
+++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobInfoTest.java
@@ -55,7 +55,7 @@ public class BlobInfoTest {
private static final String SELF_LINK = "http://storage/b/n";
private static final Long SIZE = 1024L;
private static final Long UPDATE_TIME = DELETE_TIME - 1L;
- private static final BlobInfo BLOB_INFO = BlobInfo.builder("b", "n")
+ private static final BlobInfo BLOB_INFO = BlobInfo.builder("b", "n", GENERATION)
.acl(ACL)
.componentCount(COMPONENT_COUNT)
.contentType(CONTENT_TYPE)
@@ -66,7 +66,6 @@ public class BlobInfoTest {
.crc32c(CRC32)
.deleteTime(DELETE_TIME)
.etag(ETAG)
- .generation(GENERATION)
.id(ID)
.md5(MD5)
.mediaLink(MEDIA_LINK)
@@ -85,10 +84,16 @@ public void testToBuilder() {
assertEquals("n2", blobInfo.name());
assertEquals("b2", blobInfo.bucket());
assertEquals(Long.valueOf(200), blobInfo.size());
- blobInfo = blobInfo.toBuilder().blobId(BlobId.of("b", "n")).size(SIZE).build();
+ blobInfo = blobInfo.toBuilder().blobId(BlobId.of("b", "n", GENERATION)).size(SIZE).build();
compareBlobs(BLOB_INFO, blobInfo);
}
+ @Test
+ public void testToBuilderIncomplete() {
+ BlobInfo incompleteBlobInfo = BlobInfo.builder(BlobId.of("b2", "n2")).build();
+ compareBlobs(incompleteBlobInfo, incompleteBlobInfo.toBuilder().build());
+ }
+
@Test
public void testBuilder() {
assertEquals("b", BLOB_INFO.bucket());
@@ -150,6 +155,6 @@ public void testToPbAndFromPb() {
@Test
public void testBlobId() {
- assertEquals(BlobId.of("b", "n"), BLOB_INFO.blobId());
+ assertEquals(BlobId.of("b", "n", GENERATION), BLOB_INFO.blobId());
}
}
diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobReadChannelImplTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobReadChannelImplTest.java
index e1f904bf72fe..d943715580c9 100644
--- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobReadChannelImplTest.java
+++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobReadChannelImplTest.java
@@ -19,7 +19,6 @@
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertArrayEquals;
@@ -46,7 +45,7 @@ public class BlobReadChannelImplTest {
private static final String BUCKET_NAME = "b";
private static final String BLOB_NAME = "n";
- private static final BlobId BLOB_ID = BlobId.of(BUCKET_NAME, BLOB_NAME);
+ private static final BlobId BLOB_ID = BlobId.of(BUCKET_NAME, BLOB_NAME, -1L);
private static final Map EMPTY_RPC_OPTIONS = ImmutableMap.of();
private static final int DEFAULT_CHUNK_SIZE = 2 * 1024 * 1024;
private static final int CUSTOM_CHUNK_SIZE = 2 * 1024 * 1024;
@@ -58,7 +57,7 @@ public class BlobReadChannelImplTest {
private BlobReadChannelImpl reader;
@Before
- public void setUp() throws IOException, InterruptedException {
+ public void setUp() {
rpcFactoryMock = createMock(StorageRpcFactory.class);
storageRpcMock = createMock(StorageRpc.class);
expect(rpcFactoryMock.create(anyObject(StorageOptions.class))).andReturn(storageRpcMock);
@@ -88,7 +87,7 @@ public void testReadBuffered() throws IOException {
ByteBuffer firstReadBuffer = ByteBuffer.allocate(42);
ByteBuffer secondReadBuffer = ByteBuffer.allocate(42);
expect(storageRpcMock.read(BLOB_ID.toPb(), EMPTY_RPC_OPTIONS, 0, DEFAULT_CHUNK_SIZE))
- .andReturn(result);
+ .andReturn(StorageRpc.Tuple.of("etag", result));
replay(storageRpcMock);
reader.read(firstReadBuffer);
reader.read(secondReadBuffer);
@@ -107,10 +106,11 @@ public void testReadBig() throws IOException {
byte[] secondResult = randomByteArray(DEFAULT_CHUNK_SIZE);
ByteBuffer firstReadBuffer = ByteBuffer.allocate(DEFAULT_CHUNK_SIZE);
ByteBuffer secondReadBuffer = ByteBuffer.allocate(42);
- storageRpcMock.read(BLOB_ID.toPb(), EMPTY_RPC_OPTIONS, 0, DEFAULT_CHUNK_SIZE);
- expectLastCall().andReturn(firstResult);
- storageRpcMock.read(BLOB_ID.toPb(), EMPTY_RPC_OPTIONS, DEFAULT_CHUNK_SIZE, CUSTOM_CHUNK_SIZE);
- expectLastCall().andReturn(secondResult);
+ expect(storageRpcMock.read(BLOB_ID.toPb(), EMPTY_RPC_OPTIONS, 0, DEFAULT_CHUNK_SIZE))
+ .andReturn(StorageRpc.Tuple.of("etag", firstResult));
+ expect(storageRpcMock.read(
+ BLOB_ID.toPb(), EMPTY_RPC_OPTIONS, DEFAULT_CHUNK_SIZE, CUSTOM_CHUNK_SIZE))
+ .andReturn(StorageRpc.Tuple.of("etag", secondResult));
replay(storageRpcMock);
reader.read(firstReadBuffer);
reader.read(secondReadBuffer);
@@ -125,7 +125,7 @@ public void testReadFinish() throws IOException {
byte[] result = {};
ByteBuffer readBuffer = ByteBuffer.allocate(DEFAULT_CHUNK_SIZE);
expect(storageRpcMock.read(BLOB_ID.toPb(), EMPTY_RPC_OPTIONS, 0, DEFAULT_CHUNK_SIZE))
- .andReturn(result);
+ .andReturn(StorageRpc.Tuple.of("etag", result));
replay(storageRpcMock);
assertEquals(-1, reader.read(readBuffer));
}
@@ -137,14 +137,14 @@ public void testSeek() throws IOException {
byte[] result = randomByteArray(DEFAULT_CHUNK_SIZE);
ByteBuffer readBuffer = ByteBuffer.allocate(DEFAULT_CHUNK_SIZE);
expect(storageRpcMock.read(BLOB_ID.toPb(), EMPTY_RPC_OPTIONS, 42, DEFAULT_CHUNK_SIZE))
- .andReturn(result);
+ .andReturn(StorageRpc.Tuple.of("etag", result));
replay(storageRpcMock);
reader.read(readBuffer);
assertArrayEquals(result, readBuffer.array());
}
@Test
- public void testClose() throws IOException {
+ public void testClose() {
replay(storageRpcMock);
reader = new BlobReadChannelImpl(options, BLOB_ID, EMPTY_RPC_OPTIONS);
assertTrue(reader.isOpen());
@@ -167,15 +167,40 @@ public void testReadClosed() {
}
@Test
- public void testSaveAndRestore() throws IOException, ClassNotFoundException {
+ public void testReadGenerationChanged() throws IOException {
+ BlobId blobId = BlobId.of(BUCKET_NAME, BLOB_NAME);
+ reader = new BlobReadChannelImpl(options, blobId, EMPTY_RPC_OPTIONS);
+ byte[] firstResult = randomByteArray(DEFAULT_CHUNK_SIZE);
+ byte[] secondResult = randomByteArray(DEFAULT_CHUNK_SIZE);
+ ByteBuffer firstReadBuffer = ByteBuffer.allocate(DEFAULT_CHUNK_SIZE);
+ ByteBuffer secondReadBuffer = ByteBuffer.allocate(DEFAULT_CHUNK_SIZE);
+ expect(storageRpcMock.read(blobId.toPb(), EMPTY_RPC_OPTIONS, 0, DEFAULT_CHUNK_SIZE))
+ .andReturn(StorageRpc.Tuple.of("etag1", firstResult));
+ expect(
+ storageRpcMock.read(blobId.toPb(), EMPTY_RPC_OPTIONS, DEFAULT_CHUNK_SIZE,
+ DEFAULT_CHUNK_SIZE)).andReturn(StorageRpc.Tuple.of("etag2", secondResult));
+ replay(storageRpcMock);
+ reader.read(firstReadBuffer);
+ try {
+ reader.read(secondReadBuffer);
+ fail("Expected BlobReadChannel read to throw StorageException");
+ } catch (StorageException ex) {
+ StringBuilder messageBuilder = new StringBuilder();
+ messageBuilder.append("Blob ").append(blobId).append(" was updated while reading");
+ assertEquals(messageBuilder.toString(), ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testSaveAndRestore() throws IOException {
byte[] firstResult = randomByteArray(DEFAULT_CHUNK_SIZE);
byte[] secondResult = randomByteArray(DEFAULT_CHUNK_SIZE);
ByteBuffer firstReadBuffer = ByteBuffer.allocate(42);
ByteBuffer secondReadBuffer = ByteBuffer.allocate(DEFAULT_CHUNK_SIZE);
expect(storageRpcMock.read(BLOB_ID.toPb(), EMPTY_RPC_OPTIONS, 0, DEFAULT_CHUNK_SIZE))
- .andReturn(firstResult);
+ .andReturn(StorageRpc.Tuple.of("etag", firstResult));
expect(storageRpcMock.read(BLOB_ID.toPb(), EMPTY_RPC_OPTIONS, 42, DEFAULT_CHUNK_SIZE))
- .andReturn(secondResult);
+ .andReturn(StorageRpc.Tuple.of("etag", secondResult));
replay(storageRpcMock);
reader = new BlobReadChannelImpl(options, BLOB_ID, EMPTY_RPC_OPTIONS);
reader.read(firstReadBuffer);
@@ -191,6 +216,7 @@ public void testSaveAndRestore() throws IOException, ClassNotFoundException {
public void testStateEquals() {
replay(storageRpcMock);
reader = new BlobReadChannelImpl(options, BLOB_ID, EMPTY_RPC_OPTIONS);
+ @SuppressWarnings("resource") // avoid closing when you don't want partial writes to GCS
BlobReadChannel secondReader = new BlobReadChannelImpl(options, BLOB_ID, EMPTY_RPC_OPTIONS);
RestorableState state = reader.capture();
RestorableState secondState = secondReader.capture();
diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobTest.java
index 02e325716c8b..3998ae554327 100644
--- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobTest.java
+++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobTest.java
@@ -155,7 +155,7 @@ public void testCopyTo() throws Exception {
public void testCopyToBlobId() throws Exception {
BlobId targetId = BlobId.of("bt", "nt");
CopyWriter copyWriter = createMock(CopyWriter.class);
- BlobInfo target = BLOB_INFO.builder(targetId).build();
+ BlobInfo target = BlobInfo.builder(targetId).build();
Capture capturedCopyRequest = Capture.newInstance();
expect(storage.copy(capture(capturedCopyRequest))).andReturn(copyWriter);
replay(storage);
diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobWriteChannelImplTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobWriteChannelImplTest.java
index 6faa36173ab9..c2107ff13998 100644
--- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobWriteChannelImplTest.java
+++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BlobWriteChannelImplTest.java
@@ -65,7 +65,7 @@ public class BlobWriteChannelImplTest {
private BlobWriteChannelImpl writer;
@Before
- public void setUp() throws IOException, InterruptedException {
+ public void setUp() {
rpcFactoryMock = createMock(StorageRpcFactory.class);
storageRpcMock = createMock(StorageRpc.class);
expect(rpcFactoryMock.create(anyObject(StorageOptions.class)))
@@ -234,6 +234,8 @@ public void testStateEquals() {
.times(2);
replay(storageRpcMock);
writer = new BlobWriteChannelImpl(options, BLOB_INFO, EMPTY_RPC_OPTIONS);
+ // avoid closing when you don't want partial writes to GCS upon failure
+ @SuppressWarnings("resource")
BlobWriteChannel writer2 = new BlobWriteChannelImpl(options, BLOB_INFO, EMPTY_RPC_OPTIONS);
RestorableState state = writer.capture();
RestorableState state2 = writer2.capture();
diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketInfoTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketInfoTest.java
index 09ba0e8cda8e..b705685a04b1 100644
--- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketInfoTest.java
+++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketInfoTest.java
@@ -18,7 +18,6 @@
import static com.google.gcloud.storage.Acl.Project.ProjectRole.VIEWERS;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import com.google.api.services.storage.model.Bucket.Lifecycle.Rule;
@@ -31,10 +30,8 @@
import com.google.gcloud.storage.BucketInfo.DeleteRule;
import com.google.gcloud.storage.BucketInfo.DeleteRule.Type;
import com.google.gcloud.storage.BucketInfo.IsLiveDeleteRule;
-import com.google.gcloud.storage.BucketInfo.Location;
import com.google.gcloud.storage.BucketInfo.NumNewerVersionsDeleteRule;
import com.google.gcloud.storage.BucketInfo.RawDeleteRule;
-import com.google.gcloud.storage.BucketInfo.StorageClass;
import org.junit.Test;
@@ -59,8 +56,8 @@ public class BucketInfoTest {
Collections.singletonList(new AgeDeleteRule(5));
private static final String INDEX_PAGE = "index.html";
private static final String NOT_FOUND_PAGE = "error.html";
- private static final Location LOCATION = Location.asia();
- private static final StorageClass STORAGE_CLASS = StorageClass.standard();
+ private static final String LOCATION = "ASIA";
+ private static final String STORAGE_CLASS = "STANDARD";
private static final Boolean VERSIONING_ENABLED = true;
private static final BucketInfo BUCKET_INFO = BucketInfo.builder("b")
.acl(ACL)
@@ -93,7 +90,7 @@ public void testToBuilder() {
@Test
public void testToBuilderIncomplete() {
BucketInfo incompleteBucketInfo = BucketInfo.builder("b").build();
- assertEquals(incompleteBucketInfo.name(), incompleteBucketInfo.toBuilder().build().name());
+ compareBuckets(incompleteBucketInfo, incompleteBucketInfo.toBuilder().build());
}
@Test
@@ -149,16 +146,6 @@ private void compareBuckets(BucketInfo expected, BucketInfo value) {
assertEquals(expected.versioningEnabled(), value.versioningEnabled());
}
- @Test
- public void testLocation() {
- assertEquals("ASIA", Location.asia().value());
- assertEquals("EU", Location.eu().value());
- assertEquals("US", Location.us().value());
- assertSame(Location.asia(), Location.of("asia"));
- assertSame(Location.eu(), Location.of("EU"));
- assertSame(Location.us(), Location.of("uS"));
- }
-
@Test
public void testDeleteRules() {
AgeDeleteRule ageRule = new AgeDeleteRule(10);
diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java
index 5d8fc5a9dffc..596f43a3c87a 100644
--- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java
+++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/BucketTest.java
@@ -27,8 +27,8 @@
import static org.junit.Assert.assertTrue;
import com.google.common.collect.ImmutableList;
-import com.google.gcloud.PageImpl;
import com.google.gcloud.Page;
+import com.google.gcloud.PageImpl;
import com.google.gcloud.storage.BatchResponse.Result;
import org.easymock.Capture;
@@ -153,8 +153,8 @@ public void testGetAll() throws Exception {
for (BlobInfo info : BLOB_INFO_RESULTS) {
batchResultList.add(new Result<>(info));
}
- BatchResponse response =
- new BatchResponse(Collections.EMPTY_LIST, Collections.EMPTY_LIST, batchResultList);
+ BatchResponse response = new BatchResponse(Collections.>emptyList(),
+ Collections.>emptyList(), batchResultList);
expect(storage.apply(capture(capturedBatchRequest))).andReturn(response);
replay(storage);
List blobs = bucket.get("n1", "n2", "n3");
diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/CopyWriterTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/CopyWriterTest.java
index 0fcdb744c244..f14ee934638f 100644
--- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/CopyWriterTest.java
+++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/CopyWriterTest.java
@@ -21,8 +21,8 @@
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.google.common.collect.ImmutableMap;
import com.google.gcloud.RestorableState;
@@ -33,10 +33,9 @@
import org.easymock.EasyMock;
import org.junit.After;
-import org.junit.Test;
import org.junit.Before;
+import org.junit.Test;
-import java.io.IOException;
import java.util.Map;
public class CopyWriterTest {
@@ -64,7 +63,7 @@ public class CopyWriterTest {
private CopyWriter copyWriter;
@Before
- public void setUp() throws IOException, InterruptedException {
+ public void setUp() {
rpcFactoryMock = createMock(StorageRpcFactory.class);
storageRpcMock = createMock(StorageRpc.class);
expect(rpcFactoryMock.create(anyObject(StorageOptions.class)))
@@ -105,7 +104,7 @@ public void testRewriteMultipleRequests() {
}
@Test
- public void testSaveAndRestore() throws IOException {
+ public void testSaveAndRestore() {
EasyMock.expect(storageRpcMock.continueRewrite(RESPONSE)).andReturn(RESPONSE);
EasyMock.expect(storageRpcMock.continueRewrite(RESPONSE)).andReturn(RESPONSE_DONE);
EasyMock.replay(storageRpcMock);
diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java
index 423e972a8de6..22b0a35c0620 100644
--- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java
+++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/ITStorageTest.java
@@ -19,11 +19,13 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import com.google.api.client.util.Lists;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gcloud.Page;
@@ -39,7 +41,6 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
@@ -48,9 +49,9 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -63,6 +64,7 @@ public class ITStorageTest {
private static final String CONTENT_TYPE = "text/plain";
private static final byte[] BLOB_BYTE_CONTENT = {0xD, 0xE, 0xA, 0xD};
private static final String BLOB_STRING_CONTENT = "Hello Google Cloud Storage!";
+ private static final int MAX_BATCH_DELETES = 100;
@BeforeClass
public static void beforeClass() {
@@ -72,8 +74,7 @@ public static void beforeClass() {
}
@AfterClass
- public static void afterClass()
- throws ExecutionException, TimeoutException, InterruptedException {
+ public static void afterClass() throws ExecutionException, InterruptedException {
if (storage != null && !RemoteGcsHelper.forceDelete(storage, BUCKET, 5, TimeUnit.SECONDS)) {
if (log.isLoggable(Level.WARNING)) {
log.log(Level.WARNING, "Deletion of bucket {0} timed out, bucket is not empty", BUCKET);
@@ -129,7 +130,8 @@ public void testCreateBlob() {
BlobInfo blob = BlobInfo.builder(BUCKET, blobName).build();
BlobInfo remoteBlob = storage.create(blob, BLOB_BYTE_CONTENT);
assertNotNull(remoteBlob);
- assertEquals(blob.blobId(), remoteBlob.blobId());
+ assertEquals(blob.bucket(), remoteBlob.bucket());
+ assertEquals(blob.name(), remoteBlob.name());
byte[] readBytes = storage.readAllBytes(BUCKET, blobName);
assertArrayEquals(BLOB_BYTE_CONTENT, readBytes);
assertTrue(storage.delete(BUCKET, blobName));
@@ -141,20 +143,22 @@ public void testCreateEmptyBlob() {
BlobInfo blob = BlobInfo.builder(BUCKET, blobName).build();
BlobInfo remoteBlob = storage.create(blob);
assertNotNull(remoteBlob);
- assertEquals(blob.blobId(), remoteBlob.blobId());
+ assertEquals(blob.bucket(), remoteBlob.bucket());
+ assertEquals(blob.name(), remoteBlob.name());
byte[] readBytes = storage.readAllBytes(BUCKET, blobName);
assertArrayEquals(new byte[0], readBytes);
assertTrue(storage.delete(BUCKET, blobName));
}
@Test
- public void testCreateBlobStream() throws UnsupportedEncodingException {
+ public void testCreateBlobStream() {
String blobName = "test-create-blob-stream";
BlobInfo blob = BlobInfo.builder(BUCKET, blobName).contentType(CONTENT_TYPE).build();
ByteArrayInputStream stream = new ByteArrayInputStream(BLOB_STRING_CONTENT.getBytes(UTF_8));
BlobInfo remoteBlob = storage.create(blob, stream);
assertNotNull(remoteBlob);
- assertEquals(blob.blobId(), remoteBlob.blobId());
+ assertEquals(blob.bucket(), remoteBlob.bucket());
+ assertEquals(blob.name(), remoteBlob.name());
assertEquals(blob.contentType(), remoteBlob.contentType());
byte[] readBytes = storage.readAllBytes(BUCKET, blobName);
assertEquals(BLOB_STRING_CONTENT, new String(readBytes, UTF_8));
@@ -166,8 +170,9 @@ public void testCreateBlobFail() {
String blobName = "test-create-blob-fail";
BlobInfo blob = BlobInfo.builder(BUCKET, blobName).build();
assertNotNull(storage.create(blob));
+ BlobInfo wrongGenerationBlob = BlobInfo.builder(BUCKET, blobName, -1L).build();
try {
- storage.create(blob.toBuilder().generation(-1L).build(), BLOB_BYTE_CONTENT,
+ storage.create(wrongGenerationBlob, BLOB_BYTE_CONTENT,
Storage.BlobTargetOption.generationMatch());
fail("StorageException was expected");
} catch (StorageException ex) {
@@ -177,7 +182,7 @@ public void testCreateBlobFail() {
}
@Test
- public void testCreateBlobMd5Fail() throws UnsupportedEncodingException {
+ public void testCreateBlobMd5Fail() {
String blobName = "test-create-blob-md5-fail";
BlobInfo blob = BlobInfo.builder(BUCKET, blobName)
.contentType(CONTENT_TYPE)
@@ -229,13 +234,39 @@ public void testGetBlobAllSelectedFields() {
assertNotNull(storage.create(blob));
BlobInfo remoteBlob = storage.get(blob.blobId(),
Storage.BlobGetOption.fields(BlobField.values()));
- assertEquals(blob.blobId(), remoteBlob.blobId());
+ assertEquals(blob.bucket(), remoteBlob.bucket());
+ assertEquals(blob.name(), remoteBlob.name());
assertEquals(ImmutableMap.of("k", "v"), remoteBlob.metadata());
assertNotNull(remoteBlob.id());
assertNotNull(remoteBlob.selfLink());
assertTrue(storage.delete(BUCKET, blobName));
}
+ @Test
+ public void testGetBlobFail() {
+ String blobName = "test-get-blob-fail";
+ BlobInfo blob = BlobInfo.builder(BUCKET, blobName).build();
+ assertNotNull(storage.create(blob));
+ BlobId wrongGenerationBlob = BlobId.of(BUCKET, blobName);
+ try {
+ storage.get(wrongGenerationBlob, Storage.BlobGetOption.generationMatch(-1));
+ fail("StorageException was expected");
+ } catch (StorageException ex) {
+ // expected
+ }
+ assertTrue(storage.delete(BUCKET, blobName));
+ }
+
+ @Test
+ public void testGetBlobFailNonExistingGeneration() {
+ String blobName = "test-get-blob-fail-non-existing-generation";
+ BlobInfo blob = BlobInfo.builder(BUCKET, blobName).build();
+ assertNotNull(storage.create(blob));
+ BlobId wrongGenerationBlob = BlobId.of(BUCKET, blobName, -1L);
+ assertNull(storage.get(wrongGenerationBlob));
+ assertTrue(storage.delete(BUCKET, blobName));
+ }
+
@Test
public void testListBlobsSelectedFields() {
String[] blobNames = {"test-list-blobs-selected-fields-blob1",
@@ -297,7 +328,8 @@ public void testUpdateBlob() {
assertNotNull(storage.create(blob));
BlobInfo updatedBlob = storage.update(blob.toBuilder().contentType(CONTENT_TYPE).build());
assertNotNull(updatedBlob);
- assertEquals(blob.blobId(), updatedBlob.blobId());
+ assertEquals(blob.name(), updatedBlob.name());
+ assertEquals(blob.bucket(), updatedBlob.bucket());
assertEquals(CONTENT_TYPE, updatedBlob.contentType());
assertTrue(storage.delete(BUCKET, blobName));
}
@@ -316,7 +348,8 @@ public void testUpdateBlobReplaceMetadata() {
assertNotNull(updatedBlob);
assertNull(updatedBlob.metadata());
updatedBlob = storage.update(blob.toBuilder().metadata(newMetadata).build());
- assertEquals(blob.blobId(), updatedBlob.blobId());
+ assertEquals(blob.name(), updatedBlob.name());
+ assertEquals(blob.bucket(), updatedBlob.bucket());
assertEquals(newMetadata, updatedBlob.metadata());
assertTrue(storage.delete(BUCKET, blobName));
}
@@ -334,7 +367,8 @@ public void testUpdateBlobMergeMetadata() {
assertNotNull(storage.create(blob));
BlobInfo updatedBlob = storage.update(blob.toBuilder().metadata(newMetadata).build());
assertNotNull(updatedBlob);
- assertEquals(blob.blobId(), updatedBlob.blobId());
+ assertEquals(blob.name(), updatedBlob.name());
+ assertEquals(blob.bucket(), updatedBlob.bucket());
assertEquals(expectedMetadata, updatedBlob.metadata());
assertTrue(storage.delete(BUCKET, blobName));
}
@@ -354,7 +388,8 @@ public void testUpdateBlobUnsetMetadata() {
assertNotNull(storage.create(blob));
BlobInfo updatedBlob = storage.update(blob.toBuilder().metadata(newMetadata).build());
assertNotNull(updatedBlob);
- assertEquals(blob.blobId(), updatedBlob.blobId());
+ assertEquals(blob.name(), updatedBlob.name());
+ assertEquals(blob.bucket(), updatedBlob.bucket());
assertEquals(expectedMetadata, updatedBlob.metadata());
assertTrue(storage.delete(BUCKET, blobName));
}
@@ -364,9 +399,11 @@ public void testUpdateBlobFail() {
String blobName = "test-update-blob-fail";
BlobInfo blob = BlobInfo.builder(BUCKET, blobName).build();
assertNotNull(storage.create(blob));
+ BlobInfo wrongGenerationBlob = BlobInfo.builder(BUCKET, blobName, -1L)
+ .contentType(CONTENT_TYPE)
+ .build();
try {
- storage.update(blob.toBuilder().contentType(CONTENT_TYPE).generation(-1L).build(),
- Storage.BlobTargetOption.generationMatch());
+ storage.update(wrongGenerationBlob, Storage.BlobTargetOption.generationMatch());
fail("StorageException was expected");
} catch (StorageException ex) {
// expected
@@ -380,6 +417,14 @@ public void testDeleteNonExistingBlob() {
assertTrue(!storage.delete(BUCKET, blobName));
}
+ @Test
+ public void testDeleteBlobNonExistingGeneration() {
+ String blobName = "test-delete-blob-non-existing-generation";
+ BlobInfo blob = BlobInfo.builder(BUCKET, blobName).build();
+ assertNotNull(storage.create(blob));
+ assertTrue(!storage.delete(BlobId.of(BUCKET, blobName, -1L)));
+ }
+
@Test
public void testDeleteBlobFail() {
String blobName = "test-delete-blob-fail";
@@ -408,7 +453,8 @@ public void testComposeBlob() {
Storage.ComposeRequest.of(ImmutableList.of(sourceBlobName1, sourceBlobName2), targetBlob);
BlobInfo remoteBlob = storage.compose(req);
assertNotNull(remoteBlob);
- assertEquals(targetBlob.blobId(), remoteBlob.blobId());
+ assertEquals(targetBlob.name(), remoteBlob.name());
+ assertEquals(targetBlob.bucket(), remoteBlob.bucket());
byte[] readBytes = storage.readAllBytes(BUCKET, targetBlobName);
byte[] composedBytes = Arrays.copyOf(BLOB_BYTE_CONTENT, BLOB_BYTE_CONTENT.length * 2);
System.arraycopy(BLOB_BYTE_CONTENT, 0, composedBytes, BLOB_BYTE_CONTENT.length,
@@ -491,12 +537,12 @@ public void testCopyBlobUpdateMetadata() {
@Test
public void testCopyBlobFail() {
String sourceBlobName = "test-copy-blob-source-fail";
- BlobId source = BlobId.of(BUCKET, sourceBlobName);
+ BlobId source = BlobId.of(BUCKET, sourceBlobName, -1L);
assertNotNull(storage.create(BlobInfo.builder(source).build(), BLOB_BYTE_CONTENT));
String targetBlobName = "test-copy-blob-target-fail";
BlobInfo target = BlobInfo.builder(BUCKET, targetBlobName).contentType(CONTENT_TYPE).build();
Storage.CopyRequest req = Storage.CopyRequest.builder()
- .source(source)
+ .source(BUCKET, sourceBlobName)
.sourceOptions(Storage.BlobSourceOption.generationMatch(-1L))
.target(target)
.build();
@@ -506,6 +552,17 @@ public void testCopyBlobFail() {
} catch (StorageException ex) {
// expected
}
+ Storage.CopyRequest req2 = Storage.CopyRequest.builder()
+ .source(source)
+ .sourceOptions(Storage.BlobSourceOption.generationMatch())
+ .target(target)
+ .build();
+ try {
+ storage.copy(req2);
+ fail("StorageException was expected");
+ } catch (StorageException ex) {
+ // expected
+ }
assertTrue(storage.delete(BUCKET, sourceBlobName));
}
@@ -531,8 +588,10 @@ public void testBatchRequest() {
assertEquals(0, updateResponse.gets().size());
BlobInfo remoteUpdatedBlob1 = updateResponse.updates().get(0).get();
BlobInfo remoteUpdatedBlob2 = updateResponse.updates().get(1).get();
- assertEquals(sourceBlob1.blobId(), remoteUpdatedBlob1.blobId());
- assertEquals(sourceBlob2.blobId(), remoteUpdatedBlob2.blobId());
+ assertEquals(sourceBlob1.bucket(), remoteUpdatedBlob1.bucket());
+ assertEquals(sourceBlob1.name(), remoteUpdatedBlob1.name());
+ assertEquals(sourceBlob2.bucket(), remoteUpdatedBlob2.bucket());
+ assertEquals(sourceBlob2.name(), remoteUpdatedBlob2.name());
assertEquals(updatedBlob1.contentType(), remoteUpdatedBlob1.contentType());
assertEquals(updatedBlob2.contentType(), remoteUpdatedBlob2.contentType());
@@ -563,24 +622,78 @@ public void testBatchRequest() {
assertTrue(deleteResponse.deletes().get(1).get());
}
+ @Test
+ public void testBatchRequestManyDeletes() {
+ List blobsToDelete = Lists.newArrayListWithCapacity(2 * MAX_BATCH_DELETES);
+ for (int i = 0; i < 2 * MAX_BATCH_DELETES; i++) {
+ blobsToDelete.add(BlobId.of(BUCKET, "test-batch-request-many-deletes-blob-" + i));
+ }
+ BatchRequest.Builder builder = BatchRequest.builder();
+ for (BlobId blob : blobsToDelete) {
+ builder.delete(blob);
+ }
+ String sourceBlobName1 = "test-batch-request-many-deletes-source-blob-1";
+ String sourceBlobName2 = "test-batch-request-many-deletes-source-blob-2";
+ BlobInfo sourceBlob1 = BlobInfo.builder(BUCKET, sourceBlobName1).build();
+ BlobInfo sourceBlob2 = BlobInfo.builder(BUCKET, sourceBlobName2).build();
+ assertNotNull(storage.create(sourceBlob1));
+ assertNotNull(storage.create(sourceBlob2));
+ BlobInfo updatedBlob2 = sourceBlob2.toBuilder().contentType(CONTENT_TYPE).build();
+
+ BatchRequest updateRequest = builder
+ .get(BUCKET, sourceBlobName1)
+ .update(updatedBlob2)
+ .build();
+ BatchResponse response = storage.apply(updateRequest);
+ assertEquals(2 * MAX_BATCH_DELETES, response.deletes().size());
+ assertEquals(1, response.updates().size());
+ assertEquals(1, response.gets().size());
+
+ // Check deletes
+ for (BatchResponse.Result deleteResult : response.deletes()) {
+ assertFalse(deleteResult.failed());
+ assertFalse(deleteResult.get());
+ }
+
+ // Check updates
+ BlobInfo remoteUpdatedBlob2 = response.updates().get(0).get();
+ assertEquals(sourceBlob2.bucket(), remoteUpdatedBlob2.bucket());
+ assertEquals(sourceBlob2.name(), remoteUpdatedBlob2.name());
+ assertEquals(updatedBlob2.contentType(), remoteUpdatedBlob2.contentType());
+
+ // Check gets
+ BlobInfo remoteBlob1 = response.gets().get(0).get();
+ assertEquals(sourceBlob1.bucket(), remoteBlob1.bucket());
+ assertEquals(sourceBlob1.name(), remoteBlob1.name());
+
+ assertTrue(storage.delete(BUCKET, sourceBlobName1));
+ assertTrue(storage.delete(BUCKET, sourceBlobName2));
+ }
+
@Test
public void testBatchRequestFail() {
String blobName = "test-batch-request-blob-fail";
BlobInfo blob = BlobInfo.builder(BUCKET, blobName).build();
assertNotNull(storage.create(blob));
- BlobInfo updatedBlob = blob.toBuilder().generation(-1L).build();
+ BlobInfo updatedBlob = BlobInfo.builder(BUCKET, blobName, -1L).build();
BatchRequest batchRequest = BatchRequest.builder()
.update(updatedBlob, Storage.BlobTargetOption.generationMatch())
.delete(BUCKET, blobName, Storage.BlobSourceOption.generationMatch(-1L))
+ .delete(BlobId.of(BUCKET, blobName, -1L))
.get(BUCKET, blobName, Storage.BlobGetOption.generationMatch(-1L))
+ .get(BlobId.of(BUCKET, blobName, -1L))
.build();
- BatchResponse updateResponse = storage.apply(batchRequest);
- assertEquals(1, updateResponse.updates().size());
- assertEquals(1, updateResponse.deletes().size());
- assertEquals(1, updateResponse.gets().size());
- assertTrue(updateResponse.updates().get(0).failed());
- assertTrue(updateResponse.gets().get(0).failed());
- assertTrue(updateResponse.deletes().get(0).failed());
+ BatchResponse batchResponse = storage.apply(batchRequest);
+ assertEquals(1, batchResponse.updates().size());
+ assertEquals(2, batchResponse.deletes().size());
+ assertEquals(2, batchResponse.gets().size());
+ assertTrue(batchResponse.updates().get(0).failed());
+ assertTrue(batchResponse.gets().get(0).failed());
+ assertFalse(batchResponse.gets().get(1).failed());
+ assertNull(batchResponse.gets().get(1).get());
+ assertTrue(batchResponse.deletes().get(0).failed());
+ assertFalse(batchResponse.deletes().get(1).failed());
+ assertFalse(batchResponse.deletes().get(1).get());
assertTrue(storage.delete(BUCKET, blobName));
}
@@ -648,13 +761,63 @@ public void testReadChannelFail() throws IOException {
} catch (StorageException ex) {
// expected
}
+ try (BlobReadChannel reader =
+ storage.reader(blob.blobId(), Storage.BlobSourceOption.generationMatch(-1L))) {
+ reader.read(ByteBuffer.allocate(42));
+ fail("StorageException was expected");
+ } catch (StorageException ex) {
+ // expected
+ }
+ BlobId blobIdWrongGeneration = BlobId.of(BUCKET, blobName, -1L);
+ try (BlobReadChannel reader =
+ storage.reader(blobIdWrongGeneration, Storage.BlobSourceOption.generationMatch())) {
+ reader.read(ByteBuffer.allocate(42));
+ fail("StorageException was expected");
+ } catch (StorageException ex) {
+ // expected
+ }
+ assertTrue(storage.delete(BUCKET, blobName));
+ }
+
+ @Test
+ public void testReadChannelFailUpdatedGeneration() throws IOException {
+ String blobName = "test-read-blob-fail-updated-generation";
+ BlobInfo blob = BlobInfo.builder(BUCKET, blobName).build();
+ Random random = new Random();
+ int chunkSize = 1024;
+ int blobSize = 2 * chunkSize;
+ byte[] content = new byte[blobSize];
+ random.nextBytes(content);
+ BlobInfo remoteBlob = storage.create(blob, content);
+ assertNotNull(remoteBlob);
+ assertEquals(blobSize, (long) remoteBlob.size());
+ try (BlobReadChannel reader = storage.reader(blob.blobId())) {
+ reader.chunkSize(chunkSize);
+ ByteBuffer readBytes = ByteBuffer.allocate(chunkSize);
+ int numReadBytes = reader.read(readBytes);
+ assertEquals(chunkSize, numReadBytes);
+ assertArrayEquals(Arrays.copyOf(content, chunkSize), readBytes.array());
+ try (BlobWriteChannel writer = storage.writer(blob)) {
+ byte[] newContent = new byte[blobSize];
+ random.nextBytes(newContent);
+ int numWrittenBytes = writer.write(ByteBuffer.wrap(newContent));
+ assertEquals(blobSize, numWrittenBytes);
+ }
+ readBytes = ByteBuffer.allocate(chunkSize);
+ reader.read(readBytes);
+ fail("StorageException was expected");
+ } catch (StorageException ex) {
+ StringBuilder messageBuilder = new StringBuilder();
+ messageBuilder.append("Blob ").append(blob.blobId()).append(" was updated while reading");
+ assertEquals(messageBuilder.toString(), ex.getMessage());
+ }
assertTrue(storage.delete(BUCKET, blobName));
}
@Test
public void testWriteChannelFail() throws IOException {
String blobName = "test-write-channel-blob-fail";
- BlobInfo blob = BlobInfo.builder(BUCKET, blobName).generation(-1L).build();
+ BlobInfo blob = BlobInfo.builder(BUCKET, blobName, -1L).build();
try {
try (BlobWriteChannel writer =
storage.writer(blob, Storage.BlobWriteOption.generationMatch())) {
@@ -707,7 +870,8 @@ public void testPostSignedUrl() throws IOException {
connection.connect();
BlobInfo remoteBlob = storage.get(BUCKET, blobName);
assertNotNull(remoteBlob);
- assertEquals(blob.blobId(), remoteBlob.blobId());
+ assertEquals(blob.bucket(), remoteBlob.bucket());
+ assertEquals(blob.name(), remoteBlob.name());
assertTrue(storage.delete(BUCKET, blobName));
}
@@ -720,8 +884,10 @@ public void testGetBlobs() {
assertNotNull(storage.create(sourceBlob1));
assertNotNull(storage.create(sourceBlob2));
List remoteBlobs = storage.get(sourceBlob1.blobId(), sourceBlob2.blobId());
- assertEquals(sourceBlob1.blobId(), remoteBlobs.get(0).blobId());
- assertEquals(sourceBlob2.blobId(), remoteBlobs.get(1).blobId());
+ assertEquals(sourceBlob1.bucket(), remoteBlobs.get(0).bucket());
+ assertEquals(sourceBlob1.name(), remoteBlobs.get(0).name());
+ assertEquals(sourceBlob2.bucket(), remoteBlobs.get(1).bucket());
+ assertEquals(sourceBlob2.name(), remoteBlobs.get(1).name());
assertTrue(storage.delete(BUCKET, sourceBlobName1));
assertTrue(storage.delete(BUCKET, sourceBlobName2));
}
@@ -734,7 +900,8 @@ public void testGetBlobsFail() {
BlobInfo sourceBlob2 = BlobInfo.builder(BUCKET, sourceBlobName2).build();
assertNotNull(storage.create(sourceBlob1));
List remoteBlobs = storage.get(sourceBlob1.blobId(), sourceBlob2.blobId());
- assertEquals(sourceBlob1.blobId(), remoteBlobs.get(0).blobId());
+ assertEquals(sourceBlob1.bucket(), remoteBlobs.get(0).bucket());
+ assertEquals(sourceBlob1.name(), remoteBlobs.get(0).name());
assertNull(remoteBlobs.get(1));
assertTrue(storage.delete(BUCKET, sourceBlobName1));
}
@@ -777,9 +944,11 @@ public void testUpdateBlobs() {
List updatedBlobs = storage.update(
remoteBlob1.toBuilder().contentType(CONTENT_TYPE).build(),
remoteBlob2.toBuilder().contentType(CONTENT_TYPE).build());
- assertEquals(sourceBlob1.blobId(), updatedBlobs.get(0).blobId());
+ assertEquals(sourceBlob1.bucket(), updatedBlobs.get(0).bucket());
+ assertEquals(sourceBlob1.name(), updatedBlobs.get(0).name());
assertEquals(CONTENT_TYPE, updatedBlobs.get(0).contentType());
- assertEquals(sourceBlob2.blobId(), updatedBlobs.get(1).blobId());
+ assertEquals(sourceBlob2.bucket(), updatedBlobs.get(1).bucket());
+ assertEquals(sourceBlob2.name(), updatedBlobs.get(1).name());
assertEquals(CONTENT_TYPE, updatedBlobs.get(1).contentType());
assertTrue(storage.delete(BUCKET, sourceBlobName1));
assertTrue(storage.delete(BUCKET, sourceBlobName2));
@@ -796,7 +965,8 @@ public void testUpdateBlobsFail() {
List updatedBlobs = storage.update(
remoteBlob1.toBuilder().contentType(CONTENT_TYPE).build(),
sourceBlob2.toBuilder().contentType(CONTENT_TYPE).build());
- assertEquals(sourceBlob1.blobId(), updatedBlobs.get(0).blobId());
+ assertEquals(sourceBlob1.bucket(), updatedBlobs.get(0).bucket());
+ assertEquals(sourceBlob1.name(), updatedBlobs.get(0).name());
assertEquals(CONTENT_TYPE, updatedBlobs.get(0).contentType());
assertNull(updatedBlobs.get(1));
assertTrue(storage.delete(BUCKET, sourceBlobName1));
diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java
index ff6fd68fd1eb..3c3d1aebb3df 100644
--- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java
+++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/RemoteGcsHelperTest.java
@@ -33,6 +33,7 @@
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
@@ -90,6 +91,11 @@ public Page nextPage() {
public Iterable values() {
return BLOB_LIST;
}
+
+ @Override
+ public Iterator iterateAll() {
+ return BLOB_LIST.iterator();
+ }
};
private static String keyPath = "/does/not/exist/key." + UUID.randomUUID().toString() + ".json";
@@ -153,11 +159,11 @@ public void testCreateFromStream() {
assertEquals(PROJECT_ID, options.projectId());
assertEquals(60000, options.connectTimeout());
assertEquals(60000, options.readTimeout());
- assertEquals(10, options.retryParams().getRetryMaxAttempts());
- assertEquals(6, options.retryParams().getRetryMinAttempts());
- assertEquals(30000, options.retryParams().getMaxRetryDelayMillis());
- assertEquals(120000, options.retryParams().getTotalRetryPeriodMillis());
- assertEquals(250, options.retryParams().getInitialRetryDelayMillis());
+ assertEquals(10, options.retryParams().retryMaxAttempts());
+ assertEquals(6, options.retryParams().retryMinAttempts());
+ assertEquals(30000, options.retryParams().maxRetryDelayMillis());
+ assertEquals(120000, options.retryParams().totalRetryPeriodMillis());
+ assertEquals(250, options.retryParams().initialRetryDelayMillis());
}
@Test
diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java
index a125a64df6d6..555e231f7f0e 100644
--- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java
+++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/SerializationTest.java
@@ -82,8 +82,8 @@ public void testServiceOptions() throws Exception {
options = options.toBuilder()
.projectId("p2")
- .retryParams(RetryParams.getDefaultInstance())
- .authCredentials(AuthCredentials.noCredentials())
+ .retryParams(RetryParams.defaultInstance())
+ .authCredentials(null)
.pathDelimiter(":")
.build();
serializedCopy = serializeAndDeserialize(options);
@@ -110,8 +110,7 @@ public void testModelAndRequests() throws Exception {
public void testReadChannelState() throws IOException, ClassNotFoundException {
StorageOptions options = StorageOptions.builder()
.projectId("p2")
- .retryParams(RetryParams.getDefaultInstance())
- .authCredentials(AuthCredentials.noCredentials())
+ .retryParams(RetryParams.defaultInstance())
.build();
BlobReadChannel reader =
new BlobReadChannelImpl(options, BlobId.of("b", "n"), EMPTY_RPC_OPTIONS);
@@ -120,15 +119,17 @@ public void testReadChannelState() throws IOException, ClassNotFoundException {
assertEquals(state, deserializedState);
assertEquals(state.hashCode(), deserializedState.hashCode());
assertEquals(state.toString(), deserializedState.toString());
+ reader.close();
}
@Test
public void testWriteChannelState() throws IOException, ClassNotFoundException {
StorageOptions options = StorageOptions.builder()
.projectId("p2")
- .retryParams(RetryParams.getDefaultInstance())
- .authCredentials(AuthCredentials.noCredentials())
+ .retryParams(RetryParams.defaultInstance())
.build();
+ // avoid closing when you don't want partial writes to GCS upon failure
+ @SuppressWarnings("resource")
BlobWriteChannelImpl writer = new BlobWriteChannelImpl(
options, BlobInfo.builder(BlobId.of("b", "n")).build(), "upload-id");
RestorableState state = writer.capture();
diff --git a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java
index d5e2f8de7397..dea635c3d264 100644
--- a/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java
+++ b/gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java
@@ -31,11 +31,10 @@
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.io.BaseEncoding;
-import com.google.gcloud.AuthCredentials;
import com.google.gcloud.AuthCredentials.ServiceAccountAuthCredentials;
+import com.google.gcloud.Page;
import com.google.gcloud.RetryParams;
import com.google.gcloud.ServiceOptions;
-import com.google.gcloud.Page;
import com.google.gcloud.spi.StorageRpc;
import com.google.gcloud.spi.StorageRpc.Tuple;
import com.google.gcloud.spi.StorageRpcFactory;
@@ -89,8 +88,8 @@ public class StorageImplTest {
private static final BucketInfo BUCKET_INFO2 = BucketInfo.builder(BUCKET_NAME2).build();
// BlobInfo objects
- private static final BlobInfo BLOB_INFO1 = BlobInfo.builder(BUCKET_NAME1, BLOB_NAME1)
- .metageneration(42L).generation(24L).contentType("application/json").md5("md5string").build();
+ private static final BlobInfo BLOB_INFO1 = BlobInfo.builder(BUCKET_NAME1, BLOB_NAME1, 24L)
+ .metageneration(42L).contentType("application/json").md5("md5string").build();
private static final BlobInfo BLOB_INFO2 = BlobInfo.builder(BUCKET_NAME1, BLOB_NAME2).build();
private static final BlobInfo BLOB_INFO3 = BlobInfo.builder(BUCKET_NAME1, BLOB_NAME3).build();
@@ -157,6 +156,8 @@ public class StorageImplTest {
Storage.BlobGetOption.metagenerationMatch(BLOB_INFO1.metageneration());
private static final Storage.BlobGetOption BLOB_GET_GENERATION =
Storage.BlobGetOption.generationMatch(BLOB_INFO1.generation());
+ private static final Storage.BlobGetOption BLOB_GET_GENERATION_FROM_BLOB_ID =
+ Storage.BlobGetOption.generationMatch();
private static final Storage.BlobGetOption BLOB_GET_FIELDS =
Storage.BlobGetOption.fields(Storage.BlobField.CONTENT_TYPE, Storage.BlobField.CRC32C);
private static final Storage.BlobGetOption BLOB_GET_EMPTY_FIELDS =
@@ -168,6 +169,8 @@ public class StorageImplTest {
Storage.BlobSourceOption.metagenerationMatch(BLOB_INFO1.metageneration());
private static final Storage.BlobSourceOption BLOB_SOURCE_GENERATION =
Storage.BlobSourceOption.generationMatch(BLOB_INFO1.generation());
+ private static final Storage.BlobSourceOption BLOB_SOURCE_GENERATION_FROM_BLOB_ID =
+ Storage.BlobSourceOption.generationMatch();
private static final Map BLOB_SOURCE_OPTIONS = ImmutableMap.of(
StorageRpc.Option.IF_METAGENERATION_MATCH, BLOB_SOURCE_METAGENERATION.value(),
StorageRpc.Option.IF_GENERATION_MATCH, BLOB_SOURCE_GENERATION.value());
@@ -248,7 +251,7 @@ public static void beforeClass() throws NoSuchAlgorithmException, InvalidKeySpec
}
@Before
- public void setUp() throws IOException, InterruptedException {
+ public void setUp() {
rpcFactoryMock = EasyMock.createMock(StorageRpcFactory.class);
storageRpcMock = EasyMock.createMock(StorageRpc.class);
EasyMock.expect(rpcFactoryMock.create(EasyMock.anyObject(StorageOptions.class)))
@@ -256,7 +259,6 @@ public void setUp() throws IOException, InterruptedException {
EasyMock.replay(rpcFactoryMock);
options = StorageOptions.builder()
.projectId("projectId")
- .authCredentials(AuthCredentials.noCredentials())
.clock(TIME_SOURCE)
.serviceRpcFactory(rpcFactoryMock)
.build();
@@ -361,7 +363,7 @@ public void testCreateBlobWithOptions() throws IOException {
}
@Test
- public void testCreateBlobFromStream() throws IOException {
+ public void testCreateBlobFromStream() {
ByteArrayInputStream fileStream = new ByteArrayInputStream(BLOB_CONTENT);
BlobInfo.Builder infoBuilder = BLOB_INFO1.toBuilder();
BlobInfo infoWithHashes = infoBuilder.md5(CONTENT_MD5).crc32c(CONTENT_CRC32C).build();
@@ -454,6 +456,18 @@ public void testGetBlobWithOptions() {
assertEquals(BLOB_INFO1, blob);
}
+ @Test
+ public void testGetBlobWithOptionsFromBlobId() {
+ EasyMock.expect(
+ storageRpcMock.get(BLOB_INFO1.blobId().toPb(), BLOB_GET_OPTIONS))
+ .andReturn(BLOB_INFO1.toPb());
+ EasyMock.replay(storageRpcMock);
+ storage = options.service();
+ BlobInfo blob =
+ storage.get(BLOB_INFO1.blobId(), BLOB_GET_METAGENERATION, BLOB_GET_GENERATION_FROM_BLOB_ID);
+ assertEquals(BLOB_INFO1, blob);
+ }
+
@Test
public void testGetBlobWithSelectedFields() {
Capture