Skip to content

test(joints): cover full-pool creates and five argument refusals - #350

Merged
siracozmen01 merged 1 commit into
mainfrom
joint-refusal-tests
Nov 5, 2026
Merged

siracozmen01 merged 1 commit into
mainfrom
joint-refusal-tests

Conversation

@siracozmen01

Copy link
Copy Markdown
Collaborator

Problem

A coverage run of main over every suite shows joint refusals a host can reach that no test takes. These are the full-pool create of seven joint types, and five argument checks: a distance joint's length range, a mouse target, a gear's ratio, a prismatic joint on one body and a wheel joint with no axis. A change to any of these branches would pass every suite (#349).

Change

test/test_joints.c gains two tests and a helper:

  • CreateJointOfType makes one joint of any of the 11 types between two bodies from its default def.
  • TestJointCreatesAtCapacity: a world whose one joint slot holds a revolute joint refuses each of the 11 types with m2_errorCapacity and the null id. It counts no misuse, and the world hash and joint count are unchanged. With the slot free, each type is made and has its type.
  • TestJointArgumentRefusals:
    • m2DistanceJoint_SetLengthRange with a NaN minimum or an infinite maximum counts one misuse each and keeps the range.
    • m2MouseJoint_SetTarget with a NaN or infinite coordinate counts one misuse each and keeps the target.
    • A gear with a NaN ratio, a prismatic joint from a body to itself, and a wheel joint whose axis is zero are each refused with m2_errorInvalid and the null id, counting one misuse.
    • Throughout, the world hash and the joint count are unchanged.

A test-only change.

Verification

  • test_joints passes.
  • Mutants, each built into a scratch library and run against test_joints:
Mutant Fails
a full pool refuses a distance joint as invalid the 11-type capacity check and its no-misuse check
the same, for gear the same
the same, for motor the same
the same, for prismatic the same
the same, for pulley the same
the same, for ratchet the same
the same, for weld the same
the length range is not checked before it is floored the range check, and the counts after it
the mouse target is not checked the target check, and the count after it
the gear's def check is skipped the gear refusal, and the count after it
a prismatic joint may join a body to itself the prismatic refusal, and the count after it
a wheel joint may have no axis the wheel refusal, and the count after it
  • 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 #349

@siracozmen01 siracozmen01 changed the title test(joints): refuse every joint type at a full pool, and five bad arguments test(joints): cover full-pool creates and five argument refusals Nov 5, 2026

@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 b541721: ready. Read, not run.

The pool is filled through the public API.

  • def.jointCapacity = 1 on the world def, then one revolute joint made with m2CreateRevoluteJoint, fills it.
  • The loop covers m2_distanceJoint (0) to m2_ratchetJoint (10), the eleven contiguous values of m2JointType. CreateJointOfType names ten of them and sends 10 to the ratchet through default.
  • The second loop checks m2Joint_GetType(world, joint) == type, so a helper that made the wrong type would be caught.
  • Each refusal must also leave index1 == 0 in place of {7, 7}, which proves the null id is written.

"No misuse" matches the docs.

  • world.h defines misuse as "the bugs of the calling code: an argument a correct program never passes, a stale id, a writer called from host code the world is running".
  • base.h defines m2_errorCapacity as a pool too small for the result, which a correct program can meet. So a full pool counts nothing, as the test expects.
  • The other test's refusals (NaN or infinite ranges and targets, a NaN ratio, a body joined to itself, a zero axis) are arguments a correct program never passes. They count one each, 7 in all, as joint.h documents for the setters ("counts one misuse") and as m2_errorInvalid does for the creates.
  • misuseCount is "not hashed or snapshotted", so checking the hash after misuse has been counted is sound.

Each assertion can fail, and the body has Problem, Change and Verification.

@siracozmen01
siracozmen01 merged commit 018c4a6 into main Nov 5, 2026
32 of 34 checks passed
@siracozmen01
siracozmen01 deleted the joint-refusal-tests branch November 5, 2026 09:13
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.

Joint refusals a host can reach go untested

1 participant