From: Ben Pfaff Date: Sat, 5 Jul 2025 17:53:41 +0000 (-0700) Subject: fix more tests X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0a1dc0049cb374f862514921ba535636fab187a1;p=pspp fix more tests --- diff --git a/rust/pspp/src/dictionary.rs b/rust/pspp/src/dictionary.rs index 55a795fd1a..cf416f5a79 100644 --- a/rust/pspp/src/dictionary.rs +++ b/rust/pspp/src/dictionary.rs @@ -1066,6 +1066,14 @@ impl Attributes { Self(BTreeMap::new()) } + pub fn contains_name(&self, name: &Identifier) -> bool { + self.0.contains_key(name) + } + + pub fn insert(&mut self, name: Identifier, values: Vec) { + self.0.insert(name, values); + } + pub fn append(&mut self, other: &mut Self) { self.0.append(&mut other.0) } diff --git a/rust/pspp/src/format/display/mod.rs b/rust/pspp/src/format/display/mod.rs index 7f259b94ee..6fcce1791b 100644 --- a/rust/pspp/src/format/display/mod.rs +++ b/rust/pspp/src/format/display/mod.rs @@ -25,6 +25,15 @@ pub struct DisplayDatum<'a, 'b> { endian: EndianSettings, datum: &'a Datum, encoding: &'static Encoding, + + /// If true, the output will remove leading and trailing spaces from numeric + /// values, and trailing spaces from string values. (This might make the + /// output narrower than the requested width.) + trim_spaces: bool, + + /// If true, the output will include a double quote before and after string + /// values. + quote_strings: bool, } #[cfg(test)] @@ -118,11 +127,14 @@ impl Display for DisplayDatum<'_, '_> { write!(f, "{byte:02x}")?; } } else { - write!( - f, - "{}", - self.encoding.decode_without_bom_handling(&string.0).0 - )?; + let quote = if self.quote_strings { "\"" } else { "" }; + let s = self.encoding.decode_without_bom_handling(&string.0).0; + let s = if self.trim_spaces { + s.trim_end_matches(' ') + } else { + &s + }; + write!(f, "{quote}{s}{quote}")?; } return Ok(()); } @@ -176,6 +188,8 @@ impl<'a, 'b> DisplayDatum<'a, 'b> { encoding, settings: &settings.formats, endian: settings.endian, + trim_spaces: false, + quote_strings: false, } } pub fn with_settings(self, settings: &'b Settings) -> Self { @@ -184,6 +198,18 @@ impl<'a, 'b> DisplayDatum<'a, 'b> { pub fn with_endian(self, endian: EndianSettings) -> Self { Self { endian, ..self } } + pub fn with_trimming(self) -> Self { + Self { + trim_spaces: true, + ..self + } + } + pub fn with_quoted_string(self) -> Self { + Self { + quote_strings: true, + ..self + } + } fn fmt_binary(&self, f: &mut Formatter) -> FmtResult { let output = self.to_binary().unwrap(); for b in output { @@ -226,7 +252,7 @@ impl<'a, 'b> DisplayDatum<'a, 'b> { } else { "Unknown" }; - let w = self.format.w(); + let w = if self.trim_spaces { 0 } else { self.format.w() }; write!(f, "{s:>0$.*}", w) } else { self.overflow(f) @@ -240,6 +266,10 @@ impl<'a, 'b> DisplayDatum<'a, 'b> { _ => (), } + if self.trim_spaces { + return write!(f, "."); + } + let w = self.format.w() as isize; let d = self.format.d() as isize; let dot_position = match self.format.type_ { @@ -261,8 +291,12 @@ impl<'a, 'b> DisplayDatum<'a, 'b> { } fn overflow(&self, f: &mut Formatter<'_>) -> FmtResult { - for _ in 0..self.format.w { + if self.trim_spaces { write!(f, "*")?; + } else { + for _ in 0..self.format.w { + write!(f, "*")?; + } } Ok(()) } @@ -311,8 +345,10 @@ impl<'a, 'b> DisplayDatum<'a, 'b> { // Assemble number. let magnitude = rounder.format(decimals as usize); let mut output = SmallString::<[u8; 40]>::new(); - for _ in width..self.format.w() { - output.push(' '); + if !self.trim_spaces { + for _ in width..self.format.w() { + output.push(' '); + } } if negative { output.push_str(&style.neg_prefix.s); @@ -346,7 +382,7 @@ impl<'a, 'b> DisplayDatum<'a, 'b> { } } - debug_assert!(output.len() >= self.format.w()); + debug_assert!(self.trim_spaces || output.len() >= self.format.w()); debug_assert!(output.len() <= self.format.w() + style.extra_bytes); f.write_str(&output)?; return Ok(true); @@ -386,8 +422,10 @@ impl<'a, 'b> DisplayDatum<'a, 'b> { width += fraction_width; let mut output = SmallString::<[u8; 40]>::new(); - for _ in width..self.format.w() { - output.push(' '); + if !self.trim_spaces { + for _ in width..self.format.w() { + output.push(' '); + } } if number < 0.0 { output.push_str(&style.neg_prefix.s); @@ -438,7 +476,7 @@ impl<'a, 'b> DisplayDatum<'a, 'b> { "{} for {number} width={width} fraction_width={fraction_width}: {output:?}", self.format ); - debug_assert!(output.len() >= self.format.w()); + debug_assert!(self.trim_spaces || output.len() >= self.format.w()); debug_assert!(output.len() <= self.format.w() + style.extra_bytes); f.write_str(&output)?; Ok(true) @@ -597,12 +635,20 @@ impl<'a, 'b> DisplayDatum<'a, 'b> { _ => unreachable!(), } } - write!(f, "{:>1$}", &output, self.format.w()) + if !self.trim_spaces { + write!(f, "{:>1$}", &output, self.format.w()) + } else { + f.write_str(&output) + } } fn month(&self, f: &mut Formatter<'_>, number: f64) -> FmtResult { if let Some(month) = month_name(number as u32) { - write!(f, "{month:.*}", self.format.w()) + if !self.trim_spaces { + write!(f, "{month:.*}", self.format.w()) + } else { + f.write_str(month) + } } else { self.missing(f) } diff --git a/rust/pspp/src/sys/cooked.rs b/rust/pspp/src/sys/cooked.rs index d864504bd5..84d3123be3 100644 --- a/rust/pspp/src/sys/cooked.rs +++ b/rust/pspp/src/sys/cooked.rs @@ -27,6 +27,7 @@ use crate::{ use chrono::{NaiveDate, NaiveDateTime, NaiveTime}; use encoding_rs::Encoding; use indexmap::set::MutableValues; +use itertools::Itertools; use thiserror::Error as ThisError; pub use crate::sys::raw::{CategoryLabels, Compression}; @@ -102,7 +103,7 @@ pub enum Error { }, #[error( - "At offsets {:#x}...{:#x}, record types 3 and 4 may not add value labels to one or more long string variables: {variables:?}", .offsets.start, .offsets.end + "At offsets {:#x}...{:#x}, record types 3 and 4 may not add value labels to one or more long string variables: {}", .offsets.start, .offsets.end, variables.iter().join(", ") )] InvalidLongStringValueLabels { offsets: Range, @@ -115,6 +116,12 @@ pub enum Error { string_var: Identifier, }, + #[error("{variable} has duplicate value labels for the following value(s): {}", values.iter().join(", "))] + DuplicateValueLabels { + variable: Identifier, + values: Vec, + }, + #[error("Invalid multiple response set name. {0}")] InvalidMrSetName(IdError), @@ -187,6 +194,15 @@ pub enum Error { len: usize, }, + #[error("Variable with short name {short_name} listed in very long string record with width {width} has segment {index} of width {actual} (expected {expected}).")] + VeryLongStringInvalidSegmentWidth { + short_name: Identifier, + width: u16, + index: usize, + actual: usize, + expected: usize, + }, + #[error("Invalid variable name in long string value label record. {0}")] InvalidLongStringValueLabelName(IdError), @@ -783,15 +799,41 @@ pub fn decode( }); } + let written_by_readstat = headers.header.eye_catcher.contains("ReadStat"); for dict_index in dict_indexes { let variable = dictionary.variables.get_index_mut2(dict_index).unwrap(); + let mut duplicates = Vec::new(); for ValueLabel { datum: value, label, } in record.labels.iter().cloned() { - let value = value.decode(variable.width); - variable.value_labels.insert(value, label); + let datum = value.decode(variable.width); + if variable.value_labels.insert(datum, label).is_some() { + duplicates.push(value); + } + } + if written_by_readstat { + // Ignore any possible duplicates. ReadStat is buggy and emits + // value labels whose values are longer than string variables' + // widths, that are identical in the actual width of the + // variable, e.g. both values "ABC123" and "ABC456" for a string + // variable with width 3. + } else if !duplicates.is_empty() { + warn(Error::DuplicateValueLabels { + variable: variable.name.clone(), + values: duplicates + .iter() + .map(|value| { + value + .decode(variable.width) + .display(variable.print_format, variable.encoding) + .with_trimming() + .with_quoted_string() + .to_string() + }) + .collect(), + }); } } } @@ -862,7 +904,13 @@ pub fn decode( short_names.push(segment.short_names[0].clone()); let segment_width = segment.width.as_string_width().unwrap_or(0); if segment_width.next_multiple_of(8) != alloc_width.next_multiple_of(8) { - warn(dbg!(Error::TBD)); + warn(Error::VeryLongStringInvalidSegmentWidth { + short_name: record.short_name.clone(), + width: record.length, + index: i, + actual: segment_width, + expected: alloc_width, + }); continue 'outer; } } @@ -1185,3 +1233,33 @@ impl MultipleResponseType { } } } + +/* +trait Quoted { + fn quoted(self) -> WithQuotes + where + Self: Display + Sized; +} + +impl Quoted for T +where + T: Display, +{ + fn quoted(self) -> WithQuotes { + WithQuotes(self) + } +} + +struct WithQuotes(T) +where + T: Display; + +impl Display for WithQuotes +where + T: Display, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "\"{}\"", &self.0) + } +} +*/ diff --git a/rust/pspp/src/sys/raw.rs b/rust/pspp/src/sys/raw.rs index 4fcd05562a..50149caaea 100644 --- a/rust/pspp/src/sys/raw.rs +++ b/rust/pspp/src/sys/raw.rs @@ -8,6 +8,7 @@ use crate::{ use encoding_rs::{mem::decode_latin1, Encoding}; use flate2::read::ZlibDecoder; +use itertools::Itertools; use num::Integer; use std::{ borrow::{Borrow, Cow}, @@ -257,11 +258,20 @@ pub enum Warning { #[error("Attribute record missing left parenthesis, in {0:?}.")] AttributeMissingLParen(String), - #[error("Attribute record missing new-line, in {0:?}.")] - AttributeMissingNewline(String), + #[error("Attribute for {name}[{}] lacks value.", index + 1)] + AttributeMissingValue { name: Identifier, index: usize }, - #[error("Attribute record missing quotations, in {0:?}.")] - AttributeMissingQuotes(String), + #[error("Attribute for {name}[{}] missing quotations.", index + 1)] + AttributeMissingQuotes { name: Identifier, index: usize }, + + #[error("Duplicate attributes for variable {variable}: {}.", attributes.iter().join(", "))] + DuplicateVariableAttributes { + variable: Identifier, + attributes: Vec, + }, + + #[error("Duplicate dataset attributes with names: {}.", attributes.iter().join(", "))] + DuplicateFileAttributes { attributes: Vec }, #[error("Compression bias is {0} instead of the usual values of 0 or 100.")] UnexpectedBias(f64), @@ -1940,6 +1950,7 @@ impl ValueLabelRecord, RawString> { max: Self::MAX_INDEXES, }); } else if n == 0 { + dbg!(); warn(Warning::NoVarIndexes { offset: index_offset, }); @@ -2795,7 +2806,10 @@ impl Attribute { let mut values = Vec::new(); loop { let Some((value, rest)) = input.split_once('\n') else { - return Err(Warning::AttributeMissingNewline(input.into())); + return Err(Warning::AttributeMissingValue { + name: name.clone(), + index: values.len(), + }); }; if let Some(stripped) = value .strip_prefix('\'') @@ -2803,7 +2817,10 @@ impl Attribute { { values.push(stripped.into()); } else { - decoder.warn(Warning::AttributeMissingQuotes(value.into())); + decoder.warn(Warning::AttributeMissingQuotes { + name: name.clone(), + index: values.len(), + }); values.push(value.into()); } if let Some(rest) = rest.strip_prefix(')') { @@ -2820,21 +2837,24 @@ impl Attributes { decoder: &mut Decoder, mut input: &'a str, sentinel: Option, - ) -> Result<(Attributes, &'a str), Warning> { + ) -> Result<(Attributes, &'a str, Vec), Warning> { let mut attributes = BTreeMap::new(); + let mut duplicates = Vec::new(); let rest = loop { match input.chars().next() { None => break input, c if c == sentinel => break &input[1..], _ => { let (attribute, rest) = Attribute::parse(decoder, input)?; - // XXX report duplicate name + if attributes.contains_key(&attribute.name) { + duplicates.push(attribute.name.clone()); + } attributes.insert(attribute.name, attribute.values); input = rest; } } }; - Ok((Attributes(attributes), rest)) + Ok((Attributes(attributes), rest, duplicates)) } } @@ -2854,7 +2874,12 @@ impl RawFileAttributesRecord { fn decode(self, decoder: &mut Decoder) -> FileAttributesRecord { let input = decoder.decode(&self.0.text); match Attributes::parse(decoder, &input, None).issue_warning(&mut decoder.warn) { - Some((set, rest)) => { + Some((set, rest, duplicates)) => { + if !duplicates.is_empty() { + decoder.warn(Warning::DuplicateFileAttributes { + attributes: duplicates, + }); + } if !rest.is_empty() { decoder.warn(dbg!(Warning::TBD)); } @@ -2883,7 +2908,13 @@ impl VarAttributes { .new_identifier(long_var_name) .and_then(Identifier::must_be_ordinary) .map_err(Warning::InvalidAttributeVariableName)?; - let (attributes, rest) = Attributes::parse(decoder, rest, Some('/'))?; + let (attributes, rest, duplicates) = Attributes::parse(decoder, rest, Some('/'))?; + if !duplicates.is_empty() { + decoder.warn(Warning::DuplicateVariableAttributes { + variable: long_var_name.clone(), + attributes: duplicates, + }); + } let var_attribute = VarAttributes { long_var_name, attributes, diff --git a/rust/pspp/src/sys/testdata/bad_very_long_string_segment_width.expected b/rust/pspp/src/sys/testdata/bad_very_long_string_segment_width.expected index e69de29bb2..75d706ab95 100644 --- a/rust/pspp/src/sys/testdata/bad_very_long_string_segment_width.expected +++ b/rust/pspp/src/sys/testdata/bad_very_long_string_segment_width.expected @@ -0,0 +1,23 @@ +File header claims 1 variable positions but 34 were read from file. + +Variable with short name STR1 listed in very long string record with width 256 has segment 1 of width 9 (expected 4). + +╭──────────────────────┬────────────────────────╮ +│ Created │ 01-JAN-2011 20:53:52│ +├──────────────────────┼────────────────────────┤ +│Writer Product │PSPP synthetic test file│ +├──────────────────────┼────────────────────────┤ +│ Compression │SAV │ +│ Number of Cases│Unknown │ +╰──────────────────────┴────────────────────────╯ + +╭─────────┬─╮ +│Variables│2│ +╰─────────┴─╯ + +╭──────┬────────┬─────┬─────────────────┬─────┬─────┬─────────┬────────────┬────────────┬──────────────╮ +│ │Position│Label│Measurement Level│ Role│Width│Alignment│Print Format│Write Format│Missing Values│ +├──────┼────────┼─────┼─────────────────┼─────┼─────┼─────────┼────────────┼────────────┼──────────────┤ +│str1 │ 1│ │Nominal │Input│ 32│Left │A255 │A255 │ │ +│str1_a│ 2│ │Nominal │Input│ 9│Left │A9 │A9 │ │ +╰──────┴────────┴─────┴─────────────────┴─────┴─────┴─────────┴────────────┴────────────┴──────────────╯ diff --git a/rust/pspp/src/sys/testdata/duplicate_attribute_name.expected b/rust/pspp/src/sys/testdata/duplicate_attribute_name.expected index e69de29bb2..8de0af1193 100644 --- a/rust/pspp/src/sys/testdata/duplicate_attribute_name.expected +++ b/rust/pspp/src/sys/testdata/duplicate_attribute_name.expected @@ -0,0 +1,30 @@ +Duplicate dataset attributes with names: Attr1. + +Duplicate attributes for variable FIRSTVAR: fred. + +╭──────────────────────┬────────────────────────╮ +│ Created │ 01-JAN-2011 20:53:52│ +├──────────────────────┼────────────────────────┤ +│Writer Product │PSPP synthetic test file│ +├──────────────────────┼────────────────────────┤ +│ Compression │SAV │ +│ Number of Cases│Unknown │ +╰──────────────────────┴────────────────────────╯ + +╭─────────┬─╮ +│Variables│1│ +╰─────────┴─╯ + +╭────────┬────────┬─────┬─────────────────┬─────┬─────┬─────────┬────────────┬────────────┬──────────────╮ +│ │Position│Label│Measurement Level│ Role│Width│Alignment│Print Format│Write Format│Missing Values│ +├────────┼────────┼─────┼─────────────────┼─────┼─────┼─────────┼────────────┼────────────┼──────────────┤ +│firstvar│ 1│ │ │Input│ 8│Right │F8.0 │F8.0 │ │ +╰────────┴────────┴─────┴─────────────────┴─────┴─────┴─────────┴────────────┴────────────┴──────────────╯ + +╭───────────────────────┬─────╮ +│Variable and Name │Value│ +├───────────────────────┼─────┤ +│(dataset) Attr1│value│ +├───────────────────────┼─────┤ +│firstvar fred │23 │ +╰───────────────────────┴─────╯ diff --git a/rust/pspp/src/sys/testdata/duplicate_value_labels_type.expected b/rust/pspp/src/sys/testdata/duplicate_value_labels_type.expected index e69de29bb2..e6416d44f3 100644 --- a/rust/pspp/src/sys/testdata/duplicate_value_labels_type.expected +++ b/rust/pspp/src/sys/testdata/duplicate_value_labels_type.expected @@ -0,0 +1,31 @@ +STR1 has duplicate value labels for the following value(s): "xyzzy" + +NUM1 has duplicate value labels for the following value(s): 1 + +╭──────────────────────┬────────────────────────╮ +│ Created │ 01-JAN-2011 20:53:52│ +├──────────────────────┼────────────────────────┤ +│Writer Product │PSPP synthetic test file│ +├──────────────────────┼────────────────────────┤ +│ Compression │SAV │ +│ Number of Cases│Unknown │ +╰──────────────────────┴────────────────────────╯ + +╭─────────┬─╮ +│Variables│2│ +╰─────────┴─╯ + +╭────┬────────┬─────┬─────────────────┬─────┬─────┬─────────┬────────────┬────────────┬──────────────╮ +│ │Position│Label│Measurement Level│ Role│Width│Alignment│Print Format│Write Format│Missing Values│ +├────┼────────┼─────┼─────────────────┼─────┼─────┼─────────┼────────────┼────────────┼──────────────┤ +│str1│ 1│ │Nominal │Input│ 6│Left │A6 │A6 │ │ +│num1│ 2│ │ │Input│ 8│Right │F8.0 │F8.0 │ │ +╰────┴────────┴─────┴─────────────────┴─────┴─────┴─────────┴────────────┴────────────┴──────────────╯ + +╭─────────────────────┬───╮ +│Variable Value │ │ +├─────────────────────┼───┤ +│str1 xyzzy │one│ +├─────────────────────┼───┤ +│num1 1 │one│ +╰─────────────────────┴───╯ diff --git a/rust/pspp/src/sys/testdata/missing_attribute_value.expected b/rust/pspp/src/sys/testdata/missing_attribute_value.expected index e69de29bb2..3ced2e811c 100644 --- a/rust/pspp/src/sys/testdata/missing_attribute_value.expected +++ b/rust/pspp/src/sys/testdata/missing_attribute_value.expected @@ -0,0 +1,22 @@ +Attribute for Attr1[1] lacks value. + +Attribute for fred[2] lacks value. + +╭──────────────────────┬────────────────────────╮ +│ Created │ 01-JAN-2011 20:53:52│ +├──────────────────────┼────────────────────────┤ +│Writer Product │PSPP synthetic test file│ +├──────────────────────┼────────────────────────┤ +│ Compression │SAV │ +│ Number of Cases│Unknown │ +╰──────────────────────┴────────────────────────╯ + +╭─────────┬─╮ +│Variables│1│ +╰─────────┴─╯ + +╭────────┬────────┬─────┬─────────────────┬─────┬─────┬─────────┬────────────┬────────────┬──────────────╮ +│ │Position│Label│Measurement Level│ Role│Width│Alignment│Print Format│Write Format│Missing Values│ +├────────┼────────┼─────┼─────────────────┼─────┼─────┼─────────┼────────────┼────────────┼──────────────┤ +│firstvar│ 1│ │ │Input│ 8│Right │F8.0 │F8.0 │ │ +╰────────┴────────┴─────┴─────────────────┴─────┴─────┴─────────┴────────────┴────────────┴──────────────╯ diff --git a/rust/pspp/src/sys/testdata/missing_type_4_record.expected b/rust/pspp/src/sys/testdata/missing_type_4_record.expected index e69de29bb2..78fac887fa 100644 --- a/rust/pspp/src/sys/testdata/missing_type_4_record.expected +++ b/rust/pspp/src/sys/testdata/missing_type_4_record.expected @@ -0,0 +1 @@ +At offset 0xe8, following value label record, found record type 7 instead of expected type 4 for variable index record diff --git a/rust/pspp/src/sys/testdata/too_many_value_labels.expected b/rust/pspp/src/sys/testdata/too_many_value_labels.expected index e69de29bb2..08e21a713e 100644 --- a/rust/pspp/src/sys/testdata/too_many_value_labels.expected +++ b/rust/pspp/src/sys/testdata/too_many_value_labels.expected @@ -0,0 +1 @@ +At offset 0xd4, number of value labels (2147483647) is greater than the maximum number 536870911. diff --git a/rust/pspp/src/sys/testdata/type_4_record_names_long_string_variable.expected b/rust/pspp/src/sys/testdata/type_4_record_names_long_string_variable.expected index e69de29bb2..ba37a94432 100644 --- a/rust/pspp/src/sys/testdata/type_4_record_names_long_string_variable.expected +++ b/rust/pspp/src/sys/testdata/type_4_record_names_long_string_variable.expected @@ -0,0 +1,20 @@ +At offsets 0xf4...0x114, record types 3 and 4 may not add value labels to one or more long string variables: STR1 + +╭──────────────────────┬────────────────────────╮ +│ Created │ 01-JAN-2011 20:53:52│ +├──────────────────────┼────────────────────────┤ +│Writer Product │PSPP synthetic test file│ +├──────────────────────┼────────────────────────┤ +│ Compression │SAV │ +│ Number of Cases│Unknown │ +╰──────────────────────┴────────────────────────╯ + +╭─────────┬─╮ +│Variables│1│ +╰─────────┴─╯ + +╭────┬────────┬─────┬─────────────────┬─────┬─────┬─────────┬────────────┬────────────┬──────────────╮ +│ │Position│Label│Measurement Level│ Role│Width│Alignment│Print Format│Write Format│Missing Values│ +├────┼────────┼─────┼─────────────────┼─────┼─────┼─────────┼────────────┼────────────┼──────────────┤ +│str1│ 1│ │Nominal │Input│ 9│Left │A9 │A9 │ │ +╰────┴────────┴─────┴─────────────────┴─────┴─────┴─────────┴────────────┴────────────┴──────────────╯ diff --git a/rust/pspp/src/sys/testdata/unquoted_attribute_value.expected b/rust/pspp/src/sys/testdata/unquoted_attribute_value.expected index e69de29bb2..37611c1b41 100644 --- a/rust/pspp/src/sys/testdata/unquoted_attribute_value.expected +++ b/rust/pspp/src/sys/testdata/unquoted_attribute_value.expected @@ -0,0 +1,30 @@ +Attribute for Attr1[1] missing quotations. + +Attribute for fred[1] missing quotations. + +╭──────────────────────┬────────────────────────╮ +│ Created │ 01-JAN-2011 20:53:52│ +├──────────────────────┼────────────────────────┤ +│Writer Product │PSPP synthetic test file│ +├──────────────────────┼────────────────────────┤ +│ Compression │SAV │ +│ Number of Cases│Unknown │ +╰──────────────────────┴────────────────────────╯ + +╭─────────┬─╮ +│Variables│1│ +╰─────────┴─╯ + +╭────────┬────────┬─────┬─────────────────┬─────┬─────┬─────────┬────────────┬────────────┬──────────────╮ +│ │Position│Label│Measurement Level│ Role│Width│Alignment│Print Format│Write Format│Missing Values│ +├────────┼────────┼─────┼─────────────────┼─────┼─────┼─────────┼────────────┼────────────┼──────────────┤ +│firstvar│ 1│ │ │Input│ 8│Right │F8.0 │F8.0 │ │ +╰────────┴────────┴─────┴─────────────────┴─────┴─────┴─────────┴────────────┴────────────┴──────────────╯ + +╭───────────────────────┬─────╮ +│Variable and Name │Value│ +├───────────────────────┼─────┤ +│(dataset) Attr1│value│ +├───────────────────────┼─────┤ +│firstvar fred │23 │ +╰───────────────────────┴─────╯ diff --git a/rust/pspp/src/sys/testdata/value_label_variable_indexes_must_be_in_correct_range.expected b/rust/pspp/src/sys/testdata/value_label_variable_indexes_must_be_in_correct_range.expected index e69de29bb2..d7a6ca5e5e 100644 --- a/rust/pspp/src/sys/testdata/value_label_variable_indexes_must_be_in_correct_range.expected +++ b/rust/pspp/src/sys/testdata/value_label_variable_indexes_must_be_in_correct_range.expected @@ -0,0 +1,25 @@ +At offset 0x110, one or more variable indexes for value labels were not in the valid range [1,2] or referred to string continuations: [3, 4] + +At offset 0x138, one or more variable indexes for value labels were not in the valid range [1,2] or referred to string continuations: [5, 6] + +At offset 0x160, one or more variable indexes for value labels were not in the valid range [1,2] or referred to string continuations: [7, 8] + +╭──────────────────────┬────────────────────────╮ +│ Created │ 01-JAN-2011 20:53:52│ +├──────────────────────┼────────────────────────┤ +│Writer Product │PSPP synthetic test file│ +├──────────────────────┼────────────────────────┤ +│ Compression │SAV │ +│ Number of Cases│Unknown │ +╰──────────────────────┴────────────────────────╯ + +╭─────────┬─╮ +│Variables│2│ +╰─────────┴─╯ + +╭────┬────────┬─────┬─────────────────┬─────┬─────┬─────────┬────────────┬────────────┬──────────────╮ +│ │Position│Label│Measurement Level│ Role│Width│Alignment│Print Format│Write Format│Missing Values│ +├────┼────────┼─────┼─────────────────┼─────┼─────┼─────────┼────────────┼────────────┼──────────────┤ +│str1│ 1│ │Nominal │Input│ 6│Left │A6 │A6 │ │ +│num1│ 2│ │ │Input│ 8│Right │F8.0 │F8.0 │ │ +╰────┴────────┴─────┴─────────────────┴─────┴─────┴─────────┴────────────┴────────────┴──────────────╯ diff --git a/rust/pspp/src/sys/testdata/value_label_variable_indexes_must_not_be_long_string_continuation.expected b/rust/pspp/src/sys/testdata/value_label_variable_indexes_must_not_be_long_string_continuation.expected index e69de29bb2..dd7424e7d7 100644 --- a/rust/pspp/src/sys/testdata/value_label_variable_indexes_must_not_be_long_string_continuation.expected +++ b/rust/pspp/src/sys/testdata/value_label_variable_indexes_must_not_be_long_string_continuation.expected @@ -0,0 +1,20 @@ +At offset 0x110, one or more variable indexes for value labels were not in the valid range [1,2] or referred to string continuations: [2] + +╭──────────────────────┬────────────────────────╮ +│ Created │ 01-JAN-2011 20:53:52│ +├──────────────────────┼────────────────────────┤ +│Writer Product │PSPP synthetic test file│ +├──────────────────────┼────────────────────────┤ +│ Compression │SAV │ +│ Number of Cases│Unknown │ +╰──────────────────────┴────────────────────────╯ + +╭─────────┬─╮ +│Variables│1│ +╰─────────┴─╯ + +╭────┬────────┬─────┬─────────────────┬─────┬─────┬─────────┬────────────┬────────────┬──────────────╮ +│ │Position│Label│Measurement Level│ Role│Width│Alignment│Print Format│Write Format│Missing Values│ +├────┼────────┼─────┼─────────────────┼─────┼─────┼─────────┼────────────┼────────────┼──────────────┤ +│str1│ 1│ │Nominal │Input│ 9│Left │A9 │A9 │ │ +╰────┴────────┴─────┴─────────────────┴─────┴─────┴─────────┴────────────┴────────────┴──────────────╯ diff --git a/rust/pspp/src/sys/testdata/value_label_with_no_associated_variables.expected b/rust/pspp/src/sys/testdata/value_label_with_no_associated_variables.expected index e69de29bb2..283dbd7f1e 100644 --- a/rust/pspp/src/sys/testdata/value_label_with_no_associated_variables.expected +++ b/rust/pspp/src/sys/testdata/value_label_with_no_associated_variables.expected @@ -0,0 +1,22 @@ +At offset 0xe8, at least one valid variable index for value labels is required but none were specified. + +This system file does not indicate its own character encoding. For best results, specify an encoding explicitly. Use SYSFILE INFO with ENCODING="DETECT" to analyze the possible encodings. + +╭──────────────────────┬────────────────────────╮ +│ Created │ 01-JAN-2011 20:53:52│ +├──────────────────────┼────────────────────────┤ +│Writer Product │PSPP synthetic test file│ +├──────────────────────┼────────────────────────┤ +│ Compression │SAV │ +│ Number of Cases│Unknown │ +╰──────────────────────┴────────────────────────╯ + +╭─────────┬─╮ +│Variables│1│ +╰─────────┴─╯ + +╭────┬────────┬─────┬─────────────────┬─────┬─────┬─────────┬────────────┬────────────┬──────────────╮ +│ │Position│Label│Measurement Level│ Role│Width│Alignment│Print Format│Write Format│Missing Values│ +├────┼────────┼─────┼─────────────────┼─────┼─────┼─────────┼────────────┼────────────┼──────────────┤ +│num1│ 1│ │ │Input│ 8│Right │F8.0 │F8.0 │ │ +╰────┴────────┴─────┴─────────────────┴─────┴─────┴─────────┴────────────┴────────────┴──────────────╯ diff --git a/rust/pspp/src/sys/testdata/value_label_with_no_associated_variables.sack b/rust/pspp/src/sys/testdata/value_label_with_no_associated_variables.sack index c0bf70b22a..4c6c8aa3f8 100644 --- a/rust/pspp/src/sys/testdata/value_label_with_no_associated_variables.sack +++ b/rust/pspp/src/sys/testdata/value_label_with_no_associated_variables.sack @@ -7,3 +7,6 @@ # Value label with no variables. 3; 1; 1.0; i8 3; s7 "one"; 4; >>0<<; + +# End of dictionary. +>>999; 0<<; diff --git a/rust/pspp/src/sys/testdata/variables_for_value_label_must_all_be_same_type.expected b/rust/pspp/src/sys/testdata/variables_for_value_label_must_all_be_same_type.expected index e69de29bb2..d71b23b5ca 100644 --- a/rust/pspp/src/sys/testdata/variables_for_value_label_must_all_be_same_type.expected +++ b/rust/pspp/src/sys/testdata/variables_for_value_label_must_all_be_same_type.expected @@ -0,0 +1,27 @@ +At offset 0x110, the first variable index is for a string variable but the following variable indexes are for numeric variables: [2] + +╭──────────────────────┬────────────────────────╮ +│ Created │ 01-JAN-2011 20:53:52│ +├──────────────────────┼────────────────────────┤ +│Writer Product │PSPP synthetic test file│ +├──────────────────────┼────────────────────────┤ +│ Compression │SAV │ +│ Number of Cases│Unknown │ +╰──────────────────────┴────────────────────────╯ + +╭─────────┬─╮ +│Variables│2│ +╰─────────┴─╯ + +╭────┬────────┬─────┬─────────────────┬─────┬─────┬─────────┬────────────┬────────────┬──────────────╮ +│ │Position│Label│Measurement Level│ Role│Width│Alignment│Print Format│Write Format│Missing Values│ +├────┼────────┼─────┼─────────────────┼─────┼─────┼─────────┼────────────┼────────────┼──────────────┤ +│str1│ 1│ │Nominal │Input│ 6│Left │A6 │A6 │ │ +│num1│ 2│ │ │Input│ 8│Right │F8.0 │F8.0 │ │ +╰────┴────────┴─────┴─────────────────┴─────┴─────┴─────────┴────────────┴────────────┴──────────────╯ + +╭─────────────────────┬───╮ +│Variable Value │ │ +├─────────────────────┼───┤ +│str1 xyzzy │one│ +╰─────────────────────┴───╯ diff --git a/tests/data/sys-file-reader.at b/tests/data/sys-file-reader.at index beb35adae9..7408c57d31 100644 --- a/tests/data/sys-file-reader.at +++ b/tests/data/sys-file-reader.at @@ -3269,7 +3269,7 @@ dnl Very long string map. 7; 14; 1; COUNT ( "STR1=00256"; i8 0; i8 9; ); - + dnl Character encoding record. 7; 20; 1; 12; "windows-1252";