Skip to content

Commit 8d6f3e5

Browse files
author
peng
committed
minor simplification
1 parent 6c66c9d commit 8d6f3e5

File tree

2 files changed

+104
-100
lines changed

2 files changed

+104
-100
lines changed

junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryResultValidator.java

Lines changed: 99 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,20 @@
3434
*/
3535
class EngineDiscoveryResultValidator {
3636

37-
static abstract class ValidationError {
37+
static abstract class ValidationError extends RuntimeException {
38+
static final long serialVersionUID = -7034897190745766939L;
3839

3940
public abstract String message();
4041
}
4142

4243
static class CyclicGraphError extends ValidationError {
43-
TestDescriptor node1;
44-
TestDescriptor node2;
44+
static final long serialVersionUID = -7034897190745766939L;
45+
46+
LinkedList<TestDescriptor> p1;
47+
LinkedList<TestDescriptor> p2;
4548

4649
@Override
4750
public String message() {
48-
LinkedList<TestDescriptor> p1 = getPath(node1);
49-
LinkedList<TestDescriptor> p2 = getPath(node2);
5051

5152
StringBuilder result = new StringBuilder();
5253
result.append("Graph cycle found:\n\t");
@@ -90,130 +91,132 @@ public void accept(TestDescriptor x) {
9091

9192
}
9293

93-
static class NonReciprocalParentError extends ValidationError {
94-
TestDescriptor parent;
94+
95+
static class IllegalParentError extends ValidationError {
96+
static final long serialVersionUID = -7034897190745766939L;
97+
Optional<TestDescriptor> parent = Optional.empty();
9598
TestDescriptor child;
9699

97100
@Override
98101
public String message() {
99-
String parent2 = null;
100-
if (child.getParent().isPresent()) {
101-
parent2 = child.getParent().get().getUniqueId().toString();
102-
}
103-
else {
104-
parent2 = "<none>";
105-
}
102+
String parentStr = parent.map(v -> v.getUniqueId().toString()).orElse("<none>");
103+
String parent2Str = child.getParent().map(v -> v.getUniqueId().toString()).orElse("<none>");
106104

107105
return String.format("%s is ill-formed: parent should be %s\n" + "\tbut found %s", child.getUniqueId(),
108-
parent.getUniqueId(), parent2);
106+
parentStr, parent2Str);
109107
}
110108
}
111109

112-
static class SelfReferringParentError extends ValidationError {
113-
TestDescriptor node;
114-
115-
@Override
116-
public String message() {
110+
static class ValidatorExecution {
111+
TestDescriptor root;
112+
protected List<ValidationError> errors = new ArrayList<>();
117113

118-
return String.format("%s is ill-formed: parent cannot be itself", node.getUniqueId());
114+
ValidatorExecution(TestDescriptor root) {
115+
this.root = root;
119116
}
120-
}
121-
122-
/**
123-
* Perform common validation checks.
124-
*
125-
* @throws org.junit.platform.commons.PreconditionViolationException if any check fails
126-
*/
127-
void validate(TestEngine testEngine, TestDescriptor root) {
128-
Preconditions.notNull(root,
129-
() -> String.format(
130-
"The discover() method for TestEngine with ID '%s' must return a non-null root TestDescriptor.",
131-
testEngine.getId()));
132-
Optional<String> msgs = getValidationErrorMsg(root);
133-
msgs.ifPresent(s -> Preconditions.condition(true,
134-
() -> String.format("The discover() method for TestEngine with ID '%s' returned a cyclic graph:\n" + "%s",
135-
testEngine.getId(), s)));
136117

137-
}
118+
void verifyParentChild(Optional<TestDescriptor> parent, TestDescriptor child) {
119+
Optional<TestDescriptor> effectiveParent = parent.filter(v -> !v.equals(child));
120+
Optional<TestDescriptor> parent2 = child.getParent();
121+
if (!parent2.equals(effectiveParent)) {
122+
IllegalParentError error = new IllegalParentError();
123+
error.parent = effectiveParent;
124+
error.child = child;
138125

139-
/**
140-
* @return {@code true} if the tree does <em>not</em> contain a cycle; else {@code false}.
141-
*/
142-
boolean hasNoError(TestDescriptor root) {
143-
return getValidationErrors(root).isEmpty();
144-
}
126+
errors.add(error);
145127

146-
static LinkedList<TestDescriptor> getPath(TestDescriptor v) {
128+
throw error;
129+
}
130+
}
147131

148-
LinkedList<TestDescriptor> path = new LinkedList<>();
149-
path.add(v);
132+
LinkedList<TestDescriptor> getPath(TestDescriptor v) {
150133

151-
Optional<TestDescriptor> next = v.getParent();
152-
while (next.isPresent()) {
153-
TestDescriptor parent = next.get();
154-
path.add(next.get());
155-
next = parent.getParent();
156-
}
134+
LinkedList<TestDescriptor> path = new LinkedList<>();
135+
path.add(v);
157136

158-
return path;
159-
}
137+
Optional<TestDescriptor> next = v.getParent();
138+
while (next.isPresent()) {
139+
TestDescriptor current = next.get();
140+
path.add(next.get());
141+
next = current.getParent();
142+
verifyParentChild(next, current);
143+
}
160144

161-
Optional<String> getValidationErrorMsg(TestDescriptor root) {
145+
return path;
146+
}
162147

163-
List<ValidationError> errors = getValidationErrors(root);
148+
List<ValidationError> getErrors() {
164149

165-
Stream<String> strs = errors.stream().map(ValidationError::message);
150+
Map<UniqueId, TestDescriptor> visited = new HashMap<>();
151+
visited.put(root.getUniqueId(), root);
166152

167-
return strs.reduce((a, b) -> a.concat("\n").concat(b));
168-
}
153+
Queue<TestDescriptor> queue = new ArrayDeque<>();
154+
queue.add(root);
169155

170-
List<ValidationError> getValidationErrors(TestDescriptor root) {
171-
Map<UniqueId, TestDescriptor> visited = new HashMap<>();
172-
visited.put(root.getUniqueId(), root);
156+
try {
157+
while (!queue.isEmpty()) {
158+
TestDescriptor next = queue.remove();
159+
for (TestDescriptor child : next.getChildren()) {
160+
UniqueId uid = child.getUniqueId();
173161

174-
Queue<TestDescriptor> queue = new ArrayDeque<>();
175-
queue.add(root);
162+
verifyParentChild(Optional.of(next), child);
176163

177-
List<ValidationError> errors = new ArrayList<>();
164+
TestDescriptor existing = visited.put(uid, child);
165+
if (existing != null) {
166+
CyclicGraphError error = new CyclicGraphError();
167+
error.p1 = getPath(existing);
168+
error.p2 = getPath(child);
178169

179-
while (!queue.isEmpty()) {
180-
TestDescriptor next = queue.remove();
181-
for (TestDescriptor child : next.getChildren()) {
182-
UniqueId uid = child.getUniqueId();
183-
Optional<TestDescriptor> next2 = child.getParent();
184-
if (!next2.equals(Optional.of(next))) {
185-
NonReciprocalParentError error = new NonReciprocalParentError();
186-
error.parent = next;
187-
error.child = child;
188-
errors.add(error);
170+
errors.add(error);
189171

190-
return errors;
172+
throw error;
173+
}
174+
if (child.isContainer()) {
175+
queue.add(child);
176+
}
177+
}
191178
}
179+
}
180+
catch ( ValidationError ignored) {
181+
}
182+
return errors;
183+
}
192184

193-
if (next2.equals(Optional.of(child))) {
194-
SelfReferringParentError error = new SelfReferringParentError();
195-
error.node = child;
196-
errors.add(error);
197185

198-
return errors;
199-
}
186+
Optional<String> getErrorMsg() {
200187

201-
TestDescriptor existingOrNull = visited.put(uid, child);
202-
if (existingOrNull != null) {
203-
CyclicGraphError error = new CyclicGraphError();
204-
error.node1 = existingOrNull;
205-
error.node2 = child;
188+
List<ValidationError> errors = getErrors();
206189

207-
errors.add(error);
190+
Stream<String> strs = errors.stream().map(ValidationError::message);
208191

209-
return errors; // id already known: cycle detected!
210-
}
211-
if (child.isContainer()) {
212-
queue.add(child);
213-
}
214-
}
192+
return strs.reduce((a, b) -> a.concat("\n").concat(b));
215193
}
216-
return errors;
217194
}
218195

196+
/**
197+
* Perform common validation checks.
198+
*
199+
* @throws org.junit.platform.commons.PreconditionViolationException if any check fails
200+
*/
201+
void validate(TestEngine testEngine, TestDescriptor root) {
202+
Preconditions.notNull(root,
203+
() -> String.format(
204+
"The discover() method for TestEngine with ID '%s' must return a non-null root TestDescriptor.",
205+
testEngine.getId()));
206+
Optional<String> msgs = new ValidatorExecution(root).getErrorMsg();
207+
msgs.ifPresent(s -> Preconditions.condition(true,
208+
() -> String.format("The discover() method for TestEngine with ID '%s' returned a cyclic graph:\n" + "%s",
209+
testEngine.getId(), s)));
210+
}
211+
212+
Optional<String> getErrorMsg(TestDescriptor root) {
213+
return new ValidatorExecution(root).getErrorMsg();
214+
}
215+
216+
/**
217+
* @return {@code true} if the tree does <em>not</em> contain a cycle; else {@code false}.
218+
*/
219+
boolean hasNoError(TestDescriptor root) {
220+
return new ValidatorExecution(root).getErrors().isEmpty();
221+
}
219222
}

platform-tests/src/test/java/org/junit/platform/launcher/core/EngineDiscoveryResultValidatorTests.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ void detectCycleWithDoubleRoot() {
3333

3434
root.addChild(root);
3535
assertFalse(validator.hasNoError(root));
36-
assertEquals("[engine:root] is ill-formed: parent cannot be itself",
37-
validator.getValidationErrorMsg(root).get());
36+
assertEquals("[engine:root] is ill-formed: parent should be <none>\n" +
37+
"\tbut found [engine:root]",
38+
validator.getErrorMsg(root).get());
3839
}
3940

4041
@Test
@@ -51,7 +52,7 @@ void detectCycleWithDoubleGroup() {
5152
assertFalse(validator.hasNoError(root));
5253
assertEquals("[engine:root]/[group:1] is ill-formed: parent should be [engine:root]\n"
5354
+ "\tbut found [engine:root]/[group:2]",
54-
validator.getValidationErrorMsg(root).get());
55+
validator.getErrorMsg(root).get());
5556
}
5657

5758
@Test
@@ -72,6 +73,6 @@ void detectCycleWithDoubleTest() {
7273
assertFalse(validator.hasNoError(root));
7374
assertEquals("[engine:root]/[test:1] is ill-formed: parent should be [engine:root]/[group:1]\n"
7475
+ "\tbut found [engine:root]/[group:2]",
75-
validator.getValidationErrorMsg(root).get());
76+
validator.getErrorMsg(root).get());
7677
}
7778
}

0 commit comments

Comments
 (0)