Skip to content

test(joints): read what a joint's kind does not carry - #358

Merged
siracozmen01 merged 1 commit into
mainfrom
joint-reader-kinds
Nov 5, 2026
Merged

siracozmen01 merged 1 commit into
mainfrom
joint-reader-kinds

Conversation

@siracozmen01

Copy link
Copy Markdown
Collaborator

Problem

No test asks m2Joint_GetLocalAxisA for the axis of a joint that has none, or a tuning reader for a tuning the joint's kind does not carry. Their headers promise zero, and the tuning readers one misuse, but a change to either refusal would pass every suite (#357).

Change

test/test_joints.c gains TestJointReadersCheckTheKind:

  • With one revolute, one filter and one distance joint, each of these reads zero:
    • the revolute joint's axis (m2Joint_GetLocalAxisA);
    • the filter joint's spring (m2Joint_GetSpringHertz);
    • the distance joint's constraint stiffness (m2Joint_GetConstraintHertz);
    • the revolute joint's weld spring (m2WeldJoint_GetLinearSpringHertz).
  • Each counts one misuse.
  • As the near miss, the revolute joint's own spring, set to 3 Hz, reads back and counts nothing.

A test-only change.

Verification

  • test_joints passes.
  • Mutants, each built into a scratch library and run against test_joints:
Mutant Fails
the axis reader's kind check is skipped the axis read, the misuse count and the near miss
a refused tuning read returns 1 the three tuning reads
the tuning slot checks only that the joint is live the misuse count and the near miss
  • tools/check.sh changed passes. The changed file compiles clean with gcc-14 and clang-20 under the strict flags.
  • test_golden prints the 13 lines of test/hashes.txt unchanged in the scalar (linux-clang-20-asan) and AVX2 (linux-clang-20) presets.

Closes #357

@siracozmen01 siracozmen01 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review at 4a5662a: no change needed. I read the code; I did not run it. Checks were still pending when I read them.

Each read matches what include/maul2d/joint.h documents for a joint of the wrong kind:

  • m2Joint_GetSpringHertz on a filter joint (joint.h:818-827). The filter joint is not in its list (distance, wheel, revolute, motor, mouse). It returns 0 and counts one misuse.
  • m2Joint_GetConstraintHertz on a distance joint (796-805). The distance joint is not in its list (revolute, prismatic, gear, pulley, ratchet). It returns 0 and counts one misuse.
  • m2WeldJoint_GetLinearSpringHertz on a revolute joint (840-849). It returns 0 and counts one misuse.
  • m2Joint_GetLocalAxisA on a revolute joint. Its own comment (786-794) promises only zero and says nothing about a misuse. The count the test asserts comes from the file comment at joint.h:7-9: a call made for one joint type "does the same" on another type, meaning it changes nothing, returns zero and counts one misuse. So misuse + 4 is what the header promises as a whole. The function comment could say the misuse as the tuning readers' comments do, but that is not needed for this change.
  • The near miss is valid. The revolute joint is in m2Joint_GetSpringHertz's list. The baseline is taken after m2Joint_SetSpringHertz, so the setter cannot shift the count. The final check also asserts the count did not move.

The body has Problem, Change and Verification. No line starts at column 0 with a word( or type(scope):.

@siracozmen01
siracozmen01 merged commit c102fb2 into main Nov 5, 2026
30 checks passed
@siracozmen01
siracozmen01 deleted the joint-reader-kinds branch November 5, 2026 14:39
siracozmen01 added a commit that referenced this pull request Nov 5, 2026
## Problem

The pair table's merge overflow in `m2UpdatePairs` is reachable from the public API, and no test takes it. It happens when pairs kept from earlier steps plus new candidates run past the table. Its drops are counted in `m2Counters.pairsDropped`, but only the collection's drop is tested, so a change that lost the merge's pairs silently would pass every suite. `m2Joint_GetLocalAxisA`'s `@return` also leaves out the misuse its refusals count (#359).

## Change

- `test/test_broadphase.c` gains `TestFullTableMergeIsCounted`. The world has no gravity and 24 dynamic discs on one spot with every motion lock set. They want 276 pairs, and a world of 24 shapes keeps 192.
  - The first step keeps 192 pairs and counts the other 84.
  - A second step, with nothing moving, keeps the 192 and drops nothing.
  - One disc is teleported 1 mm. Locked, the other discs never leave their fat boxes, so only it meets its 23 neighbors again. The 23 candidates fit the candidate scratch, so every pair lost now is lost in the merge into the full table. The step keeps 192, and counts between 1 and 23.
- `include/maul2d/joint.h`: `m2Joint_GetLocalAxisA`'s `@return` says that another joint type or a stale id reads zero and counts one misuse, as #358 tests.

No result changes: the code is as it was.

## Verification

- `test_broadphase` passes.
- Mutants, each built into a scratch library and run against `test_broadphase`:

| Mutant | Fails |
|---|---|
| the merge drops a pair without counting it | the teleport step's count |
| the collection drops pairs without counting them | the first step's count, and `TestFullPairTableIsCounted` |

- `tools/check.sh changed` passes, the documentation check included. The changed files compile clean with gcc-14 and clang-20 under the strict flags.
- `test_golden` prints the 13 lines of `test/hashes.txt` unchanged in the scalar (`linux-clang-20-asan`) and AVX2 (`linux-clang-20`) presets.

Closes #359
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No test asks a joint reader for what its kind lacks

1 participant