ExceptionComposer.java

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
Location : forRequire
Killed by : com.github.valid8j.entrypoints.RequiresTest.givenValidArgument_whenRequireArgument_thenValueReturned(com.github.valid8j.entrypoints.RequiresTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$Impl::forRequire → KILLED

93

1.1
Location : forEnsure
Killed by : com.github.valid8j.entrypoints.EnsuresTest.givenValidState_whenEnsureState_thenStateReturned(com.github.valid8j.entrypoints.EnsuresTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$Impl::forEnsure → KILLED

98

1.1
Location : defaultForValidate
Killed by : none
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$Impl::defaultForValidate → SURVIVED

103

1.1
Location : forAssert
Killed by : com.github.valid8j.entrypoints.AssertionsTest$Failing
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$Impl::forAssert → KILLED

108

1.1
Location : forAssertThat
Killed by : com.github.valid8j.ut.utilstest.FluentUtilsTest.example2(com.github.valid8j.ut.utilstest.FluentUtilsTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$Impl::forAssertThat → KILLED

135

1.1
Location : exceptionForNonNullViolation
Killed by : none
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$Base::exceptionForNonNullViolation → SURVIVED

146

1.1
Location : exceptionForIllegalState
Killed by : com.github.valid8j.entrypoints.EnsuresTest.testEnsureState(com.github.valid8j.entrypoints.EnsuresTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$Base::exceptionForIllegalState → KILLED

163

1.1
Location : exceptionForGeneralViolation
Killed by : com.github.valid8j.entrypoints.RequiresTest.testRequire$thenError(com.github.valid8j.entrypoints.RequiresTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForRequire::exceptionForGeneralViolation → KILLED

172

1.1
Location : exceptionForIllegalArgument
Killed by : com.github.valid8j.entrypoints.RequiresTest.givenIllegalArgument_whenRequireArgument_thenIllegalArgumentThrown(com.github.valid8j.entrypoints.RequiresTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForRequire$Default::exceptionForIllegalArgument → KILLED

180

1.1
Location : exceptionForGeneralViolation
Killed by : com.github.valid8j.entrypoints.EnsuresTest.givenIllegalValue_whenEnsure_thenPostconditionViolationThrown(com.github.valid8j.entrypoints.EnsuresTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForEnsure::exceptionForGeneralViolation → KILLED

191

1.1
Location : exceptionForGeneralViolation
Killed by : none
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForValidate::exceptionForGeneralViolation → NO_COVERAGE

195

1.1
Location : exceptionForIllegalArgument
Killed by : com.github.valid8j.entrypoints.ValidatesTest.test_validateArgument_fail(com.github.valid8j.entrypoints.ValidatesTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForValidate::exceptionForIllegalArgument → KILLED

205

1.1
Location : exceptionPreconditionViolation
Killed by : com.github.valid8j.entrypoints.AssertionsTest$Failing
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForAssertion::exceptionPreconditionViolation → KILLED

209

1.1
Location : exceptionInvariantConditionViolation
Killed by : com.github.valid8j.entrypoints.AssertionsTest$Failing
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForAssertion::exceptionInvariantConditionViolation → KILLED

213

1.1
Location : exceptionPostconditionViolation
Killed by : com.github.valid8j.entrypoints.AssertionsTest$Failing
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForAssertion::exceptionPostconditionViolation → KILLED

225

1.1
Location : testSkippedException
Killed by : none
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForTestAssertion::testSkippedException → NO_COVERAGE

238

1.1
Location : lambda$testSkippedException$0
Killed by : com.github.valid8j.ut.utilstest.TestAssertionsTest.testAssumeThat(com.github.valid8j.ut.utilstest.TestAssertionsTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForTestAssertion$JUnit4::lambda$testSkippedException$0 → KILLED

247

1.1
Location : lambda$testFailedException$1
Killed by : com.github.valid8j.ut.utilstest.FluentUtilsTest.example2(com.github.valid8j.ut.utilstest.FluentUtilsTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForTestAssertion$JUnit4::lambda$testFailedException$1 → KILLED

257

1.1
Location : lambda$testSkippedException$0
Killed by : com.github.valid8j.ut.valuechecker.Opentest4jTest.test_testSkippedException$String(com.github.valid8j.ut.valuechecker.Opentest4jTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForTestAssertion$Opentest4J::lambda$testSkippedException$0 → KILLED

264

1.1
Location : lambda$testFailedException$1
Killed by : com.github.valid8j.ut.valuechecker.Opentest4jTest.test_testFailedException(com.github.valid8j.ut.valuechecker.Opentest4jTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$ForTestAssertion$Opentest4J::lambda$testFailedException$1 → KILLED

275

1.1
Location : createException
Killed by : com.github.valid8j.ut.valuechecker.Opentest4jTest.test_testSkippedException$String(com.github.valid8j.ut.valuechecker.Opentest4jTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$Utils::createException → KILLED

288

1.1
Location : apply
Killed by : com.github.valid8j.ut.valuechecker.Opentest4jTest.test_testSkippedException$String(com.github.valid8j.ut.valuechecker.Opentest4jTest)
replaced return value with null for com/github/valid8j/pcond/validator/ExceptionComposer$Utils$ReflectiveExceptionFactory::apply → KILLED

Active mutators

Tests examined


Report generated by PIT 1.7.3