Skip to content

Commit 80438da

Browse files
committed
Fix BlobListOption.recursive, add tests and documentation
1 parent 926831e commit 80438da

File tree

4 files changed

+68
-4
lines changed

4 files changed

+68
-4
lines changed

gcloud-java-storage/src/main/java/com/google/gcloud/storage/Storage.java

+4
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,10 @@ public static BlobListOption prefix(String prefix) {
695695

696696
/**
697697
* Returns an option to specify whether blob listing should include subdirectories or not.
698+
* {@link StorageOptions#pathDelimiter()} is used as a path delimiter. If set to {@code true}
699+
* also blobs in subdirectories are listed. If set to {@code false} and used in combination
700+
* with {@link #prefix(String)} only blobs in a directory can be listed. If not set also blobs
701+
* in subdirectories are listed.
698702
*/
699703
public static BlobListOption recursive(boolean recursive) {
700704
return new BlobListOption(StorageRpc.Option.DELIMITER, recursive);

gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ private static <T> void addToOptionMap(StorageRpc.Option getOption, StorageRpc.O
668668
checkArgument(prev == null, "Duplicate option %s", option);
669669
}
670670
Boolean value = (Boolean) temp.remove(DELIMITER);
671-
if (Boolean.TRUE.equals(value)) {
671+
if (Boolean.FALSE.equals(value)) {
672672
temp.put(DELIMITER, options().pathDelimiter());
673673
}
674674
if (useAsSource) {

gcloud-java-storage/src/main/java/com/google/gcloud/storage/StorageOptions.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ protected Set<String> scopes() {
107107
}
108108

109109
/**
110-
* Returns the storage service's path delimiter.
110+
* Returns the storage service's path delimiter. If not set, {@code "/"} is used.
111111
*/
112112
public String pathDelimiter() {
113113
return pathDelimiter;

gcloud-java-storage/src/test/java/com/google/gcloud/storage/StorageImplTest.java

+62-2
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ public long millis() {
241241
private StorageRpc storageRpcMock;
242242
private Storage storage;
243243

244-
private Blob expectedBlob1, expectedBlob2, expectedBlob3;
244+
private Blob expectedBlob1, expectedBlob2;
245245
private Bucket expectedBucket1, expectedBucket2;
246246

247247
@Rule
@@ -286,7 +286,6 @@ private void initializeService() {
286286
private void initializeServiceDependentObjects() {
287287
expectedBlob1 = new Blob(storage, new BlobInfo.BuilderImpl(BLOB_INFO1));
288288
expectedBlob2 = new Blob(storage, new BlobInfo.BuilderImpl(BLOB_INFO2));
289-
expectedBlob3 = new Blob(storage, new BlobInfo.BuilderImpl(BLOB_INFO3));
290289
expectedBucket1 = new Bucket(storage, new BucketInfo.BuilderImpl(BUCKET_INFO1));
291290
expectedBucket2 = new Bucket(storage, new BucketInfo.BuilderImpl(BUCKET_INFO2));
292291
}
@@ -659,6 +658,67 @@ public void testListBlobsWithOptions() {
659658
assertArrayEquals(blobList.toArray(), Iterables.toArray(page.values(), Blob.class));
660659
}
661660

661+
@Test
662+
public void testListBlobsWithDelimiter() {
663+
String cursor = "cursor";
664+
Map<StorageRpc.Option, ?> options = ImmutableMap.of(StorageRpc.Option.DELIMITER, "/");
665+
ImmutableList<BlobInfo> blobInfoList = ImmutableList.of(BLOB_INFO1, BLOB_INFO2);
666+
Tuple<String, Iterable<com.google.api.services.storage.model.StorageObject>> result =
667+
Tuple.of(cursor, Iterables.transform(blobInfoList, BlobInfo.INFO_TO_PB_FUNCTION));
668+
EasyMock.expect(storageRpcMock.list(BUCKET_NAME1, options)).andReturn(result);
669+
EasyMock.replay(storageRpcMock);
670+
initializeService();
671+
ImmutableList<Blob> blobList = ImmutableList.of(expectedBlob1, expectedBlob2);
672+
Page<Blob> page = storage.list(BUCKET_NAME1, Storage.BlobListOption.recursive(false));
673+
assertEquals(cursor, page.nextPageCursor());
674+
assertArrayEquals(blobList.toArray(), Iterables.toArray(page.values(), Blob.class));
675+
}
676+
677+
678+
@Test
679+
public void testListBlobsWithNoDelimiter() {
680+
String cursor = "cursor";
681+
ImmutableList<BlobInfo> blobInfoList = ImmutableList.of(BLOB_INFO1, BLOB_INFO2);
682+
Tuple<String, Iterable<com.google.api.services.storage.model.StorageObject>> result =
683+
Tuple.of(cursor, Iterables.transform(blobInfoList, BlobInfo.INFO_TO_PB_FUNCTION));
684+
EasyMock.expect(storageRpcMock.list(BUCKET_NAME1, EMPTY_RPC_OPTIONS))
685+
.andReturn(result);
686+
EasyMock.replay(storageRpcMock);
687+
initializeService();
688+
ImmutableList<Blob> blobList = ImmutableList.of(expectedBlob1, expectedBlob2);
689+
Page<Blob> page = storage.list(BUCKET_NAME1, Storage.BlobListOption.recursive(true));
690+
assertEquals(cursor, page.nextPageCursor());
691+
assertArrayEquals(blobList.toArray(), Iterables.toArray(page.values(), Blob.class));
692+
}
693+
694+
@Test
695+
public void testListBlobsWithCustomDelimiter() {
696+
StorageRpcFactory factoryMock = EasyMock.createMock(StorageRpcFactory.class);
697+
StorageRpc rpcMock = EasyMock.createMock(StorageRpc.class);
698+
EasyMock.expect(factoryMock.create(EasyMock.anyObject(StorageOptions.class)))
699+
.andReturn(rpcMock);
700+
EasyMock.replay(factoryMock);
701+
EasyMock.replay(storageRpcMock);
702+
initializeService();
703+
Storage storage = StorageOptions.builder()
704+
.projectId("projectId")
705+
.pathDelimiter("-")
706+
.clock(TIME_SOURCE)
707+
.serviceRpcFactory(factoryMock)
708+
.retryParams(RetryParams.noRetries())
709+
.build()
710+
.service();
711+
Map<StorageRpc.Option, ?> options = ImmutableMap.of(StorageRpc.Option.DELIMITER, "-");
712+
EasyMock.expect(rpcMock.list(BUCKET_NAME1, options))
713+
.andReturn(Tuple.<String, Iterable<com.google.api.services.storage.model.StorageObject>>of(
714+
null, null));
715+
EasyMock.replay(rpcMock);
716+
Page<Blob> page = storage.list(BUCKET_NAME1, Storage.BlobListOption.recursive(false));
717+
assertNull(page.nextPageCursor());
718+
assertArrayEquals(ImmutableList.of().toArray(), Iterables.toArray(page.values(), Blob.class));
719+
EasyMock.verify(factoryMock, rpcMock);
720+
}
721+
662722
@Test
663723
public void testListBlobsWithSelectedFields() {
664724
String cursor = "cursor";

0 commit comments

Comments
 (0)