#[test]
fn variable_labels_and_missing_values() {
- test_sysfile("variable_labels_and_missing_values");
+ test_sack_sysfile("variable_labels_and_missing_values");
}
#[test]
fn unspecified_number_of_variable_positions() {
- test_sysfile("unspecified_number_of_variable_positions");
+ test_sack_sysfile("unspecified_number_of_variable_positions");
}
#[test]
fn wrong_variable_positions_but_v13() {
- test_sysfile("wrong_variable_positions_but_v13");
+ test_sack_sysfile("wrong_variable_positions_but_v13");
}
#[test]
fn value_labels() {
- test_sysfile("value_labels");
+ test_sack_sysfile("value_labels");
}
#[test]
fn documents() {
- test_sysfile("documents");
+ test_sack_sysfile("documents");
}
#[test]
fn empty_document_record() {
- test_sysfile("empty_document_record");
+ test_sack_sysfile("empty_document_record");
}
#[test]
fn variable_sets() {
- test_sysfile("variable_sets");
+ test_sack_sysfile("variable_sets");
}
#[test]
fn multiple_response_sets() {
- test_sysfile("multiple_response_sets");
+ test_sack_sysfile("multiple_response_sets");
}
#[test]
fn extra_product_info() {
// Also checks for handling of CR-only line ends in file label and extra
// product info.
- test_sysfile("extra_product_info");
+ test_sack_sysfile("extra_product_info");
}
#[test]
fn variable_display_without_width() {
- test_sysfile("variable_display_without_width");
+ test_sack_sysfile("variable_display_without_width");
}
#[test]
fn variable_display_with_width() {
- test_sysfile("variable_display_with_width");
+ test_sack_sysfile("variable_display_with_width");
}
#[test]
fn long_variable_names() {
- test_sysfile("long_variable_names");
+ test_sack_sysfile("long_variable_names");
}
#[test]
fn very_long_strings() {
- test_sysfile("very_long_strings");
+ test_sack_sysfile("very_long_strings");
}
#[test]
fn attributes() {
- test_sysfile("attributes");
+ test_sack_sysfile("attributes");
}
#[test]
fn variable_roles() {
- test_sysfile("variable_roles");
+ test_sack_sysfile("variable_roles");
}
#[test]
fn compressed_data() {
- test_sysfile("compressed_data");
+ test_sack_sysfile("compressed_data");
}
#[test]
fn compressed_data_zero_bias() {
- test_sysfile("compressed_data_zero_bias");
+ test_sack_sysfile("compressed_data_zero_bias");
}
#[test]
fn compressed_data_other_bias() {
- test_sysfile("compressed_data_other_bias");
+ test_sack_sysfile("compressed_data_other_bias");
}
#[test]
fn zcompressed_data() {
- test_sysfile("zcompressed_data");
+ test_sack_sysfile("zcompressed_data");
}
#[test]
fn no_variables() {
- test_sysfile("no_variables");
+ test_sack_sysfile("no_variables");
}
#[test]
fn unknown_encoding() {
- test_sysfile("unknown_encoding");
+ test_sack_sysfile("unknown_encoding");
}
#[test]
fn misplaced_type_4_record() {
- test_sysfile("misplaced_type_4_record");
+ test_sack_sysfile("misplaced_type_4_record");
}
#[test]
fn bad_record_type() {
- test_sysfile("bad_record_type");
+ test_sack_sysfile("bad_record_type");
}
#[test]
fn wrong_variable_positions() {
- test_sysfile("wrong_variable_positions");
+ test_sack_sysfile("wrong_variable_positions");
}
#[test]
fn invalid_variable_name() {
- test_sysfile("invalid_variable_name");
+ test_sack_sysfile("invalid_variable_name");
}
#[test]
fn invalid_label_indicator() {
- test_sysfile("invalid_label_indicator");
+ test_sack_sysfile("invalid_label_indicator");
}
#[test]
fn invalid_missing_indicator() {
- test_sysfile("invalid_missing_indicator");
+ test_sack_sysfile("invalid_missing_indicator");
}
#[test]
fn invalid_missing_indicator2() {
- test_sysfile("invalid_missing_indicator2");
+ test_sack_sysfile("invalid_missing_indicator2");
}
#[test]
fn missing_string_continuation() {
- test_sysfile("missing_string_continuation");
+ test_sack_sysfile("missing_string_continuation");
}
#[test]
fn invalid_variable_format() {
- test_sysfile("invalid_variable_format");
+ test_sack_sysfile("invalid_variable_format");
}
#[test]
fn invalid_long_string_missing_values() {
- test_sysfile("invalid_long_string_missing_values");
+ test_sack_sysfile("invalid_long_string_missing_values");
}
#[test]
fn weight_must_be_numeric() {
- test_sysfile("weight_must_be_numeric");
+ test_sack_sysfile("weight_must_be_numeric");
}
#[test]
fn weight_variable_bad_index() {
- test_sysfile("weight_variable_bad_index");
+ test_sack_sysfile("weight_variable_bad_index");
}
#[test]
fn weight_variable_continuation() {
- test_sysfile("weight_variable_continuation");
+ test_sack_sysfile("weight_variable_continuation");
}
#[test]
fn multiple_documents_records() {
- test_sysfile("multiple_documents_records");
+ test_sack_sysfile("multiple_documents_records");
}
#[test]
fn unknown_extension_record() {
- test_sysfile("unknown_extension_record");
+ test_sack_sysfile("unknown_extension_record");
}
#[test]
fn extension_too_large() {
- test_sysfile("extension_too_large");
+ test_sack_sysfile("extension_too_large");
}
#[test]
fn bad_machine_integer_info_count() {
- test_sysfile("bad_machine_integer_info_count");
+ test_sack_sysfile("bad_machine_integer_info_count");
}
#[test]
fn bad_machine_integer_info_float_format() {
- test_sysfile("bad_machine_integer_info_float_format");
+ test_sack_sysfile("bad_machine_integer_info_float_format");
}
#[test]
fn bad_machine_integer_info_endianness() {
- test_sysfile("bad_machine_integer_info_endianness");
+ test_sack_sysfile("bad_machine_integer_info_endianness");
}
#[test]
fn bad_machine_float_info_size() {
- test_sysfile("bad_machine_float_info_size");
+ test_sack_sysfile("bad_machine_float_info_size");
}
#[test]
fn wrong_special_floats() {
- test_sysfile("wrong_special_floats");
+ test_sack_sysfile("wrong_special_floats");
}
#[test]
fn variable_sets_unknown_variable() {
- test_sysfile("variable_sets_unknown_variable");
+ test_sack_sysfile("variable_sets_unknown_variable");
}
#[test]
fn multiple_response_sets_bad_name() {
- test_sysfile("multiple_response_sets_bad_name");
+ test_sack_sysfile("multiple_response_sets_bad_name");
}
#[test]
fn multiple_response_sets_missing_space_after_c() {
- test_sysfile("multiple_response_sets_missing_space_after_c");
+ test_sack_sysfile("multiple_response_sets_missing_space_after_c");
}
#[test]
fn multiple_response_sets_missing_space_after_e() {
- test_sysfile("multiple_response_sets_missing_space_after_e");
+ test_sack_sysfile("multiple_response_sets_missing_space_after_e");
}
#[test]
fn multiple_response_sets_missing_label_source() {
- test_sysfile("multiple_response_sets_missing_label_source");
+ test_sack_sysfile("multiple_response_sets_missing_label_source");
}
#[test]
fn multiple_response_sets_unexpected_label_source() {
- test_sysfile("multiple_response_sets_unexpected_label_source");
+ test_sack_sysfile("multiple_response_sets_unexpected_label_source");
}
#[test]
fn multiple_response_sets_bad_counted_string() {
- test_sysfile("multiple_response_sets_bad_counted_string");
+ test_sack_sysfile("multiple_response_sets_bad_counted_string");
}
#[test]
fn multiple_response_sets_counted_string_missing_space() {
- test_sysfile("multiple_response_sets_counted_string_missing_space");
+ test_sack_sysfile("multiple_response_sets_counted_string_missing_space");
}
#[test]
fn multiple_response_sets_counted_string_bad_length() {
- test_sysfile("multiple_response_sets_counted_string_bad_length");
+ test_sack_sysfile("multiple_response_sets_counted_string_bad_length");
}
#[test]
fn multiple_response_sets_missing_space_after_counted_string() {
- test_sysfile("multiple_response_sets_missing_space_after_counted_string");
+ test_sack_sysfile("multiple_response_sets_missing_space_after_counted_string");
}
#[test]
fn multiple_response_sets_missing_newline_after_variable_name() {
- test_sysfile("multiple_response_sets_missing_newline_after_variable_name");
+ test_sack_sysfile("multiple_response_sets_missing_newline_after_variable_name");
}
#[test]
fn multiple_response_sets_duplicate_variable_name() {
- test_sysfile("multiple_response_sets_duplicate_variable_name");
+ test_sack_sysfile("multiple_response_sets_duplicate_variable_name");
}
#[test]
fn mixed_variable_types_in_mrsets() {
- test_sysfile("mixed_variable_types_in_mrsets");
+ test_sack_sysfile("mixed_variable_types_in_mrsets");
}
#[test]
fn missing_newline_after_variable_name_in_mrsets() {
- test_sysfile("missing_newline_after_variable_name_in_mrsets");
+ test_sack_sysfile("missing_newline_after_variable_name_in_mrsets");
}
#[test]
fn zero_or_one_variable_in_mrset() {
- test_sysfile("zero_or_one_variable_in_mrset");
+ test_sack_sysfile("zero_or_one_variable_in_mrset");
}
#[test]
fn wrong_display_parameter_size() {
- test_sysfile("wrong_display_parameter_size");
+ test_sack_sysfile("wrong_display_parameter_size");
}
#[test]
fn wrong_display_parameter_count() {
- test_sysfile("wrong_display_parameter_count");
+ test_sack_sysfile("wrong_display_parameter_count");
}
#[test]
fn wrong_display_measurement_level() {
- test_sysfile("wrong_display_measurement_level");
+ test_sack_sysfile("wrong_display_measurement_level");
}
#[test]
fn wrong_display_alignment() {
- test_sysfile("wrong_display_alignment");
+ test_sack_sysfile("wrong_display_alignment");
}
#[test]
fn bad_variable_name_in_variable_value_pair() {
- test_sysfile("bad_variable_name_in_variable_value_pair");
+ test_sack_sysfile("bad_variable_name_in_variable_value_pair");
}
#[test]
fn duplicate_long_variable_name() {
- test_sysfile("duplicate_long_variable_name");
+ test_sack_sysfile("duplicate_long_variable_name");
}
#[test]
fn bad_very_long_string_length() {
- test_sysfile("bad_very_long_string_length");
+ test_sack_sysfile("bad_very_long_string_length");
}
#[test]
fn bad_very_long_string_segment_width() {
- test_sysfile("bad_very_long_string_segment_width");
+ test_sack_sysfile("bad_very_long_string_segment_width");
}
#[test]
fn too_many_value_labels() {
- test_sysfile("too_many_value_labels");
+ test_sack_sysfile("too_many_value_labels");
}
#[test]
fn missing_type_4_record() {
- test_sysfile("missing_type_4_record");
+ test_sack_sysfile("missing_type_4_record");
}
#[test]
fn value_label_with_no_associated_variables() {
- test_sysfile("value_label_with_no_associated_variables");
+ test_sack_sysfile("value_label_with_no_associated_variables");
}
#[test]
fn type_4_record_names_long_string_variable() {
- test_sysfile("type_4_record_names_long_string_variable");
+ test_sack_sysfile("type_4_record_names_long_string_variable");
}
#[test]
fn value_label_variable_indexes_must_be_in_correct_range() {
- test_sysfile("value_label_variable_indexes_must_be_in_correct_range");
+ test_sack_sysfile("value_label_variable_indexes_must_be_in_correct_range");
}
#[test]
fn value_label_variable_indexes_must_not_be_long_string_continuation() {
- test_sysfile("value_label_variable_indexes_must_not_be_long_string_continuation");
+ test_sack_sysfile("value_label_variable_indexes_must_not_be_long_string_continuation");
}
#[test]
fn variables_for_value_label_must_all_be_same_type() {
- test_sysfile("variables_for_value_label_must_all_be_same_type");
+ test_sack_sysfile("variables_for_value_label_must_all_be_same_type");
}
#[test]
fn duplicate_value_labels_type() {
- test_sysfile("duplicate_value_labels_type");
+ test_sack_sysfile("duplicate_value_labels_type");
}
#[test]
fn missing_attribute_value() {
- test_sysfile("missing_attribute_value");
+ test_sack_sysfile("missing_attribute_value");
}
#[test]
fn unquoted_attribute_value() {
- test_sysfile("unquoted_attribute_value");
+ test_sack_sysfile("unquoted_attribute_value");
}
#[test]
fn duplicate_attribute_name() {
- test_sysfile("duplicate_attribute_name");
+ test_sack_sysfile("duplicate_attribute_name");
}
#[test]
fn bad_variable_name_in_long_string_value_label() {
- test_sysfile("bad_variable_name_in_long_string_value_label");
+ test_sack_sysfile("bad_variable_name_in_long_string_value_label");
}
#[test]
fn fewer_data_records_than_indicated_by_file_header() {
- test_sysfile("fewer_data_records_than_indicated_by_file_header");
+ test_sack_sysfile("fewer_data_records_than_indicated_by_file_header");
+}
+
+#[test]
+fn more_data_records_than_indicated_by_file_header() {
+ test_sack_sysfile("more_data_records_than_indicated_by_file_header");
}
#[test]
fn partial_data_record_between_variables() {
- test_sysfile("partial_data_record_between_variables");
+ test_sack_sysfile("partial_data_record_between_variables");
}
#[test]
fn partial_data_record_within_long_string() {
- test_sysfile("partial_data_record_within_long_string");
+ test_sack_sysfile("partial_data_record_within_long_string");
}
#[test]
fn partial_compressed_data_record() {
- test_sysfile("partial_compressed_data_record");
+ test_sack_sysfile("partial_compressed_data_record");
}
#[test]
fn zcompressed_data_bad_zheader_ofs() {
- test_sysfile("zcompressed_data_bad_zheader_ofs");
+ test_sack_sysfile("zcompressed_data_bad_zheader_ofs");
}
#[test]
fn zcompressed_data_bad_ztrailer_ofs() {
- test_sysfile("zcompressed_data_bad_ztrailer_ofs");
+ test_sack_sysfile("zcompressed_data_bad_ztrailer_ofs");
}
#[test]
fn zcompressed_data_invalid_ztrailer_len() {
- test_sysfile("zcompressed_data_invalid_ztrailer_len");
+ test_sack_sysfile("zcompressed_data_invalid_ztrailer_len");
}
#[test]
fn zcompressed_data_wrong_ztrailer_len() {
- test_sysfile("zcompressed_data_wrong_ztrailer_len");
+ test_sack_sysfile("zcompressed_data_wrong_ztrailer_len");
}
#[test]
fn zcompressed_data_wrong_ztrailer_bias() {
- test_sysfile("zcompressed_data_wrong_ztrailer_bias");
+ test_sack_sysfile("zcompressed_data_wrong_ztrailer_bias");
}
#[test]
fn zcompressed_data_wrong_ztrailer_zero() {
- test_sysfile("zcompressed_data_wrong_ztrailer_zero");
+ test_sack_sysfile("zcompressed_data_wrong_ztrailer_zero");
}
#[test]
fn zcompressed_data_wrong_block_size() {
- test_sysfile("zcompressed_data_wrong_block_size");
+ test_sack_sysfile("zcompressed_data_wrong_block_size");
}
#[test]
fn zcompressed_data_wrong_n_blocks() {
- test_sysfile("zcompressed_data_wrong_n_blocks");
+ test_sack_sysfile("zcompressed_data_wrong_n_blocks");
}
#[test]
fn zcompressed_data_wrong_uncompressed_ofs() {
- test_sysfile("zcompressed_data_wrong_uncompressed_ofs");
+ test_sack_sysfile("zcompressed_data_wrong_uncompressed_ofs");
}
#[test]
fn zcompressed_data_wrong_compressed_ofs() {
- test_sysfile("zcompressed_data_wrong_compressed_ofs");
+ test_sack_sysfile("zcompressed_data_wrong_compressed_ofs");
}
#[test]
fn zcompressed_data_compressed_sizes_dont_add_up() {
- test_sysfile("zcompressed_data_compressed_sizes_dont_add_up");
+ test_sack_sysfile("zcompressed_data_compressed_sizes_dont_add_up");
}
#[test]
fn zcompressed_data_uncompressed_size_block_size() {
- test_sysfile("zcompressed_data_uncompressed_size_block_size");
+ test_sack_sysfile("zcompressed_data_uncompressed_size_block_size");
}
#[test]
fn zcompressed_data_compression_expands_data_too_much() {
- test_sysfile("zcompressed_data_compression_expands_data_too_much");
+ test_sack_sysfile("zcompressed_data_compression_expands_data_too_much");
}
#[test]
fn zcompressed_data_compressed_sizes_don_t_add_up() {
- test_sysfile("zcompressed_data_compressed_sizes_don_t_add_up");
+ test_sack_sysfile("zcompressed_data_compressed_sizes_don_t_add_up");
}
+/// CVE-2017-10791.
+/// See also https://bugzilla.redhat.com/show_bug.cgi?id=1467004.
+/// See also https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=866890.
+/// See also https://security-tracker.debian.org/tracker/CVE-2017-10791.
+/// Found by team OWL337, using the collAFL fuzzer.
#[test]
fn integer_overflows_in_long_string_missing_values() {
- test_sysfile("integer_overflows_in_long_string_missing_values");
+ test_raw_sysfile("integer_overflows_in_long_string_missing_values");
}
#[test]
fn null_dereference_skipping_bad_extension_record_18() {
- test_sysfile("null_dereference_skipping_bad_extension_record_18");
+ test_sack_sysfile("null_dereference_skipping_bad_extension_record_18");
}
/// Duplicate variable name handling negative test.
/// #41475).
#[test]
fn duplicate_variable_name() {
- test_sysfile("duplicate_variable_name");
+ test_sack_sysfile("duplicate_variable_name");
+}
+
+fn test_raw_sysfile(name: &str) {
+ let input_filename = Path::new(env!("CARGO_MANIFEST_DIR"))
+ .join("src/sys/testdata")
+ .join(name)
+ .with_extension("sav");
+ let sysfile = std::fs::read(&input_filename).unwrap();
+ let expected_filename = input_filename.with_extension("expected");
+ let expected = String::from_utf8(std::fs::read(&expected_filename).unwrap()).unwrap();
+ test_sysfile(name, sysfile, &expected, &expected_filename);
}
-fn test_sysfile(name: &str) {
+fn test_sack_sysfile(name: &str) {
let input_filename = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("src/sys/testdata")
.join(name)
},
);
let sysfile = sack(&input, Some(&input_filename), endian).unwrap();
- let cursor = Cursor::new(sysfile);
- let mut warnings = Vec::new();
- let mut reader = Reader::new(cursor, |warning| warnings.push(warning)).unwrap();
- let output = match reader.headers().collect() {
- Ok(headers) => {
- let cases = reader.cases();
- let encoding =
- encoding_from_headers(&headers, &mut |warning| warnings.push(warning)).unwrap();
- let mut decoder = Decoder::new(encoding, |warning| warnings.push(warning));
- let mut decoded_records = Vec::new();
- for header in headers {
- decoded_records.push(header.decode(&mut decoder).unwrap());
- }
- drop(decoder);
-
- let mut errors = Vec::new();
- let headers = Headers::new(decoded_records, &mut |e| errors.push(e)).unwrap();
- let (dictionary, metadata, cases) =
- decode(headers, cases, encoding, |e| errors.push(e)).unwrap();
- let (group, data) = metadata.to_pivot_rows();
- let metadata_table = PivotTable::new([(Axis3::Y, Dimension::new(group))])
- .with_data(
- data.into_iter()
- .enumerate()
- .filter(|(_row, value)| !value.is_empty())
- .map(|(row, value)| ([row], value)),
- );
- let (group, data) = dictionary.to_pivot_rows();
- let dictionary_table = PivotTable::new([(Axis3::Y, Dimension::new(group))])
- .with_data(
- data.into_iter()
- .enumerate()
- .filter(|(_row, value)| !value.is_empty())
- .map(|(row, value)| ([row], value)),
- );
- let mut output = Vec::new();
- output.extend(
- warnings
- .into_iter()
- .map(|warning| Arc::new(Item::from(Text::new_log(warning.to_string())))),
- );
- output.extend(
- errors
- .into_iter()
- .map(|error| Arc::new(Item::from(Text::new_log(error.to_string())))),
- );
- output.push(Arc::new(metadata_table.into()));
- output.push(Arc::new(dictionary_table.into()));
- output.push(Arc::new(
- dictionary.output_variables().to_pivot_table().into(),
- ));
- if let Some(pt) = dictionary.output_value_labels().to_pivot_table() {
- output.push(Arc::new(pt.into()));
- }
- if let Some(pt) = dictionary.output_mrsets().to_pivot_table() {
- output.push(Arc::new(pt.into()));
- }
- if let Some(pt) = dictionary.output_attributes().to_pivot_table() {
- output.push(Arc::new(pt.into()));
- }
- if let Some(pt) = dictionary.output_variable_sets().to_pivot_table() {
- output.push(Arc::new(pt.into()));
- }
- if let Some(cases) = cases {
- let variables = Group::new("Variable")
- .with_multiple(dictionary.variables.iter().map(|var| &**var));
- let mut case_numbers = Group::new("Case").with_label_shown();
- let mut data = Vec::new();
- for (case_number, case) in cases.enumerate() {
- match case {
- Ok(case) => {
- case_numbers.push(Value::new_integer(Some(
- (case_numbers.len() + 1) as f64,
- )));
- data.push(
- case.into_iter()
- .map(|datum| Value::new_datum(&datum, dictionary.encoding))
- .collect::<Vec<_>>(),
- );
- }
- Err(error) => {
- output.push(Arc::new(Item::from(Text::new_log(error.to_string()))));
- }
+ test_sysfile(name, sysfile, &expected, &expected_filename);
+ }
+}
+
+fn test_sysfile(name: &str, sysfile: Vec<u8>, expected: &str, expected_filename: &Path) {
+ let cursor = Cursor::new(sysfile);
+ let mut warnings = Vec::new();
+ let mut reader = Reader::new(cursor, |warning| warnings.push(warning)).unwrap();
+ let output = match reader.headers().collect() {
+ Ok(headers) => {
+ let cases = reader.cases();
+ let encoding =
+ encoding_from_headers(&headers, &mut |warning| warnings.push(warning)).unwrap();
+ let mut decoder = Decoder::new(encoding, |warning| warnings.push(warning));
+ let mut decoded_records = Vec::new();
+ for header in headers {
+ decoded_records.push(header.decode(&mut decoder).unwrap());
+ }
+ drop(decoder);
+
+ let mut errors = Vec::new();
+ let headers = Headers::new(decoded_records, &mut |e| errors.push(e)).unwrap();
+ let (dictionary, metadata, cases) =
+ decode(headers, cases, encoding, |e| errors.push(e)).unwrap();
+ let (group, data) = metadata.to_pivot_rows();
+ let metadata_table = PivotTable::new([(Axis3::Y, Dimension::new(group))]).with_data(
+ data.into_iter()
+ .enumerate()
+ .filter(|(_row, value)| !value.is_empty())
+ .map(|(row, value)| ([row], value)),
+ );
+ let (group, data) = dictionary.to_pivot_rows();
+ let dictionary_table = PivotTable::new([(Axis3::Y, Dimension::new(group))]).with_data(
+ data.into_iter()
+ .enumerate()
+ .filter(|(_row, value)| !value.is_empty())
+ .map(|(row, value)| ([row], value)),
+ );
+ let mut output = Vec::new();
+ output.extend(
+ warnings
+ .into_iter()
+ .map(|warning| Arc::new(Item::from(Text::new_log(warning.to_string())))),
+ );
+ output.extend(
+ errors
+ .into_iter()
+ .map(|error| Arc::new(Item::from(Text::new_log(error.to_string())))),
+ );
+ output.push(Arc::new(metadata_table.into()));
+ output.push(Arc::new(dictionary_table.into()));
+ output.push(Arc::new(
+ dictionary.output_variables().to_pivot_table().into(),
+ ));
+ if let Some(pt) = dictionary.output_value_labels().to_pivot_table() {
+ output.push(Arc::new(pt.into()));
+ }
+ if let Some(pt) = dictionary.output_mrsets().to_pivot_table() {
+ output.push(Arc::new(pt.into()));
+ }
+ if let Some(pt) = dictionary.output_attributes().to_pivot_table() {
+ output.push(Arc::new(pt.into()));
+ }
+ if let Some(pt) = dictionary.output_variable_sets().to_pivot_table() {
+ output.push(Arc::new(pt.into()));
+ }
+ if let Some(cases) = cases {
+ let variables = Group::new("Variable")
+ .with_multiple(dictionary.variables.iter().map(|var| &**var));
+ let mut case_numbers = Group::new("Case").with_label_shown();
+ let mut data = Vec::new();
+ for case in cases {
+ match case {
+ Ok(case) => {
+ case_numbers
+ .push(Value::new_integer(Some((case_numbers.len() + 1) as f64)));
+ data.push(
+ case.into_iter()
+ .map(|datum| Value::new_datum(&datum, dictionary.encoding))
+ .collect::<Vec<_>>(),
+ );
+ }
+ Err(error) => {
+ output.push(Arc::new(Item::from(Text::new_log(error.to_string()))));
}
}
- if !data.is_empty() {
- let mut pt = PivotTable::new([
- (Axis3::X, Dimension::new(variables)),
- (Axis3::Y, Dimension::new(case_numbers)),
- ]);
- for (row_number, row) in data.into_iter().enumerate() {
- for (column_number, datum) in row.into_iter().enumerate() {
- pt.insert(&[column_number, row_number], datum);
- }
+ }
+ if !data.is_empty() {
+ let mut pt = PivotTable::new([
+ (Axis3::X, Dimension::new(variables)),
+ (Axis3::Y, Dimension::new(case_numbers)),
+ ]);
+ for (row_number, row) in data.into_iter().enumerate() {
+ for (column_number, datum) in row.into_iter().enumerate() {
+ pt.insert(&[column_number, row_number], datum);
}
- output.push(Arc::new(pt.into()));
}
+ output.push(Arc::new(pt.into()));
}
- Item::new(Details::Group(output))
}
- Err(error) => Item::new(Details::Text(Box::new(Text::new_log(error.to_string())))),
- };
-
- assert_lines_eq(
- &expected,
- expected_filename.display(),
- &output.to_string(),
- "actual",
- );
- }
+ Item::new(Details::Group(output))
+ }
+ Err(error) => Item::new(Details::Text(Box::new(Text::new_log(error.to_string())))),
+ };
+
+ assert_lines_eq(
+ &expected,
+ expected_filename.display(),
+ &output.to_string(),
+ "actual",
+ );
}