Skip to content

Commit fcdd28c

Browse files
committed
add tests for sending pre-messages
1 parent 5d2a9df commit fcdd28c

File tree

2 files changed

+245
-1
lines changed

2 files changed

+245
-1
lines changed

src/download.rs

Lines changed: 224 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,12 @@ impl Session {
208208

209209
#[cfg(test)]
210210
mod tests {
211+
use mailparse::MailHeaderMap;
212+
211213
use super::*;
212-
use crate::chat::send_msg;
214+
use crate::chat::{self, create_group, send_msg};
215+
use crate::headerdef::{HeaderDef, HeaderDefMap};
216+
use crate::message::Viewtype;
213217
use crate::test_utils::TestContext;
214218

215219
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
@@ -243,4 +247,223 @@ mod tests {
243247

244248
Ok(())
245249
}
250+
251+
/// Tests that pre message is sent for attachment larger than `PRE_MESSAGE_ATTACHMENT_SIZE_THRESHOLD`
252+
/// Also test that pre message is sent first, before the full message
253+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
254+
async fn test_sending_pre_message() -> Result<()> {
255+
let alice = TestContext::new_alice().await;
256+
let bob = TestContext::new_bob().await;
257+
let chat = alice.create_chat(&bob).await;
258+
259+
let mut msg = Message::new(Viewtype::File);
260+
msg.set_file_from_bytes(&alice.ctx, "test.bin", &[0u8; 300_000], None)?;
261+
msg.set_text("test".to_owned());
262+
263+
// assert that test attachment is bigger than limit
264+
assert!(
265+
msg.get_filebytes(&alice.ctx).await?.unwrap() > PRE_MESSAGE_ATTACHMENT_SIZE_THRESHOLD
266+
);
267+
268+
let msg_id = chat::send_msg(&alice.ctx, chat.id, &mut msg).await.unwrap();
269+
let smtp_rows = alice.get_smtp_rows_for_msg(msg_id).await;
270+
271+
// pre-message and full message should be present
272+
// and test that correct headers are present on both messages
273+
assert_eq!(smtp_rows.len(), 2);
274+
let pre_message = mailparse::parse_mail(
275+
smtp_rows
276+
.first()
277+
.expect("first element exists")
278+
.2
279+
.as_bytes(),
280+
)?;
281+
let full_message = mailparse::parse_mail(
282+
smtp_rows
283+
.get(1)
284+
.expect("second element exists")
285+
.2
286+
.as_bytes(),
287+
)?;
288+
289+
assert!(
290+
pre_message
291+
.get_headers()
292+
.get_first_header(HeaderDef::ChatIsFullMessage.get_headername())
293+
.is_none()
294+
);
295+
assert!(
296+
full_message
297+
.get_headers()
298+
.get_first_header(HeaderDef::ChatIsFullMessage.get_headername())
299+
.is_some()
300+
);
301+
302+
assert_eq!(
303+
pre_message
304+
.headers
305+
.get_header_value(HeaderDef::ChatFullMessageId),
306+
full_message.headers.get_header_value(HeaderDef::MessageId)
307+
);
308+
assert!(
309+
full_message
310+
.headers
311+
.get_header_value(HeaderDef::ChatFullMessageId)
312+
.is_none()
313+
);
314+
315+
// full message should have the rfc message id
316+
assert_eq!(
317+
full_message.headers.get_header_value(HeaderDef::MessageId),
318+
Some(msg.rfc724_mid)
319+
);
320+
321+
// test that message ids are different
322+
assert_ne!(
323+
pre_message.headers.get_header_value(HeaderDef::MessageId),
324+
full_message.headers.get_header_value(HeaderDef::MessageId)
325+
);
326+
327+
// also test that Autocrypt-gossip and selfavatar should never go into full-messages
328+
// TODO: (this needs decryption, right?)
329+
Ok(())
330+
}
331+
332+
/// Tests that no pre message is sent for normal message
333+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
334+
async fn test_not_sending_pre_message_no_attachment() -> Result<()> {
335+
let alice = TestContext::new_alice().await;
336+
let bob = TestContext::new_bob().await;
337+
let chat = alice.create_chat(&bob).await;
338+
339+
// send normal text message
340+
let mut msg = Message::new(Viewtype::Text);
341+
msg.set_text("test".to_owned());
342+
let msg_id = chat::send_msg(&alice.ctx, chat.id, &mut msg).await.unwrap();
343+
let smtp_rows = alice.get_smtp_rows_for_msg(msg_id).await;
344+
345+
// only one message and no "is full message" header should be present
346+
assert_eq!(smtp_rows.len(), 1);
347+
348+
let mime = smtp_rows.first().expect("first element exists").2.clone();
349+
let mail = mailparse::parse_mail(mime.as_bytes())?;
350+
351+
assert!(
352+
mail.get_headers()
353+
.get_first_header(HeaderDef::ChatIsFullMessage.get_headername())
354+
.is_none()
355+
);
356+
assert!(
357+
mail.get_headers()
358+
.get_first_header(HeaderDef::ChatFullMessageId.get_headername())
359+
.is_none()
360+
);
361+
Ok(())
362+
}
363+
364+
/// Tests that no pre message is sent for attachment smaller than `PRE_MESSAGE_ATTACHMENT_SIZE_THRESHOLD`
365+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
366+
async fn test_not_sending_pre_message_for_small_attachment() -> Result<()> {
367+
let alice = TestContext::new_alice().await;
368+
let bob = TestContext::new_bob().await;
369+
let chat = alice.create_chat(&bob).await;
370+
371+
let mut msg = Message::new(Viewtype::File);
372+
msg.set_file_from_bytes(&alice.ctx, "test.bin", &[0u8; 100_000], None)?;
373+
msg.set_text("test".to_owned());
374+
375+
// assert that test attachment is smaller than limit
376+
assert!(
377+
msg.get_filebytes(&alice.ctx).await?.unwrap() < PRE_MESSAGE_ATTACHMENT_SIZE_THRESHOLD
378+
);
379+
380+
let msg_id = chat::send_msg(&alice.ctx, chat.id, &mut msg).await.unwrap();
381+
let smtp_rows = alice.get_smtp_rows_for_msg(msg_id).await;
382+
383+
// only one message and no "is full message" header should be present
384+
assert_eq!(smtp_rows.len(), 1);
385+
386+
let mime = smtp_rows.first().expect("first element exists").2.clone();
387+
let mail = mailparse::parse_mail(mime.as_bytes())?;
388+
389+
assert!(
390+
mail.get_headers()
391+
.get_first_header(HeaderDef::ChatIsFullMessage.get_headername())
392+
.is_none()
393+
);
394+
assert!(
395+
mail.get_headers()
396+
.get_first_header(HeaderDef::ChatFullMessageId.get_headername())
397+
.is_none()
398+
);
399+
400+
Ok(())
401+
}
402+
403+
/// Tests that pre message is not send for large webxdc updates
404+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
405+
async fn test_render_webxdc_status_update_object_range() -> Result<()> {
406+
let t = TestContext::new_alice().await;
407+
let chat_id = create_group(&t, "a chat").await?;
408+
409+
let instance = {
410+
let mut instance = Message::new(Viewtype::File);
411+
instance.set_file_from_bytes(
412+
&t,
413+
"minimal.xdc",
414+
include_bytes!("../test-data/webxdc/minimal.xdc"),
415+
None,
416+
)?;
417+
let instance_msg_id = send_msg(&t, chat_id, &mut instance).await?;
418+
assert_eq!(instance.viewtype, Viewtype::Webxdc);
419+
Message::load_from_db(&t, instance_msg_id).await
420+
}
421+
.unwrap();
422+
423+
t.pop_sent_msg().await;
424+
assert_eq!(t.sql.count("SELECT COUNT(*) FROM smtp", ()).await?, 0);
425+
426+
let long_text = String::from_utf8(vec![b'a'; 300_000])?;
427+
assert!(long_text.len() > PRE_MESSAGE_ATTACHMENT_SIZE_THRESHOLD.try_into().unwrap());
428+
t.send_webxdc_status_update(instance.id, &format!("{{\"payload\": \"{long_text}\"}}"))
429+
.await?;
430+
t.flush_status_updates().await?;
431+
432+
assert_eq!(t.sql.count("SELECT COUNT(*) FROM smtp", ()).await?, 1);
433+
Ok(())
434+
}
435+
436+
// test that pre message is not send for large large text
437+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
438+
async fn test_not_sending_pre_message_for_large_text() -> Result<()> {
439+
let alice = TestContext::new_alice().await;
440+
let bob = TestContext::new_bob().await;
441+
let chat = alice.create_chat(&bob).await;
442+
443+
// send normal text message
444+
let mut msg = Message::new(Viewtype::Text);
445+
let long_text = String::from_utf8(vec![b'a'; 300_000])?;
446+
assert!(long_text.len() > PRE_MESSAGE_ATTACHMENT_SIZE_THRESHOLD.try_into().unwrap());
447+
msg.set_text(long_text);
448+
let msg_id = chat::send_msg(&alice.ctx, chat.id, &mut msg).await.unwrap();
449+
let smtp_rows = alice.get_smtp_rows_for_msg(msg_id).await;
450+
451+
// only one message and no "is full message" header should be present
452+
assert_eq!(smtp_rows.len(), 1);
453+
454+
let mime = smtp_rows.first().expect("first element exists").2.clone();
455+
let mail = mailparse::parse_mail(mime.as_bytes())?;
456+
457+
assert!(
458+
mail.get_headers()
459+
.get_first_header(HeaderDef::ChatIsFullMessage.get_headername())
460+
.is_none()
461+
);
462+
assert!(
463+
mail.get_headers()
464+
.get_first_header(HeaderDef::ChatFullMessageId.get_headername())
465+
.is_none()
466+
);
467+
Ok(())
468+
}
246469
}

src/test_utils.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,27 @@ impl TestContext {
697697
})
698698
}
699699

700+
pub async fn get_smtp_rows_for_msg(&self, msg_id: MsgId) -> Vec<(i64, MsgId, String, String)> {
701+
self.ctx
702+
.sql
703+
.query_map_vec(
704+
r#"
705+
SELECT id, msg_id, mime, recipients
706+
FROM smtp
707+
WHERE msg_id=?"#,
708+
(msg_id,),
709+
|row| {
710+
let rowid: i64 = row.get(0)?;
711+
let msg_id: MsgId = row.get(1)?;
712+
let mime: String = row.get(2)?;
713+
let recipients: String = row.get(3)?;
714+
Ok((rowid, msg_id, mime, recipients))
715+
},
716+
)
717+
.await
718+
.unwrap()
719+
}
720+
700721
/// Retrieves a sent sync message from the db.
701722
///
702723
/// This retrieves and removes a sync message which has been scheduled to send from the jobs

0 commit comments

Comments
 (0)