Skip to content

Commit 227120f

Browse files
Add NativeMathBridgeTest and remove old test
Replace the previous MathPrimitivesTest with a much more comprehensive NativeMathBridgeTest. The new test class adds nested suites covering null handling, degenerate inputs, boundary/extrapolation, output buffer reuse, extreme/sign cases, and public API sanity for Segment2, Ray2, Transform2, Vec2, Rect, and Circle. Includes helper assertion methods for vector and approximate equality and expands coverage of edge conditions and native-bridge behaviors.
1 parent 020258c commit 227120f

2 files changed

Lines changed: 278 additions & 48 deletions

File tree

core/src/test/java/com/jvn/core/math/MathPrimitivesTest.java

Lines changed: 0 additions & 48 deletions
This file was deleted.
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
package com.jvn.core.nativebridge;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertFalse;
5+
import static org.junit.jupiter.api.Assertions.assertNotNull;
6+
import static org.junit.jupiter.api.Assertions.assertNull;
7+
import static org.junit.jupiter.api.Assertions.assertSame;
8+
import static org.junit.jupiter.api.Assertions.assertTrue;
9+
import org.junit.jupiter.api.Nested;
10+
import org.junit.jupiter.api.Test;
11+
12+
import com.jvn.core.math.Circle;
13+
import com.jvn.core.math.Ray2;
14+
import com.jvn.core.math.Rect;
15+
import com.jvn.core.math.Segment2;
16+
import com.jvn.core.math.Transform2;
17+
import com.jvn.core.math.Vec2;
18+
19+
class NativeMathBridgeTest {
20+
21+
@Nested
22+
@SuppressWarnings("unused")
23+
class NullHandlingTests {
24+
25+
@Test
26+
void segmentSetNullStartAndEndDefaultsToZeros() {
27+
Segment2 segment = new Segment2();
28+
segment.set(null, null);
29+
30+
assertEquals(0.0, segment.x1, 1e-9);
31+
assertEquals(0.0, segment.y1, 1e-9);
32+
assertEquals(0.0, segment.x2, 1e-9);
33+
assertEquals(0.0, segment.y2, 1e-9);
34+
}
35+
36+
@Test
37+
void raySetNullOriginAndDirectionDefaultsToZeros() {
38+
Ray2 ray = new Ray2();
39+
ray.set(null, null);
40+
41+
assertEquals(0.0, ray.x, 1e-9);
42+
assertEquals(0.0, ray.y, 1e-9);
43+
assertEquals(0.0, ray.dx, 1e-9);
44+
assertEquals(0.0, ray.dy, 1e-9);
45+
}
46+
47+
@Test
48+
void transformApplyToNullReturnsNull() {
49+
Transform2 transform = new Transform2(2, 3, 45, 2, 2);
50+
assertNull(transform.applyTo(null));
51+
}
52+
53+
@Test
54+
void pointSamplingAllocatesOutputWhenNullPassed() {
55+
Segment2 segment = new Segment2(0, 0, 10, 20);
56+
Ray2 ray = new Ray2(1, 2, 3, 4);
57+
58+
Vec2 segmentPoint = segment.pointAt(0.5, null);
59+
Vec2 rayPoint = ray.pointAt(2.0, null);
60+
61+
assertNotNull(segmentPoint);
62+
assertNotNull(rayPoint);
63+
assertEquals(5.0, segmentPoint.x, 1e-9);
64+
assertEquals(10.0, segmentPoint.y, 1e-9);
65+
assertEquals(7.0, rayPoint.x, 1e-9);
66+
assertEquals(10.0, rayPoint.y, 1e-9);
67+
}
68+
}
69+
70+
@Nested
71+
@SuppressWarnings("unused")
72+
class DegenerateInputTests {
73+
74+
@Test
75+
void zeroLengthSegmentHasZeroLengthAndCollapsedBounds() {
76+
Segment2 segment = new Segment2(5, 5, 5, 5);
77+
Rect bounds = segment.bounds(null);
78+
79+
assertEquals(0.0, segment.length(), 1e-9);
80+
assertEquals(5.0, bounds.x, 1e-9);
81+
assertEquals(5.0, bounds.y, 1e-9);
82+
assertEquals(0.0, bounds.w, 1e-9);
83+
assertEquals(0.0, bounds.h, 1e-9);
84+
}
85+
86+
@Test
87+
void zeroDirectionRayIsDegenerateAndSafeToNormalize() {
88+
Ray2 ray = new Ray2(4, 8, 0, 0);
89+
assertTrue(ray.isDegenerate());
90+
91+
ray.normalizeDirection();
92+
93+
assertEquals(0.0, ray.dx, 1e-9);
94+
assertEquals(0.0, ray.dy, 1e-9);
95+
assertEquals(0.0, ray.directionLength(), 1e-9);
96+
}
97+
98+
@Test
99+
void zeroVectorNormalizeDoesNotChangeVector() {
100+
Vec2 vector = new Vec2(0, 0);
101+
vector.normalize();
102+
103+
assertEquals(0.0, vector.x, 1e-9);
104+
assertEquals(0.0, vector.y, 1e-9);
105+
}
106+
107+
@Test
108+
void zeroScaleTransformCollapsesPointToTranslation() {
109+
Transform2 transform = new Transform2(9, 11, 15, 0, 0);
110+
Vec2 result = transform.transform(200, -50, null);
111+
112+
assertEquals(9.0, result.x, 1e-9);
113+
assertEquals(11.0, result.y, 1e-9);
114+
}
115+
}
116+
117+
@Nested
118+
@SuppressWarnings("unused")
119+
class BoundaryAndExtrapolationTests {
120+
121+
@Test
122+
void segmentPointAtSupportsBoundaryAndExtrapolatedT() {
123+
Segment2 segment = new Segment2(10, 10, 20, 30);
124+
125+
Vec2 start = segment.pointAt(0.0, null);
126+
Vec2 mid = segment.pointAt(0.5, null);
127+
Vec2 end = segment.pointAt(1.0, null);
128+
Vec2 before = segment.pointAt(-1.0, null);
129+
Vec2 after = segment.pointAt(2.0, null);
130+
131+
assertVecEquals(10, 10, start);
132+
assertVecEquals(15, 20, mid);
133+
assertVecEquals(20, 30, end);
134+
assertVecEquals(0, -10, before);
135+
assertVecEquals(30, 50, after);
136+
}
137+
138+
@Test
139+
void rayPointAtSupportsNegativeAndPositiveDistance() {
140+
Ray2 ray = new Ray2(5, 6, 2, 3);
141+
142+
Vec2 atZero = ray.pointAt(0.0, null);
143+
Vec2 backward = ray.pointAt(-2.0, null);
144+
Vec2 forward = ray.pointAt(3.5, null);
145+
146+
assertVecEquals(5, 6, atZero);
147+
assertVecEquals(1, 0, backward);
148+
assertVecEquals(12, 16.5, forward);
149+
}
150+
}
151+
152+
@Nested
153+
@SuppressWarnings("unused")
154+
class OutputReuseTests {
155+
156+
@Test
157+
void segmentUsesProvidedOutputBuffer() {
158+
Segment2 segment = new Segment2(1, 2, 5, 6);
159+
Vec2 out = new Vec2();
160+
161+
Vec2 result = segment.pointAt(0.5, out);
162+
163+
assertSame(out, result);
164+
assertVecEquals(3, 4, out);
165+
}
166+
167+
@Test
168+
void rayUsesProvidedOutputBuffer() {
169+
Ray2 ray = new Ray2(1, 2, 3, 4);
170+
Vec2 out = new Vec2();
171+
172+
Vec2 result = ray.pointAt(2.0, out);
173+
174+
assertSame(out, result);
175+
assertVecEquals(7, 10, out);
176+
}
177+
178+
@Test
179+
void transformUsesProvidedOutputBuffer() {
180+
Transform2 transform = new Transform2(10, 20, 0, 2, 3);
181+
Vec2 out = new Vec2();
182+
183+
Vec2 result = transform.transform(1, 1, out);
184+
185+
assertSame(out, result);
186+
assertVecEquals(12, 23, out);
187+
}
188+
189+
@Test
190+
void segmentBoundsUsesProvidedOutputBuffer() {
191+
Segment2 segment = new Segment2(2, 9, -3, 4);
192+
Rect out = new Rect();
193+
194+
Rect result = segment.bounds(out);
195+
196+
assertSame(out, result);
197+
assertEquals(-3.0, out.x, 1e-9);
198+
assertEquals(4.0, out.y, 1e-9);
199+
assertEquals(5.0, out.w, 1e-9);
200+
assertEquals(5.0, out.h, 1e-9);
201+
}
202+
}
203+
204+
@Nested
205+
@SuppressWarnings("unused")
206+
class ExtremeAndSignTests {
207+
208+
@Test
209+
void vectorOperationsHandleInfinityAndNaN() {
210+
Vec2 v = new Vec2(Double.POSITIVE_INFINITY, 1);
211+
v.add(new Vec2(1, Double.NaN));
212+
213+
assertTrue(Double.isInfinite(v.x));
214+
assertTrue(Double.isNaN(v.y));
215+
}
216+
217+
@Test
218+
void veryLargeRotationBehavesLikeEquivalentAngle() {
219+
Transform2 transform = new Transform2(0, 0, 3600, 1, 1);
220+
Vec2 rotated = transform.transform(1, 0, null);
221+
222+
assertApproxEquals(1.0, rotated.x);
223+
assertApproxEquals(0.0, rotated.y);
224+
}
225+
226+
@Test
227+
void negativeScaleFlipsDirection() {
228+
Transform2 transform = new Transform2(0, 0, 0, -2, 1);
229+
Vec2 result = transform.transform(3, 4, null);
230+
231+
assertVecEquals(-6, 4, result);
232+
}
233+
234+
@Test
235+
void negativeRadiusFollowsSquaredDistanceRule() {
236+
Circle circle = new Circle(5, 5, -2);
237+
238+
assertTrue(circle.contains(5, 5));
239+
assertFalse(circle.contains(10, 10));
240+
}
241+
}
242+
243+
@Nested
244+
@SuppressWarnings("unused")
245+
class PublicEntryPointSanityTests {
246+
247+
@Test
248+
void vec2PublicMethodsRemainChainable() {
249+
Vec2 v = new Vec2(1, 2);
250+
251+
assertSame(v, v.add(new Vec2(3, 4)));
252+
assertSame(v, v.sub(new Vec2(1, 1)));
253+
assertSame(v, v.scale(2.0));
254+
assertSame(v, v.normalize());
255+
assertTrue(Double.isFinite(v.length()));
256+
}
257+
258+
@Test
259+
void rectIntersectsAndContainsCoverEdgeBoundaries() {
260+
Rect a = new Rect(0, 0, 10, 10);
261+
Rect b = new Rect(10, 10, 5, 5);
262+
263+
assertTrue(a.contains(0, 0));
264+
assertTrue(a.contains(10, 10));
265+
assertTrue(a.intersects(b));
266+
assertTrue(b.intersects(a));
267+
}
268+
}
269+
270+
private static void assertVecEquals(double expectedX, double expectedY, Vec2 value) {
271+
assertEquals(expectedX, value.x, 1e-9);
272+
assertEquals(expectedY, value.y, 1e-9);
273+
}
274+
275+
private static void assertApproxEquals(double expected, double actual) {
276+
assertEquals(expected, actual, 1e-6);
277+
}
278+
}

0 commit comments

Comments
 (0)