diff --git a/Cargo.lock b/Cargo.lock index 5f37820be..892d0f863 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2393,6 +2393,7 @@ dependencies = [ "criterion", "de_core", "de_objects", + "de_test_utils", "de_types", "glam", "nalgebra", @@ -2673,6 +2674,13 @@ dependencies = [ "parry3d", ] +[[package]] +name = "de_test_utils" +version = "0.1.0-dev" +dependencies = [ + "glam", +] + [[package]] name = "de_tools" version = "0.1.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 515a654e5..9f7123e13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -106,6 +106,7 @@ de_pathing = { path = "crates/pathing", version = "0.1.0-dev" } de_signs = { path = "crates/signs", version = "0.1.0-dev" } de_spawner = { path = "crates/spawner", version = "0.1.0-dev" } de_terrain = { path = "crates/terrain", version = "0.1.0-dev" } +de_test_utils = { path = "crates/test_utils", version = "0.1.0-dev" } de_types = { path = "crates/types", version = "0.1.0-dev" } de_uom = { path = "crates/uom", version = "0.1.0-dev" } diff --git a/crates/index/Cargo.toml b/crates/index/Cargo.toml index cad6d474b..3a88041fd 100644 --- a/crates/index/Cargo.toml +++ b/crates/index/Cargo.toml @@ -26,6 +26,10 @@ ahash.workspace = true nalgebra.workspace = true [dev-dependencies] +# DE +de_test_utils.workspace = true + +# Other criterion.workspace = true [[bench]] diff --git a/crates/index/benches/ray.rs b/crates/index/benches/ray.rs index 6b5e97c97..5c165b4fa 100644 --- a/crates/index/benches/ray.rs +++ b/crates/index/benches/ray.rs @@ -1,9 +1,3 @@ -use std::{ - fs::File, - io::{BufRead, BufReader}, - path::PathBuf, -}; - use bevy::prelude::*; use criterion::{ criterion_group, criterion_main, AxisScale, BenchmarkId, Criterion, PlotConfiguration, @@ -11,6 +5,7 @@ use criterion::{ }; use de_index::{EntityIndex, LocalCollider, SpatialQuery}; use de_objects::ObjectCollider; +use de_test_utils::{load_points, NumPoints}; use glam::Vec2; use parry3d::{ math::{Isometry, Point, Vector}, @@ -57,25 +52,8 @@ impl Iterator for Rays { } } -fn load_points(number: u32) -> Vec { - let mut points_path: PathBuf = env!("CARGO_MANIFEST_DIR").into(); - points_path.push("test_data"); - points_path.push(format!("{number}-points.txt")); - let reader = BufReader::new(File::open(points_path).unwrap()); - - let mut points = Vec::with_capacity(number as usize); - for line in reader.lines() { - let line = line.unwrap(); - let mut numbers = line.split_whitespace(); - let x: f32 = numbers.next().unwrap().parse().unwrap(); - let y: f32 = numbers.next().unwrap().parse().unwrap(); - points.push(MAP_SIZE * Vec2::new(x, y)); - } - points -} - fn setup_world(world: &mut World, num_entities: u32, max_distance: f32) { - let points = load_points(num_entities); + let points = load_points(&num_entities.try_into().unwrap(), MAP_SIZE); let mut index = EntityIndex::new(); for (i, point) in points.iter().enumerate() { @@ -87,8 +65,8 @@ fn setup_world(world: &mut World, num_entities: u32, max_distance: f32) { } let mut rays = Rays::new(); - let ray_origins = load_points(1000); - let ray_dirs = load_points(1000); + let ray_origins = load_points(&NumPoints::OneThousand, MAP_SIZE); + let ray_dirs = load_points(&NumPoints::OneThousand, MAP_SIZE); for (origin, dir) in ray_origins.iter().zip(ray_dirs.iter()) { let dir = if dir.length() < 0.0001 { Vec2::new(1., 0.) diff --git a/crates/test_utils/Cargo.toml b/crates/test_utils/Cargo.toml new file mode 100644 index 000000000..545e42885 --- /dev/null +++ b/crates/test_utils/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "de_test_utils" +description = "Test utilities for Digital Extinction" + +version.workspace = true +edition.workspace = true +authors.workspace = true +repository.workspace = true +keywords.workspace = true +homepage.workspace = true +license.workspace = true +categories.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +glam.workspace = true diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs new file mode 100644 index 000000000..3a265d8d5 --- /dev/null +++ b/crates/test_utils/src/lib.rs @@ -0,0 +1,84 @@ +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::PathBuf; + +use glam::Vec2; + +/// An enum to allow for safe selection of the number of points to load from the test data. +#[derive(Copy, Clone, Debug)] +pub enum NumPoints { + OneHundred, + OneThousand, + TenThousand, + OneHundredThousand, +} + +impl TryFrom for NumPoints { + type Error = &'static str; + + fn try_from(value: u32) -> Result { + match value { + 100 => Ok(Self::OneHundred), + 1000 => Ok(Self::OneThousand), + 10_000 => Ok(Self::TenThousand), + 100_000 => Ok(Self::OneHundredThousand), + _ => Err("Invalid number of points"), + } + } +} + +impl From<&NumPoints> for usize { + fn from(value: &NumPoints) -> Self { + match value { + NumPoints::OneHundred => 100, + NumPoints::OneThousand => 1000, + NumPoints::TenThousand => 10_000, + NumPoints::OneHundredThousand => 100_000, + } + } +} + +impl From for usize { + fn from(value: NumPoints) -> Self { + Self::from(&value) + } +} + +/// Load deterministic points for testing. +/// +/// # Arguments +/// * `number` - the selected number of points from the [NumPoints] enum. +/// * `max_value` - the max and min value for the returned point, the numbers returned will be +/// between -max_value and +max_value. +/// +/// # Returns +/// A list of Vec2 points with x and y between -max_value and +max_value. This is guaranteed to be +/// deterministic across calls with the same input. +pub fn load_points(number: &NumPoints, max_value: f32) -> Vec { + let number: usize = number.into(); + + let mut points_path: PathBuf = env!("CARGO_MANIFEST_DIR").into(); + points_path.push("test_data"); + points_path.push(format!("{number}-points.txt")); + let reader = BufReader::new(File::open(points_path).unwrap()); + + let mut points = Vec::with_capacity(number); + for line in reader.lines() { + let line = line.unwrap(); + let mut numbers = line.split_whitespace(); + let x: f32 = numbers.next().unwrap().parse().unwrap(); + + assert!(x.is_finite()); + assert!(x >= 0.); + assert!(x <= 1.); + + let y: f32 = numbers.next().unwrap().parse().unwrap(); + + assert!(y.is_finite()); + assert!(y >= 0.); + assert!(y <= 1.); + + points.push(max_value * 2. * (Vec2::new(x, y) - 0.5)); + } + points +} diff --git a/crates/index/test_data/.gitattributes b/crates/test_utils/test_data/.gitattributes similarity index 100% rename from crates/index/test_data/.gitattributes rename to crates/test_utils/test_data/.gitattributes diff --git a/crates/index/test_data/100-points.txt b/crates/test_utils/test_data/100-points.txt similarity index 100% rename from crates/index/test_data/100-points.txt rename to crates/test_utils/test_data/100-points.txt diff --git a/crates/index/test_data/1000-points.txt b/crates/test_utils/test_data/1000-points.txt similarity index 100% rename from crates/index/test_data/1000-points.txt rename to crates/test_utils/test_data/1000-points.txt diff --git a/crates/index/test_data/10000-points.txt b/crates/test_utils/test_data/10000-points.txt similarity index 100% rename from crates/index/test_data/10000-points.txt rename to crates/test_utils/test_data/10000-points.txt diff --git a/crates/index/test_data/100000-points.txt b/crates/test_utils/test_data/100000-points.txt similarity index 100% rename from crates/index/test_data/100000-points.txt rename to crates/test_utils/test_data/100000-points.txt