From dab2960e115358188af37deafc4c63adc8a48749 Mon Sep 17 00:00:00 2001 From: torrybr <16907963+torrybr@users.noreply.github.com> Date: Wed, 15 Jan 2025 09:09:28 -0500 Subject: [PATCH 1/3] refactor(live_location_share): exclude the live location events of the rooms own user --- crates/matrix-sdk/src/live_location_share.rs | 27 +++-- crates/matrix-sdk/src/room/mod.rs | 3 + .../tests/integration/room/beacon/mod.rs | 114 ++++++++++++++++-- 3 files changed, 121 insertions(+), 23 deletions(-) diff --git a/crates/matrix-sdk/src/live_location_share.rs b/crates/matrix-sdk/src/live_location_share.rs index f2d3e4fa097..5a407e3b2dc 100644 --- a/crates/matrix-sdk/src/live_location_share.rs +++ b/crates/matrix-sdk/src/live_location_share.rs @@ -43,20 +43,23 @@ impl ObservableLiveLocation { /// Get a stream of [`LiveLocationShare`]. pub fn subscribe(&self) -> impl Stream { let stream = self.observable_room_events.subscribe(); + stream! { for await (event, room) in stream { - yield LiveLocationShare { - last_location: LastLocation { - location: event.content.location, - ts: event.origin_server_ts, - }, - beacon_info: room - .get_user_beacon_info(&event.sender) - .await - .ok() - .map(|info| info.content), - user_id: event.sender, - }; + if event.sender != room.own_user_id() { + yield LiveLocationShare { + last_location: LastLocation { + location: event.content.location, + ts: event.origin_server_ts, + }, + beacon_info: room + .get_user_beacon_info(&event.sender) + .await + .ok() + .map(|info| info.content), + user_id: event.sender, + }; + } } } } diff --git a/crates/matrix-sdk/src/room/mod.rs b/crates/matrix-sdk/src/room/mod.rs index 19210294482..a2b80ea9658 100644 --- a/crates/matrix-sdk/src/room/mod.rs +++ b/crates/matrix-sdk/src/room/mod.rs @@ -3244,6 +3244,9 @@ impl Room { /// /// The returned observable will receive the newest event for each sync /// response that contains an `m.beacon` event. + /// + /// Returns a stream of `ObservableLiveLocation` events from other users + /// in the room, excluding the live location events of the room's own user. pub fn observe_live_location_shares(&self) -> ObservableLiveLocation { ObservableLiveLocation::new(&self.client, self.room_id()) } diff --git a/crates/matrix-sdk/tests/integration/room/beacon/mod.rs b/crates/matrix-sdk/tests/integration/room/beacon/mod.rs index 2f3403087a4..57ade61d3e1 100644 --- a/crates/matrix-sdk/tests/integration/room/beacon/mod.rs +++ b/crates/matrix-sdk/tests/integration/room/beacon/mod.rs @@ -1,6 +1,6 @@ use std::time::{Duration, UNIX_EPOCH}; -use futures_util::{pin_mut, StreamExt as _}; +use futures_util::{pin_mut, FutureExt, StreamExt as _}; use js_int::uint; use matrix_sdk::{config::SyncSettings, live_location_share::LiveLocationShare}; use matrix_sdk_test::{ @@ -130,8 +130,8 @@ async fn test_send_location_beacon_with_expired_live_share() { }, "event_id": "$15139375514XsgmR:localhost", "origin_server_ts": 1_636_829_458, - "sender": "@example:localhost", - "state_key": "@example:localhost", + "sender": "@example2:localhost", + "state_key": "@example2:localhost", "type": "org.matrix.msc3672.beacon_info", "unsigned": { "age": 7034220 @@ -192,8 +192,8 @@ async fn test_most_recent_event_in_stream() { }, "event_id": "$15139375514XsgmR:localhost", "origin_server_ts": millis_time, - "sender": "@example:localhost", - "state_key": "@example:localhost", + "sender": "@example2:localhost", + "state_key": "@example2:localhost", "type": "org.matrix.msc3672.beacon_info", "unsigned": { "age": 7034220 @@ -235,7 +235,7 @@ async fn test_most_recent_event_in_stream() { }, "event_id": format!("$event_for_stream_{nth}"), "origin_server_ts": 1_636_829_458, - "sender": "@example:localhost", + "sender": "@example2:localhost", "type": "org.matrix.msc3672.beacon", "unsigned": { "age": 598971 @@ -256,7 +256,7 @@ async fn test_most_recent_event_in_stream() { let LiveLocationShare { user_id, last_location, beacon_info } = stream.next().await.expect("Another live location was expected"); - assert_eq!(user_id.to_string(), "@example:localhost"); + assert_eq!(user_id.to_string(), "@example2:localhost"); assert_eq!(last_location.location.uri, "geo:24.9575274619722,12.494122581370175;u=24"); @@ -305,8 +305,8 @@ async fn test_observe_single_live_location_share() { }, "event_id": "$test_beacon_info", "origin_server_ts": millis_time, - "sender": "@example:localhost", - "state_key": "@example:localhost", + "sender": "@example2:localhost", + "state_key": "@example2:localhost", "type": "org.matrix.msc3672.beacon_info", } ] @@ -341,7 +341,7 @@ async fn test_observe_single_live_location_share() { }, "event_id": "$location_event", "origin_server_ts": millis_time, - "sender": "@example:localhost", + "sender": "@example2:localhost", "type": "org.matrix.msc3672.beacon", }); @@ -362,7 +362,7 @@ async fn test_observe_single_live_location_share() { let LiveLocationShare { user_id, last_location, beacon_info } = stream.next().await.expect("Another live location was expected"); - assert_eq!(user_id.to_string(), "@example:localhost"); + assert_eq!(user_id.to_string(), "@example2:localhost"); assert_eq!(last_location.location.uri, "geo:10.000000,20.000000;u=5"); assert_eq!(last_location.ts, current_time); @@ -374,3 +374,95 @@ async fn test_observe_single_live_location_share() { assert_eq!(beacon_info.timeout, Duration::from_millis(3000)); assert_eq!(beacon_info.ts, current_time); } + +#[async_test] +async fn test_observing_live_location_does_not_return_own_beacon_updates() { + let (client, server) = logged_in_client_with_server().await; + + let mut sync_builder = SyncResponseBuilder::new(); + + let current_time = MilliSecondsSinceUnixEpoch::now(); + let millis_time = current_time + .to_system_time() + .unwrap() + .duration_since(UNIX_EPOCH) + .expect("Time went backwards") + .as_millis() as u64; + + mock_sync( + &server, + json!({ + "next_batch": "s526_47314_0_7_1_1_1_1_1", + "rooms": { + "join": { + *DEFAULT_TEST_ROOM_ID: { + "state": { + "events": [ + { + "content": { + "description": "Live Share", + "live": true, + "org.matrix.msc3488.ts": millis_time, + "timeout": 3000, + "org.matrix.msc3488.asset": { "type": "m.self" } + }, + "event_id": "$15139375514XsgmR:localhost", + "origin_server_ts": millis_time, + "sender": "@example:localhost", + "state_key": "@example:localhost", + "type": "org.matrix.msc3672.beacon_info", + "unsigned": { + "age": 7034220 + } + } + ] + } + } + } + } + + }), + None, + ) + .await; + let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); + let _response = client.sync_once(sync_settings.clone()).await.unwrap(); + server.reset().await; + + let room = client.get_room(*DEFAULT_TEST_ROOM_ID).unwrap(); + let observable_live_location_shares = room.observe_live_location_shares(); + let stream = observable_live_location_shares.subscribe(); + pin_mut!(stream); + + let mut timeline_events = Vec::new(); + + timeline_events.push(sync_timeline_event!({ + "content": { + "m.relates_to": { + "event_id": "$15139375514XsgmR:localhost", + "rel_type": "m.reference" + }, + "org.matrix.msc3488.location": { + "uri": "geo:1.9575274619722,12.494122581370175;u=1" + }, + "org.matrix.msc3488.ts": 1_636_829_458 + }, + "event_id": "$152037dfsef280074GZeOm:localhost", + "origin_server_ts": 1_636_829_458, + "sender": "@example:localhost", + "type": "org.matrix.msc3672.beacon", + "unsigned": { + "age": 598971 + } + })); + + sync_builder.add_joined_room( + JoinedRoomBuilder::new(*DEFAULT_TEST_ROOM_ID).add_timeline_bulk(timeline_events.clone()), + ); + + mock_sync(&server, sync_builder.build_json_sync_response(), None).await; + let _response = client.sync_once(sync_settings.clone()).await.unwrap(); + server.reset().await; + + assert!(stream.next().now_or_never().is_none()); +} From a844b46a1b802ee80a473b5981860a8d70496bb2 Mon Sep 17 00:00:00 2001 From: torrybr <16907963+torrybr@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:24:57 -0500 Subject: [PATCH 2/3] test: use new server mock --- crates/matrix-sdk/src/room/mod.rs | 2 +- .../tests/integration/room/beacon/mod.rs | 120 ++++++------------ 2 files changed, 42 insertions(+), 80 deletions(-) diff --git a/crates/matrix-sdk/src/room/mod.rs b/crates/matrix-sdk/src/room/mod.rs index a2b80ea9658..521f569925e 100644 --- a/crates/matrix-sdk/src/room/mod.rs +++ b/crates/matrix-sdk/src/room/mod.rs @@ -3245,7 +3245,7 @@ impl Room { /// The returned observable will receive the newest event for each sync /// response that contains an `m.beacon` event. /// - /// Returns a stream of `ObservableLiveLocation` events from other users + /// Returns a stream of [`ObservableLiveLocation`] events from other users /// in the room, excluding the live location events of the room's own user. pub fn observe_live_location_shares(&self) -> ObservableLiveLocation { ObservableLiveLocation::new(&self.client, self.room_id()) diff --git a/crates/matrix-sdk/tests/integration/room/beacon/mod.rs b/crates/matrix-sdk/tests/integration/room/beacon/mod.rs index 57ade61d3e1..8bbe670dbd2 100644 --- a/crates/matrix-sdk/tests/integration/room/beacon/mod.rs +++ b/crates/matrix-sdk/tests/integration/room/beacon/mod.rs @@ -2,12 +2,23 @@ use std::time::{Duration, UNIX_EPOCH}; use futures_util::{pin_mut, FutureExt, StreamExt as _}; use js_int::uint; -use matrix_sdk::{config::SyncSettings, live_location_share::LiveLocationShare}; +use matrix_sdk::{ + config::SyncSettings, live_location_share::LiveLocationShare, + test_utils::mocks::MatrixMockServer, +}; use matrix_sdk_test::{ - async_test, mocks::mock_encryption_state, sync_timeline_event, test_json, JoinedRoomBuilder, - SyncResponseBuilder, DEFAULT_TEST_ROOM_ID, + async_test, event_factory::EventFactory, mocks::mock_encryption_state, sync_timeline_event, + test_json, JoinedRoomBuilder, SyncResponseBuilder, DEFAULT_TEST_ROOM_ID, +}; +use ruma::{ + event_id, + events::{ + beacon::BeaconEventContent, beacon_info::BeaconInfoEventContent, location::AssetType, + }, + owned_event_id, room_id, + time::SystemTime, + user_id, MilliSecondsSinceUnixEpoch, }; -use ruma::{event_id, events::location::AssetType, time::SystemTime, MilliSecondsSinceUnixEpoch}; use serde_json::json; use wiremock::{ matchers::{body_partial_json, header, method, path_regex}, @@ -377,92 +388,43 @@ async fn test_observe_single_live_location_share() { #[async_test] async fn test_observing_live_location_does_not_return_own_beacon_updates() { - let (client, server) = logged_in_client_with_server().await; + let server = MatrixMockServer::new().await; + let client = server.client_builder().build().await; + let room_id = room_id!("!a:b.c"); + let event_id = event_id!("$a:b.c"); + let user_id = user_id!("@example:localhost"); - let mut sync_builder = SyncResponseBuilder::new(); + let f = EventFactory::new().room(room_id); - let current_time = MilliSecondsSinceUnixEpoch::now(); - let millis_time = current_time - .to_system_time() - .unwrap() - .duration_since(UNIX_EPOCH) - .expect("Time went backwards") - .as_millis() as u64; + let ts = Some(MilliSecondsSinceUnixEpoch(1_636_829_458_u64.try_into().unwrap())); - mock_sync( - &server, - json!({ - "next_batch": "s526_47314_0_7_1_1_1_1_1", - "rooms": { - "join": { - *DEFAULT_TEST_ROOM_ID: { - "state": { - "events": [ - { - "content": { - "description": "Live Share", - "live": true, - "org.matrix.msc3488.ts": millis_time, - "timeout": 3000, - "org.matrix.msc3488.asset": { "type": "m.self" } - }, - "event_id": "$15139375514XsgmR:localhost", - "origin_server_ts": millis_time, - "sender": "@example:localhost", - "state_key": "@example:localhost", - "type": "org.matrix.msc3672.beacon_info", - "unsigned": { - "age": 7034220 - } - } - ] - } - } - } - } + let joined_room_builder = JoinedRoomBuilder::new(room_id).add_state_bulk(vec![f + .event(BeaconInfoEventContent::new(None, Duration::from_secs(60), false, None)) + .event_id(event_id) + .sender(user_id) + .state_key(user_id) + .into_raw_timeline() + .cast()]); - }), - None, - ) - .await; - let sync_settings = SyncSettings::new().timeout(Duration::from_millis(3000)); - let _response = client.sync_once(sync_settings.clone()).await.unwrap(); - server.reset().await; + let room = server.sync_room(&client, joined_room_builder).await; - let room = client.get_room(*DEFAULT_TEST_ROOM_ID).unwrap(); let observable_live_location_shares = room.observe_live_location_shares(); let stream = observable_live_location_shares.subscribe(); pin_mut!(stream); - let mut timeline_events = Vec::new(); + let beacon_event = f + .event(BeaconEventContent::new( + owned_event_id!("$15139375514XsgmR:localhost"), + "geo:51.5008,0.1247;u=35".to_owned(), + Some(MilliSecondsSinceUnixEpoch(uint!(1_636_829_458))), + )) + .event_id(event_id!("$152037dfsef280074GZeOm:localhost")) + .sender(user_id) + .into_raw_sync(); - timeline_events.push(sync_timeline_event!({ - "content": { - "m.relates_to": { - "event_id": "$15139375514XsgmR:localhost", - "rel_type": "m.reference" - }, - "org.matrix.msc3488.location": { - "uri": "geo:1.9575274619722,12.494122581370175;u=1" - }, - "org.matrix.msc3488.ts": 1_636_829_458 - }, - "event_id": "$152037dfsef280074GZeOm:localhost", - "origin_server_ts": 1_636_829_458, - "sender": "@example:localhost", - "type": "org.matrix.msc3672.beacon", - "unsigned": { - "age": 598971 - } - })); - - sync_builder.add_joined_room( - JoinedRoomBuilder::new(*DEFAULT_TEST_ROOM_ID).add_timeline_bulk(timeline_events.clone()), - ); + let joined = JoinedRoomBuilder::new(room_id).add_timeline_event(beacon_event); - mock_sync(&server, sync_builder.build_json_sync_response(), None).await; - let _response = client.sync_once(sync_settings.clone()).await.unwrap(); - server.reset().await; + let _ = server.sync_room(&client, joined).await; assert!(stream.next().now_or_never().is_none()); } From 1d1003c13458762a143cd412624a55cfedb4f733 Mon Sep 17 00:00:00 2001 From: torrybr <16907963+torrybr@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:27:44 -0500 Subject: [PATCH 3/3] chore: remove unused var --- crates/matrix-sdk/tests/integration/room/beacon/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/matrix-sdk/tests/integration/room/beacon/mod.rs b/crates/matrix-sdk/tests/integration/room/beacon/mod.rs index 8bbe670dbd2..50b60f0de20 100644 --- a/crates/matrix-sdk/tests/integration/room/beacon/mod.rs +++ b/crates/matrix-sdk/tests/integration/room/beacon/mod.rs @@ -396,8 +396,6 @@ async fn test_observing_live_location_does_not_return_own_beacon_updates() { let f = EventFactory::new().room(room_id); - let ts = Some(MilliSecondsSinceUnixEpoch(1_636_829_458_u64.try_into().unwrap())); - let joined_room_builder = JoinedRoomBuilder::new(room_id).add_state_bulk(vec![f .event(BeaconInfoEventContent::new(None, Duration::from_secs(60), false, None)) .event_id(event_id)