Skip to content

Commit

Permalink
add snapshot testing to examples.
Browse files Browse the repository at this point in the history
  • Loading branch information
Indra-db committed Apr 13, 2024
1 parent 5efcb46 commit 8247431
Show file tree
Hide file tree
Showing 133 changed files with 1,354 additions and 258 deletions.
10 changes: 3 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,11 @@ jobs:
name: cargo fmt
steps:
- uses: actions/checkout@v4

- name: install stable toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
components: rustfmt

- name: cargo fmt
run: cargo fmt --all --check

Expand All @@ -40,26 +38,24 @@ jobs:
name: cargo clippy + test + build and run examples
steps:
- uses: actions/checkout@v4

- name: install stable toolchain
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
components: clippy

- name: cargo clippy
run: cargo clippy --all-targets --workspace -- -D warnings

- name: cargo test
run: cargo test --workspace

- name: Set execute permission on script
run: chmod +x ./scripts/run_examples.sh

- name: Build all examples
run: cargo build --examples

# CI env variable for insta snapshot testing library
- name: Run examples
env:
CI: true
run: ./scripts/run_examples.sh
shell: bash

Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ clippy.semicolon_if_nothing_returned = "warn"
lto = true
codegen-units = 1
panic = "abort"

[profile.dev.package]
insta.opt-level = 3
similar.opt-level = 3
1 change: 1 addition & 0 deletions flecs_ecs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ criterion = "0.5.1"
seq-macro = "0.3.5"
rand = "0.8.5"
ctor = "0.2.7"
insta = { version = "1.38.0", features = ["yaml"] }

[features]
# Regenerate the C binding for flecs C
Expand Down
12 changes: 9 additions & 3 deletions flecs_ecs/examples/a_hello_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ mod common;
use common::*;

fn main() {
//ignore snap in example, it's for snapshot testing
let mut snap = Snap::setup_snapshot_test();

// Create a new world
let world = World::new();

Expand All @@ -22,7 +25,7 @@ fn main() {
.add::<(Eats, Apples)>();

// Show us what you got
println!("{}'s got [{:?}]", bob.name(), bob.archetype());
fprintln!(snap, "{}'s got [{:?}]", bob.name(), bob.archetype());

// Run systems twice. Usually this function is called once per frame
world.progress();
Expand All @@ -31,9 +34,12 @@ fn main() {
//you can use `.unwrap_unchecked()` if you are sure the component exists or `get_unchecked()`
let pos = bob.get::<Position>().unwrap();
// See if Bob has moved (he has)
println!("Bob's position: {:?}", pos);
//fprintln!(snap,"Bob's position: {:?}", pos);
fprintln!(snap, "{}'s position: {:?}", bob.name(), pos);

snap.test();

// Output
// Output:
// Bob's got [Position, Velocity, (Identifier,Name), (Eats,Apples)]
// Bob's position: Position { x: 2.0, y: 4.0 }
}
51 changes: 51 additions & 0 deletions flecs_ecs/examples/common.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#![allow(dead_code)]
#![allow(unused_imports)]

use std::ffi::c_void;

pub use flecs_ecs::{core::*, macros::Component};

#[derive(Debug, Component)]
Expand Down Expand Up @@ -82,3 +84,52 @@ pub struct Group;
fn main() {
//this file is for common structs and functions used in the examples
}

#[macro_export]
macro_rules! fprintln {
($str_vec:expr) => {
{
$str_vec.push(format!("\n"));
println!();
}
};
($str_vec:expr, $format_string:expr) => {
{
$str_vec.push(format!($format_string));
println!($format_string);
}
};
($str_vec:expr, $format_string:expr, $($arg:expr),*) => {
{
$str_vec.push(format!($format_string, $($arg),*));
println!($format_string, $($arg),*);
}
};
}

pub struct Snap {
pub str: Vec<String>,
}

impl Snap {
pub fn setup_snapshot_test() -> Snap {
Snap { str: Vec::new() }
}

pub fn cvoid(&self) -> *mut c_void {
self as *const Snap as *mut c_void
}

pub fn push(&mut self, str: String) {
self.str.push(str);
}

#[allow(clippy::mut_from_ref)]
pub fn from<'a>(it: &'a flecs_ecs::core::Iter) -> &'a mut Snap {
unsafe { it.context::<Snap>() }
}

pub fn test(&self) {
insta::assert_yaml_snapshot!(self.str);
}
}
13 changes: 9 additions & 4 deletions flecs_ecs/examples/entity_basics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ mod common;
use common::*;

