Fri, 24 Apr 2020 03:58:51 +0100
Merge
1 /*
2 * Copyright (c) 2010, 2013, 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 */
24 /**
25 * @test
26 * @bug 6968063 7127924
27 * @summary provide examples of code that generate diagnostics
28 * @build ArgTypeCompilerFactory Example HTMLWriter RunExamples DocCommentProcessor
29 * @run main/othervm RunExamples
30 */
31 /*
32 * See CR 7127924 for info on why othervm is used.
33 */
35 import java.io.*;
36 import java.nio.file.*;
37 import java.nio.file.attribute.BasicFileAttributes;
38 import java.util.*;
39 import java.util.regex.Matcher;
40 import java.util.regex.Pattern;
42 /**
43 * Utility to run selected or all examples, writing results to
44 * stdout, a plain text file or an HTML file. This program can be
45 * run standalone, or as a jtreg test.
46 *
47 * Options:
48 * -examples dir directory of examples. Defaults to ${test.src}/examples
49 * -raw run examples with -XDrawDiagnostics
50 * -showFiles include text of source files in the output
51 * -verbose verbose output
52 * -o file write output to file: format will be HTML if
53 * file has .html extension; otherwise it will be plain text.
54 * default is to stdout
55 * -title string specify a title, only applies to HTML output
56 */
57 public class RunExamples {
58 public static void main(String... args) throws Exception {
59 jtreg = (System.getProperty("test.src") != null);
60 Path tmpDir;
61 boolean deleteOnExit;
62 if (jtreg) {
63 // use standard jtreg scratch directory: the current directory
64 tmpDir = Paths.get(System.getProperty("user.dir"));
65 deleteOnExit = false;
66 } else {
67 tmpDir = Files.createTempDirectory(Paths.get(System.getProperty("java.io.tmpdir")),
68 RunExamples.class.getName());
69 deleteOnExit = true;
70 }
71 Example.setTempDir(tmpDir.toFile());
73 RunExamples r = new RunExamples();
75 try {
76 if (r.run(args))
77 return;
78 } finally {
79 if (deleteOnExit) {
80 clean(tmpDir);
81 }
82 }
84 if (jtreg)
85 throw new Exception(r.errors + " errors occurred");
86 else
87 System.exit(1);
88 }
90 boolean run(String... args) {
91 Set<String> selectedKeys = new TreeSet<String>();
92 Set<Example> selectedExamples = new TreeSet<Example>();
93 File testSrc = new File(System.getProperty("test.src", "."));
94 File examplesDir = new File(testSrc, "examples");
95 File outFile = null;
96 boolean raw = false;
97 boolean showFiles = false;
98 boolean verbose = false;
99 boolean argTypes = false;
100 String title = null;
102 for (int i = 0; i < args.length; i++) {
103 String arg = args[i];
104 if (arg.equals("-k") && (i + 1) < args.length)
105 selectedKeys.add(args[++i]);
106 else if (arg.equals("-examples") && (i + 1) < args.length)
107 examplesDir = new File(args[++i]);
108 else if (arg.equals("-raw"))
109 raw = true;
110 else if (arg.equals("-showFiles"))
111 showFiles = true;
112 else if (arg.equals("-verbose"))
113 verbose = true;
114 else if (arg.equals("-o") && (i + 1) < args.length)
115 outFile = new File(args[++i]);
116 else if (arg.equals("-title") && (i + 1) < args.length)
117 title = args[++i];
118 else if (arg.equals("-argtypes"))
119 argTypes = true;
120 else if (arg.startsWith("-")) {
121 error("unknown option: " + arg);
122 return false;
123 } else {
124 while (i < args.length) {
125 File f = new File(examplesDir, args[i]);
126 selectedExamples.add(new Example(f));
127 i++;
128 }
129 }
130 }
132 // special mode to show message keys and the types of the args that
133 // are used.
134 if (argTypes)
135 Example.Compiler.factory = new ArgTypeCompilerFactory();
137 if (selectedKeys.size() > 0) {
138 Set<Example> examples = getExamples(examplesDir);
139 nextKey:
140 for (String k: selectedKeys) {
141 for (Example e: examples) {
142 if (e.getDeclaredKeys().contains(k))
143 continue nextKey;
144 }
145 error("Key " + k + ": no examples found");
146 }
147 } else {
148 if (selectedExamples.isEmpty())
149 selectedExamples = getExamples(examplesDir);
150 }
152 try {
153 Runner r;
154 if (outFile == null) {
155 PrintWriter out = new PrintWriter(System.out);
156 r = new TextRunner(out, showFiles, raw, verbose);
157 } else if (outFile.getName().endsWith(".html"))
158 r = new HTMLRunner(outFile, showFiles, raw, verbose, title);
159 else
160 r = new TextRunner(outFile, showFiles, raw, verbose);
161 r.run(selectedExamples);
162 r.close();
163 } catch (IOException e) {
164 error("Error writing output: " + e);
165 }
167 return (errors == 0);
168 }
170 /**
171 * Get the complete set of examples to be checked.
172 */
173 Set<Example> getExamples(File examplesDir) {
174 Set<Example> results = new TreeSet<Example>();
175 for (File f: examplesDir.listFiles()) {
176 if (isValidExample(f))
177 results.add(new Example(f));
178 }
179 return results;
180 }
182 boolean isValidExample(File f) {
183 return (f.isDirectory() && (!jtreg || f.list().length > 0)) ||
184 (f.isFile() && f.getName().endsWith(".java"));
185 }
187 /**
188 * Report an error.
189 */
190 void error(String msg) {
191 System.err.println("Error: " + msg);
192 errors++;
193 }
195 static boolean jtreg;
197 int errors;
199 /**
200 * Clean the contents of a directory.
201 */
202 static void clean(Path dir) throws IOException {
203 Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
204 @Override
205 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
206 Files.delete(file);
207 return super.visitFile(file, attrs);
208 }
210 @Override
211 public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
212 if (exc == null) Files.delete(dir);
213 return super.postVisitDirectory(dir, exc);
214 }
215 });
216 }
218 static abstract class Runner {
219 Runner(boolean showFiles, boolean raw, boolean verbose) {
220 this.showFiles = showFiles;
221 this.raw = raw;
222 this.verbose = verbose;
223 }
225 void close() throws IOException { }
227 void run(Collection<Example> examples) throws IOException {
228 for (Example e: examples) {
229 startExample(e);
230 if (showFiles) {
231 showFile(e, e.infoFile);
232 Set<File> srcFiles = new TreeSet<File>(e.srcFiles);
233 srcFiles.remove(e.infoFile);
234 showFiles(e, srcFiles);
235 showFiles(e, e.srcPathFiles);
236 showFiles(e, e.procFiles);
237 showFiles(e, e.supportFiles);
238 }
239 run(e);
240 }
241 }
243 void showFiles(Example e, Collection<File> files) throws IOException {
244 for (File f: files)
245 showFile(e, f);
246 }
248 abstract void startExample(Example e) throws IOException;
250 abstract void showFile(Example e, File f) throws IOException;
252 abstract void run(Example e) throws IOException;
254 protected String read(File f) throws IOException {
255 byte[] bytes = new byte[(int) f.length()];
256 DataInputStream in = new DataInputStream(new FileInputStream(f));
257 try {
258 in.readFully(bytes);
259 } finally {
260 in.close();
261 }
262 return new String(bytes);
263 }
265 protected Pattern copyrightHeaderPat =
266 Pattern.compile("(?s)(/\\*.*?Copyright.*?\\*/\n)\\s*(.*)");
267 protected Pattern infoHeaderPat =
268 Pattern.compile("(?s)((?://\\s*[a-z]+:[^\n]*\n)+)\\s*(.*)");
270 protected boolean showFiles;
271 protected boolean raw;
272 protected boolean verbose;
273 }
275 static class TextRunner extends Runner {
276 TextRunner(File file, boolean showFiles, boolean raw, boolean verbose)
277 throws IOException {
278 super(showFiles, raw, verbose);
279 this.file = file;
280 out = new PrintWriter(new FileWriter(file));
281 }
283 TextRunner(PrintWriter out, boolean showFiles, boolean raw, boolean verbose)
284 throws IOException {
285 super(showFiles, raw, verbose);
286 this.out = out;
287 }
289 @Override
290 void close() {
291 if (file != null)
292 out.close();
293 }
295 @Override
296 void startExample(Example e) {
297 out.println("----- " + e.getName() + " --------------------");
298 out.println();
299 }
301 @Override
302 void showFile(Example e, File f) {
303 out.println("--- " + f);
304 String text;
305 try {
306 text = read(f);
307 } catch (IOException ex) {
308 text = "Error reading " + f + "; " + ex;
309 }
310 Matcher m = copyrightHeaderPat.matcher(text);
311 if (m.matches()) {
312 out.println("(Copyright)");
313 writeLines(m.group(2));
314 } else {
315 writeLines(text);
316 }
317 out.println();
318 }
320 @Override
321 void run(Example e) {
322 // only show Output: header if also showing files
323 if (showFiles)
324 out.println("--- Output:");
325 e.run(out, raw, verbose);
326 out.println();
327 }
329 void writeLines(String text) {
330 for (String line: text.split("\n"))
331 out.println(line);
332 }
334 File file;
335 PrintWriter out;
336 }
338 static class HTMLRunner extends Runner {
339 HTMLRunner(File file, boolean showFiles, boolean raw, boolean verbose, String title)
340 throws IOException {
341 super(showFiles, raw, verbose);
342 this.file = file;
343 PrintWriter out = new PrintWriter(new FileWriter(file));
344 html = new HTMLWriter(out);
345 html.startTag(HTMLWriter.HEAD);
346 if (title != null) {
347 html.startTag(HTMLWriter.TITLE);
348 html.write(title);
349 html.endTag(HTMLWriter.TITLE);
350 }
351 html.startTag(HTMLWriter.STYLE);
352 html.newLine();
353 html.writeLine("div.file { background-color:#e0ffe0; margin-left:30px; margin-right:30px;\n"
354 + " padding: 3px; border: thin solid silver; }");
355 html.writeLine("p.file { white-space: pre-wrap; font-family:monospace; margin: 0; }");
356 html.writeLine("div.output { background-color:#e0e0ff; margin-left:30px; margin-right:30px;\n"
357 + " padding: 3px; border: thin solid silver; }");
358 html.writeLine("p.output { white-space: pre-wrap; font-family:monospace; margin: 0; }");
359 html.writeLine("table.index { border: thin solid silver; }");
360 html.writeLine(".copyright { font-size: x-small }");
361 html.writeLine(".hidden { display:none }");
362 html.writeLine(".unhidden { display:block }");
363 html.writeLine(".odd { background-color: #e0e0e0 }");
364 html.writeLine(".even { background-color: white }");
365 html.endTag(HTMLWriter.STYLE);
366 html.startTag(HTMLWriter.SCRIPT);
367 html.writeAttr(HTMLWriter.TYPE, HTMLWriter.TEXT_JAVASCRIPT);
368 html.writeLine("\nfunction unhide(id) {\n"
369 + " var item = document.getElementById(id);\n"
370 + " if (item) {\n"
371 + " item.className=(item.className=='hidden')?'unhidden':'hidden';\n"
372 + " }\n"
373 + "}");
374 html.endTag(HTMLWriter.SCRIPT);
375 html.endTag(HTMLWriter.HEAD);
376 html.startTag(HTMLWriter.BODY);
377 if (title != null) {
378 html.startTag(TITLE_HEADER);
379 html.write(title);
380 html.endTag(TITLE_HEADER);
381 }
382 }
384 @Override
385 void close() throws IOException {
386 html.endTag(HTMLWriter.BODY);
387 html.newLine();
388 html.flush();
389 }
391 @Override
392 void run(Collection<Example> examples) throws IOException {
393 if (examples.size() > 1)
394 writeIndex(examples);
395 super.run(examples);
396 }
398 void writeIndex(Collection<Example> examples) throws IOException {
399 Map<String, Set<Example>> index = new TreeMap<String, Set<Example>>();
400 Set<String> initials = new HashSet<String>();
401 for (Example e: examples) {
402 for (String k: e.getDeclaredKeys()) {
403 Set<Example> s = index.get(k);
404 if (s == null)
405 index.put(k, s = new TreeSet<Example>());
406 s.add(e);
407 }
408 initials.add(e.getName().substring(0, 1).toUpperCase());
409 }
412 if (INDEX_HEADER != null) {
413 html.startTag(INDEX_HEADER);
414 html.write("Index");
415 html.endTag(INDEX_HEADER);
416 }
418 html.startTag(HTMLWriter.P);
419 html.writeLine("Examples: ");
420 for (char initial = 'A'; initial <= 'Z'; initial++) {
421 String s = String.valueOf(initial);
422 if (initials.contains(s)) {
423 html.writeLink("#" + s, s);
424 } else {
425 html.write(s);
426 }
427 html.newLine();
428 }
429 html.endTag(HTMLWriter.P);
431 html.startTag(HTMLWriter.TABLE);
432 html.writeAttr(HTMLWriter.CLASS, "index");
433 html.newLine();
434 int row = 0;
435 for (Map.Entry<String, Set<Example>> entry: index.entrySet()) {
436 html.startTag(HTMLWriter.TR);
437 html.writeAttr(HTMLWriter.CLASS,
438 (row++ % 2 == 0 ? "even" : "odd"));
439 html.startTag(HTMLWriter.TD);
440 html.writeAttr("valign", "top");
441 html.write(entry.getKey());
442 html.endTag(HTMLWriter.TD);
443 html.newLine();
444 html.startTag(HTMLWriter.TD);
445 html.writeAttr(HTMLWriter.ALIGN, "top");
446 String sep = "";
447 for (Example e: entry.getValue()) {
448 html.write(sep);
449 html.writeLink('#' + e.getName(), e.getName());
450 sep = ", ";
451 }
452 html.endTag(HTMLWriter.TD);
453 html.endTag(HTMLWriter.TR);
454 html.newLine();
455 }
456 html.endTag(HTMLWriter.TABLE);
457 }
459 @Override
460 void startExample(Example e) throws IOException {
461 String name = e.getName();
462 String initial = name.substring(0, 1).toUpperCase();
463 if (!initial.equals(currInitial)) {
464 html.writeLinkDestination(initial, "");
465 currInitial = initial;
466 }
467 html.writeLinkDestination(name, "");
468 html.startTag(EXAMPLE_HEADER);
469 html.write(e.getName());
470 html.endTag(EXAMPLE_HEADER);
471 }
473 @Override
474 void showFile(Example e, File f) throws IOException {
475 String text;
476 try {
477 text = read(f);
478 } catch (IOException ex) {
479 text = "Error reading " + f + ": " + ex;
480 }
481 if (!f.equals(e.file)) {
482 html.startTag(FILE_HEADER);
483 html.write(e.file.toURI().relativize(f.toURI()).toString());
484 html.endTag(FILE_HEADER);
485 }
486 html.startTag(HTMLWriter.DIV);
487 html.writeAttr(CLASS, FILE);
489 String legalHeader;
490 Matcher m1 = copyrightHeaderPat.matcher(text);
491 if (m1.matches()) {
492 legalHeader = m1.group(1);
493 text = m1.group(2);
494 } else
495 legalHeader = null;
497 String infoHeader;
498 Matcher m2 = infoHeaderPat.matcher(text);
499 if (m2.matches()) {
500 infoHeader = m2.group(1);
501 text = m2.group(2);
502 } else
503 infoHeader = null;
505 String legalId = null, infoId = null;
506 if (legalHeader != null || infoHeader != null) {
507 String sep = "";
508 html.startTag(HTMLWriter.SPAN);
509 html.writeStyleAttr("float: right");
510 if (legalHeader != null) {
511 legalId = nextId();
512 html.startTag(HTMLWriter.A);
513 html.writeAttr(HTMLWriter.HREF, "javascript:unhide('" + legalId + "');");
514 //html.writeEntity("©");
515 html.write("Copyright");
516 html.endTag(HTMLWriter.A);
517 sep = ", ";
518 }
519 if (infoHeader != null) {
520 html.write(sep);
521 infoId = nextId();
522 html.startTag(HTMLWriter.A);
523 html.writeAttr(HTMLWriter.HREF, "javascript:unhide('" + infoId + "');");
524 html.write("Info");
525 html.endTag(HTMLWriter.A);
526 sep = ", ";
527 }
528 html.endTag(HTMLWriter.SPAN);
529 }
531 html.startTag(HTMLWriter.P);
532 html.writeAttr(CLASS, FILE);
533 if (legalHeader != null) {
534 html.startTag(HTMLWriter.SPAN);
535 html.writeAttr(HTMLWriter.CLASS, "hidden");
536 html.writeAttr(HTMLWriter.ID, legalId);
537 html.write(legalHeader);
538 html.newLine();
539 html.endTag(HTMLWriter.SPAN);
540 }
541 if (infoHeader != null) {
542 html.startTag(HTMLWriter.SPAN);
543 html.writeAttr(HTMLWriter.CLASS, "hidden");
544 html.writeAttr(HTMLWriter.ID, infoId);
545 html.write(infoHeader);
546 html.newLine();
547 html.endTag(HTMLWriter.SPAN);
548 }
549 html.write(text);
550 html.endTag(HTMLWriter.P);
552 html.endTag(HTMLWriter.DIV);
553 }
555 @Override
556 void run(Example e) throws IOException {
557 StringWriter sw = new StringWriter();
558 PrintWriter pw = new PrintWriter(sw);
559 e.run(pw, raw, verbose);
560 pw.flush();
562 // only show Output: header if also showing files
563 if (showFiles) {
564 html.startTag(OUTPUT_HEADER);
565 html.write("Output:");
566 html.endTag(OUTPUT_HEADER);
567 }
569 html.startTag(HTMLWriter.DIV);
570 html.writeAttr(CLASS, OUTPUT);
571 html.startTag(HTMLWriter.P);
572 html.writeAttr(CLASS, OUTPUT);
573 String[] lines = sw.toString().split("\n");
574 for (String line: lines) {
575 html.write(line);
576 html.newLine();
577 }
578 html.endTag(HTMLWriter.P);
579 html.endTag(HTMLWriter.DIV);
580 }
582 String nextId() {
583 return "id" + (nextId++);
584 }
586 File file;
587 HTMLWriter html;
588 int nextId;
589 String currInitial = "";
591 static final String TITLE_HEADER = HTMLWriter.H3;
592 static final String INDEX_HEADER = HTMLWriter.H4;
593 static final String EXAMPLE_HEADER = HTMLWriter.H4;
594 static final String FILE_HEADER = HTMLWriter.H5;
595 static final String OUTPUT_HEADER = HTMLWriter.H5;
596 static final String CLASS = "class";
597 static final String FILE = "file";
598 static final String OUTPUT = "output";
599 }
600 }