//! Tests for writer, tree, and parser. #![cfg(all(feature = "tree", feature = "writer"))] use std::{cell::RefCell, io::Cursor, iter, rc::Rc}; use fbxcel::{ low::FbxVersion, pull_parser::{any::AnyParser, error::Warning}, }; use self::v7400::writer::{ expect_fbx_end, expect_node_end, expect_node_start, CUSTOM_UNKNOWN1, MAGIC, UNKNOWN3, }; mod v7400; /// Parses a node which lacks necessary node end marker. #[test] fn missing_node_end_marker() -> Result<(), Box> { let data = { let raw_ver = 7400_u32; let mut vec = Vec::new(); // Header. { // Magic. vec.extend(MAGIC); // Version. vec.extend(raw_ver.to_le_bytes()); } // Nodes. { // Container node. { const CONTAINER: &[u8] = b"Container"; let container_start = vec.len(); // End offset. vec.extend([0; 4]); // Number of node properties. vec.extend([0; 4]); // Length of node properties in bytes. vec.extend([0; 4]); // Node name length. vec.push(CONTAINER.len() as u8); // Node name. vec.extend(CONTAINER); // Invalid node. { const INVALID_NODE: &[u8] = b"InvalidNode"; let invalid_node_start = vec.len(); // End offset. vec.extend([0; 4]); // Number of node properties. vec.extend([0; 4]); // Length of node properties in bytes. vec.extend([0; 4]); // Node name length. vec.push(INVALID_NODE.len() as u8); // Node name. vec.extend(INVALID_NODE); let end_pos = (vec.len() as u32).to_le_bytes(); vec[invalid_node_start..(invalid_node_start + 4)].copy_from_slice(&end_pos); } // Node end marker. vec.extend([0; 13]); let end_pos = (vec.len() as u32).to_le_bytes(); vec[container_start..(container_start + 4)].copy_from_slice(&end_pos); } // End of implicit root. { vec.extend(iter::repeat(0).take(4 * 3 + 1)); } } // Footer. { // Footer: unknown1. vec.extend(CUSTOM_UNKNOWN1); // Footer: padding. { let len = vec.len().wrapping_neg() % 16; assert_eq!((vec.len() + len) % 16, 0); vec.extend(iter::repeat(0).take(len)); } // Footer: unknown2. vec.extend([0; 4]); // Footer: FBX version. vec.extend(raw_ver.to_le_bytes()); // Footer: 120 zeroes. vec.extend(iter::repeat(0).take(120)); // Footer: unknown3. vec.extend(UNKNOWN3); } vec }; assert_eq!(data.len() % 16, 0); let mut parser = match AnyParser::from_seekable_reader(Cursor::new(data))? { AnyParser::V7400(parser) => parser, _ => panic!("Generated data should be parsable with v7400 parser"), }; let warnings = Rc::new(RefCell::new(Vec::new())); parser.set_warning_handler({ let warnings = warnings.clone(); move |warning, _pos| { warnings.borrow_mut().push(warning); Ok(()) } }); assert_eq!(parser.fbx_version(), FbxVersion::V7_4); { let attrs = expect_node_start(&mut parser, "Container")?; assert_eq!(attrs.total_count(), 0); } { let attrs = expect_node_start(&mut parser, "InvalidNode")?; assert_eq!(attrs.total_count(), 0); } expect_node_end(&mut parser)?; expect_node_end(&mut parser)?; let _: Box = expect_fbx_end(&mut parser)??; match &warnings.borrow()[..] { [Warning::MissingNodeEndMarker] => {} v => panic!("Unexpected warnings: {:?}", v), } Ok(()) } /// Parses a node which has extra node end marker. #[test] fn extra_node_end_marker() -> Result<(), Box> { let data = { let raw_ver = 7400_u32; let mut vec = Vec::new(); // Header. { // Magic. vec.extend(MAGIC); // Version. vec.extend(raw_ver.to_le_bytes()); } // Nodes. { // Container node. { const CONTAINER: &[u8] = b"Container"; let container_start = vec.len(); // End offset. vec.extend([0; 4]); // Number of node properties. vec.extend([0; 4]); // Length of node properties in bytes. vec.extend([0; 4]); // Node name length. vec.push(CONTAINER.len() as u8); // Node name. vec.extend(CONTAINER); // Invalid node. { const INVALID_NODE: &[u8] = b"InvalidNode"; let invalid_node_start = vec.len(); // End offset. vec.extend([0; 4]); // Number of node properties. vec.extend(1_u32.to_le_bytes()); // Length of node properties in bytes. vec.extend(2_u32.to_le_bytes()); // Node name length. vec.push(INVALID_NODE.len() as u8); // Node name. vec.extend(INVALID_NODE); // An attribute. vec.extend([b'C', b'T']); // Extra node end marker. vec.extend([0; 13]); let end_pos = (vec.len() as u32).to_le_bytes(); vec[invalid_node_start..(invalid_node_start + 4)].copy_from_slice(&end_pos); } // Node end marker. vec.extend([0; 13]); let end_pos = (vec.len() as u32).to_le_bytes(); vec[container_start..(container_start + 4)].copy_from_slice(&end_pos); } // End of implicit root. { vec.extend(iter::repeat(0).take(4 * 3 + 1)); } } // Footer. { // Footer: unknown1. vec.extend(CUSTOM_UNKNOWN1); // Footer: padding. { let len = vec.len().wrapping_neg() % 16; assert_eq!((vec.len() + len) % 16, 0); vec.extend(iter::repeat(0).take(len)); } // Footer: unknown2. vec.extend([0; 4]); // Footer: FBX version. vec.extend(raw_ver.to_le_bytes()); // Footer: 120 zeroes. vec.extend(iter::repeat(0).take(120)); // Footer: unknown3. vec.extend(UNKNOWN3); } vec }; assert_eq!(data.len() % 16, 0); let mut parser = match AnyParser::from_seekable_reader(Cursor::new(data))? { AnyParser::V7400(parser) => parser, _ => panic!("Generated data should be parsable with v7400 parser"), }; let warnings = Rc::new(RefCell::new(Vec::new())); parser.set_warning_handler({ let warnings = warnings.clone(); move |warning, _pos| { warnings.borrow_mut().push(warning); Ok(()) } }); assert_eq!(parser.fbx_version(), FbxVersion::V7_4); { let attrs = expect_node_start(&mut parser, "Container")?; assert_eq!(attrs.total_count(), 0); } { let attrs = expect_node_start(&mut parser, "InvalidNode")?; assert_eq!(attrs.total_count(), 1); } expect_node_end(&mut parser)?; expect_node_end(&mut parser)?; let _: Box = expect_fbx_end(&mut parser)??; match &warnings.borrow()[..] { [Warning::ExtraNodeEndMarker] => {} v => panic!("Unexpected warnings: {:?}", v), } Ok(()) }