Skip to content

Commit

Permalink
feat(s2n-quic-core): generate state reactions to events (#2221)
Browse files Browse the repository at this point in the history
  • Loading branch information
camshaft authored May 23, 2024
1 parent f23d87b commit c96e57c
Show file tree
Hide file tree
Showing 7 changed files with 329 additions and 622 deletions.
83 changes: 83 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,89 @@ macro_rules! __state_event__ {
);
)*

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

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| {
[$({
let mut state = state.clone();
let result = state.$event().map(|_| state);
(stringify!($event), result)
}),*]
};

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, Error<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(&format_args!("{name}"), &Entry(events));
}

m.finish()
}
}

struct Entry<T>([(&'static str, Result<T, Error<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() {
m.entry(&format_args!("{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,86 @@
---
source: quic/s2n-quic-core/src/state/tests.rs
expression: outcomes
expression: "State::test_transitions()"
---
[
(
Init,
"on_left",
Ok(
{
Init: {
on_left: Ok(
Left,
),
),
(
Init,
"on_right",
Ok(
on_right: Ok(
Right,
),
),
(
Left,
"on_left",
Ok(
},
Left: {
on_left: Ok(
LeftLeft,
),
),
(
Left,
"on_right",
Ok(
on_right: Ok(
LeftRight,
),
),
(
Right,
"on_left",
Ok(
RightLeft,
),
),
(
Right,
"on_right",
Ok(
RightRight,
),
),
(
LeftLeft,
"on_left",
Err(
},
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(
RightLeft,
),
on_right: Ok(
RightRight,
),
},
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 c96e57c

Please sign in to comment.