Strict, 1:1 upstream test conformance against
Flecs Core (flecs/test/core)
and Bevy ECS (bevy_ecs 0.18.1),
with standard macro benchmarks from rust-gamedev/ecs_bench_suite.
| ID | Test Function | Specification & Verification Target | Oracle | SoA Baseline | StateFabric | Bevy ECS | Hecs |
|---|---|---|---|---|---|---|---|
| Suite 1: Entity & Lifecycle (10 Tests) | |||||||
| TC-01 | test_entity_new_id | Spawn multiple entities and ensure IDs are unique and non-zero | ✅ 216μs | ✅ 20μs | ✅ 84μs | ✅ 30μs | ✅ 29μs |
| TC-02 | test_entity_is_alive | Verify entity is_alive status before and after despawn | ✅ 3μs | ✅ 1μs | ✅ 11μs | ✅ 2μs | ✅ 2μs |
| TC-03 | test_entity_recycle_id | Despawn entity and verify new spawns maintain validity and uniqueness | ✅ 0μs | ✅ 0μs | ✅ 8μs | ✅ 0μs | ✅ 0μs |
| TC-04 | test_entity_batch_spawn | Batch spawn 1,000 entities and verify entity count | ✅ 246μs | ✅ 58μs | ✅ 233μs | ✅ 193μs | ✅ 186μs |
| TC-05 | test_entity_clear_world | Spawn entities, attach components, clear world and verify all reset | ✅ 59μs | ✅ 5μs | ✅ 158μs | ✅ 27μs | ✅ 19μs |
| TC-06 | test_entity_name_lookup | Attach Name component and reverse lookup entity by name ID | ✅ 0μs | ✅ 1μs | ✅ 7μs | ✅ 1μs | ✅ 0μs |
| TC-07 | test_entity_parent_child | Set parent-child hierarchy relationship and read back | ✅ 0μs | ✅ 0μs | ✅ 7μs | ✅ 2μs | ✅ 0μs |
| TC-08 | test_entity_double_despawn | Attempting to despawn an already despawned entity should safely return Err | ✅ 1μs | ✅ 0μs | ✅ 7μs | ✅ 1μs | ✅ 0μs |
| TC-09 | test_entity_invalid_id_lookup | Querying non-existent entity ID returns is_alive == false | ✅ 0μs | ✅ 0μs | ✅ 6μs | ✅ 0μs | ✅ 0μs |
| TC-10 | test_entity_count_by_filter | Verify world length accurately tracks active entities after interleaved despawns | ✅ 47μs | ✅ 3μs | ✅ 19μs | ✅ 9μs | ✅ 7μs |
| Suite 2: Component Mutation & Archetypes (10 Tests) | |||||||
| TC-11 | test_component_add_single | Attach single component and verify get and has | ✅ 1μs | ✅ 0μs | ✅ 11μs | ✅ 1μs | ✅ 0μs |
| TC-12 | test_component_add_multiple | Attach Position, Velocity, Mass, Rotation and verify all coexist | ✅ 1μs | ✅ 0μs | ✅ 22μs | ✅ 10μs | ✅ 4μs |
| TC-13 | test_component_remove_single | Remove one component from entity and verify other remains intact | ✅ 1μs | ✅ 0μs | ✅ 21μs | ✅ 2μs | ✅ 1μs |
| TC-14 | test_component_overwrite_value | Overwrite component value in-place and verify latest value | ✅ 0μs | ✅ 0μs | ✅ 15μs | ✅ 1μs | ✅ 0μs |
| TC-15 | test_archetype_migration_swap_remove | Dynamic component addition forces archetype transition and preserves entity mapping | ✅ 1μs | ✅ 0μs | ✅ 16μs | ✅ 2μs | ✅ 1μs |
| TC-16 | test_component_has_check | Verify has_component returns false for unattached components | ✅ 0μs | ✅ 0μs | ✅ 7μs | ✅ 0μs | ✅ 0μs |
| TC-17 | test_component_get_mut_borrow | Update position and velocity via simulation step and assert updated values | ✅ 0μs | ✅ 0μs | ✅ 14μs | ✅ 2μs | ✅ 0μs |
| TC-18 | test_component_drop_cleanup | Despawning entity cleans up attached component states | ✅ 0μs | ✅ 0μs | ✅ 11μs | ✅ 1μs | ✅ 0μs |
| TC-19 | test_component_tag_zero_sized | Attach Zero-Sized Type (ZST) tags and verify tag query flags | ✅ 0μs | ✅ 0μs | ✅ 13μs | ✅ 5μs | ✅ 2μs |
| TC-20 | test_component_26_fragmentation | Create 26 entities across 26 distinct archetype tags (A..Z) | ✅ 13μs | ✅ 5μs | ✅ 147μs | ✅ 58μs | ✅ 27μs |
| Suite 3: Query & Filtering (10 Tests) | |||||||
| TC-21 | test_query_single_component_iter | Iterate single component across 100 entities and assert sum | ✅ 43μs | ✅ 6μs | ✅ 217μs | ✅ 36μs | ✅ 25μs |
| TC-22 | test_query_multi_component_join | Join query matching entities carrying both Position and Velocity | ✅ 48μs | ✅ 7μs | ✅ 313μs | ✅ 40μs | ✅ 29μs |
| TC-23 | test_query_with_tag_filter | Filter scan matching entities with specified Tag | ✅ 73μs | ✅ 7μs | ✅ 284μs | ✅ 33μs | ✅ 29μs |
| TC-24 | test_query_without_tag_filter | Filter scan excluding entities with specified Tag | ✅ 47μs | ✅ 7μs | ✅ 258μs | ✅ 31μs | ✅ 36μs |
| TC-25 | test_query_empty_result | Query on non-existent component or empty world returns 0 with no panics | ✅ 3μs | ✅ 0μs | ✅ 9μs | ✅ 0μs | ✅ 2μs |
| TC-26 | test_query_mut_disjoint | Disjoint mutation of position and velocity across 500 entities | ✅ 345μs | ✅ 33μs | ✅ 2039μs | ✅ 228μs | ✅ 224μs |
| TC-27 | test_query_sparse_vs_dense | Filter 100 tagged entities out of 1,000 total entities | ✅ 663μs | ✅ 52μs | ✅ 2196μs | ✅ 316μs | ✅ 311μs |
| TC-28 | test_query_entities_id_read | Assert query preserves entity identifier tracking | ✅ 48μs | ✅ 3μs | ✅ 55μs | ✅ 10μs | ✅ 12μs |
| TC-29 | test_query_early_break | Assert point queries and counts match after partial operations | ✅ 16μs | ✅ 2μs | ✅ 102μs | ✅ 12μs | ✅ 11μs |
| TC-30 | test_query_26_frag_scan | Scan across 26 fragmented archetype tables and calculate total coordinate sum | ✅ 191μs | ✅ 15μs | ✅ 1101μs | ✅ 131μs | ✅ 122μs |
| Suite 4: Defer & Command Buffer (10 Tests) | |||||||
| TC-31 | test_defer_spawn_in_query | Deferred spawn of new entities during iteration buffer, executed at flush | ✅ 17μs | ✅ 3μs | ✅ 26μs | ✅ 3μs | ✅ 3μs |
| TC-32 | test_defer_despawn_in_query | Deferred despawn recorded in buffer, executed cleanly at flush | ✅ 2μs | ✅ 0μs | ✅ 8μs | ✅ 1μs | ✅ 1μs |
| TC-33 | test_defer_add_component_in_query | Deferred addition of component to existing entity during flush | ✅ 0μs | ✅ 0μs | ✅ 9μs | ✅ 0μs | ✅ 0μs |
| TC-34 | test_defer_remove_component_in_query | Deferred removal of tag from entity during flush | ✅ 0μs | ✅ 0μs | ✅ 13μs | ✅ 3μs | ✅ 1μs |
| TC-35 | test_defer_batch_flush_order | Sequential execution preserves FIFO command order | ✅ 1μs | ✅ 0μs | ✅ 10μs | ✅ 1μs | ✅ 1μs |
| TC-36 | test_defer_nested_scopes | Multiple sequential batches executed successively | ✅ 0μs | ✅ 0μs | ✅ 12μs | ✅ 1μs | ✅ 0μs |
| TC-37 | test_defer_empty_flush | Flushing empty command batch is a safe no-op | ✅ 0μs | ✅ 0μs | ✅ 7μs | ✅ 0μs | ✅ 0μs |
| TC-38 | test_defer_abort_discard | Dropping unexecuted commands leaves world intact | ✅ 0μs | ✅ 0μs | ✅ 9μs | ✅ 0μs | ✅ 0μs |
| TC-39 | test_defer_component_update_merge | Multiple component modifications in single batch resolve to latest state | ✅ 0μs | ✅ 0μs | ✅ 12μs | ✅ 1μs | ✅ 1μs |
| TC-40 | test_defer_multiple_systems_flush | Simulate multiple systems appending commands and flushing together | ✅ 1μs | ✅ 0μs | ✅ 16μs | ✅ 1μs | ✅ 1μs |
| Suite 5: Entity Relationships & Pairs (10 Tests) | |||||||
| TC-41 | test_relation_add_target | Attach (ChildOf, Parent) relation pair and retrieve target | ✅ 38μs | ✅ 0μs | ✅ 1μs | ✅ 1μs | ✅ 0μs |
| TC-42 | test_relation_query_by_target | Reverse query entities matching specific relation and target | ✅ 11μs | ✅ 0μs | ✅ 1μs | ✅ 1μs | ✅ 1μs |
| TC-43 | test_relation_remove_pair | Remove specific relationship pair while preserving attached components | ✅ 19μs | ✅ 0μs | ✅ 3μs | ✅ 1μs | ✅ 0μs |
| TC-44 | test_relation_cascade_despawn | Despawn target entity cleans relation reference or marks target dead | ✅ 1μs | ✅ 0μs | ✅ 1μs | ✅ 1μs | ✅ 0μs |
| TC-45 | test_relation_multi_parent | Single entity carries multiple disjoint relation kinds concurrently | ✅ 0μs | ✅ 0μs | ✅ 0μs | ✅ 0μs | ✅ 0μs |
| TC-46 | test_relation_target_invalid_id | Attempting to link non-existent target is rejected safely | ✅ 0μs | ✅ 0μs | ✅ 0μs | ✅ 0μs | ✅ 0μs |
| TC-47 | test_relation_cycle_detection | Self-referencing relationship is rejected or handled safely | ✅ 0μs | ✅ 0μs | ✅ 0μs | ✅ 0μs | ✅ 0μs |
| TC-48 | test_relation_archetype_transition | Adding relationship maintains existing component data integrity | ✅ 0μs | ✅ 0μs | ✅ 5μs | ✅ 1μs | ✅ 0μs |
| TC-49 | test_relation_hierarchy_depth_scan | 3-level ancestor tree (Root -> Mid -> Leaf) chain intact | ✅ 0μs | ✅ 0μs | ✅ 1μs | ✅ 0μs | ✅ 0μs |
| TC-50 | test_relation_wildcard_query | Query all entities having DependsOn relationship targeting specific entity | ✅ 1μs | ✅ 0μs | ✅ 1μs | ✅ 0μs | ✅ 0μs |
| Suite 6: Change Detection & Epochs (10 Tests) | |||||||
| TC-51 | test_change_detect_newly_spawned | Newly spawned entity with component has is_pos_added == true | ✅ 0μs | ✅ 0μs | ✅ 2μs | ✅ 0μs | ✅ 0μs |
| TC-52 | test_change_detect_mutated | Mutating component marks is_pos_changed == true in current tick | ✅ 0μs | ✅ 0μs | ✅ 2μs | ✅ 0μs | ✅ 0μs |
| TC-53 | test_change_detect_read_only_unchanged | Read-only access does not trigger change flag | ✅ 0μs | ✅ 0μs | ✅ 3μs | ✅ 0μs | ✅ 0μs |
| TC-54 | test_change_detect_tick_advance | Advancing world tick resets change flags from previous tick | ✅ 0μs | ✅ 0μs | ✅ 3μs | ✅ 0μs | ✅ 0μs |
| TC-55 | test_change_detect_query_filter | query_changed_pos() strictly filters entities modified in current tick | ✅ 1μs | ✅ 0μs | ✅ 6μs | ✅ 1μs | ✅ 0μs |
| TC-56 | test_change_detect_in_place_identical | In-place set_pos marks changed according to mutation intent | ✅ 0μs | ✅ 0μs | ✅ 2μs | ✅ 0μs | ✅ 0μs |
| TC-57 | test_change_detect_despawn_clear | Despawned entity is pruned from active changed entities list | ✅ 1μs | ✅ 0μs | ✅ 3μs | ✅ 1μs | ✅ 0μs |
| TC-58 | test_change_detect_deferred_mutation | Deferred commands execution correctly sets change detection flag | ✅ 0μs | ✅ 0μs | ✅ 2μs | ✅ 0μs | ✅ 0μs |
| TC-59 | test_change_detect_multi_component_partial | Partial mutation modifies only the targeted component's change state | ✅ 0μs | ✅ 0μs | ✅ 5μs | ✅ 0μs | ✅ 0μs |
| TC-60 | test_change_detect_epoch_counter | World current_tick counter advances strictly and monotonically | ✅ 0μs | ✅ 0μs | ✅ 0μs | ✅ 0μs | ✅ 0μs |
| Suite 7: Parallel Query & Disjoint Access (10 Tests) | |||||||
| TC-61 | test_parallel_readonly_pos_vel | Parallel query pos sum aligns with serial query sum | ✅ 47μs | ✅ 6μs | ✅ 382μs | ✅ 38μs | ✅ 42μs |
| TC-62 | test_parallel_disjoint_components | Disjoint mutation across distinct component columns maintains mutual integrity | ✅ 1μs | ✅ 0μs | ✅ 7μs | ✅ 3μs | ✅ 2μs |
| TC-63 | test_parallel_same_component_conflict | Conflicting component writes resolve deterministically | ✅ 0μs | ✅ 0μs | ✅ 3μs | ✅ 1μs | ✅ 0μs |
| TC-64 | test_parallel_rayon_chunk_split | Parallel chunked stepping across 1,000 entities matches expected sum | ✅ 650μs | ✅ 70μs | ✅ 3854μs | ✅ 395μs | ✅ 389μs |
| TC-65 | test_parallel_defer_command_channel | Aggregated deferred commands batch executes safely and updates world length | ✅ 20μs | ✅ 1542μs | ✅ 100μs | ✅ 14μs | ✅ 15μs |
| TC-66 | test_parallel_archetype_table_parallel | Parallel query across 26 fragmented archetype tables yields 260.0 | ✅ 136μs | ✅ 14μs | ✅ 1060μs | ✅ 102μs | ✅ 104μs |
| TC-67 | test_parallel_world_borrow_exclusive | Exclusive clear operation reliably resets all tables to empty state | ✅ 3μs | ✅ 0μs | ✅ 27μs | ✅ 3μs | ✅ 3μs |
| TC-68 | test_parallel_atomic_digest_compute | Deterministic digest computation is repeatable and matches entity count | ✅ 26μs | ✅ 3μs | ✅ 126μs | ✅ 19μs | ✅ 18μs |
| TC-69 | test_parallel_worker_thread_pool | Rayon scope execution operates normally in current runtime environment | ✅ 342μs | ✅ 24μs | ✅ 20μs | ✅ 30μs | ✅ 21μs |
| TC-70 | test_parallel_starvation_free | 50 interleaved read-write cycles complete without hangs or starvation | ✅ 3μs | ✅ 2μs | ✅ 23μs | ✅ 11μs | ✅ 10μs |
| Suite 8: Binary Serialization & Snapshot (10 Tests) | |||||||
| TC-71 | test_serde_full_world_binary | Full world serializes to binary and restores into homogeneous world | ✅ 179μs | ✅ 29μs | ✅ 453μs | ✅ 112μs | ✅ 70μs |
| TC-72 | test_serde_digest_equality | Digest hash matches byte-for-byte before and after roundtrip serde | ✅ 26μs | ✅ 10μs | ✅ 137μs | ✅ 36μs | ✅ 24μs |
| TC-73 | test_serde_sparse_archetypes | Sparse archetype distributions across 26 tags roundtrip without data loss | ✅ 45μs | ✅ 11μs | ✅ 291μs | ✅ 136μs | ✅ 56μs |
| TC-74 | test_serde_entity_id_preservation | Entity 64-bit ID index and generation are strictly preserved upon restore | ✅ 3μs | ✅ 1μs | ✅ 26μs | ✅ 9μs | ✅ 4μs |
| TC-75 | test_serde_relations_tree_preservation | Relationship pairs and topology tree structure remain intact after restore | ✅ 6μs | ✅ 2μs | ✅ 20μs | ✅ 6μs | ✅ 2μs |
| TC-76 | test_serde_empty_world | Empty world binary serialization roundtrip succeeds with length 0 | ✅ 0μs | ✅ 0μs | ✅ 12μs | ✅ 2μs | ✅ 0μs |
| TC-77 | test_serde_corrupted_buffer_defense | Corrupted or truncated buffer returns safe error instead of panicking | ✅ 35μs | ✅ 1μs | ✅ 0μs | ✅ 0μs | ✅ 0μs |
| TC-78 | test_serde_schema_compatibility | Snapshot model export preserves schema structure consistently | ✅ 0μs | ✅ 0μs | ✅ 0μs | ✅ 0μs | ✅ 0μs |
| TC-79 | test_serde_zero_copy_archive | Snapshot can be archived via rkyv binary serializer | ✅ 1μs | ✅ 0μs | ✅ 0μs | ✅ 6μs | ✅ 0μs |
| TC-80 | test_serde_partial_world_snapshot | Snapshot data struct correctly captures entity attributes and components | ✅ 1μs | ✅ 0μs | ✅ 3μs | ✅ 1μs | ✅ 0μs |