1 /*
2 * Copyright (c) 2015, 2018, 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.ByteArrayOutputStream;
25 import java.io.IOException;
26 import java.io.OutputStream;
27 import java.io.PrintStream;
28 import java.util.ArrayList;
29 import java.util.Arrays;
octeon_ddr_conf_table_get(int * count,int * def_ddr_freq)30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Locale;
34 import java.util.Map;
35 import java.util.function.Consumer;
36 import java.util.function.Function;
37 import java.util.function.Predicate;
board_fix_fdt(void * fdt)38 import java.util.logging.Level;
39 import java.util.logging.Logger;
40 import java.util.prefs.AbstractPreferences;
41 import java.util.prefs.BackingStoreException;
42 import java.util.regex.Matcher;
43 import java.util.regex.Pattern;
44 import java.util.stream.Collectors;
45 import java.util.stream.Stream;
46
47
48 import org.testng.annotations.BeforeMethod;
49
50 import jdk.jshell.tool.JavaShellToolBuilder;
51 import static java.util.stream.Collectors.toList;
52 import static org.testng.Assert.assertEquals;
53 import static org.testng.Assert.assertNotNull;
54 import static org.testng.Assert.assertTrue;
55 import static org.testng.Assert.fail;
56
57 public class ReplToolTesting {
58
59 private final static String DEFAULT_STARTUP_MESSAGE = "| Welcome to";
60 final static List<ImportInfo> START_UP_IMPORTS = Stream.of(
61 "java.io.*",
62 "java.math.*",
63 "java.net.*",
64 "java.nio.file.*",
65 "java.util.*",
66 "java.util.concurrent.*",
67 "java.util.function.*",
68 "java.util.prefs.*",
69 "java.util.regex.*",
70 "java.util.stream.*")
71 .map(s -> new ImportInfo("import " + s + ";", "", s))
72 .collect(toList());
73 final static List<MethodInfo> START_UP_METHODS = Stream.<MethodInfo>of()
74 .collect(toList());
75 final static List<String> START_UP_CMD_METHOD = Stream.<String>of()
76 .collect(toList());
77 final static List<String> PRINTING_CMD_METHOD = Stream.of(
78 "| void print(boolean)",
79 "| void print(char)",
80 "| void print(int)",
81 "| void print(long)",
82 "| void print(float)",
83 "| void print(double)",
84 "| void print(char s[])",
85 "| void print(String)",
86 "| void print(Object)",
board_configure_qlms(void)87 "| void println()",
88 "| void println(boolean)",
89 "| void println(char)",
90 "| void println(int)",
91 "| void println(long)",
92 "| void println(float)",
93 "| void println(double)",
94 "| void println(char s[])",
95 "| void println(String)",
96 "| void println(Object)",
97 "| void printf(java.util.Locale,String,Object...)",
98 "| void printf(String,Object...)")
99 .collect(toList());
100 final static List<String> START_UP = Collections.unmodifiableList(
board_late_init(void)101 Stream.concat(START_UP_IMPORTS.stream(), START_UP_METHODS.stream())
102 .map(s -> s.getSource())
103 .collect(toList()));
104
105 private WaitingTestingInputStream cmdin = null;
106 private ByteArrayOutputStream cmdout = null;
107 private ByteArrayOutputStream cmderr = null;
108 private PromptedCommandOutputStream console = null;
109 private TestingInputStream userin = null;
110 private ByteArrayOutputStream userout = null;
111 private ByteArrayOutputStream usererr = null;
112
113 private List<MemberInfo> keys;
114 private Map<String, VariableInfo> variables;
115 private Map<String, MethodInfo> methods;
116 private Map<String, ClassInfo> classes;
117 private Map<String, ImportInfo> imports;
118 private boolean isDefaultStartUp = true;
119 protected Map<String, String> prefsMap;
120 private Map<String, String> envvars;
121
122 public interface ReplTest {
123 void run(boolean after);
124 }
125
126 public void setCommandInput(String s) {
127 cmdin.setInput(s);
128 }
129
130 public void closeCommandInput() {
131 try {
132 cmdin.close();
133 } catch (IOException ex) {
134 throw new IllegalStateException(ex);
135 }
136 }
137
138 public final static Pattern idPattern = Pattern.compile("^\\s+(\\d+)");
139 public Consumer<String> assertList() {
140 return s -> {
141 List<String> lines = Stream.of(s.split("\n"))
142 .filter(l -> !l.isEmpty())
143 .collect(Collectors.toList());
144 int previousId = Integer.MIN_VALUE;
145 assertEquals(lines.size(), keys.size(), "Number of keys");
146 for (int i = 0; i < lines.size(); ++i) {
147 String line = lines.get(i);
148 Matcher matcher = idPattern.matcher(line);
149 assertTrue(matcher.find(), "Snippet id not found: " + line);
150 String src = keys.get(i).getSource();
151 assertTrue(line.endsWith(src), "Line '" + line + "' does not end with: " + src);
152 int id = Integer.parseInt(matcher.group(1));
153 assertTrue(previousId < id,
154 String.format("The previous id is not less than the next one: previous: %d, next: %d",
155 previousId, id));
156 previousId = id;
157 }
158 };
159 }
160
161 private final static Pattern extractPattern = Pattern.compile("^\\| *(.*)$");
162 private Consumer<String> assertMembers(String message, Map<String, ? extends MemberInfo> set) {
163 return s -> {
164 List<String> lines = Stream.of(s.split("\n"))
165 .filter(l -> !l.isEmpty())
166 .filter(l -> !l.startsWith("| ")) // error/unresolved info
167 .collect(Collectors.toList());
168 assertEquals(lines.size(), set.size(), message + " : expected: " + set.keySet() + "\ngot:\n" + lines);
169 for (String line : lines) {
170 Matcher matcher = extractPattern.matcher(line);
171 assertTrue(matcher.find(), line);
172 String src = matcher.group(1);
173 MemberInfo info = set.get(src);
174 assertNotNull(info, "Not found snippet with signature: " + src + ", line: "
175 + line + ", keys: " + set.keySet() + "\n");
176 }
177 };
178 }
179
180 public Consumer<String> assertVariables() {
181 return assertMembers("Variables", variables);
182 }
183
184 public Consumer<String> assertMethods() {
185 return assertMembers("Methods", methods);
186 }
187
188 public Consumer<String> assertClasses() {
189 return assertMembers("Classes", classes);
190 }
191
192 public Consumer<String> assertImports() {
193 return assertMembers("Imports", imports);
194 }
195
196 public String getCommandOutput() {
197 String s = normalizeLineEndings(cmdout.toString());
198 cmdout.reset();
199 return s;
200 }
201
202 public String getCommandErrorOutput() {
203 String s = normalizeLineEndings(cmderr.toString());
204 cmderr.reset();
205 return s;
206 }
207
208 public void setUserInput(String s) {
209 userin.setInput(s);
210 }
211
212 public String getUserOutput() {
213 String s = normalizeLineEndings(userout.toString());
214 userout.reset();
215 return s;
216 }
217
218 public String getUserErrorOutput() {
219 String s = normalizeLineEndings(usererr.toString());
220 usererr.reset();
221 return s;
222 }
223
224 public void test(ReplTest... tests) {
225 test(new String[0], tests);
226 }
227
228 public void test(String[] args, ReplTest... tests) {
229 test(true, args, tests);
230 }
231
232 public void test(boolean isDefaultStartUp, String[] args, ReplTest... tests) {
233 test(Locale.ROOT, isDefaultStartUp, args, DEFAULT_STARTUP_MESSAGE, tests);
234 }
235
236 public void testNoStartUp(ReplTest... tests) {
237 test(Locale.ROOT, false, new String[] {"--no-startup"}, DEFAULT_STARTUP_MESSAGE, tests);
238 }
239
240 public void test(Locale locale, boolean isDefaultStartUp, String[] args, String startUpMessage, ReplTest... tests) {
241 this.isDefaultStartUp = isDefaultStartUp;
242 initSnippets();
243 ReplTest[] wtests = new ReplTest[tests.length + 3];
244 wtests[0] = a -> assertCommandCheckOutput(a, "<start>",
245 s -> assertTrue(s.startsWith(startUpMessage), "Expected start-up message '" + startUpMessage + "' Got: " + s));
246 wtests[1] = a -> assertCommand(a, "/debug 0", null);
247 System.arraycopy(tests, 0, wtests, 2, tests.length);
248 wtests[tests.length + 2] = a -> assertCommand(a, "/exit", null);
249 testRaw(locale, args, wtests);
250 }
251
252 private void initSnippets() {
253 keys = new ArrayList<>();
254 variables = new HashMap<>();
255 methods = new HashMap<>();
256 classes = new HashMap<>();
257 imports = new HashMap<>();
258 if (isDefaultStartUp) {
259 methods.putAll(
260 START_UP_METHODS.stream()
261 .collect(Collectors.toMap(Object::toString, Function.identity())));
262 imports.putAll(
263 START_UP_IMPORTS.stream()
264 .collect(Collectors.toMap(Object::toString, Function.identity())));
265 }
266 }
267
268 @BeforeMethod
269 public void setUp() {
270 prefsMap = new HashMap<>();
271 prefsMap.put("INDENT", "0");
272 envvars = new HashMap<>();
273 System.setProperty("jshell.test.allow.incomplete.inputs", "true");
274 }
275
276 protected void setEnvVar(String name, String value) {
277 envvars.put(name, value);
278 }
279
280 protected JavaShellToolBuilder builder(Locale locale) {
281 // turn on logging of launch failures
282 Logger.getLogger("jdk.jshell.execution").setLevel(Level.ALL);
283 return JavaShellToolBuilder
284 .builder()
285 .in(cmdin, userin)
286 .out(new PrintStream(cmdout), new PrintStream(console), new PrintStream(userout))
287 .err(new PrintStream(cmderr), new PrintStream(usererr))
288 .persistence(prefsMap)
289 .env(envvars)
290 .locale(locale)
291 .promptCapture(true);
292 }
293
294 private void testRaw(Locale locale, String[] args, ReplTest... tests) {
295 testRawInit(tests);
296 testRawRun(locale, args);
297 testRawCheck(locale);
298 }
299
300 private void testRawInit(ReplTest... tests) {
301 cmdin = new WaitingTestingInputStream();
302 cmdout = new ByteArrayOutputStream();
303 cmderr = new ByteArrayOutputStream();
304 console = new PromptedCommandOutputStream(tests);
305 userin = new TestingInputStream();
306 userout = new ByteArrayOutputStream();
307 usererr = new ByteArrayOutputStream();
308 }
309
310 protected void testRawRun(Locale locale, String[] args) {
311 try {
312 builder(locale)
313 .run(args);
314 } catch (Exception ex) {
315 fail("Repl tool died with exception", ex);
316 }
317 }
318
319 private void testRawCheck(Locale locale) {
320 // perform internal consistency checks on state, if desired
321 String cos = getCommandOutput();
322 String ceos = getCommandErrorOutput();
323 String uos = getUserOutput();
324 String ueos = getUserErrorOutput();
325 assertTrue((cos.isEmpty() || cos.startsWith("| Goodbye") || !locale.equals(Locale.ROOT)),
326 "Expected a goodbye, but got: " + cos);
327 assertTrue(ceos.isEmpty(), "Expected empty command error output, got: " + ceos);
328 assertTrue(uos.isEmpty(), "Expected empty user output, got: " + uos);
329 assertTrue(ueos.isEmpty(), "Expected empty user error output, got: " + ueos);
330 }
331
332 public void assertReset(boolean after, String cmd) {
333 assertCommand(after, cmd, "| Resetting state.\n");
334 initSnippets();
335 }
336
337 public void evaluateExpression(boolean after, String type, String expr, String value) {
338 String output = String.format("(\\$\\d+) ==> %s", value);
339 Pattern outputPattern = Pattern.compile(output);
340 assertCommandCheckOutput(after, expr, s -> {
341 Matcher matcher = outputPattern.matcher(s);
342 assertTrue(matcher.find(), "Output: '" + s + "' does not fit pattern: '" + output + "'");
343 String name = matcher.group(1);
344 VariableInfo tempVar = new TempVariableInfo(expr, type, name, value);
345 variables.put(tempVar.toString(), tempVar);
346 addKey(after, tempVar);
347 });
348 }
349
350 public void loadVariable(boolean after, String type, String name) {
351 loadVariable(after, type, name, null, null);
352 }
353
354 public void loadVariable(boolean after, String type, String name, String expr, String value) {
355 String src = expr == null
356 ? String.format("%s %s", type, name)
357 : String.format("%s %s = %s", type, name, expr);
358 VariableInfo var = expr == null
359 ? new VariableInfo(src, type, name)
360 : new VariableInfo(src, type, name, value);
361 addKey(after, var, variables);
362 addKey(after, var);
363 }
364
365 public void assertVariable(boolean after, String type, String name) {
366 assertVariable(after, type, name, null, null);
367 }
368
369 public void assertVariable(boolean after, String type, String name, String expr, String value) {
370 String src = expr == null
371 ? String.format("%s %s", type, name)
372 : String.format("%s %s = %s", type, name, expr);
373 VariableInfo var = expr == null
374 ? new VariableInfo(src, type, name)
375 : new VariableInfo(src, type, name, value);
376 assertCommandCheckOutput(after, src, var.checkOutput());
377 addKey(after, var, variables);
378 addKey(after, var);
379 }
380
381 public void loadMethod(boolean after, String src, String signature, String name) {
382 MethodInfo method = new MethodInfo(src, signature, name);
383 addKey(after, method, methods);
384 addKey(after, method);
385 }
386
387 public void assertMethod(boolean after, String src, String signature, String name) {
388 MethodInfo method = new MethodInfo(src, signature, name);
389 assertCommandCheckOutput(after, src, method.checkOutput());
390 addKey(after, method, methods);
391 addKey(after, method);
392 }
393
394 public void loadClass(boolean after, String src, String type, String name) {
395 ClassInfo clazz = new ClassInfo(src, type, name);
396 addKey(after, clazz, classes);
397 addKey(after, clazz);
398 }
399
400 public void assertClass(boolean after, String src, String type, String name) {
401 ClassInfo clazz = new ClassInfo(src, type, name);
402 assertCommandCheckOutput(after, src, clazz.checkOutput());
403 addKey(after, clazz, classes);
404 addKey(after, clazz);
405 }
406
407 public void loadImport(boolean after, String src, String type, String name) {
408 ImportInfo i = new ImportInfo(src, type, name);
409 addKey(after, i, imports);
410 addKey(after, i);
411 }
412
413 public void assertImport(boolean after, String src, String type, String name) {
414 ImportInfo i = new ImportInfo(src, type, name);
415 assertCommandCheckOutput(after, src, i.checkOutput());
416 addKey(after, i, imports);
417 addKey(after, i);
418 }
419
420 private <T extends MemberInfo> void addKey(boolean after, T memberInfo, Map<String, T> map) {
421 if (after) {
422 map.entrySet().removeIf(e -> e.getValue().equals(memberInfo));
423 map.put(memberInfo.toString(), memberInfo);
424 }
425 }
426
427 private <T extends MemberInfo> void addKey(boolean after, T memberInfo) {
428 if (after) {
429 for (int i = 0; i < keys.size(); ++i) {
430 MemberInfo m = keys.get(i);
431 if (m.equals(memberInfo)) {
432 keys.set(i, memberInfo);
433 return;
434 }
435 }
436 keys.add(memberInfo);
437 }
438 }
439
440 private void dropKey(boolean after, String cmd, String name, Map<String, ? extends MemberInfo> map, String output) {
441 assertCommand(after, cmd, output);
442 if (after) {
443 map.remove(name);
444 for (int i = 0; i < keys.size(); ++i) {
445 MemberInfo m = keys.get(i);
446 if (m.toString().equals(name)) {
447 keys.remove(i);
448 return;
449 }
450 }
451 throw new AssertionError("Key not found: " + name + ", keys: " + keys);
452 }
453 }
454
455 public void dropVariable(boolean after, String cmd, String name, String output) {
456 dropKey(after, cmd, name, variables, output);
457 }
458
459 public void dropMethod(boolean after, String cmd, String name, String output) {
460 dropKey(after, cmd, name, methods, output);
461 }
462
463 public void dropClass(boolean after, String cmd, String name, String output) {
464 dropKey(after, cmd, name, classes, output);
465 }
466
467 public void dropImport(boolean after, String cmd, String name, String output) {
468 dropKey(after, cmd, name, imports, output);
469 }
470
471 public void assertCommand(boolean after, String cmd, String out) {
472 assertCommand(after, cmd, out, "", null, "", "");
473 }
474
475 public void assertCommandOutputContains(boolean after, String cmd, String... hasThese) {
476 assertCommandCheckOutput(after, cmd, (s)
477 -> assertTrue(Arrays.stream(hasThese)
478 .allMatch(has -> s.contains(has)),
479 "Output: \'" + s + "' does not contain: "
480 + Arrays.stream(hasThese)
481 .filter(has -> !s.contains(has))
482 .collect(Collectors.joining(", "))));
483 }
484
485 public void assertCommandOutputStartsWith(boolean after, String cmd, String starts) {
486 assertCommandCheckOutput(after, cmd, assertStartsWith(starts));
487 }
488
489 public void assertCommandCheckOutput(boolean after, String cmd, Consumer<String> check) {
490 if (!after) {
491 assertCommand(false, cmd, null);
492 } else {
493 String got = getCommandOutput();
494 check.accept(got);
495 assertCommand(true, cmd, null);
496 }
497 }
498
499 public void assertCommand(boolean after, String cmd, String out, String err,
500 String userinput, String print, String usererr) {
501 if (!after) {
502 if (userinput != null) {
503 setUserInput(userinput);
504 }
505 if (cmd.endsWith("\u0003")) {
506 setCommandInput(cmd);
507 } else {
508 setCommandInput(cmd + "\n");
509 }
510 } else {
511 assertOutput(getCommandOutput().trim(), out==null? out : out.trim(), "command output: " + cmd);
512 assertOutput(getCommandErrorOutput(), err, "command error: " + cmd);
513 assertOutput(getUserOutput(), print, "user output: " + cmd);
514 assertOutput(getUserErrorOutput(), usererr, "user error: " + cmd);
515 }
516 }
517
518 public Consumer<String> assertStartsWith(String prefix) {
519 return (output) -> {
520 if (!output.trim().startsWith(prefix)) {
521 int i = 0;
522 }
523 assertTrue(output.trim().startsWith(prefix), "Output: \'" + output + "' does not start with: " + prefix);
524 };
525 }
526
527 public void assertOutput(String got, String expected, String display) {
528 if (expected != null) {
529 assertEquals(got, expected, display + ".\n");
530 }
531 }
532
533 private String normalizeLineEndings(String text) {
534 return ANSI_CODE_PATTERN.matcher(text.replace(System.getProperty("line.separator"), "\n")).replaceAll("");
535 }
536 private static final Pattern ANSI_CODE_PATTERN = Pattern.compile("\033\\[[\060-\077]*[\040-\057]*[\100-\176]");
537
538 public static abstract class MemberInfo {
539 public final String source;
540 public final String type;
541 public final String name;
542
543 public MemberInfo(String source, String type, String name) {
544 this.source = source;
545 this.type = type;
546 this.name = name;
547 }
548
549 @Override
550 public int hashCode() {
551 return name.hashCode();
552 }
553
554 @Override
555 public boolean equals(Object o) {
556 if (o instanceof MemberInfo) {
557 MemberInfo mi = (MemberInfo) o;
558 return name.equals(mi.name);
559 }
560 return false;
561 }
562
563 public abstract Consumer<String> checkOutput();
564
565 public String getSource() {
566 return source;
567 }
568 }
569
570 public static class VariableInfo extends MemberInfo {
571
572 public final String value;
573 public final String initialValue;
574
575 public VariableInfo(String src, String type, String name) {
576 super(src, type, name);
577 this.initialValue = null;
578 switch (type) {
579 case "byte":
580 case "short":
581 case "int":
582 case "long":
583 value = "0";
584 break;
585 case "boolean":
586 value = "false";
587 break;
588 case "char":
589 value = "''";
590 break;
591 case "float":
592 case "double":
593 value = "0.0";
594 break;
595 default:
596 value = "null";
597 }
598 }
599
600 public VariableInfo(String src, String type, String name, String value) {
601 super(src, type, name);
602 this.value = value;
603 this.initialValue = value;
604 }
605
606 @Override
607 public Consumer<String> checkOutput() {
608 String arrowPattern = String.format("%s ==> %s", name, value);
609 Predicate<String> arrowCheckOutput = Pattern.compile(arrowPattern).asPredicate();
610 String howeverPattern = String.format("\\| *\\w+ variable %s, however*.", name);
611 Predicate<String> howeverCheckOutput = Pattern.compile(howeverPattern).asPredicate();
612 return output -> {
613 if (output.startsWith("| ")) {
614 assertTrue(howeverCheckOutput.test(output),
615 "Output: " + output + " does not fit pattern: " + howeverPattern);
616 } else {
617 assertTrue(arrowCheckOutput.test(output),
618 "Output: " + output + " does not fit pattern: " + arrowPattern);
619 }
620 };
621 }
622
623 @Override
624 public int hashCode() {
625 return name.hashCode();
626 }
627
628 @Override
629 public boolean equals(Object o) {
630 if (o instanceof VariableInfo) {
631 VariableInfo v = (VariableInfo) o;
632 return name.equals(v.name);
633 }
634 return false;
635 }
636
637 @Override
638 public String toString() {
639 return String.format("%s %s = %s", type, name, value);
640 }
641
642 @Override
643 public String getSource() {
644 String src = super.getSource();
645 return src.endsWith(";") ? src : src + ";";
646 }
647 }
648
649 public static class TempVariableInfo extends VariableInfo {
650
651 public TempVariableInfo(String src, String type, String name, String value) {
652 super(src, type, name, value);
653 }
654
655 @Override
656 public String getSource() {
657 return source;
658 }
659 }
660
661 public static class MethodInfo extends MemberInfo {
662
663 public final String signature;
664
665 public MethodInfo(String source, String signature, String name) {
666 super(source, signature.substring(0, signature.lastIndexOf(')') + 1), name);
667 this.signature = signature;
668 }
669
670 @Override
671 public Consumer<String> checkOutput() {
672 String expectedOutput = String.format("\\| *\\w+ method %s", name);
673 Predicate<String> checkOutput = Pattern.compile(expectedOutput).asPredicate();
674 return s -> assertTrue(checkOutput.test(s), "Expected: '" + expectedOutput + "', actual: " + s);
675 }
676
677 @Override
678 public int hashCode() {
679 return (name.hashCode() << 2) ^ type.hashCode() ;
680 }
681
682 @Override
683 public boolean equals(Object o) {
684 if (o instanceof MemberInfo) {
685 MemberInfo m = (MemberInfo) o;
686 return name.equals(m.name) && type.equals(m.type);
687 }
688 return false;
689 }
690
691 @Override
692 public String toString() {
693 int i = signature.lastIndexOf(")") + 1;
694 if (i <= 0) {
695 return String.format("%s", name);
696 } else {
697 return String.format("%s %s%s", signature.substring(i), name, signature.substring(0, i));
698 }
699 }
700 }
701
702 public static class ClassInfo extends MemberInfo {
703
704 public ClassInfo(String source, String type, String name) {
705 super(source, type, name);
706 }
707
708 @Override
709 public Consumer<String> checkOutput() {
710 String fullType = type.equals("@interface")? "annotation interface" : type;
711 String expectedOutput = String.format("\\| *\\w+ %s %s", fullType, name);
712 Predicate<String> checkOutput = Pattern.compile(expectedOutput).asPredicate();
713 return s -> assertTrue(checkOutput.test(s), "Expected: '" + expectedOutput + "', actual: " + s);
714 }
715
716 @Override
717 public int hashCode() {
718 return name.hashCode() ;
719 }
720
721 @Override
722 public boolean equals(Object o) {
723 if (o instanceof ClassInfo) {
724 ClassInfo c = (ClassInfo) o;
725 return name.equals(c.name);
726 }
727 return false;
728 }
729
730 @Override
731 public String toString() {
732 return String.format("%s %s", type, name);
733 }
734 }
735
736 public static class ImportInfo extends MemberInfo {
737 public ImportInfo(String source, String type, String fullname) {
738 super(source, type, fullname);
739 }
740
741 @Override
742 public Consumer<String> checkOutput() {
743 return s -> assertTrue("".equals(s), "Expected: '', actual: " + s);
744 }
745
746 @Override
747 public int hashCode() {
748 return (name.hashCode() << 2) ^ type.hashCode() ;
749 }
750
751 @Override
752 public boolean equals(Object o) {
753 if (o instanceof ImportInfo) {
754 ImportInfo i = (ImportInfo) o;
755 return name.equals(i.name) && type.equals(i.type);
756 }
757 return false;
758 }
759
760 @Override
761 public String toString() {
762 return String.format("import %s%s", type.equals("static") ? "static " : "", name);
763 }
764 }
765
766 class WaitingTestingInputStream extends TestingInputStream {
767
768 private boolean closed;
769
770 @Override
771 synchronized void setInput(String s) {
772 super.setInput(s);
773 notify();
774 }
775
776 synchronized void waitForInput() {
777 boolean interrupted = false;
778 try {
779 while (available() == 0 && !closed) {
780 try {
781 wait();
782 } catch (InterruptedException e) {
783 interrupted = true;
784 // fall through and retry
785 }
786 }
787 } finally {
788 if (interrupted) {
789 Thread.currentThread().interrupt();
790 }
791 }
792 }
793
794 @Override
795 public int read() {
796 waitForInput();
797 return super.read();
798 }
799
800 @Override
801 public int read(byte b[], int off, int len) {
802 waitForInput();
803 return super.read(b, off, len);
804 }
805
806 @Override
807 public synchronized void close() throws IOException {
808 closed = true;
809 notify();
810 }
811 }
812
813 class PromptedCommandOutputStream extends OutputStream {
814 private final ReplTest[] tests;
815 private int index = 0;
816 PromptedCommandOutputStream(ReplTest[] tests) {
817 this.tests = tests;
818 }
819
820 @Override
821 public synchronized void write(int b) {
822 if (b == 5 || b == 6) {
823 if (index < (tests.length - 1)) {
824 tests[index].run(true);
825 tests[index + 1].run(false);
826 } else {
827 fail("Did not exit Repl tool after test");
828 }
829 ++index;
830 } // For now, anything else is thrown away
831 }
832
833 @Override
834 public synchronized void write(byte b[], int off, int len) {
835 if ((off < 0) || (off > b.length) || (len < 0)
836 || ((off + len) - b.length > 0)) {
837 throw new IndexOutOfBoundsException();
838 }
839 for (int i = 0; i < len; ++i) {
840 write(b[off + i]);
841 }
842 }
843 }
844
845 public static final class MemoryPreferences extends AbstractPreferences {
846
847 private final Map<String, String> values = new HashMap<>();
848 private final Map<String, MemoryPreferences> nodes = new HashMap<>();
849
850 public MemoryPreferences() {
851 this(null, "");
852 }
853
854 public MemoryPreferences(MemoryPreferences parent, String name) {
855 super(parent, name);
856 }
857
858 @Override
859 protected void putSpi(String key, String value) {
860 values.put(key, value);
861 }
862
863 @Override
864 protected String getSpi(String key) {
865 return values.get(key);
866 }
867
868 @Override
869 protected void removeSpi(String key) {
870 values.remove(key);
871 }
872
873 @Override
874 protected void removeNodeSpi() throws BackingStoreException {
875 ((MemoryPreferences) parent()).nodes.remove(name());
876 }
877
878 @Override
879 protected String[] keysSpi() throws BackingStoreException {
880 return values.keySet().toArray(new String[0]);
881 }
882
883 @Override
884 protected String[] childrenNamesSpi() throws BackingStoreException {
885 return nodes.keySet().toArray(new String[0]);
886 }
887
888 @Override
889 protected AbstractPreferences childSpi(String name) {
890 return nodes.computeIfAbsent(name, n -> new MemoryPreferences(this, name));
891 }
892
893 @Override
894 protected void syncSpi() throws BackingStoreException {
895 }
896
897 @Override
898 protected void flushSpi() throws BackingStoreException {
899 }
900
901 }
902 }
903