View Javadoc
1   /*
2    * Copyright (C) 2008-2009, Google Inc.
3    * and other copyright owners as documented in the project's IP log.
4    *
5    * This program and the accompanying materials are made available
6    * under the terms of the Eclipse Distribution License v1.0 which
7    * accompanies this distribution, is reproduced below, and is
8    * available at http://www.eclipse.org/org/documents/edl-v10.php
9    *
10   * All rights reserved.
11   *
12   * Redistribution and use in source and binary forms, with or
13   * without modification, are permitted provided that the following
14   * conditions are met:
15   *
16   * - Redistributions of source code must retain the above copyright
17   *   notice, this list of conditions and the following disclaimer.
18   *
19   * - Redistributions in binary form must reproduce the above
20   *   copyright notice, this list of conditions and the following
21   *   disclaimer in the documentation and/or other materials provided
22   *   with the distribution.
23   *
24   * - Neither the name of the Eclipse Foundation, Inc. nor the
25   *   names of its contributors may be used to endorse or promote
26   *   products derived from this software without specific prior
27   *   written permission.
28   *
29   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  
44  package org.eclipse.jgit.util;
45  
46  import static org.eclipse.jgit.junit.JGitTestUtil.getName;
47  import static org.junit.Assert.assertArrayEquals;
48  import static org.junit.Assert.assertEquals;
49  import static org.junit.Assert.assertNotNull;
50  import static org.junit.Assert.fail;
51  
52  import java.io.ByteArrayInputStream;
53  import java.io.ByteArrayOutputStream;
54  import java.io.IOException;
55  import java.io.InputStream;
56  
57  import org.eclipse.jgit.junit.TestRng;
58  import org.eclipse.jgit.util.TemporaryBuffer.Block;
59  import org.junit.Test;
60  
61  public class TemporaryBufferTest {
62  	@Test
63  	public void testEmpty() throws IOException {
64  		@SuppressWarnings("resource") // Buffer is explicitly destroyed in finally block
65  		final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
66  		try {
67  			b.close();
68  			assertEquals(0, b.length());
69  			final byte[] r = b.toByteArray();
70  			assertNotNull(r);
71  			assertEquals(0, r.length);
72  		} finally {
73  			b.destroy();
74  		}
75  	}
76  
77  	@Test
78  	public void testOneByte() throws IOException {
79  		@SuppressWarnings("resource") // Buffer is explicitly destroyed in finally block
80  		final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
81  		final byte test = (byte) new TestRng(getName()).nextInt();
82  		try {
83  			b.write(test);
84  			b.close();
85  			assertEquals(1, b.length());
86  			{
87  				final byte[] r = b.toByteArray();
88  				assertNotNull(r);
89  				assertEquals(1, r.length);
90  				assertEquals(test, r[0]);
91  			}
92  			try (ByteArrayOutputStream o = new ByteArrayOutputStream()) {
93  				b.writeTo(o, null);
94  				final byte[] r = o.toByteArray();
95  				assertEquals(1, r.length);
96  				assertEquals(test, r[0]);
97  			}
98  		} finally {
99  			b.destroy();
100 		}
101 	}
102 
103 	@Test
104 	public void testOneBlock_BulkWrite() throws IOException {
105 		@SuppressWarnings("resource") // Buffer is explicitly destroyed in finally block
106 		final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
107 		final byte[] test = new TestRng(getName())
108 				.nextBytes(TemporaryBuffer.Block.SZ);
109 		try {
110 			b.write(test, 0, 2);
111 			b.write(test, 2, 4);
112 			b.write(test, 6, test.length - 6 - 2);
113 			b.write(test, test.length - 2, 2);
114 			b.close();
115 			assertEquals(test.length, b.length());
116 			{
117 				final byte[] r = b.toByteArray();
118 				assertNotNull(r);
119 				assertEquals(test.length, r.length);
120 				assertArrayEquals(test, r);
121 			}
122 			try (ByteArrayOutputStream o = new ByteArrayOutputStream()) {
123 				b.writeTo(o, null);
124 				final byte[] r = o.toByteArray();
125 				assertEquals(test.length, r.length);
126 				assertArrayEquals(test, r);
127 			}
128 		} finally {
129 			b.destroy();
130 		}
131 	}
132 
133 	@Test
134 	public void testOneBlockAndHalf_BulkWrite() throws IOException {
135 		@SuppressWarnings("resource") // Buffer is explicitly destroyed in finally block
136 		final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
137 		final byte[] test = new TestRng(getName())
138 				.nextBytes(TemporaryBuffer.Block.SZ * 3 / 2);
139 		try {
140 			b.write(test, 0, 2);
141 			b.write(test, 2, 4);
142 			b.write(test, 6, test.length - 6 - 2);
143 			b.write(test, test.length - 2, 2);
144 			b.close();
145 			assertEquals(test.length, b.length());
146 			{
147 				final byte[] r = b.toByteArray();
148 				assertNotNull(r);
149 				assertEquals(test.length, r.length);
150 				assertArrayEquals(test, r);
151 			}
152 			try (ByteArrayOutputStream o = new ByteArrayOutputStream()) {
153 				b.writeTo(o, null);
154 				final byte[] r = o.toByteArray();
155 				assertEquals(test.length, r.length);
156 				assertArrayEquals(test, r);
157 			}
158 		} finally {
159 			b.destroy();
160 		}
161 	}
162 
163 	@Test
164 	public void testOneBlockAndHalf_SingleWrite() throws IOException {
165 		@SuppressWarnings("resource") // Buffer is explicitly destroyed in finally block
166 		final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
167 		final byte[] test = new TestRng(getName())
168 				.nextBytes(TemporaryBuffer.Block.SZ * 3 / 2);
169 		try {
170 			for (int i = 0; i < test.length; i++)
171 				b.write(test[i]);
172 			b.close();
173 			assertEquals(test.length, b.length());
174 			{
175 				final byte[] r = b.toByteArray();
176 				assertNotNull(r);
177 				assertEquals(test.length, r.length);
178 				assertArrayEquals(test, r);
179 			}
180 			try (ByteArrayOutputStream o = new ByteArrayOutputStream()) {
181 				b.writeTo(o, null);
182 				final byte[] r = o.toByteArray();
183 				assertEquals(test.length, r.length);
184 				assertArrayEquals(test, r);
185 			}
186 		} finally {
187 			b.destroy();
188 		}
189 	}
190 
191 	@Test
192 	public void testOneBlockAndHalf_Copy() throws IOException {
193 		@SuppressWarnings("resource") // Buffer is explicitly destroyed in finally block
194 		final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
195 		final byte[] test = new TestRng(getName())
196 				.nextBytes(TemporaryBuffer.Block.SZ * 3 / 2);
197 		try {
198 			final ByteArrayInputStream in = new ByteArrayInputStream(test);
199 			b.write(in.read());
200 			b.copy(in);
201 			b.close();
202 			assertEquals(test.length, b.length());
203 			{
204 				final byte[] r = b.toByteArray();
205 				assertNotNull(r);
206 				assertEquals(test.length, r.length);
207 				assertArrayEquals(test, r);
208 			}
209 			try (ByteArrayOutputStream o = new ByteArrayOutputStream()) {
210 				b.writeTo(o, null);
211 				final byte[] r = o.toByteArray();
212 				assertEquals(test.length, r.length);
213 				assertArrayEquals(test, r);
214 			}
215 		} finally {
216 			b.destroy();
217 		}
218 	}
219 
220 	@Test
221 	public void testLarge_SingleWrite() throws IOException {
222 		@SuppressWarnings("resource") // Buffer is explicitly destroyed in finally block
223 		final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
224 		final byte[] test = new TestRng(getName())
225 				.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 3);
226 		try {
227 			b.write(test);
228 			b.close();
229 			assertEquals(test.length, b.length());
230 			{
231 				final byte[] r = b.toByteArray();
232 				assertNotNull(r);
233 				assertEquals(test.length, r.length);
234 				assertArrayEquals(test, r);
235 			}
236 			try (ByteArrayOutputStream o = new ByteArrayOutputStream()) {
237 				b.writeTo(o, null);
238 				final byte[] r = o.toByteArray();
239 				assertEquals(test.length, r.length);
240 				assertArrayEquals(test, r);
241 			}
242 		} finally {
243 			b.destroy();
244 		}
245 	}
246 
247 	@Test
248 	public void testInCoreInputStream() throws IOException {
249 		final int cnt = 256;
250 		final byte[] test = new TestRng(getName()).nextBytes(cnt);
251 		try (TemporaryBuffer.Heap b = new TemporaryBuffer.Heap(cnt + 4)) {
252 			b.write(test);
253 			InputStream in = b.openInputStream();
254 			byte[] act = new byte[cnt];
255 			IO.readFully(in, act, 0, cnt);
256 			assertArrayEquals(test, act);
257 		}
258 	}
259 
260 	@Test
261 	public void testInCoreLimit_SwitchOnAppendByte() throws IOException {
262 		@SuppressWarnings("resource") // Buffer is explicitly destroyed in finally block
263 		final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
264 		final byte[] test = new TestRng(getName())
265 				.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT + 1);
266 		try {
267 			b.write(test, 0, test.length - 1);
268 			b.write(test[test.length - 1]);
269 			b.close();
270 			assertEquals(test.length, b.length());
271 			{
272 				final byte[] r = b.toByteArray();
273 				assertNotNull(r);
274 				assertEquals(test.length, r.length);
275 				assertArrayEquals(test, r);
276 			}
277 			try (ByteArrayOutputStream o = new ByteArrayOutputStream()) {
278 				b.writeTo(o, null);
279 				final byte[] r = o.toByteArray();
280 				assertEquals(test.length, r.length);
281 				assertArrayEquals(test, r);
282 			}
283 		} finally {
284 			b.destroy();
285 		}
286 	}
287 
288 	@Test
289 	public void testInCoreLimit_SwitchBeforeAppendByte() throws IOException {
290 		@SuppressWarnings("resource") // Buffer is explicitly destroyed in finally block
291 		final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
292 		final byte[] test = new TestRng(getName())
293 				.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 3);
294 		try {
295 			b.write(test, 0, test.length - 1);
296 			b.write(test[test.length - 1]);
297 			b.close();
298 			assertEquals(test.length, b.length());
299 			{
300 				final byte[] r = b.toByteArray();
301 				assertNotNull(r);
302 				assertEquals(test.length, r.length);
303 				assertArrayEquals(test, r);
304 			}
305 			try (ByteArrayOutputStream o = new ByteArrayOutputStream()) {
306 				b.writeTo(o, null);
307 				final byte[] r = o.toByteArray();
308 				assertEquals(test.length, r.length);
309 				assertArrayEquals(test, r);
310 			}
311 		} finally {
312 			b.destroy();
313 		}
314 	}
315 
316 	@Test
317 	public void testInCoreLimit_SwitchOnCopy() throws IOException {
318 		@SuppressWarnings("resource") // Buffer is explicitly destroyed in finally block
319 		final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
320 		final byte[] test = new TestRng(getName())
321 				.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2);
322 		try {
323 			final ByteArrayInputStream in = new ByteArrayInputStream(test,
324 					TemporaryBuffer.DEFAULT_IN_CORE_LIMIT, test.length
325 							- TemporaryBuffer.DEFAULT_IN_CORE_LIMIT);
326 			b.write(test, 0, TemporaryBuffer.DEFAULT_IN_CORE_LIMIT);
327 			b.copy(in);
328 			b.close();
329 			assertEquals(test.length, b.length());
330 			{
331 				final byte[] r = b.toByteArray();
332 				assertNotNull(r);
333 				assertEquals(test.length, r.length);
334 				assertArrayEquals(test, r);
335 			}
336 			try (ByteArrayOutputStream o = new ByteArrayOutputStream()) {
337 				b.writeTo(o, null);
338 				final byte[] r = o.toByteArray();
339 				assertEquals(test.length, r.length);
340 				assertArrayEquals(test, r);
341 			}
342 		} finally {
343 			b.destroy();
344 		}
345 	}
346 
347 	@Test
348 	public void testDestroyWhileOpen() throws IOException {
349 		@SuppressWarnings("resource") // Buffer is explicitly destroyed in finally block
350 		final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
351 		try {
352 			b.write(new TestRng(getName())
353 					.nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2));
354 		} finally {
355 			b.destroy();
356 		}
357 	}
358 
359 	@Test
360 	public void testRandomWrites() throws IOException {
361 		@SuppressWarnings("resource") // Buffer is explicitly destroyed in finally block
362 		final TemporaryBuffer b = new TemporaryBuffer.LocalFile(null);
363 		final TestRng rng = new TestRng(getName());
364 		final int max = TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2;
365 		final byte[] expect = new byte[max];
366 		try {
367 			int written = 0;
368 			boolean onebyte = true;
369 			while (written < max) {
370 				if (onebyte) {
371 					final byte v = (byte) rng.nextInt();
372 					b.write(v);
373 					expect[written++] = v;
374 				} else {
375 					final int len = Math
376 							.min(rng.nextInt() & 127, max - written);
377 					final byte[] tmp = rng.nextBytes(len);
378 					b.write(tmp, 0, len);
379 					System.arraycopy(tmp, 0, expect, written, len);
380 					written += len;
381 				}
382 				onebyte = !onebyte;
383 			}
384 			assertEquals(expect.length, written);
385 			b.close();
386 
387 			assertEquals(expect.length, b.length());
388 			{
389 				final byte[] r = b.toByteArray();
390 				assertNotNull(r);
391 				assertEquals(expect.length, r.length);
392 				assertArrayEquals(expect, r);
393 			}
394 			try (ByteArrayOutputStream o = new ByteArrayOutputStream()) {
395 				b.writeTo(o, null);
396 				final byte[] r = o.toByteArray();
397 				assertEquals(expect.length, r.length);
398 				assertArrayEquals(expect, r);
399 			}
400 		} finally {
401 			b.destroy();
402 		}
403 	}
404 
405 	@Test
406 	public void testHeap() throws IOException {
407 		@SuppressWarnings("resource" /* java 7 */)
408 		final TemporaryBuffer b = new TemporaryBuffer.Heap(2 * 8 * 1024);
409 		final byte[] r = new byte[8 * 1024];
410 		b.write(r);
411 		b.write(r);
412 		try {
413 			b.write(1);
414 			fail("accepted too many bytes of data");
415 		} catch (IOException e) {
416 			assertEquals("In-memory buffer limit exceeded", e.getMessage());
417 		}
418 	}
419 
420 	@Test
421 	public void testHeapWithEstimatedSize() throws IOException {
422 		int sz = 2 * Block.SZ;
423 		try (TemporaryBuffer b = new TemporaryBuffer.Heap(sz / 2, sz)) {
424 			for (int i = 0; i < sz; i++) {
425 				b.write('x');
426 			}
427 			try {
428 				b.write(1);
429 				fail("accepted too many bytes of data");
430 			} catch (IOException e) {
431 				assertEquals("In-memory buffer limit exceeded", e.getMessage());
432 			}
433 
434 			try (InputStream in = b.openInputStream()) {
435 				for (int i = 0; i < sz; i++) {
436 					assertEquals('x', in.read());
437 				}
438 				assertEquals(-1, in.read());
439 			}
440 		}
441 	}
442 }