1
// Copyright (C) Moondance Labs Ltd.
2
// This file is part of Tanssi.
3

            
4
// Tanssi is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Tanssi is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Tanssi.  If not, see <http://www.gnu.org/licenses/>
16

            
17
use {
18
    crate::{
19
        assignment::{Assignment, ChainNumCollators},
20
        tests::Test,
21
    },
22
    sp_std::collections::{btree_map::BTreeMap, btree_set::BTreeSet},
23
};
24

            
25
#[test]
26
1
fn invulnerable_priority_0_collators() {
27
1
    let collators = vec![];
28
1
    let orchestrator_chain = ChainNumCollators {
29
1
        para_id: 1000.into(),
30
1
        min_collators: 2,
31
1
        max_collators: 5,
32
1
    };
33
1
    let mut old_assigned = BTreeMap::new();
34
1

            
35
1
    let num_invulnerables = Assignment::<Test>::prioritize_invulnerables(
36
1
        &collators,
37
1
        orchestrator_chain,
38
1
        &mut old_assigned,
39
1
    );
40
1

            
41
1
    assert_eq!(num_invulnerables, 0);
42
1
}
43

            
44
#[test]
45
1
fn invulnerable_priority_0_invulnerables() {
46
1
    let collators = vec![1, 2, 3, 4, 5];
47
1
    let orchestrator_chain = ChainNumCollators {
48
1
        para_id: 1000.into(),
49
1
        min_collators: 2,
50
1
        max_collators: 5,
51
1
    };
52
1
    let mut old_assigned = BTreeMap::from_iter(vec![(1000.into(), vec![1, 2])]);
53
1

            
54
1
    let num_invulnerables = Assignment::<Test>::prioritize_invulnerables(
55
1
        &collators,
56
1
        orchestrator_chain,
57
1
        &mut old_assigned,
58
1
    );
59
1

            
60
1
    assert_eq!(num_invulnerables, 0);
61
1
}
62

            
63
#[test]
64
1
fn invulnerable_priority_1_invulnerable_orchestrator() {
65
1
    let collators = vec![1, 2, 3, 4, 5, 101];
66
1
    let orchestrator_chain = ChainNumCollators {
67
1
        para_id: 1000.into(),
68
1
        min_collators: 2,
69
1
        max_collators: 5,
70
1
    };
71
1
    let mut old_assigned = BTreeMap::from_iter(vec![(1000.into(), vec![101])]);
72
1

            
73
1
    let num_invulnerables = Assignment::<Test>::prioritize_invulnerables(
74
1
        &collators,
75
1
        orchestrator_chain,
76
1
        &mut old_assigned,
77
1
    );
78
1

            
79
1
    assert_eq!(num_invulnerables, 1);
80
1
}
81

            
82
#[test]
83
1
fn invulnerable_priority_1_invulnerable_not_assigned() {
84
1
    let collators = vec![1, 2, 3, 4, 5, 101];
85
1
    let orchestrator_chain = ChainNumCollators {
86
1
        para_id: 1000.into(),
87
1
        min_collators: 2,
88
1
        max_collators: 5,
89
1
    };
90
1
    let mut old_assigned = BTreeMap::new();
91
1

            
92
1
    let num_invulnerables = Assignment::<Test>::prioritize_invulnerables(
93
1
        &collators,
94
1
        orchestrator_chain,
95
1
        &mut old_assigned,
96
1
    );
97
1

            
98
1
    assert_eq!(num_invulnerables, 1);
99
1
}
100

            
101
#[test]
102
1
fn invulnerable_priority_1_invulnerable_assigned_to_another_chain() {
103
1
    let collators = vec![1, 2, 3, 4, 5, 101];
104
1
    let orchestrator_chain = ChainNumCollators {
105
1
        para_id: 1000.into(),
106
1
        min_collators: 2,
107
1
        max_collators: 5,
108
1
    };
109
1
    let mut old_assigned =
110
1
        BTreeMap::from_iter(vec![(1000.into(), vec![]), (2000.into(), vec![101])]);
111
1

            
112
1
    let num_invulnerables = Assignment::<Test>::prioritize_invulnerables(
113
1
        &collators,
114
1
        orchestrator_chain,
115
1
        &mut old_assigned,
116
1
    );
117
1

            
118
1
    assert_eq!(num_invulnerables, 1);
119
1
}
120

            
121
#[test]
122
1
fn bug_same_invulnerable_selected_twice() {
123
1
    let collators = vec![100];
124
1
    let orchestrator_chain = ChainNumCollators {
125
1
        para_id: 1000.into(),
126
1
        min_collators: 2,
127
1
        max_collators: 5,
128
1
    };
129
1
    let mut old_assigned = BTreeMap::from_iter(vec![(1000.into(), vec![100])]);
130
1

            
131
1
    let num_invulnerables = Assignment::<Test>::prioritize_invulnerables(
132
1
        &collators,
133
1
        orchestrator_chain,
134
1
        &mut old_assigned,
135
1
    );
136
1

            
137
1
    assert_eq!(num_invulnerables, 1);
138
1
}
139

            
140
#[test]
141
1
fn bug_not_using_assigned_invulnerables() {
142
1
    // There are 3 invulnerables, 1 assigned to orchestrator and 2 assigned to a container chain.
143
1
    // After `prioritize_invulnerables` the first one from the container should move to orchestrator
144
1
    let collators = vec![1, 2, 3, 4, 5, 102, 103, 104];
145
1

            
146
1
    let container_chains = [
147
1
        ChainNumCollators {
148
1
            para_id: 1000.into(),
149
1
            min_collators: 2,
150
1
            max_collators: 5,
151
1
        },
152
1
        ChainNumCollators {
153
1
            para_id: 2000.into(),
154
1
            min_collators: 2,
155
1
            max_collators: 2,
156
1
        },
157
1
        ChainNumCollators {
158
1
            para_id: 2001.into(),
159
1
            min_collators: 2,
160
1
            max_collators: 2,
161
1
        },
162
1
    ];
163
1
    let orchestrator_chain = container_chains[0];
164
1

            
165
1
    let mut old_assigned = BTreeMap::from_iter(vec![
166
1
        (1000.into(), vec![101, 104, 1, 2, 3]),
167
1
        (2000.into(), vec![4, 5]),
168
1
        (2001.into(), vec![102, 103]),
169
1
    ]);
170
1

            
171
1
    let chains_with_collators_set =
172
3
        BTreeSet::from_iter(container_chains.iter().map(|cc| cc.para_id));
173
1
    let collators_set = BTreeSet::from_iter(collators.iter().cloned());
174
1
    Assignment::<Test>::retain_valid_old_assigned(
175
1
        &mut old_assigned,
176
1
        &chains_with_collators_set,
177
1
        &collators_set,
178
1
    );
179
1
    let num_invulnerables = Assignment::<Test>::prioritize_invulnerables(
180
1
        &collators,
181
1
        orchestrator_chain,
182
1
        &mut old_assigned,
183
1
    );
184
1

            
185
1
    assert_eq!(num_invulnerables, 2);
186
1
}