Added some tests to dynatos_reactive::{effect, trigger}.

This commit is contained in:
2024-02-21 12:37:09 +00:00
parent b7ef16e391
commit 43bc3cb029
2 changed files with 116 additions and 0 deletions

View File

@@ -195,3 +195,79 @@ impl fmt::Debug for WeakEffect {
f.debug_struct("WeakEffect").finish_non_exhaustive()
}
}
#[cfg(test)]
mod test {
// Imports
use {super::*, std::cell::OnceCell};
/// Leaks a value and returns a `&'static T`
///
/// This is useful because `&'static T` is `Copy`,
/// so we don't need to worry about cloning `Rc`s to
/// pass variables to effects.
fn leaked<T>(value: T) -> &'static T {
Box::leak(Box::new(value))
}
/// Ensures the function returned by `Effect::running` is the same as the future being run.
#[test]
fn running() {
// Create an effect, and save the running effect within it to `running`.
let running = self::leaked(OnceCell::new());
let effect = Effect::new(move || {
running
.set(Effect::running().expect("Future wasn't running"))
.expect("Unable to set running effect");
});
// Then ensure the running effect is the same as the one created.
let running = running
.get()
.expect("Running effect missing")
.upgrade()
.expect("Running effect was dropped");
assert_eq!(effect, running);
}
/// Ensures the function returned by `Effect::running` is the same as the future being run,
/// while running stacked futures
#[test]
fn running_stacked() {
// Create 2 stacked effects, saving the running within each to `running1` and `running2`.
// `running1` contains the top-level effect, while `running2` contains the inner one.
let running_top = self::leaked(OnceCell::new());
let running_bottom = self::leaked(OnceCell::new());
let effect = Effect::new(move || {
running_top
.set(Effect::running().expect("Future wasn't running"))
.expect("Unable to set running effect");
let effect = Effect::new(move || {
running_bottom
.set(Effect::running().expect("Future wasn't running"))
.expect("Unable to set running effect");
});
// Then ensure the bottom-level running effect is the same as the one created.
let running_bottom = running_bottom
.get()
.expect("Running effect missing")
.upgrade()
.expect("Running effect was dropped");
assert_eq!(effect, running_bottom);
});
// Then ensure the top-level running effect is the same as the one created.
let running_top = running_top
.get()
.expect("Running effect missing")
.upgrade()
.expect("Running effect was dropped");
assert_eq!(effect, running_top);
// And that the bottom-level running effect was already dropped
let running_bottom = running_bottom.get().expect("Running effect missing").upgrade();
assert_eq!(running_bottom, None);
}
}

View File

@@ -106,3 +106,43 @@ impl IntoSubscriber for T {
body
}
}
#[cfg(test)]
mod test {
// Imports
use {
super::*,
std::{cell::Cell, mem},
};
#[test]
fn basic() {
thread_local! {
/// Counts the number of times the effect was run
static TRIGGERS: Cell<usize> = const { Cell::new(0) };
}
// Create the effect and reset the flag
let effect = Effect::new(move || TRIGGERS.set(TRIGGERS.get() + 1));
// Then create the trigger, and ensure it wasn't triggered
// by just creating it and adding the subscriber
let trigger = Trigger::new();
trigger.add_subscriber(effect.downgrade());
assert_eq!(TRIGGERS.get(), 1, "Trigger was triggered early");
// Then trigger and ensure it was triggered
trigger.trigger();
assert_eq!(TRIGGERS.get(), 2, "Trigger was not triggered");
// Then add the subscriber again and ensure the effect isn't run twice
trigger.add_subscriber(effect.downgrade());
trigger.trigger();
assert_eq!(TRIGGERS.get(), 3, "Trigger ran effect multiple times");
// Finally drop the effect and try again
mem::drop(effect);
trigger.trigger();
assert_eq!(TRIGGERS.get(), 3, "Trigger was triggered after effect was dropped");
}
}