lexi_topo_sort needs to return a neg power_level to sort properly
All tests pass!!! Changed println! to logger calls.
This commit is contained in:
parent
a0db51b3bd
commit
106cab46bc
54
src/lib.rs
54
src/lib.rs
@ -140,13 +140,15 @@ impl StateResolution {
|
||||
// TODO make sure each conflicting event is in event_map??
|
||||
// synapse says `full_set = {eid for eid in full_conflicted_set if eid in event_map}`
|
||||
all_conflicted.retain(|id| event_map.contains_key(id));
|
||||
println!(
|
||||
|
||||
tracing::debug!(
|
||||
"ALL {:?}",
|
||||
all_conflicted
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
// get only the power events with a state_key: "" or ban/kick event (sender != state_key)
|
||||
let power_events = all_conflicted
|
||||
.iter()
|
||||
@ -154,7 +156,7 @@ impl StateResolution {
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
println!(
|
||||
tracing::debug!(
|
||||
"POWER {:?}",
|
||||
power_events
|
||||
.iter()
|
||||
@ -171,7 +173,7 @@ impl StateResolution {
|
||||
&all_conflicted,
|
||||
);
|
||||
|
||||
println!(
|
||||
tracing::debug!(
|
||||
"SRTD {:?}",
|
||||
sorted_power_levels
|
||||
.iter()
|
||||
@ -209,7 +211,7 @@ impl StateResolution {
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
println!(
|
||||
tracing::debug!(
|
||||
"LEFT {:?}",
|
||||
events_to_resolve
|
||||
.iter()
|
||||
@ -224,7 +226,7 @@ impl StateResolution {
|
||||
let sorted_left_events =
|
||||
self.mainline_sort(room_id, &events_to_resolve, power_event, &event_map, store);
|
||||
|
||||
println!(
|
||||
tracing::debug!(
|
||||
"SORTED LEFT {:?}",
|
||||
sorted_left_events
|
||||
.iter()
|
||||
@ -330,7 +332,7 @@ impl StateResolution {
|
||||
let mut event_to_pl = BTreeMap::new();
|
||||
for (idx, event_id) in graph.keys().enumerate() {
|
||||
let pl = self.get_power_level_for_sender(room_id, &event_id, event_map, store);
|
||||
println!("{} power level {}", event_id.to_string(), pl);
|
||||
tracing::info!("{} power level {}", event_id.to_string(), pl);
|
||||
|
||||
event_to_pl.insert(event_id.clone(), pl);
|
||||
|
||||
@ -345,10 +347,20 @@ impl StateResolution {
|
||||
// tracing::debug!("{:?}", event_map.get(event_id).unwrap().origin_server_ts());
|
||||
let ev = event_map.get(event_id).unwrap();
|
||||
let pl = event_to_pl.get(event_id).unwrap();
|
||||
|
||||
tracing::debug!(
|
||||
"{:?}",
|
||||
(
|
||||
-*pl,
|
||||
ev.origin_server_ts().clone(),
|
||||
ev.event_id().unwrap().to_string()
|
||||
)
|
||||
);
|
||||
|
||||
// This return value is the key used for sorting events,
|
||||
// events are then sorted by power level, time,
|
||||
// and lexically by event_id.
|
||||
(*pl, ev.origin_server_ts().clone(), ev.event_id().cloned())
|
||||
(-*pl, ev.origin_server_ts().clone(), ev.event_id().cloned())
|
||||
})
|
||||
}
|
||||
|
||||
@ -419,16 +431,12 @@ impl StateResolution {
|
||||
sorted.push(node.clone());
|
||||
}
|
||||
|
||||
// tracing::debug!(
|
||||
// "{:#?}",
|
||||
// sorted.iter().map(ToString::to_string).collect::<Vec<_>>()
|
||||
// );
|
||||
sorted
|
||||
}
|
||||
|
||||
fn get_power_level_for_sender(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
_room_id: &RoomId,
|
||||
event_id: &EventId,
|
||||
event_map: &EventMap<StateEvent>, // TODO use event_map over store ??
|
||||
store: &dyn StateStore,
|
||||
@ -438,9 +446,8 @@ impl StateResolution {
|
||||
let mut pl = None;
|
||||
// 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 ?
|
||||
for aid in event_map.get(event_id).unwrap().auth_event_ids() {
|
||||
println!("aid {}", aid.to_string());
|
||||
if let Some(aev) = event_map.get(&aid) {
|
||||
for aid in store.get_event(event_id).unwrap().auth_event_ids() {
|
||||
if let Ok(aev) = store.get_event(&aid) {
|
||||
if aev.is_type_and_key(EventType::RoomPowerLevels, "") {
|
||||
pl = Some(aev);
|
||||
break;
|
||||
@ -449,10 +456,8 @@ impl StateResolution {
|
||||
}
|
||||
|
||||
if pl.is_none() {
|
||||
for aid in event_map.get(event_id).unwrap().auth_event_ids() {
|
||||
println!("aid NONE {}", aid.to_string());
|
||||
|
||||
if let Some(aev) = event_map.get(&aid) {
|
||||
for aid in store.get_event(event_id).unwrap().auth_event_ids() {
|
||||
if let Ok(aev) = store.get_event(&aid) {
|
||||
if aev.is_type_and_key(EventType::RoomCreate, "") {
|
||||
if let Ok(content) = aev
|
||||
.deserialize_content::<ruma::events::room::create::CreateEventContent>()
|
||||
@ -478,10 +483,11 @@ impl StateResolution {
|
||||
{
|
||||
if let Some(ev) = event {
|
||||
if let Some(user) = content.users.get(ev.sender()) {
|
||||
tracing::debug!("found {} at power_level {}", ev.sender().to_string(), user);
|
||||
return (*user).into();
|
||||
}
|
||||
}
|
||||
content.state_default.into()
|
||||
content.users_default.into()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
@ -549,7 +555,7 @@ impl StateResolution {
|
||||
/// the `resolved_power_level`.
|
||||
fn mainline_sort(
|
||||
&mut self,
|
||||
room_id: &RoomId,
|
||||
_room_id: &RoomId,
|
||||
to_sort: &[EventId],
|
||||
resolved_power_level: Option<&EventId>,
|
||||
event_map: &EventMap<StateEvent>,
|
||||
@ -571,7 +577,7 @@ impl StateResolution {
|
||||
while let Some(p) = pl {
|
||||
mainline.push(p.clone());
|
||||
// We don't need the actual pl_ev here since we delegate to the store
|
||||
let auth_events = store.auth_event_ids(room_id, &[p]).unwrap();
|
||||
let auth_events = store.get_event(&p).unwrap().auth_event_ids();
|
||||
pl = None;
|
||||
for aid in auth_events {
|
||||
let ev = store.get_event(&aid).unwrap();
|
||||
@ -664,7 +670,7 @@ impl StateResolution {
|
||||
|
||||
fn add_event_and_auth_chain_to_graph(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
_room_id: &RoomId,
|
||||
graph: &mut BTreeMap<EventId, Vec<EventId>>,
|
||||
event_id: &EventId,
|
||||
store: &dyn StateStore,
|
||||
@ -677,7 +683,7 @@ impl StateResolution {
|
||||
graph.entry(eid.clone()).or_insert(vec![]);
|
||||
// prefer the store to event as the store filters dedups the events
|
||||
// otherwise it seems we can loop forever
|
||||
for aid in store.auth_event_ids(room_id, &[eid.clone()]).unwrap() {
|
||||
for aid in store.get_event(&eid).unwrap().auth_event_ids() {
|
||||
if auth_diff.contains(&aid) {
|
||||
if !graph.contains_key(&aid) {
|
||||
state.push(aid.clone());
|
||||
|
@ -44,9 +44,32 @@ impl StateEvent {
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
Pdu::RoomV3Pdu(event) => panic!(),
|
||||
Pdu::RoomV3Pdu(event) => event.state_key == Some("".into()),
|
||||
},
|
||||
Self::Sync(any_event) => match any_event {
|
||||
PduStub::RoomV1PduStub(event) => match event.kind {
|
||||
EventType::RoomPowerLevels
|
||||
| EventType::RoomJoinRules
|
||||
| EventType::RoomCreate => event.state_key == Some("".into()),
|
||||
EventType::RoomMember => {
|
||||
if let Ok(content) =
|
||||
serde_json::from_value::<MemberEventContent>(event.content.clone())
|
||||
{
|
||||
if [MembershipState::Leave, MembershipState::Ban]
|
||||
.contains(&content.membership)
|
||||
{
|
||||
return event.sender.as_str()
|
||||
// TODO does None here mean the same as state_key = ""
|
||||
!= event.state_key.as_deref().unwrap_or("");
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
PduStub::RoomV3PduStub(event) => event.state_key == Some("".into()),
|
||||
},
|
||||
Self::Sync(any_event) => panic!(),
|
||||
}
|
||||
}
|
||||
pub fn deserialize_content<C: serde::de::DeserializeOwned>(
|
||||
|
@ -32,11 +32,11 @@ fn id(id: &str) -> EventId {
|
||||
fn alice() -> UserId {
|
||||
UserId::try_from("@alice:foo").unwrap()
|
||||
}
|
||||
fn bobo() -> UserId {
|
||||
UserId::try_from("@bobo:foo").unwrap()
|
||||
fn bob() -> UserId {
|
||||
UserId::try_from("@bob:foo").unwrap()
|
||||
}
|
||||
fn devin() -> UserId {
|
||||
UserId::try_from("@devin:foo").unwrap()
|
||||
fn charlie() -> UserId {
|
||||
UserId::try_from("@charlie:foo").unwrap()
|
||||
}
|
||||
fn zera() -> UserId {
|
||||
UserId::try_from("@zera:foo").unwrap()
|
||||
@ -244,16 +244,16 @@ fn INITIAL_EVENTS() -> BTreeMap<EventId, StateEvent> {
|
||||
),
|
||||
to_init_pdu_event(
|
||||
"IMB",
|
||||
bobo(),
|
||||
bob(),
|
||||
EventType::RoomMember,
|
||||
Some(bobo().to_string().as_str()),
|
||||
Some(bob().to_string().as_str()),
|
||||
member_content_join(),
|
||||
),
|
||||
to_init_pdu_event(
|
||||
"IMC",
|
||||
devin(),
|
||||
charlie(),
|
||||
EventType::RoomMember,
|
||||
Some(devin().to_string().as_str()),
|
||||
Some(charlie().to_string().as_str()),
|
||||
member_content_join(),
|
||||
),
|
||||
to_init_pdu_event(
|
||||
@ -292,7 +292,7 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
|
||||
// .init();
|
||||
|
||||
let mut resolver = StateResolution::default();
|
||||
// TODO what do we fill this with, everything ??
|
||||
|
||||
let store = TestStore(RefCell::new(
|
||||
INITIAL_EVENTS()
|
||||
.values()
|
||||
@ -354,16 +354,16 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// println!(
|
||||
// "RESOLVING {:?}",
|
||||
// state_sets
|
||||
// .iter()
|
||||
// .map(|map| map
|
||||
// .iter()
|
||||
// .map(|((t, s), id)| (t, s, id.to_string()))
|
||||
// .collect::<Vec<_>>())
|
||||
// .collect::<Vec<_>>()
|
||||
// );
|
||||
tracing::debug!(
|
||||
"RESOLVING {:?}",
|
||||
state_sets
|
||||
.iter()
|
||||
.map(|map| map
|
||||
.iter()
|
||||
.map(|((t, s), id)| (t, s, id.to_string()))
|
||||
.collect::<Vec<_>>())
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
let resolved = resolver.resolve(
|
||||
&room_id(),
|
||||
@ -397,10 +397,6 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
|
||||
}
|
||||
|
||||
let auth_types = state_res::auth_types_for_event(fake_event);
|
||||
// println!(
|
||||
// "AUTH TYPES {:?}",
|
||||
// auth_types.iter().map(|(t, id)| (t, id)).collect::<Vec<_>>()
|
||||
// );
|
||||
|
||||
let mut auth_events = vec![];
|
||||
for key in auth_types {
|
||||
@ -469,7 +465,7 @@ fn ban_vs_power_level() {
|
||||
alice(),
|
||||
EventType::RoomPowerLevels,
|
||||
Some(""),
|
||||
json!({"users": {alice(): 100, bobo(): 50}}),
|
||||
json!({"users": {alice(): 100, bob(): 50}}),
|
||||
),
|
||||
to_init_pdu_event(
|
||||
"MA",
|
||||
@ -482,15 +478,15 @@ fn ban_vs_power_level() {
|
||||
"MB",
|
||||
alice(),
|
||||
EventType::RoomMember,
|
||||
Some(bobo().to_string().as_str()),
|
||||
Some(bob().to_string().as_str()),
|
||||
member_content_ban(),
|
||||
),
|
||||
to_init_pdu_event(
|
||||
"PB",
|
||||
bobo(),
|
||||
bob(),
|
||||
EventType::RoomPowerLevels,
|
||||
Some(""),
|
||||
json!({"users": {alice(): 100, bobo(): 50}}),
|
||||
json!({"users": {alice(): 100, bob(): 50}}),
|
||||
),
|
||||
];
|
||||
|
||||
@ -518,7 +514,7 @@ fn ban_vs_power_level() {
|
||||
do_check(events, edges, expected_state_ids)
|
||||
}
|
||||
|
||||
// #[test]
|
||||
#[test]
|
||||
fn topic_basic() {
|
||||
let events = &[
|
||||
to_init_pdu_event("T1", alice(), EventType::RoomTopic, Some(""), json!({})),
|
||||
@ -527,7 +523,7 @@ fn topic_basic() {
|
||||
alice(),
|
||||
EventType::RoomPowerLevels,
|
||||
Some(""),
|
||||
json!({"users": {alice(): 100, bobo(): 50}}),
|
||||
json!({"users": {alice(): 100, bob(): 50}}),
|
||||
),
|
||||
to_init_pdu_event("T2", alice(), EventType::RoomTopic, Some(""), json!({})),
|
||||
to_init_pdu_event(
|
||||
@ -535,16 +531,16 @@ fn topic_basic() {
|
||||
alice(),
|
||||
EventType::RoomPowerLevels,
|
||||
Some(""),
|
||||
json!({"users": {alice(): 100, bobo(): 0}}),
|
||||
json!({"users": {alice(): 100, bob(): 0}}),
|
||||
),
|
||||
to_init_pdu_event(
|
||||
"PAB",
|
||||
bobo(),
|
||||
"PB",
|
||||
bob(),
|
||||
EventType::RoomPowerLevels,
|
||||
Some(""),
|
||||
json!({"users": {alice(): 100, bobo(): 50}}),
|
||||
json!({"users": {alice(): 100, bob(): 50}}),
|
||||
),
|
||||
to_init_pdu_event("T3", bobo(), EventType::RoomTopic, Some(""), json!({})),
|
||||
to_init_pdu_event("T3", bob(), EventType::RoomTopic, Some(""), json!({})),
|
||||
];
|
||||
|
||||
let edges = vec![
|
||||
@ -580,14 +576,14 @@ fn topic_reset() {
|
||||
alice(),
|
||||
EventType::RoomPowerLevels,
|
||||
Some(""),
|
||||
json!({"users": {alice(): 100, bobo(): 50}}),
|
||||
json!({"users": {alice(): 100, bob(): 50}}),
|
||||
),
|
||||
to_init_pdu_event("T2", bobo(), EventType::RoomTopic, Some(""), json!({})),
|
||||
to_init_pdu_event("T2", bob(), EventType::RoomTopic, Some(""), json!({})),
|
||||
to_init_pdu_event(
|
||||
"MB",
|
||||
alice(),
|
||||
EventType::RoomMember,
|
||||
Some(bobo().to_string().as_str()),
|
||||
Some(bob().to_string().as_str()),
|
||||
member_content_ban(),
|
||||
),
|
||||
];
|
||||
@ -616,6 +612,30 @@ fn topic_reset() {
|
||||
do_check(events, edges, expected_state_ids)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_event_map_none() {
|
||||
let mut resolver = StateResolution::default();
|
||||
|
||||
let store = TestStore(RefCell::new(btreemap! {}));
|
||||
|
||||
// build up the DAG
|
||||
let (state_at_bob, state_at_charlie, expected) = store.set_up();
|
||||
|
||||
let resolved = match resolver.resolve(
|
||||
&room_id(),
|
||||
&RoomVersionId::version_2(),
|
||||
&[state_at_bob, state_at_charlie],
|
||||
None,
|
||||
&store,
|
||||
) {
|
||||
Ok(ResolutionResult::Resolved(state)) => state,
|
||||
Err(e) => panic!("{}", e),
|
||||
_ => panic!("conflicted state left"),
|
||||
};
|
||||
|
||||
assert_eq!(expected, resolved)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lexicographical_sort() {
|
||||
let mut resolver = StateResolution::default();
|
||||
@ -699,16 +719,10 @@ impl StateStore for TestStore {
|
||||
) -> Result<Vec<EventId>, String> {
|
||||
use itertools::Itertools;
|
||||
|
||||
// println!(
|
||||
// "EVENTS FOR AUTH {:?}",
|
||||
// event_ids
|
||||
// .iter()
|
||||
// .map(|v| v.iter().map(ToString::to_string).collect::<Vec<_>>())
|
||||
// .collect::<Vec<_>>()
|
||||
// );
|
||||
|
||||
let mut chains = vec![];
|
||||
for ids in event_ids {
|
||||
// TODO state store `auth_event_ids` returns self in the event ids list
|
||||
// when an event returns `auth_event_ids` self is not contained
|
||||
let chain = self
|
||||
.auth_event_ids(room_id, &ids)?
|
||||
.into_iter()
|
||||
@ -719,10 +733,7 @@ impl StateStore for TestStore {
|
||||
if let Some(chain) = chains.first() {
|
||||
let rest = chains.iter().skip(1).flatten().cloned().collect();
|
||||
let common = chain.intersection(&rest).collect::<Vec<_>>();
|
||||
// println!(
|
||||
// "COMMON {:?}",
|
||||
// common.iter().map(ToString::to_string).collect::<Vec<_>>()
|
||||
// );
|
||||
|
||||
Ok(chains
|
||||
.iter()
|
||||
.flatten()
|
||||
@ -736,3 +747,113 @@ impl StateStore for TestStore {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TestStore {
|
||||
pub fn set_up(&self) -> (StateMap<EventId>, StateMap<EventId>, StateMap<EventId>) {
|
||||
let create_event = to_pdu_event::<EventId>(
|
||||
"CREATE",
|
||||
alice(),
|
||||
EventType::RoomCreate,
|
||||
Some(""),
|
||||
json!({ "creator": alice() }),
|
||||
&[],
|
||||
&[],
|
||||
);
|
||||
let cre = create_event.event_id().unwrap().clone();
|
||||
self.0
|
||||
.borrow_mut()
|
||||
.insert(cre.clone(), create_event.clone());
|
||||
|
||||
let alice_mem = to_pdu_event(
|
||||
"IMA",
|
||||
alice(),
|
||||
EventType::RoomMember,
|
||||
Some(alice().to_string().as_str()),
|
||||
member_content_join(),
|
||||
&[cre.clone()],
|
||||
&[cre.clone()],
|
||||
);
|
||||
self.0
|
||||
.borrow_mut()
|
||||
.insert(alice_mem.event_id().unwrap().clone(), alice_mem.clone());
|
||||
|
||||
let join_rules = to_pdu_event(
|
||||
"IJR",
|
||||
alice(),
|
||||
EventType::RoomJoinRules,
|
||||
Some(""),
|
||||
json!({ "join_rule": JoinRule::Public }),
|
||||
&[cre.clone(), alice_mem.event_id().unwrap().clone()],
|
||||
&[alice_mem.event_id().unwrap().clone()],
|
||||
);
|
||||
self.0
|
||||
.borrow_mut()
|
||||
.insert(join_rules.event_id().unwrap().clone(), join_rules.clone());
|
||||
|
||||
// Bob and Charlie join at the same time, so there is a fork
|
||||
// this will be represented in the state_sets when we resolve
|
||||
let bob_mem = to_pdu_event(
|
||||
"IMB",
|
||||
bob(),
|
||||
EventType::RoomMember,
|
||||
Some(bob().to_string().as_str()),
|
||||
member_content_join(),
|
||||
&[cre.clone(), join_rules.event_id().unwrap().clone()],
|
||||
&[join_rules.event_id().unwrap().clone()],
|
||||
);
|
||||
self.0
|
||||
.borrow_mut()
|
||||
.insert(bob_mem.event_id().unwrap().clone(), bob_mem.clone());
|
||||
|
||||
let charlie_mem = to_pdu_event(
|
||||
"IMC",
|
||||
charlie(),
|
||||
EventType::RoomMember,
|
||||
Some(charlie().to_string().as_str()),
|
||||
member_content_join(),
|
||||
&[cre.clone(), join_rules.event_id().unwrap().clone()],
|
||||
&[join_rules.event_id().unwrap().clone()],
|
||||
);
|
||||
self.0
|
||||
.borrow_mut()
|
||||
.insert(charlie_mem.event_id().unwrap().clone(), charlie_mem.clone());
|
||||
|
||||
let state_at_bob = [&create_event, &alice_mem, &join_rules, &bob_mem]
|
||||
.iter()
|
||||
.map(|e| {
|
||||
(
|
||||
(e.kind(), e.state_key().unwrap().clone()),
|
||||
e.event_id().unwrap().clone(),
|
||||
)
|
||||
})
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
|
||||
let state_at_charlie = [&create_event, &alice_mem, &join_rules, &charlie_mem]
|
||||
.iter()
|
||||
.map(|e| {
|
||||
(
|
||||
(e.kind(), e.state_key().unwrap().clone()),
|
||||
e.event_id().unwrap().clone(),
|
||||
)
|
||||
})
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
|
||||
let expected = [
|
||||
&create_event,
|
||||
&alice_mem,
|
||||
&join_rules,
|
||||
&bob_mem,
|
||||
&charlie_mem,
|
||||
]
|
||||
.iter()
|
||||
.map(|e| {
|
||||
(
|
||||
(e.kind(), e.state_key().unwrap().clone()),
|
||||
e.event_id().unwrap().clone(),
|
||||
)
|
||||
})
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
|
||||
(state_at_bob, state_at_charlie, expected)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user