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