51 }
52
53 TestBuilder(Consumer<TestInstance> testConsumer) {
54 argProcessors = Map.of(
55 CMDLINE_ARG_PREFIX + "after-run",
56 arg -> getJavaMethodsFromArg(arg).map(
57 this::wrap).forEachOrdered(afterActions::add),
58
59 CMDLINE_ARG_PREFIX + "before-run",
60 arg -> getJavaMethodsFromArg(arg).map(
61 this::wrap).forEachOrdered(beforeActions::add),
62
63 CMDLINE_ARG_PREFIX + "run",
64 arg -> addTestGroup(getJavaMethodsFromArg(arg).map(
65 ThrowingFunction.toFunction(
66 TestBuilder::toMethodCalls)).flatMap(s -> s).collect(
67 Collectors.toList())),
68
69 CMDLINE_ARG_PREFIX + "exclude",
70 arg -> (excludedTests = Optional.ofNullable(
71 excludedTests).orElse(new HashSet<String>())).add(arg),
72
73 CMDLINE_ARG_PREFIX + "include",
74 arg -> (includedTests = Optional.ofNullable(
75 includedTests).orElse(new HashSet<String>())).add(arg),
76
77 CMDLINE_ARG_PREFIX + "space-subst",
78 arg -> spaceSubstitute = arg,
79
80 CMDLINE_ARG_PREFIX + "group",
81 arg -> flushTestGroup(),
82
83 CMDLINE_ARG_PREFIX + "dry-run",
84 arg -> dryRun = true
85 );
86 this.testConsumer = testConsumer;
87 clear();
88 }
89
90 void processCmdLineArg(String arg) throws Throwable {
91 int separatorIdx = arg.indexOf('=');
92 final String argName;
93 final String argValue;
94 if (separatorIdx != -1) {
95 argName = arg.substring(0, separatorIdx);
110 }
111 }
112
113 private void addTestGroup(List<MethodCall> newTestGroup) {
114 if (testGroup != null) {
115 testGroup.addAll(newTestGroup);
116 } else {
117 testGroup = newTestGroup;
118 }
119 }
120
121 private static Stream<MethodCall> filterTests(Stream<MethodCall> tests,
122 Set<String> filters, UnaryOperator<Boolean> pred, String logMsg) {
123 if (filters == null) {
124 return tests;
125 }
126
127 // Log all matches before returning from the function
128 return tests.filter(test -> {
129 String testDescription = test.createDescription().testFullName();
130 boolean match = filters.stream().anyMatch(
131 v -> testDescription.contains(v));
132 if (match) {
133 trace(String.format(logMsg + ": %s", testDescription));
134 }
135 return pred.apply(match);
136 }).collect(Collectors.toList()).stream();
137 }
138
139 private Stream<MethodCall> filterTestGroup() {
140 Objects.requireNonNull(testGroup);
141
142 UnaryOperator<Set<String>> restoreSpaces = filters -> {
143 if (spaceSubstitute == null || filters == null) {
144 return filters;
145 }
146 return filters.stream().map(
147 filter -> filter.replace(spaceSubstitute, " ")).collect(
148 Collectors.toSet());
149 };
150
151 if (includedTests != null) {
152 return filterTests(testGroup.stream(), restoreSpaces.apply(
153 includedTests), x -> x, "Include");
154 }
155
156 return filterTests(testGroup.stream(),
157 restoreSpaces.apply(excludedTests), x -> !x, "Exclude");
158 }
159
160 private void flushTestGroup() {
161 if (testGroup != null) {
162 filterTestGroup().forEach(testBody -> createTestInstance(testBody));
163 clear();
164 }
165 }
166
167 private void createTestInstance(MethodCall testBody) {
168 final List<ThrowingConsumer> curBeforeActions;
169 final List<ThrowingConsumer> curAfterActions;
170
171 Method testMethod = testBody.getMethod();
172 if (Stream.of(BeforeEach.class, AfterEach.class).anyMatch(
173 type -> testMethod.isAnnotationPresent(type))) {
174 curBeforeActions = beforeActions;
175 curAfterActions = afterActions;
176 } else {
177 curBeforeActions = new ArrayList<>(beforeActions);
178 curAfterActions = new ArrayList<>(afterActions);
179
180 selectFrameMethods(testMethod.getDeclaringClass(), BeforeEach.class).map(
181 this::wrap).forEachOrdered(curBeforeActions::add);
182 selectFrameMethods(testMethod.getDeclaringClass(), AfterEach.class).map(
183 this::wrap).forEachOrdered(curAfterActions::add);
184 }
185
186 TestInstance test = new TestInstance(testBody, curBeforeActions,
187 curAfterActions, dryRun);
188 if (includedTests == null) {
189 trace(String.format("Create: %s", test.fullName()));
190 }
191 testConsumer.accept(test);
192 }
193
269
270 private static List<Method> getJavaMethodFromString(
271 String qualifiedMethodName) {
272 int lastDotIdx = qualifiedMethodName.lastIndexOf('.');
273 if (lastDotIdx == -1) {
274 throw new ParseException("Class name not found in");
275 }
276 String className = qualifiedMethodName.substring(0, lastDotIdx);
277 String methodName = qualifiedMethodName.substring(lastDotIdx + 1);
278 Class methodClass;
279 try {
280 methodClass = Class.forName(className);
281 } catch (ClassNotFoundException ex) {
282 throw new ParseException(String.format("Class [%s] not found;",
283 className));
284 }
285 // Get the list of all public methods as need to deal with overloads.
286 List<Method> methods = Stream.of(methodClass.getMethods()).filter(
287 (m) -> filterMethod(methodName, m)).collect(Collectors.toList());
288 if (methods.isEmpty()) {
289 new ParseException(String.format(
290 "Method [%s] not found in [%s] class;",
291 methodName, className));
292 }
293
294 trace(String.format("%s -> %s", qualifiedMethodName, methods));
295 return methods;
296 }
297
298 private static Stream<Method> getJavaMethodsFromArg(String argValue) {
299 return cmdLineArgValueToMethodNames(argValue).map(
300 ThrowingFunction.toFunction(
301 TestBuilder::getJavaMethodFromString)).flatMap(
302 List::stream).sequential();
303 }
304
305 private static Parameter[] getMethodParameters(Method method) {
306 if (method.isAnnotationPresent(ParameterGroup.class)) {
307 return ((ParameterGroup) method.getAnnotation(ParameterGroup.class)).value();
308 }
309
|
51 }
52
53 TestBuilder(Consumer<TestInstance> testConsumer) {
54 argProcessors = Map.of(
55 CMDLINE_ARG_PREFIX + "after-run",
56 arg -> getJavaMethodsFromArg(arg).map(
57 this::wrap).forEachOrdered(afterActions::add),
58
59 CMDLINE_ARG_PREFIX + "before-run",
60 arg -> getJavaMethodsFromArg(arg).map(
61 this::wrap).forEachOrdered(beforeActions::add),
62
63 CMDLINE_ARG_PREFIX + "run",
64 arg -> addTestGroup(getJavaMethodsFromArg(arg).map(
65 ThrowingFunction.toFunction(
66 TestBuilder::toMethodCalls)).flatMap(s -> s).collect(
67 Collectors.toList())),
68
69 CMDLINE_ARG_PREFIX + "exclude",
70 arg -> (excludedTests = Optional.ofNullable(
71 excludedTests).orElseGet(() -> new HashSet<String>())).add(arg),
72
73 CMDLINE_ARG_PREFIX + "include",
74 arg -> (includedTests = Optional.ofNullable(
75 includedTests).orElseGet(() -> new HashSet<String>())).add(arg),
76
77 CMDLINE_ARG_PREFIX + "space-subst",
78 arg -> spaceSubstitute = arg,
79
80 CMDLINE_ARG_PREFIX + "group",
81 arg -> flushTestGroup(),
82
83 CMDLINE_ARG_PREFIX + "dry-run",
84 arg -> dryRun = true
85 );
86 this.testConsumer = testConsumer;
87 clear();
88 }
89
90 void processCmdLineArg(String arg) throws Throwable {
91 int separatorIdx = arg.indexOf('=');
92 final String argName;
93 final String argValue;
94 if (separatorIdx != -1) {
95 argName = arg.substring(0, separatorIdx);
110 }
111 }
112
113 private void addTestGroup(List<MethodCall> newTestGroup) {
114 if (testGroup != null) {
115 testGroup.addAll(newTestGroup);
116 } else {
117 testGroup = newTestGroup;
118 }
119 }
120
121 private static Stream<MethodCall> filterTests(Stream<MethodCall> tests,
122 Set<String> filters, UnaryOperator<Boolean> pred, String logMsg) {
123 if (filters == null) {
124 return tests;
125 }
126
127 // Log all matches before returning from the function
128 return tests.filter(test -> {
129 String testDescription = test.createDescription().testFullName();
130 boolean match = filters.stream().anyMatch(testDescription::contains);
131 if (match) {
132 trace(String.format(logMsg + ": %s", testDescription));
133 }
134 return pred.apply(match);
135 }).collect(Collectors.toList()).stream();
136 }
137
138 private Stream<MethodCall> filterTestGroup() {
139 Objects.requireNonNull(testGroup);
140
141 UnaryOperator<Set<String>> restoreSpaces = filters -> {
142 if (spaceSubstitute == null || filters == null) {
143 return filters;
144 }
145 return filters.stream().map(
146 filter -> filter.replace(spaceSubstitute, " ")).collect(
147 Collectors.toSet());
148 };
149
150 if (includedTests != null) {
151 return filterTests(testGroup.stream(), restoreSpaces.apply(
152 includedTests), x -> x, "Include");
153 }
154
155 return filterTests(testGroup.stream(),
156 restoreSpaces.apply(excludedTests), x -> !x, "Exclude");
157 }
158
159 private void flushTestGroup() {
160 if (testGroup != null) {
161 filterTestGroup().forEach(this::createTestInstance);
162 clear();
163 }
164 }
165
166 private void createTestInstance(MethodCall testBody) {
167 final List<ThrowingConsumer> curBeforeActions;
168 final List<ThrowingConsumer> curAfterActions;
169
170 Method testMethod = testBody.getMethod();
171 if (Stream.of(BeforeEach.class, AfterEach.class).anyMatch(
172 testMethod::isAnnotationPresent)) {
173 curBeforeActions = beforeActions;
174 curAfterActions = afterActions;
175 } else {
176 curBeforeActions = new ArrayList<>(beforeActions);
177 curAfterActions = new ArrayList<>(afterActions);
178
179 selectFrameMethods(testMethod.getDeclaringClass(), BeforeEach.class).map(
180 this::wrap).forEachOrdered(curBeforeActions::add);
181 selectFrameMethods(testMethod.getDeclaringClass(), AfterEach.class).map(
182 this::wrap).forEachOrdered(curAfterActions::add);
183 }
184
185 TestInstance test = new TestInstance(testBody, curBeforeActions,
186 curAfterActions, dryRun);
187 if (includedTests == null) {
188 trace(String.format("Create: %s", test.fullName()));
189 }
190 testConsumer.accept(test);
191 }
192
268
269 private static List<Method> getJavaMethodFromString(
270 String qualifiedMethodName) {
271 int lastDotIdx = qualifiedMethodName.lastIndexOf('.');
272 if (lastDotIdx == -1) {
273 throw new ParseException("Class name not found in");
274 }
275 String className = qualifiedMethodName.substring(0, lastDotIdx);
276 String methodName = qualifiedMethodName.substring(lastDotIdx + 1);
277 Class methodClass;
278 try {
279 methodClass = Class.forName(className);
280 } catch (ClassNotFoundException ex) {
281 throw new ParseException(String.format("Class [%s] not found;",
282 className));
283 }
284 // Get the list of all public methods as need to deal with overloads.
285 List<Method> methods = Stream.of(methodClass.getMethods()).filter(
286 (m) -> filterMethod(methodName, m)).collect(Collectors.toList());
287 if (methods.isEmpty()) {
288 throw new ParseException(String.format(
289 "Method [%s] not found in [%s] class;",
290 methodName, className));
291 }
292
293 trace(String.format("%s -> %s", qualifiedMethodName, methods));
294 return methods;
295 }
296
297 private static Stream<Method> getJavaMethodsFromArg(String argValue) {
298 return cmdLineArgValueToMethodNames(argValue).map(
299 ThrowingFunction.toFunction(
300 TestBuilder::getJavaMethodFromString)).flatMap(
301 List::stream).sequential();
302 }
303
304 private static Parameter[] getMethodParameters(Method method) {
305 if (method.isAnnotationPresent(ParameterGroup.class)) {
306 return ((ParameterGroup) method.getAnnotation(ParameterGroup.class)).value();
307 }
308
|