Remove self param from all StateResolution methods

This commit is contained in:
Devin Ragotzy 2020-08-20 17:43:04 -04:00
parent 4e9b428c0d
commit 43e0f20d3b
4 changed files with 59 additions and 82 deletions

View File

@ -38,25 +38,22 @@ fn lexico_topo_sort(c: &mut Criterion) {
event_id("p") => vec![event_id("o")], event_id("p") => vec![event_id("o")],
}; };
b.iter(|| { b.iter(|| {
let resolver = StateResolution::default(); let _ = StateResolution::lexicographical_topological_sort(&graph, |id| {
(0, UNIX_EPOCH, id.clone())
let _ = });
resolver.lexicographical_topological_sort(&graph, |id| (0, UNIX_EPOCH, id.clone()));
}) })
}); });
} }
fn resolution_shallow_auth_chain(c: &mut Criterion) { fn resolution_shallow_auth_chain(c: &mut Criterion) {
c.bench_function("resolve state of 5 events one fork", |b| { c.bench_function("resolve state of 5 events one fork", |b| {
let resolver = StateResolution::default();
let store = TestStore(RefCell::new(btreemap! {})); let store = TestStore(RefCell::new(btreemap! {}));
// build up the DAG // build up the DAG
let (state_at_bob, state_at_charlie, _) = store.set_up(); let (state_at_bob, state_at_charlie, _) = store.set_up();
b.iter(|| { b.iter(|| {
let _resolved = match resolver.resolve( let _resolved = match StateResolution::resolve(
&room_id(), &room_id(),
&RoomVersionId::Version2, &RoomVersionId::Version2,
&[state_at_bob.clone(), state_at_charlie.clone()], &[state_at_bob.clone(), state_at_charlie.clone()],
@ -73,8 +70,6 @@ fn resolution_shallow_auth_chain(c: &mut Criterion) {
fn resolve_deeper_event_set(c: &mut Criterion) { fn resolve_deeper_event_set(c: &mut Criterion) {
c.bench_function("resolve state of 10 events 3 conflicting", |b| { c.bench_function("resolve state of 10 events 3 conflicting", |b| {
let resolver = StateResolution::default();
let init = INITIAL_EVENTS(); let init = INITIAL_EVENTS();
let ban = BAN_STATE_SET(); let ban = BAN_STATE_SET();
@ -109,7 +104,7 @@ fn resolve_deeper_event_set(c: &mut Criterion) {
.collect::<StateMap<_>>(); .collect::<StateMap<_>>();
b.iter(|| { b.iter(|| {
let _resolved = match resolver.resolve( let _resolved = match StateResolution::resolve(
&room_id(), &room_id(),
&RoomVersionId::Version2, &RoomVersionId::Version2,
&[state_set_a.clone(), state_set_b.clone()], &[state_set_a.clone(), state_set_b.clone()],

View File

@ -57,7 +57,6 @@ impl StateResolution {
/// * `store` - Any type that implements `StateStore` acts as the database. When an event is not /// * `store` - Any type that implements `StateStore` acts as the database. When an event is not
/// found in the `event_map` it will be retrieved from the `store`. /// found in the `event_map` it will be retrieved from the `store`.
pub fn resolve( pub fn resolve(
&self,
room_id: &RoomId, room_id: &RoomId,
room_version: &RoomVersionId, room_version: &RoomVersionId,
state_sets: &[StateMap<EventId>], state_sets: &[StateMap<EventId>],
@ -73,7 +72,7 @@ impl StateResolution {
EventMap::new() EventMap::new()
}; };
// split non-conflicting and conflicting state // split non-conflicting and conflicting state
let (clean, conflicting) = self.separate(&state_sets); let (clean, conflicting) = StateResolution::separate(&state_sets);
tracing::info!("non conflicting {:?}", clean.len()); tracing::info!("non conflicting {:?}", clean.len());
@ -85,7 +84,7 @@ impl StateResolution {
tracing::info!("{} conflicting events", conflicting.len()); tracing::info!("{} conflicting events", conflicting.len());
// the set of auth events that are not common across server forks // the set of auth events that are not common across server forks
let mut auth_diff = self.get_auth_chain_diff(room_id, &state_sets, store)?; let mut auth_diff = StateResolution::get_auth_chain_diff(room_id, &state_sets, store)?;
tracing::debug!("auth diff size {}", auth_diff.len()); tracing::debug!("auth diff size {}", auth_diff.len());
@ -142,7 +141,7 @@ impl StateResolution {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// sort the power events based on power_level/clock/event_id and outgoing/incoming edges // sort the power events based on power_level/clock/event_id and outgoing/incoming edges
let mut sorted_power_levels = self.reverse_topological_power_sort( let mut sorted_power_levels = StateResolution::reverse_topological_power_sort(
room_id, room_id,
&power_events, &power_events,
&mut event_map, &mut event_map,
@ -159,7 +158,7 @@ impl StateResolution {
); );
// sequentially auth check each power level event event. // sequentially auth check each power level event event.
let resolved = self.iterative_auth_check( let resolved = StateResolution::iterative_auth_check(
room_id, room_id,
room_version, room_version,
&sorted_power_levels, &sorted_power_levels,
@ -200,7 +199,7 @@ impl StateResolution {
tracing::debug!("PL {:?}", power_event); tracing::debug!("PL {:?}", power_event);
let sorted_left_events = self.mainline_sort( let sorted_left_events = StateResolution::mainline_sort(
room_id, room_id,
&events_to_resolve, &events_to_resolve,
power_event, power_event,
@ -216,7 +215,7 @@ impl StateResolution {
.collect::<Vec<_>>() .collect::<Vec<_>>()
); );
let mut resolved_state = self.iterative_auth_check( let mut resolved_state = StateResolution::iterative_auth_check(
room_id, room_id,
room_version, room_version,
&sorted_left_events, &sorted_left_events,
@ -235,7 +234,6 @@ impl StateResolution {
/// ///
/// The tuple looks like `(unconflicted, conflicted)`. /// The tuple looks like `(unconflicted, conflicted)`.
pub fn separate( pub fn separate(
&self,
state_sets: &[StateMap<EventId>], state_sets: &[StateMap<EventId>],
) -> (StateMap<EventId>, StateMap<Vec<EventId>>) { ) -> (StateMap<EventId>, StateMap<Vec<EventId>>) {
use itertools::Itertools; use itertools::Itertools;
@ -248,12 +246,7 @@ impl StateResolution {
let mut unconflicted_state = StateMap::new(); let mut unconflicted_state = StateMap::new();
let mut conflicted_state = StateMap::new(); let mut conflicted_state = StateMap::new();
for key in state_sets for key in state_sets.iter().flat_map(|map| map.keys()).dedup() {
.iter()
.flat_map(|map| map.keys())
.dedup()
.collect::<Vec<_>>()
{
let mut event_ids = state_sets let mut event_ids = state_sets
.iter() .iter()
.map(|state_set| state_set.get(key)) .map(|state_set| state_set.get(key))
@ -287,7 +280,6 @@ impl StateResolution {
/// Returns a Vec of deduped EventIds that appear in some chains but not others. /// Returns a Vec of deduped EventIds that appear in some chains but not others.
pub fn get_auth_chain_diff( pub fn get_auth_chain_diff(
&self,
room_id: &RoomId, room_id: &RoomId,
state_sets: &[StateMap<EventId>], state_sets: &[StateMap<EventId>],
store: &dyn StateStore, store: &dyn StateStore,
@ -315,7 +307,6 @@ impl StateResolution {
/// The power level is negative because a higher power level is equated to an /// The power level is negative because a higher power level is equated to an
/// earlier (further back in time) origin server timestamp. /// earlier (further back in time) origin server timestamp.
pub fn reverse_topological_power_sort( pub fn reverse_topological_power_sort(
&self,
room_id: &RoomId, room_id: &RoomId,
events_to_sort: &[EventId], events_to_sort: &[EventId],
event_map: &mut EventMap<StateEvent>, event_map: &mut EventMap<StateEvent>,
@ -326,7 +317,7 @@ impl StateResolution {
let mut graph = BTreeMap::new(); let mut graph = BTreeMap::new();
for (idx, event_id) in events_to_sort.iter().enumerate() { for (idx, event_id) in events_to_sort.iter().enumerate() {
self.add_event_and_auth_chain_to_graph( StateResolution::add_event_and_auth_chain_to_graph(
room_id, &mut graph, event_id, event_map, store, auth_diff, room_id, &mut graph, event_id, event_map, store, auth_diff,
); );
@ -340,7 +331,8 @@ impl StateResolution {
// this is used in the `key_fn` passed to the lexico_topo_sort fn // this is used in the `key_fn` passed to the lexico_topo_sort fn
let mut event_to_pl = BTreeMap::new(); let mut event_to_pl = BTreeMap::new();
for (idx, event_id) in graph.keys().enumerate() { for (idx, event_id) in graph.keys().enumerate() {
let pl = self.get_power_level_for_sender(room_id, &event_id, event_map, store); let pl =
StateResolution::get_power_level_for_sender(room_id, &event_id, event_map, store);
tracing::info!("{} power level {}", event_id.to_string(), pl); tracing::info!("{} power level {}", event_id.to_string(), pl);
event_to_pl.insert(event_id.clone(), pl); event_to_pl.insert(event_id.clone(), pl);
@ -352,7 +344,7 @@ impl StateResolution {
} }
} }
self.lexicographical_topological_sort(&graph, |event_id| { StateResolution::lexicographical_topological_sort(&graph, |event_id| {
// tracing::debug!("{:?}", event_map.get(event_id).unwrap().origin_server_ts()); // tracing::debug!("{:?}", event_map.get(event_id).unwrap().origin_server_ts());
let ev = event_map.get(event_id).unwrap(); let ev = event_map.get(event_id).unwrap();
let pl = event_to_pl.get(event_id).unwrap(); let pl = event_to_pl.get(event_id).unwrap();
@ -376,7 +368,6 @@ impl StateResolution {
/// `key_fn` is used as a tie breaker. The tie breaker happens based on /// `key_fn` is used as a tie breaker. The tie breaker happens based on
/// power level, age, and event_id. /// power level, age, and event_id.
pub fn lexicographical_topological_sort<F>( pub fn lexicographical_topological_sort<F>(
&self,
graph: &BTreeMap<EventId, Vec<EventId>>, graph: &BTreeMap<EventId, Vec<EventId>>,
key_fn: F, key_fn: F,
) -> Vec<EventId> ) -> Vec<EventId>
@ -444,7 +435,6 @@ impl StateResolution {
/// Find the power level for the sender of `event_id` or return a default value of zero. /// Find the power level for the sender of `event_id` or return a default value of zero.
fn get_power_level_for_sender( fn get_power_level_for_sender(
&self,
room_id: &RoomId, room_id: &RoomId,
event_id: &EventId, event_id: &EventId,
event_map: &mut EventMap<StateEvent>, event_map: &mut EventMap<StateEvent>,
@ -452,13 +442,13 @@ impl StateResolution {
) -> i64 { ) -> i64 {
tracing::info!("fetch event ({}) senders power level", event_id.to_string()); tracing::info!("fetch event ({}) senders power level", event_id.to_string());
let event = self.get_or_load_event(room_id, event_id, event_map, store); let event = StateResolution::get_or_load_event(room_id, event_id, event_map, store);
let mut pl = None; let mut pl = None;
// TODO store.auth_event_ids returns "self" with the event ids is this ok // TODO store.auth_event_ids returns "self" with the event ids is this ok
// event.auth_event_ids does not include its own event id ? // event.auth_event_ids does not include its own event id ?
for aid in event.as_ref().unwrap().auth_events() { for aid in event.as_ref().unwrap().auth_events() {
if let Some(aev) = self.get_or_load_event(room_id, &aid, event_map, store) { if let Some(aev) = StateResolution::get_or_load_event(room_id, &aid, event_map, store) {
if aev.is_type_and_key(EventType::RoomPowerLevels, "") { if aev.is_type_and_key(EventType::RoomPowerLevels, "") {
pl = Some(aev); pl = Some(aev);
break; break;
@ -504,8 +494,12 @@ impl StateResolution {
} }
} }
fn iterative_auth_check( /// Check the that each event is authenticated based on the events before it.
&self, ///
/// For each `power_events` event we gather the events needed to auth it from the
/// `event_map` or `store` and verify each event using the `event_auth::auth_check`
/// function.
pub fn iterative_auth_check(
room_id: &RoomId, room_id: &RoomId,
room_version: &RoomVersionId, room_version: &RoomVersionId,
power_events: &[EventId], power_events: &[EventId],
@ -526,13 +520,14 @@ impl StateResolution {
let mut resolved_state = unconflicted_state.clone(); let mut resolved_state = unconflicted_state.clone();
for (idx, event_id) in power_events.iter().enumerate() { for (idx, event_id) in power_events.iter().enumerate() {
let event = self let event =
.get_or_load_event(room_id, event_id, event_map, store) StateResolution::get_or_load_event(room_id, event_id, event_map, store).unwrap();
.unwrap();
let mut auth_events = BTreeMap::new(); let mut auth_events = BTreeMap::new();
for aid in event.auth_events() { for aid in event.auth_events() {
if let Some(ev) = self.get_or_load_event(room_id, &aid, event_map, store) { if let Some(ev) =
StateResolution::get_or_load_event(room_id, &aid, event_map, store)
{
// TODO what to do when no state_key is found ?? // TODO what to do when no state_key is found ??
// TODO synapse check "rejected_reason", I'm guessing this is redacted_because for ruma ?? // TODO synapse check "rejected_reason", I'm guessing this is redacted_because for ruma ??
auth_events.insert((ev.kind(), ev.state_key()), ev); auth_events.insert((ev.kind(), ev.state_key()), ev);
@ -548,7 +543,9 @@ impl StateResolution {
event.content().clone(), event.content().clone(),
) { ) {
if let Some(ev_id) = resolved_state.get(&key) { if let Some(ev_id) = resolved_state.get(&key) {
if let Some(event) = self.get_or_load_event(room_id, ev_id, event_map, store) { if let Some(event) =
StateResolution::get_or_load_event(room_id, ev_id, event_map, store)
{
// TODO synapse checks `rejected_reason` is None here // TODO synapse checks `rejected_reason` is None here
auth_events.insert(key.clone(), event); auth_events.insert(key.clone(), event);
} }
@ -582,18 +579,14 @@ impl StateResolution {
/// Returns the sorted `to_sort` list of `EventId`s based on a mainline sort using /// Returns the sorted `to_sort` list of `EventId`s based on a mainline sort using
/// the `resolved_power_level`. /// the `resolved_power_level`.
/// pub fn mainline_sort(
/// NOTE we rely on the `event_map` beign full at this point.
/// TODO is this ok?
fn mainline_sort(
&self,
room_id: &RoomId, room_id: &RoomId,
to_sort: &[EventId], to_sort: &[EventId],
resolved_power_level: Option<&EventId>, resolved_power_level: Option<&EventId>,
event_map: &mut EventMap<StateEvent>, event_map: &mut EventMap<StateEvent>,
store: &dyn StateStore, store: &dyn StateStore,
) -> Vec<EventId> { ) -> Vec<EventId> {
tracing::debug!("mainline sort of remaining events"); tracing::debug!("mainline sort of events");
// There are no EventId's to sort, bail. // There are no EventId's to sort, bail.
if to_sort.is_empty() { if to_sort.is_empty() {
@ -606,15 +599,12 @@ impl StateResolution {
while let Some(p) = pl { while let Some(p) = pl {
mainline.push(p.clone()); mainline.push(p.clone());
let event = self let event = StateResolution::get_or_load_event(room_id, &p, event_map, store).unwrap();
.get_or_load_event(room_id, &p, event_map, store)
.unwrap();
let auth_events = event.auth_events(); let auth_events = event.auth_events();
pl = None; pl = None;
for aid in auth_events { for aid in auth_events {
let ev = self let ev =
.get_or_load_event(room_id, &aid, event_map, store) StateResolution::get_or_load_event(room_id, &aid, event_map, store).unwrap();
.unwrap();
if ev.is_type_and_key(EventType::RoomPowerLevels, "") { if ev.is_type_and_key(EventType::RoomPowerLevels, "") {
pl = Some(aid.clone()); pl = Some(aid.clone());
break; break;
@ -638,8 +628,14 @@ impl StateResolution {
let mut order_map = BTreeMap::new(); let mut order_map = BTreeMap::new();
for (idx, ev_id) in to_sort.iter().enumerate() { for (idx, ev_id) in to_sort.iter().enumerate() {
let event = self.get_or_load_event(room_id, ev_id, event_map, store); let event = StateResolution::get_or_load_event(room_id, ev_id, event_map, store);
let depth = self.get_mainline_depth(room_id, event, &mainline_map, event_map, store); let depth = StateResolution::get_mainline_depth(
room_id,
event,
&mainline_map,
event_map,
store,
);
order_map.insert( order_map.insert(
ev_id, ev_id,
( (
@ -668,7 +664,6 @@ impl StateResolution {
// TODO make `event` not clone every loop // TODO make `event` not clone every loop
fn get_mainline_depth( fn get_mainline_depth(
&self,
room_id: &RoomId, room_id: &RoomId,
mut event: Option<StateEvent>, mut event: Option<StateEvent>,
mainline_map: &EventMap<usize>, mainline_map: &EventMap<usize>,
@ -685,9 +680,8 @@ impl StateResolution {
let auth_events = sort_ev.auth_events(); let auth_events = sort_ev.auth_events();
event = None; event = None;
for aid in auth_events { for aid in auth_events {
let aev = self let aev =
.get_or_load_event(room_id, &aid, event_map, store) StateResolution::get_or_load_event(room_id, &aid, event_map, store).unwrap();
.unwrap();
if aev.is_type_and_key(EventType::RoomPowerLevels, "") { if aev.is_type_and_key(EventType::RoomPowerLevels, "") {
event = Some(aev.clone()); event = Some(aev.clone());
break; break;
@ -699,7 +693,6 @@ impl StateResolution {
} }
fn add_event_and_auth_chain_to_graph( fn add_event_and_auth_chain_to_graph(
&self,
room_id: &RoomId, room_id: &RoomId,
graph: &mut BTreeMap<EventId, Vec<EventId>>, graph: &mut BTreeMap<EventId, Vec<EventId>>,
event_id: &EventId, event_id: &EventId,
@ -714,8 +707,7 @@ impl StateResolution {
graph.entry(eid.clone()).or_insert_with(Vec::new); graph.entry(eid.clone()).or_insert_with(Vec::new);
// prefer the store to event as the store filters dedups the events // prefer the store to event as the store filters dedups the events
// otherwise it seems we can loop forever // otherwise it seems we can loop forever
for aid in self for aid in StateResolution::get_or_load_event(room_id, &eid, event_map, store)
.get_or_load_event(room_id, &eid, event_map, store)
.unwrap() .unwrap()
.auth_events() .auth_events()
{ {
@ -738,7 +730,6 @@ impl StateResolution {
/// ///
/// If the PDU is missing from the `event_map` it is added. /// If the PDU is missing from the `event_map` it is added.
fn get_or_load_event( fn get_or_load_event(
&self,
room_id: &RoomId, room_id: &RoomId,
ev_id: &EventId, ev_id: &EventId,
event_map: &mut EventMap<StateEvent>, event_map: &mut EventMap<StateEvent>,

View File

@ -35,8 +35,6 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
.init() .init()
}); });
let resolver = StateResolution::default();
let store = TestStore(RefCell::new( let store = TestStore(RefCell::new(
INITIAL_EVENTS() INITIAL_EVENTS()
.values() .values()
@ -78,7 +76,8 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
// resolve the current state and add it to the state_at_event map then continue // resolve the current state and add it to the state_at_event map then continue
// on in "time" // on in "time"
for node in resolver.lexicographical_topological_sort(&graph, |id| (0, UNIX_EPOCH, id.clone())) for node in
StateResolution::lexicographical_topological_sort(&graph, |id| (0, UNIX_EPOCH, id.clone()))
{ {
let fake_event = fake_event_map.get(&node).unwrap(); let fake_event = fake_event_map.get(&node).unwrap();
let event_id = fake_event.event_id(); let event_id = fake_event.event_id();
@ -107,7 +106,7 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
.collect::<Vec<_>>() .collect::<Vec<_>>()
); );
let resolved = resolver.resolve( let resolved = StateResolution::resolve(
&room_id(), &room_id(),
&RoomVersionId::Version1, &RoomVersionId::Version1,
&state_sets, &state_sets,
@ -589,12 +588,10 @@ fn ban_with_auth_chains() {
#[test] #[test]
fn base_with_auth_chains() { fn base_with_auth_chains() {
let resolver = StateResolution::default();
let store = TestStore(RefCell::new(INITIAL_EVENTS())); let store = TestStore(RefCell::new(INITIAL_EVENTS()));
let resolved: BTreeMap<_, EventId> = let resolved: BTreeMap<_, EventId> =
match resolver.resolve(&room_id(), &RoomVersionId::Version2, &[], None, &store) { match StateResolution::resolve(&room_id(), &RoomVersionId::Version2, &[], None, &store) {
Ok(ResolutionResult::Resolved(state)) => state, Ok(ResolutionResult::Resolved(state)) => state,
Err(e) => panic!("{}", e), Err(e) => panic!("{}", e),
_ => panic!("conflicted state left"), _ => panic!("conflicted state left"),
@ -625,8 +622,6 @@ fn base_with_auth_chains() {
#[test] #[test]
fn ban_with_auth_chains2() { fn ban_with_auth_chains2() {
let resolver = StateResolution::default();
let init = INITIAL_EVENTS(); let init = INITIAL_EVENTS();
let ban = BAN_STATE_SET(); let ban = BAN_STATE_SET();
@ -660,7 +655,7 @@ fn ban_with_auth_chains2() {
.map(|ev| ((ev.kind(), ev.state_key()), ev.event_id())) .map(|ev| ((ev.kind(), ev.state_key()), ev.event_id()))
.collect::<StateMap<_>>(); .collect::<StateMap<_>>();
let resolved: StateMap<EventId> = match resolver.resolve( let resolved: StateMap<EventId> = match StateResolution::resolve(
&room_id(), &room_id(),
&RoomVersionId::Version2, &RoomVersionId::Version2,
&[state_set_a, state_set_b], &[state_set_a, state_set_b],

View File

@ -295,8 +295,6 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
.init() .init()
}); });
let resolver = StateResolution::default();
let store = TestStore(RefCell::new( let store = TestStore(RefCell::new(
INITIAL_EVENTS() INITIAL_EVENTS()
.values() .values()
@ -338,7 +336,8 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
// resolve the current state and add it to the state_at_event map then continue // resolve the current state and add it to the state_at_event map then continue
// on in "time" // on in "time"
for node in resolver.lexicographical_topological_sort(&graph, |id| (0, UNIX_EPOCH, id.clone())) for node in
StateResolution::lexicographical_topological_sort(&graph, |id| (0, UNIX_EPOCH, id.clone()))
{ {
let fake_event = fake_event_map.get(&node).unwrap(); let fake_event = fake_event_map.get(&node).unwrap();
let event_id = fake_event.event_id(); let event_id = fake_event.event_id();
@ -367,7 +366,7 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
.collect::<Vec<_>>() .collect::<Vec<_>>()
); );
let resolved = resolver.resolve( let resolved = StateResolution::resolve(
&room_id(), &room_id(),
&RoomVersionId::Version1, &RoomVersionId::Version1,
&state_sets, &state_sets,
@ -712,14 +711,12 @@ fn topic_setting() {
#[test] #[test]
fn test_event_map_none() { fn test_event_map_none() {
let resolver = StateResolution::default();
let store = TestStore(RefCell::new(btreemap! {})); let store = TestStore(RefCell::new(btreemap! {}));
// build up the DAG // build up the DAG
let (state_at_bob, state_at_charlie, expected) = store.set_up(); let (state_at_bob, state_at_charlie, expected) = store.set_up();
let resolved = match resolver.resolve( let resolved = match StateResolution::resolve(
&room_id(), &room_id(),
&RoomVersionId::Version2, &RoomVersionId::Version2,
&[state_at_bob, state_at_charlie], &[state_at_bob, state_at_charlie],
@ -736,8 +733,6 @@ fn test_event_map_none() {
#[test] #[test]
fn test_lexicographical_sort() { fn test_lexicographical_sort() {
let resolver = StateResolution::default();
let graph = btreemap! { let graph = btreemap! {
event_id("l") => vec![event_id("o")], event_id("l") => vec![event_id("o")],
event_id("m") => vec![event_id("n"), event_id("o")], event_id("m") => vec![event_id("n"), event_id("o")],
@ -746,7 +741,8 @@ fn test_lexicographical_sort() {
event_id("p") => vec![event_id("o")], event_id("p") => vec![event_id("o")],
}; };
let res = resolver.lexicographical_topological_sort(&graph, |id| (0, UNIX_EPOCH, id.clone())); let res =
StateResolution::lexicographical_topological_sort(&graph, |id| (0, UNIX_EPOCH, id.clone()));
assert_eq!( assert_eq!(
vec!["o", "l", "n", "m", "p"], vec!["o", "l", "n", "m", "p"],