Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit test the bulk of the public API. #88

Merged
merged 31 commits into from
Aug 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9165158
Unit tests for Location.
Anders429 Aug 4, 2022
56cd857
Unit tests for Slot.
Anders429 Aug 4, 2022
5fd6dfc
Test hlist::define_null.
Anders429 Aug 16, 2022
2ef1f2c
Test archetype identifier serialization and deserialization.
Anders429 Aug 16, 2022
ff58d95
Merge branch 'master' into unit
Anders429 Aug 16, 2022
dc5faae
Test Archetype serde impls.
Anders429 Aug 17, 2022
3e0697a
Test serde impls for Archetypes.
Anders429 Aug 18, 2022
17a36c4
Formatting.
Anders429 Aug 18, 2022
c4e43e0
Fix undefined behavior related to component alignment.
Anders429 Aug 18, 2022
fdb419d
Formatting.
Anders429 Aug 18, 2022
b6abae4
Remove unnecessary mut.
Anders429 Aug 18, 2022
8d2e906
Test serde impls for entity::Allocator.
Anders429 Aug 19, 2022
1570041
Add safety coment.
Anders429 Aug 19, 2022
0a231e5
Test serde implementations for World.
Anders429 Aug 19, 2022
1930e18
Test entities.
Anders429 Aug 19, 2022
5a14518
Test entity.
Anders429 Aug 19, 2022
f99a986
Test claims.
Anders429 Aug 19, 2022
3ec47a7
Test World default implementation.
Anders429 Aug 19, 2022
dd1da82
Test world equality.
Anders429 Aug 19, 2022
128845d
Test entities length.
Anders429 Aug 19, 2022
1dd1b68
Test filter Seal trait.
Anders429 Aug 19, 2022
05d69b6
Test world insert, extend, and query methods.
Anders429 Aug 19, 2022
44aaae3
Test world parallel query.
Anders429 Aug 19, 2022
27355cf
Test world run_system method.
Anders429 Aug 19, 2022
1471380
Test world run_par_system method.
Anders429 Aug 19, 2022
a71002e
World test schedule
Anders429 Aug 19, 2022
56ea504
Formatting.
Anders429 Aug 19, 2022
d4ea02c
Test world contains method.
Anders429 Aug 19, 2022
a744240
Test world entry method.
Anders429 Aug 19, 2022
5680e23
Test remaining world container methods.
Anders429 Aug 19, 2022
b77db73
Test setting existing component with entry.
Anders429 Aug 19, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ serde = {version = "1.0.143", default-features = false, features = ["alloc"], op
[dev-dependencies]
claim = "0.5.0"
rustversion = "1.0.9"
serde_derive = "1.0.143"
serde_test = "1.0.143"
# Temporarily use this fork until https://github.com/dtolnay/trybuild/issues/171 is resolved.
trybuild = {git = "https://github.com/Anders429/trybuild"}
Expand Down
98 changes: 88 additions & 10 deletions src/archetype/identifier/impl_serde.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{archetype::Identifier, registry::Registry};
use alloc::vec::Vec;
use alloc::{format, vec::Vec};
use core::{fmt, marker::PhantomData, mem::ManuallyDrop};
use serde::{
de,
Expand Down Expand Up @@ -66,15 +66,17 @@ where
}

// Check that trailing bits are not set.
// SAFETY: `buffer` is guaranteed to have `(R::LEN + 7) / 8` elements, so this will
// always be within the bounds of `buffer.`
let byte = unsafe { buffer.get_unchecked((R::LEN + 7) / 8 - 1) };
let bit = R::LEN % 8;
if bit != 0 && byte & (255 << bit) != 0 {
return Err(de::Error::invalid_value(
Unexpected::Unsigned(u64::from(*byte)),
&self,
));
if R::LEN != 0 {
// SAFETY: `buffer` is guaranteed to have `(R::LEN + 7) / 8` elements, so this will
// always be within the bounds of `buffer.`
let byte = unsafe { buffer.get_unchecked((R::LEN + 7) / 8 - 1) };
let bit = R::LEN % 8;
if bit != 0 && byte & (255 << bit) != 0 {
return Err(de::Error::invalid_value(
Unexpected::Other(&format!("byte array {:?}", &buffer)),
&self,
));
}
}

let mut buffer = ManuallyDrop::new(buffer);
Expand All @@ -96,3 +98,79 @@ where
)
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::registry;
use alloc::vec;
use serde_test::{assert_de_tokens_error, assert_tokens, Token};

macro_rules! create_components {
($( $variants:ident ),*) => {
$(
struct $variants(f32);
)*
};
}

create_components!(
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
);

type Registry =
registry!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);

