1use super::new_test_user;
2use crate::{
3 db::{ChannelRole, Database, MessageId},
4 test_both_dbs,
5};
6use channel::mentions_to_proto;
7use std::sync::Arc;
8use time::OffsetDateTime;
9
10test_both_dbs!(
11 test_channel_message_retrieval,
12 test_channel_message_retrieval_postgres,
13 test_channel_message_retrieval_sqlite
14);
15
16async fn test_channel_message_retrieval(db: &Arc<Database>) {
17 let user = new_test_user(db, "user@example.com").await;
18 let channel = db.create_channel("channel", None, user).await.unwrap();
19
20 let owner_id = db.create_server("test").await.unwrap().0 as u32;
21 db.join_channel_chat(channel.id, rpc::ConnectionId { owner_id, id: 0 }, user)
22 .await
23 .unwrap();
24
25 let mut all_messages = Vec::new();
26 for i in 0..10 {
27 all_messages.push(
28 db.create_channel_message(
29 channel.id,
30 user,
31 &i.to_string(),
32 &[],
33 OffsetDateTime::now_utc(),
34 i,
35 )
36 .await
37 .unwrap()
38 .message_id
39 .to_proto(),
40 );
41 }
42
43 let messages = db
44 .get_channel_messages(channel.id, user, 3, None)
45 .await
46 .unwrap()
47 .into_iter()
48 .map(|message| message.id)
49 .collect::<Vec<_>>();
50 assert_eq!(messages, &all_messages[7..10]);
51
52 let messages = db
53 .get_channel_messages(
54 channel.id,
55 user,
56 4,
57 Some(MessageId::from_proto(all_messages[6])),
58 )
59 .await
60 .unwrap()
61 .into_iter()
62 .map(|message| message.id)
63 .collect::<Vec<_>>();
64 assert_eq!(messages, &all_messages[2..6]);
65}
66
67test_both_dbs!(
68 test_channel_message_nonces,
69 test_channel_message_nonces_postgres,
70 test_channel_message_nonces_sqlite
71);
72
73async fn test_channel_message_nonces(db: &Arc<Database>) {
74 let user_a = new_test_user(db, "user_a@example.com").await;
75 let user_b = new_test_user(db, "user_b@example.com").await;
76 let user_c = new_test_user(db, "user_c@example.com").await;
77 let channel = db.create_root_channel("channel", user_a).await.unwrap();
78 db.invite_channel_member(channel, user_b, user_a, ChannelRole::Member)
79 .await
80 .unwrap();
81 db.invite_channel_member(channel, user_c, user_a, ChannelRole::Member)
82 .await
83 .unwrap();
84 db.respond_to_channel_invite(channel, user_b, true)
85 .await
86 .unwrap();
87 db.respond_to_channel_invite(channel, user_c, true)
88 .await
89 .unwrap();
90
91 let owner_id = db.create_server("test").await.unwrap().0 as u32;
92 db.join_channel_chat(channel, rpc::ConnectionId { owner_id, id: 0 }, user_a)
93 .await
94 .unwrap();
95 db.join_channel_chat(channel, rpc::ConnectionId { owner_id, id: 1 }, user_b)
96 .await
97 .unwrap();
98
99 // As user A, create messages that re-use the same nonces. The requests
100 // succeed, but return the same ids.
101 let id1 = db
102 .create_channel_message(
103 channel,
104 user_a,
105 "hi @user_b",
106 &mentions_to_proto(&[(3..10, user_b.to_proto())]),
107 OffsetDateTime::now_utc(),
108 100,
109 )
110 .await
111 .unwrap()
112 .message_id;
113 let id2 = db
114 .create_channel_message(
115 channel,
116 user_a,
117 "hello, fellow users",
118 &mentions_to_proto(&[]),
119 OffsetDateTime::now_utc(),
120 200,
121 )
122 .await
123 .unwrap()
124 .message_id;
125 let id3 = db
126 .create_channel_message(
127 channel,
128 user_a,
129 "bye @user_c (same nonce as first message)",
130 &mentions_to_proto(&[(4..11, user_c.to_proto())]),
131 OffsetDateTime::now_utc(),
132 100,
133 )
134 .await
135 .unwrap()
136 .message_id;
137 let id4 = db
138 .create_channel_message(
139 channel,
140 user_a,
141 "omg (same nonce as second message)",
142 &mentions_to_proto(&[]),
143 OffsetDateTime::now_utc(),
144 200,
145 )
146 .await
147 .unwrap()
148 .message_id;
149
150 // As a different user, reuse one of the same nonces. This request succeeds
151 // and returns a different id.
152 let id5 = db
153 .create_channel_message(
154 channel,
155 user_b,
156 "omg @user_a (same nonce as user_a's first message)",
157 &mentions_to_proto(&[(4..11, user_a.to_proto())]),
158 OffsetDateTime::now_utc(),
159 100,
160 )
161 .await
162 .unwrap()
163 .message_id;
164
165 assert_ne!(id1, id2);
166 assert_eq!(id1, id3);
167 assert_eq!(id2, id4);
168 assert_ne!(id5, id1);
169
170 let messages = db
171 .get_channel_messages(channel, user_a, 5, None)
172 .await
173 .unwrap()
174 .into_iter()
175 .map(|m| (m.id, m.body, m.mentions))
176 .collect::<Vec<_>>();
177 assert_eq!(
178 messages,
179 &[
180 (
181 id1.to_proto(),
182 "hi @user_b".into(),
183 mentions_to_proto(&[(3..10, user_b.to_proto())]),
184 ),
185 (
186 id2.to_proto(),
187 "hello, fellow users".into(),
188 mentions_to_proto(&[])
189 ),
190 (
191 id5.to_proto(),
192 "omg @user_a (same nonce as user_a's first message)".into(),
193 mentions_to_proto(&[(4..11, user_a.to_proto())]),
194 ),
195 ]
196 );
197}
198
199test_both_dbs!(
200 test_unseen_channel_messages,
201 test_unseen_channel_messages_postgres,
202 test_unseen_channel_messages_sqlite
203);
204
205async fn test_unseen_channel_messages(db: &Arc<Database>) {
206 let user = new_test_user(db, "user_a@example.com").await;
207 let observer = new_test_user(db, "user_b@example.com").await;
208
209 let channel_1 = db.create_root_channel("channel", user).await.unwrap();
210 let channel_2 = db.create_root_channel("channel-2", user).await.unwrap();
211
212 db.invite_channel_member(channel_1, observer, user, ChannelRole::Member)
213 .await
214 .unwrap();
215 db.invite_channel_member(channel_2, observer, user, ChannelRole::Member)
216 .await
217 .unwrap();
218
219 db.respond_to_channel_invite(channel_1, observer, true)
220 .await
221 .unwrap();
222 db.respond_to_channel_invite(channel_2, observer, true)
223 .await
224 .unwrap();
225
226 let owner_id = db.create_server("test").await.unwrap().0 as u32;
227 let user_connection_id = rpc::ConnectionId { owner_id, id: 0 };
228
229 db.join_channel_chat(channel_1, user_connection_id, user)
230 .await
231 .unwrap();
232
233 let _ = db
234 .create_channel_message(channel_1, user, "1_1", &[], OffsetDateTime::now_utc(), 1)
235 .await
236 .unwrap();
237
238 let second_message = db
239 .create_channel_message(channel_1, user, "1_2", &[], OffsetDateTime::now_utc(), 2)
240 .await
241 .unwrap()
242 .message_id;
243
244 let third_message = db
245 .create_channel_message(channel_1, user, "1_3", &[], OffsetDateTime::now_utc(), 3)
246 .await
247 .unwrap()
248 .message_id;
249
250 db.join_channel_chat(channel_2, user_connection_id, user)
251 .await
252 .unwrap();
253
254 let fourth_message = db
255 .create_channel_message(channel_2, user, "2_1", &[], OffsetDateTime::now_utc(), 4)
256 .await
257 .unwrap()
258 .message_id;
259
260 // Check that observer has new messages
261 let unseen_messages = db
262 .transaction(|tx| async move {
263 db.unseen_channel_messages(observer, &[channel_1, channel_2], &*tx)
264 .await
265 })
266 .await
267 .unwrap();
268
269 assert_eq!(
270 unseen_messages,
271 [
272 rpc::proto::UnseenChannelMessage {
273 channel_id: channel_1.to_proto(),
274 message_id: third_message.to_proto(),
275 },
276 rpc::proto::UnseenChannelMessage {
277 channel_id: channel_2.to_proto(),
278 message_id: fourth_message.to_proto(),
279 },
280 ]
281 );
282
283 // Observe the second message
284 db.observe_channel_message(channel_1, observer, second_message)
285 .await
286 .unwrap();
287
288 // Make sure the observer still has a new message
289 let unseen_messages = db
290 .transaction(|tx| async move {
291 db.unseen_channel_messages(observer, &[channel_1, channel_2], &*tx)
292 .await
293 })
294 .await
295 .unwrap();
296 assert_eq!(
297 unseen_messages,
298 [
299 rpc::proto::UnseenChannelMessage {
300 channel_id: channel_1.to_proto(),
301 message_id: third_message.to_proto(),
302 },
303 rpc::proto::UnseenChannelMessage {
304 channel_id: channel_2.to_proto(),
305 message_id: fourth_message.to_proto(),
306 },
307 ]
308 );
309
310 // Observe the third message,
311 db.observe_channel_message(channel_1, observer, third_message)
312 .await
313 .unwrap();
314
315 // Make sure the observer does not have a new method
316 let unseen_messages = db
317 .transaction(|tx| async move {
318 db.unseen_channel_messages(observer, &[channel_1, channel_2], &*tx)
319 .await
320 })
321 .await
322 .unwrap();
323
324 assert_eq!(
325 unseen_messages,
326 [rpc::proto::UnseenChannelMessage {
327 channel_id: channel_2.to_proto(),
328 message_id: fourth_message.to_proto(),
329 }]
330 );
331
332 // Observe the second message again, should not regress our observed state
333 db.observe_channel_message(channel_1, observer, second_message)
334 .await
335 .unwrap();
336
337 // Make sure the observer does not have a new message
338 let unseen_messages = db
339 .transaction(|tx| async move {
340 db.unseen_channel_messages(observer, &[channel_1, channel_2], &*tx)
341 .await
342 })
343 .await
344 .unwrap();
345 assert_eq!(
346 unseen_messages,
347 [rpc::proto::UnseenChannelMessage {
348 channel_id: channel_2.to_proto(),
349 message_id: fourth_message.to_proto(),
350 }]
351 );
352}
353
354test_both_dbs!(
355 test_channel_message_mentions,
356 test_channel_message_mentions_postgres,
357 test_channel_message_mentions_sqlite
358);
359
360async fn test_channel_message_mentions(db: &Arc<Database>) {
361 let user_a = new_test_user(db, "user_a@example.com").await;
362 let user_b = new_test_user(db, "user_b@example.com").await;
363 let user_c = new_test_user(db, "user_c@example.com").await;
364
365 let channel = db.create_channel("channel", None, user_a).await.unwrap().id;
366 db.invite_channel_member(channel, user_b, user_a, ChannelRole::Member)
367 .await
368 .unwrap();
369 db.respond_to_channel_invite(channel, user_b, true)
370 .await
371 .unwrap();
372
373 let owner_id = db.create_server("test").await.unwrap().0 as u32;
374 let connection_id = rpc::ConnectionId { owner_id, id: 0 };
375 db.join_channel_chat(channel, connection_id, user_a)
376 .await
377 .unwrap();
378
379 db.create_channel_message(
380 channel,
381 user_a,
382 "hi @user_b and @user_c",
383 &mentions_to_proto(&[(3..10, user_b.to_proto()), (15..22, user_c.to_proto())]),
384 OffsetDateTime::now_utc(),
385 1,
386 )
387 .await
388 .unwrap();
389 db.create_channel_message(
390 channel,
391 user_a,
392 "bye @user_c",
393 &mentions_to_proto(&[(4..11, user_c.to_proto())]),
394 OffsetDateTime::now_utc(),
395 2,
396 )
397 .await
398 .unwrap();
399 db.create_channel_message(
400 channel,
401 user_a,
402 "umm",
403 &mentions_to_proto(&[]),
404 OffsetDateTime::now_utc(),
405 3,
406 )
407 .await
408 .unwrap();
409 db.create_channel_message(
410 channel,
411 user_a,
412 "@user_b, stop.",
413 &mentions_to_proto(&[(0..7, user_b.to_proto())]),
414 OffsetDateTime::now_utc(),
415 4,
416 )
417 .await
418 .unwrap();
419
420 let messages = db
421 .get_channel_messages(channel, user_b, 5, None)
422 .await
423 .unwrap()
424 .into_iter()
425 .map(|m| (m.body, m.mentions))
426 .collect::<Vec<_>>();
427 assert_eq!(
428 &messages,
429 &[
430 (
431 "hi @user_b and @user_c".into(),
432 mentions_to_proto(&[(3..10, user_b.to_proto()), (15..22, user_c.to_proto())]),
433 ),
434 (
435 "bye @user_c".into(),
436 mentions_to_proto(&[(4..11, user_c.to_proto())]),
437 ),
438 ("umm".into(), mentions_to_proto(&[]),),
439 (
440 "@user_b, stop.".into(),
441 mentions_to_proto(&[(0..7, user_b.to_proto())]),
442 ),
443 ]
444 );
445}