#![allow(clippy::unwrap_used)] #![allow(clippy::print_stdout)] use crate::test::util::new_empty_model; // These tests are grouped because in many cases XOR and OR have similar behaviour. // Test specific to xor #[test] fn fn_xor() { let mut model = new_empty_model(); model._set("A1", "=XOR(1, 1, 1, 0, 0)"); model._set("A2", "=XOR(1, 1, 0, 0, 0)"); model._set("A3", "=XOR(TRUE, TRUE, TRUE, FALSE, FALSE)"); model._set("A4", "=XOR(TRUE, TRUE, FALSE, FALSE, FALSE)"); model._set("A5", "=XOR(FALSE, FALSE, FALSE, FALSE, FALSE)"); model._set("A6", "=XOR(TRUE, TRUE)"); model._set("A7", "=XOR(0,0,0)"); model._set("A8", "=XOR(0,0,1)"); model._set("A9", "=XOR(0,1,0)"); model._set("A10", "=XOR(0,1,1)"); model._set("A11", "=XOR(1,0,0)"); model._set("A12", "=XOR(1,0,1)"); model._set("A13", "=XOR(1,1,0)"); model._set("A14", "=XOR(1,1,1)"); model.evaluate(); assert_eq!(model._get_text("A1"), *"TRUE"); assert_eq!(model._get_text("A2"), *"FALSE"); assert_eq!(model._get_text("A3"), *"TRUE"); assert_eq!(model._get_text("A4"), *"FALSE"); assert_eq!(model._get_text("A5"), *"FALSE"); assert_eq!(model._get_text("A6"), *"FALSE"); assert_eq!(model._get_text("A7"), *"FALSE"); assert_eq!(model._get_text("A8"), *"TRUE"); assert_eq!(model._get_text("A9"), *"TRUE"); assert_eq!(model._get_text("A10"), *"FALSE"); assert_eq!(model._get_text("A11"), *"TRUE"); assert_eq!(model._get_text("A12"), *"FALSE"); assert_eq!(model._get_text("A13"), *"FALSE"); assert_eq!(model._get_text("A14"), *"TRUE"); } #[test] fn fn_or() { let mut model = new_empty_model(); model._set("A1", "=OR(1, 1, 1, 0, 0)"); model._set("A2", "=OR(1, 1, 0, 0, 0)"); model._set("A3", "=OR(TRUE, TRUE, TRUE, FALSE, FALSE)"); model._set("A4", "=OR(TRUE, TRUE, FALSE, FALSE, FALSE)"); model._set("A5", "=OR(FALSE, FALSE, FALSE, FALSE, FALSE)"); model._set("A6", "=OR(TRUE, TRUE)"); model.evaluate(); assert_eq!(model._get_text("A1"), *"TRUE"); assert_eq!(model._get_text("A2"), *"TRUE"); assert_eq!(model._get_text("A3"), *"TRUE"); assert_eq!(model._get_text("A4"), *"TRUE"); assert_eq!(model._get_text("A5"), *"FALSE"); assert_eq!(model._get_text("A6"), *"TRUE"); } #[test] fn fn_or_xor() { inner("or"); inner("xor"); fn inner(func: &str) { println!("Testing function: {func}"); let mut model = new_empty_model(); // Text args model._set("A1", &format!(r#"={func}("")"#)); model._set("A2", &format!(r#"={func}("", "")"#)); model._set("A3", &format!(r#"={func}("", TRUE)"#)); model._set("A4", &format!(r#"={func}("", FALSE)"#)); model._set("A5", &format!("={func}(FALSE, TRUE)")); model._set("A6", &format!("={func}(FALSE, FALSE)")); model._set("A7", &format!("={func}(TRUE, FALSE)")); // Reference to empty cell, plus true argument model._set("A8", &format!("={func}(Z99, 1)")); // Reference to empty cell/range model._set("A9", &format!("={func}(Z99)")); model._set("A10", &format!("={func}(X99:Z99")); // Reference to cell with reference to empty range model._set("B11", "=X99:Z99"); model._set("A11", &format!("={func}(B11)")); // Reference to cell with non-empty range model._set("X12", "1"); model._set("B12", "=X12:Z12"); model._set("A12", &format!("={func}(B12)")); // Reference to text cell model._set("B13", "some_text"); model._set("A13", &format!("={func}(B13)")); model._set("A14", &format!("={func}(B13, 0)")); model._set("A15", &format!("={func}(B13, 1)")); // Reference to Implicit intersection model._set("X16", "1"); model._set("B16", "=@X15:X16"); model._set("A16", &format!("={func}(B16)")); // Non-empty range model._set("B17", "1"); model._set("A17", &format!("={func}(B17:C17)")); // Non-empty range with text model._set("B18", "text"); model._set("A18", &format!("={func}(B18:C18)")); // Non-empty range with text and number model._set("B19", "text"); model._set("C19", "1"); model._set("A19", &format!("={func}(B19:C19)")); // range with error model._set("B20", "=1/0"); model._set("A20", &format!("={func}(B20:C20)")); model.evaluate(); assert_eq!(model._get_text("A1"), *"#VALUE!"); assert_eq!(model._get_text("A2"), *"#VALUE!"); assert_eq!(model._get_text("A3"), *"TRUE"); assert_eq!(model._get_text("A4"), *"FALSE"); assert_eq!(model._get_text("A5"), *"TRUE"); assert_eq!(model._get_text("A6"), *"FALSE"); assert_eq!(model._get_text("A7"), *"TRUE"); assert_eq!(model._get_text("A8"), *"TRUE"); assert_eq!(model._get_text("A9"), *"#VALUE!"); assert_eq!(model._get_text("A10"), *"#VALUE!"); assert_eq!(model._get_text("A11"), *"#VALUE!"); // TODO: This one depends on spill behaviour which isn't implemented yet // assert_eq!(model._get_text("A12"), *"TRUE"); assert_eq!(model._get_text("A13"), *"#VALUE!"); assert_eq!(model._get_text("A14"), *"FALSE"); assert_eq!(model._get_text("A15"), *"TRUE"); // TODO: This one depends on @ implicit intersection behaviour which isn't implemented yet // assert_eq!(model._get_text("A16"), *"TRUE"); assert_eq!(model._get_text("A17"), *"TRUE"); assert_eq!(model._get_text("A18"), *"#VALUE!"); assert_eq!(model._get_text("A19"), *"TRUE"); assert_eq!(model._get_text("A20"), *"#DIV/0!"); } } #[test] fn fn_or_xor_no_arguments() { inner("or"); inner("xor"); fn inner(func: &str) { println!("Testing function: {func}"); let mut model = new_empty_model(); model._set("A1", &format!("={func}()")); model.evaluate(); assert_eq!(model._get_text("A1"), *"#ERROR!"); } } #[test] fn fn_or_xor_missing_arguments() { inner("or"); inner("xor"); fn inner(func: &str) { println!("Testing function: {func}"); let mut model = new_empty_model(); model._set("A1", &format!("={func}(,)")); model._set("A2", &format!("={func}(,1)")); model._set("A3", &format!("={func}(1,)")); model._set("A4", &format!("={func}(,B1)")); model._set("A5", &format!("={func}(,B1:B4)")); model.evaluate(); assert_eq!(model._get_text("A1"), *"FALSE"); assert_eq!(model._get_text("A2"), *"TRUE"); assert_eq!(model._get_text("A3"), *"TRUE"); assert_eq!(model._get_text("A4"), *"FALSE"); assert_eq!(model._get_text("A5"), *"FALSE"); } }