async_utils/hanging_get/
test_util.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::cell::RefCell;
6use std::fmt::Debug;
7use std::rc::Rc;
8
9/// An observer that can be used to observe values from a `HangingGet` or
10/// `Window` instance. The observer must not be observed multiple
11/// times without the value being taken with `take_value` inbetween each
12/// observation. This prevents overwriting observations without checking
13/// them and simplifies the logic and API surface of this fake.
14#[derive(Clone, Debug, PartialEq)]
15pub struct TestObserver<V: Debug + PartialEq> {
16    value: Rc<RefCell<Option<V>>>,
17    expected: Option<V>,
18}
19
20impl<V: Debug + Clone + Send + PartialEq> TestObserver<V> {
21    pub fn new() -> Self {
22        Self { value: Rc::new(RefCell::new(None)), expected: None }
23    }
24
25    pub fn expect_value(expected: V) -> Self {
26        let mut o = TestObserver::new();
27        o.expected = Some(expected);
28        o
29    }
30
31    pub fn expect_no_value() -> Self {
32        TestObserver::new()
33    }
34
35    pub fn observe(v: &V, o: Self) -> bool {
36        let mut value = o.value.borrow_mut();
37        if value.is_some() {
38            panic!("This observer has an observed a value that was not taken");
39        }
40        match &o.expected {
41            Some(expected) => assert_eq!(expected, v),
42            None => panic!("This observer expected no observations to occur"),
43        }
44        *value = Some(v.clone());
45        true
46    }
47
48    // Observation happens but function returns false, arbitrarily indicating that the value was
49    // not completely consumed.
50    pub fn observe_incomplete(v: &V, o: Self) -> bool {
51        let mut value = o.value.borrow_mut();
52        if value.is_some() {
53            panic!("This observer has an observed a value that was not taken");
54        }
55        match &o.expected {
56            Some(expected) => assert_eq!(expected, v),
57            None => panic!("This observer expected no observations to occur"),
58        }
59        *value = Some(v.clone());
60        false
61    }
62
63    pub fn has_value(&self) -> bool {
64        self.value.borrow().is_some()
65    }
66}
67
68impl<V: Debug + PartialEq> Drop for TestObserver<V> {
69    fn drop(&mut self) {
70        if !std::thread::panicking() {
71            assert_eq!(
72                *self.value.borrow(),
73                self.expected,
74                "Observer dropped without expected state being met"
75            );
76        }
77    }
78}
79
80#[test]
81fn test_observer_take_value() {
82    assert_eq!(true, TestObserver::observe(&1, TestObserver::expect_value(1)));
83}
84
85#[test]
86#[should_panic]
87fn test_observer_take_cannot_double_observe() {
88    let observer: TestObserver<i32> = TestObserver::new();
89    let _ = TestObserver::observe(&1, observer.clone());
90    let _ = TestObserver::observe(&2, observer.clone());
91}