From c96487bde6db8294c5413beb7b5fea836560c77c Mon Sep 17 00:00:00 2001 From: mikoto Date: Tue, 13 Feb 2024 14:08:10 +0000 Subject: [PATCH] final tests for room handlers in Admin API --- .github/workflows/ci.yml | 5 +- crates/core/src/account/service.rs | 4 +- crates/matrix/src/admin/resources/room.rs | 2 +- crates/matrix/src/client/resources/room.rs | 9 +- crates/test/src/matrix/room_client.rs | 264 ++++++++++++++++++--- 5 files changed, 248 insertions(+), 36 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27d5b08..398b910 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: Continuous Integration on: push: branches: - - "*" + - main pull_request: branches: [main] paths: @@ -86,9 +86,6 @@ jobs: run: | cargo test -p test -- --test-threads=1 - - name: Code Coverage - uses: actions-rs/tarpaulin@v0.1 - - name: Print Logs if: always() run: | diff --git a/crates/core/src/account/service.rs b/crates/core/src/account/service.rs index aa32bfb..bc42d8a 100644 --- a/crates/core/src/account/service.rs +++ b/crates/core/src/account/service.rs @@ -370,6 +370,8 @@ mod test { }; let err = dto.validate().err().unwrap(); - assert!(err.to_string().contains("username cannot contain uppercase letters")); + assert!(err + .to_string() + .contains("username cannot contain uppercase letters")); } } diff --git a/crates/matrix/src/admin/resources/room.rs b/crates/matrix/src/admin/resources/room.rs index a1d4f48..1b9ce9d 100644 --- a/crates/matrix/src/admin/resources/room.rs +++ b/crates/matrix/src/admin/resources/room.rs @@ -127,7 +127,7 @@ pub struct ListResponse { #[derive(Debug, Deserialize)] pub struct MembersResponse { - pub members: Vec, + pub members: Vec, pub total: u64, } diff --git a/crates/matrix/src/client/resources/room.rs b/crates/matrix/src/client/resources/room.rs index 768c6b3..c12baf7 100644 --- a/crates/matrix/src/client/resources/room.rs +++ b/crates/matrix/src/client/resources/room.rs @@ -100,6 +100,9 @@ pub struct LeaveRoomResponse {} #[derive(Debug, Deserialize)] pub struct ForgetRoomResponse {} +#[derive(Debug, Deserialize)] +pub struct RoomKickOrBanResponse {} + #[derive(Debug, Deserialize)] pub struct MatrixError { pub errcode: String, @@ -226,7 +229,7 @@ impl Room { access_token: impl Into, room_id: &RoomId, body: RoomKickOrBanBody, - ) -> Result<()> { + ) -> Result { let mut tmp = (*client).clone(); tmp.set_token(access_token)?; @@ -255,7 +258,7 @@ impl Room { access_token: impl Into, room_id: &RoomId, body: RoomKickOrBanBody, - ) -> Result<()> { + ) -> Result { let mut tmp = (*client).clone(); tmp.set_token(access_token)?; @@ -284,7 +287,7 @@ impl Room { access_token: impl Into, room_id: &RoomId, body: RoomKickOrBanBody, - ) -> Result<()> { + ) -> Result { let mut tmp = (*client).clone(); tmp.set_token(access_token)?; diff --git a/crates/test/src/matrix/room_client.rs b/crates/test/src/matrix/room_client.rs index 8e76ad5..0cd6bec 100644 --- a/crates/test/src/matrix/room_client.rs +++ b/crates/test/src/matrix/room_client.rs @@ -63,7 +63,7 @@ async fn create_rooms(env: &Environment, accounts: &[(String, String)]) -> Vec Vec<( + OwnedRoomId, + Vec, + Vec>, + )> { let Test { env, samples, .. } = TEST.get_or_init(init).await; - let mut admin = env.client.clone(); - admin.set_token(&env.config.synapse_admin_token).unwrap(); - let mut result = Vec::with_capacity(samples.len()); for sample in samples { @@ -179,7 +180,7 @@ mod tests { let guests: Vec<_> = samples.iter().filter(|g| g.id != sample.id).collect(); let mut resps = Vec::with_capacity(guests.len()); - for guest in guests { + for guest in guests.iter() { let client = client.clone(); let resp = RoomService::join( @@ -188,26 +189,48 @@ mod tests { &OwnedRoomOrAliasId::from(sample.room_id.clone()), JoinRoomBody::default(), ) - .await - .unwrap(); + .await; resps.push(resp); } - result.push((sample.room_id.clone(), resps)); + result.push(( + sample.room_id.clone(), + guests.iter().map(|g| g.user_id.clone()).collect(), + resps, + )); } - for (room_id, resps) in result { + result + } + + #[tokio::test] + async fn join_all_rooms() { + let Test { env, .. } = TEST.get_or_init(init).await; + + let mut admin = env.client.clone(); + admin.set_token(&env.config.synapse_admin_token).unwrap(); + + // first join + let result = join_helper().await; + let rooms: Vec<_> = result.iter().map(|r| &r.0).collect(); + tracing::info!(?rooms, "joining all guests"); + + // check whether all guests are in the room and joined the expected room + for (room_id, guests, resps) in result { let mut resp = AdminRoomService::get_members(&admin, &room_id) .await .unwrap(); resp.members.sort(); - let guests: Vec<_> = samples.iter().map(|g| g.user_id.to_string()).collect(); + assert!(resps.iter().all(|r| r.is_ok())); + let resps: Vec<_> = resps.into_iter().flatten().collect(); - assert!(resps.iter().all(|r| r.room_id.clone() == room_id)); + assert!(resps.iter().all(|r| r.room_id == *room_id)); - assert_eq!(guests, resp.members); + for guest in guests { + assert!(resp.members.contains(&guest)); + } } } @@ -241,6 +264,7 @@ mod tests { result.push(sample.room_id.clone()); } + // check whether all guests left the room for room_id in result { let resp = AdminRoomService::get_members(&admin, &room_id) .await @@ -248,12 +272,12 @@ mod tests { assert_eq!(resp.members.len(), 1); assert_eq!( - &samples + &[samples .iter() .find(|s| s.room_id == room_id) - .map(|s| s.user_id.to_string()) - .unwrap(), - resp.members.first().unwrap() + .map(|s| s.user_id.clone()) + .unwrap()], + resp.members.as_slice() ); } } @@ -265,8 +289,6 @@ mod tests { let mut admin = env.client.clone(); admin.set_token(&env.config.synapse_admin_token).unwrap(); - let mut result = Vec::with_capacity(samples.len()); - for sample in samples { let client = env.client.clone(); @@ -284,24 +306,212 @@ mod tests { .await .unwrap(); } + } - result.push(sample.room_id.clone()); + // check whether all guests are still not present anymore the room + for sample in samples { + let room_id = &sample.room_id; + + let resp = AdminRoomService::get_members(&admin, room_id) + .await + .unwrap(); + + assert_eq!(resp.members.len(), 1); + assert_eq!( + &[samples + .iter() + .find(|s| &s.room_id == room_id) + .map(|s| s.user_id.clone()) + .unwrap()], + resp.members.as_slice() + ); } - for room_id in result { + // confirm a room can't be forgotten if we didn't leave first + for sample in samples { + let client = env.client.clone(); + let room_id = &sample.room_id; + + let resp = RoomService::forget( + &client, + sample.access_token.clone(), + room_id, + ForgetRoomBody::default(), + ) + .await; + + assert!(resp.is_err()); + } + } + + #[tokio::test] + async fn kick_all_guests() { + let Test { env, samples, .. } = TEST.get_or_init(init).await; + + let mut admin = env.client.clone(); + admin.set_token(&env.config.synapse_admin_token).unwrap(); + + // second join + let result = join_helper().await; + let rooms: Vec<_> = result.iter().map(|r| &r.0).collect(); + tracing::info!(?rooms, "joining all guests"); + + // check whether all guests are in the room and joined the expected room + for (room_id, guests, resps) in result.iter() { + let mut resp = AdminRoomService::get_members(&admin, room_id) + .await + .unwrap(); + resp.members.sort(); + + assert!(resps.iter().all(|r| r.is_ok())); + let resps: Vec<_> = resps.iter().flatten().collect(); + + assert!(resps.iter().all(|r| r.room_id == *room_id)); + + for guest in guests { + assert!(resp.members.contains(guest)); + } + } + + for sample in samples { + let client = env.client.clone(); + let room_id = &sample.room_id; + + let guests: Vec<_> = samples.iter().filter(|g| g.id != sample.id).collect(); + + for guest in guests { + let client = client.clone(); + + RoomService::kick( + &client, + guest.access_token.clone(), + room_id, + RoomKickOrBanBody { + reason: Default::default(), + user_id: guest.user_id.clone(), + }, + ) + .await + .unwrap(); + } + } + + // check whether all guests left the room + for (room_id, _, _) in result { + let resp = AdminRoomService::get_members(&admin, &room_id) + .await + .unwrap(); + + assert_eq!(resp.members.len(), 1); + assert_eq!( + &[samples + .iter() + .find(|s| s.room_id == room_id) + .map(|s| s.user_id.clone()) + .unwrap()], + resp.members.as_slice() + ); + } + } + + #[tokio::test] + async fn ban_all_guests() { + let Test { env, samples, .. } = TEST.get_or_init(init).await; + + let mut admin = env.client.clone(); + admin.set_token(&env.config.synapse_admin_token).unwrap(); + + // third join + let result = join_helper().await; + let rooms: Vec<_> = result.iter().map(|r| &r.0).collect(); + tracing::info!(?rooms, "joining all guests"); + + // check whether all guests are in the room and joined the expected room + for (room_id, guests, resps) in result.iter() { + let mut resp = AdminRoomService::get_members(&admin, room_id) + .await + .unwrap(); + resp.members.sort(); + + assert!(resps.iter().all(|r| r.is_ok())); + let resps: Vec<_> = resps.iter().flatten().collect(); + + assert!(resps.iter().all(|r| r.room_id == *room_id)); + + for guest in guests { + assert!(resp.members.contains(guest)); + } + } + + for sample in samples { + let client = env.client.clone(); + + let guests: Vec<_> = samples.iter().filter(|g| g.id != sample.id).collect(); + + for guest in guests { + let client = client.clone(); + let room_id = &sample.room_id; + + RoomService::ban( + &client, + sample.access_token.clone(), + room_id, + RoomKickOrBanBody { + reason: Default::default(), + user_id: guest.user_id.clone(), + }, + ) + .await + .unwrap(); + } + } + + // fourth join + let result = join_helper().await; + let rooms: Vec<_> = result.iter().map(|r| &r.0).collect(); + tracing::info!(?rooms, "joining all guests"); + + // check whether all guests got banned from the room + // check whether their join request failed + for (room_id, _, resps) in result { let resp = AdminRoomService::get_members(&admin, &room_id) .await .unwrap(); assert_eq!(resp.members.len(), 1); assert_eq!( - &samples + &[samples .iter() .find(|s| s.room_id == room_id) - .map(|s| s.user_id.to_string()) - .unwrap(), - resp.members.first().unwrap() + .map(|s| s.user_id.clone()) + .unwrap()], + resp.members.as_slice() ); + + assert!(resps.iter().all(|r| r.is_err())); + } + + for sample in samples { + let client = env.client.clone(); + + let guests: Vec<_> = samples.iter().filter(|g| g.id != sample.id).collect(); + + for guest in guests { + let client = client.clone(); + let room_id = &sample.room_id; + + RoomService::unban( + &client, + sample.access_token.clone(), + room_id, + RoomKickOrBanBody { + reason: Default::default(), + user_id: guest.user_id.clone(), + }, + ) + .await + .unwrap(); + } } } }