tests: perform some undo-redo sanity testing before each test

This commit is contained in:
Mikolaj Wielgus 2024-06-07 19:23:13 +02:00
parent 91480453b3
commit cd1e78db6f
2 changed files with 99 additions and 56 deletions

View File

@ -1,43 +1,61 @@
use std::fs::File;
use petgraph::{stable_graph::NodeIndex, unionfind::UnionFind, visit::NodeIndexable}; use petgraph::{stable_graph::NodeIndex, unionfind::UnionFind, visit::NodeIndexable};
use topola::{ use topola::{
autorouter::{board::Board, Autorouter}, autorouter::{
board::Board,
history::HistoryError,
invoker::{Invoker, InvokerError},
Autorouter,
},
drawing::{ drawing::{
graph::{GetLayer, GetMaybeNet}, graph::{GetLayer, GetMaybeNet},
rules::RulesTrait, rules::RulesTrait,
}, },
dsn::{design::DsnDesign, rules::DsnRules},
graph::GetNodeIndex, graph::GetNodeIndex,
}; };
fn unionfind(autorouter: &mut Autorouter<impl RulesTrait>) -> UnionFind<NodeIndex<usize>> { pub fn load_design_and_assert(filename: &str) -> Invoker<DsnRules> {
for ratline in autorouter.ratsnest().graph().edge_indices() { let design = DsnDesign::load_from_file(filename).unwrap();
// Accessing endpoints may create new dots because apex construction is lazy, so we access let mut invoker = Invoker::new(Autorouter::new(design.make_board()).unwrap());
// tem all before starting unionfind, as it requires a constant index bound.
let _ = autorouter.ratline_endpoints(ratline); assert!(matches!(
invoker.undo(),
Err(InvokerError::History(HistoryError::NoPreviousCommand))
));
assert!(matches!(
invoker.redo(),
Err(InvokerError::History(HistoryError::NoNextCommand))
));
invoker
}
pub fn replay_and_assert(invoker: &mut Invoker<DsnRules>, filename: &str) {
let file = File::open(filename).unwrap();
invoker.replay(serde_json::from_reader(file).unwrap());
let prev_node_count = invoker.autorouter().board().layout().drawing().node_count();
// Sanity test: check if node count remained the same after some attempts at undo-redo.
if invoker.redo().is_ok() {
let _ = invoker.undo();
} }
let mut unionfind = UnionFind::new( if invoker.undo().is_ok() {
autorouter if invoker.undo().is_ok() {
.board() let _ = invoker.redo();
.layout() }
.drawing()
.geometry() let _ = invoker.redo();
.graph() }
.node_bound(),
assert_eq!(
invoker.autorouter().board().layout().drawing().node_count(),
prev_node_count,
); );
for primitive in autorouter.board().layout().drawing().primitive_nodes() {
for joined in autorouter
.board()
.layout()
.drawing()
.geometry()
.joineds(primitive)
{
unionfind.union(primitive.node_index(), joined.node_index());
}
}
unionfind
} }
pub fn assert_single_layer_groundless_autoroute( pub fn assert_single_layer_groundless_autoroute(
@ -130,3 +148,35 @@ pub fn assert_band_length(
dbg!(band_length); dbg!(band_length);
assert!((band_length - length).abs() < epsilon); assert!((band_length - length).abs() < epsilon);
} }
fn unionfind(autorouter: &mut Autorouter<impl RulesTrait>) -> UnionFind<NodeIndex<usize>> {
for ratline in autorouter.ratsnest().graph().edge_indices() {
// Accessing endpoints may create new dots because apex construction is lazy, so we access
// tem all before starting unionfind, as it requires a constant index bound.
let _ = autorouter.ratline_endpoints(ratline);
}
let mut unionfind = UnionFind::new(
autorouter
.board()
.layout()
.drawing()
.geometry()
.graph()
.node_bound(),
);
for primitive in autorouter.board().layout().drawing().primitive_nodes() {
for joined in autorouter
.board()
.layout()
.drawing()
.geometry()
.joineds(primitive)
{
unionfind.union(primitive.node_index(), joined.node_index());
}
}
unionfind
}

View File

@ -20,12 +20,12 @@ mod common;
#[test] #[test]
fn test_0603_breakout() { fn test_0603_breakout() {
let design = let mut invoker =
DsnDesign::load_from_file("tests/single_layer/data/0603_breakout/0603_breakout.dsn") common::load_design_and_assert("tests/single_layer/data/0603_breakout/0603_breakout.dsn");
.unwrap(); common::replay_and_assert(
let mut invoker = Invoker::new(Autorouter::new(design.make_board()).unwrap()); &mut invoker,
let file = File::open("tests/single_layer/data/0603_breakout/autoroute_all.cmd").unwrap(); "tests/single_layer/data/0603_breakout/autoroute_all.cmd",
invoker.replay(serde_json::from_reader(file).unwrap()); );
let (mut autorouter, ..) = invoker.destruct(); let (mut autorouter, ..) = invoker.destruct();
@ -35,15 +35,13 @@ fn test_0603_breakout() {
#[test] #[test]
fn test_tht_diode_bridge_rectifier() { fn test_tht_diode_bridge_rectifier() {
let design = DsnDesign::load_from_file( let mut invoker = common::load_design_and_assert(
"tests/single_layer/data/tht_diode_bridge_rectifier/tht_diode_bridge_rectifier.dsn", "tests/single_layer/data/tht_diode_bridge_rectifier/tht_diode_bridge_rectifier.dsn",
); );
let board = design.unwrap().make_board(); common::replay_and_assert(
&mut invoker,
let mut invoker = Invoker::new(Autorouter::new(board).unwrap()); "tests/single_layer/data/tht_diode_bridge_rectifier/autoroute_all.cmd",
let file = );
File::open("tests/single_layer/data/tht_diode_bridge_rectifier/autoroute_all.cmd").unwrap();
invoker.replay(serde_json::from_reader(file).unwrap());
let (mut autorouter, ..) = invoker.destruct(); let (mut autorouter, ..) = invoker.destruct();
@ -54,16 +52,13 @@ fn test_tht_diode_bridge_rectifier() {
#[test] #[test]
fn test_four_3rd_order_smd_lc_filters() { fn test_four_3rd_order_smd_lc_filters() {
let design = DsnDesign::load_from_file( let mut invoker = common::load_design_and_assert(
"tests/single_layer/data/four_3rd_order_smd_lc_filters/four_3rd_order_smd_lc_filters.dsn", "tests/single_layer/data/four_3rd_order_smd_lc_filters/four_3rd_order_smd_lc_filters.dsn",
); );
let board = design.unwrap().make_board(); common::replay_and_assert(
&mut invoker,
let mut invoker = Invoker::new(Autorouter::new(board).unwrap()); "tests/single_layer/data/four_3rd_order_smd_lc_filters/autoroute_signals.cmd",
let file = );
File::open("tests/single_layer/data/four_3rd_order_smd_lc_filters/autoroute_signals.cmd")
.unwrap();
invoker.replay(serde_json::from_reader(file).unwrap());
let (mut autorouter, ..) = invoker.destruct(); let (mut autorouter, ..) = invoker.destruct();
@ -71,18 +66,16 @@ fn test_four_3rd_order_smd_lc_filters() {
//common::assert_number_of_conncomps(&mut autorouter, 16); //common::assert_number_of_conncomps(&mut autorouter, 16);
} }
// FIXME: This test fails indeterministically.
#[test] #[test]
fn test_3pin_xlr_tht_female_to_tht_female() { fn test_3pin_xlr_tht_female_to_tht_female() {
let design = DsnDesign::load_from_file( let mut invoker = common::load_design_and_assert(
"tests/single_layer/data/3pin_xlr_tht_female_to_tht_female/3pin_xlr_tht_female_to_tht_female.dsn" "tests/single_layer/data/3pin_xlr_tht_female_to_tht_female/3pin_xlr_tht_female_to_tht_female.dsn",
);
common::replay_and_assert(
&mut invoker,
"tests/single_layer/data/3pin_xlr_tht_female_to_tht_female/autoroute_all.cmd",
); );
let board = design.unwrap().make_board();
let mut invoker = Invoker::new(Autorouter::new(board).unwrap());
let file =
File::open("tests/single_layer/data/3pin_xlr_tht_female_to_tht_female/autoroute_all.cmd")
.unwrap();
invoker.replay(serde_json::from_reader(file).unwrap());
let (mut autorouter, ..) = invoker.destruct(); let (mut autorouter, ..) = invoker.destruct();