message_tests.rs

  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}