41 import java.util.Set; |
41 import java.util.Set; |
42 import java.util.TreeSet; |
42 import java.util.TreeSet; |
43 import java.util.stream.Collectors; |
43 import java.util.stream.Collectors; |
44 |
44 |
45 import toolbox.JavacTask; |
45 import toolbox.JavacTask; |
|
46 import toolbox.TestRunner; |
46 import toolbox.ToolBox; |
47 import toolbox.ToolBox; |
47 |
48 |
48 /** |
49 /** |
49 * Base class for module tests. |
50 * Base class for module tests. |
50 */ |
51 */ |
51 public class ModuleTestBase { |
52 public class ModuleTestBase extends TestRunner { |
52 protected ToolBox tb; |
53 protected ToolBox tb; |
53 protected PrintStream out; |
|
54 private int errors; |
54 private int errors; |
55 |
55 |
56 /** Marker annotation for test methods to be invoked by runTests. */ |
56 ModuleTestBase() { |
57 @Retention(RetentionPolicy.RUNTIME) |
57 super(System.err); |
58 @interface Test { } |
58 tb = new ToolBox(); |
|
59 } |
59 |
60 |
60 /** |
61 /** |
61 * Run all methods annotated with @Test, and throw an exception if any |
62 * Run all methods annotated with @Test, and throw an exception if any |
62 * errors are reported.. |
63 * errors are reported.. |
63 * |
64 * |
64 * @throws Exception if any errors occurred |
65 * @throws Exception if any errors occurred |
65 */ |
66 */ |
66 void runTests() throws Exception { |
67 protected void runTests() throws Exception { |
67 if (tb == null) |
68 runTests(m -> new Object[] { Paths.get(m.getName()) }); |
68 tb = new ToolBox(); |
|
69 out = System.err; |
|
70 |
|
71 for (Method m: getClass().getDeclaredMethods()) { |
|
72 Annotation a = m.getAnnotation(Test.class); |
|
73 if (a != null) { |
|
74 try { |
|
75 out.println("Running test " + m.getName()); |
|
76 Path baseDir = Paths.get(m.getName()); |
|
77 m.invoke(this, new Object[] { baseDir }); |
|
78 } catch (InvocationTargetException e) { |
|
79 Throwable cause = e.getCause(); |
|
80 error("Exception: " + e.getCause()); |
|
81 cause.printStackTrace(out); |
|
82 } |
|
83 out.println(); |
|
84 } |
|
85 } |
|
86 if (errors > 0) |
|
87 throw new Exception(errors + " errors occurred"); |
|
88 } |
69 } |
89 |
70 |
90 // move to ToolBox? |
|
91 // change returntyp to List<Path> -- means updating ToolBox methods |
|
92 Path[] findJavaFiles(Path... paths) throws IOException { |
71 Path[] findJavaFiles(Path... paths) throws IOException { |
93 Set<Path> files = new TreeSet<>(); |
72 return tb.findJavaFiles(paths); |
94 for (Path p : paths) { |
|
95 Files.walkFileTree(p, new SimpleFileVisitor<Path>() { |
|
96 @Override |
|
97 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) |
|
98 throws IOException { |
|
99 if (file.getFileName().toString().endsWith(".java")) { |
|
100 files.add(file); |
|
101 } |
|
102 return FileVisitResult.CONTINUE; |
|
103 } |
|
104 }); |
|
105 } |
|
106 return files.toArray(new Path[files.size()]); |
|
107 } |
73 } |
108 |
74 |
109 void error(String message) { |
75 void error(String message) { |
110 out.println("Error: " + message); |
76 out.println("Error: " + message); |
111 errors++; |
77 errors++; |
112 } |
78 } |
113 |
79 |
114 public class ModuleBuilder { |
|
115 |
|
116 private final String name; |
|
117 private String requires = ""; |
|
118 private String exports = ""; |
|
119 private String uses = ""; |
|
120 private String provides = ""; |
|
121 private String modulePath = ""; |
|
122 private List<String> content = new ArrayList<>(); |
|
123 |
|
124 public ModuleBuilder(String name) { |
|
125 this.name = name; |
|
126 } |
|
127 |
|
128 public ModuleBuilder requiresPublic(String requires, Path... modulePath) { |
|
129 return requires("public " + requires, modulePath); |
|
130 } |
|
131 |
|
132 public ModuleBuilder requires(String requires, Path... modulePath) { |
|
133 this.requires += " requires " + requires + ";\n"; |
|
134 this.modulePath += Arrays.stream(modulePath) |
|
135 .map(Path::toString) |
|
136 .collect(Collectors.joining(File.pathSeparator)); |
|
137 return this; |
|
138 } |
|
139 |
|
140 public ModuleBuilder exportsTo(String pkg, String module) { |
|
141 return exports(pkg + " to " + module); |
|
142 } |
|
143 |
|
144 public ModuleBuilder exports(String pkg) { |
|
145 this.exports += " exports " + pkg + ";\n"; |
|
146 return this; |
|
147 } |
|
148 |
|
149 public ModuleBuilder uses(String uses) { |
|
150 this.uses += " uses " + uses + ";\n"; |
|
151 return this; |
|
152 } |
|
153 |
|
154 public ModuleBuilder provides(String service, String implementation) { |
|
155 this.provides += " provides " + service + " with " + implementation + ";\n"; |
|
156 return this; |
|
157 } |
|
158 |
|
159 public ModuleBuilder classes(String... content) { |
|
160 this.content.addAll(Arrays.asList(content)); |
|
161 return this; |
|
162 } |
|
163 |
|
164 public Path write(Path where) throws IOException { |
|
165 Files.createDirectories(where); |
|
166 List<String> sources = new ArrayList<>(); |
|
167 sources.add("module " + name + "{" |
|
168 + requires |
|
169 + exports |
|
170 + uses |
|
171 + provides |
|
172 + "}"); |
|
173 sources.addAll(content); |
|
174 Path moduleSrc = where.resolve(name + "/src"); |
|
175 tb.writeJavaFiles(moduleSrc, sources.toArray(new String[]{})); |
|
176 return moduleSrc; |
|
177 } |
|
178 |
|
179 public void build(Path where) throws IOException { |
|
180 Path moduleSrc = write(where); |
|
181 new JavacTask(tb) |
|
182 .outdir(where.resolve(name)) |
|
183 .options("-mp", modulePath) |
|
184 .files(findJavaFiles(moduleSrc)) |
|
185 .run() |
|
186 .writeAll(); |
|
187 } |
|
188 } |
|
189 } |
80 } |