matrix_sdk_test/sync_builder/
mod.rs1use std::collections::HashMap;
2
3use http::Response;
4use ruma::{
5 OwnedRoomId, OwnedUserId, UserId,
6 api::{
7 IncomingResponse,
8 client::sync::sync_events::v3::{
9 InvitedRoom, JoinedRoom, KnockedRoom, LeftRoom, Response as SyncResponse, State,
10 },
11 },
12 events::{
13 AnyGlobalAccountDataEvent, AnySyncStateEvent, AnyToDeviceEvent, presence::PresenceEvent,
14 },
15 serde::Raw,
16};
17use serde_json::{Value as JsonValue, from_value as from_json_value, json};
18
19use super::test_json;
20
21mod bulk;
22mod invited_room;
23mod joined_room;
24mod knocked_room;
25mod left_room;
26mod test_event;
27
28pub use bulk::bulk_room_members;
29pub use invited_room::InvitedRoomBuilder;
30pub use joined_room::JoinedRoomBuilder;
31pub use knocked_room::KnockedRoomBuilder;
32pub use left_room::LeftRoomBuilder;
33pub use test_event::{
34 PresenceTestEvent, RoomAccountDataTestEvent, StateTestEvent, StrippedStateTestEvent,
35};
36
37#[derive(Default)]
44pub struct SyncResponseBuilder {
45 joined_rooms: HashMap<OwnedRoomId, JoinedRoom>,
47 invited_rooms: HashMap<OwnedRoomId, InvitedRoom>,
49 left_rooms: HashMap<OwnedRoomId, LeftRoom>,
51 knocked_rooms: HashMap<OwnedRoomId, KnockedRoom>,
53 presence: Vec<Raw<PresenceEvent>>,
55 account_data: Vec<Raw<AnyGlobalAccountDataEvent>>,
57 batch_counter: i64,
60 changed_device_lists: Vec<OwnedUserId>,
62 to_device_events: Vec<Raw<AnyToDeviceEvent>>,
63}
64
65impl SyncResponseBuilder {
66 pub fn new() -> Self {
67 Self::default()
68 }
69
70 pub fn add_joined_room(&mut self, room: JoinedRoomBuilder) -> &mut Self {
75 self.invited_rooms.remove(&room.room_id);
76 self.left_rooms.remove(&room.room_id);
77 self.knocked_rooms.remove(&room.room_id);
78 self.joined_rooms.insert(room.room_id, room.inner);
79 self
80 }
81
82 pub fn add_invited_room(&mut self, room: InvitedRoomBuilder) -> &mut Self {
87 self.joined_rooms.remove(&room.room_id);
88 self.left_rooms.remove(&room.room_id);
89 self.knocked_rooms.remove(&room.room_id);
90 self.invited_rooms.insert(room.room_id, room.inner);
91 self
92 }
93
94 pub fn add_left_room(&mut self, room: LeftRoomBuilder) -> &mut Self {
99 self.joined_rooms.remove(&room.room_id);
100 self.invited_rooms.remove(&room.room_id);
101 self.knocked_rooms.remove(&room.room_id);
102 self.left_rooms.insert(room.room_id, room.inner);
103 self
104 }
105
106 pub fn add_knocked_room(&mut self, room: KnockedRoomBuilder) -> &mut Self {
111 self.joined_rooms.remove(&room.room_id);
112 self.invited_rooms.remove(&room.room_id);
113 self.left_rooms.remove(&room.room_id);
114 self.knocked_rooms.insert(room.room_id, room.inner);
115 self
116 }
117
118 pub fn add_presence_event(&mut self, event: PresenceTestEvent) -> &mut Self {
120 let val = match event {
121 PresenceTestEvent::Presence => test_json::PRESENCE.to_owned(),
122 PresenceTestEvent::Custom(json) => json,
123 };
124
125 self.presence.push(from_json_value(val).unwrap());
126 self
127 }
128
129 pub fn add_presence_bulk<I>(&mut self, events: I) -> &mut Self
131 where
132 I: IntoIterator<Item = Raw<PresenceEvent>>,
133 {
134 self.presence.extend(events);
135 self
136 }
137
138 pub fn add_global_account_data(
140 &mut self,
141 event: impl Into<Raw<AnyGlobalAccountDataEvent>>,
142 ) -> &mut Self {
143 self.account_data.push(event.into());
144 self
145 }
146
147 pub fn add_custom_global_account_data(&mut self, event: serde_json::Value) -> &mut Self {
149 self.account_data.push(Raw::new(&event).unwrap().cast_unchecked());
150 self
151 }
152
153 pub fn add_change_device(&mut self, user_id: &UserId) -> &mut Self {
154 self.changed_device_lists.push(user_id.to_owned());
155 self
156 }
157
158 pub fn add_to_device_event(&mut self, event: JsonValue) -> &mut Self {
160 self.to_device_events.push(from_json_value(event).unwrap());
161 self
162 }
163
164 pub fn build_json_sync_response(&mut self) -> JsonValue {
175 self.batch_counter += 1;
176 let next_batch = self.generate_sync_token();
177
178 let body = json! {
179 {
180 "device_one_time_keys_count": {},
181 "next_batch": next_batch,
182 "device_lists": {
183 "changed": self.changed_device_lists,
184 "left": [],
185 },
186 "rooms": {
187 "invite": self.invited_rooms,
188 "join": self.joined_rooms,
189 "leave": self.left_rooms,
190 "knock": self.knocked_rooms,
191 },
192 "to_device": {
193 "events": self.to_device_events,
194 },
195 "presence": {
196 "events": self.presence,
197 },
198 "account_data": {
199 "events": self.account_data,
200 },
201 }
202 };
203
204 self.clear();
207
208 body
209 }
210
211 pub fn build_sync_response(&mut self) -> SyncResponse {
221 let body = self.build_json_sync_response();
222
223 let response = Response::builder().body(serde_json::to_vec(&body).unwrap()).unwrap();
224
225 SyncResponse::try_from_http_response(response).unwrap()
226 }
227
228 fn generate_sync_token(&self) -> String {
229 format!("t392-516_47314_0_7_1_1_1_11444_{}", self.batch_counter)
230 }
231
232 pub fn clear(&mut self) {
233 self.account_data.clear();
234 self.invited_rooms.clear();
235 self.joined_rooms.clear();
236 self.left_rooms.clear();
237 self.knocked_rooms.clear();
238 self.presence.clear();
239 }
240}
241
242trait StateMutExt {
244 fn use_state_after(&mut self);
246 fn events_mut(&mut self) -> &mut Vec<Raw<AnySyncStateEvent>>;
248}
249
250impl StateMutExt for State {
251 fn use_state_after(&mut self) {
252 *self = Self::After(Default::default());
253 }
254
255 fn events_mut(&mut self) -> &mut Vec<Raw<AnySyncStateEvent>> {
256 match self {
257 Self::Before(state) => &mut state.events,
258 Self::After(state) => &mut state.events,
259 _ => unreachable!(),
261 }
262 }
263}