From fc1be038c25297dc5de38a9177857eb89d188e80 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 9 Jun 2025 14:47:30 -0700 Subject: [PATCH] more tests --- rust/pspp/src/output/mod.rs | 39 +++++++++++++++- rust/pspp/src/output/pivot/mod.rs | 16 ++++++- rust/pspp/src/output/text.rs | 2 +- rust/pspp/src/sys/test.rs | 10 ++++ .../src/sys/testdata/compressed_data.expected | 23 ++++++++++ .../src/sys/testdata/compressed_data.sack | 32 +++++++++++++ .../src/sys/testdata/variable_roles.expected | 46 +++++++++++++++++++ .../pspp/src/sys/testdata/variable_roles.sack | 39 ++++++++++++++++ 8 files changed, 203 insertions(+), 4 deletions(-) create mode 100644 rust/pspp/src/sys/testdata/compressed_data.expected create mode 100644 rust/pspp/src/sys/testdata/compressed_data.sack create mode 100644 rust/pspp/src/sys/testdata/variable_roles.expected create mode 100644 rust/pspp/src/sys/testdata/variable_roles.sack diff --git a/rust/pspp/src/output/mod.rs b/rust/pspp/src/output/mod.rs index ff054b9e46..a39cb9da19 100644 --- a/rust/pspp/src/output/mod.rs +++ b/rust/pspp/src/output/mod.rs @@ -1,9 +1,16 @@ #![allow(dead_code)] -use std::{borrow::Cow, sync::Arc}; +use std::{ + borrow::Cow, + sync::{Arc, OnceLock}, +}; +use enum_map::EnumMap; use pivot::PivotTable; -use crate::message::Diagnostic; +use crate::{ + message::Diagnostic, + output::pivot::{Axis3, BorderStyle, Dimension, Group, Look}, +}; use self::pivot::Value; @@ -157,6 +164,7 @@ impl From> for Details { } } +#[derive(Clone, Debug)] pub struct Text { type_: TextType, @@ -172,12 +180,39 @@ impl Text { } } +fn text_item_table_look() -> Arc { + static LOOK: OnceLock> = OnceLock::new(); + LOOK.get_or_init(|| { + Arc::new({ + let mut look = Look::default().with_borders(EnumMap::from_fn(|_| BorderStyle::none())); + for style in look.areas.values_mut() { + style.cell_style.margins = EnumMap::from_fn(|_| [0, 0]); + } + look + }) + }) + .clone() +} + +impl From for PivotTable { + fn from(value: Text) -> Self { + let dimension = + Dimension::new(Group::new(Value::new_text("Text")).with(Value::new_user_text("null"))) + .with_all_labels_hidden(); + PivotTable::new([(Axis3::Y, dimension)]) + .with_look(text_item_table_look()) + .with_data([(&[0], value.content)]) + .with_subtype(Value::new_user_text("Text")) + } +} + impl From<&Diagnostic> for Text { fn from(value: &Diagnostic) -> Self { Self::new_log(value.to_string()) } } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum TextType { /// `TITLE` and `SUBTITLE` commands. PageTitle, diff --git a/rust/pspp/src/output/pivot/mod.rs b/rust/pspp/src/output/pivot/mod.rs index ce2db04c91..2fb4dfa773 100644 --- a/rust/pspp/src/output/pivot/mod.rs +++ b/rust/pspp/src/output/pivot/mod.rs @@ -375,6 +375,13 @@ impl Dimension { pub fn leaf_path(&self, index: usize) -> Option> { self.root.leaf_path(index, SmallVec::new()) } + + pub fn with_all_labels_hidden(self) -> Self { + Self { + hide_all_labels: true, + ..self + } + } } #[derive(Clone, Debug)] @@ -1334,6 +1341,13 @@ impl PivotTable { self } + pub fn with_subtype(self, subtype: Value) -> Self { + Self { + subtype: Some(Box::new(subtype)), + ..self + } + } + pub fn with_show_title(mut self, show_title: bool) -> Self { self.show_title = show_title; self @@ -1486,7 +1500,7 @@ impl PivotTable { self.cells.get(&self.cell_index(data_indexes)) } - pub fn with_data(mut self, iter: impl Iterator) -> Self + pub fn with_data(mut self, iter: impl IntoIterator) -> Self where I: AsRef<[usize]>, { diff --git a/rust/pspp/src/output/text.rs b/rust/pspp/src/output/text.rs index c29fad0545..8f556454b3 100644 --- a/rust/pspp/src/output/text.rs +++ b/rust/pspp/src/output/text.rs @@ -370,7 +370,7 @@ impl TextRenderer { Details::Message(_diagnostic) => todo!(), Details::PageBreak => Ok(()), Details::Table(pivot_table) => self.render_table(&*pivot_table, writer), - Details::Text(_text) => todo!(), + Details::Text(text) => self.render_table(&PivotTable::from((**text).clone()), writer), } } diff --git a/rust/pspp/src/sys/test.rs b/rust/pspp/src/sys/test.rs index 69e1af3e1c..e5f5f914fe 100644 --- a/rust/pspp/src/sys/test.rs +++ b/rust/pspp/src/sys/test.rs @@ -87,6 +87,16 @@ fn attributes() { test_sysfile("attributes"); } +#[test] +fn variable_roles() { + test_sysfile("variable_roles"); +} + +#[test] +fn compressed_data() { + test_sysfile("compressed_data"); +} + fn test_sysfile(name: &str) { let input_filename = Path::new(env!("CARGO_MANIFEST_DIR")) .join("src/sys/testdata") diff --git a/rust/pspp/src/sys/testdata/compressed_data.expected b/rust/pspp/src/sys/testdata/compressed_data.expected new file mode 100644 index 0000000000..f36fb5ebce --- /dev/null +++ b/rust/pspp/src/sys/testdata/compressed_data.expected @@ -0,0 +1,23 @@ +╭──────────────────────┬────────────────────────╮ +│ Created │ 01-JAN-2011 20:53:52│ +├──────────────────────┼────────────────────────┤ +│Writer Product │PSPP synthetic test file│ +├──────────────────────┼────────────────────────┤ +│ Compression │SAV │ +│ Number of Cases│Unknown │ +╰──────────────────────┴────────────────────────╯ + +╭─────────┬────────────────────────╮ +│Label │PSPP synthetic test file│ +│Variables│ 5│ +╰─────────┴────────────────────────╯ + +╭─────┬────────┬─────┬─────────────────┬─────┬─────┬─────────┬────────────┬────────────┬──────────────╮ +│ │Position│Label│Measurement Level│ Role│Width│Alignment│Print Format│Write Format│Missing Values│ +├─────┼────────┼─────┼─────────────────┼─────┼─────┼─────────┼────────────┼────────────┼──────────────┤ +│num1 │ 1│ │ │Input│ 8│Right │F8.0 │F8.0 │ │ +│num2 │ 2│ │ │Input│ 8│Right │F8.0 │F8.0 │ │ +│str4 │ 3│ │Nominal │Input│ 4│Left │A4 │A4 │ │ +│str8 │ 4│ │Nominal │Input│ 8│Left │A8 │A8 │ │ +│str15│ 5│ │Nominal │Input│ 15│Left │A15 │A15 │ │ +╰─────┴────────┴─────┴─────────────────┴─────┴─────┴─────────┴────────────┴────────────┴──────────────╯ diff --git a/rust/pspp/src/sys/testdata/compressed_data.sack b/rust/pspp/src/sys/testdata/compressed_data.sack new file mode 100644 index 0000000000..fec8358d97 --- /dev/null +++ b/rust/pspp/src/sys/testdata/compressed_data.sack @@ -0,0 +1,32 @@ +# File header. +"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file"; +2; # Layout code +6; # Nominal case size +1; # Simple compression +0; # Not weighted +-1; # Unspecified number of cases. +100.0; # Bias. +"01 Jan 11"; "20:53:52"; s64 "PSPP synthetic test file"; +i8 0 *3; + +# Numeric variables. +2; 0; 0; 0; 0x050800 *2; s8 "NUM1"; +2; 0; 0; 0; 0x050800 *2; s8 "NUM2"; + +# String variable. +2; 4; 0; 0; 0x010400 *2; s8 "STR4"; +2; 8; 0; 0; 0x010800 *2; s8 "STR8"; +2; 15; 0; 0; 0x010f00 *2; s8 "STR15"; +2; -1; 0; 0; 0; 0; s8 ""; + +# Character encoding record. +7; 20; 1; 12; "windows-1252"; + +# Dictionary termination record. +999; 0; + +# Compressed data. +i8 1 100 254 253 254 253; i8 255 251; "abcdefgh"; s8 "0123"; +i8 253 253 253 254; i8 101 102 253 253; s8 "jklm"; s8 "nopqrstu"; +s8 "vwxyzABC"; s8 "DEFG"; s8 "HIJKLMNO"; +i8 254 253 252 0 0 0 0 0; s8 "PQRSTUVW"; diff --git a/rust/pspp/src/sys/testdata/variable_roles.expected b/rust/pspp/src/sys/testdata/variable_roles.expected new file mode 100644 index 0000000000..ce3c4cc80f --- /dev/null +++ b/rust/pspp/src/sys/testdata/variable_roles.expected @@ -0,0 +1,46 @@ +Unknown role "6". + +╭──────────────────────┬────────────────────────╮ +│ Created │ 01-JAN-2011 20:53:52│ +├──────────────────────┼────────────────────────┤ +│Writer Product │PSPP synthetic test file│ +│ Version │1.2.3 │ +├──────────────────────┼────────────────────────┤ +│ Compression │None │ +│ Number of Cases│ 0│ +╰──────────────────────┴────────────────────────╯ + +╭─────────┬────────────────────────╮ +│Label │PSPP synthetic test file│ +│Variables│ 7│ +╰─────────┴────────────────────────╯ + +╭─┬────────┬─────┬─────────────────┬─────────┬─────┬─────────┬────────────┬────────────┬──────────────╮ +│ │Position│Label│Measurement Level│ Role │Width│Alignment│Print Format│Write Format│Missing Values│ +├─┼────────┼─────┼─────────────────┼─────────┼─────┼─────────┼────────────┼────────────┼──────────────┤ +│i│ 1│ │ │Input │ 8│Right │F8.0 │F8.0 │ │ +│o│ 2│ │ │Target │ 8│Right │F8.0 │F8.0 │ │ +│b│ 3│ │ │Both │ 8│Right │F8.0 │F8.0 │ │ +│n│ 4│ │ │None │ 8│Right │F8.0 │F8.0 │ │ +│p│ 5│ │ │Partition│ 8│Right │F8.0 │F8.0 │ │ +│s│ 6│ │ │Split │ 8│Right │F8.0 │F8.0 │ │ +│x│ 7│ │ │Input │ 8│Right │F8.0 │F8.0 │ │ +╰─┴────────┴─────┴─────────────────┴─────────┴─────┴─────────┴────────────┴────────────┴──────────────╯ + +╭────────────────────────┬─────╮ +│Variable and Name │Value│ +├────────────────────────┼─────┤ +│i $@Role│0 │ +├────────────────────────┼─────┤ +│o $@Role│1 │ +├────────────────────────┼─────┤ +│b $@Role│2 │ +├────────────────────────┼─────┤ +│n $@Role│3 │ +├────────────────────────┼─────┤ +│p $@Role│4 │ +├────────────────────────┼─────┤ +│s $@Role│5 │ +├────────────────────────┼─────┤ +│x $@Role│6 │ +╰────────────────────────┴─────╯ diff --git a/rust/pspp/src/sys/testdata/variable_roles.sack b/rust/pspp/src/sys/testdata/variable_roles.sack new file mode 100644 index 0000000000..8e47a88063 --- /dev/null +++ b/rust/pspp/src/sys/testdata/variable_roles.sack @@ -0,0 +1,39 @@ +# File header. +"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file"; +2; # Layout code +7; # Nominal case size +0; # Not compressed +0; # Not weighted +0; # 1 case. +100.0; # Bias. +"01 Jan 11"; "20:53:52"; s64 "PSPP synthetic test file"; +i8 0 *3; + +# Variables. +2; 0; 0; 0; 0x050800 *2; s8 "I"; +2; 0; 0; 0; 0x050800 *2; s8 "O"; +2; 0; 0; 0; 0x050800 *2; s8 "B"; +2; 0; 0; 0; 0x050800 *2; s8 "N"; +2; 0; 0; 0; 0x050800 *2; s8 "P"; +2; 0; 0; 0; 0x050800 *2; s8 "S"; +2; 0; 0; 0; 0x050800 *2; s8 "X"; + +# Machine integer info record. +7; 3; 4; 8; 1; 2; 3; -1; 1; 1; ENDIAN; 1252; + +# Variable attributes record. +7; 18; 1; COUNT ( +"I:$@Role('0'"; i8 10; ")"; +"/O:$@Role('1'"; i8 10; ")"; +"/B:$@Role('2'"; i8 10; ")"; +"/N:$@Role('3'"; i8 10; ")"; +"/P:$@Role('4'"; i8 10; ")"; +"/S:$@Role('5'"; i8 10; ")"; +"/X:$@Role('6'"; i8 10; ")"; +); + +# Character encoding record. +7; 20; 1; 12; "windows-1252"; + +# Dictionary termination record. +999; 0; -- 2.30.2