1use crate::Node;
6use crate::{BinderInfo, Environment, Expr, FVarId, Level, Literal, Name};
7use std::rc::Rc;
8
9use super::types::{
10 ConfigNode, DecisionNode, Either2, FlatSubstitution, FocusStack, InferCache, InferStats,
11 LabelSet, NonEmptyVec, PathBuf, RewriteRule, RewriteRuleSet, SimpleDag, SlidingSum, SmallMap,
12 SparseVec, StackCalc, StatSummary, Stopwatch, StringPool, TokenBucket, TransformStat,
13 TransitiveClosure, TypeChecker, TypeKind, TypingJudgment, VersionedRecord, WindowIterator,
14 WriteOnce,
15};
16
17#[cfg(test)]
18mod tests {
19 use super::*;
20 use crate::{BinderInfo, Declaration};
21 #[test]
22 fn test_infer_sort() {
23 let env = Environment::new();
24 let mut tc = TypeChecker::new(&env);
25 let prop = Expr::Sort(Level::zero());
26 let prop_ty = tc.infer_type(&prop).expect("prop_ty should be present");
27 assert_eq!(prop_ty, Expr::Sort(Level::succ(Level::zero())));
28 }
29 #[test]
30 fn test_infer_constant() {
31 let mut env = Environment::new();
32 let nat_ty = Expr::Sort(Level::succ(Level::zero()));
33 env.add(Declaration::Axiom {
34 name: Name::str("Nat"),
35 univ_params: vec![],
36 ty: nat_ty.clone(),
37 })
38 .expect("value should be present");
39 let mut tc = TypeChecker::new(&env);
40 let nat_const = Expr::Const(Name::str("Nat"), vec![]);
41 let result = tc.infer_type(&nat_const).expect("result should be present");
42 assert_eq!(result, nat_ty);
43 }
44 #[test]
45 fn test_infer_lambda() {
46 let env = Environment::new();
47 let mut tc = TypeChecker::new(&env);
48 let ty = Expr::Sort(Level::zero());
49 let body = Expr::BVar(0);
50 let lam = Expr::Lam(
51 BinderInfo::Default,
52 Name::str("x"),
53 Node::new(ty.clone()),
54 Node::new(body),
55 );
56 let result = tc.infer_type(&lam).expect("result should be present");
57 assert!(matches!(result, Expr::Pi(_, _, _, _)));
58 }
59 #[test]
60 fn test_infer_literal() {
61 let env = Environment::new();
62 let mut tc = TypeChecker::new(&env);
63 let nat_lit = Expr::Lit(Literal::nat(42));
64 let result = tc.infer_type(&nat_lit).expect("result should be present");
65 assert_eq!(result, Expr::Const(Name::str("Nat"), vec![]));
66 }
67 #[test]
68 fn test_ensure_sort() {
69 let env = Environment::new();
70 let mut tc = TypeChecker::new(&env);
71 let prop = Expr::Sort(Level::zero());
72 let level = tc.ensure_sort(&prop).expect("level should be present");
73 assert_eq!(level, Level::succ(Level::zero()));
74 }
75 #[test]
76 fn test_def_eq_integration() {
77 let mut env = Environment::new();
78 let val = Expr::Lit(Literal::nat(42));
79 env.add(Declaration::Definition {
80 name: Name::str("answer"),
81 univ_params: vec![],
82 ty: Expr::Const(Name::str("Nat"), vec![]),
83 val: val.clone(),
84 hint: crate::ReducibilityHint::Regular(1),
85 })
86 .expect("value should be present");
87 let mut tc = TypeChecker::new(&env);
88 let answer = Expr::Const(Name::str("answer"), vec![]);
89 assert!(tc.is_def_eq(&answer, &val));
90 }
91 #[test]
92 fn test_whnf_integration() {
93 let mut env = Environment::new();
94 let val = Expr::Lit(Literal::nat(42));
95 env.add(Declaration::Definition {
96 name: Name::str("x"),
97 univ_params: vec![],
98 ty: Expr::Const(Name::str("Nat"), vec![]),
99 val: val.clone(),
100 hint: crate::ReducibilityHint::Abbrev,
101 })
102 .expect("value should be present");
103 let mut tc = TypeChecker::new(&env);
104 let result = tc.whnf(&Expr::Const(Name::str("x"), vec![]));
105 assert_eq!(result, val);
106 }
107 #[test]
108 fn test_infer_only_mode() {
109 let env = Environment::new();
110 let mut tc = TypeChecker::new_infer_only(&env);
111 let ty = Expr::FVar(FVarId(999));
112 let body = Expr::BVar(0);
113 let lam = Expr::Lam(
114 BinderInfo::Default,
115 Name::str("x"),
116 Node::new(ty),
117 Node::new(body),
118 );
119 let result = tc.infer_type(&lam);
120 assert!(result.is_ok());
121 }
122 #[test]
123 fn test_const_with_levels() {
124 let mut env = Environment::new();
125 let ci = crate::ConstantInfo::Axiom(crate::declaration::AxiomVal {
126 common: crate::declaration::ConstantVal {
127 name: Name::str("List"),
128 level_params: vec![Name::str("u")],
129 ty: Expr::Sort(Level::succ(Level::param(Name::str("u")))),
130 },
131 is_unsafe: false,
132 });
133 env.add_constant(ci).expect("value should be present");
134 let mut tc = TypeChecker::new(&env);
135 let list_type1 = Expr::Const(Name::str("List"), vec![Level::zero()]);
136 let result = tc
137 .infer_type(&list_type1)
138 .expect("result should be present");
139 assert_eq!(result, Expr::Sort(Level::succ(Level::zero())));
140 }
141}
142#[cfg(test)]
143mod extended_tests {
144 use super::*;
145 use crate::{BinderInfo, Literal};
146 #[test]
147 fn test_infer_app_chain_no_args() {
148 let env = Environment::new();
149 let mut tc = TypeChecker::new(&env);
150 let nat_ty = Expr::Sort(Level::succ(Level::zero()));
151 let fvar = tc.fresh_fvar(Name::str("f"), nat_ty.clone());
152 let result = tc.infer_app_chain(&Expr::FVar(fvar), &[]);
153 assert!(result.is_ok());
154 assert_eq!(result.expect("result should be valid"), nat_ty);
155 }
156 #[test]
157 fn test_telescope_type_no_pis() {
158 let env = Environment::new();
159 let mut tc = TypeChecker::new(&env);
160 let nat = Expr::Const(Name::str("Nat"), vec![]);
161 let (fvars, body) = tc.telescope_type(&nat, 5);
162 assert!(fvars.is_empty());
163 assert_eq!(body, nat);
164 }
165 #[test]
166 fn test_telescope_type_with_pi() {
167 let env = Environment::new();
168 let mut tc = TypeChecker::new(&env);
169 let nat = Expr::Const(Name::str("Nat"), vec![]);
170 let pi = Expr::Pi(
171 BinderInfo::Default,
172 Name::str("x"),
173 Node::new(nat.clone()),
174 Node::new(nat.clone()),
175 );
176 let (fvars, body) = tc.telescope_type(&pi, 1);
177 assert_eq!(fvars.len(), 1);
178 assert_eq!(body, nat);
179 }
180 #[test]
181 fn test_count_pi_binders_none() {
182 let env = Environment::new();
183 let mut tc = TypeChecker::new(&env);
184 let nat = Expr::Const(Name::str("Nat"), vec![]);
185 assert_eq!(tc.count_pi_binders(&nat), 0);
186 }
187 #[test]
188 fn test_count_pi_binders_two() {
189 let env = Environment::new();
190 let mut tc = TypeChecker::new(&env);
191 let nat = Expr::Const(Name::str("Nat"), vec![]);
192 let pi = Expr::Pi(
193 BinderInfo::Default,
194 Name::str("a"),
195 Node::new(nat.clone()),
196 Node::new(Expr::Pi(
197 BinderInfo::Default,
198 Name::str("b"),
199 Node::new(nat.clone()),
200 Node::new(nat.clone()),
201 )),
202 );
203 assert_eq!(tc.count_pi_binders(&pi), 2);
204 }
205 #[test]
206 fn test_close_type_over_fvars_empty() {
207 let env = Environment::new();
208 let mut tc = TypeChecker::new(&env);
209 let ty = Expr::Const(Name::str("Nat"), vec![]);
210 let result = tc.close_type_over_fvars(&[], ty.clone());
211 assert_eq!(result, ty);
212 }
213 #[test]
214 fn test_close_term_over_fvars_empty() {
215 let env = Environment::new();
216 let mut tc = TypeChecker::new(&env);
217 let term = Expr::Lit(Literal::nat(42));
218 let result = tc.close_term_over_fvars(&[], term.clone());
219 assert_eq!(result, term);
220 }
221 #[test]
222 fn test_try_check_correct() {
223 let env = Environment::new();
224 let mut tc = TypeChecker::new(&env);
225 let prop = Expr::Sort(Level::zero());
226 let type1 = Expr::Sort(Level::succ(Level::zero()));
227 assert!(tc.try_check(&prop, &type1));
228 }
229 #[test]
230 fn test_try_check_wrong() {
231 let env = Environment::new();
232 let mut tc = TypeChecker::new(&env);
233 let prop = Expr::Sort(Level::zero());
234 assert!(!tc.try_check(&prop, &prop));
235 }
236 #[test]
237 fn test_normalize_literal() {
238 let env = Environment::new();
239 let mut tc = TypeChecker::new(&env);
240 let lit = Expr::Lit(Literal::nat(5));
241 let result = tc.normalize(&lit);
242 assert_eq!(result, lit);
243 }
244 #[test]
245 fn test_verify_declaration_ok() {
246 let env = Environment::new();
247 let mut tc = TypeChecker::new(&env);
248 let ty = Expr::Sort(Level::succ(Level::zero()));
249 assert!(tc.verify_declaration(&Name::str("Foo"), &ty, None).is_ok());
250 }
251 #[test]
252 fn test_infer_stats_default() {
253 let stats = InferStats::default();
254 assert_eq!(stats.infer_calls, 0);
255 assert_eq!(stats.total_ops(), 0);
256 }
257 #[test]
258 fn test_infer_stats_total_ops() {
259 let stats = InferStats {
260 infer_calls: 3,
261 whnf_calls: 2,
262 def_eq_calls: 1,
263 const_lookups: 4,
264 cache_hits: 0,
265 };
266 assert_eq!(stats.total_ops(), 6);
267 }
268}
269#[allow(dead_code)]
271pub fn classify_expr(expr: &Expr) -> TypeKind {
272 match expr {
273 Expr::Sort(l) => {
274 if let Some(n) = l.to_nat() {
275 if n == 0 {
276 TypeKind::Prop
277 } else if n == 1 {
278 TypeKind::Type0
279 } else {
280 TypeKind::LargeType
281 }
282 } else {
283 TypeKind::Universe
284 }
285 }
286 Expr::Pi(_, _, _, _) => TypeKind::Pi,
287 Expr::Lam(_, _, _, _) => TypeKind::Lambda,
288 Expr::App(_, _) => TypeKind::Application,
289 Expr::FVar(_) => TypeKind::FreeVar,
290 Expr::Const(_, _) => TypeKind::Constant,
291 Expr::Lit(_) => TypeKind::Literal,
292 _ => TypeKind::Unknown,
293 }
294}
295#[allow(dead_code)]
297pub fn is_sort(expr: &Expr) -> bool {
298 matches!(expr, Expr::Sort(_))
299}
300#[allow(dead_code)]
302pub fn is_prop(expr: &Expr) -> bool {
303 matches!(expr, Expr::Sort(l) if l.is_zero())
304}
305#[allow(dead_code)]
307pub fn is_pi(expr: &Expr) -> bool {
308 matches!(expr, Expr::Pi(_, _, _, _))
309}
310#[allow(dead_code)]
314pub fn pi_components(expr: &Expr) -> Option<(&BinderInfo, &Name, &Expr, &Expr)> {
315 match expr {
316 Expr::Pi(bi, name, ty, body) => Some((bi, name, ty, body)),
317 _ => None,
318 }
319}
320#[allow(dead_code)]
326pub fn pi_sort(domain_sort: &Level, codomain_sort: &Level) -> Level {
327 if codomain_sort.is_zero() {
328 Level::zero()
329 } else {
330 Level::max(domain_sort.clone(), codomain_sort.clone())
331 }
332}
333#[cfg(test)]
334mod extra_infer_tests {
335 use super::*;
336 #[test]
337 fn test_infer_cache_insert_get() {
338 let mut cache = InferCache::new(10);
339 let expr = Expr::Lit(Literal::nat(42));
340 let ty = Expr::Const(Name::str("Nat"), vec![]);
341 cache.insert(expr.clone(), ty.clone());
342 assert_eq!(cache.get(&expr), Some(&ty));
343 }
344 #[test]
345 fn test_infer_cache_miss() {
346 let cache = InferCache::new(10);
347 let expr = Expr::Lit(Literal::nat(1));
348 assert_eq!(cache.get(&expr), None);
349 }
350 #[test]
351 fn test_infer_cache_eviction() {
352 let mut cache = InferCache::new(2);
353 let e0 = Expr::Lit(Literal::nat(0));
354 let e1 = Expr::Lit(Literal::nat(1));
355 let e2 = Expr::Lit(Literal::nat(2));
356 let ty = Expr::Sort(Level::zero());
357 cache.insert(e0.clone(), ty.clone());
358 cache.insert(e1.clone(), ty.clone());
359 cache.insert(e2.clone(), ty.clone());
360 assert_eq!(cache.get(&e0), None);
361 assert!(cache.get(&e1).is_some());
362 assert!(cache.get(&e2).is_some());
363 }
364 #[test]
365 fn test_infer_cache_clear() {
366 let mut cache = InferCache::new(5);
367 cache.insert(Expr::Lit(Literal::nat(1)), Expr::Sort(Level::zero()));
368 cache.clear();
369 assert!(cache.is_empty());
370 }
371 #[test]
372 fn test_typing_judgment_ok() {
373 let j = TypingJudgment::ok(
374 Expr::Lit(Literal::nat(1)),
375 Expr::Const(Name::str("Nat"), vec![]),
376 );
377 assert!(j.is_ok());
378 }
379 #[test]
380 fn test_typing_judgment_fail() {
381 let j = TypingJudgment::fail(Expr::Lit(Literal::nat(0)));
382 assert!(!j.is_ok());
383 }
384 #[test]
385 fn test_classify_expr_prop() {
386 let prop = Expr::Sort(Level::zero());
387 assert_eq!(classify_expr(&prop), TypeKind::Prop);
388 }
389 #[test]
390 fn test_classify_expr_type0() {
391 let t0 = Expr::Sort(Level::succ(Level::zero()));
392 assert_eq!(classify_expr(&t0), TypeKind::Type0);
393 }
394 #[test]
395 fn test_classify_expr_pi() {
396 let pi = Expr::Pi(
397 BinderInfo::Default,
398 Name::str("x"),
399 Node::new(Expr::Sort(Level::zero())),
400 Node::new(Expr::Sort(Level::zero())),
401 );
402 assert_eq!(classify_expr(&pi), TypeKind::Pi);
403 }
404 #[test]
405 fn test_classify_expr_lambda() {
406 let lam = Expr::Lam(
407 BinderInfo::Default,
408 Name::str("x"),
409 Node::new(Expr::Sort(Level::zero())),
410 Node::new(Expr::BVar(0)),
411 );
412 assert_eq!(classify_expr(&lam), TypeKind::Lambda);
413 }
414 #[test]
415 fn test_classify_expr_literal() {
416 let lit = Expr::Lit(Literal::nat(5));
417 assert_eq!(classify_expr(&lit), TypeKind::Literal);
418 }
419 #[test]
420 fn test_is_sort_true() {
421 assert!(is_sort(&Expr::Sort(Level::zero())));
422 }
423 #[test]
424 fn test_is_sort_false() {
425 assert!(!is_sort(&Expr::Lit(Literal::nat(1))));
426 }
427 #[test]
428 fn test_is_prop_true() {
429 assert!(is_prop(&Expr::Sort(Level::zero())));
430 }
431 #[test]
432 fn test_is_prop_false() {
433 assert!(!is_prop(&Expr::Sort(Level::succ(Level::zero()))));
434 }
435 #[test]
436 fn test_is_pi_true() {
437 let pi = Expr::Pi(
438 BinderInfo::Default,
439 Name::str("_"),
440 Node::new(Expr::Sort(Level::zero())),
441 Node::new(Expr::Sort(Level::zero())),
442 );
443 assert!(is_pi(&pi));
444 }
445 #[test]
446 fn test_pi_components() {
447 let pi = Expr::Pi(
448 BinderInfo::Default,
449 Name::str("x"),
450 Node::new(Expr::Sort(Level::zero())),
451 Node::new(Expr::Sort(Level::succ(Level::zero()))),
452 );
453 let result = pi_components(&pi);
454 assert!(result.is_some());
455 let (_, name, _, _) = result.expect("result should be valid");
456 assert_eq!(*name, Name::str("x"));
457 }
458 #[test]
459 fn test_pi_sort_prop_codomain() {
460 let dom = Level::succ(Level::zero());
461 let cod = Level::zero();
462 let result = pi_sort(&dom, &cod);
463 assert!(result.is_zero());
464 }
465 #[test]
466 fn test_pi_sort_type_codomain() {
467 let dom = Level::succ(Level::zero());
468 let cod = Level::succ(Level::zero());
469 let result = pi_sort(&dom, &cod);
470 assert!(!result.is_zero());
471 }
472}
473#[cfg(test)]
474mod tests_padding_infra {
475 use super::*;
476 #[test]
477 fn test_stat_summary() {
478 let mut ss = StatSummary::new();
479 ss.record(10.0);
480 ss.record(20.0);
481 ss.record(30.0);
482 assert_eq!(ss.count(), 3);
483 assert!((ss.mean().expect("mean should succeed") - 20.0).abs() < 1e-9);
484 assert_eq!(ss.min().expect("min should succeed") as i64, 10);
485 assert_eq!(ss.max().expect("max should succeed") as i64, 30);
486 }
487 #[test]
488 fn test_transform_stat() {
489 let mut ts = TransformStat::new();
490 ts.record_before(100.0);
491 ts.record_after(80.0);
492 let ratio = ts.mean_ratio().expect("ratio should be present");
493 assert!((ratio - 0.8).abs() < 1e-9);
494 }
495 #[test]
496 fn test_small_map() {
497 let mut m: SmallMap<u32, &str> = SmallMap::new();
498 m.insert(3, "three");
499 m.insert(1, "one");
500 m.insert(2, "two");
501 assert_eq!(m.get(&2), Some(&"two"));
502 assert_eq!(m.len(), 3);
503 let keys = m.keys();
504 assert_eq!(*keys[0], 1);
505 assert_eq!(*keys[2], 3);
506 }
507 #[test]
508 fn test_label_set() {
509 let mut ls = LabelSet::new();
510 ls.add("foo");
511 ls.add("bar");
512 ls.add("foo");
513 assert_eq!(ls.count(), 2);
514 assert!(ls.has("bar"));
515 assert!(!ls.has("baz"));
516 }
517 #[test]
518 fn test_config_node() {
519 let mut root = ConfigNode::section("root");
520 let child = ConfigNode::leaf("key", "value");
521 root.add_child(child);
522 assert_eq!(root.num_children(), 1);
523 }
524 #[test]
525 fn test_versioned_record() {
526 let mut vr = VersionedRecord::new(0u32);
527 vr.update(1);
528 vr.update(2);
529 assert_eq!(*vr.current(), 2);
530 assert_eq!(vr.version(), 2);
531 assert!(vr.has_history());
532 assert_eq!(*vr.at_version(0).expect("value should be present"), 0);
533 }
534 #[test]
535 fn test_simple_dag() {
536 let mut dag = SimpleDag::new(4);
537 dag.add_edge(0, 1);
538 dag.add_edge(1, 2);
539 dag.add_edge(2, 3);
540 assert!(dag.can_reach(0, 3));
541 assert!(!dag.can_reach(3, 0));
542 let order = dag.topological_sort().expect("order should be present");
543 assert_eq!(order, vec![0, 1, 2, 3]);
544 }
545 #[test]
546 fn test_focus_stack() {
547 let mut fs: FocusStack<&str> = FocusStack::new();
548 fs.focus("a");
549 fs.focus("b");
550 assert_eq!(fs.current(), Some(&"b"));
551 assert_eq!(fs.depth(), 2);
552 fs.blur();
553 assert_eq!(fs.current(), Some(&"a"));
554 }
555}
556#[cfg(test)]
557mod tests_extra_iterators {
558 use super::*;
559 #[test]
560 fn test_window_iterator() {
561 let data = vec![1u32, 2, 3, 4, 5];
562 let windows: Vec<_> = WindowIterator::new(&data, 3).collect();
563 assert_eq!(windows.len(), 3);
564 assert_eq!(windows[0], &[1, 2, 3]);
565 assert_eq!(windows[2], &[3, 4, 5]);
566 }
567 #[test]
568 fn test_non_empty_vec() {
569 let mut nev = NonEmptyVec::singleton(10u32);
570 nev.push(20);
571 nev.push(30);
572 assert_eq!(nev.len(), 3);
573 assert_eq!(*nev.first(), 10);
574 assert_eq!(*nev.last(), 30);
575 }
576}
577#[cfg(test)]
578mod tests_padding2 {
579 use super::*;
580 #[test]
581 fn test_sliding_sum() {
582 let mut ss = SlidingSum::new(3);
583 ss.push(1.0);
584 ss.push(2.0);
585 ss.push(3.0);
586 assert!((ss.sum() - 6.0).abs() < 1e-9);
587 ss.push(4.0);
588 assert!((ss.sum() - 9.0).abs() < 1e-9);
589 assert_eq!(ss.count(), 3);
590 }
591 #[test]
592 fn test_path_buf() {
593 let mut pb = PathBuf::new();
594 pb.push("src");
595 pb.push("main");
596 assert_eq!(pb.as_str(), "src/main");
597 assert_eq!(pb.depth(), 2);
598 pb.pop();
599 assert_eq!(pb.as_str(), "src");
600 }
601 #[test]
602 fn test_string_pool() {
603 let mut pool = StringPool::new();
604 let s = pool.take();
605 assert!(s.is_empty());
606 pool.give("hello".to_string());
607 let s2 = pool.take();
608 assert!(s2.is_empty());
609 assert_eq!(pool.free_count(), 0);
610 }
611 #[test]
612 fn test_transitive_closure() {
613 let mut tc = TransitiveClosure::new(4);
614 tc.add_edge(0, 1);
615 tc.add_edge(1, 2);
616 tc.add_edge(2, 3);
617 assert!(tc.can_reach(0, 3));
618 assert!(!tc.can_reach(3, 0));
619 let r = tc.reachable_from(0);
620 assert_eq!(r.len(), 4);
621 }
622 #[test]
623 fn test_token_bucket() {
624 let mut tb = TokenBucket::new(100, 0);
625 assert_eq!(tb.available(), 100);
626 assert!(tb.try_consume(50));
627 assert_eq!(tb.available(), 50);
628 assert!(!tb.try_consume(60));
629 assert_eq!(tb.capacity(), 100);
630 }
631 #[test]
632 fn test_rewrite_rule_set() {
633 let mut rrs = RewriteRuleSet::new();
634 rrs.add(RewriteRule::unconditional(
635 "beta",
636 "App(Lam(x, b), v)",
637 "b[x:=v]",
638 ));
639 rrs.add(RewriteRule::conditional("comm", "a + b", "b + a"));
640 assert_eq!(rrs.len(), 2);
641 assert_eq!(rrs.unconditional_rules().len(), 1);
642 assert_eq!(rrs.conditional_rules().len(), 1);
643 assert!(rrs.get("beta").is_some());
644 let disp = rrs
645 .get("beta")
646 .expect("element at \'beta\' should exist")
647 .display();
648 assert!(disp.contains("→"));
649 }
650}
651#[cfg(test)]
652mod tests_padding3 {
653 use super::*;
654 #[test]
655 fn test_decision_node() {
656 let tree = DecisionNode::Branch {
657 key: "x".into(),
658 val: "1".into(),
659 yes_branch: Box::new(DecisionNode::Leaf("yes".into())),
660 no_branch: Box::new(DecisionNode::Leaf("no".into())),
661 };
662 let mut ctx = std::collections::HashMap::new();
663 ctx.insert("x".into(), "1".into());
664 assert_eq!(tree.evaluate(&ctx), "yes");
665 ctx.insert("x".into(), "2".into());
666 assert_eq!(tree.evaluate(&ctx), "no");
667 assert_eq!(tree.depth(), 1);
668 }
669 #[test]
670 fn test_flat_substitution() {
671 let mut sub = FlatSubstitution::new();
672 sub.add("foo", "bar");
673 sub.add("baz", "qux");
674 assert_eq!(sub.apply("foo and baz"), "bar and qux");
675 assert_eq!(sub.len(), 2);
676 }
677 #[test]
678 fn test_stopwatch() {
679 let mut sw = Stopwatch::start();
680 sw.split();
681 sw.split();
682 assert_eq!(sw.num_splits(), 2);
683 assert!(sw.elapsed_ms() >= 0.0);
684 for &s in sw.splits() {
685 assert!(s >= 0.0);
686 }
687 }
688 #[test]
689 fn test_either2() {
690 let e: Either2<i32, &str> = Either2::First(42);
691 assert!(e.is_first());
692 let mapped = e.map_first(|x| x * 2);
693 assert_eq!(mapped.first(), Some(84));
694 let e2: Either2<i32, &str> = Either2::Second("hello");
695 assert!(e2.is_second());
696 assert_eq!(e2.second(), Some("hello"));
697 }
698 #[test]
699 fn test_write_once() {
700 let wo: WriteOnce<u32> = WriteOnce::new();
701 assert!(!wo.is_written());
702 assert!(wo.write(42));
703 assert!(!wo.write(99));
704 assert_eq!(wo.read(), Some(42));
705 }
706 #[test]
707 fn test_sparse_vec() {
708 let mut sv: SparseVec<i32> = SparseVec::new(100);
709 sv.set(5, 10);
710 sv.set(50, 20);
711 assert_eq!(*sv.get(5), 10);
712 assert_eq!(*sv.get(50), 20);
713 assert_eq!(*sv.get(0), 0);
714 assert_eq!(sv.nnz(), 2);
715 sv.set(5, 0);
716 assert_eq!(sv.nnz(), 1);
717 }
718 #[test]
719 fn test_stack_calc() {
720 let mut calc = StackCalc::new();
721 calc.push(3);
722 calc.push(4);
723 assert_eq!(calc.add(), Some(7));
724 assert_eq!(calc.peek(), Some(7));
725 calc.push(2);
726 assert_eq!(calc.mul(), Some(14));
727 assert_eq!(calc.peek(), Some(14));
728 }
729}