Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/nio/file/Files/SubstDrive.java
41153 views
1
/*
2
* Copyright (c) 2020 Microsoft Corporation. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
import java.util.Map;
26
import java.util.Optional;
27
import java.util.stream.Stream;
28
import java.io.IOException;
29
import java.io.UnsupportedEncodingException;
30
import java.io.ByteArrayOutputStream;
31
import java.io.PrintStream;
32
import java.nio.charset.StandardCharsets;
33
import java.nio.file.*;
34
35
import static org.testng.Assert.*;
36
import org.testng.annotations.BeforeClass;
37
import org.testng.annotations.AfterClass;
38
import org.testng.annotations.AfterMethod;
39
import org.testng.annotations.Test;
40
import org.testng.SkipException;
41
42
import jdk.test.lib.process.ProcessTools;
43
import jdk.test.lib.process.OutputAnalyzer;
44
45
/* @test
46
* @summary Test Files' public APIs with drives created using the subst command on Windows.
47
* @requires (os.family == "windows")
48
* @library /test/lib ..
49
* @build SubstDrive
50
* @run testng SubstDrive
51
*/
52
public class SubstDrive {
53
54
private static Path SUBST_DRIVE;
55
private static Path TEST_TEMP_DIRECTORY;
56
57
/**
58
* Setup for the test:
59
* + Create a temporary directory where all subsequently created temp
60
* directories will be in. This directory and all of its contents will be
61
* deleted when the test finishes.
62
* + Find a drive that is available for use with subst.
63
*/
64
@BeforeClass
65
public void setup() throws IOException {
66
TEST_TEMP_DIRECTORY = Files.createTempDirectory("tmp");
67
System.out.printf("Test directory is at %s\n", TEST_TEMP_DIRECTORY);
68
69
Optional<Path> substDrive = findAvailableDrive(TEST_TEMP_DIRECTORY);
70
if (!substDrive.isPresent()) {
71
throw new SkipException(
72
"Could not find any available drive to use with subst, skipping the tests");
73
}
74
SUBST_DRIVE = substDrive.get();
75
System.out.printf("Using drive %s\n with subst", SUBST_DRIVE);
76
}
77
78
/**
79
* Delete the root temporary directory together with all of its contents
80
* when all tests finish.
81
*/
82
@AfterClass
83
public void removeRootTempDirectory() throws IOException {
84
TestUtil.removeAll(TEST_TEMP_DIRECTORY);
85
}
86
87
/**
88
* Each test method maps drive `SUBST_DRIVE` to a temporary directory,
89
* unmap the drive after every test so that subsequent ones can reuse
90
* the drive.
91
*/
92
@AfterMethod
93
public void deleteSubstDrive() throws IOException {
94
Stream<String> substitutedDrives = substFindMappedDrives();
95
// Only delete `SUBST_DRIVE` if it is currently being substituted
96
if (substitutedDrives.anyMatch(e -> e.contains(SUBST_DRIVE.toString()))) {
97
substDelete(SUBST_DRIVE);
98
}
99
}
100
101
/**
102
* Test whether files can be created in the substituted drive.
103
*/
104
@Test
105
public void testCreateAndDeleteFile() throws IOException {
106
Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
107
substCreate(SUBST_DRIVE, tempDirectory);
108
109
String fileContents = "Hello world!";
110
Path p = Path.of(SUBST_DRIVE.toString(), "testFile.txt");
111
Files.createFile(p);
112
113
assertTrue(Files.exists(p));
114
115
Files.writeString(p, fileContents);
116
assertEquals(Files.readString(p), fileContents);
117
}
118
119
/**
120
* Test if we can delete the substituted drive (essentially just a directory).
121
*/
122
@Test
123
public void testDeleteSubstitutedDrive() throws IOException {
124
Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
125
substCreate(SUBST_DRIVE, tempDirectory);
126
127
assertTrue(Files.exists(tempDirectory));
128
Files.delete(SUBST_DRIVE);
129
assertTrue(Files.notExists(tempDirectory));
130
}
131
132
/**
133
* Test if the attributes returned by the Files' APIs are consistent when
134
* using the actual path and the substituted path.
135
*/
136
@Test
137
public void testAttributes() throws IOException {
138
Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
139
substCreate(SUBST_DRIVE, tempDirectory);
140
141
assertTrue(Files.isSameFile(tempDirectory, SUBST_DRIVE));
142
143
assertEquals(
144
Files.isExecutable(tempDirectory),
145
Files.isExecutable(SUBST_DRIVE));
146
147
assertEquals(
148
Files.isReadable(tempDirectory),
149
Files.isReadable(SUBST_DRIVE));
150
151
assertEquals(
152
Files.isDirectory(tempDirectory),
153
Files.isDirectory(SUBST_DRIVE));
154
155
assertEquals(
156
Files.isHidden(tempDirectory),
157
Files.isHidden(SUBST_DRIVE));
158
159
assertEquals(
160
Files.isRegularFile(tempDirectory),
161
Files.isRegularFile(SUBST_DRIVE));
162
163
assertEquals(
164
Files.isSymbolicLink(tempDirectory),
165
Files.isSymbolicLink(SUBST_DRIVE));
166
167
assertEquals(
168
Files.getOwner(tempDirectory),
169
Files.getOwner(SUBST_DRIVE));
170
171
assertEquals(
172
Files.isWritable(tempDirectory),
173
Files.isWritable(SUBST_DRIVE));
174
}
175
176
/**
177
* Test if setting attributes for a substituted path works the same way
178
* as it would for a real path.
179
*/
180
@Test
181
public void testGetSetAttributes() throws IOException {
182
Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
183
substCreate(SUBST_DRIVE, tempDirectory);
184
185
Files.setAttribute(SUBST_DRIVE, "dos:hidden", true);
186
assertTrue(Files.isHidden(SUBST_DRIVE));
187
assertTrue(Files.isHidden(tempDirectory));
188
189
Files.setAttribute(tempDirectory, "dos:hidden", false);
190
assertFalse(Files.isHidden(SUBST_DRIVE));
191
assertFalse(Files.isHidden(tempDirectory));
192
193
Map<String, Object> attr1 = Files.readAttributes(SUBST_DRIVE, "*");
194
Map<String, Object> attr2 = Files.readAttributes(tempDirectory, "*");
195
assertEquals(attr1, attr2);
196
}
197
198
/**
199
* Test if the FileStores returned from using substituted path and real path
200
* are the same.
201
*/
202
@Test
203
public void testFileStore() throws IOException {
204
Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
205
substCreate(SUBST_DRIVE, tempDirectory);
206
207
FileStore fileStore1 = Files.getFileStore(tempDirectory);
208
FileStore fileStore2 = Files.getFileStore(SUBST_DRIVE);
209
210
assertEquals(
211
fileStore1.getTotalSpace(),
212
fileStore2.getTotalSpace());
213
214
assertEquals(
215
fileStore1.getBlockSize(),
216
fileStore2.getBlockSize());
217
218
assertEquals(
219
fileStore1.name(),
220
fileStore2.name());
221
222
assertEquals(
223
fileStore1.type(),
224
fileStore2.type());
225
226
assertEquals(
227
SUBST_DRIVE.getFileSystem().getRootDirectories(),
228
tempDirectory.getFileSystem().getRootDirectories());
229
}
230
231
/**
232
* Test if Files.copy works correctly on a substituted drive, and that
233
* all of the attributes are the same.
234
*/
235
@Test
236
public void testMoveAndCopySubstDrive() throws IOException {
237
Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
238
Path tempDirectoryCopy = Path.of(tempDirectory.toString() + "_copy");
239
240
substCreate(SUBST_DRIVE, tempDirectory);
241
242
Files.copy(SUBST_DRIVE, tempDirectoryCopy);
243
244
assertEquals(
245
Files.isExecutable(SUBST_DRIVE),
246
Files.isExecutable(tempDirectoryCopy));
247
248
assertEquals(
249
Files.isReadable(SUBST_DRIVE),
250
Files.isReadable(tempDirectoryCopy));
251
252
assertEquals(
253
Files.isDirectory(SUBST_DRIVE),
254
Files.isDirectory(tempDirectoryCopy));
255
256
assertEquals(
257
Files.isHidden(SUBST_DRIVE),
258
Files.isHidden(tempDirectoryCopy));
259
260
assertEquals(
261
Files.isRegularFile(SUBST_DRIVE),
262
Files.isRegularFile(tempDirectoryCopy));
263
264
assertEquals(
265
Files.isWritable(SUBST_DRIVE),
266
Files.isWritable(tempDirectoryCopy));
267
268
assertEquals(
269
Files.getOwner(SUBST_DRIVE),
270
Files.getOwner(tempDirectoryCopy));
271
}
272
273
/**
274
* Test if the attributes of a resolved symlink are the same as its target's
275
* Note: requires administrator privileges.
276
*/
277
@Test
278
public void testGetResolvedSymlinkAttribute() throws IOException {
279
if (!TestUtil.supportsLinks(TEST_TEMP_DIRECTORY)) {
280
return;
281
}
282
283
Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
284
substCreate(SUBST_DRIVE, tempDirectory);
285
286
Path tempFile = Path.of(SUBST_DRIVE.toString(), "test.txt");
287
String contents = "Hello world!";
288
Files.writeString(tempFile, contents);
289
assertEquals(Files.readString(tempFile), contents);
290
291
Path link = Path.of(SUBST_DRIVE.toString(), "link");
292
Files.createSymbolicLink(link, tempFile);
293
294
assertEquals(Files.readString(link), contents);
295
assertEquals(Files.isExecutable(link), Files.isExecutable(tempFile));
296
assertEquals(Files.isReadable(link), Files.isReadable(tempFile));
297
assertEquals(Files.isDirectory(link), Files.isDirectory(tempFile));
298
assertEquals(Files.isHidden(link), Files.isHidden(tempFile));
299
assertEquals(Files.isRegularFile(link), Files.isRegularFile(tempFile));
300
assertEquals(Files.isWritable(link), Files.isWritable(tempFile));
301
assertEquals(Files.getOwner(link), Files.getOwner(tempFile));
302
}
303
304
/**
305
* Test if files and directories can be created, moved, and cut when the
306
* substituted drive is a symlink.
307
* Note: requires administrator privileges.
308
*/
309
@Test
310
public void testSubstWithSymlinkedDirectory() throws IOException {
311
if (!TestUtil.supportsLinks(TEST_TEMP_DIRECTORY)) {
312
return;
313
}
314
315
Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
316
Path tempLink = Path.of(tempDirectory.toString() + "_link");
317
Files.createSymbolicLink(tempLink, tempDirectory);
318
319
substCreate(SUBST_DRIVE, tempLink);
320
321
assertEquals(
322
Files.readAttributes(SUBST_DRIVE, "*"),
323
Files.readAttributes(tempDirectory, "*"));
324
325
assertTrue(Files.isWritable(SUBST_DRIVE));
326
327
Path tempFile = Files.createTempFile(SUBST_DRIVE, "prefix", "suffix");
328
String contents = "Hello world!";
329
Files.writeString(tempFile, contents);
330
assertEquals(Files.readString(tempFile), contents);
331
332
Path tempDirectory2 = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
333
Path copy = Path.of(tempDirectory2.toString(), "copied");
334
Files.copy(tempFile, copy);
335
336
assertTrue(Files.exists(copy));
337
assertEquals(Files.readString(copy), contents);
338
339
Path cut = Path.of(tempDirectory2.toString(), "cut");
340
Files.move(tempFile, cut);
341
assertTrue(Files.notExists(tempFile));
342
assertTrue(Files.exists(cut));
343
assertEquals(Files.readString(cut), contents);
344
}
345
346
/**
347
* When the substituted drive is a symlink, test if it has the same
348
* attributes as its target.
349
* Note: requires administrator privileges.
350
*/
351
@Test
352
public void testMoveAndCopyFilesToSymlinkedDrive() throws IOException {
353
if (!TestUtil.supportsLinks(TEST_TEMP_DIRECTORY)) {
354
return;
355
}
356
357
Path tempDirectory = Files.createTempDirectory(TEST_TEMP_DIRECTORY, "tmp");
358
Path tempLink = Path.of(tempDirectory.toString() + "_link");
359
Files.createSymbolicLink(tempLink, tempDirectory);
360
361
substCreate(SUBST_DRIVE, tempLink);
362
363
assertEquals(
364
Files.readAttributes(SUBST_DRIVE, "*"),
365
Files.readAttributes(tempDirectory, "*"));
366
367
assertTrue(Files.isWritable(SUBST_DRIVE));
368
}
369
370
/**
371
* Run a command and optionally prints stdout contents to
372
* `customOutputStream`.
373
*/
374
private void runCmd(ProcessBuilder pb, PrintStream customOutputStream) {
375
try {
376
PrintStream ps = customOutputStream != null ?
377
customOutputStream :
378
System.out;
379
OutputAnalyzer outputAnalyzer = ProcessTools.executeCommand(pb)
380
.outputTo(ps)
381
.errorTo(System.err);
382
383
int exitCode = outputAnalyzer.getExitValue();
384
assertEquals(
385
exitCode /* actual value */,
386
0 /* expected value */,
387
String.format(
388
"Command `%s` failed with exit code %d",
389
pb.command(),
390
exitCode
391
)
392
);
393
394
} catch (Throwable t) {
395
throw new RuntimeException(t);
396
}
397
}
398
399
/**
400
* Helper to map a path to a drive letter using subst.
401
* For reference, see:
402
* https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/subst
403
*/
404
private void substCreate(Path drive, Path path) {
405
runCmd(
406
new ProcessBuilder(
407
"cmd", "/c", "subst", drive.toString(), path.toString()),
408
null /* customOutputStream */);
409
}
410
411
/**
412
* Delete a drive mapping using subst.
413
* For reference, see:
414
* https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/subst
415
*/
416
private void substDelete(Path drive) throws IOException {
417
runCmd(
418
new ProcessBuilder(
419
"cmd", "/c", "subst", drive.toString(), "/D"),
420
null /* customOutputStream */);
421
}
422
423
/**
424
* Return a list of strings that represents all the currently mapped drives.
425
* For instance, with the following output of subst:
426
* A:\: => path1
427
* B:\: => path2
428
* T:\: => path3
429
* X:\: => path4
430
* The function returns: ["A:\", "B:\", "T:\", "X:\"]
431
* For reference, see:
432
* https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/subst
433
*/
434
private Stream<String> substFindMappedDrives() throws UnsupportedEncodingException {
435
ByteArrayOutputStream baos = new ByteArrayOutputStream();
436
String utf8 = StandardCharsets.UTF_8.name();
437
try (PrintStream ps = new PrintStream(baos, true, utf8)) {
438
// subst without any arguments returns a list of drives that
439
// are being substituted
440
runCmd(new ProcessBuilder("cmd", "/c", "subst"), ps);
441
String stdout = baos.toString(utf8);
442
return stdout
443
// split lines
444
.lines()
445
// only examine lines with "=>"
446
.filter(line -> line.contains("=>"))
447
// split each line into 2 components and take the first one
448
.map(line -> line.split("=>")[0].trim());
449
}
450
}
451
452
/**
453
* subst can fail if the drive to be mapped already exists. The method returns
454
* a drive that is available.
455
*/
456
private Optional<Path> findAvailableDrive(Path tempDirectory) {
457
for (char letter = 'Z'; letter >= 'A'; letter--) {
458
try {
459
Path p = Path.of(letter + ":");
460
substCreate(p, tempDirectory);
461
substDelete(p);
462
return Optional.of(p);
463
} catch (Throwable t) {
464
// fall through
465
}
466
}
467
return Optional.empty();
468
}
469
}
470
471