Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/tools/launcher/TestHelper.java
41145 views
1
/*
2
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. 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
import java.io.OutputStream;
25
import java.io.InputStream;
26
import java.lang.annotation.ElementType;
27
import java.lang.annotation.Retention;
28
import java.lang.annotation.RetentionPolicy;
29
import java.lang.annotation.Target;
30
import java.lang.reflect.Method;
31
import java.util.regex.Pattern;
32
import java.io.StringWriter;
33
import java.io.PrintWriter;
34
import java.util.Set;
35
import java.io.BufferedReader;
36
import java.io.File;
37
import java.io.FileFilter;
38
import java.io.FileNotFoundException;
39
import java.io.FileOutputStream;
40
import java.io.IOException;
41
import java.io.InputStreamReader;
42
import java.io.PrintStream;
43
import java.nio.charset.Charset;
44
import java.nio.file.attribute.BasicFileAttributes;
45
import java.nio.file.Files;
46
import java.nio.file.FileVisitResult;
47
import java.nio.file.SimpleFileVisitor;
48
import java.nio.file.Path;
49
import java.util.ArrayList;
50
import java.util.List;
51
import java.util.Locale;
52
import java.util.Map;
53
import java.util.Arrays;
54
import java.util.spi.ToolProvider;
55
56
import static java.nio.file.StandardCopyOption.*;
57
import static java.nio.file.StandardOpenOption.*;
58
59
/**
60
* This class provides some common utilities for the launcher tests.
61
*/
62
public class TestHelper {
63
// commonly used jtreg constants
64
static final File TEST_CLASSES_DIR;
65
static final File TEST_SOURCES_DIR;
66
67
static final String JAVAHOME = System.getProperty("java.home");
68
static final String JAVA_BIN;
69
static final String JAVA_LIB;
70
static final String javaCmd;
71
static final String javawCmd;
72
static final String javacCmd;
73
static final String jarCmd;
74
static final boolean haveServerVM;
75
static final boolean haveClientVM;
76
77
static final ToolProvider compiler = ToolProvider.findFirst("javac").orElse(null);
78
79
static final boolean debug = Boolean.getBoolean("TestHelper.Debug");
80
static final boolean isWindows =
81
System.getProperty("os.name", "unknown").startsWith("Windows");
82
static final boolean isMacOSX =
83
System.getProperty("os.name", "unknown").contains("OS X");
84
static final boolean is64Bit =
85
System.getProperty("sun.arch.data.model").equals("64");
86
static final boolean is32Bit =
87
System.getProperty("sun.arch.data.model").equals("32");
88
static final boolean isLinux =
89
System.getProperty("os.name", "unknown").startsWith("Linux");
90
static final boolean isAIX =
91
System.getProperty("os.name", "unknown").startsWith("AIX");
92
static final String LIBJVM = isWindows
93
? "jvm.dll"
94
: "libjvm" + (isMacOSX ? ".dylib" : ".so");
95
96
// make a note of the golden default locale
97
static final Locale DefaultLocale = Locale.getDefault();
98
99
static final String JAVA_FILE_EXT = ".java";
100
static final String CLASS_FILE_EXT = ".class";
101
static final String JAR_FILE_EXT = ".jar";
102
static final String EXE_FILE_EXT = ".exe";
103
static final String MAC_DSYM_EXT = ".dsym";
104
static final String NIX_DBGINFO_EXT = ".debuginfo";
105
static final String JLDEBUG_KEY = "_JAVA_LAUNCHER_DEBUG";
106
static final String EXPECTED_MARKER = "TRACER_MARKER:About to EXEC";
107
static final String TEST_PREFIX = "###TestError###: ";
108
109
static int testExitValue = 0;
110
111
static {
112
String tmp = System.getProperty("test.classes", null);
113
if (tmp == null) {
114
throw new Error("property test.classes not defined ??");
115
}
116
TEST_CLASSES_DIR = new File(tmp).getAbsoluteFile();
117
118
tmp = System.getProperty("test.src", null);
119
if (tmp == null) {
120
throw new Error("property test.src not defined ??");
121
}
122
TEST_SOURCES_DIR = new File(tmp).getAbsoluteFile();
123
124
if (is64Bit && is32Bit) {
125
throw new RuntimeException("arch model cannot be both 32 and 64 bit");
126
}
127
if (!is64Bit && !is32Bit) {
128
throw new RuntimeException("arch model is not 32 or 64 bit ?");
129
}
130
131
File binDir = new File(JAVAHOME, "bin");
132
JAVA_BIN = binDir.getAbsolutePath();
133
File libDir = new File(JAVAHOME, "lib");
134
JAVA_LIB = libDir.getAbsolutePath();
135
136
File javaCmdFile = (isWindows)
137
? new File(binDir, "java.exe")
138
: new File(binDir, "java");
139
javaCmd = javaCmdFile.getAbsolutePath();
140
if (!javaCmdFile.canExecute()) {
141
throw new RuntimeException("java <" + TestHelper.javaCmd +
142
"> must exist and should be executable");
143
}
144
145
File javacCmdFile = (isWindows)
146
? new File(binDir, "javac.exe")
147
: new File(binDir, "javac");
148
javacCmd = javacCmdFile.getAbsolutePath();
149
150
File jarCmdFile = (isWindows)
151
? new File(binDir, "jar.exe")
152
: new File(binDir, "jar");
153
jarCmd = jarCmdFile.getAbsolutePath();
154
if (!jarCmdFile.canExecute()) {
155
throw new RuntimeException("java <" + TestHelper.jarCmd +
156
"> must exist and should be executable");
157
}
158
159
if (isWindows) {
160
File javawCmdFile = new File(binDir, "javaw.exe");
161
javawCmd = javawCmdFile.getAbsolutePath();
162
if (!javawCmdFile.canExecute()) {
163
throw new RuntimeException("java <" + javawCmd +
164
"> must exist and should be executable");
165
}
166
} else {
167
javawCmd = null;
168
}
169
170
if (!javacCmdFile.canExecute()) {
171
throw new RuntimeException("java <" + javacCmd +
172
"> must exist and should be executable");
173
}
174
175
haveClientVM = haveVmVariant("client");
176
haveServerVM = haveVmVariant("server");
177
}
178
private static boolean haveVmVariant(String type) {
179
if (isWindows) {
180
File vmDir = new File(JAVA_BIN, type);
181
File jvmFile = new File(vmDir, LIBJVM);
182
return jvmFile.exists();
183
} else {
184
File vmDir = new File(JAVA_LIB, type);
185
File jvmFile = new File(vmDir, LIBJVM);
186
return jvmFile.exists();
187
}
188
}
189
void run(String[] args) throws Exception {
190
int passed = 0, failed = 0;
191
final Pattern p = (args != null && args.length > 0)
192
? Pattern.compile(args[0])
193
: null;
194
for (Method m : this.getClass().getDeclaredMethods()) {
195
boolean selected = (p == null)
196
? m.isAnnotationPresent(Test.class)
197
: p.matcher(m.getName()).matches();
198
if (selected) {
199
try {
200
m.invoke(this, (Object[]) null);
201
System.out.println(m.getName() + ": OK");
202
passed++;
203
System.out.printf("Passed: %d, Failed: %d, ExitValue: %d%n",
204
passed, failed, testExitValue);
205
} catch (Throwable ex) {
206
System.out.printf("Test %s failed: %s %n", m, ex);
207
System.out.println("----begin detailed exceptions----");
208
ex.printStackTrace(System.out);
209
for (Throwable t : ex.getSuppressed()) {
210
t.printStackTrace(System.out);
211
}
212
System.out.println("----end detailed exceptions----");
213
failed++;
214
}
215
}
216
}
217
System.out.printf("Total: Passed: %d, Failed %d%n", passed, failed);
218
if (failed > 0) {
219
throw new RuntimeException("Tests failed: " + failed);
220
}
221
if (passed == 0 && failed == 0) {
222
throw new AssertionError("No test(s) selected: passed = " +
223
passed + ", failed = " + failed + " ??????????");
224
}
225
}
226
227
/*
228
* usually the jre/lib/arch-name is the same as os.arch, except for x86.
229
*/
230
static String getJreArch() {
231
String arch = System.getProperty("os.arch");
232
return arch.equals("x86") ? "i386" : arch;
233
}
234
static String getArch() {
235
return System.getProperty("os.arch");
236
}
237
static File getClassFile(File javaFile) {
238
String s = javaFile.getAbsolutePath().replace(JAVA_FILE_EXT, CLASS_FILE_EXT);
239
return new File(s);
240
}
241
242
static File getJavaFile(File classFile) {
243
String s = classFile.getAbsolutePath().replace(CLASS_FILE_EXT, JAVA_FILE_EXT);
244
return new File(s);
245
}
246
247
static String baseName(File f) {
248
String s = f.getName();
249
return s.substring(0, s.indexOf("."));
250
}
251
252
/*
253
* A convenience method to create a jar with jar file name and defs
254
*/
255
static void createJar(File jarName, String... mainDefs)
256
throws FileNotFoundException{
257
createJar(null, jarName, new File("Foo"), mainDefs);
258
}
259
260
/*
261
* A convenience method to create a java file, compile and jar it up, using
262
* the sole class file name in the jar, as the Main-Class attribute value.
263
*/
264
static void createJar(File jarName, File mainClass, String... mainDefs)
265
throws FileNotFoundException {
266
createJar(null, jarName, mainClass, mainDefs);
267
}
268
269
/*
270
* A convenience method to compile java files.
271
*/
272
static void compile(String... compilerArgs) {
273
if (compiler.run(System.out, System.err, compilerArgs) != 0) {
274
String sarg = "";
275
for (String x : compilerArgs) {
276
sarg.concat(x + " ");
277
}
278
throw new Error("compilation failed: " + sarg);
279
}
280
}
281
282
/*
283
* A generic jar file creator to create a java file, compile it
284
* and jar it up, a specific Main-Class entry name in the
285
* manifest can be specified or a null to use the sole class file name
286
* as the Main-Class attribute value.
287
*/
288
static void createJar(String mEntry, File jarName, File mainClass,
289
String... mainDefs) throws FileNotFoundException {
290
if (jarName.exists()) {
291
jarName.delete();
292
}
293
try (PrintStream ps = new PrintStream(new FileOutputStream(mainClass + ".java"))) {
294
ps.println("public class Foo {");
295
if (mainDefs != null) {
296
for (String x : mainDefs) {
297
ps.println(x);
298
}
299
}
300
ps.println("}");
301
}
302
303
String compileArgs[] = {
304
mainClass + ".java"
305
};
306
if (compiler.run(System.out, System.err, compileArgs) != 0) {
307
throw new RuntimeException("compilation failed " + mainClass + ".java");
308
}
309
if (mEntry == null) {
310
mEntry = mainClass.getName();
311
}
312
String jarArgs[] = {
313
(debug) ? "cvfe" : "cfe",
314
jarName.getAbsolutePath(),
315
mEntry,
316
mainClass.getName() + ".class"
317
};
318
createJar(jarArgs);
319
}
320
321
static void createJar(String... args) {
322
List<String> cmdList = new ArrayList<>();
323
cmdList.add(jarCmd);
324
cmdList.addAll(Arrays.asList(args));
325
doExec(cmdList.toArray(new String[cmdList.size()]));
326
}
327
328
static void copyStream(InputStream in, OutputStream out) throws IOException {
329
byte[] buf = new byte[8192];
330
int n = in.read(buf);
331
while (n > 0) {
332
out.write(buf, 0, n);
333
n = in.read(buf);
334
}
335
}
336
337
static void copyFile(File src, File dst) throws IOException {
338
Path parent = dst.toPath().getParent();
339
if (parent != null) {
340
Files.createDirectories(parent);
341
}
342
Files.copy(src.toPath(), dst.toPath(), COPY_ATTRIBUTES, REPLACE_EXISTING);
343
}
344
345
/**
346
* Attempt to create a file at the given location. If an IOException
347
* occurs then back off for a moment and try again. When a number of
348
* attempts fail, give up and throw an exception.
349
*/
350
void createAFile(File aFile, List<String> lines) throws IOException {
351
createAFile(aFile, lines, true);
352
}
353
354
void createAFile(File aFile, List<String> lines, boolean endWithNewline) throws IOException {
355
IOException cause = null;
356
for (int attempts = 0; attempts < 10; attempts++) {
357
try {
358
if (endWithNewline) {
359
Files.write(aFile.getAbsoluteFile().toPath(),
360
lines, Charset.defaultCharset(),
361
CREATE, TRUNCATE_EXISTING, WRITE);
362
} else {
363
Files.write(aFile.getAbsoluteFile().toPath(),
364
String.join(System.lineSeparator(), lines).getBytes(Charset.defaultCharset()),
365
CREATE, TRUNCATE_EXISTING, WRITE);
366
}
367
if (cause != null) {
368
/*
369
* report attempts and errors that were encountered
370
* for diagnostic purposes
371
*/
372
System.err.println("Created batch file " +
373
aFile + " in " + (attempts + 1) +
374
" attempts");
375
System.err.println("Errors encountered: " + cause);
376
cause.printStackTrace();
377
}
378
return;
379
} catch (IOException ioe) {
380
if (cause != null) {
381
// chain the exceptions so they all get reported for diagnostics
382
cause.addSuppressed(ioe);
383
} else {
384
cause = ioe;
385
}
386
}
387
388
try {
389
Thread.sleep(500);
390
} catch (InterruptedException ie) {
391
if (cause != null) {
392
// cause should alway be non-null here
393
ie.addSuppressed(cause);
394
}
395
throw new RuntimeException("Interrupted while creating batch file", ie);
396
}
397
}
398
throw new RuntimeException("Unable to create batch file", cause);
399
}
400
401
static void createFile(File outFile, List<String> content) throws IOException {
402
Files.write(outFile.getAbsoluteFile().toPath(), content,
403
Charset.defaultCharset(), CREATE_NEW);
404
}
405
406
static void recursiveDelete(File target) throws IOException {
407
if (!target.exists()) {
408
return;
409
}
410
Files.walkFileTree(target.toPath(), new SimpleFileVisitor<Path>() {
411
@Override
412
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
413
try {
414
Files.deleteIfExists(dir);
415
} catch (IOException ex) {
416
System.out.println("Error: could not delete: " + dir.toString());
417
System.out.println(ex.getMessage());
418
return FileVisitResult.TERMINATE;
419
}
420
return FileVisitResult.CONTINUE;
421
}
422
@Override
423
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
424
try {
425
Files.deleteIfExists(file);
426
} catch (IOException ex) {
427
System.out.println("Error: could not delete: " + file.toString());
428
System.out.println(ex.getMessage());
429
return FileVisitResult.TERMINATE;
430
}
431
return FileVisitResult.CONTINUE;
432
}
433
});
434
}
435
436
static TestResult doExec(String...cmds) {
437
return doExec(null, null, cmds);
438
}
439
440
static TestResult doExec(Map<String, String> envToSet, String...cmds) {
441
return doExec(envToSet, null, cmds);
442
}
443
/*
444
* A method which executes a java cmd and returns the results in a container
445
*/
446
static TestResult doExec(Map<String, String> envToSet,
447
Set<String> envToRemove, String...cmds) {
448
String cmdStr = "";
449
for (String x : cmds) {
450
cmdStr = cmdStr.concat(x + " ");
451
}
452
ProcessBuilder pb = new ProcessBuilder(cmds);
453
Map<String, String> env = pb.environment();
454
if (envToRemove != null) {
455
for (String key : envToRemove) {
456
env.remove(key);
457
}
458
}
459
if (envToSet != null) {
460
env.putAll(envToSet);
461
}
462
BufferedReader rdr = null;
463
try {
464
List<String> outputList = new ArrayList<>();
465
pb.redirectErrorStream(true);
466
Process p = pb.start();
467
rdr = new BufferedReader(new InputStreamReader(p.getInputStream()));
468
String in = rdr.readLine();
469
while (in != null) {
470
outputList.add(in);
471
in = rdr.readLine();
472
}
473
p.waitFor();
474
p.destroy();
475
476
return new TestHelper.TestResult(cmdStr, p.exitValue(), outputList,
477
env, new Throwable("current stack of the test"));
478
} catch (Exception ex) {
479
ex.printStackTrace();
480
throw new RuntimeException(ex.getMessage());
481
}
482
}
483
484
static FileFilter createFilter(final String extension) {
485
return new FileFilter() {
486
@Override
487
public boolean accept(File pathname) {
488
String name = pathname.getName();
489
if (name.endsWith(extension)) {
490
return true;
491
}
492
return false;
493
}
494
};
495
}
496
497
static boolean isEnglishLocale() {
498
return Locale.getDefault().getLanguage().equals("en");
499
}
500
501
/**
502
* Helper method to initialize a simple module that just prints the passed in arguments
503
*/
504
static void createEchoArgumentsModule(File modulesDir) throws IOException {
505
if (modulesDir.exists()) {
506
recursiveDelete(modulesDir);
507
}
508
509
modulesDir.mkdirs();
510
511
File srcDir = new File(modulesDir, "src");
512
File modsDir = new File(modulesDir, "mods");
513
File testDir = new File(srcDir, "test");
514
File launcherTestDir = new File(testDir, "launcher");
515
srcDir.mkdir();
516
modsDir.mkdir();
517
testDir.mkdir();
518
launcherTestDir.mkdir();
519
520
String[] moduleInfoCode = { "module test {}" };
521
createFile(new File(testDir, "module-info.java"), Arrays.asList(moduleInfoCode));
522
523
String[] moduleCode = {
524
"package launcher;",
525
"import java.util.Arrays;",
526
"public class Main {",
527
"public static void main(String[] args) {",
528
"System.out.println(Arrays.toString(args));",
529
"}",
530
"}"
531
};
532
createFile(new File(launcherTestDir, "Main.java"), Arrays.asList(moduleCode));
533
}
534
535
static class ToolFilter implements FileFilter {
536
final List<String> exclude = new ArrayList<>();
537
protected ToolFilter(String... exclude) {
538
for (String x : exclude) {
539
String str = x + ((isWindows) ? EXE_FILE_EXT : "");
540
this.exclude.add(str.toLowerCase());
541
}
542
}
543
544
@Override
545
public boolean accept(File pathname) {
546
if (!pathname.isFile() || !pathname.canExecute()) {
547
return false;
548
}
549
String name = pathname.getName().toLowerCase();
550
if (isWindows) {
551
if (!name.endsWith(EXE_FILE_EXT)) {
552
return false;
553
}
554
} else if (isMacOSX) {
555
if (name.endsWith(MAC_DSYM_EXT)) {
556
return false;
557
}
558
} else {
559
if (name.endsWith(NIX_DBGINFO_EXT)) {
560
return false;
561
}
562
}
563
for (String x : exclude) {
564
if (name.endsWith(x)) {
565
return false;
566
}
567
}
568
return true;
569
}
570
}
571
572
/*
573
* A class to encapsulate the test results and stuff, with some ease
574
* of use methods to check the test results.
575
*/
576
static class TestResult {
577
PrintWriter status;
578
StringWriter sw;
579
int exitValue;
580
List<String> testOutput;
581
Map<String, String> env;
582
Throwable t;
583
boolean testStatus;
584
585
public TestResult(String str, int rv, List<String> oList,
586
Map<String, String> env, Throwable t) {
587
sw = new StringWriter();
588
status = new PrintWriter(sw);
589
status.println("Executed command: " + str + "\n");
590
exitValue = rv;
591
testOutput = oList;
592
this.env = env;
593
this.t = t;
594
testStatus = true;
595
}
596
597
void appendError(String x) {
598
testStatus = false;
599
testExitValue++;
600
status.println(TEST_PREFIX + x);
601
}
602
603
void indentStatus(String x) {
604
status.println(" " + x);
605
}
606
607
void checkNegative() {
608
if (exitValue == 0) {
609
appendError("test must not return 0 exit value");
610
}
611
}
612
613
void checkPositive() {
614
if (exitValue != 0) {
615
appendError("test did not return 0 exit value");
616
}
617
}
618
619
boolean isOK() {
620
return exitValue == 0;
621
}
622
623
boolean isZeroOutput() {
624
if (!testOutput.isEmpty()) {
625
appendError("No message from cmd please");
626
return false;
627
}
628
return true;
629
}
630
631
boolean isNotZeroOutput() {
632
if (testOutput.isEmpty()) {
633
appendError("Missing message");
634
return false;
635
}
636
return true;
637
}
638
639
@Override
640
public String toString() {
641
status.println("++++Begin Test Info++++");
642
status.println("Test Status: " + (testStatus ? "PASS" : "FAIL"));
643
status.println("++++Test Environment++++");
644
for (String x : env.keySet()) {
645
indentStatus(x + "=" + env.get(x));
646
}
647
status.println("++++Test Output++++");
648
for (String x : testOutput) {
649
indentStatus(x);
650
}
651
status.println("++++Test Stack Trace++++");
652
status.println(t.toString());
653
for (StackTraceElement e : t.getStackTrace()) {
654
indentStatus(e.toString());
655
}
656
status.println("++++End of Test Info++++");
657
status.flush();
658
String out = sw.toString();
659
status.close();
660
return out;
661
}
662
663
boolean contains(String str) {
664
for (String x : testOutput) {
665
if (x.contains(str)) {
666
return true;
667
}
668
}
669
appendError("string <" + str + "> not found");
670
return false;
671
}
672
673
boolean notContains(String str) {
674
for (String x : testOutput) {
675
if (x.contains(str)) {
676
appendError("string <" + str + "> found");
677
return false;
678
}
679
}
680
return true;
681
}
682
683
boolean matches(String regexToMatch) {
684
for (String x : testOutput) {
685
if (x.matches(regexToMatch)) {
686
return true;
687
}
688
}
689
appendError("regex <" + regexToMatch + "> not matched");
690
return false;
691
}
692
693
boolean notMatches(String regexToMatch) {
694
for (String x : testOutput) {
695
if (!x.matches(regexToMatch)) {
696
return true;
697
}
698
}
699
appendError("regex <" + regexToMatch + "> matched");
700
return false;
701
}
702
}
703
/**
704
* Indicates that the annotated method is a test method.
705
*/
706
@Retention(RetentionPolicy.RUNTIME)
707
@Target(ElementType.METHOD)
708
public @interface Test {}
709
}
710
711