Jondolf / avian

ECS-driven 2D and 3D physics engine for the Bevy game engine.
https://crates.io/crates/avian3d
Apache License 2.0
1.54k stars 120 forks source link

Replace snapshots with hash-based cross-platform determinism test #555

Closed Jondolf closed 1 week ago

Jondolf commented 1 week ago

Objective

Currently, Avian has a cross-platform determinism test that produces insta snapshots, which are compared between platforms in CI with GitHub Actions.

However, these snapshots are quite large, and always pollute diffs in PRs (such as this one) whenever changes affecting simulation behavior are made. Insta must also be installed to generate these snapshots, making it annoying for new contributors to deal with. Overall, it's a hassle.

The test itself is also very simplistic and only tests collisions.

Instead of using snapshots, we should just run the simulation for a while, and compute a single transform hash based on the position and rotation of all bodies. This is much simpler and more convenient.

Solution

Add a 2D test for cross-platform determinism, simulating pairs of objects constrained via revolute joints falling to the ground. After 500 steps, a transform hash is computed and compared against the expected value. If they don't match, the test will fail with a message indicating that the expected hash should be updated if the change in behavior was intended.

test tests::determinism_2d::cross_platform_determinism_2d ... FAILED

failures:

---- tests::determinism_2d::cross_platform_determinism_2d stdout ----
thread 'tests::determinism_2d::cross_platform_determinism_2d' panicked at crates\avian2d\../../src\tests\determinism_2d.rs:63:5:

Expected hash 0xa1c6b39, found hash 0xa38b5132 instead.
If changes in behavior were expected, update the hash in src/tests/determinism_2d.rs on line 61.

This test is based on Box2D's FallingHinges test and sample.

There is also a new determinism_2d example, which is a visual representation of the test.

https://github.com/user-attachments/assets/2d212fe7-14b3-4dff-b1d0-96c531da6918

While making this, I stumbled upon some bugs as well:

I have fixed both of these issues.