#[test] fn test_xsdebug() {
let mut xsd = XSDebug::new("abcvw");
let (a, b, v) = (xsd.xid("a"), xsd.xid("b"), xsd.xid("v"));
let x = xsd.xid("abv?");
assert_eq!(xsd.ite(v,b,a), x);
let (y,w) = (xsd.xid("acv?"), xsd.xid("w"));
let z = xsd.ite(w,y,x);
assert_eq!(xsd.fmt(z), "abv? acv? w? "); }
#[cfg(test)]
fn check_swap(old:&str, new:&str) {
let mut xsd = XSDebug::new("abcdvw");
let (v, x) = (xsd.vid('v'), xsd.xid(old));
xsd.xs.swap(v);
assert_eq!(xsd.fmt(x), new.to_string(), "unexpected results after swap.")}
#[test] fn test_swap() {
check_swap("abv? cdv? w?", "acw? bdw? v? ");
check_swap("abv? acv? w?", "abcw? v? ");
check_swap("a abv? w?", "aabw? v? ");
check_swap("abv? b w?", "abw? bv? "); }
#[test] fn test_tbl() {
let mut xsd = XSDebug::new("abcd");
let x = xsd.xid("a 1 b? 0 c?");
let o = XID_O; let i = XID_I;
assert_eq!(xsd.xs.tbl(x, None), vec![o,i,i,i, o,o,o,o]);
let a = xsd.xid("a");
assert_eq!(xsd.xs.tbl(x, Some(VID::var(0))), vec![a,i,o,o]);
let y = xsd.xid("a 1 b?");
assert_eq!(xsd.xs.tbl(x, Some(VID::var(1))), vec![y,o]);
assert_eq!(xsd.xs.tbl(x, Some(VID::var(2))), vec![x]);
assert_eq!(xsd.xs.tbl(x, Some(VID::var(3))), vec![x]);}
#[test] fn test_tbl_inv() {
let mut xsd = XSDebug::new("abcd");
let x = xsd.xid("a 1 b? 0 c?");
let o = XID_O; let i = XID_I;
assert_eq!(xsd.xs.tbl(!x, None), vec![i,o,o,o, i,i,i,i]);
let a = xsd.xid("a");
assert_eq!(xsd.xs.tbl(!x, Some(VID::var(0))), vec![!a,o,i,i]);
let y = xsd.xid("a 1 b?");
assert_eq!(xsd.xs.tbl(!x, Some(VID::var(1))), vec![!y,i]);
assert_eq!(xsd.xs.tbl(!x, Some(VID::var(2))), vec![!x]);
assert_eq!(xsd.xs.tbl(!x, Some(VID::var(3))), vec![!x]);}
#[test] fn test_tbl_skip() {
let mut xsd = XSDebug::new("abc");
let x = xsd.xid("a a! c?");
let o = XID_O; let i = XID_I;
assert_eq!(xsd.xs.tbl(x, None), vec![o,i,o,i, i,o,i,o]);}
#[test] fn test_untbl() {
let mut xsd = XSDebug::new("abc");
assert_eq!(xsd.run(" 01#"), "a");
assert_eq!(xsd.run(".10#"), "a!");
assert_eq!(xsd.run(".0101#"), "a");
assert_eq!(xsd.run(".0111#"), "a1b? ");
assert_eq!(xsd.run(".01b#"), "b"); }
#[test] fn test_untbl_base() {
let mut xsd = XSDebug::new("abc");
assert_eq!(xsd.run(" 01b#"), "b");
assert_eq!(xsd.run(".10b#"), "b!");
assert_eq!(xsd.run(".0101b#"), "b");
assert_eq!(xsd.run(".0111b#"), "b1c? ");
assert_eq!(xsd.run(".01c#"), "c"); }
#[cfg(test)]
fn check_sub(vids:&str, dst_s:&str, v:char, src_s:&str, goal:&str) {
let mut dst = XSDebug::new("");
let mut src = XSDebug::new("");
let mut expected_order = "";
let mut cv:HashMap<char,usize> = HashMap::new();
let mut phase = 0;
for (i,c) in vids.char_indices() {
if c == '|' { phase += 1 }
else { match phase {
0 => { cv.insert(c, i); },
1 => dst.var(*cv.get(&c).expect("bad entry in dst vars"), c),
2 => src.var(*cv.get(&c).expect("bad entry in src vars"), c),
3 => {
let mut parts = vids.split('|');
expected_order = (if c=='=' { parts.next() } else { parts.last() }).unwrap();
break },
_ => panic!("too many '|' chars encountered!") }}}
println!("building dst");
let dx = dst.xid(dst_s);
let rv = dst.vid(v);
println!("building src");
let sx = src.xid(src_s);
let (ss, xid) = {
let mut ss = SwapSolver::new(); ss.init(rv);
ss.dst = dst.xs; ss.dx = dx;
ss.src = src.xs; ss.sx = sx;
let xid = ss.sub();
(ss, xid)};
dst.xs = ss.dst; for (&c, &i) in cv.iter() { if !dst.cv.contains_key(&c) { dst.name_var(VID::var(i as u32), c) }}
assert_eq!(dst.vids(), expected_order, "unexpected vid ordering at end");
assert_eq!(dst.fmt(xid), dst.run(goal));}
#[test] fn test_sub_simple_0() {
check_sub("xy|x|y|y", "x", 'x', "y", "y") }
#[test] fn test_sub_simple_1() {
check_sub("wvxy|vxy|w|xyw", "vxy?", 'v', "w", "0xy? 1xy? w?")}
#[test] fn test_two_new() {
check_sub("abzxy|abz|xy|abxy", "abz?", 'z', "x0y?", "abx? ay?")}
#[test] fn test_two_old() {
check_sub("xyz|xyz|zx|xz", "xyz?", 'y', "z!zx?", "x")}
#[test] fn test_one_new() {
check_sub("wyx|wy|wx|xw", "w!wy?", 'y', "w0x?", "0xw?!")}
#[test] fn check_wtov_simple() {
let v = XID{ x: 1 };
let w = XID{ x: 2 };
let io = XHiLo{ hi: XID_I, lo: XID_O };
let mut ru = XVHLRow::new(); ru.hm.insert(io, IxRc{ ix:v, irc: 1, erc:0 });
let mut rd = XVHLRow::new(); rd.hm.insert(io, IxRc{ ix:w, irc: 1, erc:0 });
let mut worker = SwapWorker::new(WID::default());
let res = worker.set_ru(VID::var(0), ru).set_rd(VID::var(1), rd).gather_umovs();
assert_eq!(0, res.len());}
#[test] fn check_swap_merge() {
let mut xsd = XSDebug::new("tuvw");
let top:XID = xsd.xid("utv? uu!v? w?");
let v = xsd.cv[&'v'];
xsd.xs.swap(v);
assert_eq!(xsd.fmt(top), "utu!w? v? ")}
#[test] fn test_fun_tbl() {
use crate::ops; let o = XID_O; let i = XID_I;
assert_eq!(fun_tbl(ops::AND.to_nid()), vec![o,o,o,i])}
#[cfg(test)] macro_rules! s {
{ } => { HashSet::new() };
{$( $x:expr ),+ } => {{ let mut tmp = HashSet::new(); $( tmp.insert($x); )* tmp }};}
#[cfg(test)] macro_rules! d {
{ } => { HashMap::new() };
{$( $k:ident : $v:expr ),+ }=> {{ let mut tmp = HashMap::new(); $( tmp.insert($k,$v); )* tmp }};}
#[test] fn test_plan_regroup() {
let x0:VID = VID::var(0);
let x1:VID = VID::var(1);
let x2:VID = VID::var(2);
let x3:VID = VID::var(3);
let x4:VID = VID::var(4);
assert_eq!(d!{ }, plan_regroup(&[x0,x1,x2], &[s![x0], s![x1], s![x2]]));
assert_eq!(d!{ x1:1 }, plan_regroup(&[x1,x0,x2], &[s![x0], s![x1], s![x2]]));
assert_eq!(d!{ x4:4, x3:3 }, plan_regroup(&[x3,x2,x4,x0,x1], &[s![x2,x0,x1],s![],s![x4,x3]]));
assert_eq!(d!{ x4:3, x3:4 }, plan_regroup(&[x4,x2,x3,x0,x1], &[s![x2,x0,x1],s![],s![x4,x3]]));
assert_eq!(d!{ x4:4, x3:3 }, plan_regroup(&[x3,x1,x2,x4,x0], &[s![x2,x0,x1],s![],s![x4,x3]]));
println!("----------");
assert_eq!(d!{ x3:3 }, plan_regroup(&[x3,x1,x2,x0,x4], &[s![x2,x0,x1],s![],s![x4,x3]]));
}