diff --git a/src/objects/acad_group.rs b/src/objects/acad_group.rs index 2c351b7..a7b60ba 100644 --- a/src/objects/acad_group.rs +++ b/src/objects/acad_group.rs @@ -116,94 +116,3 @@ pub(crate) fn decode_object( split.finish("ACAD_GROUP")?; Ok(out) } - -#[cfg(test)] -mod tests { - use super::*; - use crate::bitwriter::BitWriter; - - fn encode_tv_r2000(w: &mut BitWriter, s: &[u8]) { - w.write_bs_u(s.len() as u16); - for b in s { - w.write_rc(*b); - } - } - - #[test] - fn roundtrip_empty_group() { - let mut w = BitWriter::new(); - encode_tv_r2000(&mut w, b"MyGroup"); - w.write_bs(0); // named - w.write_bs(1); // selectable - w.write_bl(0); - let bytes = w.into_bytes(); - let mut c = BitCursor::new(&bytes); - let g = decode(&mut c, Version::R2000).unwrap(); - assert_eq!(g.name, "MyGroup"); - assert!(!g.is_unnamed()); - assert!(g.is_selectable()); - assert_eq!(g.num_members, 0); - } - - #[test] - fn roundtrip_populated_group() { - let mut w = BitWriter::new(); - encode_tv_r2000(&mut w, b"*A1"); - w.write_bs(2); // unnamed (AutoCAD-generated) - w.write_bs(0); // not selectable as a whole - w.write_bl(2); - let bytes = w.into_bytes(); - let mut c = BitCursor::new(&bytes); - let g = decode(&mut c, Version::R2000).unwrap(); - assert_eq!(g.name, "*A1"); - assert!(g.is_unnamed()); - assert!(!g.is_selectable()); - assert_eq!(g.num_members, 2); - } - - /// The exact field widths of `sample_AC1032.dwg`'s two GROUP - /// records: three 10-bit fields reading 2, 1 and 6. - #[test] - fn r2018_split_stream_group_matches_the_measured_widths() { - let mut body = modern::tests::r2018_object_prefix(1); - body.write_bs(2); // unnamed - body.write_bs(1); // selectable - body.write_bl(6); // member count - let bits = crate::string_stream::tests::bits_of(&body); - assert_eq!(bits.len(), 14 + 30, "measured budget is 30 bits of body"); - let payload = crate::string_stream::tests::build_payload(&bits, &[""]); - let g = decode_object(&payload, 8, None, Version::R2018).unwrap(); - assert_eq!(g.name, ""); - assert_eq!(g.unnamed, 2); - assert_eq!(g.selectable, 1); - assert_eq!(g.num_members, 6); - } - - /// Two single-bit flags cannot fill the measured budget — the - /// pre-fix field list must now be rejected, not silently accepted. - #[test] - fn r2018_split_stream_group_rejects_the_old_boolean_field_list() { - let mut body = modern::tests::r2018_object_prefix(1); - body.write_b(true); - body.write_b(true); - body.write_bl(6); - let bits = crate::string_stream::tests::bits_of(&body); - let payload = crate::string_stream::tests::build_payload(&bits, &[""]); - assert!(decode_object(&payload, 8, None, Version::R2018).is_err()); - } - - #[test] - fn rejects_excessive_handle_count() { - // Synthesize a stream where num_handles claims a count past the cap. - let mut w = BitWriter::new(); - encode_tv_r2000(&mut w, b"G"); - w.write_bs(0); - w.write_bs(1); - // BL 0b00 tag then 32-bit LE = 200_001 - w.write_bl((MAX_GROUP_HANDLES + 1) as i32); - let bytes = w.into_bytes(); - let mut c = BitCursor::new(&bytes); - let err = decode(&mut c, Version::R2000).unwrap_err(); - assert!(matches!(&err, Error::SectionMap(msg) if msg.contains("ACAD_GROUP"))); - } -} diff --git a/src/objects/acad_layout.rs b/src/objects/acad_layout.rs index 7fa90ed..fcb5892 100644 --- a/src/objects/acad_layout.rs +++ b/src/objects/acad_layout.rs @@ -304,166 +304,3 @@ pub fn decode_object( trailing_strings, }) } - -#[cfg(test)] -mod tests { - use super::*; - use crate::bitwriter::BitWriter; - use crate::objects::acad_plot_settings::tests::write_split_stream_block; - - fn write_bd3(w: &mut BitWriter, p: Point3D) { - w.write_bd(p.x); - w.write_bd(p.y); - w.write_bd(p.z); - } - - fn write_rd2(w: &mut BitWriter, p: Point2D) { - w.write_rd(p.x); - w.write_rd(p.y); - } - - const X_AXIS: Point3D = Point3D { - x: 1.0, - y: 0.0, - z: 0.0, - }; - const Y_AXIS: Point3D = Point3D { - x: 0.0, - y: 1.0, - z: 0.0, - }; - - /// Build the LAYOUT half of the body, with the `TV` layout name - /// left to the string stream. - fn write_layout_block(w: &mut BitWriter, tab_order: i32, limmax: Point2D, viewports: i32) { - w.write_bl(tab_order); - w.write_bs(1); // flags - write_bd3(w, Point3D::default()); // ucs_origin - write_rd2(w, Point2D::default()); // limmin - write_rd2(w, limmax); - write_bd3(w, Point3D::default()); // insertion_point - write_bd3(w, X_AXIS); - write_bd3(w, Y_AXIS); - w.write_bd(0.0); // elevation - w.write_bs(0); // ucs_ortho_view_type - write_bd3(w, Point3D::default()); // extent_min - write_bd3( - w, - Point3D { - x: 3.0, - y: 4.0, - z: 0.0, - }, - ); // extent_max - w.write_bl(viewports); - } - - fn build_r2018(name: &str, tab_order: i32, limmax: Point2D, viewports: i32) -> Vec { - let mut body = modern::tests::r2018_object_prefix(1); - write_split_stream_block(&mut body); - write_layout_block(&mut body, tab_order, limmax, viewports); - let bits = crate::string_stream::tests::bits_of(&body); - crate::string_stream::tests::build_payload( - &bits, - &[ - "", - "none_device", - "ANSI_A_(8.50_x_11.00_Inches)", - "acad.ctb", - name, - ], - ) - } - - #[test] - fn r2018_split_stream_layout_closes_on_its_string_stream() { - let payload = build_r2018("Layout1", 1, Point2D { x: 10.75, y: 8.25 }, 2); - let l = decode_object(&payload, 8, None, Version::R2018).unwrap(); - assert_eq!(l.layout_name, "Layout1"); - assert_eq!(l.tab_order, 1); - assert_eq!(l.flags, 1); - assert_eq!(l.viewport_count, 2); - assert!(!l.is_model_space()); - assert_eq!(l.ucs_x_axis, X_AXIS); - assert_eq!(l.ucs_y_axis, Y_AXIS); - assert!((l.limits_width() - 10.75).abs() < 1e-12); - assert!((l.limits_height() - 8.25).abs() < 1e-12); - assert!((l.extents_diagonal() - 5.0).abs() < 1e-12); - assert!(l.trailing_strings.is_empty()); - // The embedded plot-settings block round-trips too. - assert_eq!(l.plot_settings.printer_config_name, "none_device"); - assert_eq!(l.plot_settings.paper_size, "ANSI_A_(8.50_x_11.00_Inches)"); - assert!((l.plot_settings.paper_width - 215.9).abs() < 1e-12); - assert!((l.plot_settings.paper_height - 279.4).abs() < 1e-12); - assert!((l.plot_settings.margin_left - 6.35).abs() < 1e-12); - assert_eq!(l.plot_settings.shade_plot_custom_dpi, 300); - } - - #[test] - fn model_layout_is_recognised() { - let payload = build_r2018("Model", 0, Point2D { x: 12.0, y: 9.0 }, 0); - let l = decode_object(&payload, 8, None, Version::R2018).unwrap(); - assert!(l.is_model_space()); - assert_eq!(l.viewport_count, 0); - assert!((l.limits_width() - 12.0).abs() < 1e-12); - } - - /// `viewport_count` is a `BL`: reading the same body with a 32-bit - /// `RL` there would overrun the string-stream start, so the - /// boundary check must reject a body that carries an `RL`. - #[test] - fn an_rl_sized_viewport_count_does_not_close() { - let mut body = modern::tests::r2018_object_prefix(1); - write_split_stream_block(&mut body); - body.write_bl(1); // tab_order - body.write_bs(1); // flags - write_bd3(&mut body, Point3D::default()); - write_rd2(&mut body, Point2D::default()); - write_rd2(&mut body, Point2D { x: 1.0, y: 1.0 }); - write_bd3(&mut body, Point3D::default()); - write_bd3(&mut body, X_AXIS); - write_bd3(&mut body, Y_AXIS); - body.write_bd(0.0); - body.write_bs(0); - write_bd3(&mut body, Point3D::default()); - write_bd3(&mut body, Point3D::default()); - body.write_rl(2); // an RL viewport count instead of a BL - let bits = crate::string_stream::tests::bits_of(&body); - let payload = crate::string_stream::tests::build_payload( - &bits, - &["", "none_device", "A4", "", "Layout1"], - ); - assert!(decode_object(&payload, 8, None, Version::R2018).is_err()); - } - - /// The plot-settings block is not optional: a body that omits it - /// leaves the field list short and the boundary check has to - /// reject it. - #[test] - fn a_body_without_the_plot_settings_block_is_rejected() { - let mut body = modern::tests::r2018_object_prefix(1); - write_layout_block(&mut body, 0, Point2D::default(), 0); - let bits = crate::string_stream::tests::bits_of(&body); - let payload = crate::string_stream::tests::build_payload(&bits, &["", "", "", "", "Model"]); - assert!(decode_object(&payload, 8, None, Version::R2018).is_err()); - } - - #[test] - fn uninitialised_extents_report_a_zero_diagonal() { - let l = AcadLayout { - extent_min: Point3D { - x: 1e20, - y: 1e20, - z: 1e20, - }, - extent_max: Point3D { - x: -1e20, - y: -1e20, - z: -1e20, - }, - ..AcadLayout::default() - }; - assert!(l.has_uninitialised_extents()); - assert_eq!(l.extents_diagonal(), 0.0); - } -} diff --git a/src/objects/acad_material.rs b/src/objects/acad_material.rs index 5d33b04..8819570 100644 --- a/src/objects/acad_material.rs +++ b/src/objects/acad_material.rs @@ -287,7 +287,7 @@ pub(crate) fn decode_object( /// The strings and data-field budget of an ACAD_MATERIAL record, as /// [`read_strings`] measured them before the field list was derived. -/// [`Material`] supersedes it; it is kept with its tests. +/// [`Material`] supersedes it; it stays as public API. #[derive(Debug, Clone, PartialEq, Eq)] pub struct AcadMaterial { /// Material name — `ByLayer`, `ByBlock` and `Global` in every @@ -336,50 +336,3 @@ pub fn read_strings( data_field_bits, }) } - -#[cfg(test)] -mod tests { - use super::*; - use crate::bitwriter::BitWriter; - - #[test] - fn r2018_split_stream_material_reads_its_names_from_the_string_stream() { - let mut body = modern::tests::r2018_object_prefix(1); - // Stand-in for the undecoded data fields. - for _ in 0..40 { - body.write_b(false); - } - let bits = crate::string_stream::tests::bits_of(&body); - let payload = - crate::string_stream::tests::build_payload(&bits, &["Global", "", "", "", "", "", ""]); - let material = read_strings(&payload, 8, None, Version::R2018).unwrap(); - assert_eq!(material.name, "Global"); - assert_eq!(material.description, ""); - assert_eq!(material.extra_strings.len(), 5); - assert_eq!(material.data_field_bits, Some(40)); - } - - #[test] - fn inline_layout_reads_its_names_from_the_data_cursor() { - let mut w = BitWriter::new(); - w.write_bs_u(0); // EED terminator - w.write_bl(1); // num_reactors - w.write_b(true); // no xdictionary (R2004+) - w.write_bs_u(8); - for b in b"ByLayer\0" { - w.write_rc(*b); - } - w.write_bs_u(0); // empty description - let after_names = w.position_bits(); - for _ in 0..24 { - w.write_b(false); - } - let end = w.position_bits(); - let bytes = w.into_bytes(); - let material = read_strings(&bytes, 0, Some(end), Version::R2004).unwrap(); - assert_eq!(material.name, "ByLayer"); - assert_eq!(material.description, ""); - assert!(material.extra_strings.is_empty()); - assert_eq!(material.data_field_bits, Some(end - after_names)); - } -} diff --git a/src/objects/acad_mlinestyle.rs b/src/objects/acad_mlinestyle.rs index e0cd128..33e7b44 100644 --- a/src/objects/acad_mlinestyle.rs +++ b/src/objects/acad_mlinestyle.rs @@ -153,85 +153,3 @@ fn read_fields(split: &mut modern::ObjectStream<'_>, version: Version) -> Result lines, }) } - -#[cfg(test)] -mod tests { - use super::*; - use crate::bitwriter::BitWriter; - - fn cmc(w: &mut BitWriter, index: u16, rgb: u32, color_byte: u8) { - w.write_bs_u(index); - w.write_bl_u(rgb); - w.write_rc(color_byte); - } - - /// The `STANDARD` style every corpus file carries: two elements at - /// ±0.5, both ByLayer, both with the `32767` linetype sentinel. - fn build(version: Version) -> Vec { - let mut body = modern::tests::r2018_object_prefix(1); - body.write_bs(0); // flags - cmc(&mut body, 0, 0xC000_0000, 0); // fill colour, ByLayer - body.write_bd(std::f64::consts::FRAC_PI_2); - body.write_bd(std::f64::consts::FRAC_PI_2); - body.write_rc(2); // linesinstyle - for offset in [0.5, -0.5] { - body.write_bd(offset); - cmc(&mut body, 0, 0xC000_0000, 0); - if !matches!(version, Version::R2018) { - body.write_bs(32767); - } - } - let bits = crate::string_stream::tests::bits_of(&body); - crate::string_stream::tests::build_payload(&bits, &["STANDARD", ""]) - } - - #[test] - fn r2018_mlinestyle_closes_on_its_string_stream() { - let payload = build(Version::R2018); - let style = decode_object(&payload, 8, None, Version::R2018).unwrap(); - assert_eq!(style.name, "STANDARD"); - assert_eq!(style.description, ""); - assert_eq!(style.flags, 0); - assert_eq!(style.fill_color.method(), 0xC0); - assert!((style.start_angle - std::f64::consts::FRAC_PI_2).abs() < 1e-12); - assert!((style.end_angle - std::f64::consts::FRAC_PI_2).abs() < 1e-12); - assert_eq!(style.lines.len(), 2); - assert_eq!(style.lines[0].offset, 0.5); - assert_eq!(style.lines[1].offset, -0.5); - assert_eq!(style.lines[0].color.method(), 0xC0); - // R2018 takes the per-line linetype from the handle stream. - assert_eq!(style.lines[0].linetype_index, 0); - } - - /// The pre-R2018 `BS ltindex` is not optional: an R2013 body read - /// with the R2018 field list leaves both index words unread, and the - /// boundary check has to reject that. - #[test] - fn r2013_body_rejected_by_the_r2018_field_list() { - let payload = build(Version::R2013); - let style = decode_object(&payload, 8, None, Version::R2013).unwrap(); - assert_eq!(style.lines[0].linetype_index, 32767); - assert!(decode_object(&payload, 8, None, Version::R2018).is_err()); - } - - /// …and the converse. - #[test] - fn r2018_body_rejected_by_the_r2013_field_list() { - let payload = build(Version::R2018); - assert!(decode_object(&payload, 8, None, Version::R2013).is_err()); - } - - #[test] - fn rejects_too_many_lines() { - let mut body = modern::tests::r2018_object_prefix(0); - body.write_bs(0); - cmc(&mut body, 0, 0xC000_0000, 0); - body.write_bd(0.0); - body.write_bd(0.0); - body.write_rc(17); // > 16 - let bits = crate::string_stream::tests::bits_of(&body); - let payload = crate::string_stream::tests::build_payload(&bits, &["BIG", ""]); - let err = decode_object(&payload, 8, None, Version::R2018).unwrap_err(); - assert!(matches!(&err, Error::SectionMap(msg) if msg.contains("MLINESTYLE"))); - } -} diff --git a/src/objects/acad_plot_settings.rs b/src/objects/acad_plot_settings.rs index d8a9e19..bf96079 100644 --- a/src/objects/acad_plot_settings.rs +++ b/src/objects/acad_plot_settings.rs @@ -278,95 +278,3 @@ pub fn decode_object( split.finish("PLOTSETTINGS")?; Ok(settings) } - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use crate::bitwriter::BitWriter; - - /// Write the §20.4.84 plot-settings block with `TV` slots left to - /// the string stream, as an R2007+ record does. - pub(crate) fn write_split_stream_block(w: &mut BitWriter) { - w.write_bs(1712); // plot_layout_flags - w.write_bd(6.35); // margin_left - w.write_bd(19.05); // margin_bottom - w.write_bd(6.35); // margin_right - w.write_bd(19.05); // margin_top - w.write_bd(215.9); // paper_width - w.write_bd(279.4); // paper_height - w.write_bd(0.0); // plot_origin.x - w.write_bd(0.0); // plot_origin.y - w.write_bs(0); // paper_units - w.write_bs(1); // plot_rotation - w.write_bs(5); // plot_type - w.write_bd(0.0); // window_min.x - w.write_bd(0.0); // window_min.y - w.write_bd(0.0); // window_max.x - w.write_bd(0.0); // window_max.y - w.write_bd(1.0); // real_world_units - w.write_bd(1.0); // drawing_units - w.write_bs(16); // standard_scale_type - w.write_bd(1.0); // scale_factor - w.write_bd(0.0); // paper_image_origin.x - w.write_bd(0.0); // paper_image_origin.y - w.write_bs(0); // shade_plot_mode - w.write_bs(2); // shade_plot_resolution_level - w.write_bs(300); // shade_plot_custom_dpi - } - - fn build_r2018() -> Vec { - let mut body = modern::tests::r2018_object_prefix(1); - write_split_stream_block(&mut body); - let bits = crate::string_stream::tests::bits_of(&body); - crate::string_stream::tests::build_payload( - &bits, - &[ - "", - "none_device", - "ANSI_A_(8.50_x_11.00_Inches)", - "acad.ctb", - ], - ) - } - - #[test] - fn r2018_split_stream_plot_settings_closes_on_its_string_stream() { - let payload = build_r2018(); - let s = decode_object(&payload, 8, None, Version::R2018).unwrap(); - assert_eq!(s.page_setup_name, ""); - assert_eq!(s.printer_config_name, "none_device"); - assert_eq!(s.paper_size, "ANSI_A_(8.50_x_11.00_Inches)"); - assert_eq!(s.current_style_sheet, "acad.ctb"); - assert_eq!(s.plot_layout_flags, 1712); - assert!((s.margin_left - 6.35).abs() < 1e-12); - assert!((s.margin_top - 19.05).abs() < 1e-12); - assert!((s.paper_width - 215.9).abs() < 1e-12); - assert!((s.paper_height - 279.4).abs() < 1e-12); - assert_eq!(s.plot_rotation, 1); - assert_eq!(s.plot_type, 5); - assert_eq!(s.standard_scale_type, 16); - assert_eq!(s.shade_plot_custom_dpi, 300); - assert!((s.printable_width() - (215.9 - 12.7)).abs() < 1e-12); - assert!((s.printable_height() - (279.4 - 38.1)).abs() < 1e-12); - assert_eq!(s.custom_scale(), Some(1.0)); - } - - /// A body one field short of the list must not satisfy the - /// boundary check — the decoder has to error rather than return a - /// plausible-looking struct. - #[test] - fn a_short_body_is_rejected_by_the_boundary_check() { - let mut body = modern::tests::r2018_object_prefix(1); - write_split_stream_block(&mut body); - body.write_bs(0); // one field too many - let bits = crate::string_stream::tests::bits_of(&body); - let payload = crate::string_stream::tests::build_payload(&bits, &["", "x", "", ""]); - assert!(decode_object(&payload, 8, None, Version::R2018).is_err()); - } - - #[test] - fn custom_scale_is_none_when_drawing_units_is_zero() { - let s = AcadPlotSettings::default(); - assert_eq!(s.custom_scale(), None); - } -} diff --git a/src/objects/acad_property_set_data.rs b/src/objects/acad_property_set_data.rs index 857abda..9ef48a4 100644 --- a/src/objects/acad_property_set_data.rs +++ b/src/objects/acad_property_set_data.rs @@ -119,94 +119,3 @@ pub fn decode(c: &mut BitCursor<'_>, version: Version) -> Result= u16::MAX as usize); - } -} diff --git a/src/objects/dictionary_var.rs b/src/objects/dictionary_var.rs index 4685228..74a054b 100644 --- a/src/objects/dictionary_var.rs +++ b/src/objects/dictionary_var.rs @@ -69,45 +69,3 @@ pub(crate) fn decode_object( split.finish("DICTIONARYVAR")?; Ok(out) } - -#[cfg(test)] -mod tests { - use super::*; - use crate::bitwriter::BitWriter; - - #[test] - fn roundtrip_inline_value() { - let mut w = BitWriter::new(); - w.write_rc(0); - w.write_bs_u(8); - for b in b"Metric50" { - w.write_rc(*b); - } - let bytes = w.into_bytes(); - let mut c = BitCursor::new(&bytes); - let v = decode(&mut c, Version::R2000).unwrap(); - assert_eq!(v.schema, 0); - assert_eq!(v.value, "Metric50"); - } - - #[test] - fn r2018_split_stream_var_reads_its_value_from_the_string_stream() { - let mut body = modern::tests::r2018_object_prefix(1); - body.write_rc(0); - let bits = crate::string_stream::tests::bits_of(&body); - let payload = crate::string_stream::tests::build_payload(&bits, &["STANDARD"]); - let v = decode_object(&payload, 8, None, Version::R2018).unwrap(); - assert_eq!(v.schema, 0); - assert_eq!(v.value, "STANDARD"); - } - - #[test] - fn r2018_split_stream_var_rejects_a_misaligned_body() { - let mut body = modern::tests::r2018_object_prefix(1); - body.write_rc(0); - body.write_rc(0); - let bits = crate::string_stream::tests::bits_of(&body); - let payload = crate::string_stream::tests::build_payload(&bits, &["STANDARD"]); - assert!(decode_object(&payload, 8, None, Version::R2018).is_err()); - } -} diff --git a/src/objects/placeholder.rs b/src/objects/placeholder.rs index debada8..9fe4175 100644 --- a/src/objects/placeholder.rs +++ b/src/objects/placeholder.rs @@ -52,39 +52,3 @@ pub(crate) fn decode_object( num_reactors: split.num_reactors, }) } - -#[cfg(test)] -mod tests { - use super::*; - use crate::bitwriter::BitWriter; - - #[test] - fn r2018_placeholder_is_exactly_the_common_object_data() { - let body = modern::tests::r2018_object_prefix(1); - let bits = crate::string_stream::tests::bits_of(&body); - let payload = modern::tests::build_payload_without_strings(&bits); - let p = decode_object(&payload, 8, None, Version::R2018).unwrap(); - assert_eq!(p.num_reactors, 1); - } - - #[test] - fn r2018_placeholder_rejects_a_record_with_a_body() { - let mut body = modern::tests::r2018_object_prefix(1); - body.write_bl(7); // a field a placeholder must not have - let bits = crate::string_stream::tests::bits_of(&body); - let payload = modern::tests::build_payload_without_strings(&bits); - assert!(decode_object(&payload, 8, None, Version::R2018).is_err()); - } - - #[test] - fn r2004_placeholder_closes_on_the_inline_object_size() { - let mut w = BitWriter::new(); - w.write_bs_u(0); - w.write_bl(1); - w.write_b(true); - let end = w.position_bits(); - let bytes = w.into_bytes(); - let p = decode_object(&bytes, 0, Some(end), Version::R2004).unwrap(); - assert_eq!(p.num_reactors, 1); - } -} diff --git a/src/objects/proxy_entity.rs b/src/objects/proxy_entity.rs index 30a680c..63c04f6 100644 --- a/src/objects/proxy_entity.rs +++ b/src/objects/proxy_entity.rs @@ -68,69 +68,3 @@ pub fn decode(c: &mut BitCursor<'_>, _version: crate::version::Version) -> Resul handles, }) } - -#[cfg(test)] -mod tests { - use super::*; - use crate::bitwriter::BitWriter; - use crate::version::Version; - - #[test] - fn roundtrip_empty_proxy() { - let mut w = BitWriter::new(); - w.write_bl(500); - w.write_bl(0); - w.write_bl(0); - let bytes = w.into_bytes(); - let mut c = BitCursor::new(&bytes); - let p = decode(&mut c, Version::R2000).unwrap(); - assert_eq!(p.proxy_class_id, 500); - assert!(p.raw_proxy_data.is_empty()); - assert!(p.handles.is_empty()); - } - - #[test] - fn roundtrip_populated_proxy() { - let mut w = BitWriter::new(); - w.write_bl(501); - let payload: [u8; 4] = [0xDE, 0xAD, 0xBE, 0xEF]; - w.write_bl(payload.len() as i32); - for b in &payload { - w.write_rc(*b); - } - w.write_bl(2); - w.write_handle(5, 0x10); - w.write_handle(5, 0x20); - let bytes = w.into_bytes(); - let mut c = BitCursor::new(&bytes); - let p = decode(&mut c, Version::R2000).unwrap(); - assert_eq!(p.proxy_class_id, 501); - assert_eq!(p.raw_proxy_data, &payload); - assert_eq!(p.handles.len(), 2); - assert_eq!(p.handles[0].value, 0x10); - assert_eq!(p.handles[1].value, 0x20); - } - - #[test] - fn rejects_oversized_data() { - let mut w = BitWriter::new(); - w.write_bl(500); - w.write_bl((MAX_PROXY_DATA_BYTES + 1) as i32); - let bytes = w.into_bytes(); - let mut c = BitCursor::new(&bytes); - let err = decode(&mut c, Version::R2000).unwrap_err(); - assert!(matches!(&err, Error::SectionMap(msg) if msg.contains("ProxyEntity"))); - } - - #[test] - fn rejects_excessive_handle_count() { - let mut w = BitWriter::new(); - w.write_bl(500); - w.write_bl(0); - w.write_bl((MAX_PROXY_HANDLES + 1) as i32); - let bytes = w.into_bytes(); - let mut c = BitCursor::new(&bytes); - let err = decode(&mut c, Version::R2000).unwrap_err(); - assert!(matches!(&err, Error::SectionMap(msg) if msg.contains("handles"))); - } -} diff --git a/src/objects/proxy_object.rs b/src/objects/proxy_object.rs index c2358b7..4daa8d1 100644 --- a/src/objects/proxy_object.rs +++ b/src/objects/proxy_object.rs @@ -66,67 +66,3 @@ pub fn decode(c: &mut BitCursor<'_>, _version: crate::version::Version) -> Resul handles, }) } - -#[cfg(test)] -mod tests { - use super::*; - use crate::bitwriter::BitWriter; - use crate::version::Version; - - #[test] - fn roundtrip_empty_proxy() { - let mut w = BitWriter::new(); - w.write_bl(600); - w.write_bl(0); - w.write_bl(0); - let bytes = w.into_bytes(); - let mut c = BitCursor::new(&bytes); - let p = decode(&mut c, Version::R2000).unwrap(); - assert_eq!(p.proxy_class_id, 600); - assert!(p.raw_proxy_data.is_empty()); - assert!(p.handles.is_empty()); - } - - #[test] - fn roundtrip_populated_proxy_object() { - let mut w = BitWriter::new(); - w.write_bl(601); - let payload: [u8; 3] = [0xC0, 0xDE, 0x42]; - w.write_bl(payload.len() as i32); - for b in &payload { - w.write_rc(*b); - } - w.write_bl(1); - w.write_handle(3, 0x55); - let bytes = w.into_bytes(); - let mut c = BitCursor::new(&bytes); - let p = decode(&mut c, Version::R2000).unwrap(); - assert_eq!(p.proxy_class_id, 601); - assert_eq!(p.raw_proxy_data, &payload); - assert_eq!(p.handles.len(), 1); - assert_eq!(p.handles[0].value, 0x55); - } - - #[test] - fn rejects_oversized_data() { - let mut w = BitWriter::new(); - w.write_bl(600); - w.write_bl((MAX_PROXY_DATA_BYTES + 1) as i32); - let bytes = w.into_bytes(); - let mut c = BitCursor::new(&bytes); - let err = decode(&mut c, Version::R2000).unwrap_err(); - assert!(matches!(&err, Error::SectionMap(msg) if msg.contains("ProxyObject"))); - } - - #[test] - fn rejects_excessive_handle_count() { - let mut w = BitWriter::new(); - w.write_bl(600); - w.write_bl(0); - w.write_bl((MAX_PROXY_HANDLES + 1) as i32); - let bytes = w.into_bytes(); - let mut c = BitCursor::new(&bytes); - let err = decode(&mut c, Version::R2000).unwrap_err(); - assert!(matches!(&err, Error::SectionMap(msg) if msg.contains("handles"))); - } -} diff --git a/src/objects/xdata.rs b/src/objects/xdata.rs index 730f911..22c38f4 100644 --- a/src/objects/xdata.rs +++ b/src/objects/xdata.rs @@ -146,99 +146,3 @@ fn decode_item(c: &mut BitCursor<'_>, version: Version, code: u16) -> Result