1use crate::{Expr, Name};
6use std::collections::{HashMap, HashSet};
7
8use super::types::{
9 ConfigNode, CongrArgKind, CongrHypothesis, CongrLemmaCache, CongrProof, CongruenceClosure,
10 CongruenceTheorem, DecisionNode, EGraph, ENode, Either2, Fixture, FlatApp, FlatCC,
11 FlatSubstitution, FocusStack, InstrumentedCC, LabelSet, MinHeap, NonEmptyVec, PathBuf,
12 PrefixCounter, RewriteRule, RewriteRuleSet, SimpleDag, SlidingSum, SmallMap, SparseVec,
13 StackCalc, StatSummary, Stopwatch, StringPool, TokenBucket, TransformStat, TransitiveClosure,
14 VersionedRecord, WindowIterator, WriteOnce,
15};
16
17pub fn mk_congr_theorem(fn_name: Name, num_args: usize) -> CongruenceTheorem {
23 let arg_kinds = vec![CongrArgKind::Eq; num_args];
24 CongruenceTheorem::new(fn_name, arg_kinds)
25}
26pub fn mk_congr_theorem_with_fixed(
31 fn_name: Name,
32 num_args: usize,
33 fixed_positions: &[usize],
34) -> CongruenceTheorem {
35 let mut arg_kinds = vec![CongrArgKind::Eq; num_args];
36 for &pos in fixed_positions {
37 if pos < num_args {
38 arg_kinds[pos] = CongrArgKind::Fixed;
39 }
40 }
41 CongruenceTheorem::new(fn_name, arg_kinds)
42}
43#[cfg(test)]
44mod tests {
45 use super::*;
46 use crate::{Literal, Name};
47 #[test]
48 fn test_find_self() {
49 let mut cc = CongruenceClosure::new();
50 let expr = Expr::Lit(Literal::Nat(42));
51 let found = cc.find(&expr);
52 assert_eq!(found, expr);
53 }
54 #[test]
55 fn test_merge() {
56 let mut cc = CongruenceClosure::new();
57 let e1 = Expr::Lit(Literal::Nat(1));
58 let e2 = Expr::Lit(Literal::Nat(2));
59 cc.add_equality(e1.clone(), e2.clone());
60 assert!(cc.are_equal(&e1, &e2));
61 }
62 #[test]
63 fn test_congruence() {
64 let mut cc = CongruenceClosure::new();
65 let f = Expr::Const(Name::str("f"), vec![]);
66 let a = Expr::Lit(Literal::Nat(1));
67 let b = Expr::Lit(Literal::Nat(2));
68 let fa = Expr::App(Box::new(f.clone()), Box::new(a.clone()));
69 let fb = Expr::App(Box::new(f), Box::new(b.clone()));
70 cc.add_equality(a, b);
71 assert!(cc.are_equal(&fa, &fb));
72 }
73 #[test]
74 fn test_transitivity() {
75 let mut cc = CongruenceClosure::new();
76 let a = Expr::Lit(Literal::Nat(1));
77 let b = Expr::Lit(Literal::Nat(2));
78 let c = Expr::Lit(Literal::Nat(3));
79 cc.add_equality(a.clone(), b.clone());
80 cc.add_equality(b, c.clone());
81 assert!(cc.are_equal(&a, &c));
82 }
83 #[test]
84 fn test_congr_theorem_basic() {
85 let ct = mk_congr_theorem(Name::str("f"), 2);
86 assert_eq!(ct.num_args, 2);
87 assert_eq!(ct.arg_kinds.len(), 2);
88 assert!(ct.arg_kinds.iter().all(|k| *k == CongrArgKind::Eq));
89 assert!(ct.has_eq_args());
90 assert_eq!(ct.num_eq_hypotheses(), 2);
91 }
92 #[test]
93 fn test_congr_theorem_with_fixed() {
94 let ct = mk_congr_theorem_with_fixed(Name::str("List.map"), 3, &[0]);
95 assert_eq!(ct.num_args, 3);
96 assert_eq!(ct.arg_kinds[0], CongrArgKind::Fixed);
97 assert_eq!(ct.arg_kinds[1], CongrArgKind::Eq);
98 assert_eq!(ct.arg_kinds[2], CongrArgKind::Eq);
99 assert_eq!(ct.num_eq_hypotheses(), 2);
100 }
101 #[test]
102 fn test_congr_arg_kind_enum() {
103 assert_ne!(CongrArgKind::Fixed, CongrArgKind::Eq);
104 assert_ne!(CongrArgKind::HEq, CongrArgKind::Cast);
105 assert_eq!(CongrArgKind::Subsingle, CongrArgKind::Subsingle);
106 }
107 #[test]
108 fn test_equality_with_proof() {
109 let mut cc = CongruenceClosure::new();
110 let a = Expr::Lit(Literal::Nat(1));
111 let b = Expr::Lit(Literal::Nat(2));
112 let proof = Expr::Const(Name::str("proof_a_eq_b"), vec![]);
113 cc.add_equality_with_proof(a.clone(), b.clone(), proof.clone());
114 assert!(cc.are_equal(&a, &b));
115 assert_eq!(cc.get_proof(&a, &b), Some(&proof));
116 }
117 #[test]
118 fn test_num_classes() {
119 let mut cc = CongruenceClosure::new();
120 let a = Expr::Lit(Literal::Nat(1));
121 let b = Expr::Lit(Literal::Nat(2));
122 let c = Expr::Lit(Literal::Nat(3));
123 cc.add_equality(a.clone(), b.clone());
124 let _ = cc.find(&c);
125 assert_eq!(cc.num_classes(), 2);
126 }
127 #[test]
128 fn test_clear() {
129 let mut cc = CongruenceClosure::new();
130 let a = Expr::Lit(Literal::Nat(1));
131 let b = Expr::Lit(Literal::Nat(2));
132 cc.add_equality(a, b);
133 cc.clear();
134 assert_eq!(cc.num_classes(), 0);
135 }
136}
137pub fn generate_congr_hypotheses(
143 lhs_args: &[Expr],
144 rhs_args: &[Expr],
145 kinds: &[CongrArgKind],
146) -> Vec<CongrHypothesis> {
147 assert_eq!(lhs_args.len(), rhs_args.len());
148 assert_eq!(lhs_args.len(), kinds.len());
149 lhs_args
150 .iter()
151 .zip(rhs_args.iter())
152 .zip(kinds.iter())
153 .filter_map(|((l, r), k)| match k {
154 CongrArgKind::Eq => Some(CongrHypothesis::eq(l.clone(), r.clone())),
155 CongrArgKind::HEq => Some(CongrHypothesis::heq(l.clone(), r.clone())),
156 _ => None,
157 })
158 .collect()
159}
160pub fn all_hypotheses_trivial(hyps: &[CongrHypothesis]) -> bool {
165 hyps.iter().all(|h| h.is_trivial())
166}
167pub fn is_simple_head(expr: &Expr) -> bool {
171 matches!(expr, Expr::Const(_, _) | Expr::FVar(_))
172}
173pub fn compatible_heads(e1: &Expr, e2: &Expr) -> bool {
175 match (e1, e2) {
176 (Expr::Const(n1, _), Expr::Const(n2, _)) => n1 == n2,
177 (Expr::FVar(f1), Expr::FVar(f2)) => f1 == f2,
178 (Expr::BVar(i1), Expr::BVar(i2)) => i1 == i2,
179 _ => false,
180 }
181}
182#[cfg(test)]
183mod egraph_tests {
184 use super::*;
185 use crate::{Literal, Name};
186 #[test]
187 fn test_enode_singleton() {
188 let expr = Expr::Lit(Literal::Nat(1));
189 let node = ENode::singleton(expr.clone());
190 assert!(node.contains(&expr));
191 assert_eq!(node.size(), 1);
192 }
193 #[test]
194 fn test_enode_add_member() {
195 let e1 = Expr::Lit(Literal::Nat(1));
196 let e2 = Expr::Lit(Literal::Nat(2));
197 let mut node = ENode::singleton(e1.clone());
198 node.add_member(e2.clone(), None);
199 assert!(node.contains(&e2));
200 assert_eq!(node.size(), 2);
201 }
202 #[test]
203 fn test_egraph_add_expr() {
204 let mut g = EGraph::new();
205 let e = Expr::Lit(Literal::Nat(42));
206 let id = g.add_expr(e.clone());
207 assert_eq!(g.find_class(&e), Some(id));
208 }
209 #[test]
210 fn test_egraph_add_equality() {
211 let mut g = EGraph::new();
212 let a = Expr::Lit(Literal::Nat(1));
213 let b = Expr::Lit(Literal::Nat(2));
214 g.add_equality(a.clone(), b.clone(), None);
215 assert!(g.are_equal(&a, &b));
216 }
217 #[test]
218 fn test_egraph_representative() {
219 let mut g = EGraph::new();
220 let a = Expr::Lit(Literal::Nat(1));
221 g.add_expr(a.clone());
222 let repr = g.representative(&a);
223 assert_eq!(repr, Some(&a));
224 }
225 #[test]
226 fn test_egraph_num_classes() {
227 let mut g = EGraph::new();
228 let a = Expr::Lit(Literal::Nat(1));
229 let b = Expr::Lit(Literal::Nat(2));
230 g.add_expr(a.clone());
231 g.add_expr(b.clone());
232 assert_eq!(g.num_classes(), 2);
233 g.add_equality(a, b, None);
234 assert_eq!(g.num_classes(), 1);
235 }
236 #[test]
237 fn test_congr_hypothesis_trivial() {
238 let e = Expr::Lit(Literal::Nat(1));
239 let h = CongrHypothesis::eq(e.clone(), e);
240 assert!(h.is_trivial());
241 }
242 #[test]
243 fn test_congr_hypothesis_nontrivial() {
244 let a = Expr::Lit(Literal::Nat(1));
245 let b = Expr::Lit(Literal::Nat(2));
246 let h = CongrHypothesis::eq(a, b);
247 assert!(!h.is_trivial());
248 }
249 #[test]
250 fn test_generate_congr_hypotheses() {
251 let a1 = Expr::Lit(Literal::Nat(1));
252 let a2 = Expr::Lit(Literal::Nat(2));
253 let b1 = Expr::Lit(Literal::Nat(3));
254 let b2 = Expr::Lit(Literal::Nat(4));
255 let hyps = generate_congr_hypotheses(
256 &[a1.clone(), b1.clone()],
257 &[a2.clone(), b2.clone()],
258 &[CongrArgKind::Eq, CongrArgKind::Fixed],
259 );
260 assert_eq!(hyps.len(), 1);
261 assert_eq!(hyps[0].lhs, a1);
262 }
263 #[test]
264 fn test_all_hypotheses_trivial_true() {
265 let e = Expr::Lit(Literal::Nat(1));
266 let hyps = vec![CongrHypothesis::eq(e.clone(), e)];
267 assert!(all_hypotheses_trivial(&hyps));
268 }
269 #[test]
270 fn test_all_hypotheses_trivial_false() {
271 let a = Expr::Lit(Literal::Nat(1));
272 let b = Expr::Lit(Literal::Nat(2));
273 let hyps = vec![CongrHypothesis::eq(a, b)];
274 assert!(!all_hypotheses_trivial(&hyps));
275 }
276 #[test]
277 fn test_is_simple_head() {
278 let c = Expr::Const(Name::str("f"), vec![]);
279 assert!(is_simple_head(&c));
280 let app = Expr::App(Box::new(c.clone()), Box::new(Expr::Lit(Literal::Nat(0))));
281 assert!(!is_simple_head(&app));
282 }
283 #[test]
284 fn test_compatible_heads() {
285 let c1 = Expr::Const(Name::str("f"), vec![]);
286 let c2 = Expr::Const(Name::str("f"), vec![]);
287 let c3 = Expr::Const(Name::str("g"), vec![]);
288 assert!(compatible_heads(&c1, &c2));
289 assert!(!compatible_heads(&c1, &c3));
290 }
291 #[test]
292 fn test_egraph_clear() {
293 let mut g = EGraph::new();
294 g.add_expr(Expr::Lit(Literal::Nat(1)));
295 g.clear();
296 assert_eq!(g.num_classes(), 0);
297 }
298}
299pub type TermIdx = usize;
301#[cfg(test)]
302mod new_tests {
303 use super::*;
304 use crate::{Literal, Name};
305 #[test]
306 fn test_instrumented_cc_add_equality() {
307 let mut icc = InstrumentedCC::new();
308 let a = Expr::Lit(Literal::Nat(1));
309 let b = Expr::Lit(Literal::Nat(2));
310 icc.add_equality(a.clone(), b.clone());
311 assert!(icc.are_equal(&a, &b));
312 assert_eq!(icc.stats.equalities_added, 1);
313 }
314 #[test]
315 fn test_flat_cc_basic() {
316 let mut fcc = FlatCC::new(4);
317 assert_eq!(fcc.num_nodes(), 4);
318 assert!(!fcc.are_equal(0, 1));
319 fcc.union(0, 1);
320 assert!(fcc.are_equal(0, 1));
321 assert!(!fcc.are_equal(0, 2));
322 }
323 #[test]
324 fn test_flat_cc_add_node() {
325 let mut fcc = FlatCC::new(2);
326 let idx = fcc.add_node();
327 assert_eq!(idx, 2);
328 assert_eq!(fcc.num_nodes(), 3);
329 }
330 #[test]
331 fn test_flat_cc_add_app() {
332 let mut fcc = FlatCC::new(3);
333 fcc.add_app(FlatApp {
334 fn_idx: 0,
335 arg_idx: 1,
336 result_idx: Some(2),
337 });
338 assert_eq!(fcc.num_apps(), 1);
339 }
340 #[test]
341 fn test_flat_cc_propagate_congruences() {
342 let mut fcc = FlatCC::new(5);
343 fcc.add_app(FlatApp {
344 fn_idx: 0,
345 arg_idx: 1,
346 result_idx: Some(3),
347 });
348 fcc.add_app(FlatApp {
349 fn_idx: 0,
350 arg_idx: 2,
351 result_idx: Some(4),
352 });
353 assert!(!fcc.are_equal(3, 4));
354 fcc.union(1, 2);
355 fcc.propagate_congruences();
356 assert!(fcc.are_equal(3, 4));
357 }
358 #[test]
359 fn test_flat_cc_find_self() {
360 let mut fcc = FlatCC::new(3);
361 assert_eq!(fcc.find(1), 1);
362 }
363 #[test]
364 fn test_congr_lemma_cache_basic() {
365 let mut cache = CongrLemmaCache::new();
366 assert!(cache.is_empty());
367 let _thm = cache.get_or_compute(Name::str("f"), 2);
368 assert_eq!(cache.len(), 1);
369 }
370 #[test]
371 fn test_congr_lemma_cache_hit() {
372 let mut cache = CongrLemmaCache::new();
373 let thm1 = cache.get_or_compute(Name::str("g"), 3);
374 let num_args1 = thm1.num_args;
375 let thm2 = cache.get_or_compute(Name::str("g"), 3);
376 assert_eq!(thm2.num_args, num_args1);
377 assert_eq!(cache.len(), 1);
378 }
379 #[test]
380 fn test_congr_lemma_cache_insert_get() {
381 let mut cache = CongrLemmaCache::new();
382 let thm = mk_congr_theorem(Name::str("h"), 1);
383 cache.insert(thm.clone());
384 let got = cache.get(&Name::str("h"), 1);
385 assert!(got.is_some());
386 assert_eq!(got.expect("got should be valid").num_args, 1);
387 }
388 #[test]
389 fn test_congr_lemma_cache_clear() {
390 let mut cache = CongrLemmaCache::new();
391 let _ = cache.get_or_compute(Name::str("f"), 1);
392 cache.clear();
393 assert!(cache.is_empty());
394 }
395 #[test]
396 fn test_congr_proof_refl() {
397 let p = CongrProof::Refl(Expr::Lit(Literal::Nat(1)));
398 assert!(p.is_refl());
399 assert_eq!(p.depth(), 0);
400 assert_eq!(p.hypothesis_count(), 0);
401 }
402 #[test]
403 fn test_congr_proof_symm() {
404 let hyp = CongrProof::Hyp(Name::str("h_eq"));
405 let p = CongrProof::Symm(Box::new(hyp));
406 assert!(!p.is_refl());
407 assert_eq!(p.depth(), 1);
408 assert_eq!(p.hypothesis_count(), 1);
409 }
410 #[test]
411 fn test_congr_proof_trans() {
412 let p1 = CongrProof::Hyp(Name::str("h1"));
413 let p2 = CongrProof::Hyp(Name::str("h2"));
414 let t = CongrProof::Trans(Box::new(p1), Box::new(p2));
415 assert_eq!(t.depth(), 1);
416 assert_eq!(t.hypothesis_count(), 2);
417 }
418 #[test]
419 fn test_congr_proof_simplify_double_symm() {
420 let hyp = CongrProof::Hyp(Name::str("h"));
421 let symm_symm = CongrProof::Symm(Box::new(CongrProof::Symm(Box::new(hyp))));
422 let simplified = symm_symm.simplify();
423 assert!(matches!(simplified, CongrProof::Hyp(_)));
424 }
425 #[test]
426 fn test_instrumented_cc_reset() {
427 let mut icc = InstrumentedCC::new();
428 let a = Expr::Lit(Literal::Nat(1));
429 let b = Expr::Lit(Literal::Nat(2));
430 icc.add_equality(a, b);
431 icc.reset();
432 assert_eq!(icc.stats.equalities_added, 0);
433 assert_eq!(icc.num_classes(), 0);
434 }
435}
436#[cfg(test)]
437mod tests_padding_infra {
438 use super::*;
439 #[test]
440 fn test_stat_summary() {
441 let mut ss = StatSummary::new();
442 ss.record(10.0);
443 ss.record(20.0);
444 ss.record(30.0);
445 assert_eq!(ss.count(), 3);
446 assert!((ss.mean().expect("mean should succeed") - 20.0).abs() < 1e-9);
447 assert_eq!(ss.min().expect("min should succeed") as i64, 10);
448 assert_eq!(ss.max().expect("max should succeed") as i64, 30);
449 }
450 #[test]
451 fn test_transform_stat() {
452 let mut ts = TransformStat::new();
453 ts.record_before(100.0);
454 ts.record_after(80.0);
455 let ratio = ts.mean_ratio().expect("ratio should be present");
456 assert!((ratio - 0.8).abs() < 1e-9);
457 }
458 #[test]
459 fn test_small_map() {
460 let mut m: SmallMap<u32, &str> = SmallMap::new();
461 m.insert(3, "three");
462 m.insert(1, "one");
463 m.insert(2, "two");
464 assert_eq!(m.get(&2), Some(&"two"));
465 assert_eq!(m.len(), 3);
466 let keys = m.keys();
467 assert_eq!(*keys[0], 1);
468 assert_eq!(*keys[2], 3);
469 }
470 #[test]
471 fn test_label_set() {
472 let mut ls = LabelSet::new();
473 ls.add("foo");
474 ls.add("bar");
475 ls.add("foo");
476 assert_eq!(ls.count(), 2);
477 assert!(ls.has("bar"));
478 assert!(!ls.has("baz"));
479 }
480 #[test]
481 fn test_config_node() {
482 let mut root = ConfigNode::section("root");
483 let child = ConfigNode::leaf("key", "value");
484 root.add_child(child);
485 assert_eq!(root.num_children(), 1);
486 }
487 #[test]
488 fn test_versioned_record() {
489 let mut vr = VersionedRecord::new(0u32);
490 vr.update(1);
491 vr.update(2);
492 assert_eq!(*vr.current(), 2);
493 assert_eq!(vr.version(), 2);
494 assert!(vr.has_history());
495 assert_eq!(*vr.at_version(0).expect("value should be present"), 0);
496 }
497 #[test]
498 fn test_simple_dag() {
499 let mut dag = SimpleDag::new(4);
500 dag.add_edge(0, 1);
501 dag.add_edge(1, 2);
502 dag.add_edge(2, 3);
503 assert!(dag.can_reach(0, 3));
504 assert!(!dag.can_reach(3, 0));
505 let order = dag.topological_sort().expect("order should be present");
506 assert_eq!(order, vec![0, 1, 2, 3]);
507 }
508 #[test]
509 fn test_focus_stack() {
510 let mut fs: FocusStack<&str> = FocusStack::new();
511 fs.focus("a");
512 fs.focus("b");
513 assert_eq!(fs.current(), Some(&"b"));
514 assert_eq!(fs.depth(), 2);
515 fs.blur();
516 assert_eq!(fs.current(), Some(&"a"));
517 }
518}
519#[cfg(test)]
520mod tests_extra_iterators {
521 use super::*;
522 #[test]
523 fn test_window_iterator() {
524 let data = vec![1u32, 2, 3, 4, 5];
525 let windows: Vec<_> = WindowIterator::new(&data, 3).collect();
526 assert_eq!(windows.len(), 3);
527 assert_eq!(windows[0], &[1, 2, 3]);
528 assert_eq!(windows[2], &[3, 4, 5]);
529 }
530 #[test]
531 fn test_non_empty_vec() {
532 let mut nev = NonEmptyVec::singleton(10u32);
533 nev.push(20);
534 nev.push(30);
535 assert_eq!(nev.len(), 3);
536 assert_eq!(*nev.first(), 10);
537 assert_eq!(*nev.last(), 30);
538 }
539}
540#[cfg(test)]
541mod tests_padding2 {
542 use super::*;
543 #[test]
544 fn test_sliding_sum() {
545 let mut ss = SlidingSum::new(3);
546 ss.push(1.0);
547 ss.push(2.0);
548 ss.push(3.0);
549 assert!((ss.sum() - 6.0).abs() < 1e-9);
550 ss.push(4.0);
551 assert!((ss.sum() - 9.0).abs() < 1e-9);
552 assert_eq!(ss.count(), 3);
553 }
554 #[test]
555 fn test_path_buf() {
556 let mut pb = PathBuf::new();
557 pb.push("src");
558 pb.push("main");
559 assert_eq!(pb.as_str(), "src/main");
560 assert_eq!(pb.depth(), 2);
561 pb.pop();
562 assert_eq!(pb.as_str(), "src");
563 }
564 #[test]
565 fn test_string_pool() {
566 let mut pool = StringPool::new();
567 let s = pool.take();
568 assert!(s.is_empty());
569 pool.give("hello".to_string());
570 let s2 = pool.take();
571 assert!(s2.is_empty());
572 assert_eq!(pool.free_count(), 0);
573 }
574 #[test]
575 fn test_transitive_closure() {
576 let mut tc = TransitiveClosure::new(4);
577 tc.add_edge(0, 1);
578 tc.add_edge(1, 2);
579 tc.add_edge(2, 3);
580 assert!(tc.can_reach(0, 3));
581 assert!(!tc.can_reach(3, 0));
582 let r = tc.reachable_from(0);
583 assert_eq!(r.len(), 4);
584 }
585 #[test]
586 fn test_token_bucket() {
587 let mut tb = TokenBucket::new(100, 10);
588 assert_eq!(tb.available(), 100);
589 assert!(tb.try_consume(50));
590 assert_eq!(tb.available(), 50);
591 assert!(!tb.try_consume(60));
592 assert_eq!(tb.capacity(), 100);
593 }
594 #[test]
595 fn test_rewrite_rule_set() {
596 let mut rrs = RewriteRuleSet::new();
597 rrs.add(RewriteRule::unconditional(
598 "beta",
599 "App(Lam(x, b), v)",
600 "b[x:=v]",
601 ));
602 rrs.add(RewriteRule::conditional("comm", "a + b", "b + a"));
603 assert_eq!(rrs.len(), 2);
604 assert_eq!(rrs.unconditional_rules().len(), 1);
605 assert_eq!(rrs.conditional_rules().len(), 1);
606 assert!(rrs.get("beta").is_some());
607 let disp = rrs
608 .get("beta")
609 .expect("element at \'beta\' should exist")
610 .display();
611 assert!(disp.contains("→"));
612 }
613}
614#[cfg(test)]
615mod tests_padding3 {
616 use super::*;
617 #[test]
618 fn test_decision_node() {
619 let tree = DecisionNode::Branch {
620 key: "x".into(),
621 val: "1".into(),
622 yes_branch: Box::new(DecisionNode::Leaf("yes".into())),
623 no_branch: Box::new(DecisionNode::Leaf("no".into())),
624 };
625 let mut ctx = std::collections::HashMap::new();
626 ctx.insert("x".into(), "1".into());
627 assert_eq!(tree.evaluate(&ctx), "yes");
628 ctx.insert("x".into(), "2".into());
629 assert_eq!(tree.evaluate(&ctx), "no");
630 assert_eq!(tree.depth(), 1);
631 }
632 #[test]
633 fn test_flat_substitution() {
634 let mut sub = FlatSubstitution::new();
635 sub.add("foo", "bar");
636 sub.add("baz", "qux");
637 assert_eq!(sub.apply("foo and baz"), "bar and qux");
638 assert_eq!(sub.len(), 2);
639 }
640 #[test]
641 fn test_stopwatch() {
642 let mut sw = Stopwatch::start();
643 sw.split();
644 sw.split();
645 assert_eq!(sw.num_splits(), 2);
646 assert!(sw.elapsed_ms() >= 0.0);
647 for &s in sw.splits() {
648 assert!(s >= 0.0);
649 }
650 }
651 #[test]
652 fn test_either2() {
653 let e: Either2<i32, &str> = Either2::First(42);
654 assert!(e.is_first());
655 let mapped = e.map_first(|x| x * 2);
656 assert_eq!(mapped.first(), Some(84));
657 let e2: Either2<i32, &str> = Either2::Second("hello");
658 assert!(e2.is_second());
659 assert_eq!(e2.second(), Some("hello"));
660 }
661 #[test]
662 fn test_write_once() {
663 let wo: WriteOnce<u32> = WriteOnce::new();
664 assert!(!wo.is_written());
665 assert!(wo.write(42));
666 assert!(!wo.write(99));
667 assert_eq!(wo.read(), Some(42));
668 }
669 #[test]
670 fn test_sparse_vec() {
671 let mut sv: SparseVec<i32> = SparseVec::new(100);
672 sv.set(5, 10);
673 sv.set(50, 20);
674 assert_eq!(*sv.get(5), 10);
675 assert_eq!(*sv.get(50), 20);
676 assert_eq!(*sv.get(0), 0);
677 assert_eq!(sv.nnz(), 2);
678 sv.set(5, 0);
679 assert_eq!(sv.nnz(), 1);
680 }
681 #[test]
682 fn test_stack_calc() {
683 let mut calc = StackCalc::new();
684 calc.push(3);
685 calc.push(4);
686 calc.add();
687 assert_eq!(calc.peek(), Some(7));
688 calc.push(2);
689 calc.mul();
690 assert_eq!(calc.peek(), Some(14));
691 }
692}
693#[cfg(test)]
694mod tests_final_padding {
695 use super::*;
696 #[test]
697 fn test_min_heap() {
698 let mut h = MinHeap::new();
699 h.push(5u32);
700 h.push(1u32);
701 h.push(3u32);
702 assert_eq!(h.peek(), Some(&1));
703 assert_eq!(h.pop(), Some(1));
704 assert_eq!(h.pop(), Some(3));
705 assert_eq!(h.pop(), Some(5));
706 assert!(h.is_empty());
707 }
708 #[test]
709 fn test_prefix_counter() {
710 let mut pc = PrefixCounter::new();
711 pc.record("hello");
712 pc.record("help");
713 pc.record("world");
714 assert_eq!(pc.count_with_prefix("hel"), 2);
715 assert_eq!(pc.count_with_prefix("wor"), 1);
716 assert_eq!(pc.count_with_prefix("xyz"), 0);
717 }
718 #[test]
719 fn test_fixture() {
720 let mut f = Fixture::new();
721 f.set("key1", "val1");
722 f.set("key2", "val2");
723 assert_eq!(f.get("key1"), Some("val1"));
724 assert_eq!(f.get("key3"), None);
725 assert_eq!(f.len(), 2);
726 }
727}