sync hierarchy over federation MR
Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
parent
bd69d9b565
commit
3efb3a93ca
1 changed files with 211 additions and 169 deletions
|
@ -1,4 +1,7 @@
|
||||||
use std::str::FromStr;
|
use std::{
|
||||||
|
fmt::{Display, Formatter},
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
use lru_cache::LruCache;
|
use lru_cache::LruCache;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
|
@ -24,7 +27,7 @@ use ruma::{
|
||||||
},
|
},
|
||||||
serde::Raw,
|
serde::Raw,
|
||||||
space::SpaceRoomJoinRule,
|
space::SpaceRoomJoinRule,
|
||||||
OwnedRoomId, RoomId, ServerName, UInt, UserId,
|
OwnedRoomId, OwnedServerName, RoomId, ServerName, UInt, UserId,
|
||||||
};
|
};
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tracing::{debug, error, warn};
|
use tracing::{debug, error, warn};
|
||||||
|
@ -58,6 +61,7 @@ pub struct Node {
|
||||||
// o o o o
|
// o o o o
|
||||||
first_child: Option<NodeId>,
|
first_child: Option<NodeId>,
|
||||||
pub room_id: OwnedRoomId,
|
pub room_id: OwnedRoomId,
|
||||||
|
pub via: Vec<OwnedServerName>,
|
||||||
traversed: bool,
|
traversed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +137,7 @@ impl Arena {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds all the given nodes as children of the parent node
|
/// Adds all the given nodes as children of the parent node
|
||||||
fn push(&mut self, parent: NodeId, mut children: Vec<OwnedRoomId>) {
|
fn push(&mut self, parent: NodeId, mut children: Vec<(OwnedRoomId, Vec<OwnedServerName>)>) {
|
||||||
if children.is_empty() {
|
if children.is_empty() {
|
||||||
self.traverse(parent);
|
self.traverse(parent);
|
||||||
} else if self.nodes.get(parent.index).is_some() {
|
} else if self.nodes.get(parent.index).is_some() {
|
||||||
|
@ -166,7 +170,7 @@ impl Arena {
|
||||||
|
|
||||||
let mut next_id = None;
|
let mut next_id = None;
|
||||||
|
|
||||||
for child in children {
|
for (child, via) in children {
|
||||||
// Prevent adding a child which is a parent (recursion)
|
// Prevent adding a child which is a parent (recursion)
|
||||||
if !parents.iter().any(|parent| parent.1 == child) {
|
if !parents.iter().any(|parent| parent.1 == child) {
|
||||||
self.nodes.push(Node {
|
self.nodes.push(Node {
|
||||||
|
@ -175,6 +179,7 @@ impl Arena {
|
||||||
first_child: None,
|
first_child: None,
|
||||||
room_id: child,
|
room_id: child,
|
||||||
traversed: false,
|
traversed: false,
|
||||||
|
via,
|
||||||
});
|
});
|
||||||
|
|
||||||
next_id = Some(NodeId {
|
next_id = Some(NodeId {
|
||||||
|
@ -214,6 +219,7 @@ impl Arena {
|
||||||
first_child: None,
|
first_child: None,
|
||||||
room_id: root,
|
room_id: root,
|
||||||
traversed: zero_depth,
|
traversed: zero_depth,
|
||||||
|
via: vec![],
|
||||||
}],
|
}],
|
||||||
max_depth,
|
max_depth,
|
||||||
first_untraversed: if zero_depth {
|
first_untraversed: if zero_depth {
|
||||||
|
@ -273,8 +279,8 @@ impl FromStr for PagnationToken {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for PagnationToken {
|
impl Display for PagnationToken {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}_{}_{}_{}", self.skip, self.limit, self.max_depth, self.suggested_only)
|
write!(f, "{}_{}_{}_{}", self.skip, self.limit, self.max_depth, self.suggested_only)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,16 +342,16 @@ impl Service {
|
||||||
&self, room_id: &RoomId, server_name: &ServerName, suggested_only: bool,
|
&self, room_id: &RoomId, server_name: &ServerName, suggested_only: bool,
|
||||||
) -> Result<federation::space::get_hierarchy::v1::Response> {
|
) -> Result<federation::space::get_hierarchy::v1::Response> {
|
||||||
match self
|
match self
|
||||||
.get_summary_and_children(&room_id.to_owned(), suggested_only, Identifier::None)
|
.get_summary_and_children_local(&room_id.to_owned(), Identifier::None)
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
Some(SummaryAccessibility::Accessible(room)) => {
|
Some(SummaryAccessibility::Accessible(room)) => {
|
||||||
let mut children = Vec::new();
|
let mut children = Vec::new();
|
||||||
let mut inaccessible_children = Vec::new();
|
let mut inaccessible_children = Vec::new();
|
||||||
|
|
||||||
for child in get_parent_children(&room.clone(), suggested_only) {
|
for (child, _via) in get_parent_children_via(&room, suggested_only) {
|
||||||
match self
|
match self
|
||||||
.get_summary_and_children(&child, suggested_only, Identifier::ServerName(server_name))
|
.get_summary_and_children_local(&child, Identifier::ServerName(server_name))
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
Some(SummaryAccessibility::Accessible(summary)) => {
|
Some(SummaryAccessibility::Accessible(summary)) => {
|
||||||
|
@ -371,8 +377,8 @@ impl Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_summary_and_children(
|
async fn get_summary_and_children_local(
|
||||||
&self, current_room: &OwnedRoomId, suggested_only: bool, identifier: Identifier<'_>,
|
&self, current_room: &OwnedRoomId, identifier: Identifier<'_>,
|
||||||
) -> Result<Option<SummaryAccessibility>> {
|
) -> Result<Option<SummaryAccessibility>> {
|
||||||
if let Some(cached) = self
|
if let Some(cached) = self
|
||||||
.roomid_spacehierarchy_cache
|
.roomid_spacehierarchy_cache
|
||||||
|
@ -399,7 +405,7 @@ impl Service {
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
if let Some(children_pdus) = get_stripped_space_child_events(current_room).await? {
|
if let Some(children_pdus) = get_stripped_space_child_events(current_room).await? {
|
||||||
let summary = self.get_room_summary(current_room, children_pdus, &identifier);
|
let summary = Self::get_room_summary(current_room, children_pdus, &identifier);
|
||||||
if let Ok(summary) = summary {
|
if let Ok(summary) = summary {
|
||||||
self.roomid_spacehierarchy_cache.lock().await.insert(
|
self.roomid_spacehierarchy_cache.lock().await.insert(
|
||||||
current_room.clone(),
|
current_room.clone(),
|
||||||
|
@ -410,96 +416,6 @@ impl Service {
|
||||||
|
|
||||||
Some(SummaryAccessibility::Accessible(Box::new(summary)))
|
Some(SummaryAccessibility::Accessible(Box::new(summary)))
|
||||||
} else {
|
} else {
|
||||||
None
|
|
||||||
}
|
|
||||||
// Federation requests should not request information from other
|
|
||||||
// servers
|
|
||||||
} else if let Identifier::UserId(_) = identifier {
|
|
||||||
let server = current_room
|
|
||||||
.server_name()
|
|
||||||
.expect("Room IDs should always have a server name");
|
|
||||||
if server == services().globals.server_name() {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("Asking {server} for /hierarchy");
|
|
||||||
if let Ok(response) = services()
|
|
||||||
.sending
|
|
||||||
.send_federation_request(
|
|
||||||
server,
|
|
||||||
federation::space::get_hierarchy::v1::Request {
|
|
||||||
room_id: current_room.to_owned(),
|
|
||||||
suggested_only,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
debug!("Got response from {server} for /hierarchy\n{response:?}");
|
|
||||||
let summary = response.room.clone();
|
|
||||||
|
|
||||||
self.roomid_spacehierarchy_cache.lock().await.insert(
|
|
||||||
current_room.clone(),
|
|
||||||
Some(CachedSpaceHierarchySummary {
|
|
||||||
summary: summary.clone(),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
for child in response.children {
|
|
||||||
let mut guard = self.roomid_spacehierarchy_cache.lock().await;
|
|
||||||
if !guard.contains_key(current_room) {
|
|
||||||
guard.insert(
|
|
||||||
current_room.clone(),
|
|
||||||
Some(CachedSpaceHierarchySummary {
|
|
||||||
summary: {
|
|
||||||
let SpaceHierarchyChildSummary {
|
|
||||||
canonical_alias,
|
|
||||||
name,
|
|
||||||
num_joined_members,
|
|
||||||
room_id,
|
|
||||||
topic,
|
|
||||||
world_readable,
|
|
||||||
guest_can_join,
|
|
||||||
avatar_url,
|
|
||||||
join_rule,
|
|
||||||
room_type,
|
|
||||||
allowed_room_ids,
|
|
||||||
} = child;
|
|
||||||
|
|
||||||
SpaceHierarchyParentSummary {
|
|
||||||
canonical_alias,
|
|
||||||
name,
|
|
||||||
num_joined_members,
|
|
||||||
room_id: room_id.clone(),
|
|
||||||
topic,
|
|
||||||
world_readable,
|
|
||||||
guest_can_join,
|
|
||||||
avatar_url,
|
|
||||||
join_rule,
|
|
||||||
room_type,
|
|
||||||
children_state: get_stripped_space_child_events(&room_id).await?.unwrap(),
|
|
||||||
allowed_room_ids,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if is_accessable_child(
|
|
||||||
current_room,
|
|
||||||
&response.room.join_rule,
|
|
||||||
&identifier,
|
|
||||||
&response.room.allowed_room_ids,
|
|
||||||
)? {
|
|
||||||
Some(SummaryAccessibility::Accessible(Box::new(summary.clone())))
|
|
||||||
} else {
|
|
||||||
Some(SummaryAccessibility::Inaccessible)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.roomid_spacehierarchy_cache
|
|
||||||
.lock()
|
|
||||||
.await
|
|
||||||
.insert(current_room.clone(), None);
|
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -508,9 +424,108 @@ impl Service {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_summary_and_children_federation(
|
||||||
|
&self, current_room: &OwnedRoomId, suggested_only: bool, user_id: &UserId, via: &Vec<OwnedServerName>,
|
||||||
|
) -> Result<Option<SummaryAccessibility>> {
|
||||||
|
for server in via {
|
||||||
|
debug!("Asking {server} for /hierarchy");
|
||||||
|
if let Ok(response) = services()
|
||||||
|
.sending
|
||||||
|
.send_federation_request(
|
||||||
|
server,
|
||||||
|
federation::space::get_hierarchy::v1::Request {
|
||||||
|
room_id: current_room.to_owned(),
|
||||||
|
suggested_only,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
debug!("Got response from {server} for /hierarchy\n{response:?}");
|
||||||
|
let summary = response.room.clone();
|
||||||
|
|
||||||
|
self.roomid_spacehierarchy_cache.lock().await.insert(
|
||||||
|
current_room.clone(),
|
||||||
|
Some(CachedSpaceHierarchySummary {
|
||||||
|
summary: summary.clone(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
for child in response.children {
|
||||||
|
let mut guard = self.roomid_spacehierarchy_cache.lock().await;
|
||||||
|
if !guard.contains_key(current_room) {
|
||||||
|
guard.insert(
|
||||||
|
current_room.clone(),
|
||||||
|
Some(CachedSpaceHierarchySummary {
|
||||||
|
summary: {
|
||||||
|
let SpaceHierarchyChildSummary {
|
||||||
|
canonical_alias,
|
||||||
|
name,
|
||||||
|
num_joined_members,
|
||||||
|
room_id,
|
||||||
|
topic,
|
||||||
|
world_readable,
|
||||||
|
guest_can_join,
|
||||||
|
avatar_url,
|
||||||
|
join_rule,
|
||||||
|
room_type,
|
||||||
|
allowed_room_ids,
|
||||||
|
} = child;
|
||||||
|
|
||||||
|
SpaceHierarchyParentSummary {
|
||||||
|
canonical_alias,
|
||||||
|
name,
|
||||||
|
num_joined_members,
|
||||||
|
room_id: room_id.clone(),
|
||||||
|
topic,
|
||||||
|
world_readable,
|
||||||
|
guest_can_join,
|
||||||
|
avatar_url,
|
||||||
|
join_rule,
|
||||||
|
room_type,
|
||||||
|
children_state: get_stripped_space_child_events(&room_id).await?.unwrap(),
|
||||||
|
allowed_room_ids,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if is_accessable_child(
|
||||||
|
current_room,
|
||||||
|
&response.room.join_rule,
|
||||||
|
&Identifier::UserId(user_id),
|
||||||
|
&response.room.allowed_room_ids,
|
||||||
|
)? {
|
||||||
|
return Ok(Some(SummaryAccessibility::Accessible(Box::new(summary.clone()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(Some(SummaryAccessibility::Inaccessible));
|
||||||
|
}
|
||||||
|
|
||||||
|
self.roomid_spacehierarchy_cache
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.insert(current_room.clone(), None);
|
||||||
|
}
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_summary_and_children_client(
|
||||||
|
&self, current_room: &OwnedRoomId, suggested_only: bool, user_id: &UserId, via: &Vec<OwnedServerName>,
|
||||||
|
) -> Result<Option<SummaryAccessibility>> {
|
||||||
|
if let Ok(Some(response)) = self
|
||||||
|
.get_summary_and_children_local(current_room, Identifier::UserId(user_id))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(Some(response))
|
||||||
|
} else {
|
||||||
|
self.get_summary_and_children_federation(current_room, suggested_only, user_id, via)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_room_summary(
|
fn get_room_summary(
|
||||||
&self, current_room: &OwnedRoomId, children_state: Vec<Raw<HierarchySpaceChildEvent>>,
|
current_room: &OwnedRoomId, children_state: Vec<Raw<HierarchySpaceChildEvent>>, identifier: &Identifier<'_>,
|
||||||
identifier: &Identifier<'_>,
|
|
||||||
) -> Result<SpaceHierarchyParentSummary, Error> {
|
) -> Result<SpaceHierarchyParentSummary, Error> {
|
||||||
let room_id: &RoomId = current_room;
|
let room_id: &RoomId = current_room;
|
||||||
|
|
||||||
|
@ -611,7 +626,15 @@ impl Service {
|
||||||
suggested_only: bool,
|
suggested_only: bool,
|
||||||
) -> Result<client::space::get_hierarchy::v1::Response> {
|
) -> Result<client::space::get_hierarchy::v1::Response> {
|
||||||
match self
|
match self
|
||||||
.get_summary_and_children(&room_id.to_owned(), suggested_only, Identifier::UserId(sender_user))
|
.get_summary_and_children_client(
|
||||||
|
&room_id.to_owned(),
|
||||||
|
suggested_only,
|
||||||
|
sender_user,
|
||||||
|
&match room_id.server_name() {
|
||||||
|
Some(server_name) => vec![server_name.into()],
|
||||||
|
None => vec![],
|
||||||
|
},
|
||||||
|
)
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
Some(SummaryAccessibility::Accessible(summary)) => {
|
Some(SummaryAccessibility::Accessible(summary)) => {
|
||||||
|
@ -623,23 +646,23 @@ impl Service {
|
||||||
.first_untraversed()
|
.first_untraversed()
|
||||||
.expect("The node just added is not traversed");
|
.expect("The node just added is not traversed");
|
||||||
|
|
||||||
arena.push(root, get_parent_children(&summary.clone(), suggested_only));
|
arena.push(root, get_parent_children_via(&summary, suggested_only));
|
||||||
results.push(summary_to_chunk(*summary.clone()));
|
if left_to_skip > 0 {
|
||||||
|
left_to_skip -= 1;
|
||||||
|
} else {
|
||||||
|
results.push(summary_to_chunk(*summary.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
while let Some(current_room) = arena.first_untraversed() {
|
while let Some(current_room) = arena.first_untraversed() {
|
||||||
if limit > results.len() {
|
if limit > results.len() {
|
||||||
|
let node = arena
|
||||||
|
.get(current_room)
|
||||||
|
.expect("We added this node, it must exist");
|
||||||
if let Some(SummaryAccessibility::Accessible(summary)) = self
|
if let Some(SummaryAccessibility::Accessible(summary)) = self
|
||||||
.get_summary_and_children(
|
.get_summary_and_children_client(&node.room_id, suggested_only, sender_user, &node.via)
|
||||||
&arena
|
|
||||||
.get(current_room)
|
|
||||||
.expect("We added this node, it must exist")
|
|
||||||
.room_id,
|
|
||||||
suggested_only,
|
|
||||||
Identifier::UserId(sender_user),
|
|
||||||
)
|
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
let children = get_parent_children(&summary.clone(), suggested_only);
|
let children = get_parent_children_via(&summary, suggested_only);
|
||||||
arena.push(current_room, children);
|
arena.push(current_room, children);
|
||||||
|
|
||||||
if left_to_skip > 0 {
|
if left_to_skip > 0 {
|
||||||
|
@ -736,6 +759,7 @@ fn is_accessable_child_recurse(
|
||||||
allowed_room_ids: &Vec<OwnedRoomId>, recurse_num: usize,
|
allowed_room_ids: &Vec<OwnedRoomId>, recurse_num: usize,
|
||||||
) -> Result<bool, Error> {
|
) -> Result<bool, Error> {
|
||||||
// Set limit at 10, as we cannot keep going up parents forever
|
// Set limit at 10, as we cannot keep going up parents forever
|
||||||
|
// and it is very unlikely to have 10 space parents
|
||||||
if recurse_num < 10 {
|
if recurse_num < 10 {
|
||||||
match identifier {
|
match identifier {
|
||||||
Identifier::ServerName(server_name) => {
|
Identifier::ServerName(server_name) => {
|
||||||
|
@ -767,10 +791,9 @@ fn is_accessable_child_recurse(
|
||||||
Identifier::None => (),
|
Identifier::None => (),
|
||||||
} // Takes care of joinrules
|
} // Takes care of joinrules
|
||||||
Ok(match join_rule {
|
Ok(match join_rule {
|
||||||
SpaceRoomJoinRule::KnockRestricted | SpaceRoomJoinRule::Restricted => {
|
SpaceRoomJoinRule::Restricted => {
|
||||||
for room in allowed_room_ids {
|
for room in allowed_room_ids {
|
||||||
if let Ok((join_rule, allowed_room_ids)) = get_join_rule(room) {
|
if let Ok((join_rule, allowed_room_ids)) = get_join_rule(room) {
|
||||||
// Recursive, get rid of if possible
|
|
||||||
if let Ok(true) = is_accessable_child_recurse(
|
if let Ok(true) = is_accessable_child_recurse(
|
||||||
room,
|
room,
|
||||||
&join_rule,
|
&join_rule,
|
||||||
|
@ -784,9 +807,8 @@ fn is_accessable_child_recurse(
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
},
|
},
|
||||||
SpaceRoomJoinRule::Public | SpaceRoomJoinRule::Knock => true,
|
SpaceRoomJoinRule::Public | SpaceRoomJoinRule::Knock | SpaceRoomJoinRule::KnockRestricted => true,
|
||||||
// SpaceRoomJoinRule::Invite | SpaceRoomJoinRule::Private => false,
|
// Custom join rules, Invite, or Private
|
||||||
// Custom join rules, Invites, or Private
|
|
||||||
_ => false,
|
_ => false,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -890,7 +912,9 @@ fn allowed_room_ids(join_rule: JoinRule) -> Vec<OwnedRoomId> {
|
||||||
|
|
||||||
/// Returns the children of a SpaceHierarchyParentSummary, making use of the
|
/// Returns the children of a SpaceHierarchyParentSummary, making use of the
|
||||||
/// children_state field
|
/// children_state field
|
||||||
fn get_parent_children(parent: &SpaceHierarchyParentSummary, suggested_only: bool) -> Vec<OwnedRoomId> {
|
fn get_parent_children_via(
|
||||||
|
parent: &SpaceHierarchyParentSummary, suggested_only: bool,
|
||||||
|
) -> Vec<(OwnedRoomId, Vec<OwnedServerName>)> {
|
||||||
parent
|
parent
|
||||||
.children_state
|
.children_state
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -899,7 +923,7 @@ fn get_parent_children(parent: &SpaceHierarchyParentSummary, suggested_only: boo
|
||||||
if suggested_only && !ce.content.suggested {
|
if suggested_only && !ce.content.suggested {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(ce.state_key)
|
Some((ce.state_key, ce.content.via))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -910,14 +934,15 @@ fn get_parent_children(parent: &SpaceHierarchyParentSummary, suggested_only: boo
|
||||||
mod tests {
|
mod tests {
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::federation::space::SpaceHierarchyParentSummaryInit, events::room::join_rules::Restricted, owned_room_id,
|
api::federation::space::SpaceHierarchyParentSummaryInit, events::room::join_rules::Restricted, owned_room_id,
|
||||||
|
owned_server_name,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
fn first(arena: &mut Arena, room_id: &OwnedRoomId) {
|
fn first(arena: &mut Arena, room_id: OwnedRoomId) {
|
||||||
let first_untrav = arena.first_untraversed().unwrap();
|
let first_untrav = arena.first_untraversed().unwrap();
|
||||||
|
|
||||||
assert_eq!(&arena.get(first_untrav).unwrap().room_id, room_id);
|
assert_eq!(arena.get(first_untrav).unwrap().room_id, room_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -935,9 +960,9 @@ mod tests {
|
||||||
arena.push(
|
arena.push(
|
||||||
root,
|
root,
|
||||||
vec![
|
vec![
|
||||||
owned_room_id!("!subspace1:example.org"),
|
(owned_room_id!("!subspace1:example.org"), vec![]),
|
||||||
owned_room_id!("!subspace2:example.org"),
|
(owned_room_id!("!subspace2:example.org"), vec![]),
|
||||||
owned_room_id!("!foo:example.org"),
|
(owned_room_id!("!foo:example.org"), vec![]),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -946,19 +971,24 @@ mod tests {
|
||||||
|
|
||||||
arena.push(
|
arena.push(
|
||||||
subspace1,
|
subspace1,
|
||||||
vec![owned_room_id!("!room1:example.org"), owned_room_id!("!room2:example.org")],
|
vec![
|
||||||
|
(owned_room_id!("!room1:example.org"), vec![]),
|
||||||
|
(owned_room_id!("!room2:example.org"), vec![]),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
first(&mut arena, &owned_room_id!("!room1:example.org"));
|
first(&mut arena, owned_room_id!("!room1:example.org"));
|
||||||
first(&mut arena, &owned_room_id!("!room2:example.org"));
|
first(&mut arena, owned_room_id!("!room2:example.org"));
|
||||||
|
|
||||||
arena.push(
|
arena.push(
|
||||||
subspace2,
|
subspace2,
|
||||||
vec![owned_room_id!("!room3:example.org"), owned_room_id!("!room4:example.org")],
|
vec![
|
||||||
|
(owned_room_id!("!room3:example.org"), vec![]),
|
||||||
|
(owned_room_id!("!room4:example.org"), vec![]),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
first(&mut arena, owned_room_id!("!room3:example.org"));
|
||||||
first(&mut arena, &owned_room_id!("!room3:example.org"));
|
first(&mut arena, owned_room_id!("!room4:example.org"));
|
||||||
first(&mut arena, &owned_room_id!("!room4:example.org"));
|
|
||||||
|
|
||||||
let foo_node = NodeId {
|
let foo_node = NodeId {
|
||||||
index: 1,
|
index: 1,
|
||||||
|
@ -978,13 +1008,16 @@ mod tests {
|
||||||
let root = arena.first_untraversed().unwrap();
|
let root = arena.first_untraversed().unwrap();
|
||||||
arena.push(
|
arena.push(
|
||||||
root,
|
root,
|
||||||
vec![owned_room_id!("!room1:example.org"), owned_room_id!("!room2:example.org")],
|
vec![
|
||||||
|
(owned_room_id!("!room1:example.org"), vec![]),
|
||||||
|
(owned_room_id!("!room2:example.org"), vec![]),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
let room1 = arena.first_untraversed().unwrap();
|
let room1 = arena.first_untraversed().unwrap();
|
||||||
arena.push(room1, vec![]);
|
arena.push(room1, vec![]);
|
||||||
|
|
||||||
first(&mut arena, &owned_room_id!("!room2:example.org"));
|
first(&mut arena, owned_room_id!("!room2:example.org"));
|
||||||
assert!(arena.first_untraversed().is_none());
|
assert!(arena.first_untraversed().is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -996,7 +1029,7 @@ mod tests {
|
||||||
index: 0,
|
index: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
arena.push(root, vec![owned_room_id!("!too_deep:example.org")]);
|
arena.push(root, vec![(owned_room_id!("!too_deep:example.org"), vec![])]);
|
||||||
|
|
||||||
assert_eq!(arena.first_child(root), None);
|
assert_eq!(arena.first_child(root), None);
|
||||||
assert_eq!(arena.nodes.len(), 1);
|
assert_eq!(arena.nodes.len(), 1);
|
||||||
|
@ -1010,9 +1043,9 @@ mod tests {
|
||||||
arena.push(
|
arena.push(
|
||||||
root,
|
root,
|
||||||
vec![
|
vec![
|
||||||
owned_room_id!("!subspace1:example.org"),
|
(owned_room_id!("!subspace1:example.org"), vec![]),
|
||||||
owned_room_id!("!subspace2:example.org"),
|
(owned_room_id!("!subspace2:example.org"), vec![]),
|
||||||
owned_room_id!("!foo:example.org"),
|
(owned_room_id!("!foo:example.org"), vec![]),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1020,15 +1053,15 @@ mod tests {
|
||||||
arena.push(
|
arena.push(
|
||||||
subspace1,
|
subspace1,
|
||||||
vec![
|
vec![
|
||||||
owned_room_id!("!room1:example.org"),
|
(owned_room_id!("!room1:example.org"), vec![]),
|
||||||
owned_room_id!("!room3:example.org"),
|
(owned_room_id!("!room3:example.org"), vec![]),
|
||||||
owned_room_id!("!room5:example.org"),
|
(owned_room_id!("!room5:example.org"), vec![]),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
first(&mut arena, &owned_room_id!("!room1:example.org"));
|
first(&mut arena, owned_room_id!("!room1:example.org"));
|
||||||
first(&mut arena, &owned_room_id!("!room3:example.org"));
|
first(&mut arena, owned_room_id!("!room3:example.org"));
|
||||||
first(&mut arena, &owned_room_id!("!room5:example.org"));
|
first(&mut arena, owned_room_id!("!room5:example.org"));
|
||||||
|
|
||||||
let subspace2 = arena.first_untraversed().unwrap();
|
let subspace2 = arena.first_untraversed().unwrap();
|
||||||
|
|
||||||
|
@ -1036,12 +1069,15 @@ mod tests {
|
||||||
|
|
||||||
arena.push(
|
arena.push(
|
||||||
subspace2,
|
subspace2,
|
||||||
vec![owned_room_id!("!room1:example.org"), owned_room_id!("!room2:example.org")],
|
vec![
|
||||||
|
(owned_room_id!("!room1:example.org"), vec![]),
|
||||||
|
(owned_room_id!("!room2:example.org"), vec![]),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
first(&mut arena, &owned_room_id!("!room1:example.org"));
|
first(&mut arena, owned_room_id!("!room1:example.org"));
|
||||||
first(&mut arena, &owned_room_id!("!room2:example.org"));
|
first(&mut arena, owned_room_id!("!room2:example.org"));
|
||||||
first(&mut arena, &owned_room_id!("!foo:example.org"));
|
first(&mut arena, owned_room_id!("!foo:example.org"));
|
||||||
|
|
||||||
assert_eq!(arena.first_untraversed(), None);
|
assert_eq!(arena.first_untraversed(), None);
|
||||||
}
|
}
|
||||||
|
@ -1105,18 +1141,21 @@ mod tests {
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_parent_children(&summary, false),
|
get_parent_children_via(&summary, false),
|
||||||
vec![
|
vec![
|
||||||
owned_room_id!("!foo:example.org"),
|
(owned_room_id!("!foo:example.org"), vec![owned_server_name!("example.org")]),
|
||||||
owned_room_id!("!bar:example.org"),
|
(owned_room_id!("!bar:example.org"), vec![owned_server_name!("example.org")]),
|
||||||
owned_room_id!("!baz:example.org")
|
(owned_room_id!("!baz:example.org"), vec![owned_server_name!("example.org")])
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
assert_eq!(get_parent_children(&summary, true), vec![owned_room_id!("!bar:example.org")]);
|
assert_eq!(
|
||||||
|
get_parent_children_via(&summary, true),
|
||||||
|
vec![(owned_room_id!("!bar:example.org"), vec![owned_server_name!("example.org")])]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn allowed_room_ids_rom_join_rule() {
|
fn allowed_room_ids_from_join_rule() {
|
||||||
let restricted_join_rule = JoinRule::Restricted(Restricted {
|
let restricted_join_rule = JoinRule::Restricted(Restricted {
|
||||||
allow: vec![
|
allow: vec![
|
||||||
AllowRule::RoomMembership(RoomMembership {
|
AllowRule::RoomMembership(RoomMembership {
|
||||||
|
@ -1151,7 +1190,7 @@ mod tests {
|
||||||
fn invalid_pagnation_tokens() {
|
fn invalid_pagnation_tokens() {
|
||||||
fn token_is_err(token: &str) {
|
fn token_is_err(token: &str) {
|
||||||
let token: Result<PagnationToken> = PagnationToken::from_str(token);
|
let token: Result<PagnationToken> = PagnationToken::from_str(token);
|
||||||
token.unwrap_err();
|
assert!(token.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
token_is_err("231_2_noabool");
|
token_is_err("231_2_noabool");
|
||||||
|
@ -1219,16 +1258,19 @@ mod tests {
|
||||||
arena.push(
|
arena.push(
|
||||||
root_node_id,
|
root_node_id,
|
||||||
vec![
|
vec![
|
||||||
owned_room_id!("!subspace1:example.org"),
|
(owned_room_id!("!subspace1:example.org"), vec![]),
|
||||||
owned_room_id!("!room1:example.org"),
|
(owned_room_id!("!room1:example.org"), vec![]),
|
||||||
owned_room_id!("!subspace2:example.org"),
|
(owned_room_id!("!subspace2:example.org"), vec![]),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
let subspace1_node_id = arena.first_untraversed().unwrap();
|
let subspace1_node_id = arena.first_untraversed().unwrap();
|
||||||
arena.push(
|
arena.push(
|
||||||
subspace1_node_id,
|
subspace1_node_id,
|
||||||
vec![owned_room_id!("!subspace2:example.org"), owned_room_id!("!room1:example.org")],
|
vec![
|
||||||
|
(owned_room_id!("!subspace2:example.org"), vec![]),
|
||||||
|
(owned_room_id!("!room1:example.org"), vec![]),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
let subspace2_node_id = arena.first_untraversed().unwrap();
|
let subspace2_node_id = arena.first_untraversed().unwrap();
|
||||||
|
@ -1237,17 +1279,17 @@ mod tests {
|
||||||
arena.push(
|
arena.push(
|
||||||
subspace2_node_id,
|
subspace2_node_id,
|
||||||
vec![
|
vec![
|
||||||
owned_room_id!("!subspace1:example.org"),
|
(owned_room_id!("!subspace1:example.org"), vec![]),
|
||||||
owned_room_id!("!subspace2:example.org"),
|
(owned_room_id!("!subspace2:example.org"), vec![]),
|
||||||
owned_room_id!("!room1:example.org"),
|
(owned_room_id!("!room1:example.org"), vec![]),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(arena.nodes.len(), 7);
|
assert_eq!(arena.nodes.len(), 7);
|
||||||
first(&mut arena, &owned_room_id!("!room1:example.org"));
|
first(&mut arena, owned_room_id!("!room1:example.org"));
|
||||||
first(&mut arena, &owned_room_id!("!room1:example.org"));
|
first(&mut arena, owned_room_id!("!room1:example.org"));
|
||||||
first(&mut arena, &owned_room_id!("!room1:example.org"));
|
first(&mut arena, owned_room_id!("!room1:example.org"));
|
||||||
first(&mut arena, &owned_room_id!("!subspace2:example.org"));
|
first(&mut arena, owned_room_id!("!subspace2:example.org"));
|
||||||
assert!(arena.first_untraversed().is_none());
|
assert!(arena.first_untraversed().is_none());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue