1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.eclipse.jgit.util;
45
46 import static java.time.Instant.EPOCH;
47 import static org.junit.Assert.assertEquals;
48 import static org.junit.Assert.assertFalse;
49 import static org.junit.Assert.assertTrue;
50 import static org.junit.Assume.assumeTrue;
51
52 import java.io.File;
53 import java.io.IOException;
54 import java.nio.charset.Charset;
55 import java.nio.file.Files;
56 import java.nio.file.Path;
57 import java.nio.file.attribute.FileTime;
58 import java.nio.file.attribute.PosixFileAttributeView;
59 import java.nio.file.attribute.PosixFilePermission;
60 import java.time.Duration;
61 import java.time.ZoneId;
62 import java.time.format.DateTimeFormatter;
63 import java.util.Locale;
64 import java.util.Set;
65 import java.util.concurrent.TimeUnit;
66
67 import org.eclipse.jgit.errors.CommandFailedException;
68 import org.eclipse.jgit.junit.MockSystemReader;
69 import org.eclipse.jgit.junit.RepositoryTestCase;
70 import org.eclipse.jgit.lib.RepositoryCache;
71 import org.junit.After;
72 import org.junit.Assume;
73 import org.junit.Before;
74 import org.junit.Test;
75
76 public class FSTest {
77 private File trash;
78
79 @Before
80 public void setUp() throws Exception {
81 SystemReader.setInstance(new MockSystemReader());
82 trash = File.createTempFile("tmp_", "");
83 trash.delete();
84 assertTrue("mkdir " + trash, trash.mkdir());
85 }
86
87 @After
88 public void tearDown() throws Exception {
89 FileUtils.delete(trash, FileUtils.RECURSIVE | FileUtils.RETRY);
90 }
91
92
93
94
95
96
97
98
99
100
101
102 @Test
103 public void testSymlinkAttributes() throws IOException, InterruptedException {
104 Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
105 FS fs = FS.DETECTED;
106 File link = new File(trash, "ä");
107 File target = new File(trash, "å");
108 fs.createSymLink(link, "å");
109 assertTrue(fs.exists(link));
110 String targetName = fs.readSymLink(link);
111 assertEquals("å", targetName);
112 assertTrue(fs.lastModifiedInstant(link).compareTo(EPOCH) > 0);
113 assertTrue(fs.exists(link));
114 assertFalse(fs.canExecute(link));
115 assertEquals(2, fs.length(link));
116 assertFalse(fs.exists(target));
117 assertFalse(fs.isFile(target));
118 assertFalse(fs.isDirectory(target));
119 assertFalse(fs.canExecute(target));
120
121 RepositoryTestCase.fsTick(link);
122
123 FileUtils.createNewFile(target);
124 assertTrue(fs.exists(link));
125 assertTrue(fs.lastModifiedInstant(link).compareTo(EPOCH) > 0);
126 assertTrue(fs.lastModifiedInstant(target)
127 .compareTo(fs.lastModifiedInstant(link)) > 0);
128 assertFalse(fs.canExecute(link));
129 fs.setExecute(target, true);
130 assertFalse(fs.canExecute(link));
131 assumeTrue(fs.supportsExecute());
132 assertTrue(fs.canExecute(target));
133 }
134
135 @Test
136 public void testExecutableAttributes() throws Exception {
137 FS fs = FS.DETECTED.newInstance();
138
139 assumeTrue(fs instanceof FS_POSIX);
140 ((FS_POSIX) fs).setUmask(0022);
141
142 File f = new File(trash, "bla");
143 assertTrue(f.createNewFile());
144 assertFalse(fs.canExecute(f));
145
146 Set<PosixFilePermission> permissions = readPermissions(f);
147 assertTrue(!permissions.contains(PosixFilePermission.OTHERS_EXECUTE));
148 assertTrue(!permissions.contains(PosixFilePermission.GROUP_EXECUTE));
149 assertTrue(!permissions.contains(PosixFilePermission.OWNER_EXECUTE));
150
151 fs.setExecute(f, true);
152
153 permissions = readPermissions(f);
154 assertTrue("'owner' execute permission not set",
155 permissions.contains(PosixFilePermission.OWNER_EXECUTE));
156 assertTrue("'group' execute permission not set",
157 permissions.contains(PosixFilePermission.GROUP_EXECUTE));
158 assertTrue("'others' execute permission not set",
159 permissions.contains(PosixFilePermission.OTHERS_EXECUTE));
160
161 ((FS_POSIX) fs).setUmask(0033);
162 fs.setExecute(f, false);
163 assertFalse(fs.canExecute(f));
164 fs.setExecute(f, true);
165
166 permissions = readPermissions(f);
167 assertTrue("'owner' execute permission not set",
168 permissions.contains(PosixFilePermission.OWNER_EXECUTE));
169 assertFalse("'group' execute permission set",
170 permissions.contains(PosixFilePermission.GROUP_EXECUTE));
171 assertFalse("'others' execute permission set",
172 permissions.contains(PosixFilePermission.OTHERS_EXECUTE));
173 }
174
175 private Set<PosixFilePermission> readPermissions(File f) throws IOException {
176 return Files
177 .getFileAttributeView(f.toPath(), PosixFileAttributeView.class)
178 .readAttributes().permissions();
179 }
180
181 @Test(expected = CommandFailedException.class)
182 public void testReadPipePosixCommandFailure()
183 throws CommandFailedException {
184 FS fs = FS.DETECTED.newInstance();
185 assumeTrue(fs instanceof FS_POSIX);
186
187 FS.readPipe(fs.userHome(),
188 new String[] { "/bin/sh", "-c", "exit 1" },
189 Charset.defaultCharset().name());
190 }
191
192 @Test(expected = CommandFailedException.class)
193 public void testReadPipeCommandStartFailure()
194 throws CommandFailedException {
195 FS fs = FS.DETECTED.newInstance();
196
197 FS.readPipe(fs.userHome(),
198 new String[] { "this-command-does-not-exist" },
199 Charset.defaultCharset().name());
200 }
201
202 @Test
203 public void testFsTimestampResolution() throws Exception {
204 DateTimeFormatter formatter = DateTimeFormatter
205 .ofPattern("uuuu-MMM-dd HH:mm:ss.nnnnnnnnn", Locale.ENGLISH)
206 .withZone(ZoneId.systemDefault());
207 Path dir = Files.createTempDirectory("probe-filesystem");
208 Duration resolution = FS.getFileStoreAttributes(dir)
209 .getFsTimestampResolution();
210 long resolutionNs = resolution.toNanos();
211 assertTrue(resolutionNs > 0);
212 for (int i = 0; i < 10; i++) {
213 Path f = null;
214 try {
215 f = dir.resolve("testTimestampResolution" + i);
216 Files.createFile(f);
217 FileUtils.touch(f);
218 FileTime t1 = Files.getLastModifiedTime(f);
219 TimeUnit.NANOSECONDS.sleep(resolutionNs);
220 FileUtils.touch(f);
221 FileTime t2 = Files.getLastModifiedTime(f);
222 assertTrue(String.format(
223 "expected t2=%s to be larger than t1=%s\nsince file timestamp resolution was measured to be %,d ns",
224 formatter.format(t2.toInstant()),
225 formatter.format(t1.toInstant()),
226 Long.valueOf(resolutionNs)), t2.compareTo(t1) > 0);
227 } finally {
228 Files.delete(f);
229 }
230 }
231 }
232
233
234 @Test
235 public void testRepoCacheRelativePathUnbornRepo() {
236 assertFalse(RepositoryCache.FileKey
237 .isGitRepository(new File("repo.git"), FS.DETECTED));
238 }
239 }