Skip to content

Commit 3a684e9

Browse files
committed
add tests for sending pre-messages
1 parent b85829c commit 3a684e9

File tree

2 files changed

+243
-1
lines changed

2 files changed

+243
-1
lines changed

src/download.rs

Lines changed: 222 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,13 @@ impl Session {
208208

209209
#[cfg(test)]
210210
mod tests {
211+
use mailparse::MailHeaderMap;
211212
use num_traits::FromPrimitive;
212213

213214
use super::*;
214-
use crate::chat::send_msg;
215+
use crate::chat::{self, create_group, send_msg};
216+
use crate::headerdef::{HeaderDef, HeaderDefMap};
217+
use crate::message::Viewtype;
215218
use crate::receive_imf::receive_imf_from_inbox;
216219
use crate::test_utils::TestContext;
217220

@@ -310,4 +313,222 @@ mod tests {
310313

311314
Ok(())
312315
}
316+
/// Tests that pre message is sent for attachment larger than `PRE_MESSAGE_ATTACHMENT_SIZE_THRESHOLD`
317+
/// Also test that pre message is sent first, before the full message
318+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
319+
async fn test_sending_pre_message() -> Result<()> {
320+
let alice = TestContext::new_alice().await;
321+
let bob = TestContext::new_bob().await;
322+
let chat = alice.create_chat(&bob).await;
323+
324+
let mut msg = Message::new(Viewtype::File);
325+
msg.set_file_from_bytes(&alice.ctx, "test.bin", &[0u8; 300_000], None)?;
326+
msg.set_text("test".to_owned());
327+
328+
// assert that test attachment is bigger than limit
329+
assert!(
330+
msg.get_filebytes(&alice.ctx).await?.unwrap() > PRE_MESSAGE_ATTACHMENT_SIZE_THRESHOLD
331+
);
332+
333+
let msg_id = chat::send_msg(&alice.ctx, chat.id, &mut msg).await.unwrap();
334+
let smtp_rows = alice.get_smtp_rows_for_msg(msg_id).await;
335+
336+
// pre-message and full message should be present
337+
// and test that correct headers are present on both messages
338+
assert_eq!(smtp_rows.len(), 2);
339+
let pre_message = mailparse::parse_mail(
340+
smtp_rows
341+
.first()
342+
.expect("first element exists")
343+
.2
344+
.as_bytes(),
345+
)?;
346+
let full_message = mailparse::parse_mail(
347+
smtp_rows
348+
.get(1)
349+
.expect("second element exists")
350+
.2
351+
.as_bytes(),
352+
)?;
353+
354+
assert!(
355+
pre_message
356+
.get_headers()
357+
.get_first_header(HeaderDef::ChatIsFullMessage.get_headername())
358+
.is_none()
359+
);
360+
assert!(
361+
full_message
362+
.get_headers()
363+
.get_first_header(HeaderDef::ChatIsFullMessage.get_headername())
364+
.is_some()
365+
);
366+
367+
assert_eq!(
368+
pre_message
369+
.headers
370+
.get_header_value(HeaderDef::ChatFullMessageId),
371+
full_message.headers.get_header_value(HeaderDef::MessageId)
372+
);
373+
assert!(
374+
full_message
375+
.headers
376+
.get_header_value(HeaderDef::ChatFullMessageId)
377+
.is_none()
378+
);
379+
380+
// full message should have the rfc message id
381+
assert_eq!(
382+
full_message.headers.get_header_value(HeaderDef::MessageId),
383+
Some(msg.rfc724_mid)
384+
);
385+
386+
// test that message ids are different
387+
assert_ne!(
388+
pre_message.headers.get_header_value(HeaderDef::MessageId),
389+
full_message.headers.get_header_value(HeaderDef::MessageId)
390+
);
391+
392+
// also test that Autocrypt-gossip and selfavatar should never go into full-messages
393+
// TODO: (this needs decryption, right?)
394+
Ok(())
395+
}
396+
397+
/// Tests that no pre message is sent for normal message
398+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
399+
async fn test_not_sending_pre_message_no_attachment() -> Result<()> {
400+
let alice = TestContext::new_alice().await;
401+
let bob = TestContext::new_bob().await;
402+
let chat = alice.create_chat(&bob).await;
403+
404+
// send normal text message
405+
let mut msg = Message::new(Viewtype::Text);
406+
msg.set_text("test".to_owned());
407+
let msg_id = chat::send_msg(&alice.ctx, chat.id, &mut msg).await.unwrap();
408+
let smtp_rows = alice.get_smtp_rows_for_msg(msg_id).await;
409+
410+
// only one message and no "is full message" header should be present
411+
assert_eq!(smtp_rows.len(), 1);
412+
413+
let mime = smtp_rows.first().expect("first element exists").2.clone();
414+
let mail = mailparse::parse_mail(mime.as_bytes())?;
415+
416+
assert!(
417+
mail.get_headers()
418+
.get_first_header(HeaderDef::ChatIsFullMessage.get_headername())
419+
.is_none()
420+
);
421+
assert!(
422+
mail.get_headers()
423+
.get_first_header(HeaderDef::ChatFullMessageId.get_headername())
424+
.is_none()
425+
);
426+
Ok(())
427+
}
428+
429+
/// Tests that no pre message is sent for attachment smaller than `PRE_MESSAGE_ATTACHMENT_SIZE_THRESHOLD`
430+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
431+
async fn test_not_sending_pre_message_for_small_attachment() -> Result<()> {
432+
let alice = TestContext::new_alice().await;
433+
let bob = TestContext::new_bob().await;
434+
let chat = alice.create_chat(&bob).await;
435+
436+
let mut msg = Message::new(Viewtype::File);
437+
msg.set_file_from_bytes(&alice.ctx, "test.bin", &[0u8; 100_000], None)?;
438+
msg.set_text("test".to_owned());
439+
440+
// assert that test attachment is smaller than limit
441+
assert!(
442+
msg.get_filebytes(&alice.ctx).await?.unwrap() < PRE_MESSAGE_ATTACHMENT_SIZE_THRESHOLD
443+
);
444+
445+
let msg_id = chat::send_msg(&alice.ctx, chat.id, &mut msg).await.unwrap();
446+
let smtp_rows = alice.get_smtp_rows_for_msg(msg_id).await;
447+
448+
// only one message and no "is full message" header should be present
449+
assert_eq!(smtp_rows.len(), 1);
450+
451+
let mime = smtp_rows.first().expect("first element exists").2.clone();
452+
let mail = mailparse::parse_mail(mime.as_bytes())?;
453+
454+
assert!(
455+
mail.get_headers()
456+
.get_first_header(HeaderDef::ChatIsFullMessage.get_headername())
457+
.is_none()
458+
);
459+
assert!(
460+
mail.get_headers()
461+
.get_first_header(HeaderDef::ChatFullMessageId.get_headername())
462+
.is_none()
463+
);
464+
465+
Ok(())
466+
}
467+
468+
/// Tests that pre message is not send for large webxdc updates
469+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
470+
async fn test_render_webxdc_status_update_object_range() -> Result<()> {
471+
let t = TestContext::new_alice().await;
472+
let chat_id = create_group(&t, "a chat").await?;
473+
474+
let instance = {
475+
let mut instance = Message::new(Viewtype::File);
476+
instance.set_file_from_bytes(
477+
&t,
478+
"minimal.xdc",
479+
include_bytes!("../test-data/webxdc/minimal.xdc"),
480+
None,
481+
)?;
482+
let instance_msg_id = send_msg(&t, chat_id, &mut instance).await?;
483+
assert_eq!(instance.viewtype, Viewtype::Webxdc);
484+
Message::load_from_db(&t, instance_msg_id).await
485+
}
486+
.unwrap();
487+
488+
t.pop_sent_msg().await;
489+
assert_eq!(t.sql.count("SELECT COUNT(*) FROM smtp", ()).await?, 0);
490+
491+
let long_text = String::from_utf8(vec![b'a'; 300_000])?;
492+
assert!(long_text.len() > PRE_MESSAGE_ATTACHMENT_SIZE_THRESHOLD.try_into().unwrap());
493+
t.send_webxdc_status_update(instance.id, &format!("{{\"payload\": \"{long_text}\"}}"))
494+
.await?;
495+
t.flush_status_updates().await?;
496+
497+
assert_eq!(t.sql.count("SELECT COUNT(*) FROM smtp", ()).await?, 1);
498+
Ok(())
499+
}
500+
501+
// test that pre message is not send for large large text
502+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
503+
async fn test_not_sending_pre_message_for_large_text() -> Result<()> {
504+
let alice = TestContext::new_alice().await;
505+
let bob = TestContext::new_bob().await;
506+
let chat = alice.create_chat(&bob).await;
507+
508+
// send normal text message
509+
let mut msg = Message::new(Viewtype::Text);
510+
let long_text = String::from_utf8(vec![b'a'; 300_000])?;
511+
assert!(long_text.len() > PRE_MESSAGE_ATTACHMENT_SIZE_THRESHOLD.try_into().unwrap());
512+
msg.set_text(long_text);
513+
let msg_id = chat::send_msg(&alice.ctx, chat.id, &mut msg).await.unwrap();
514+
let smtp_rows = alice.get_smtp_rows_for_msg(msg_id).await;
515+
516+
// only one message and no "is full message" header should be present
517+
assert_eq!(smtp_rows.len(), 1);
518+
519+
let mime = smtp_rows.first().expect("first element exists").2.clone();
520+
let mail = mailparse::parse_mail(mime.as_bytes())?;
521+
522+
assert!(
523+
mail.get_headers()
524+
.get_first_header(HeaderDef::ChatIsFullMessage.get_headername())
525+
.is_none()
526+
);
527+
assert!(
528+
mail.get_headers()
529+
.get_first_header(HeaderDef::ChatFullMessageId.get_headername())
530+
.is_none()
531+
);
532+
Ok(())
533+
}
313534
}

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)