Skip to content

Commit

Permalink
feat(s2n-quic-core): generate state reactions to events
Browse files Browse the repository at this point in the history
  • Loading branch information
camshaft committed May 23, 2024
1 parent f23d87b commit eb19e16
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 645 deletions.
85 changes: 85 additions & 0 deletions quic/s2n-quic-core/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,91 @@ macro_rules! __state_event__ {
);
)*

#[cfg(test)]
pub fn test_transitions() -> impl ::core::fmt::Debug {
use $crate::state::Result;
use ::core::fmt;

let mut all_states = [
// collect all of the states we've observed
$($(
$(
(stringify!($valid), Self::$valid),
)*
(stringify!($target), Self::$target),
)*)*
];

all_states.sort_unstable_by_key(|v| v.0);
let (sorted, _) = $crate::slice::partition_dedup(&mut all_states);

const EVENT_LEN: usize = {
let mut len = 0;
$({
let _ = stringify!($event);
len += 1;
})*
len
};

let apply = |state: &Self| {
[$(
(stringify!($event), state.clone().$event())
),*]
};

struct Transitions<const L: usize, T, A> {
states: [(&'static str, T); L],
count: usize,
apply: A,
}

impl<const L: usize, T, A> fmt::Debug for Transitions<L, T, A>
where
T: fmt::Debug,
A: Fn(&T) -> [(&'static str, Result<T>); EVENT_LEN],
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut m = f.debug_map();

for (name, state) in self.states.iter().take(self.count) {
let events = (self.apply)(state);
m.entry(name, &Entry(events));
}

m.finish()
}
}

struct Entry<T>([(&'static str, Result<T>); EVENT_LEN]);

impl<T> fmt::Debug for Entry<T>
where
T: fmt::Debug
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut m = f.debug_map();

for (event, outcome) in self.0.iter() {
if outcome.is_ok() {
m.entry(event, &format_args!("Ok"));
} else {
m.entry(event, outcome);
}
}

m.finish()
}
}

let count = sorted.len();
Transitions {
states: all_states,
count,
apply,
}
}

/// Generates a dot graph of all state transitions
pub fn dot() -> impl ::core::fmt::Display {
struct Dot;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,128 +1,74 @@
---
source: quic/s2n-quic-core/src/state/tests.rs
expression: outcomes
expression: "State::test_transitions()"
---
[
(
Init,
"on_left",
Ok(
Left,
),
),
(
Init,
"on_right",
Ok(
Right,
),
),
(
Left,
"on_left",
Ok(
LeftLeft,
),
),
(
Left,
"on_right",
Ok(
LeftRight,
),
),
(
Right,
"on_left",
Ok(
RightLeft,
),
),
(
Right,
"on_right",
Ok(
RightRight,
),
),
(
LeftLeft,
"on_left",
Err(
{
"Init": {
"on_left": Ok,
"on_right": Ok,
},
"Left": {
"on_left": Ok,
"on_right": Ok,
},
"LeftLeft": {
"on_left": Err(
InvalidTransition {
current: LeftLeft,
event: "on_left",
},
),
),
(
LeftLeft,
"on_right",
Err(
"on_right": Err(
InvalidTransition {
current: LeftLeft,
event: "on_right",
},
),
),
(
LeftRight,
"on_left",
Err(
},
"LeftRight": {
"on_left": Err(
InvalidTransition {
current: LeftRight,
event: "on_left",
},
),
),
(
LeftRight,
"on_right",
Err(
"on_right": Err(
InvalidTransition {
current: LeftRight,
event: "on_right",
},
),
),
(
RightLeft,
"on_left",
Err(
},
"Right": {
"on_left": Ok,
"on_right": Ok,
},
"RightLeft": {
"on_left": Err(
InvalidTransition {
current: RightLeft,
event: "on_left",
},
),
),
(
RightLeft,
"on_right",
Err(
"on_right": Err(
InvalidTransition {
current: RightLeft,
event: "on_right",
},
),
),
(
RightRight,
"on_left",
Err(
},
"RightRight": {
"on_left": Err(
InvalidTransition {
current: RightRight,
event: "on_left",
},
),
),
(
RightRight,
"on_right",
Err(
"on_right": Err(
InvalidTransition {
current: RightRight,
event: "on_right",
},
),
),
]
},
}
24 changes: 1 addition & 23 deletions quic/s2n-quic-core/src/state/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,7 @@ impl State {
#[test]
#[cfg_attr(miri, ignore)]
fn snapshots() {
let mut outcomes = vec![];
let states = [
State::Init,
State::Left,
State::Right,
State::LeftLeft,
State::LeftRight,
State::RightLeft,
State::RightRight,
];
for state in states {
macro_rules! push {
($event:ident) => {
let mut target = state.clone();
let result = target.$event().map(|_| target);
outcomes.push((state.clone(), stringify!($event), result));
};
}
push!(on_left);
push!(on_right);
}

assert_debug_snapshot!(outcomes);
assert_debug_snapshot!(State::test_transitions());
}

#[test]
Expand Down
26 changes: 1 addition & 25 deletions quic/s2n-quic-core/src/stream/state/recv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,31 +74,7 @@ mod tests {
#[test]
#[cfg_attr(miri, ignore)]
fn snapshots() {
let mut outcomes = vec![];
let states = [
Receiver::Recv,
Receiver::SizeKnown,
Receiver::DataRecvd,
Receiver::DataRead,
Receiver::ResetRecvd,
Receiver::ResetRead,
];
for state in states {
macro_rules! push {
($event:ident) => {
let mut target = state.clone();
let result = target.$event().map(|_| target);
outcomes.push((state.clone(), stringify!($event), result));
};
}
push!(on_receive_fin);
push!(on_receive_all_data);
push!(on_app_read_all_data);
push!(on_reset);
push!(on_app_read_reset);
}

assert_debug_snapshot!(outcomes);
assert_debug_snapshot!(Receiver::test_transitions());
}

#[test]
Expand Down
28 changes: 1 addition & 27 deletions quic/s2n-quic-core/src/stream/state/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,33 +80,7 @@ mod tests {
#[test]
#[cfg_attr(miri, ignore)]
fn snapshots() {
let mut outcomes = vec![];
let states = [
Sender::Ready,
Sender::Send,
Sender::DataSent,
Sender::DataRecvd,
Sender::ResetQueued,
Sender::ResetSent,
Sender::ResetRecvd,
];
for state in states {
macro_rules! push {
($event:ident) => {
let mut target = state.clone();
let result = target.$event().map(|_| target);
outcomes.push((state.clone(), stringify!($event), result));
};
}
push!(on_send_stream);
push!(on_send_fin);
push!(on_queue_reset);
push!(on_send_reset);
push!(on_recv_all_acks);
push!(on_recv_reset_ack);
}

assert_debug_snapshot!(outcomes);
assert_debug_snapshot!(Sender::test_transitions());
}

#[test]
Expand Down
Loading

0 comments on commit eb19e16

Please sign in to comment.