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