1818
1919import static com .google .common .truth .Truth .assertThat ;
2020
21- import com .google .cloud .NoCredentials ;
2221import com .google .cloud .ReadChannel ;
2322import com .google .cloud .WriteChannel ;
23+ import com .google .cloud .storage .BlobId ;
2424import com .google .cloud .storage .BlobInfo ;
25- import com .google .cloud .storage .Bucket ;
2625import com .google .cloud .storage .BucketInfo ;
2726import com .google .cloud .storage .DataGeneration ;
2827import com .google .cloud .storage .Storage ;
2928import com .google .cloud .storage .StorageOptions ;
30- import com .google .cloud .storage .conformance .retry .TestBench ;
29+ import com .google .cloud .storage .testing .RemoteStorageHelper ;
30+ import com .google .common .io .ByteStreams ;
31+ import java .io .File ;
3132import java .io .IOException ;
3233import java .nio .ByteBuffer ;
34+ import java .nio .channels .FileChannel ;
35+ import java .nio .file .Files ;
36+ import java .nio .file .Paths ;
37+ import java .nio .file .StandardOpenOption ;
3338import java .util .Random ;
34- import org .junit .ClassRule ;
39+ import org .junit .After ;
40+ import org .junit .Before ;
3541import org .junit .Rule ;
3642import org .junit .Test ;
43+ import org .junit .rules .TemporaryFolder ;
3744import org .junit .rules .TestName ;
3845
3946public final class ITBlobReadChannelTest {
4047
4148 private static final int _16MiB = 16 * 1024 * 1024 ;
4249 private static final int _256KiB = 256 * 1024 ;
4350
44- @ ClassRule
45- public static final TestBench testBench =
46- TestBench .newBuilder ().setContainerName ("blob-read-channel-test" ).build ();
47-
4851 @ Rule public final TestName testName = new TestName ();
4952
5053 @ Rule public final DataGeneration dataGeneration = new DataGeneration (new Random (872364872 ));
5154
55+ @ Rule public final TemporaryFolder tmp = new TemporaryFolder ();
56+
57+ private Storage storage ;
58+ private String bucketName ;
59+ private String blobName ;
60+
61+ @ Before
62+ public void setUp () throws Exception {
63+ storage = StorageOptions .newBuilder ().build ().getService ();
64+
65+ bucketName = RemoteStorageHelper .generateBucketName ();
66+ storage .create (BucketInfo .of (bucketName ));
67+ blobName = String .format ("%s/src" , testName .getMethodName ());
68+ }
69+
70+ @ After
71+ public void tearDown () throws Exception {
72+ RemoteStorageHelper .forceDelete (storage , bucketName );
73+ }
74+
5275 @ Test
5376 public void testLimit_smallerThanOneChunk () throws IOException {
5477 int srcContentSize = _256KiB ;
@@ -58,6 +81,24 @@ public void testLimit_smallerThanOneChunk() throws IOException {
5881 doLimitTest (srcContentSize , rangeBegin , rangeEnd , chunkSize );
5982 }
6083
84+ @ Test
85+ public void testLimit_pastEndOfBlob () throws IOException {
86+ int srcContentSize = _256KiB ;
87+ int rangeBegin = _256KiB - 20 ;
88+ int rangeEnd = _256KiB + 20 ;
89+ int chunkSize = _16MiB ;
90+ doLimitTest (srcContentSize , rangeBegin , rangeEnd , chunkSize );
91+ }
92+
93+ @ Test
94+ public void testLimit_endBeforeBegin () throws IOException {
95+ int srcContentSize = _256KiB ;
96+ int rangeBegin = 4 ;
97+ int rangeEnd = 3 ;
98+ int chunkSize = _16MiB ;
99+ doLimitTest (srcContentSize , rangeBegin , rangeEnd , chunkSize );
100+ }
101+
61102 @ Test
62103 public void testLimit_largerThanOneChunk () throws IOException {
63104 int srcContentSize = _16MiB + (_256KiB * 3 );
@@ -68,40 +109,65 @@ public void testLimit_largerThanOneChunk() throws IOException {
68109 doLimitTest (srcContentSize , rangeBegin , rangeEnd , chunkSize );
69110 }
70111
112+ @ Test
113+ public void testLimit_downloadToFile () throws IOException {
114+ BlobId blobId = BlobId .of (bucketName , blobName );
115+ ByteBuffer content = dataGeneration .randByteBuffer (108 );
116+ try (WriteChannel writer = storage .writer (BlobInfo .newBuilder (blobId ).build ())) {
117+ writer .write (content );
118+ }
119+
120+ File file = tmp .newFile ();
121+ String destFileName = file .getAbsolutePath ();
122+ byte [] expectedBytes = new byte [37 - 14 ];
123+ ByteBuffer duplicate = content .duplicate ();
124+ duplicate .position (14 );
125+ duplicate .limit (37 );
126+ duplicate .get (expectedBytes );
127+
128+ try {
129+ try (ReadChannel from = storage .reader (blobId );
130+ FileChannel to = FileChannel .open (Paths .get (destFileName ), StandardOpenOption .WRITE )) {
131+ from .seek (14 );
132+ from .limit (37 );
133+
134+ ByteStreams .copy (from , to );
135+ }
136+
137+ byte [] readBytes = Files .readAllBytes (Paths .get (destFileName ));
138+ assertThat (readBytes ).isEqualTo (expectedBytes );
139+ } finally {
140+ file .delete ();
141+ }
142+ }
143+
71144 private void doLimitTest (int srcContentSize , int rangeBegin , int rangeEnd , int chunkSize )
72145 throws IOException {
73- Storage s =
74- StorageOptions .newBuilder ()
75- .setProjectId ("blob-read-channel-test" )
76- .setHost (testBench .getBaseUri ())
77- .setCredentials (NoCredentials .getInstance ())
78- .build ()
79- .getService ();
80-
81- String testNameMethodName = testName .getMethodName ();
82- String bucketName = String .format ("bucket-%s" , testNameMethodName .toLowerCase ());
83- String blobName = String .format ("%s/src" , testNameMethodName );
84-
85- Bucket bucket = s .create (BucketInfo .of (bucketName ));
86- BlobInfo src = BlobInfo .newBuilder (bucket , blobName ).build ();
146+ BlobInfo src = BlobInfo .newBuilder (bucketName , blobName ).build ();
87147 ByteBuffer content = dataGeneration .randByteBuffer (srcContentSize );
88- ByteBuffer expectedSubContent = content .duplicate ();
89- expectedSubContent .position (rangeBegin );
90- expectedSubContent .limit (rangeEnd );
91- try (WriteChannel writer = s .writer (src )) {
148+ ByteBuffer dup = content .duplicate ();
149+ dup .position (rangeBegin );
150+ dup .limit (Math .min (dup .capacity (), rangeEnd ));
151+ byte [] expectedSubContent = new byte [dup .remaining ()];
152+ dup .get (expectedSubContent );
153+
154+ try (WriteChannel writer = storage .writer (src )) {
92155 writer .write (content );
93156 }
94157
95- ByteBuffer actual = ByteBuffer .allocate (rangeEnd - rangeBegin );
158+ ByteBuffer buffer = ByteBuffer .allocate (srcContentSize );
96159
97- try (ReadChannel reader = s .reader (src .getBlobId ())) {
160+ try (ReadChannel reader = storage .reader (src .getBlobId ())) {
98161 reader .setChunkSize (chunkSize );
99162 reader .seek (rangeBegin );
100163 reader .limit (rangeEnd );
101- reader .read (actual );
102- actual .flip ();
164+ reader .read (buffer );
165+ buffer .flip ();
103166 }
104167
168+ byte [] actual = new byte [buffer .limit ()];
169+ buffer .get (actual );
170+
105171 assertThat (actual ).isEqualTo (expectedSubContent );
106172 }
107173}
0 commit comments