feat(specctra-core-fuzz): actually test roundtrip through serialization+parsing

This commit is contained in:
Alain Emilia Anna Zscheile 2024-12-05 21:09:51 +01:00
parent e381731475
commit cbf99e0a6e
2 changed files with 54 additions and 45 deletions

View File

@ -5,7 +5,7 @@ use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: &str| { fuzz_target!(|data: &str| {
let cursor = std::io::Cursor::new(data); let cursor = std::io::Cursor::new(data);
use specctra_core::{read::ListTokenizer, write::ListWriter, structure::Structure}; use specctra_core::{read::ListTokenizer, structure::Structure, write::ListWriter};
let mut tkz = ListTokenizer::new(cursor); let mut tkz = ListTokenizer::new(cursor);
@ -13,7 +13,16 @@ fuzz_target!(|data: &str| {
if let Ok(val) = res { if let Ok(val) = res {
let mut dat = Vec::new(); let mut dat = Vec::new();
let mut lw = ListWriter::new(&mut dat); {
let _ = lw.write_value(&val); let mut lw = ListWriter::new(&mut dat);
let _ = lw.write_value(&val).unwrap();
}
let cursor = std::io::Cursor::new(dat);
let mut tkz = ListTokenizer::new(cursor);
let val2 = tkz.read_value::<Structure>().unwrap();
// make sure that serialization+parsing after parsing is identity
assert_eq!(val, val2);
} }
}); });

View File

@ -7,7 +7,7 @@ use crate::ListToken;
use specctra_derive::ReadDsn; use specctra_derive::ReadDsn;
use specctra_derive::WriteSes; use specctra_derive::WriteSes;
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Dummy {} pub struct Dummy {}
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug)]
@ -15,27 +15,27 @@ pub struct SesFile {
pub session: Session, pub session: Session,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Session { pub struct Session {
#[anon] #[anon]
pub id: String, pub id: String,
pub routes: Routes, pub routes: Routes,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Routes { pub struct Routes {
pub resolution: Resolution, pub resolution: Resolution,
pub library_out: Library, pub library_out: Library,
pub network_out: NetworkOut, pub network_out: NetworkOut,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct NetworkOut { pub struct NetworkOut {
#[vec("net")] #[vec("net")]
pub net: Vec<NetOut>, pub net: Vec<NetOut>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct NetOut { pub struct NetOut {
#[anon] #[anon]
pub name: String, pub name: String,
@ -50,7 +50,7 @@ pub struct DsnFile {
pub pcb: Pcb, pub pcb: Pcb,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Pcb { pub struct Pcb {
#[anon] #[anon]
pub name: String, pub name: String,
@ -64,7 +64,7 @@ pub struct Pcb {
pub wiring: Wiring, pub wiring: Wiring,
} }
#[derive(WriteSes, Debug)] #[derive(WriteSes, Debug, Clone, PartialEq)]
pub struct Parser { pub struct Parser {
pub string_quote: Option<char>, pub string_quote: Option<char>,
pub space_in_quoted_tokens: Option<bool>, pub space_in_quoted_tokens: Option<bool>,
@ -72,7 +72,7 @@ pub struct Parser {
pub host_version: Option<String>, pub host_version: Option<String>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Resolution { pub struct Resolution {
#[anon] #[anon]
pub unit: String, pub unit: String,
@ -80,7 +80,7 @@ pub struct Resolution {
pub value: f32, pub value: f32,
} }
#[derive(WriteSes, Debug)] #[derive(WriteSes, Debug, Clone, PartialEq)]
pub struct Structure { pub struct Structure {
#[vec("layer")] #[vec("layer")]
pub layers: Vec<Layer>, pub layers: Vec<Layer>,
@ -120,7 +120,7 @@ impl<R: std::io::BufRead> ReadDsn<R> for Structure {
} }
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Layer { pub struct Layer {
#[anon] #[anon]
pub name: String, pub name: String,
@ -128,30 +128,30 @@ pub struct Layer {
pub property: Option<Property>, pub property: Option<Property>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Property { pub struct Property {
pub index: usize, pub index: usize,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Boundary { pub struct Boundary {
pub path: Path, pub path: Path,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Plane { pub struct Plane {
#[anon] #[anon]
pub net: String, pub net: String,
pub polygon: Polygon, pub polygon: Polygon,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct ViaNames { pub struct ViaNames {
#[anon_vec] #[anon_vec]
pub names: Vec<String>, pub names: Vec<String>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Grid { pub struct Grid {
#[anon] #[anon]
pub kind: String, pub kind: String,
@ -159,20 +159,20 @@ pub struct Grid {
pub value: f64, pub value: f64,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct StructureRule { pub struct StructureRule {
pub width: Option<f32>, pub width: Option<f32>,
#[vec("clearance", "clear")] #[vec("clearance", "clear")]
pub clearances: Vec<Clearance>, pub clearances: Vec<Clearance>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Placement { pub struct Placement {
#[vec("component")] #[vec("component")]
pub components: Vec<Component>, pub components: Vec<Component>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Component { pub struct Component {
#[anon] #[anon]
pub name: String, pub name: String,
@ -180,7 +180,7 @@ pub struct Component {
pub places: Vec<Place>, pub places: Vec<Place>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub struct Place { pub struct Place {
#[anon] #[anon]
@ -205,7 +205,7 @@ impl Place {
} }
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Library { pub struct Library {
#[vec("image")] #[vec("image")]
pub images: Vec<Image>, pub images: Vec<Image>,
@ -219,7 +219,7 @@ impl Library {
} }
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Image { pub struct Image {
#[anon] #[anon]
pub name: String, pub name: String,
@ -231,12 +231,12 @@ pub struct Image {
pub keepouts: Vec<Keepout>, pub keepouts: Vec<Keepout>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Outline { pub struct Outline {
pub path: Path, pub path: Path,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Pin { pub struct Pin {
#[anon] #[anon]
pub name: String, pub name: String,
@ -258,7 +258,7 @@ impl Pin {
} }
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Keepout { pub struct Keepout {
#[anon] #[anon]
pub idk: String, pub idk: String,
@ -266,7 +266,7 @@ pub struct Keepout {
pub shape: Shape, pub shape: Shape,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Padstack { pub struct Padstack {
#[anon] #[anon]
pub name: String, pub name: String,
@ -276,7 +276,7 @@ pub struct Padstack {
} }
// TODO: derive for enums if more than this single one is needed // TODO: derive for enums if more than this single one is needed
#[derive(Debug)] #[derive(Debug, Clone, PartialEq)]
pub enum Shape { pub enum Shape {
Circle(Circle), Circle(Circle),
Rect(Rect), Rect(Rect),
@ -311,7 +311,7 @@ impl<W: std::io::Write> WriteSes<W> for Shape {
} }
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Circle { pub struct Circle {
#[anon] #[anon]
pub layer: String, pub layer: String,
@ -321,7 +321,7 @@ pub struct Circle {
pub offset: Option<Point>, pub offset: Option<Point>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Network { pub struct Network {
#[vec("net")] #[vec("net")]
pub nets: Vec<NetPinAssignments>, pub nets: Vec<NetPinAssignments>,
@ -329,7 +329,7 @@ pub struct Network {
pub classes: Vec<Class>, pub classes: Vec<Class>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
// dsn names this "net", but it's a structure unrelated to "net" in wiring or elsewhere // dsn names this "net", but it's a structure unrelated to "net" in wiring or elsewhere
pub struct NetPinAssignments { pub struct NetPinAssignments {
#[anon] #[anon]
@ -337,13 +337,13 @@ pub struct NetPinAssignments {
pub pins: Option<Pins>, pub pins: Option<Pins>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Pins { pub struct Pins {
#[anon_vec] #[anon_vec]
pub names: Vec<String>, pub names: Vec<String>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Class { pub struct Class {
#[anon] #[anon]
pub name: String, pub name: String,
@ -353,12 +353,12 @@ pub struct Class {
pub rule: Rule, pub rule: Rule,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Circuit { pub struct Circuit {
pub use_via: String, pub use_via: String,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Wiring { pub struct Wiring {
#[vec("wire")] #[vec("wire")]
pub wires: Vec<Wire>, pub wires: Vec<Wire>,
@ -366,14 +366,14 @@ pub struct Wiring {
pub vias: Vec<Via>, pub vias: Vec<Via>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Wire { pub struct Wire {
pub path: Path, pub path: Path,
pub net: String, pub net: String,
pub r#type: String, pub r#type: String,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct WireOut { pub struct WireOut {
pub path: Path, pub path: Path,
} }
@ -386,7 +386,7 @@ pub struct WireOut {
// more conveniently represented as fields on the enclosing struct) // more conveniently represented as fields on the enclosing struct)
// It exists to give a way to read arrays of coordinates // It exists to give a way to read arrays of coordinates
// (and enforce that such an array actually contains a whole number of points) // (and enforce that such an array actually contains a whole number of points)
#[derive(Debug)] #[derive(Debug, Clone, PartialEq)]
pub struct Point { pub struct Point {
pub x: f64, pub x: f64,
pub y: f64, pub y: f64,
@ -439,7 +439,7 @@ impl<W: std::io::Write> WriteSes<W> for Option<Point> {
} }
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Polygon { pub struct Polygon {
#[anon] #[anon]
pub layer: String, pub layer: String,
@ -449,7 +449,7 @@ pub struct Polygon {
pub coords: Vec<Point>, pub coords: Vec<Point>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Path { pub struct Path {
#[anon] #[anon]
pub layer: String, pub layer: String,
@ -459,7 +459,7 @@ pub struct Path {
pub coords: Vec<Point>, pub coords: Vec<Point>,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Rect { pub struct Rect {
#[anon] #[anon]
pub layer: String, pub layer: String,
@ -473,7 +473,7 @@ pub struct Rect {
pub y2: f64, pub y2: f64,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Via { pub struct Via {
#[anon] #[anon]
pub name: String, pub name: String,
@ -485,14 +485,14 @@ pub struct Via {
pub r#type: String, pub r#type: String,
} }
#[derive(ReadDsn, WriteSes, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Rule { pub struct Rule {
pub width: f32, pub width: f32,
#[vec("clearance")] #[vec("clearance")]
pub clearances: Vec<Clearance>, pub clearances: Vec<Clearance>,
} }
#[derive(ReadDsn, WriteSes, Clone, Debug)] #[derive(ReadDsn, WriteSes, Debug, Clone, PartialEq)]
pub struct Clearance { pub struct Clearance {
#[anon] #[anon]
pub value: f32, pub value: f32,