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.
45use std::cell::RefCell;
6use std::fmt::Debug;
7use std::rc::Rc;
89/// 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}
1920impl<V: Debug + Clone + Send + PartialEq> TestObserver<V> {
21pub fn new() -> Self {
22Self { value: Rc::new(RefCell::new(None)), expected: None }
23 }
2425pub fn expect_value(expected: V) -> Self {
26let mut o = TestObserver::new();
27 o.expected = Some(expected);
28 o
29 }
3031pub fn expect_no_value() -> Self {
32 TestObserver::new()
33 }
3435pub fn observe(v: &V, o: Self) -> bool {
36let mut value = o.value.borrow_mut();
37if value.is_some() {
38panic!("This observer has an observed a value that was not taken");
39 }
40match &o.expected {
41Some(expected) => assert_eq!(expected, v),
42None => panic!("This observer expected no observations to occur"),
43 }
44*value = Some(v.clone());
45true
46}
4748// Observation happens but function returns false, arbitrarily indicating that the value was
49 // not completely consumed.
50pub fn observe_incomplete(v: &V, o: Self) -> bool {
51let mut value = o.value.borrow_mut();
52if value.is_some() {
53panic!("This observer has an observed a value that was not taken");
54 }
55match &o.expected {
56Some(expected) => assert_eq!(expected, v),
57None => panic!("This observer expected no observations to occur"),
58 }
59*value = Some(v.clone());
60false
61}
6263pub fn has_value(&self) -> bool {
64self.value.borrow().is_some()
65 }
66}
6768impl<V: Debug + PartialEq> Drop for TestObserver<V> {
69fn drop(&mut self) {
70if !std::thread::panicking() {
71assert_eq!(
72*self.value.borrow(),
73self.expected,
74"Observer dropped without expected state being met"
75);
76 }
77 }
78}
7980#[test]
81fn test_observer_take_value() {
82assert_eq!(true, TestObserver::observe(&1, TestObserver::expect_value(1)));
83}
8485#[test]
86#[should_panic]
87fn test_observer_take_cannot_double_observe() {
88let observer: TestObserver<i32> = TestObserver::new();
89let _ = TestObserver::observe(&1, observer.clone());
90let _ = TestObserver::observe(&2, observer.clone());
91}