1 | package com.github.dakusui.pcond.validator; | |
2 | ||
3 | import com.github.dakusui.pcond.validator.exceptions.PostconditionViolationException; | |
4 | import com.github.dakusui.pcond.validator.exceptions.PreconditionViolationException; | |
5 | import com.github.dakusui.pcond.validator.exceptions.ValidationException; | |
6 | ||
7 | import java.lang.reflect.InvocationTargetException; | |
8 | ||
9 | import static com.github.dakusui.pcond.validator.ExceptionComposer.Utils.createException; | |
10 | import static com.github.dakusui.pcond.validator.Explanation.reportToString; | |
11 | ||
12 | /** | |
13 | * An interface to define how an exception is composed based on a given message, | |
14 | * a class of a condition that the value violates (non-null constraint, invalid state, | |
15 | * input validation), and the context the violation happened (pre-, post-condition check, | |
16 | * test-assertion, etc.). | |
17 | * | |
18 | * This interface has methods to return objects, each of which composes actual exceptions. | |
19 | * Each of them intended to group methods that compose exceptions for a single context. | |
20 | */ | |
21 | public interface ExceptionComposer { | |
22 | /** | |
23 | * Returns an instance to compose exceptions used with `requireXyz` methods in | |
24 | * {@code Requires} entry-point class of valid8j library. | |
25 | * | |
26 | * @return An object to compose exceptions for methods in {@code Requires}. | |
27 | */ | |
28 | ForRequire forRequire(); | |
29 | ||
30 | /** | |
31 | * Returns an instance to compose exceptions used with `ensureXyz` methods in | |
32 | * {@code Ensures} entry-point class of valid8j library. | |
33 | * | |
34 | * @return An object to compose exceptions for methods in {@code Ensures}. | |
35 | */ | |
36 | ForEnsure forEnsure(); | |
37 | ||
38 | /** | |
39 | * Returns an instance to compose exceptions used with `validateXyz` methods in | |
40 | * {@code Validates} entry-point class of valid8j library. | |
41 | * | |
42 | * @return An object to compose exceptions for methods in {@code Validates}. | |
43 | */ | |
44 | ForValidate defaultForValidate(); | |
45 | ||
46 | /** | |
47 | * Returns an instance to compose exceptions used in `assert` statements. | |
48 | * | |
49 | * @return An object to compose exceptions for "precondition" violation. | |
50 | */ | |
51 | ForAssertion forAssert(); | |
52 | ||
53 | /** | |
54 | * Returns an instance to compose exceptions used in `assertThat` and `assumeThat` | |
55 | * methods in {@code TestAssertions} entry-point class of thincrest library. | |
56 | * Other entry-point classes provided for use cases of the `pcond` library as | |
57 | * a test assertion library may also use this method. | |
58 | * | |
59 | * @return An object to compose exceptions for test assertions | |
60 | */ | |
61 | ForTestAssertion forAssertThat(); | |
62 | ||
63 | /** | |
64 | * An implementation of the {@link ExceptionComposer} interface. | |
65 | * You usually do not need to extend this method to customize its behavior. | |
66 | * Rather you only need to control the arguments passed to its constructor | |
67 | * through {@link Validator.Configuration.Builder}. | |
68 | * | |
69 | * @see Validator.Configuration | |
70 | * @see Validator.Configuration.Builder | |
71 | */ | |
72 | class Impl implements ExceptionComposer { | |
73 | final private ForRequire forRequire; | |
74 | final private ForEnsure forEnsure; | |
75 | final private ForValidate defaultForValidate; | |
76 | final private ForAssertion forAssert; | |
77 | final private ForTestAssertion forAssertThat; | |
78 | ||
79 | public Impl(ForRequire forRequire, ForEnsure forEnsure, ForValidate defaultForValidate, ForAssertion forAssert, ForTestAssertion forAssertThat) { | |
80 | this.forRequire = forRequire; | |
81 | this.forEnsure = forEnsure; | |
82 | this.defaultForValidate = defaultForValidate; | |
83 | this.forAssert = forAssert; | |
84 | this.forAssertThat = forAssertThat; | |
85 | } | |
86 | ||
87 | @Override | |
88 | public ForRequire forRequire() { | |
89 |
1
1. forRequire : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$Impl::forRequire → KILLED |
return this.forRequire; |
90 | } | |
91 | ||
92 | @Override | |
93 | public ForEnsure forEnsure() { | |
94 |
1
1. forEnsure : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$Impl::forEnsure → KILLED |
return this.forEnsure; |
95 | } | |
96 | ||
97 | @Override | |
98 | public ForValidate defaultForValidate() { | |
99 |
1
1. defaultForValidate : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$Impl::defaultForValidate → SURVIVED |
return this.defaultForValidate; |
100 | } | |
101 | ||
102 | @Override | |
103 | public ForAssertion forAssert() { | |
104 |
1
1. forAssert : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$Impl::forAssert → KILLED |
return this.forAssert; |
105 | } | |
106 | ||
107 | @Override | |
108 | public ForTestAssertion forAssertThat() { | |
109 |
1
1. forAssertThat : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$Impl::forAssertThat → KILLED |
return this.forAssertThat; |
110 | } | |
111 | } | |
112 | ||
113 | /** | |
114 | * An interface that defines common methods that an object returned by each method | |
115 | * in the {@link ExceptionComposer} has. | |
116 | */ | |
117 | interface Base { | |
118 | /** | |
119 | * A method to compose an exception for a "Null-violation". | |
120 | * When you are checking a "pre-condition", if the value must not be `null`, | |
121 | * you may prefer a {@link NullPointerException}, rather than an exception | |
122 | * such as `YourPreconditionException` as Google Guava's `Precondition` does | |
123 | * so. | |
124 | * | |
125 | * This method by default, returns a `NullPointerException`. | |
126 | * | |
127 | * In case you prefer to throw `YourPreconditionException` for the sake of uniformity, | |
128 | * you can override this method for an object returned by {@link ExceptionComposer#forRequire()} | |
129 | * | |
130 | * For more detail, please refer to {@link Validator.Configuration}. | |
131 | * | |
132 | * @param message A message attached to the composed exception. | |
133 | * @return A composed exception. | |
134 | */ | |
135 | default Throwable exceptionForNonNullViolation(String message) { | |
136 |
1
1. exceptionForNonNullViolation : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$Base::exceptionForNonNullViolation → SURVIVED |
return new NullPointerException(message); |
137 | } | |
138 | ||
139 | /** | |
140 | * A method to compose an exception for a "State-violation". | |
141 | * | |
142 | * @param message A message attached to the composed exception. | |
143 | * @return A composed exception. | |
144 | * @see Base#exceptionForNonNullViolation(String) | |
145 | */ | |
146 | default Throwable exceptionForIllegalState(String message) { | |
147 |
1
1. exceptionForIllegalState : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$Base::exceptionForIllegalState → KILLED |
return new IllegalStateException(message); |
148 | } | |
149 | ||
150 | /** | |
151 | * A method to compose an exception for a general violation. | |
152 | * An extension-point to customize the exception to be thrown for a certain | |
153 | * context. | |
154 | * | |
155 | * @param message A message attached to the composed exception. | |
156 | * @return A composed exception. | |
157 | */ | |
158 | Throwable exceptionForGeneralViolation(String message); | |
159 | } | |
160 | ||
161 | interface ForRequire extends Base { | |
162 | @Override | |
163 | default Throwable exceptionForGeneralViolation(String message) { | |
164 |
1
1. exceptionForGeneralViolation : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForRequire::exceptionForGeneralViolation → KILLED |
return new PreconditionViolationException(message); |
165 | } | |
166 | ||
167 | Throwable exceptionForIllegalArgument(String message); | |
168 | ||
169 | @SuppressWarnings("unused") // Referenced reflectively | |
170 | class Default implements ForRequire { | |
171 | @Override | |
172 | public Throwable exceptionForIllegalArgument(String message) { | |
173 |
1
1. exceptionForIllegalArgument : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForRequire$Default::exceptionForIllegalArgument → KILLED |
return new IllegalArgumentException(message); |
174 | } | |
175 | } | |
176 | } | |
177 | ||
178 | interface ForEnsure extends Base { | |
179 | @Override | |
180 | default Throwable exceptionForGeneralViolation(String message) { | |
181 |
1
1. exceptionForGeneralViolation : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForEnsure::exceptionForGeneralViolation → KILLED |
return new PostconditionViolationException(message); |
182 | } | |
183 | ||
184 | @SuppressWarnings("unused") // Referenced reflectively | |
185 | class Default implements ForEnsure { | |
186 | } | |
187 | } | |
188 | ||
189 | interface ForValidate extends Base { | |
190 | @Override | |
191 | default Throwable exceptionForGeneralViolation(String message) { | |
192 |
1
1. exceptionForGeneralViolation : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForValidate::exceptionForGeneralViolation → KILLED |
return new ValidationException(message); |
193 | } | |
194 | ||
195 | default Throwable exceptionForIllegalArgument(String message) { | |
196 |
1
1. exceptionForIllegalArgument : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForValidate::exceptionForIllegalArgument → KILLED |
return new IllegalArgumentException(message); |
197 | } | |
198 | ||
199 | @SuppressWarnings("unused") // Referenced reflectively | |
200 | class Default implements ForValidate { | |
201 | } | |
202 | } | |
203 | ||
204 | interface ForAssertion { | |
205 | default Throwable exceptionPreconditionViolation(String message) { | |
206 |
1
1. exceptionPreconditionViolation : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForAssertion::exceptionPreconditionViolation → KILLED |
return new AssertionError(message); |
207 | } | |
208 | ||
209 | default Throwable exceptionInvariantConditionViolation(String message) { | |
210 |
1
1. exceptionInvariantConditionViolation : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForAssertion::exceptionInvariantConditionViolation → KILLED |
return new AssertionError(message); |
211 | } | |
212 | ||
213 | default Throwable exceptionPostconditionViolation(String message) { | |
214 |
1
1. exceptionPostconditionViolation : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForAssertion::exceptionPostconditionViolation → KILLED |
return new AssertionError(message); |
215 | } | |
216 | ||
217 | @SuppressWarnings("unused") // Referenced reflectively | |
218 | class Default implements ForAssertion { | |
219 | } | |
220 | } | |
221 | ||
222 | interface ForTestAssertion { | |
223 | <T extends RuntimeException> T testSkippedException(String message, ReportComposer reportComposer); | |
224 | ||
225 | default <T extends RuntimeException> T testSkippedException(Explanation explanation, ReportComposer reportComposer) { | |
226 |
1
1. testSkippedException : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForTestAssertion::testSkippedException → NO_COVERAGE |
return testSkippedException(explanation.toString(), reportComposer); |
227 | } | |
228 | ||
229 | <T extends Error> T testFailedException(Explanation explanation, ReportComposer reportComposer); | |
230 | ||
231 | @SuppressWarnings("unused") // Referenced reflectively | |
232 | class JUnit4 implements ForTestAssertion { | |
233 | @SuppressWarnings("unchecked") | |
234 | @Override | |
235 | public <T extends RuntimeException> T testSkippedException(String message, ReportComposer reportComposer) { | |
236 | throw (T) createException( | |
237 | "org.junit.AssumptionViolatedException", | |
238 | reportComposer.explanationFromMessage(message), | |
239 |
1
1. lambda$testSkippedException$0 : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForTestAssertion$JUnit4::lambda$testSkippedException$0 → KILLED |
(c, exp) -> c.getConstructor(String.class).newInstance(exp.message())); |
240 | } | |
241 | ||
242 | @SuppressWarnings("unchecked") | |
243 | @Override | |
244 | public <T extends Error> T testFailedException(Explanation explanation, ReportComposer reportComposer) { | |
245 | throw (T) createException( | |
246 | "org.junit.ComparisonFailure", | |
247 | explanation, | |
248 |
1
1. lambda$testFailedException$1 : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForTestAssertion$JUnit4::lambda$testFailedException$1 → KILLED |
(c, exp) -> c.getConstructor(String.class, String.class, String.class).newInstance(exp.message(), reportToString(exp.expected()), reportToString(exp.actual()))); |
249 | } | |
250 | } | |
251 | ||
252 | @SuppressWarnings("unused") // Referenced reflectively | |
253 | class Opentest4J implements ForTestAssertion { | |
254 | @SuppressWarnings("unchecked") | |
255 | @Override | |
256 | public <T extends RuntimeException> T testSkippedException(String message, ReportComposer reportComposer) { | |
257 | throw (T) createException("org.opentest4j.TestSkippedException", reportComposer.explanationFromMessage(message), (c, exp) -> | |
258 |
1
1. lambda$testSkippedException$0 : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForTestAssertion$Opentest4J::lambda$testSkippedException$0 → KILLED |
c.getConstructor(String.class).newInstance(exp.message())); |
259 | } | |
260 | ||
261 | @SuppressWarnings("unchecked") | |
262 | @Override | |
263 | public <T extends Error> T testFailedException(Explanation explanation, ReportComposer reportComposer) { | |
264 | throw (T) createException("org.opentest4j.AssertionFailedError", explanation, (c, exp) -> | |
265 |
1
1. lambda$testFailedException$1 : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$ForTestAssertion$Opentest4J::lambda$testFailedException$1 → KILLED |
c.getConstructor(String.class, Object.class, Object.class).newInstance(exp.message(), reportToString(exp.expected()), reportToString(exp.actual()))); |
266 | } | |
267 | } | |
268 | } | |
269 | ||
270 | enum Utils { | |
271 | ; | |
272 | ||
273 | @SuppressWarnings("unchecked") | |
274 | public static <T extends Throwable> T createException(String className, Explanation explanation, ReflectiveExceptionFactory<T> reflectiveExceptionFactory) { | |
275 | try { | |
276 |
1
1. createException : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$Utils::createException → KILLED |
return reflectiveExceptionFactory.apply((Class<T>) Class.forName(className), explanation); |
277 | } catch (ClassNotFoundException e) { | |
278 | throw new RuntimeException("FAILED TO INSTANTIATE EXCEPTION: '" + className + "' (NOT FOUND)", e); | |
279 | } | |
280 | } | |
281 | ||
282 | @FunctionalInterface | |
283 | public | |
284 | interface ReflectiveExceptionFactory<T extends Throwable> { | |
285 | T create(Class<T> c, Explanation explanation) throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException; | |
286 | ||
287 | default T apply(Class<T> c, Explanation explanation) { | |
288 | try { | |
289 |
1
1. apply : replaced return value with null for com/github/dakusui/pcond/validator/ExceptionComposer$Utils$ReflectiveExceptionFactory::apply → KILLED |
return create(c, explanation); |
290 | } catch (InvocationTargetException | InstantiationException | | |
291 | IllegalAccessException | NoSuchMethodException e) { | |
292 | throw new RuntimeException("FAILED TO INSTANTIATE EXCEPTION: '" + c.getCanonicalName() + "'", e); | |
293 | } | |
294 | } | |
295 | } | |
296 | } | |
297 | } | |
Mutations | ||
89 |
1.1 |
|
94 |
1.1 |
|
99 |
1.1 |
|
104 |
1.1 |
|
109 |
1.1 |
|
136 |
1.1 |
|
147 |
1.1 |
|
164 |
1.1 |
|
173 |
1.1 |
|
181 |
1.1 |
|
192 |
1.1 |
|
196 |
1.1 |
|
206 |
1.1 |
|
210 |
1.1 |
|
214 |
1.1 |
|
226 |
1.1 |
|
239 |
1.1 |
|
248 |
1.1 |
|
258 |
1.1 |
|
265 |
1.1 |
|
276 |
1.1 |
|
289 |
1.1 |