fn main() {
//ignore snap in example, it's for snapshot testing
let mut snap = Snap::setup_snapshot_test();

let world = World::new();

// Create an entity with name Bob
Expand All @@ -16,7 +19,7 @@ fn main() {

// Get the value for the Position component
let pos = bob.get::<Position>().unwrap();
println!("Bob's position: {:?}", pos);
fprintln!(snap, "Bob's position: {:?}", pos);

// Overwrite the value of the Position component
bob.set(Position { x: 20.0, y: 30.0 });
Expand All @@ -31,17 +34,19 @@ fn main() {

// Print all of the components the entity has. This will output:
// Position, Walking, (Identifier,Name)
println!("[{}]", alice.archetype());
fprintln!(snap, "[{}]", alice.archetype());

// Remove tag
alice.remove::<Walking>();

// Iterate all entities with position
world.each_entity::<&Position>(|entity, pos| {
println!("{} has {:?}", entity.name(), pos);
fprintln!(snap, "{} has {:?}", entity.name(), pos);
});

// Output
snap.test();

// Output:
// Bob's position: Position { x: 10.0, y: 20.0 }
// [Position, Walking, (Identifier,Name)]
// Alice has Position { x: 10.0, y: 20.0 }
Expand Down
27 changes: 19 additions & 8 deletions flecs_ecs/examples/entity_hierarchy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ struct Planet;
#[derive(Debug, Component)]
struct Moon;

fn iterate_tree(entity: EntityView, position_parent: &Position) {
fn iterate_tree(entity: EntityView, position_parent: &Position, snap: &mut Snap) {
// Print hierarchical name of entity & the entity type
println!("{} [{:?}]", entity.path().unwrap(), entity.archetype());
fprintln!(
snap,
"{} [{:?}]",
entity.path().unwrap(),
entity.archetype()
);

// Get the position of the entity
let pos = entity.get::<Position>().unwrap();
Expand All @@ -24,14 +29,17 @@ fn iterate_tree(entity: EntityView, position_parent: &Position) {
};

// Print the position
println!("{:?}", pos_actual);
fprintln!(snap, "{:?}", pos_actual);

entity.for_each_child_of(|child| {
iterate_tree(child, &pos_actual);
iterate_tree(child, &pos_actual, snap);
});
}

fn main() {
//ignore snap in example, it's for snapshot testing
let mut snap = Snap::setup_snapshot_test();

let world = World::new();

// Create a simple hierarchy.
Expand Down Expand Up @@ -67,18 +75,21 @@ fn main() {
.child_of_id(earth);

// Is the Moon a child of the Earth?
println!(
fprintln!(
snap,
"Is the Moon a child of the Earth? {} / {}",
moon.has_id((flecs::ChildOf::ID, earth)), //or you can do
moon.has_pair_first::<flecs::ChildOf>(earth)
);

println!();
fprintln!(snap);

// Do a depth-first traversal of the tree
iterate_tree(sun, &Position { x: 0.0, y: 0.0 });
iterate_tree(sun, &Position { x: 0.0, y: 0.0 }, &mut snap);

snap.test();

// Output
// Output:
// Is the Moon a child of the Earth? true / true
// ::Sun [Position, (Identifier,Name)]
// Position { x: 1.0, y: 1.0 }
Expand Down
22 changes: 17 additions & 5 deletions flecs_ecs/examples/entity_hooks.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
mod common;
use std::sync::{Arc, Mutex};

use common::*;

fn main() {
let snap = Arc::new(Mutex::new(Snap::setup_snapshot_test()));
let snap_clone_add = Arc::clone(&snap);
let snap_clone_remove = Arc::clone(&snap);
let snap_clone_set = Arc::clone(&snap);

let world = World::new();

world
.component::<Position>()
.on_add(|entity, pos| {
println!("added {:?} to {:?}", pos, entity.name());
.on_add(|entity, _pos| {
let mut snap = snap_clone_add.lock().unwrap();
fprintln!(snap, "added Position to {:?}", entity.name());
})
.on_remove(|entity, pos| {
println!("removed {:?} from {:?}", pos, entity.name());
let mut snap = snap_clone_remove.lock().unwrap();
fprintln!(snap, "removed {:?} from {:?}", pos, entity.name());
})
.on_set(|entity, pos| {
println!("set {:?} for {:?}", pos, entity.name());
let mut snap = snap_clone_set.lock().unwrap();
fprintln!(snap, "set {:?} for {:?}", pos, entity.name());
});

let entity = world.new_entity_named(c"Bob");
Expand All @@ -27,7 +37,9 @@ fn main() {

entity.destruct();

// Output
snap.lock().unwrap().test();

// Output:
// added Position { x: 0.0, y: 0.0 } to "Bob"
// set Position { x: 10.0, y: 20.0 } for "Bob"
// removed Position { x: 10.0, y: 20.0 } from "Bob"
Expand Down
44 changes: 28 additions & 16 deletions flecs_ecs/examples/entity_iterate_components.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,52 @@
mod common;
use common::*;

fn iterate_components(entity: EntityView) {
fn iterate_components(entity: EntityView, snap: &mut Snap) {
// 1. The easiest way to print the components is to use archetype
println!("[{:?}]", entity.archetype());
println!();
fprintln!(snap, "[{:?}]", entity.archetype());
fprintln!(snap);
// 2. To get individual component ids, use for_each
let mut count_components = 0;
entity.for_each_component(|id| {
println!("{}: {}", count_components, id.to_str());
fprintln!(snap, "{}: {}", count_components, id.to_str());
count_components += 1;
});
println!();
fprintln!(snap);

// 3. we can also inspect and print the ids in our own way. This is a
// bit more complicated as we need to handle the edge cases of what can be
// encoded in an id, but provides the most flexibility.
count_components = 0;

entity.for_each_component(|id| {
print!("{}: ", count_components);
snap.str
.last_mut()
.unwrap()
.push_str(format!("{}: ", count_components).as_str());

count_components += 1;
if id.is_pair() {
// If id is a pair, extract & print both parts of the pair
let rel = id.first();
let target = id.second();
print!("rel: {}, target: {}", rel.name(), target.name());
snap.str
.last_mut()
.unwrap()
.push_str(format!("rel: {}, target: {}", rel.name(), target.name()).as_str());
} else {
// Id contains a regular entity. Strip role before printing.
let comp = id.entity_view();
print!("entity: {}", comp.name());
snap.str
.last_mut()
.unwrap()
.push_str(format!("entity: {}", comp.name()).as_str());
}

println!();
println!();
});
}
fn main() {
//ignore snap in example, it's for snapshot testing
let mut snap = Snap::setup_snapshot_test();

let world = World::new();

let bob = world
Expand All @@ -46,14 +56,16 @@ fn main() {
.add::<Human>()
.add::<(Eats, Apples)>();

println!("Bob's components:");
iterate_components(bob);
fprintln!(snap, "Bob's components:");
iterate_components(bob, &mut snap);

// We can use the same function to iterate the components of a component
println!("Position's components:");
iterate_components(world.component::<Position>().entity());
fprintln!(snap, "Position's components:");
iterate_components(world.component::<Position>().entity(), &mut snap);

snap.test();

// Output
// Output:
// Bob's components:
// [Position, Velocity, Human, (Identifier,Name), (Eats,Apples)]
//
Expand Down
Loading

0 comments on commit 8247431

Please sign in to comment.