diff --git a/crates/model/src/b64.rs b/crates/model/src/b64.rs index b377fe451..f36ede104 100644 --- a/crates/model/src/b64.rs +++ b/crates/model/src/b64.rs @@ -90,10 +90,11 @@ pub mod opt { #[cfg(test)] mod tests { #[test] - fn roundtrip() { + fn roundtrip() -> Result<(), Box> { for data in [&b""[..], b"a", b"ab", b"abc", b"hello world", &[0, 255, 128, 7]] { - assert_eq!(super::decode(&super::encode(data)).unwrap(), data); + assert_eq!(super::decode(&super::encode(data)).ok_or("none")?, data); } assert_eq!(super::encode(b"Man"), "TWFu"); + Ok(()) } } diff --git a/crates/model/src/cellmap.rs b/crates/model/src/cellmap.rs index f72b7b5af..bc120acce 100644 --- a/crates/model/src/cellmap.rs +++ b/crates/model/src/cellmap.rs @@ -27,7 +27,7 @@ mod tests { use gridcraft_core::CellRef; #[test] - fn comments_and_hyperlinks_survive_json() { + fn comments_and_hyperlinks_survive_json() -> Result<(), Box> { let mut s = Sheet::new("S"); let a1 = CellRef::new(0, 0); let c3 = CellRef::new(2, 2); @@ -45,9 +45,10 @@ mod tests { }, ); s.hyperlinks.insert(c3, Hyperlink { target: "Sheet1!A1".into(), tooltip: Some("jump".into()), external: false }); - let json = serde_json::to_string(&s).expect("serialize"); - let back: Sheet = serde_json::from_str(&json).expect("deserialize"); + let json = serde_json::to_string(&s)?; + let back: Sheet = serde_json::from_str(&json)?; assert_eq!(back.comments, s.comments); assert_eq!(back.hyperlinks, s.hyperlinks); + Ok(()) } } diff --git a/crates/model/src/features/pivot.rs b/crates/model/src/features/pivot.rs index 368aa1f53..b34015f4c 100644 --- a/crates/model/src/features/pivot.rs +++ b/crates/model/src/features/pivot.rs @@ -1,4 +1,5 @@ -use super::*; +use super::{CellRef, RangeRef}; +use serde::{Deserialize, Serialize}; // ---------------------------------------------------------------- pivot tables diff --git a/crates/model/src/features/print.rs b/crates/model/src/features/print.rs index 6a4ab0be0..cbcaf3e55 100644 --- a/crates/model/src/features/print.rs +++ b/crates/model/src/features/print.rs @@ -1,4 +1,5 @@ -use super::*; +use super::{CellRef, RangeRef}; +use serde::{Deserialize, Serialize}; #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum Orientation { diff --git a/crates/model/src/password.rs b/crates/model/src/password.rs index 59b9aafba..f46de4b44 100644 --- a/crates/model/src/password.rs +++ b/crates/model/src/password.rs @@ -106,28 +106,30 @@ mod tests { use super::*; #[test] - fn legacy_hash_matches_the_published_example() { + fn legacy_hash_matches_the_published_example() -> Result<(), Box> { // The hash Excel writes for the password "password" (`password="83AF"`). assert_eq!(legacy_hash("password"), 0x83AF); - assert!(PasswordHash::Legacy(0x83AF).verify("password").unwrap()); - assert!(!PasswordHash::Legacy(0x83AF).verify("Password").unwrap()); + assert!(PasswordHash::Legacy(0x83AF).verify("password")?); + assert!(!PasswordHash::Legacy(0x83AF).verify("Password")?); assert_eq!(legacy_hash(""), 0xCE4B); + Ok(()) } #[test] - fn iterated_hash_verifies_and_refuses_what_it_cannot_check() { + fn iterated_hash_verifies_and_refuses_what_it_cannot_check() -> Result<(), Box> { let h = PasswordHash::new_sha512("s3cret", b"0123456789abcdef"); - assert!(h.verify("s3cret").unwrap()); - assert!(!h.verify("s3cret ").unwrap()); + assert!(h.verify("s3cret")?); + assert!(!h.verify("s3cret ")?); assert!(matches!(&h, PasswordHash::Iterated { algorithm, spin_count: DEFAULT_SPIN_COUNT, .. } if algorithm == "SHA-512")); - let PasswordHash::Iterated { hash, salt, .. } = h else { return }; + let PasswordHash::Iterated { hash, salt, .. } = h else { return Err("not an iterated hash".into()) }; let other = |algorithm: &str, spin_count| PasswordHash::Iterated { algorithm: algorithm.into(), hash: hash.clone(), salt: salt.clone(), spin_count }; assert!(other("SHA-1", 10).verify("s3cret").is_err()); assert!(other("MD5", 10).verify("s3cret").is_err()); assert!(other("SHA-512", MAX_SPIN_COUNT + 1).verify("s3cret").is_err()); - assert!(!other("SHA-256", 2).verify("s3cret").unwrap()); + assert!(!other("SHA-256", 2).verify("s3cret")?); let broken = PasswordHash::Iterated { algorithm: "SHA-512".into(), hash: "!!".into(), salt: salt.clone(), spin_count: 1 }; assert!(broken.verify("s3cret").is_err()); + Ok(()) } } diff --git a/crates/model/src/store.rs b/crates/model/src/store.rs index 531273ce9..d6beb4994 100644 --- a/crates/model/src/store.rs +++ b/crates/model/src/store.rs @@ -330,30 +330,32 @@ mod tests { } #[test] - fn set_get_remove() { + fn set_get_remove() -> Result<(), Box> { let mut s = CellStore::new(); s.set(c(0, 0), Cell::value(1.0.into())); s.set(c(100, 5), Cell::value("x".into())); assert_eq!(s.len(), 2); assert_eq!(s.get(c(100, 5)).map(|x| x.value.clone()), Some(Value::from("x"))); - assert_eq!(s.used_range().unwrap().a1(), "A1:F101"); + assert_eq!(s.used_range().ok_or("none")?.a1(), "A1:F101"); s.set(c(0, 0), Cell::default()); assert_eq!(s.len(), 1); assert!(s.remove(c(100, 5)).is_some()); assert!(s.is_empty()); assert!(s.used_range().is_none()); + Ok(()) } #[test] - fn cow_snapshots() { + fn cow_snapshots() -> Result<(), Box> { let mut s = CellStore::new(); for r in 0..1000 { s.set(c(r, 0), Cell::value((r as f64).into())); } let snap = s.clone(); s.set(c(5, 0), Cell::value(99.0.into())); - assert_eq!(snap.get(c(5, 0)).unwrap().value, Value::Number(5.0)); - assert_eq!(s.get(c(5, 0)).unwrap().value, Value::Number(99.0)); + assert_eq!(snap.get(c(5, 0)).ok_or("none")?.value, Value::Number(5.0)); + assert_eq!(s.get(c(5, 0)).ok_or("none")?.value, Value::Number(99.0)); + Ok(()) } #[test] @@ -371,14 +373,16 @@ mod tests { } #[test] - fn range_iteration_order() { + fn range_iteration_order() -> Result<(), Box> { let mut s = CellStore::new(); s.set(c(70, 2), Cell::value(3.0.into())); s.set(c(1, 1), Cell::value(1.0.into())); s.set(c(1, 3), Cell::value(2.0.into())); s.set(c(500, 0), Cell::value(4.0.into())); - let v: Vec = s.iter_range(RangeRef::parse("A1:D100").unwrap()).map(|(_, x)| x.value.as_f64().unwrap()).collect(); + let v: Vec = + s.iter_range(RangeRef::parse("A1:D100").ok_or("none")?).map(|(_, x)| x.value.as_f64()).collect::>().ok_or("none")?; assert_eq!(v, [1.0, 2.0, 3.0]); + Ok(()) } #[test] diff --git a/crates/model/src/style.rs b/crates/model/src/style.rs index 1ded99288..d2f10780e 100644 --- a/crates/model/src/style.rs +++ b/crates/model/src/style.rs @@ -500,32 +500,34 @@ mod tests { } #[test] - fn a_theme_saved_before_per_script_fonts_still_opens() { - let mut json = serde_json::to_value(Theme::default()).unwrap(); - let fields = json.as_object_mut().unwrap(); + fn a_theme_saved_before_per_script_fonts_still_opens() -> Result<(), Box> { + let mut json = serde_json::to_value(Theme::default())?; + let fields = json.as_object_mut().ok_or("none")?; assert!(fields.remove("major_font_scripts").is_some() && fields.remove("minor_font_scripts").is_some()); - assert_eq!(serde_json::from_value::(json).unwrap(), Theme::default()); + assert_eq!(serde_json::from_value::(json)?, Theme::default()); + Ok(()) } #[test] - fn colors() { + fn colors() -> Result<(), Box> { let th = Theme::default(); - assert_eq!(Color::from_hex("#FF0000").unwrap().resolve(&th), Some([255, 0, 0])); - assert_eq!(Color::from_hex("FF00FF00").unwrap().resolve(&th), Some([0, 255, 0])); + assert_eq!(Color::from_hex("#FF0000").ok_or("none")?.resolve(&th), Some([255, 0, 0])); + assert_eq!(Color::from_hex("FF00FF00").ok_or("none")?.resolve(&th), Some([0, 255, 0])); assert_eq!(Color::Theme(0, -500).resolve(&th), Some([128, 128, 128])); assert_eq!(Color::Theme(1, 500).resolve(&th), Some([128, 128, 128])); assert_eq!(Color::Auto.resolve(&th), None); + Ok(()) } #[test] - fn theme_json_keeps_ea_and_cs_and_reads_old_json() { + fn theme_json_keeps_ea_and_cs_and_reads_old_json() -> Result<(), Box> { // JSON written before the ea/cs fields existed still deserializes (`serde(default)`). - let mut old = serde_json::to_value(Theme::default()).unwrap(); - let obj = old.as_object_mut().unwrap(); + let mut old = serde_json::to_value(Theme::default())?; + let obj = old.as_object_mut().ok_or("none")?; for key in ["major_font_ea", "minor_font_ea", "major_font_cs", "minor_font_cs"] { assert!(obj.remove(key).is_some(), "the default theme serializes {key}"); } - assert_eq!(serde_json::from_value::(old).unwrap(), Theme::default()); + assert_eq!(serde_json::from_value::(old)?, Theme::default()); // Set fields serialize and come back. let t = Theme { @@ -535,8 +537,9 @@ mod tests { minor_font_cs: "Times New Roman".into(), ..Theme::default() }; - let json = serde_json::to_string(&t).unwrap(); + let json = serde_json::to_string(&t)?; assert!(json.contains("major_font_ea") && json.contains("游ゴシック"), "{json}"); - assert_eq!(serde_json::from_str::(&json).unwrap(), t); + assert_eq!(serde_json::from_str::(&json)?, t); + Ok(()) } } diff --git a/crates/model/src/workbook.rs b/crates/model/src/workbook.rs index ac6b3131b..ab02c4536 100644 --- a/crates/model/src/workbook.rs +++ b/crates/model/src/workbook.rs @@ -439,7 +439,7 @@ mod tests { use super::*; #[test] - fn phonetics_are_additive_in_json() { + fn phonetics_are_additive_in_json() -> Result<(), Box> { let mut wb = Workbook::new(); assert!(wb.phonetics.is_empty(), "new workbooks have no phonetic data"); wb.phonetics.push(PhoneticString { @@ -447,12 +447,13 @@ mod tests { runs: vec![PhoneticRun { start: 0, end: 1, text: "ヒガシ".into() }], props: Some(PhoneticProps { font_id: 3, kind: Some("Hiragana".into()), alignment: None }), }); - let json = serde_json::to_string(&wb).expect("serialize"); - assert_eq!(serde_json::from_str::(&json).expect("deserialize").phonetics, wb.phonetics); + let json = serde_json::to_string(&wb)?; + assert_eq!(serde_json::from_str::(&json)?.phonetics, wb.phonetics); // JSON written before the field existed still loads. - let mut value: serde_json::Value = serde_json::from_str(&json).expect("value"); - value.as_object_mut().expect("an object").remove("phonetics"); - assert!(serde_json::from_value::(value).expect("older JSON").phonetics.is_empty()); + let mut value: serde_json::Value = serde_json::from_str(&json)?; + value.as_object_mut().ok_or("none")?.remove("phonetics"); + assert!(serde_json::from_value::(value)?.phonetics.is_empty()); + Ok(()) } #[test]