View Javadoc
1   /*
2    * Copyright (C) 2021 Thomas Wolf <thomas.wolf@paranor.ch> and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.util.io;
11  
12  import static org.junit.Assert.assertArrayEquals;
13  import static org.junit.Assert.assertEquals;
14  import static org.junit.Assert.assertTrue;
15  
16  import java.io.ByteArrayOutputStream;
17  import java.io.InputStream;
18  import java.util.zip.InflaterInputStream;
19  
20  import org.junit.Test;
21  
22  /**
23   * Crude tests for the {@link BinaryDeltaInputStream} using delta diffs
24   * generated by C git.
25   */
26  public class BinaryDeltaInputStreamTest {
27  
28  	private InputStream getBinaryHunk(String name) {
29  		return this.getClass().getResourceAsStream(name);
30  	}
31  
32  	@Test
33  	public void testBinaryDelta() throws Exception {
34  		// Prepare our test data
35  		byte[] data = new byte[8192];
36  		for (int i = 0; i < data.length; i++) {
37  			data[i] = (byte) (255 - (i % 256));
38  		}
39  		// Same, but with five 'x' inserted in the middle.
40  		int middle = data.length / 2;
41  		byte[] newData = new byte[data.length + 5];
42  		System.arraycopy(data, 0, newData, 0, middle);
43  		for (int i = 0; i < 5; i++) {
44  			newData[middle + i] = 'x';
45  		}
46  		System.arraycopy(data, middle, newData, middle + 5, middle);
47  		// delta1.forward has the instructions
48  		// @formatter:off
49  		// COPY 0 4096
50  		// INSERT 5 xxxxx
51  		// COPY 0 4096
52  		// @formatter:on
53  		// Note that the way we built newData could be expressed as
54  		// @formatter:off
55  		// COPY 0 4096
56  		// INSERT 5 xxxxx
57  		// COPY 4096 4096
58  		// @formatter:on
59  		try (ByteArrayOutputStream out = new ByteArrayOutputStream();
60  				BinaryDeltaInputStream input = new BinaryDeltaInputStream(data,
61  						new InflaterInputStream(new BinaryHunkInputStream(
62  								getBinaryHunk("delta1.forward"))))) {
63  			byte[] buf = new byte[1024];
64  			int n;
65  			while ((n = input.read(buf)) >= 0) {
66  				out.write(buf, 0, n);
67  			}
68  			assertArrayEquals(newData, out.toByteArray());
69  			assertTrue(input.isFullyConsumed());
70  		}
71  		// delta1.reverse has the instructions
72  		// @formatter:off
73  		// COPY 0 4096
74  		// COPY 256 3840
75  		// COPY 256 256
76  		// @formatter:on
77  		// Note that there are alternatives, for instance
78  		// @formatter:off
79  		// COPY 0 4096
80  		// COPY 4101 4096
81  		// @formatter:on
82  		// or
83  		// @formatter:off
84  		// COPY 0 4096
85  		// COPY 0 4096
86  		// @formatter:on
87  		try (ByteArrayOutputStream out = new ByteArrayOutputStream();
88  				BinaryDeltaInputStream input = new BinaryDeltaInputStream(
89  						newData,
90  						new InflaterInputStream(new BinaryHunkInputStream(
91  								getBinaryHunk("delta1.reverse"))))) {
92  			long expectedSize = input.getExpectedResultSize();
93  			assertEquals(data.length, expectedSize);
94  			byte[] buf = new byte[1024];
95  			int n;
96  			while ((n = input.read(buf)) >= 0) {
97  				out.write(buf, 0, n);
98  			}
99  			assertArrayEquals(data, out.toByteArray());
100 			assertTrue(input.isFullyConsumed());
101 		}
102 	}
103 }