#[test]
fn serialize_deserialize() {
let identifier = unsafe { Identifier::<Registry>::new(vec![1, 2, 3, 0]) };

assert_tokens(
&identifier,
&[
Token::Tuple { len: 4 },
Token::U8(1),
Token::U8(2),
Token::U8(3),
Token::U8(0),
Token::TupleEnd,
],
);
}

#[test]
fn serialize_deserialize_empty() {
let identifier = unsafe { Identifier::<registry!()>::new(vec![]) };

assert_tokens(&identifier, &[Token::Tuple { len: 0 }, Token::TupleEnd]);
}

#[test]
fn deserialize_from_too_many_bits() {
assert_de_tokens_error::<Identifier<Registry>>(
&[
Token::Tuple { len: 4 },
Token::U8(1),
Token::U8(2),
Token::U8(3),
Token::U8(255),
Token::TupleEnd,
],
"invalid value: byte array [1, 2, 3, 255], expected 26 bits corresponding to components, with prefixed 0s padded on the last byte to round up to 4 bytes"
);
}

#[test]
fn deserialize_from_too_few_bytes() {
assert_de_tokens_error::<Identifier<Registry>>(
&[
Token::Tuple { len: 3 },
Token::U8(1),
Token::U8(2),
Token::U8(3),
Token::TupleEnd,
],
"invalid length 3, expected 26 bits corresponding to components, with prefixed 0s padded on the last byte to round up to 4 bytes"
);
}
}
38 changes: 38 additions & 0 deletions src/archetype/identifier/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,16 @@ where
unsafe { Iter::<R>::new(self.pointer) }
}

/// Returns the number of components identified by this identifier.
///
/// This is not a cheap operation. It is O(N), looping over the bits individually and counting
/// them.
#[must_use]
pub(crate) fn count(&self) -> usize {
// SAFETY: The identifier here will outlive the derived `Iter`.
unsafe { self.iter() }.filter(|b| *b).count()
}

/// Returns the size of the components within the canonical entity represented by this
/// identifier.
///
Expand Down Expand Up @@ -241,6 +251,17 @@ where
unsafe { Iter::<R>::new(self.pointer) }
}

/// Returns the number of components identified by this identifier.
///
/// This is not a cheap operation. It is O(N), looping over the bits individually and counting
/// them.
#[cfg(feature = "serde")]
#[must_use]
pub(crate) fn count(self) -> usize {
// SAFETY: The identifier here will outlive the derived `Iter`.
unsafe { self.iter() }.filter(|b| *b).count()
}

/// Returns a copy of the bytes defining this identifier.
pub(crate) fn as_vec(self) -> Vec<u8> {
// SAFETY: The reference created here will always live longer than the referenced
Expand Down Expand Up @@ -379,6 +400,14 @@ mod tests {
);
}

#[cfg(feature = "serde")]
#[test]
fn buffer_count() {
let buffer = unsafe { Identifier::<Registry>::new(vec![1, 2, 3, 0]) };

assert_eq!(buffer.count(), 4);
}

#[test]
fn buffer_size_of_components() {
let buffer = unsafe { Identifier::<registry!(bool, u64, f32)>::new(vec![7]) };
Expand Down Expand Up @@ -417,6 +446,15 @@ mod tests {
);
}

#[cfg(feature = "serde")]
#[test]
fn identifier_count() {
let buffer = unsafe { Identifier::<Registry>::new(vec![1, 2, 3, 0]) };
let identifier = unsafe { buffer.as_ref() };

assert_eq!(identifier.count(), 4);
}

#[test]
fn identifier_as_vec() {
let buffer = unsafe { Identifier::<Registry>::new(vec![1, 2, 3, 0]) };
Expand Down
Loading