#![allow(clippy::unwrap_used, clippy::expect_used)]
use super::*;
#[test]
fn fetch_response_default() {
let resp = FetchResponse::default();
assert_eq!(resp.seq, 0);
assert!(resp.uid.is_none());
assert!(resp.flags.is_none());
assert!(resp.envelope.is_none());
assert!(resp.body_structure.is_none());
assert!(resp.rfc822_size.is_none());
assert!(resp.internal_date.is_none());
assert!(resp.body_sections.is_empty());
assert!(resp.mod_seq.is_none());
assert!(resp.save_date.is_none());
assert!(resp.binary_sections.is_empty());
assert!(resp.binary_sizes.is_empty());
assert!(resp.preview.is_none());
assert!(resp.email_id.is_none());
assert!(resp.thread_id.is_none());
}
#[test]
fn fetch_response_with_seq_and_uid() {
let resp = FetchResponse {
seq: 5,
uid: Some(1234),
..Default::default()
};
assert_eq!(resp.seq, 5);
assert_eq!(resp.uid, Some(1234));
}
#[test]
fn fetch_response_with_flags() {
let resp = FetchResponse {
seq: 1,
flags: Some(vec![Flag::Seen, Flag::Flagged]),
..Default::default()
};
let flags = resp.flags.unwrap();
assert_eq!(flags.len(), 2);
assert_eq!(flags[0], Flag::Seen);
assert_eq!(flags[1], Flag::Flagged);
}
#[test]
fn fetch_response_with_envelope() {
let env = Envelope {
subject: Some("Test subject".into()),
..Default::default()
};
let resp = FetchResponse {
seq: 1,
envelope: Some(env),
..Default::default()
};
assert_eq!(
resp.envelope.unwrap().subject.as_deref(),
Some("Test subject")
);
}
#[test]
fn fetch_response_with_rfc822_size() {
let resp = FetchResponse {
seq: 1,
rfc822_size: Some(4096),
..Default::default()
};
assert_eq!(resp.rfc822_size, Some(4096));
}
#[test]
fn fetch_response_with_internal_date() {
let resp = FetchResponse {
seq: 1,
internal_date: Some("17-Jul-1996 02:44:25 -0700".into()),
..Default::default()
};
assert_eq!(
resp.internal_date.as_deref(),
Some("17-Jul-1996 02:44:25 -0700")
);
}
#[test]
fn fetch_response_with_mod_seq() {
let resp = FetchResponse {
seq: 1,
mod_seq: Some(99999),
..Default::default()
};
assert_eq!(resp.mod_seq, Some(99999));
}
#[test]
fn fetch_response_with_save_date() {
let resp = FetchResponse {
seq: 1,
save_date: Some("01-Jan-2024 00:00:00 +0000".into()),
..Default::default()
};
assert_eq!(
resp.save_date.as_deref(),
Some("01-Jan-2024 00:00:00 +0000")
);
}
#[test]
fn body_section_full() {
let section = BodySection {
section: "HEADER".into(),
origin: None,
data: Some(b"Subject: Hi\r\n".to_vec()),
};
assert_eq!(section.section, "HEADER");
assert!(section.origin.is_none());
assert_eq!(section.data.as_deref(), Some(b"Subject: Hi\r\n".as_slice()));
}
#[test]
fn body_section_with_origin() {
let section = BodySection {
section: "1".into(),
origin: Some(100),
data: Some(b"partial data".to_vec()),
};
assert_eq!(section.origin, Some(100));
}
#[test]
fn body_section_nil_data() {
let section = BodySection {
section: "TEXT".into(),
origin: None,
data: None,
};
assert!(section.data.is_none());
}
#[test]
fn body_section_empty_section_string() {
let section = BodySection {
section: String::new(),
origin: None,
data: Some(b"full message".to_vec()),
};
assert!(section.section.is_empty());
}
#[test]
fn binary_section_basic() {
let section = BinarySection {
section: vec![1, 2, 3],
origin: None,
data: Some(vec![0xFF, 0xD8, 0xFF]),
};
assert_eq!(section.section, [1, 2, 3]);
assert!(section.origin.is_none());
assert_eq!(section.data.as_deref(), Some([0xFF, 0xD8, 0xFF].as_slice()));
}
#[test]
fn binary_section_with_origin() {
let section = BinarySection {
section: vec![1],
origin: Some(512),
data: Some(vec![0x00]),
};
assert_eq!(section.origin, Some(512));
}
#[test]
fn binary_section_nil_data() {
let section = BinarySection {
section: vec![],
origin: None,
data: None,
};
assert!(section.data.is_none());
}
#[test]
fn fetch_response_multiple_body_sections() {
let resp = FetchResponse {
seq: 3,
body_sections: vec![
BodySection {
section: "HEADER".into(),
origin: None,
data: Some(b"From: alice@example.com\r\n".to_vec()),
},
BodySection {
section: "TEXT".into(),
origin: None,
data: Some(b"Hello world".to_vec()),
},
],
..Default::default()
};
assert_eq!(resp.body_sections.len(), 2);
assert_eq!(resp.body_sections[0].section, "HEADER");
assert_eq!(resp.body_sections[1].section, "TEXT");
}
#[test]
fn fetch_response_binary_sizes() {
let resp = FetchResponse {
seq: 1,
binary_sizes: vec![(vec![1], 1024), (vec![2, 1], 512)],
..Default::default()
};
assert_eq!(resp.binary_sizes.len(), 2);
assert_eq!(resp.binary_sizes[0], (vec![1], 1024));
assert_eq!(resp.binary_sizes[1], (vec![2, 1], 512));
}
#[test]
fn fetch_attr_simple_variants() {
assert_eq!(FetchAttr::Uid, FetchAttr::Uid);
assert_eq!(FetchAttr::Flags, FetchAttr::Flags);
assert_eq!(FetchAttr::Envelope, FetchAttr::Envelope);
assert_eq!(FetchAttr::BodyStructure, FetchAttr::BodyStructure);
assert_eq!(FetchAttr::Rfc822Size, FetchAttr::Rfc822Size);
assert_eq!(FetchAttr::InternalDate, FetchAttr::InternalDate);
assert_eq!(FetchAttr::Rfc822, FetchAttr::Rfc822);
assert_eq!(FetchAttr::Rfc822Header, FetchAttr::Rfc822Header);
assert_eq!(FetchAttr::Rfc822Text, FetchAttr::Rfc822Text);
assert_eq!(FetchAttr::ModSeq, FetchAttr::ModSeq);
assert_eq!(FetchAttr::SaveDate, FetchAttr::SaveDate);
assert_eq!(FetchAttr::Preview, FetchAttr::Preview);
assert_eq!(FetchAttr::PreviewLazy, FetchAttr::PreviewLazy);
assert_eq!(FetchAttr::EmailId, FetchAttr::EmailId);
assert_eq!(FetchAttr::ThreadId, FetchAttr::ThreadId);
}
#[test]
fn fetch_response_with_preview() {
let resp = FetchResponse {
seq: 1,
preview: Some("Meeting tomorrow at 3pm to discuss...".into()),
..Default::default()
};
assert_eq!(
resp.preview.as_deref(),
Some("Meeting tomorrow at 3pm to discuss...")
);
}
#[test]
fn fetch_response_with_preview_nil() {
let resp = FetchResponse {
seq: 1,
preview: None,
..Default::default()
};
assert!(resp.preview.is_none());
}
#[test]
fn fetch_response_with_email_id() {
let resp = FetchResponse {
seq: 1,
email_id: Some("M6d99ac3275826486".into()),
..Default::default()
};
assert_eq!(resp.email_id.as_deref(), Some("M6d99ac3275826486"));
}
#[test]
fn fetch_response_with_thread_id() {
let resp = FetchResponse {
seq: 1,
thread_id: Some("T64b478a75b7ea9fd".into()),
..Default::default()
};
assert_eq!(resp.thread_id.as_deref(), Some("T64b478a75b7ea9fd"));
}
#[test]
fn fetch_attr_body_section_peek() {
let attr = FetchAttr::BodySection {
peek: true,
section: Some("HEADER".into()),
partial: None,
};
match &attr {
FetchAttr::BodySection {
peek,
section,
partial,
} => {
assert!(*peek);
assert_eq!(section.as_deref(), Some("HEADER"));
assert!(partial.is_none());
}
_ => panic!("expected BodySection"),
}
}
#[test]
fn fetch_attr_body_section_with_partial() {
let attr = FetchAttr::BodySection {
peek: false,
section: Some("1".into()),
partial: Some((0, 1024)),
};
match &attr {
FetchAttr::BodySection { partial, .. } => {
assert_eq!(*partial, Some((0, 1024)));
}
_ => panic!("expected BodySection"),
}
}
#[test]
fn fetch_attr_body_section_no_section() {
let attr = FetchAttr::BodySection {
peek: false,
section: None,
partial: None,
};
match &attr {
FetchAttr::BodySection { section, .. } => {
assert!(section.is_none());
}
_ => panic!("expected BodySection"),
}
}
#[test]
fn fetch_attr_binary() {
let attr = FetchAttr::Binary {
peek: true,
section: vec![1, 2],
partial: Some((0, 512)),
};
match &attr {
FetchAttr::Binary {
peek,
section,
partial,
} => {
assert!(*peek);
assert_eq!(section, &[1, 2]);
assert_eq!(*partial, Some((0, 512)));
}
_ => panic!("expected Binary"),
}
}
#[test]
fn fetch_attr_binary_size() {
let attr = FetchAttr::BinarySize {
section: vec![3, 1],
};
match &attr {
FetchAttr::BinarySize { section } => {
assert_eq!(section, &[3, 1]);
}
_ => panic!("expected BinarySize"),
}
}
#[test]
fn store_operation_variants() {
assert_eq!(StoreOperation::Add, StoreOperation::Add);
assert_eq!(StoreOperation::Remove, StoreOperation::Remove);
assert_eq!(StoreOperation::Replace, StoreOperation::Replace);
assert_ne!(StoreOperation::Add, StoreOperation::Remove);
assert_ne!(StoreOperation::Remove, StoreOperation::Replace);
}
#[test]
fn store_operation_copy() {
let op = StoreOperation::Add;
let op2 = op; assert_eq!(op, op2);
}
#[test]
fn append_message_basic() {
let msg = AppendMessage {
flags: vec![Flag::Seen],
date: Some("01-Jan-2024 00:00:00 +0000".into()),
data: b"From: test@example.com\r\nSubject: Hi\r\n\r\nBody".to_vec(),
};
assert_eq!(msg.flags.len(), 1);
assert_eq!(msg.flags[0], Flag::Seen);
assert!(msg.date.is_some());
assert!(!msg.data.is_empty());
}
#[test]
fn append_message_no_flags_no_date() {
let msg = AppendMessage {
flags: vec![],
date: None,
data: b"minimal message".to_vec(),
};
assert!(msg.flags.is_empty());
assert!(msg.date.is_none());
}
#[test]
fn fetch_response_clone_eq() {
let resp = FetchResponse {
seq: 10,
uid: Some(500),
flags: Some(vec![Flag::Draft]),
..Default::default()
};
let cloned = resp.clone();
assert_eq!(resp, cloned);
}
#[test]
fn body_section_clone_eq() {
let section = BodySection {
section: "1.2".into(),
origin: Some(0),
data: Some(b"data".to_vec()),
};
let cloned = section.clone();
assert_eq!(section, cloned);
}
#[test]
fn store_result_provides_access_to_fetches() {
let result = StoreResult {
fetches: vec![
FetchResponse {
seq: 1,
uid: Some(100),
flags: Some(vec![Flag::Seen]),
..Default::default()
},
FetchResponse {
seq: 2,
uid: Some(101),
flags: Some(vec![Flag::Flagged]),
..Default::default()
},
],
code: None,
};
assert_eq!(result.fetches.len(), 2);
assert_eq!(result.fetches[0].seq, 1);
assert_eq!(result.fetches[1].uid, Some(101));
let seqs: Vec<u32> = result.fetches.iter().map(|f| f.seq).collect();
assert_eq!(seqs, vec![1, 2]);
}
#[test]
fn store_result_empty() {
let result = StoreResult {
fetches: vec![],
code: None,
};
assert!(result.fetches.is_empty());
}
#[test]
fn fetch_response_debug() {
let resp = FetchResponse {
seq: 1,
uid: Some(42),
..Default::default()
};
let debug = format!("{resp:?}");
assert!(debug.contains("seq: 1"));
assert!(debug.contains("uid: Some(42)"));
}
#[test]
fn fetch_attr_simple_items() {
assert_eq!(FetchAttr::Uid.to_imap_string(), "UID");
assert_eq!(FetchAttr::Flags.to_imap_string(), "FLAGS");
assert_eq!(FetchAttr::Envelope.to_imap_string(), "ENVELOPE");
assert_eq!(FetchAttr::BodyStructure.to_imap_string(), "BODYSTRUCTURE");
assert_eq!(FetchAttr::Rfc822Size.to_imap_string(), "RFC822.SIZE");
assert_eq!(FetchAttr::InternalDate.to_imap_string(), "INTERNALDATE");
assert_eq!(FetchAttr::Rfc822.to_imap_string(), "RFC822");
assert_eq!(FetchAttr::Rfc822Header.to_imap_string(), "RFC822.HEADER");
assert_eq!(FetchAttr::Rfc822Text.to_imap_string(), "RFC822.TEXT");
assert_eq!(FetchAttr::ModSeq.to_imap_string(), "MODSEQ");
assert_eq!(FetchAttr::SaveDate.to_imap_string(), "SAVEDATE");
assert_eq!(FetchAttr::Preview.to_imap_string(), "PREVIEW");
assert_eq!(FetchAttr::PreviewLazy.to_imap_string(), "PREVIEW (LAZY)");
assert_eq!(FetchAttr::EmailId.to_imap_string(), "EMAILID");
assert_eq!(FetchAttr::ThreadId.to_imap_string(), "THREADID");
}
#[test]
fn fetch_attr_body_section_no_section_no_partial() {
let attr = FetchAttr::BodySection {
peek: false,
section: None,
partial: None,
};
assert_eq!(attr.to_imap_string(), "BODY[]");
}
#[test]
fn fetch_attr_body_section_peek_with_section() {
let attr = FetchAttr::BodySection {
peek: true,
section: Some("HEADER".into()),
partial: None,
};
assert_eq!(attr.to_imap_string(), "BODY.PEEK[HEADER]");
}
#[test]
fn fetch_attr_body_section_wire_format_with_partial() {
let attr = FetchAttr::BodySection {
peek: false,
section: Some("TEXT".into()),
partial: Some((0, 1024)),
};
assert_eq!(attr.to_imap_string(), "BODY[TEXT]<0.1024>");
}
#[test]
fn fetch_attr_binary_section() {
let attr = FetchAttr::Binary {
peek: false,
section: vec![1, 2],
partial: None,
};
assert_eq!(attr.to_imap_string(), "BINARY[1.2]");
}
#[test]
fn fetch_attr_binary_peek_with_partial() {
let attr = FetchAttr::Binary {
peek: true,
section: vec![3],
partial: Some((100, 200)),
};
assert_eq!(attr.to_imap_string(), "BINARY.PEEK[3]<100.200>");
}
#[test]
fn fetch_attr_binary_size_wire_format() {
let attr = FetchAttr::BinarySize {
section: vec![1, 2, 3],
};
assert_eq!(attr.to_imap_string(), "BINARY.SIZE[1.2.3]");
}
#[test]
fn format_single_attr_no_parens() {
assert_eq!(format_fetch_attrs(&[FetchAttr::Flags]), "FLAGS");
}
#[test]
fn format_multiple_attrs_with_parens() {
let result = format_fetch_attrs(&[FetchAttr::Uid, FetchAttr::Flags, FetchAttr::Envelope]);
assert_eq!(result, "(UID FLAGS ENVELOPE)");
}