Skip to content

Commit cf65536

Browse files
authored
fix: update FakeStorageRpc to better handle resumable sessions that overwrite existing objects (#1296)
1 parent 55da5e1 commit cf65536

2 files changed

Lines changed: 74 additions & 3 deletions

File tree

java-storage-nio/google-cloud-nio/src/main/java/com/google/cloud/storage/contrib/nio/testing/FakeStorageRpc.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ public String open(StorageObject object, Map<Option, ?> options) throws StorageE
356356
checkGeneration(key, generationMatch);
357357
metadata.put(key, object);
358358

359-
return fullname(object);
359+
return key;
360360
}
361361

362362
@Override
@@ -613,11 +613,12 @@ public MockLowLevelHttpResponse getResponse() {
613613
try {
614614
ByteArrayOutputStream baos = new ByteArrayOutputStream();
615615
this.getStreamingContent().writeTo(baos);
616+
bytes = futureContents.get(key);
616617
byte[] byteArray = baos.toByteArray();
617618
if (storageObject.getGeneration() != null) {
618-
contents.put(key, concat(bytes, byteArray));
619+
futureContents.put(key, concat(bytes, byteArray));
619620
} else {
620-
contents.put(key, byteArray);
621+
futureContents.put(key, byteArray);
621622
}
622623

623624
List<String> contentRanges = getHeaders().get("content-range");
@@ -637,6 +638,8 @@ public MockLowLevelHttpResponse getResponse() {
637638
resp.addHeader("Content-Type", "application/json;charset=utf-8");
638639
resp.addHeader("Content-Length", String.valueOf(string.length()));
639640
resp.setContent(string);
641+
contents.put(key, byteArray);
642+
futureContents.remove(key);
640643
} else {
641644
resp.setStatusCode(NOT_FOUND);
642645
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.google.cloud.storage.contrib.nio.testing;
17+
18+
import static com.google.common.truth.Truth.assertThat;
19+
20+
import com.google.cloud.WriteChannel;
21+
import com.google.cloud.storage.Blob;
22+
import com.google.cloud.storage.BlobId;
23+
import com.google.cloud.storage.BlobInfo;
24+
import com.google.cloud.storage.Storage;
25+
import com.google.cloud.storage.Storage.BlobWriteOption;
26+
import com.google.cloud.storage.StorageOptions;
27+
import com.google.cloud.storage.contrib.nio.testing.LocalStorageHelper.FakeStorageRpcFactory;
28+
import java.io.IOException;
29+
import java.nio.ByteBuffer;
30+
import java.nio.charset.StandardCharsets;
31+
import org.junit.Test;
32+
33+
public final class FakeStorageRpcTest {
34+
35+
@Test
36+
public void overwritingAnObjectOverwritesItsContent() throws IOException {
37+
Storage storage =
38+
StorageOptions.http()
39+
.setServiceRpcFactory(new FakeStorageRpcFactory())
40+
.build()
41+
.getService();
42+
43+
try (WriteChannel writer =
44+
storage.writer(
45+
BlobInfo.newBuilder(BlobId.of("bucket", "obj", 0L)).build(),
46+
BlobWriteOption.generationMatch())) {
47+
writer.write(ByteBuffer.wrap("abc".getBytes(StandardCharsets.UTF_8)));
48+
}
49+
Blob gen1 = storage.get(BlobId.of("bucket", "obj"));
50+
// get existing generation
51+
String gen1read1 = new String(gen1.getContent(), StandardCharsets.UTF_8);
52+
assertThat(gen1read1).isEqualTo("abc");
53+
System.out.println("gen1read1 = " + gen1read1);
54+
55+
// start an upload that will overwrite the existing generation
56+
WriteChannel writer = storage.writer(gen1, BlobWriteOption.generationMatch());
57+
writer.write(ByteBuffer.wrap("def".getBytes(StandardCharsets.UTF_8)));
58+
// make sure we can still read the existing generations value after starting but before closing
59+
String gen1read2 = new String(gen1.getContent(), StandardCharsets.UTF_8);
60+
assertThat(gen1read2).isEqualTo("abc");
61+
writer.close();
62+
63+
Blob gen2 = storage.get(BlobId.of("bucket", "obj"));
64+
String gen2read1 = new String(gen2.getContent(), StandardCharsets.UTF_8);
65+
System.out.println("gen2read1 = " + gen2read1);
66+
assertThat(gen2read1).isEqualTo("def");
67+
}
68+
}

0 commit comments

Comments
 (0)