File size: 4,585 Bytes
84d2a97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use super::local_shard::clock_map::ClockMap;
use super::replica_set::clock_set::ClockSet;
use super::shard::PeerId;
use crate::operations::ClockTag;

#[test]
fn clock_set_clock_map_workflow() {
    let mut helper = Helper::new();

    // `ClockSet` and `ClockMap` "stick" to tick `0`, until `ClockSet` is advanced at least once
    helper.tick_clock().assert(0);
    helper.advance_clock_map(false).assert(0, 0, false);
    helper.advance_clock_map(false).assert(0, 0, false);
    helper.advance_clock(false).assert(0, 0, false);

    // `ClockSet` and `ClockMap` tick sequentially and in sync after that
    for tick in 1..=10 {
        helper.advance_clock(false).assert(tick, tick, true);
    }

    // `ClockMap` advances to newer ticks
    for tick in 11..=50 {
        if tick % 10 != 0 {
            // Tick `ClockSet` few times, without advancing `ClockMap`...
            helper.tick_clock().assert(tick);
        } else {
            // ...then advance both `ClockMap` and `ClockSet`
            helper.advance_clock(false).assert(tick, tick, true);
        }
    }

    // `ClockMap` rejects tick `0` and advances `ClockSet`
    helper.clock_set = Default::default();
    helper.advance_clock(false).assert(0, 50, false);
    helper.tick_clock().assert(51);

    // `ClockMap` rejects older (or current) ticks...
    helper.clock_set = Default::default();
    helper.clock_set.get_clock().advance_to(0);

    for tick in 1..=50 {
        helper.advance_clock_map(false).assert(tick, 50, false);
    }

    // ...and advances `ClockSet`
    helper.clock_set = Default::default();
    helper.clock_set.get_clock().advance_to(42);

    helper.advance_clock(false).assert(43, 50, false);
    helper.tick_clock().assert(51);

    // `ClockMap` advances to newer ticks with `force = true`
    helper.clock_set = Default::default();
    helper.advance_clock(false).assert(0, 50, false);

    for tick in 51..=100 {
        helper.advance_clock(true).assert(tick, tick, true);
    }

    // `ClockMap` accepts older (or current) ticks with `force = true`...
    helper.clock_set = Default::default();

    for tick in 0..=100 {
        helper.advance_clock(true).assert(tick, tick, true);
    }

    // ...but it does not affect current tick of `ClockMap` in any way
    helper.clock_set = Default::default();
    helper.clock_set.get_clock().advance_to(42);

    helper.advance_clock(false).assert(43, 100, false);
    helper.tick_clock().assert(101);
}

#[derive(Clone, Debug)]
struct Helper {
    clock_set: ClockSet,
    clock_map: ClockMap,
}

const PEER_ID: PeerId = 1337;

impl Helper {
    pub fn new() -> Self {
        Self {
            clock_set: ClockSet::default(),
            clock_map: ClockMap::default(),
        }
    }

    pub fn tick_clock(&mut self) -> TickClockStatus {
        let mut clock = self.clock_set.get_clock();
        let clock_tag = ClockTag::new(PEER_ID, clock.id() as _, clock.tick_once());
        TickClockStatus { clock_tag }
    }

    pub fn advance_clock_map(&mut self, force: bool) -> AdvanceStatus {
        self.advance(force, false)
    }

    pub fn advance_clock(&mut self, force: bool) -> AdvanceStatus {
        self.advance(force, true)
    }

    fn advance(&mut self, force: bool, advance_clock: bool) -> AdvanceStatus {
        let mut clock = self.clock_set.get_clock();

        let clock_tag = ClockTag::new(PEER_ID, clock.id() as _, clock.tick_once()).force(force);

        let mut clock_map_tag = clock_tag;
        let accepted = self
            .clock_map
            .advance_clock_and_correct_tag(&mut clock_map_tag);

        assert_eq!(clock_tag.peer_id, clock_map_tag.peer_id);
        assert_eq!(clock_tag.clock_id, clock_map_tag.clock_id);

        if advance_clock {
            clock.advance_to(clock_map_tag.clock_tick);
        }

        AdvanceStatus {
            clock_tag,
            clock_map_tag,
            accepted,
        }
    }
}

#[derive(Copy, Clone, Debug)]
struct TickClockStatus {
    clock_tag: ClockTag,
}

impl TickClockStatus {
    pub fn assert(&self, expected_tick: u64) {
        assert_eq!(self.clock_tag.clock_tick, expected_tick)
    }
}

#[derive(Copy, Clone, Debug)]
struct AdvanceStatus {
    clock_tag: ClockTag,
    clock_map_tag: ClockTag,
    accepted: bool,
}

impl AdvanceStatus {
    pub fn assert(&self, expected_tick: u64, expected_cm_tick: u64, expected_status: bool) {
        assert_eq!(expected_tick, self.clock_tag.clock_tick);
        assert_eq!(expected_cm_tick, self.clock_map_tag.clock_tick);
        assert_eq!(expected_status, self.accepted);
    }
}