Merge branch 'master' into 9998-unsigned_manifest
[arvados.git] / services / datamanager / summary / pull_list_test.go
1 package summary
2
3 import (
4         "encoding/json"
5         "git.curoverse.com/arvados.git/sdk/go/blockdigest"
6         . "gopkg.in/check.v1"
7         "sort"
8         "testing"
9 )
10
11 // Gocheck boilerplate
12 func TestPullLists(t *testing.T) {
13         TestingT(t)
14 }
15
16 type PullSuite struct{}
17
18 var _ = Suite(&PullSuite{})
19
20 // Helper method to declare string sets more succinctly
21 // Could be placed somewhere more general.
22 func stringSet(slice ...string) (m map[string]struct{}) {
23         m = map[string]struct{}{}
24         for _, s := range slice {
25                 m[s] = struct{}{}
26         }
27         return
28 }
29
30 func (s *PullSuite) TestPullListPrintsJSONCorrectly(c *C) {
31         pl := PullList{PullRequest{
32                 Locator: Locator(blockdigest.MakeTestDigestSpecifySize(0xBadBeef, 56789)),
33                 Servers: []string{"keep0.qr1hi.arvadosapi.com:25107",
34                         "keep1.qr1hi.arvadosapi.com:25108"}}}
35
36         b, err := json.Marshal(pl)
37         c.Assert(err, IsNil)
38         expectedOutput := `[{"locator":"0000000000000000000000000badbeef+56789",` +
39                 `"servers":["keep0.qr1hi.arvadosapi.com:25107",` +
40                 `"keep1.qr1hi.arvadosapi.com:25108"]}]`
41         c.Check(string(b), Equals, expectedOutput)
42 }
43
44 func (s *PullSuite) TestCreatePullServers(c *C) {
45         var cs CanonicalString
46         c.Check(
47                 CreatePullServers(cs,
48                         stringSet(),
49                         stringSet(),
50                         []string{},
51                         5),
52                 DeepEquals,
53                 PullServers{To: []string{}, From: []string{}})
54
55         c.Check(
56                 CreatePullServers(cs,
57                         stringSet("https://keep0:25107", "https://keep1:25108"),
58                         stringSet(),
59                         []string{},
60                         5),
61                 DeepEquals,
62                 PullServers{To: []string{}, From: []string{}})
63
64         c.Check(
65                 CreatePullServers(cs,
66                         stringSet("https://keep0:25107", "https://keep1:25108"),
67                         stringSet("https://keep0:25107"),
68                         []string{"https://keep0:25107"},
69                         5),
70                 DeepEquals,
71                 PullServers{To: []string{}, From: []string{"https://keep0:25107"}})
72
73         c.Check(
74                 CreatePullServers(cs,
75                         stringSet("https://keep0:25107", "https://keep1:25108"),
76                         stringSet("https://keep3:25110", "https://keep2:25109", "https://keep1:25108", "https://keep0:25107"),
77                         []string{"https://keep3:25110", "https://keep2:25109", "https://keep1:25108", "https://keep0:25107"},
78                         5),
79                 DeepEquals,
80                 PullServers{To: []string{"https://keep3:25110", "https://keep2:25109"},
81                         From: []string{"https://keep1:25108", "https://keep0:25107"}})
82
83         c.Check(
84                 CreatePullServers(cs,
85                         stringSet("https://keep0:25107", "https://keep1:25108"),
86                         stringSet("https://keep3:25110", "https://keep1:25108", "https://keep0:25107"),
87                         []string{"https://keep3:25110", "https://keep2:25109", "https://keep1:25108", "https://keep0:25107"},
88                         5),
89                 DeepEquals,
90                 PullServers{To: []string{"https://keep3:25110"},
91                         From: []string{"https://keep1:25108", "https://keep0:25107"}})
92
93         c.Check(
94                 CreatePullServers(cs,
95                         stringSet("https://keep0:25107", "https://keep1:25108"),
96                         stringSet("https://keep3:25110", "https://keep2:25109", "https://keep1:25108", "https://keep0:25107"),
97                         []string{"https://keep3:25110", "https://keep2:25109", "https://keep1:25108", "https://keep0:25107"},
98                         1),
99                 DeepEquals,
100                 PullServers{To: []string{"https://keep3:25110"},
101                         From: []string{"https://keep1:25108", "https://keep0:25107"}})
102
103         c.Check(
104                 CreatePullServers(cs,
105                         stringSet("https://keep0:25107", "https://keep1:25108"),
106                         stringSet("https://keep3:25110", "https://keep2:25109",
107                                 "https://keep1:25108", "https://keep0:25107"),
108                         []string{"https://keep3:25110", "https://keep2:25109",
109                                 "https://keep1:25108", "https://keep0:25107"},
110                         1),
111                 DeepEquals,
112                 PullServers{To: []string{"https://keep3:25110"},
113                         From: []string{"https://keep1:25108", "https://keep0:25107"}})
114
115         c.Check(
116                 CreatePullServers(cs,
117                         stringSet("https://keep0:25107", "https://keep1:25108"),
118                         stringSet("https://keep3:25110", "https://keep2:25109", "https://keep1:25108", "https://keep0:25107"),
119                         []string{"https://keep3:25110", "https://keep2:25109", "https://keep1:25108", "https://keep0:25107"},
120                         0),
121                 DeepEquals,
122                 PullServers{To: []string{},
123                         From: []string{"https://keep1:25108", "https://keep0:25107"}})
124 }
125
126 // Checks whether two pull list maps are equal. Since pull lists are
127 // ordered arbitrarily, we need to sort them by digest before
128 // comparing them for deep equality.
129 type pullListMapEqualsChecker struct {
130         *CheckerInfo
131 }
132
133 func (c *pullListMapEqualsChecker) Check(params []interface{}, names []string) (result bool, error string) {
134         obtained, ok := params[0].(map[string]PullList)
135         if !ok {
136                 return false, "First parameter is not a PullList map"
137         }
138         expected, ok := params[1].(map[string]PullList)
139         if !ok {
140                 return false, "Second parameter is not a PullList map"
141         }
142
143         for _, v := range obtained {
144                 sort.Sort(PullListByLocator(v))
145         }
146         for _, v := range expected {
147                 sort.Sort(PullListByLocator(v))
148         }
149
150         return DeepEquals.Check(params, names)
151 }
152
153 var PullListMapEquals Checker = &pullListMapEqualsChecker{&CheckerInfo{
154         Name:   "PullListMapEquals",
155         Params: []string{"obtained", "expected"},
156 }}
157
158 func (s *PullSuite) TestBuildPullLists(c *C) {
159         c.Check(
160                 BuildPullLists(map[Locator]PullServers{}),
161                 PullListMapEquals,
162                 map[string]PullList{})
163
164         locator1 := Locator{Digest: blockdigest.MakeTestBlockDigest(0xBadBeef)}
165         c.Check(
166                 BuildPullLists(map[Locator]PullServers{
167                         locator1: {To: []string{}, From: []string{}}}),
168                 PullListMapEquals,
169                 map[string]PullList{})
170
171         c.Check(
172                 BuildPullLists(map[Locator]PullServers{
173                         locator1: {To: []string{}, From: []string{"f1", "f2"}}}),
174                 PullListMapEquals,
175                 map[string]PullList{})
176
177         c.Check(
178                 BuildPullLists(map[Locator]PullServers{
179                         locator1: {To: []string{"t1"}, From: []string{"f1", "f2"}}}),
180                 PullListMapEquals,
181                 map[string]PullList{
182                         "t1": {PullRequest{locator1, []string{"f1", "f2"}}}})
183
184         c.Check(
185                 BuildPullLists(map[Locator]PullServers{
186                         locator1: {To: []string{"t1"}, From: []string{}}}),
187                 PullListMapEquals,
188                 map[string]PullList{"t1": {
189                         PullRequest{locator1, []string{}}}})
190
191         c.Check(
192                 BuildPullLists(map[Locator]PullServers{
193                         locator1: {
194                                 To:   []string{"t1", "t2"},
195                                 From: []string{"f1", "f2"},
196                         }}),
197                 PullListMapEquals,
198                 map[string]PullList{
199                         "t1": {PullRequest{locator1, []string{"f1", "f2"}}},
200                         "t2": {PullRequest{locator1, []string{"f1", "f2"}}},
201                 })
202
203         locator2 := Locator{Digest: blockdigest.MakeTestBlockDigest(0xCabbed)}
204         c.Check(
205                 BuildPullLists(map[Locator]PullServers{
206                         locator1: {To: []string{"t1"}, From: []string{"f1", "f2"}},
207                         locator2: {To: []string{"t2"}, From: []string{"f3", "f4"}}}),
208                 PullListMapEquals,
209                 map[string]PullList{
210                         "t1": {PullRequest{locator1, []string{"f1", "f2"}}},
211                         "t2": {PullRequest{locator2, []string{"f3", "f4"}}},
212                 })
213
214         c.Check(
215                 BuildPullLists(map[Locator]PullServers{
216                         locator1: {
217                                 To:   []string{"t1"},
218                                 From: []string{"f1", "f2"}},
219                         locator2: {
220                                 To:   []string{"t2", "t1"},
221                                 From: []string{"f3", "f4"}},
222                 }),
223                 PullListMapEquals,
224                 map[string]PullList{
225                         "t1": {
226                                 PullRequest{locator1, []string{"f1", "f2"}},
227                                 PullRequest{locator2, []string{"f3", "f4"}},
228                         },
229                         "t2": {
230                                 PullRequest{locator2, []string{"f3", "f4"}},
231                         },
232                 })
233
234         locator3 := Locator{Digest: blockdigest.MakeTestBlockDigest(0xDeadBeef)}
235         locator4 := Locator{Digest: blockdigest.MakeTestBlockDigest(0xFedBeef)}
236         c.Check(
237                 BuildPullLists(map[Locator]PullServers{
238                         locator1: {
239                                 To:   []string{"t1"},
240                                 From: []string{"f1", "f2"}},
241                         locator2: {
242                                 To:   []string{"t2", "t1"},
243                                 From: []string{"f3", "f4"}},
244                         locator3: {
245                                 To:   []string{"t3", "t2", "t1"},
246                                 From: []string{"f4", "f5"}},
247                         locator4: {
248                                 To:   []string{"t4", "t3", "t2", "t1"},
249                                 From: []string{"f1", "f5"}},
250                 }),
251                 PullListMapEquals,
252                 map[string]PullList{
253                         "t1": {
254                                 PullRequest{locator1, []string{"f1", "f2"}},
255                                 PullRequest{locator2, []string{"f3", "f4"}},
256                                 PullRequest{locator3, []string{"f4", "f5"}},
257                                 PullRequest{locator4, []string{"f1", "f5"}},
258                         },
259                         "t2": {
260                                 PullRequest{locator2, []string{"f3", "f4"}},
261                                 PullRequest{locator3, []string{"f4", "f5"}},
262                                 PullRequest{locator4, []string{"f1", "f5"}},
263                         },
264                         "t3": {
265                                 PullRequest{locator3, []string{"f4", "f5"}},
266                                 PullRequest{locator4, []string{"f1", "f5"}},
267                         },
268                         "t4": {
269                                 PullRequest{locator4, []string{"f1", "f5"}},
270                         },
271                 })
272 }