blob: 640203dd5418e54e77193c02d16ff498a29f0835 [file] [log] [blame]
/*
* Copyright (C) 2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.eclipse.jgit.internal.storage.pack;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.eclipse.jgit.junit.JGitTestUtil;
import org.eclipse.jgit.junit.TestRng;
import org.eclipse.jgit.lib.Constants;
import org.junit.Before;
import org.junit.Test;
public class DeltaIndexTest {
private TestRng rng;
private ByteArrayOutputStream actDeltaBuf;
private ByteArrayOutputStream expDeltaBuf;
private DeltaEncoder expDeltaEnc;
private byte[] src;
private byte[] dst;
private ByteArrayOutputStream dstBuf;
private TestRng getRng() {
if (rng == null)
rng = new TestRng(JGitTestUtil.getName());
return rng;
}
@Before
public void setUp() throws Exception {
actDeltaBuf = new ByteArrayOutputStream();
expDeltaBuf = new ByteArrayOutputStream();
expDeltaEnc = new DeltaEncoder(expDeltaBuf, 0, 0);
dstBuf = new ByteArrayOutputStream();
}
@Test
public void testInsertWholeObject_Length12() throws IOException {
src = getRng().nextBytes(12);
insert(src);
doTest();
}
@Test
public void testCopyWholeObject_Length128() throws IOException {
src = getRng().nextBytes(128);
copy(0, 128);
doTest();
}
@Test
public void testCopyWholeObject_Length123() throws IOException {
src = getRng().nextBytes(123);
copy(0, 123);
doTest();
}
@Test
public void testCopyZeros_Length128() throws IOException {
src = new byte[2048];
copy(0, src.length);
doTest();
// The index should be smaller than expected due to the chain
// being truncated. Without truncation we would expect to have
// more than 3584 bytes used.
//
assertEquals(2636, new DeltaIndex(src).getIndexSize());
}
@Test
public void testShuffleSegments() throws IOException {
src = getRng().nextBytes(128);
copy(64, 64);
copy(0, 64);
doTest();
}
@Test
public void testInsertHeadMiddle() throws IOException {
src = getRng().nextBytes(1024);
insert("foo");
copy(0, 512);
insert("yet more fooery");
copy(0, 512);
doTest();
}
@Test
public void testInsertTail() throws IOException {
src = getRng().nextBytes(1024);
copy(0, 512);
insert("bar");
doTest();
}
@Test
public void testIndexSize() {
src = getRng().nextBytes(1024);
DeltaIndex di = new DeltaIndex(src);
assertEquals(1860, di.getIndexSize());
assertEquals("DeltaIndex[2 KiB]", di.toString());
}
@Test
public void testLimitObjectSize_Length12InsertFails() throws IOException {
src = getRng().nextBytes(12);
dst = src;
DeltaIndex di = new DeltaIndex(src);
assertFalse(di.encode(actDeltaBuf, dst, src.length));
}
@Test
public void testLimitObjectSize_Length130InsertFails() throws IOException {
src = getRng().nextBytes(130);
dst = getRng().nextBytes(130);
DeltaIndex di = new DeltaIndex(src);
assertFalse(di.encode(actDeltaBuf, dst, src.length));
}
@Test
public void testLimitObjectSize_Length130CopyOk() throws IOException {
src = getRng().nextBytes(130);
copy(0, 130);
dst = dstBuf.toByteArray();
DeltaIndex di = new DeltaIndex(src);
assertTrue(di.encode(actDeltaBuf, dst, dst.length));
byte[] actDelta = actDeltaBuf.toByteArray();
byte[] expDelta = expDeltaBuf.toByteArray();
assertEquals(BinaryDelta.format(expDelta, false), //
BinaryDelta.format(actDelta, false));
}
@Test
public void testLimitObjectSize_Length130CopyFails() throws IOException {
src = getRng().nextBytes(130);
copy(0, 130);
dst = dstBuf.toByteArray();
// The header requires 4 bytes for these objects, so a target length
// of 5 is bigger than the copy instruction and should cause an abort.
//
DeltaIndex di = new DeltaIndex(src);
assertFalse(di.encode(actDeltaBuf, dst, 5));
assertEquals(4, actDeltaBuf.size());
}
@Test
public void testLimitObjectSize_InsertFrontFails() throws IOException {
src = getRng().nextBytes(130);
insert("eight");
copy(0, 130);
dst = dstBuf.toByteArray();
// The header requires 4 bytes for these objects, so a target length
// of 5 is bigger than the copy instruction and should cause an abort.
//
DeltaIndex di = new DeltaIndex(src);
assertFalse(di.encode(actDeltaBuf, dst, 5));
assertEquals(4, actDeltaBuf.size());
}
private void copy(int offset, int len) throws IOException {
dstBuf.write(src, offset, len);
expDeltaEnc.copy(offset, len);
}
private void insert(String text) throws IOException {
insert(Constants.encode(text));
}
private void insert(byte[] text) throws IOException {
dstBuf.write(text);
expDeltaEnc.insert(text);
}
private void doTest() throws IOException {
dst = dstBuf.toByteArray();
DeltaIndex di = new DeltaIndex(src);
di.encode(actDeltaBuf, dst);
byte[] actDelta = actDeltaBuf.toByteArray();
byte[] expDelta = expDeltaBuf.toByteArray();
assertEquals(BinaryDelta.format(expDelta, false), //
BinaryDelta.format(actDelta, false));
assertTrue("delta is not empty", actDelta.length > 0);
assertEquals(src.length, BinaryDelta.getBaseSize(actDelta));
assertEquals(dst.length, BinaryDelta.getResultSize(actDelta));
assertArrayEquals(dst, BinaryDelta.apply(src, actDelta));
}
}