message_tests.rs

  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}