Skip to content

Commit bf4fcdc

Browse files
authored
Merge pull request jMonkeyEngine#2499 from capdevon/capdevon-ConstantVerifierState
Feat: ConstantVerifierState - expand JME constant verification, fix logger name + javadoc
2 parents a6fbad5 + cb167d8 commit bf4fcdc

File tree

1 file changed

+75
-25
lines changed

1 file changed

+75
-25
lines changed

jme3-core/src/main/java/com/jme3/app/state/ConstantVerifierState.java

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014-2021 jMonkeyEngine
2+
* Copyright (c) 2014-2025 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -29,30 +29,39 @@
2929
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3030
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3131
*/
32-
3332
package com.jme3.app.state;
3433

35-
import java.util.Arrays;
36-
import java.util.logging.Logger;
37-
3834
import com.jme3.app.Application;
39-
import com.jme3.math.*;
35+
import com.jme3.math.Matrix3f;
36+
import com.jme3.math.Matrix4f;
37+
import com.jme3.math.Quaternion;
38+
import com.jme3.math.Vector2f;
39+
import com.jme3.math.Vector3f;
40+
import com.jme3.math.Vector4f;
4041
import com.jme3.util.SafeArrayList;
4142

43+
import java.util.Arrays;
44+
import java.util.logging.Logger;
45+
46+
import static java.lang.Float.NEGATIVE_INFINITY;
4247
import static java.lang.Float.NaN;
4348
import static java.lang.Float.POSITIVE_INFINITY;
44-
import static java.lang.Float.NEGATIVE_INFINITY;
4549

