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            )
 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 reuse 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 _ = db
239        .create_channel_message(channel_1, user, "1_2", &[], OffsetDateTime::now_utc(), 2)
240        .await
241        .unwrap();
242
243    let third_message = db
244        .create_channel_message(channel_1, user, "1_3", &[], OffsetDateTime::now_utc(), 3)
245        .await
246        .unwrap()
247        .message_id;
248
249    db.join_channel_chat(channel_2, user_connection_id, user)
250        .await
251        .unwrap();
252
253    let fourth_message = db
254        .create_channel_message(channel_2, user, "2_1", &[], OffsetDateTime::now_utc(), 4)
255        .await
256        .unwrap()
257        .message_id;
258
259    // Check that observer has new messages
260    let latest_messages = db
261        .transaction(|tx| async move {
262            db.latest_channel_messages(&[channel_1, channel_2], &*tx)
263                .await
264        })
265        .await
266        .unwrap();
267
268    assert_eq!(
269        latest_messages,
270        [
271            rpc::proto::ChannelMessageId {
272                channel_id: channel_1.to_proto(),
273                message_id: third_message.to_proto(),
274            },
275            rpc::proto::ChannelMessageId {
276                channel_id: channel_2.to_proto(),
277                message_id: fourth_message.to_proto(),
278            },
279        ]
280    );
281}
282
283test_both_dbs!(
284    test_channel_message_mentions,
285    test_channel_message_mentions_postgres,
286    test_channel_message_mentions_sqlite
287);
288
289async fn test_channel_message_mentions(db: &Arc<Database>) {
290    let user_a = new_test_user(db, "user_a@example.com").await;
291    let user_b = new_test_user(db, "user_b@example.com").await;
292    let user_c = new_test_user(db, "user_c@example.com").await;
293
294    let channel = db
295        .create_channel("channel", None, user_a)
296        .await
297        .unwrap()
298        .0
299        .id;
300    db.invite_channel_member(channel, user_b, user_a, ChannelRole::Member)
301        .await
302        .unwrap();
303    db.respond_to_channel_invite(channel, user_b, true)
304        .await
305        .unwrap();
306
307    let owner_id = db.create_server("test").await.unwrap().0 as u32;
308    let connection_id = rpc::ConnectionId { owner_id, id: 0 };
309    db.join_channel_chat(channel, connection_id, user_a)
310        .await
311        .unwrap();
312
313    db.create_channel_message(
314        channel,
315        user_a,
316        "hi @user_b and @user_c",
317        &mentions_to_proto(&[(3..10, user_b.to_proto()), (15..22, user_c.to_proto())]),
318        OffsetDateTime::now_utc(),
319        1,
320    )
321    .await
322    .unwrap();
323    db.create_channel_message(
324        channel,
325        user_a,
326        "bye @user_c",
327        &mentions_to_proto(&[(4..11, user_c.to_proto())]),
328        OffsetDateTime::now_utc(),
329        2,
330    )
331    .await
332    .unwrap();
333    db.create_channel_message(
334        channel,
335        user_a,
336        "umm",
337        &mentions_to_proto(&[]),
338        OffsetDateTime::now_utc(),
339        3,
340    )
341    .await
342    .unwrap();
343    db.create_channel_message(
344        channel,
345        user_a,
346        "@user_b, stop.",
347        &mentions_to_proto(&[(0..7, user_b.to_proto())]),
348        OffsetDateTime::now_utc(),
349        4,
350    )
351    .await
352    .unwrap();
353
354    let messages = db
355        .get_channel_messages(channel, user_b, 5, None)
356        .await
357        .unwrap()
358        .into_iter()
359        .map(|m| (m.body, m.mentions))
360        .collect::<Vec<_>>();
361    assert_eq!(
362        &messages,
363        &[
364            (
365                "hi @user_b and @user_c".into(),
366                mentions_to_proto(&[(3..10, user_b.to_proto()), (15..22, user_c.to_proto())]),
367            ),
368            (
369                "bye @user_c".into(),
370                mentions_to_proto(&[(4..11, user_c.to_proto())]),
371            ),
372            ("umm".into(), mentions_to_proto(&[]),),
373            (
374                "@user_b, stop.".into(),
375                mentions_to_proto(&[(0..7, user_b.to_proto())]),
376            ),
377        ]
378    );
379}