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