#[cfg(test)]
mod tests {
use super::super::*;
use crate::vectorizer::{Point, Curve, VectorizedData};
use std::fs;
use std::path::PathBuf;
fn create_test_vectorized_data() -> VectorizedData {
VectorizedData {
width: 100,
height: 100,
background_color: (255, 255, 255, 255),
curves: vec![
Curve {
points: vec![
Point { x: 10.0, y: 10.0 },
Point { x: 90.0, y: 10.0 },
Point { x: 90.0, y: 90.0 },
Point { x: 10.0, y: 90.0 },
],
color: (255, 0, 0, 255),
is_closed: true,
subpaths: vec![],
},
Curve {
points: vec![
Point { x: 30.0, y: 30.0 },
Point { x: 70.0, y: 30.0 },
Point { x: 70.0, y: 70.0 },
Point { x: 30.0, y: 70.0 },
],
color: (0, 0, 255, 255),
is_closed: true,
subpaths: vec![],
},
],
}
}
fn create_test_vectorized_data_with_subpaths() -> VectorizedData {
VectorizedData {
width: 100,
height: 100,
background_color: (255, 255, 255, 255),
curves: vec![
Curve {
points: vec![],
color: (255, 0, 0, 255),
is_closed: true,
subpaths: vec![
vec![
Point { x: 10.0, y: 10.0 },
Point { x: 40.0, y: 10.0 },
Point { x: 40.0, y: 40.0 },
Point { x: 10.0, y: 40.0 },
],
vec![
Point { x: 60.0, y: 60.0 },
Point { x: 90.0, y: 60.0 },
Point { x: 90.0, y: 90.0 },
Point { x: 60.0, y: 90.0 },
],
],
},
],
}
}
#[test]
fn test_generate_svg_basic() {
let data = create_test_vectorized_data();
let output_path = PathBuf::from("/tmp/test_output.svg");
let result = generate_svg(&data, &output_path);
assert!(result.is_ok());
assert!(output_path.exists());
let content = fs::read_to_string(&output_path).unwrap();
assert!(content.contains("<svg"));
assert!(content.contains("width=\"100\""));
assert!(content.contains("height=\"100\""));
assert!(content.contains("</svg>"));
let _ = fs::remove_file(&output_path);
}
#[test]
fn test_generate_svg_with_background_color() {
let data = create_test_vectorized_data();
let output_path = PathBuf::from("/tmp/test_background.svg");
let result = generate_svg(&data, &output_path);
assert!(result.is_ok());
let content = fs::read_to_string(&output_path).unwrap();
assert!(content.contains("#ffffff"));
let _ = fs::remove_file(&output_path);
}
#[test]
fn test_generate_svg_with_curves() {
let data = create_test_vectorized_data();
let output_path = PathBuf::from("/tmp/test_curves.svg");
let result = generate_svg(&data, &output_path);
assert!(result.is_ok());
let content = fs::read_to_string(&output_path).unwrap();
assert!(content.contains("#ff0000")); assert!(content.contains("#0000ff")); assert!(content.contains("<path"));
let _ = fs::remove_file(&output_path);
}
#[test]
fn test_generate_svg_advanced() {
let data = create_test_vectorized_data();
let output_path = PathBuf::from("/tmp/test_advanced.svg");
let result = generate_svg_advanced(&data, &output_path);
assert!(result.is_ok());
assert!(output_path.exists());
let _ = fs::remove_file(&output_path);
}
#[test]
fn test_generate_svg_with_subpaths() {
let data = create_test_vectorized_data_with_subpaths();
let output_path = PathBuf::from("/tmp/test_subpaths.svg");
let result = generate_svg(&data, &output_path);
assert!(result.is_ok());
let content = fs::read_to_string(&output_path).unwrap();
assert!(content.contains("<path"));
let _ = fs::remove_file(&output_path);
}
#[test]
fn test_generate_svg_empty_curves() {
let data = VectorizedData {
width: 50,
height: 50,
background_color: (128, 128, 128, 255),
curves: vec![],
};
let output_path = PathBuf::from("/tmp/test_empty.svg");
let result = generate_svg(&data, &output_path);
assert!(result.is_ok());
let content = fs::read_to_string(&output_path).unwrap();
assert!(content.contains("<svg"));
assert!(content.contains("#808080"));
let _ = fs::remove_file(&output_path);
}
#[test]
fn test_fmt_coord_integer() {
assert_eq!(fmt_coord(5.0), "5");
assert_eq!(fmt_coord(10.0), "10");
assert_eq!(fmt_coord(0.0), "0");
}
#[test]
fn test_fmt_coord_half() {
assert_eq!(fmt_coord(5.5), "5.5");
assert_eq!(fmt_coord(10.5), "10.5");
}
#[test]
fn test_fmt_coord_rounding() {
assert_eq!(fmt_coord(5.24), "5"); assert_eq!(fmt_coord(5.26), "5.5"); assert_eq!(fmt_coord(5.74), "5.5"); assert_eq!(fmt_coord(5.76), "6"); }
#[test]
fn test_fmt_coord_negative() {
assert_eq!(fmt_coord(-5.0), "-5");
assert_eq!(fmt_coord(-5.5), "-5.5");
}
#[test]
fn test_create_subpath_string_empty() {
let points: Vec<Point> = vec![];
let result = create_subpath_string(&points, true);
assert_eq!(result, "");
}
#[test]
fn test_create_subpath_string_single_point() {
let points = vec![Point { x: 10.0, y: 20.0 }];
let result = create_subpath_string(&points, false);
assert_eq!(result, "M10 20");
}
#[test]
fn test_create_subpath_string_two_points() {
let points = vec![
Point { x: 10.0, y: 20.0 },
Point { x: 30.0, y: 40.0 },
];
let result = create_subpath_string(&points, false);
assert_eq!(result, "M10 20L30 40");
}
#[test]
fn test_create_subpath_string_closed() {
let points = vec![
Point { x: 10.0, y: 10.0 },
Point { x: 20.0, y: 10.0 },
Point { x: 20.0, y: 20.0 },
];
let result = create_subpath_string(&points, true);
assert!(result.contains("M10 10"));
assert!(result.contains("L20 10"));
assert!(result.contains("L20 20"));
assert!(result.ends_with('Z'));
}
#[test]
fn test_create_subpath_string_not_closed() {
let points = vec![
Point { x: 10.0, y: 10.0 },
Point { x: 20.0, y: 10.0 },
Point { x: 20.0, y: 20.0 },
];
let result = create_subpath_string(&points, false);
assert!(result.contains("M10 10"));
assert!(result.contains("L20 10"));
assert!(result.contains("L20 20"));
assert!(!result.ends_with('Z'));
}
#[test]
fn test_create_subpath_string_with_decimals() {
let points = vec![
Point { x: 10.5, y: 20.5 },
Point { x: 30.25, y: 40.75 },
];
let result = create_subpath_string(&points, false);
assert_eq!(result, "M10.5 20.5L30.5 41"); }
#[test]
fn test_generate_svg_with_alpha() {
let data = VectorizedData {
width: 50,
height: 50,
background_color: (255, 255, 255, 128),
curves: vec![
Curve {
points: vec![
Point { x: 10.0, y: 10.0 },
Point { x: 40.0, y: 10.0 },
Point { x: 40.0, y: 40.0 },
Point { x: 10.0, y: 40.0 },
],
color: (255, 0, 0, 64),
is_closed: true,
subpaths: vec![],
},
],
};
let output_path = PathBuf::from("/tmp/test_alpha.svg");
let result = generate_svg(&data, &output_path);
assert!(result.is_ok());
let content = fs::read_to_string(&output_path).unwrap();
assert!(content.contains("fill-opacity=\"0.5\""));
let _ = fs::remove_file(&output_path);
}
#[test]
fn test_generate_svg_hierarchical_evenodd() {
let data = VectorizedData {
width: 100,
height: 100,
background_color: (255, 255, 255, 255),
curves: vec![
Curve {
points: vec![],
color: (255, 0, 0, 255),
is_closed: true,
subpaths: vec![
vec![
Point { x: 10.0, y: 10.0 },
Point { x: 90.0, y: 10.0 },
Point { x: 90.0, y: 90.0 },
Point { x: 10.0, y: 90.0 },
],
vec![
Point { x: 30.0, y: 30.0 },
Point { x: 30.0, y: 70.0 },
Point { x: 70.0, y: 70.0 },
Point { x: 70.0, y: 30.0 },
],
],
},
],
};
let output_path = PathBuf::from("/tmp/test_evenodd.svg");
let result = generate_svg(&data, &output_path);
assert!(result.is_ok());
let content = fs::read_to_string(&output_path).unwrap();
assert!(content.contains("fill-rule=\"evenodd\""));
let _ = fs::remove_file(&output_path);
}
#[test]
fn test_create_multi_path_string_empty() {
let subpaths: Vec<Vec<Point>> = vec![];
let result = create_multi_path_string(&subpaths);
assert_eq!(result, "");
}
#[test]
fn test_create_multi_path_string_single_subpath() {
let subpaths = vec![
vec![
Point { x: 0.0, y: 0.0 },
Point { x: 10.0, y: 0.0 },
Point { x: 10.0, y: 10.0 },
],
];
let result = create_multi_path_string(&subpaths);
assert!(!result.is_empty());
assert!(result.contains("M0 0"));
}
#[test]
fn test_create_multi_path_string_multiple_subpaths() {
let subpaths = vec![
vec![
Point { x: 0.0, y: 0.0 },
Point { x: 10.0, y: 0.0 },
Point { x: 10.0, y: 10.0 },
],
vec![
Point { x: 20.0, y: 20.0 },
Point { x: 30.0, y: 20.0 },
Point { x: 30.0, y: 30.0 },
],
];
let result = create_multi_path_string(&subpaths);
assert!(result.contains("M0 0"));
assert!(result.contains("M20 20"));
}
#[test]
fn test_create_multi_path_string_skips_small_subpaths() {
let subpaths = vec![
vec![
Point { x: 0.0, y: 0.0 },
Point { x: 10.0, y: 0.0 },
], vec![
Point { x: 20.0, y: 20.0 },
Point { x: 30.0, y: 20.0 },
Point { x: 30.0, y: 30.0 },
], ];
let result = create_multi_path_string(&subpaths);
assert!(!result.contains("M0 0"));
assert!(result.contains("M20 20"));
}
#[test]
fn test_create_subpath_string_removes_zero_length_segments() {
let pts = vec![
Point { x: 0.0, y: 0.0 },
Point { x: 0.1, y: 0.1 }, Point { x: 0.0, y: 0.0 }, Point { x: 10.0, y: 10.0 },
];
let result = create_subpath_string(&pts, true);
assert_eq!(result, "M0 0L10 10Z");
}
#[test]
fn test_generate_svg_to_matches_file_output() {
let data = VectorizedData {
width: 100,
height: 100,
background_color: (255, 255, 255, 255),
curves: vec![
Curve {
points: vec![],
color: (255, 0, 0, 255),
is_closed: true,
subpaths: vec![
vec![
Point { x: 10.0, y: 10.0 },
Point { x: 90.0, y: 10.0 },
Point { x: 90.0, y: 90.0 },
Point { x: 10.0, y: 90.0 },
],
],
},
],
};
let file_path = PathBuf::from("/tmp/test_svg_to.svg");
generate_svg(&data, &file_path).unwrap();
let from_file = std::fs::read_to_string(&file_path).unwrap();
let mut buffer = Vec::new();
generate_svg_to(&data, &mut buffer).unwrap();
let from_writer = String::from_utf8(buffer).unwrap();
assert_eq!(from_file, from_writer);
let _ = std::fs::remove_file(&file_path);
}
#[test]
fn test_write_subpath_to_matches_string_version() {
let pts = vec![
Point { x: 0.0, y: 0.0 },
Point { x: 5.0, y: 0.0 },
Point { x: 5.0, y: 5.0 },
];
let string_version = create_subpath_string(&pts, true);
let mut buf = Vec::new();
write_subpath_to(&mut buf, &pts, true).unwrap();
let writer_version = String::from_utf8(buf).unwrap();
assert_eq!(string_version, writer_version);
}
#[test]
fn test_write_multi_path_to_matches_string_version() {
let subpaths = vec![
vec![
Point { x: 0.0, y: 0.0 },
Point { x: 10.0, y: 0.0 },
Point { x: 10.0, y: 10.0 },
],
vec![
Point { x: 20.0, y: 20.0 },
Point { x: 30.0, y: 20.0 },
Point { x: 30.0, y: 30.0 },
],
];
let string_version = create_multi_path_string(&subpaths);
let mut buf = Vec::new();
write_multi_path_to(&mut buf, &subpaths).unwrap();
let writer_version = String::from_utf8(buf).unwrap();
assert_eq!(string_version, writer_version);
}
}