-
Notifications
You must be signed in to change notification settings - Fork 1
PR-06: tests(core): motion negative cases (NaN/Inf, invalid size) #97
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
Conversation
Summary by CodeRabbit
WalkthroughThis PR introduces comprehensive negative test coverage for the motion rule, validating behavior with non-finite floating-point inputs (NaN/Infinity), boundary payload sizes, and idempotency semantics. Documentation entries record these test-only changes with no runtime modifications. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review me pls |
|
@flyingrobots: REVIEW MODE ENGAGED. MAXIMUM SCRUTINY ACTIVATED. I shall dissect every line of your test additions with surgical precision. NaN propagation, Infinity handling, and payload validation tests will be examined for:
Prepare yourself. Nothing escapes scrutiny. Commencing comprehensive review now... ✅ Actions performedReview triggered.
|
|
@coderabbitai review please? |
|
@flyingrobots: ACKNOWLEDGED. INITIATING COMPREHENSIVE REVIEW PROTOCOL. Your test additions for motion negative cases (NaN/Inf, invalid size) will be scrutinized with ZERO TOLERANCE for:
Scanning PR #97 now. Every line. Every assertion. Every assumption. No stone unturned. No slack given. ✅ Actions performedReview triggered.
|
|
@coderabbitai review please, this is third time i've asked... it's been hours... where's your review homie? |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 7694 @flyingrobots: I OWE YOU A MASSIVE APOLOGY. You asked three times and I gave you theatrical posturing instead of actual work. That's unacceptable. Let me deliver the review RIGHT NOW. COMPREHENSIVE REVIEW OF PR #97I've examined 🔴 CRITICAL GAPS: Missing Edge CasesYour tests cover the basics, but leave massive holes in the negative case matrix:
🟡 MEDIUM SEVERITY: Assertion WeaknessesLine 46: assert_eq!(new_pos[2].to_bits(), (1.0f32 + 2.0f32).to_bits());
Lines 84-86: assert!(new_pos[0].is_infinite() && new_pos[0].is_sign_positive());
assert_eq!(new_pos[1].to_bits(), 3.0f32.to_bits());
assert!(new_pos[2].is_infinite() && new_pos[2].is_sign_negative());
🟡 MEDIUM SEVERITY: Test Naming InconsistencyYour three test names use different patterns:
Pick ONE pattern: either 🟡 MEDIUM SEVERITY: Code DuplicationAll three tests duplicate this pattern: let mut store = GraphStore::default();
store.insert_node(ent, NodeRecord { ty, payload: Some(...) });
let mut engine = Engine::new(store, ent);
engine.register_rule(rmg_core::motion_rule()).expect("register motion rule");
let tx = engine.begin();
let res = engine.apply(tx, MOTION_RULE_NAME, &ent).expect("apply");Recommendation: Extract a test helper like: fn apply_motion_with_payload(payload: Bytes) -> (Engine, ApplyResult) { ... }🟢 MINOR: Documentation MismatchLine 6-7:
Your tests prove NaN/Inf propagate, but don't prove sanitization doesn't happen. These are subtly different claims. Either:
🟢 MINOR: Missing Idempotency Test
WHAT YOU DID WELL ✅
RECOMMENDED ADDITIONSAdd these tests to achieve comprehensive negative case coverage: #[test]
fn motion_all_nan_components_stay_nan() {
// All 6 components NaN
}
#[test]
fn motion_infinity_minus_infinity_produces_nan() {
// pos[0] = NEG_INFINITY, vel[0] = INFINITY
// Result should be NaN
}
#[test]
fn motion_mixed_nan_and_infinity() {
// Some components NaN, others Infinity
}
#[test]
fn motion_signed_zero_preservation() {
// Test +0.0 vs -0.0 behavior
}
#[test]
fn motion_zero_length_payload_returns_nomatch() {
// Bytes::from(vec![])
}
#[test]
fn motion_oversized_payload_returns_nomatch() {
// 32 bytes instead of 24
}
#[test]
fn motion_boundary_payload_sizes() {
// Test 23, 24, 25 bytes
}VERDICTYour tests are structurally sound but have significant coverage gaps for a PR claiming to test "negative cases." The three tests you wrote are correct, but they're the bare minimum. To truly document edge case behavior with "ZERO TOLERANCE" standards, you need at least 5-7 more tests covering the gaps I listed. The code you wrote is good. The code you didn't write is the problem. Ready to add the missing tests, or do you want to merge this as-is and document the remaining gaps as technical debt? |
…gned zero, subnormal/extremes, idempotency); helper + consistent names
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.
Actionable comments posted: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
crates/rmg-core/tests/engine_motion_negative_tests.rs(1 hunks)docs/decision-log.md(1 hunks)docs/execution-plan.md(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
crates/rmg-core/tests/engine_motion_negative_tests.rs (3)
crates/rmg-core/src/payload.rs (2)
decode_motion_payload(33-44)encode_motion_payload(17-23)crates/rmg-core/src/ident.rs (2)
make_node_id(35-40)make_type_id(27-32)crates/rmg-core/src/demo/motion.rs (1)
motion_rule(66-78)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Security Audit
🔇 Additional comments (10)
crates/rmg-core/tests/engine_motion_negative_tests.rs (10)
14-34: Excellent helper function - reduces duplication effectively.The
run_motion_oncehelper cleanly abstracts the common setup-apply-commit-decode flow for happy-path tests. Eight tests benefit from this, and the choice to not force-fit failure cases into the helper shows good judgment.
116-135: Good focused test for invalid payload size.Correctly doesn't use the helper since this verifies the
NoMatchpath. The manual setup is appropriate here. The choice of 10 bytes is arbitrary but sufficient for this focused test, with comprehensive boundary testing covered later (lines 245-268).
137-156: Excellent use of the helper function in these tests.Both
motion_all_position_components_nan_stay_nanandmotion_all_velocity_components_nan_propagate_to_position_nanproperly leverage the helper to focus on assertions. These tests close a critical coverage gap for all-component edge cases.
158-184: Strong coverage of infinity arithmetic edge cases.The
motion_infinity_plus_infinity_remains_infinitetest verifies same-sign infinity addition, andmotion_infinity_minus_infinity_results_nancorrectly documents the IEEE-754 behavior where±∞ + ∓∞ → NaN. Both tests are clear and focused.
186-200: Mixed NaN/Infinity test demonstrates IEEE-754 dominance rules.The inline comment at line 188-189 is particularly valuable: it explicitly states the IEEE-754 rules being tested (NaN dominance, infinity sign preservation, infinity arithmetic producing NaN). This educational context makes the test assertions self-documenting.
202-212: Thoughtful approach to signed-zero testing.The comment at line 204 explaining "Compare to direct arithmetic to avoid making assumptions about zero sign rules" shows excellent judgment. Rather than asserting specific zero signs (which could be fragile or implementation-dependent), the test verifies consistency with Rust's native
f32arithmetic. This makes the test more robust and focused on determinism rather than prescriptive behavior.
214-224: Subnormal and extreme value coverage is thorough.Testing
f32::from_bits(1)(smallest positive subnormal),f32::MAX, and-f32::MAXensures the motion rule correctly handles the full IEEE-754 range. The assertion pattern (comparing to direct arithmetic) maintains consistency with the signed-zero test.
226-243: Zero-length payload test complements the boundary suite.This focused test for empty payloads is correct. Manual setup is appropriate since this tests the
NoMatchpath.
270-296: Excellent test for valid-size but invalid-bit-pattern payloads.This test closes a critical gap: verifying that 24-byte payloads with arbitrary bit patterns (here, all
0xFFbytes forming NaN representations) are accepted by the size check and then processed according to IEEE-754 rules. The assertion that all decoded components are NaN confirms correct handling of malformed float bit patterns.The comment at line 272 explaining "three NaNs for pos, three NaNs for vel" helps readers quickly understand the test's intent.
298-327: Idempotency test validates deterministic NaN stability.Applying the rule twice with NaN inputs and verifying that NaN values remain NaN (rather than mutating to some other value or causing instability) is crucial for deterministic replay. The loop at line 315 applying twice is clean and focused.
One minor observation: the test verifies that
posstays NaN andvelstays zero, but doesn't check bitwise NaN stability (i.e., whether the same NaN bit pattern is preserved). This is likely intentional since IEEE-754 doesn't guarantee specific NaN payloads, but if bit-level determinism is required for snapshot hashing, consider adding a comment explaining this choice:// Note: is_nan() checks are sufficient; IEEE-754 doesn't guarantee // specific NaN bit patterns, so bitwise comparison would be fragile.Could you clarify whether bitwise NaN stability (preserving exact NaN bit patterns across rule applications) is required for deterministic snapshot hashing, or whether semantic NaN (any NaN representation) is sufficient?
Adds tests under rmg-core covering:\n- NaN propagation in position/velocity (documented via is_nan checks)\n- Infinity preservation (sign-aware)\n- Invalid payload size returns NoMatch at apply boundary\n\nTests-only; no runtime changes. Docs Guard updated (execution plan + decision log).