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