View Javadoc
1   /*
2    * Copyright (C) 2012, 2021 GitHub Inc. 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.internal.storage.file;
11  
12  import static org.junit.Assert.assertFalse;
13  import static org.junit.Assert.assertNotNull;
14  import static org.junit.Assert.assertThrows;
15  import static org.junit.Assert.assertTrue;
16  import static org.junit.Assert.fail;
17  
18  import java.io.File;
19  import java.io.OutputStream;
20  import java.nio.charset.StandardCharsets;
21  
22  import org.eclipse.jgit.api.Git;
23  import org.eclipse.jgit.api.errors.JGitInternalException;
24  import org.eclipse.jgit.errors.LockFailedException;
25  import org.eclipse.jgit.junit.RepositoryTestCase;
26  import org.eclipse.jgit.revwalk.RevCommit;
27  import org.junit.Test;
28  
29  /**
30   * Unit tests of {@link LockFile}
31   */
32  public class LockFileTest extends RepositoryTestCase {
33  
34  	@Test
35  	public void lockFailedExceptionRecovery() throws Exception {
36  		try (Git git = new Git(db)) {
37  			writeTrashFile("file.txt", "content");
38  			git.add().addFilepattern("file.txt").call();
39  			RevCommit commit1 = git.commit().setMessage("create file").call();
40  
41  			assertNotNull(commit1);
42  			writeTrashFile("file.txt", "content2");
43  			git.add().addFilepattern("file.txt").call();
44  			assertNotNull(git.commit().setMessage("edit file").call());
45  
46  			LockFile lf = new LockFile(db.getIndexFile());
47  			assertTrue(lf.lock());
48  			try {
49  				git.checkout().setName(commit1.name()).call();
50  				fail("JGitInternalException not thrown");
51  			} catch (JGitInternalException e) {
52  				assertTrue(e.getCause() instanceof LockFailedException);
53  				lf.unlock();
54  				git.checkout().setName(commit1.name()).call();
55  			}
56  		}
57  	}
58  
59  	@Test
60  	public void testLockTwice() throws Exception {
61  		File f = writeTrashFile("somefile", "content");
62  		LockFile lock = new LockFile(f);
63  		assertTrue(lock.lock());
64  		lock.write("other".getBytes(StandardCharsets.US_ASCII));
65  		lock.commit();
66  		assertFalse(lock.isLocked());
67  		checkFile(f, "other");
68  		assertTrue(lock.lock());
69  		assertTrue(lock.isLocked());
70  		try (OutputStream out = lock.getOutputStream()) {
71  			out.write("second".getBytes(StandardCharsets.US_ASCII));
72  		}
73  		lock.commit();
74  		assertFalse(lock.isLocked());
75  		checkFile(f, "second");
76  	}
77  
78  	@Test
79  	public void testLockTwiceUnlock() throws Exception {
80  		File f = writeTrashFile("somefile", "content");
81  		LockFile lock = new LockFile(f);
82  		assertTrue(lock.lock());
83  		assertTrue(lock.isLocked());
84  		lock.write("other".getBytes(StandardCharsets.US_ASCII));
85  		lock.unlock();
86  		assertFalse(lock.isLocked());
87  		checkFile(f, "content");
88  		assertTrue(lock.lock());
89  		assertTrue(lock.isLocked());
90  		try (OutputStream out = lock.getOutputStream()) {
91  			out.write("second".getBytes(StandardCharsets.US_ASCII));
92  		}
93  		lock.commit();
94  		assertFalse(lock.isLocked());
95  		checkFile(f, "second");
96  	}
97  
98  	@Test
99  	public void testLockWriteTwiceThrows1() throws Exception {
100 		File f = writeTrashFile("somefile", "content");
101 		LockFile lock = new LockFile(f);
102 		assertTrue(lock.lock());
103 		assertTrue(lock.isLocked());
104 		lock.write("other".getBytes(StandardCharsets.US_ASCII));
105 		assertThrows(Exception.class,
106 				() -> lock.write("second".getBytes(StandardCharsets.US_ASCII)));
107 		lock.unlock();
108 	}
109 
110 	@Test
111 	public void testLockWriteTwiceThrows2() throws Exception {
112 		File f = writeTrashFile("somefile", "content");
113 		LockFile lock = new LockFile(f);
114 		assertTrue(lock.lock());
115 		assertTrue(lock.isLocked());
116 		try (OutputStream out = lock.getOutputStream()) {
117 			out.write("other".getBytes(StandardCharsets.US_ASCII));
118 		}
119 		assertThrows(Exception.class,
120 				() -> lock.write("second".getBytes(StandardCharsets.US_ASCII)));
121 		lock.unlock();
122 	}
123 
124 	@Test
125 	public void testLockWriteTwiceThrows3() throws Exception {
126 		File f = writeTrashFile("somefile", "content");
127 		LockFile lock = new LockFile(f);
128 		assertTrue(lock.lock());
129 		assertTrue(lock.isLocked());
130 		lock.write("other".getBytes(StandardCharsets.US_ASCII));
131 		assertThrows(Exception.class, () -> {
132 			try (OutputStream out = lock.getOutputStream()) {
133 				out.write("second".getBytes(StandardCharsets.US_ASCII));
134 			}
135 		});
136 		lock.unlock();
137 	}
138 
139 	@Test
140 	public void testLockWriteTwiceThrows4() throws Exception {
141 		File f = writeTrashFile("somefile", "content");
142 		LockFile lock = new LockFile(f);
143 		assertTrue(lock.lock());
144 		assertTrue(lock.isLocked());
145 		try (OutputStream out = lock.getOutputStream()) {
146 			out.write("other".getBytes(StandardCharsets.US_ASCII));
147 		}
148 		assertThrows(Exception.class, () -> {
149 			try (OutputStream out = lock.getOutputStream()) {
150 				out.write("second".getBytes(StandardCharsets.US_ASCII));
151 			}
152 		});
153 		lock.unlock();
154 	}
155 
156 	@Test
157 	public void testLockUnclosedCommitThrows() throws Exception {
158 		File f = writeTrashFile("somefile", "content");
159 		LockFile lock = new LockFile(f);
160 		assertTrue(lock.lock());
161 		assertTrue(lock.isLocked());
162 		try (OutputStream out = lock.getOutputStream()) {
163 			out.write("other".getBytes(StandardCharsets.US_ASCII));
164 			assertThrows(Exception.class, () -> lock.commit());
165 		}
166 	}
167 
168 	@Test
169 	public void testLockNested() throws Exception {
170 		File f = writeTrashFile("somefile", "content");
171 		LockFile lock = new LockFile(f);
172 		assertTrue(lock.lock());
173 		assertTrue(lock.isLocked());
174 		assertThrows(IllegalStateException.class, () -> lock.lock());
175 		assertTrue(lock.isLocked());
176 		lock.unlock();
177 	}
178 
179 	@Test
180 	public void testLockHeld() throws Exception {
181 		File f = writeTrashFile("somefile", "content");
182 		LockFile lock = new LockFile(f);
183 		assertTrue(lock.lock());
184 		assertTrue(lock.isLocked());
185 		LockFile lock2 = new LockFile(f);
186 		assertFalse(lock2.lock());
187 		assertFalse(lock2.isLocked());
188 		assertTrue(lock.isLocked());
189 		lock.unlock();
190 	}
191 
192 	@Test
193 	public void testLockForAppend() throws Exception {
194 		File f = writeTrashFile("somefile", "content");
195 		LockFile lock = new LockFile(f);
196 		assertTrue(lock.lockForAppend());
197 		assertTrue(lock.isLocked());
198 		lock.write("other".getBytes(StandardCharsets.US_ASCII));
199 		lock.commit();
200 		assertFalse(lock.isLocked());
201 		checkFile(f, "contentother");
202 	}
203 }