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