4650
/**
47-
* Checks the various JME 'constants' for drift using either asserts
48-
* or straight checks. The list of constants can also be configured
49-
* but defaults to the standard JME Vector3f, Quaternion, etc. constants.
51+
* An AppState that periodically checks the values of various JME math constants
52+
* (e.g., `Vector3f.ZERO`, `Quaternion.IDENTITY`) against their known good values.
53+
* This is useful for detecting accidental modifications or "drift" of these
54+
* supposedly immutable constants during application runtime.
55+
* <p>
56+
* The state can be configured to report discrepancies using asserts,
57+
* throwing runtime exceptions, or logging severe messages.
58+
* The set of constants to check is configurable.
5059
*
51-
* @author Paul Speed
60+
* @author Paul Speed
5261
*/
5362
public class ConstantVerifierState extends BaseAppState {
5463

55-
private static final Logger log = Logger.getLogger(BaseAppState.class.getName());
64+
private static final Logger log = Logger.getLogger(ConstantVerifierState.class.getName());
5665

5766
// Note: I've used actual constructed objects for the good values
5867
// instead of clone just to better catch cases where the values
@@ -73,7 +82,14 @@ public class ConstantVerifierState extends BaseAppState {
7382
new Quaternion().fromAxes(Vector3f.UNIT_X, Vector3f.UNIT_Y, Vector3f.UNIT_Z)),
7483
new Checker(Quaternion.ZERO, new Quaternion(0, 0, 0, 0)),
7584
new Checker(Vector2f.ZERO, new Vector2f(0f, 0f)),
85+
new Checker(Vector2f.NAN, new Vector2f(NaN, NaN)),
86+
new Checker(Vector2f.UNIT_X, new Vector2f(1, 0)),
87+
new Checker(Vector2f.UNIT_Y, new Vector2f(0, 1)),
7688
new Checker(Vector2f.UNIT_XY, new Vector2f(1f, 1f)),
89+
new Checker(Vector2f.POSITIVE_INFINITY,
90+
new Vector2f(POSITIVE_INFINITY, POSITIVE_INFINITY)),
91+
new Checker(Vector2f.NEGATIVE_INFINITY,
92+
new Vector2f(NEGATIVE_INFINITY, NEGATIVE_INFINITY)),
7793
new Checker(Vector4f.ZERO, new Vector4f(0, 0, 0, 0)),
7894
new Checker(Vector4f.NAN, new Vector4f(NaN, NaN, NaN, NaN)),
7995
new Checker(Vector4f.UNIT_X, new Vector4f(1, 0, 0, 0)),
@@ -91,24 +107,34 @@ public class ConstantVerifierState extends BaseAppState {
91107
new Checker(Matrix4f.IDENTITY, new Matrix4f())
92108
};
93109

94-
public enum ErrorType { Assert, Exception, Log };
110+
/**
111+
* Defines how constant value discrepancies should be reported.
112+
*/
113+
public enum ErrorType {
114+
/** Causes an `assert` failure if the constant has changed. Requires assertions to be enabled. */
115+
Assert,
116+
/** Throws a `RuntimeException` if the constant has changed. */
117+
Exception,
118+
/** Logs a severe message if the constant has changed. */
119+
Log
120+
}
95121

96-
final private SafeArrayList<Checker> checkers = new SafeArrayList<>(Checker.class);
122+
private final SafeArrayList<Checker> checkers = new SafeArrayList<>(Checker.class);
97123
private ErrorType errorType;
98124

99125
/**
100-
* Creates a verifier app state that will check all of the default
101-
* constant checks using asserts.
126+
* Creates a verifier app state that will check all of the default
127+
* JME math constants using `ErrorType.Assert`.
102128
*/
103129
public ConstantVerifierState() {
104130
this(ErrorType.Assert);
105131
}
106132

107133
/**
108-
* Creates a verifier app state that will check all of the default
109-
* constant checks using the specified error reporting mechanism.
134+
* Creates a verifier app state that will check all of the default
135+
* JME math constants using the specified error reporting mechanism.
110136
*
111-
* @param errorType the mechanism to use
137+
* @param errorType The mechanism to use when a constant's value drifts.
112138
*/
113139
public ConstantVerifierState(ErrorType errorType) {
114140
this(errorType, DEFAULT_CHECKS);
@@ -126,14 +152,32 @@ private ConstantVerifierState(ErrorType errorType, Checker... checkers) {
126152
this.checkers.addAll(Arrays.asList(checkers));
127153
}
128154

155+
/**
156+
* Adds a new constant and its expected good value to the list of items to be checked.
157+
* The `constant` and `goodValue` should be instances of the same class.
158+
*
159+
* @param constant The JME constant object to monitor for drift (e.g., `Vector3f.ZERO`).
160+
* @param goodValue An independent instance representing the expected correct value of the constant.
161+
* This instance should match the initial value of `constant`.
162+
*/
129163
public void addChecker(Object constant, Object goodValue) {
130164
checkers.add(new Checker(constant, goodValue));
131165
}
132166

167+
/**
168+
* Sets the error reporting mechanism to be used when a constant's value drifts.
169+
*
170+
* @param errorType The desired error reporting type.
171+
*/
133172
public void setErrorType(ErrorType errorType) {
134173
this.errorType = errorType;
135174
}
136175

176+
/**
177+
* Returns the currently configured error reporting mechanism.
178+
*
179+
* @return The current `ErrorType`.
180+
*/
137181
public ErrorType getErrorType() {
138182
return errorType;
139183
}
@@ -161,21 +205,26 @@ public void postRender() {
161205
checkValues();
162206
}
163207

208+
/**
209+
* Iterates through all registered checkers and verifies the current values
210+
* of the constants against their known good values.
211+
* Reports any discrepancies based on the configured `ErrorType`.
212+
*/
164213
protected void checkValues() {
165214
for (Checker checker : checkers.getArray()) {
166215
switch (errorType) {
167-
default:
216+
default: // Fall through to Assert if somehow null
168217
case Assert:
169218
assert checker.isValid() : checker.toString();
170219
break;
171220
case Exception:
172221
if (!checker.isValid()) {
173-
throw new RuntimeException("Constant has changed, " + checker.toString());
222+
throw new RuntimeException("JME Constant has changed, " + checker.toString());
174223
}
175224
break;
176225
case Log:
177226
if (!checker.isValid()) {
178-
log.severe("Constant has changed, " + checker.toString());
227+
log.severe("JME Constant has changed, " + checker.toString());
179228
}
180229
break;
181230
}
@@ -188,16 +237,17 @@ protected void checkValues() {
188237
* mean anything.
189238
*/
190239
private static class Checker {
191-
private Object constant;
192-
private Object goodValue;
240+
241+
private final Object constant;
242+
private final Object goodValue;
193243

194244
public Checker(Object constant, Object goodValue) {
195245
if (constant == null) {
196246
throw new IllegalArgumentException("Constant cannot be null");
197247
}
198248
if (!constant.equals(goodValue)) {
199249
throw new IllegalArgumentException(
200-
"Constant value:" + constant + " does not match value:" + goodValue);
250+
"Constant value: " + constant + " does not match value: " + goodValue);
201251
}
202252
this.constant = constant;
203253
this.goodValue = goodValue;

0 commit comments

Comments
 (0)