View Javadoc
1   /*
2    * Copyright (C) 2012, Robin Rosenberg <robin.rosenberg@dewire.com>
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  package org.eclipse.jgit.api;
44  
45  import static org.junit.Assert.assertEquals;
46  
47  import java.io.File;
48  import java.io.RandomAccessFile;
49  import java.util.Arrays;
50  import java.util.Collection;
51  
52  import org.eclipse.jgit.api.ResetCommand.ResetType;
53  import org.eclipse.jgit.junit.RepositoryTestCase;
54  import org.junit.Ignore;
55  import org.junit.Test;
56  
57  public class HugeFileTest extends RepositoryTestCase {
58  
59  	private long t = System.currentTimeMillis();
60  
61  	private long lastt = t;
62  
63  	private void measure(String name) {
64  		long c = System.currentTimeMillis();
65  		System.out.println(name + ", dt=" + (c - lastt) / 1000.0 + "s");
66  		lastt = c;
67  	}
68  
69  	@Ignore("Test takes way too long (~10 minutes) to be part of the standard suite")
70  	@Test
71  	public void testAddHugeFile() throws Exception {
72  		measure("Commencing test");
73  		File file = new File(db.getWorkTree(), "a.txt");
74  		RandomAccessFile rf = new RandomAccessFile(file, "rw");
75  		rf.setLength(4429185024L);
76  		rf.close();
77  		measure("Created file");
78  		Git git = new Git(db);
79  
80  		git.add().addFilepattern("a.txt").call();
81  		measure("Added file");
82  		assertEquals(
83  				"[a.txt, mode:100644, length:134217728, sha1:b8cfba97c2b962a44f080b3ca4e03b3204b6a350]",
84  				indexState(LENGTH | CONTENT_ID));
85  
86  		Status status = git.status().call();
87  		measure("Status after add");
88  		assertCollectionEquals(Arrays.asList("a.txt"), status.getAdded());
89  		assertEquals(0, status.getChanged().size());
90  		assertEquals(0, status.getConflicting().size());
91  		assertEquals(0, status.getMissing().size());
92  		assertEquals(0, status.getModified().size());
93  		assertEquals(0, status.getRemoved().size());
94  		assertEquals(0, status.getUntracked().size());
95  
96  		// Does not change anything, but modified timestamp
97  		rf = new RandomAccessFile(file, "rw");
98  		rf.write(0);
99  		rf.close();
100 
101 		status = git.status().call();
102 		measure("Status after non-modifying update");
103 
104 		assertCollectionEquals(Arrays.asList("a.txt"), status.getAdded());
105 		assertEquals(0, status.getChanged().size());
106 		assertEquals(0, status.getConflicting().size());
107 		assertEquals(0, status.getMissing().size());
108 		assertEquals(0, status.getModified().size());
109 		assertEquals(0, status.getRemoved().size());
110 		assertEquals(0, status.getUntracked().size());
111 
112 		// Change something
113 		rf = new RandomAccessFile(file, "rw");
114 		rf.write('a');
115 		rf.close();
116 
117 		status = git.status().call();
118 		measure("Status after modifying update");
119 
120 		assertCollectionEquals(Arrays.asList("a.txt"), status.getAdded());
121 		assertEquals(0, status.getChanged().size());
122 		assertEquals(0, status.getConflicting().size());
123 		assertEquals(0, status.getMissing().size());
124 		assertCollectionEquals(Arrays.asList("a.txt"), status.getModified());
125 		assertEquals(0, status.getRemoved().size());
126 		assertEquals(0, status.getUntracked().size());
127 
128 		// Truncate mod 4G and re-establish equality
129 		rf = new RandomAccessFile(file, "rw");
130 		rf.setLength(134217728L);
131 		rf.write(0);
132 		rf.close();
133 
134 		status = git.status().call();
135 		measure("Status after truncating update");
136 
137 		assertCollectionEquals(Arrays.asList("a.txt"), status.getAdded());
138 		assertEquals(0, status.getChanged().size());
139 		assertEquals(0, status.getConflicting().size());
140 		assertEquals(0, status.getMissing().size());
141 		assertCollectionEquals(Arrays.asList("a.txt"), status.getModified());
142 		assertEquals(0, status.getRemoved().size());
143 		assertEquals(0, status.getUntracked().size());
144 
145 		// Change something
146 		rf = new RandomAccessFile(file, "rw");
147 		rf.write('a');
148 		rf.close();
149 
150 		status = git.status().call();
151 		measure("Status after modifying and truncating update");
152 
153 		assertCollectionEquals(Arrays.asList("a.txt"), status.getAdded());
154 		assertEquals(0, status.getChanged().size());
155 		assertEquals(0, status.getConflicting().size());
156 		assertEquals(0, status.getMissing().size());
157 		assertCollectionEquals(Arrays.asList("a.txt"), status.getModified());
158 		assertEquals(0, status.getRemoved().size());
159 		assertEquals(0, status.getUntracked().size());
160 
161 		// Truncate to entry length becomes negative int
162 		rf = new RandomAccessFile(file, "rw");
163 		rf.setLength(3429185024L);
164 		rf.write(0);
165 		rf.close();
166 
167 		git.add().addFilepattern("a.txt").call();
168 		measure("Added truncated file");
169 		assertEquals(
170 				"[a.txt, mode:100644, length:-865782272, sha1:59b3282f8f59f22d953df956ad3511bf2dc660fd]",
171 				indexState(LENGTH | CONTENT_ID));
172 
173 		status = git.status().call();
174 		measure("Status after status on truncated file");
175 
176 		assertCollectionEquals(Arrays.asList("a.txt"), status.getAdded());
177 		assertEquals(0, status.getChanged().size());
178 		assertEquals(0, status.getConflicting().size());
179 		assertEquals(0, status.getMissing().size());
180 		assertEquals(0, status.getModified().size());
181 		assertEquals(0, status.getRemoved().size());
182 		assertEquals(0, status.getUntracked().size());
183 
184 		// Change something
185 		rf = new RandomAccessFile(file, "rw");
186 		rf.write('a');
187 		rf.close();
188 
189 		status = git.status().call();
190 		measure("Status after modifying and truncating update");
191 
192 		assertCollectionEquals(Arrays.asList("a.txt"), status.getAdded());
193 		assertEquals(0, status.getChanged().size());
194 		assertEquals(0, status.getConflicting().size());
195 		assertEquals(0, status.getMissing().size());
196 		assertCollectionEquals(Arrays.asList("a.txt"), status.getModified());
197 		assertEquals(0, status.getRemoved().size());
198 		assertEquals(0, status.getUntracked().size());
199 
200 		git.commit().setMessage("make a commit").call();
201 		measure("After commit");
202 		status = git.status().call();
203 		measure("After status after commit");
204 
205 		assertEquals(0, status.getAdded().size());
206 		assertEquals(0, status.getChanged().size());
207 		assertEquals(0, status.getConflicting().size());
208 		assertEquals(0, status.getMissing().size());
209 		assertCollectionEquals(Arrays.asList("a.txt"), status.getModified());
210 		assertEquals(0, status.getRemoved().size());
211 		assertEquals(0, status.getUntracked().size());
212 
213 		git.reset().setMode(ResetType.HARD).call();
214 		measure("After reset --hard");
215 		assertEquals(
216 				"[a.txt, mode:100644, length:-865782272, sha1:59b3282f8f59f22d953df956ad3511bf2dc660fd]",
217 				indexState(LENGTH | CONTENT_ID));
218 
219 		status = git.status().call();
220 		measure("Status after hard reset");
221 
222 		assertEquals(0, status.getAdded().size());
223 		assertEquals(0, status.getChanged().size());
224 		assertEquals(0, status.getConflicting().size());
225 		assertEquals(0, status.getMissing().size());
226 		assertEquals(0, status.getModified().size());
227 		assertEquals(0, status.getRemoved().size());
228 		assertEquals(0, status.getUntracked().size());
229 	}
230 
231 	private static void assertCollectionEquals(Collection<?> asList,
232 			Collection<?> added) {
233 		assertEquals(asList.toString(), added.toString());
234 	}
235 
236 }