-
Notifications
You must be signed in to change notification settings - Fork 0
correctness: Add degenerate calibration guard to Calibration transform #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8d0bc7a
8ef2103
7a45d81
b59948a
8ca6f0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,6 +24,18 @@ | |||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| public Calibration(double scale, double originX, double originY, double angle) { | ||||||||||||||||||||
| if (!Double.isFinite(scale) || scale == 0.0) { | ||||||||||||||||||||
|
Check warning on line 27 in src/main/java/org/opensourcephysics/cabrillo/tracker/calibration/Calibration.java
|
||||||||||||||||||||
| throw new IllegalArgumentException("Invalid scale: " + scale); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| if (!Double.isFinite(originX)) { | ||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 [suggestion] Negative zero scale passes validation but may be degenerate The check There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 [suggestion] Magic string pattern in exception messages The error message prefix Suggested fix:
Suggested change
|
||||||||||||||||||||
| throw new IllegalArgumentException("Invalid originX: " + originX); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| if (!Double.isFinite(originY)) { | ||||||||||||||||||||
| throw new IllegalArgumentException("Invalid originY: " + originY); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| if (!Double.isFinite(angle)) { | ||||||||||||||||||||
| throw new IllegalArgumentException("Invalid angle: " + angle); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| this.scale = scale; | ||||||||||||||||||||
| this.originX = originX; | ||||||||||||||||||||
| this.originY = originY; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -82,4 +82,45 @@ | |||||||||||||||||||||||||||
| assertEquals(412.5, p.x(), 1e-9); | ||||||||||||||||||||||||||||
| assertEquals(173.25, p.y(), 1e-9); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| @Test | ||||||||||||||||||||||||||||
| public void testDegenerateScale() { | ||||||||||||||||||||||||||||
| IllegalArgumentException ex1 = assertThrows(IllegalArgumentException.class, () -> new Calibration(0.0, 0, 0, 0)); | ||||||||||||||||||||||||||||
| assertTrue(ex1.getMessage().contains("scale")); | ||||||||||||||||||||||||||||
| IllegalArgumentException ex2 = assertThrows(IllegalArgumentException.class, () -> new Calibration(Double.NaN, 0, 0, 0)); | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔵 [suggestion] Test assertions use substring matching instead of exact validation The degenerate tests use Suggested fix:
Suggested change
|
||||||||||||||||||||||||||||
| assertTrue(ex2.getMessage().contains("scale")); | ||||||||||||||||||||||||||||
| IllegalArgumentException ex3 = assertThrows(IllegalArgumentException.class, () -> new Calibration(Double.POSITIVE_INFINITY, 0, 0, 0)); | ||||||||||||||||||||||||||||
| assertTrue(ex3.getMessage().contains("scale")); | ||||||||||||||||||||||||||||
| IllegalArgumentException ex4 = assertThrows(IllegalArgumentException.class, () -> new Calibration(Double.NEGATIVE_INFINITY, 0, 0, 0)); | ||||||||||||||||||||||||||||
| assertTrue(ex4.getMessage().contains("scale")); | ||||||||||||||||||||||||||||
|
Check warning on line 98 in src/test/java/org/opensourcephysics/cabrillo/tracker/calibration/CalibrationTest.java
|
||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 [warning] Weak test assertions using message substring matching The Suggested fix:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 [warning] Missing test for negative scale values The constructor at line 27 in |
||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| @Test | ||||||||||||||||||||||||||||
| public void testDegenerateOrigin() { | ||||||||||||||||||||||||||||
| IllegalArgumentException ex1 = assertThrows(IllegalArgumentException.class, () -> new Calibration(1.0, Double.NaN, 0, 0)); | ||||||||||||||||||||||||||||
| assertTrue(ex1.getMessage().contains("originX")); | ||||||||||||||||||||||||||||
| IllegalArgumentException ex2 = assertThrows(IllegalArgumentException.class, () -> new Calibration(1.0, 0, Double.NaN, 0)); | ||||||||||||||||||||||||||||
| assertTrue(ex2.getMessage().contains("originY")); | ||||||||||||||||||||||||||||
| IllegalArgumentException ex3 = assertThrows(IllegalArgumentException.class, () -> new Calibration(1.0, Double.POSITIVE_INFINITY, 0, 0)); | ||||||||||||||||||||||||||||
| assertTrue(ex3.getMessage().contains("originX")); | ||||||||||||||||||||||||||||
| IllegalArgumentException ex4 = assertThrows(IllegalArgumentException.class, () -> new Calibration(1.0, Double.NEGATIVE_INFINITY, 0, 0)); | ||||||||||||||||||||||||||||
| assertTrue(ex4.getMessage().contains("originX")); | ||||||||||||||||||||||||||||
| IllegalArgumentException ex5 = assertThrows(IllegalArgumentException.class, () -> new Calibration(1.0, 0, Double.POSITIVE_INFINITY, 0)); | ||||||||||||||||||||||||||||
|
Check warning on line 111 in src/test/java/org/opensourcephysics/cabrillo/tracker/calibration/CalibrationTest.java
|
||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 [warning] Weak test assertions using message substring matching The Suggested fix:
Suggested change
|
||||||||||||||||||||||||||||
| assertTrue(ex5.getMessage().contains("originY")); | ||||||||||||||||||||||||||||
| IllegalArgumentException ex6 = assertThrows(IllegalArgumentException.class, () -> new Calibration(1.0, 0, Double.NEGATIVE_INFINITY, 0)); | ||||||||||||||||||||||||||||
| assertTrue(ex6.getMessage().contains("originY")); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| @Test | ||||||||||||||||||||||||||||
| public void testDegenerateAngle() { | ||||||||||||||||||||||||||||
| IllegalArgumentException ex1 = assertThrows(IllegalArgumentException.class, () -> new Calibration(1.0, 0, 0, Double.NaN)); | ||||||||||||||||||||||||||||
| assertTrue(ex1.getMessage().contains("angle")); | ||||||||||||||||||||||||||||
|
Check warning on line 120 in src/test/java/org/opensourcephysics/cabrillo/tracker/calibration/CalibrationTest.java
|
||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 [warning] Weak test assertions using message substring matching The Suggested fix:
Suggested change
|
||||||||||||||||||||||||||||
| IllegalArgumentException ex2 = assertThrows(IllegalArgumentException.class, () -> new Calibration(1.0, 0, 0, Double.POSITIVE_INFINITY)); | ||||||||||||||||||||||||||||
| assertTrue(ex2.getMessage().contains("angle")); | ||||||||||||||||||||||||||||
| IllegalArgumentException ex3 = assertThrows(IllegalArgumentException.class, () -> new Calibration(1.0, 0, 0, Double.NEGATIVE_INFINITY)); | ||||||||||||||||||||||||||||
| assertTrue(ex3.getMessage().contains("angle")); | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 [warning] Negative scale values accepted but likely semantically invalid
Line 27 checks
scale == 0.0but permits negative scale values. A negative scale (meters per pixel) would invert coordinate transformations intoWorld(line 54:rx * scale) andtoPixel(line 66:worldX / scale), producing mirrored world coordinates. For a physical calibration system, scale should be strictly positive. The check should bescale <= 0.0instead ofscale == 0.0, or the validation should usescale > 0.0.Suggested fix: