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 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}