1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use common::protocol::recoverable::MockRecoverableVisitor;
use treaty::{
    any::OwnedStatic,
    effect::blocking::Blocking,
    protocol::{
        visitor::{Recoverable, ValueProto, VisitResult},
        DynVisitor,
    },
    Flow, Status,
};

use crate::common::{
    builder::MockBuilder,
    protocol::recoverable::{MockRecoverableScopeVisitor, RecoverableScopeFactory},
};

mod common;

/// Tests that the recoverable protocol allows multiple walks by the visitor.
#[test]
fn recoverable_can_be_visited() {
    let mut mock = MockRecoverableVisitor::<Blocking>::new();

    // Expect a visit using the rescoverable protocol.
    mock.expect_visit().once().return_const(
        (|(), scope| {
            let mut visitor = MockBuilder::<(), (), ()>::new();

            // Expect that the visitor gets used.
            visitor.expect_traits().times(2).return_const(None);

            // Attempt to walk once.
            assert_eq!(scope.new_walk(DynVisitor(&mut visitor)).value(), Status::Ok);

            // Attempt to walk twice.
            assert_eq!(scope.new_walk(DynVisitor(&mut visitor)).value(), Status::Ok);

            // We are done.
            VisitResult::Control(Flow::Done)
        }) as RecoverableScopeFactory<Blocking>,
    );

    let visitor: &mut dyn Recoverable<Blocking> = &mut mock;

    let mut scope = MockRecoverableScopeVisitor::new();

    // Expect two walks of the recoverable walker.
    scope.expect_new_walk().times(2).returning(|visitor| {
        // Attempt to use the visitor.
        assert!(visitor
            .upcast::<ValueProto<OwnedStatic<i32>, Blocking>>()
            .is_none());

        Status::Ok
    });

    // Visit using the recoverable protocol.
    assert!(matches!(
        visitor.visit(&mut scope).value(),
        VisitResult::Control(Flow::Done)
    ));
}