@Test
public void testDelta_SmallObjectChain() throws Exception {
- ObjectInserter.Formatter fmt = new ObjectInserter.Formatter();
- byte[] data0 = new byte[512];
- Arrays.fill(data0, (byte) 0xf3);
- ObjectId id0 = fmt.idFor(Constants.OBJ_BLOB, data0);
-
- TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64 * 1024);
- packHeader(pack, 4);
- objectHeader(pack, Constants.OBJ_BLOB, data0.length);
- deflate(pack, data0);
-
- byte[] data1 = clone(0x01, data0);
- byte[] delta1 = delta(data0, data1);
- ObjectId id1 = fmt.idFor(Constants.OBJ_BLOB, data1);
- objectHeader(pack, Constants.OBJ_REF_DELTA, delta1.length);
- id0.copyRawTo(pack);
- deflate(pack, delta1);
-
- byte[] data2 = clone(0x02, data1);
- byte[] delta2 = delta(data1, data2);
- ObjectId id2 = fmt.idFor(Constants.OBJ_BLOB, data2);
- objectHeader(pack, Constants.OBJ_REF_DELTA, delta2.length);
- id1.copyRawTo(pack);
- deflate(pack, delta2);
-
- byte[] data3 = clone(0x03, data2);
- byte[] delta3 = delta(data2, data3);
- ObjectId id3 = fmt.idFor(Constants.OBJ_BLOB, data3);
- objectHeader(pack, Constants.OBJ_REF_DELTA, delta3.length);
- id2.copyRawTo(pack);
- deflate(pack, delta3);
-
- digest(pack);
- PackParser ip = index(pack.toByteArray());
- ip.setAllowThin(true);
- ip.parse(NullProgressMonitor.INSTANCE);
-
- assertTrue("has blob", wc.has(id3));
-
- ObjectLoader ol = wc.open(id3);
- assertNotNull("created loader", ol);
- assertEquals(Constants.OBJ_BLOB, ol.getType());
- assertEquals(data3.length, ol.getSize());
- assertFalse("is large", ol.isLarge());
- assertNotNull(ol.getCachedBytes());
- assertArrayEquals(data3, ol.getCachedBytes());
-
- ObjectStream in = ol.openStream();
- assertNotNull("have stream", in);
- assertEquals(Constants.OBJ_BLOB, in.getType());
- assertEquals(data3.length, in.getSize());
- byte[] act = new byte[data3.length];
- IO.readFully(in, act, 0, data3.length);
- assertTrue("same content", Arrays.equals(act, data3));
- assertEquals("stream at EOF", -1, in.read());
- in.close();
+ try (ObjectInserter.Formatter fmt = new ObjectInserter.Formatter()) {
+ byte[] data0 = new byte[512];
+ Arrays.fill(data0, (byte) 0xf3);
+ ObjectId id0 = fmt.idFor(Constants.OBJ_BLOB, data0);
+
+ TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64 * 1024);
+ packHeader(pack, 4);
+ objectHeader(pack, Constants.OBJ_BLOB, data0.length);
+ deflate(pack, data0);
+
+ byte[] data1 = clone(0x01, data0);
+ byte[] delta1 = delta(data0, data1);
+ ObjectId id1 = fmt.idFor(Constants.OBJ_BLOB, data1);
+ objectHeader(pack, Constants.OBJ_REF_DELTA, delta1.length);
+ id0.copyRawTo(pack);
+ deflate(pack, delta1);
+
+ byte[] data2 = clone(0x02, data1);
+ byte[] delta2 = delta(data1, data2);
+ ObjectId id2 = fmt.idFor(Constants.OBJ_BLOB, data2);
+ objectHeader(pack, Constants.OBJ_REF_DELTA, delta2.length);
+ id1.copyRawTo(pack);
+ deflate(pack, delta2);
+
+ byte[] data3 = clone(0x03, data2);
+ byte[] delta3 = delta(data2, data3);
+ ObjectId id3 = fmt.idFor(Constants.OBJ_BLOB, data3);
+ objectHeader(pack, Constants.OBJ_REF_DELTA, delta3.length);
+ id2.copyRawTo(pack);
+ deflate(pack, delta3);
+
+ digest(pack);
+ PackParser ip = index(pack.toByteArray());
+ ip.setAllowThin(true);
+ ip.parse(NullProgressMonitor.INSTANCE);
+
+ assertTrue("has blob", wc.has(id3));
+
+ ObjectLoader ol = wc.open(id3);
+ assertNotNull("created loader", ol);
+ assertEquals(Constants.OBJ_BLOB, ol.getType());
+ assertEquals(data3.length, ol.getSize());
+ assertFalse("is large", ol.isLarge());
+ assertNotNull(ol.getCachedBytes());
+ assertArrayEquals(data3, ol.getCachedBytes());
+
+ ObjectStream in = ol.openStream();
+ assertNotNull("have stream", in);
+ assertEquals(Constants.OBJ_BLOB, in.getType());
+ assertEquals(data3.length, in.getSize());
+ byte[] act = new byte[data3.length];
+ IO.readFully(in, act, 0, data3.length);
+ assertTrue("same content", Arrays.equals(act, data3));
+ assertEquals("stream at EOF", -1, in.read());
+ in.close();
+ }
}
@Test
public void testDelta_FailsOver2GiB() throws Exception {
- ObjectInserter.Formatter fmt = new ObjectInserter.Formatter();
- byte[] base = new byte[] { 'a' };
- ObjectId idA = fmt.idFor(Constants.OBJ_BLOB, base);
- ObjectId idB = fmt.idFor(Constants.OBJ_BLOB, new byte[] { 'b' });
-
- PackedObjectInfo a = new PackedObjectInfo(idA);
- PackedObjectInfo b = new PackedObjectInfo(idB);
-
- TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64 * 1024);
- packHeader(pack, 2);
- a.setOffset(pack.length());
- objectHeader(pack, Constants.OBJ_BLOB, base.length);
- deflate(pack, base);
-
- ByteArrayOutputStream tmp = new ByteArrayOutputStream();
- DeltaEncoder de = new DeltaEncoder(tmp, base.length, 3L << 30);
- de.copy(0, 1);
- byte[] delta = tmp.toByteArray();
- b.setOffset(pack.length());
- objectHeader(pack, Constants.OBJ_REF_DELTA, delta.length);
- idA.copyRawTo(pack);
- deflate(pack, delta);
- byte[] footer = digest(pack);
-
- File dir = new File(repo.getObjectDatabase().getDirectory(), "pack");
- File packName = new File(dir, idA.name() + ".pack");
- File idxName = new File(dir, idA.name() + ".idx");
-
- FileOutputStream f = new FileOutputStream(packName);
- try {
- f.write(pack.toByteArray());
- } finally {
- f.close();
- }
-
- f = new FileOutputStream(idxName);
- try {
- List<PackedObjectInfo> list = new ArrayList<PackedObjectInfo>();
- list.add(a);
- list.add(b);
- Collections.sort(list);
- new PackIndexWriterV1(f).write(list, footer);
- } finally {
- f.close();
- }
-
- PackFile packFile = new PackFile(packName, PackExt.INDEX.getBit());
- try {
- packFile.get(wc, b);
- fail("expected LargeObjectException.ExceedsByteArrayLimit");
- } catch (LargeObjectException.ExceedsByteArrayLimit bad) {
- assertNull(bad.getObjectId());
- } finally {
- packFile.close();
+ try (ObjectInserter.Formatter fmt = new ObjectInserter.Formatter()) {
+ byte[] base = new byte[] { 'a' };
+ ObjectId idA = fmt.idFor(Constants.OBJ_BLOB, base);
+ ObjectId idB = fmt.idFor(Constants.OBJ_BLOB, new byte[] { 'b' });
+
+ PackedObjectInfo a = new PackedObjectInfo(idA);
+ PackedObjectInfo b = new PackedObjectInfo(idB);
+
+ TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(64 * 1024);
+ packHeader(pack, 2);
+ a.setOffset(pack.length());
+ objectHeader(pack, Constants.OBJ_BLOB, base.length);
+ deflate(pack, base);
+
+ ByteArrayOutputStream tmp = new ByteArrayOutputStream();
+ DeltaEncoder de = new DeltaEncoder(tmp, base.length, 3L << 30);
+ de.copy(0, 1);
+ byte[] delta = tmp.toByteArray();
+ b.setOffset(pack.length());
+ objectHeader(pack, Constants.OBJ_REF_DELTA, delta.length);
+ idA.copyRawTo(pack);
+ deflate(pack, delta);
+ byte[] footer = digest(pack);
+
+ File dir = new File(repo.getObjectDatabase().getDirectory(),
+ "pack");
+ File packName = new File(dir, idA.name() + ".pack");
+ File idxName = new File(dir, idA.name() + ".idx");
+
+ FileOutputStream f = new FileOutputStream(packName);
+ try {
+ f.write(pack.toByteArray());
+ } finally {
+ f.close();
+ }
+
+ f = new FileOutputStream(idxName);
+ try {
+ List<PackedObjectInfo> list = new ArrayList<PackedObjectInfo>();
+ list.add(a);
+ list.add(b);
+ Collections.sort(list);
+ new PackIndexWriterV1(f).write(list, footer);
+ } finally {
+ f.close();
+ }
+
+ PackFile packFile = new PackFile(packName, PackExt.INDEX.getBit());
+ try {
+ packFile.get(wc, b);
+ fail("expected LargeObjectException.ExceedsByteArrayLimit");
+ } catch (LargeObjectException.ExceedsByteArrayLimit bad) {
+ assertNull(bad.getObjectId());
+ } finally {
+ packFile.close();
+ }
}
}