1package deb
2
3import (
4	"errors"
5
6	"github.com/aptly-dev/aptly/database"
7
8	. "gopkg.in/check.v1"
9)
10
11type PackageRefListSuite struct {
12	// Simple list with "real" packages from stanzas
13	list                   *PackageList
14	p1, p2, p3, p4, p5, p6 *Package
15}
16
17var _ = Suite(&PackageRefListSuite{})
18
19func toStrSlice(reflist *PackageRefList) (result []string) {
20	result = make([]string, reflist.Len())
21	for i, r := range reflist.Refs {
22		result[i] = string(r)
23	}
24	return
25}
26
27func (s *PackageRefListSuite) SetUpTest(c *C) {
28	s.list = NewPackageList()
29
30	s.p1 = NewPackageFromControlFile(packageStanza.Copy())
31	s.p2 = NewPackageFromControlFile(packageStanza.Copy())
32	stanza := packageStanza.Copy()
33	stanza["Package"] = "mars-invaders"
34	s.p3 = NewPackageFromControlFile(stanza)
35	stanza = packageStanza.Copy()
36	stanza["Source"] = "unknown-planet"
37	s.p4 = NewPackageFromControlFile(stanza)
38	stanza = packageStanza.Copy()
39	stanza["Package"] = "lonely-strangers"
40	s.p5 = NewPackageFromControlFile(stanza)
41	stanza = packageStanza.Copy()
42	stanza["Version"] = "99.1"
43	s.p6 = NewPackageFromControlFile(stanza)
44}
45
46func (s *PackageRefListSuite) TestNewPackageListFromRefList(c *C) {
47	db, _ := database.NewOpenDB(c.MkDir())
48	coll := NewPackageCollection(db)
49	coll.Update(s.p1)
50	coll.Update(s.p3)
51
52	s.list.Add(s.p1)
53	s.list.Add(s.p3)
54	s.list.Add(s.p5)
55	s.list.Add(s.p6)
56
57	reflist := NewPackageRefListFromPackageList(s.list)
58
59	_, err := NewPackageListFromRefList(reflist, coll, nil)
60	c.Assert(err, ErrorMatches, "unable to load package with key.*")
61
62	coll.Update(s.p5)
63	coll.Update(s.p6)
64
65	list, err := NewPackageListFromRefList(reflist, coll, nil)
66	c.Assert(err, IsNil)
67	c.Check(list.Len(), Equals, 4)
68	c.Check(list.Add(s.p4), ErrorMatches, "conflict in package.*")
69
70	list, err = NewPackageListFromRefList(nil, coll, nil)
71	c.Assert(err, IsNil)
72	c.Check(list.Len(), Equals, 0)
73}
74
75func (s *PackageRefListSuite) TestNewPackageRefList(c *C) {
76	s.list.Add(s.p1)
77	s.list.Add(s.p3)
78	s.list.Add(s.p5)
79	s.list.Add(s.p6)
80
81	reflist := NewPackageRefListFromPackageList(s.list)
82	c.Assert(reflist.Len(), Equals, 4)
83	c.Check(reflist.Refs[0], DeepEquals, []byte(s.p1.Key("")))
84	c.Check(reflist.Refs[1], DeepEquals, []byte(s.p6.Key("")))
85	c.Check(reflist.Refs[2], DeepEquals, []byte(s.p5.Key("")))
86	c.Check(reflist.Refs[3], DeepEquals, []byte(s.p3.Key("")))
87
88	reflist = NewPackageRefList()
89	c.Check(reflist.Len(), Equals, 0)
90}
91
92func (s *PackageRefListSuite) TestPackageRefListEncodeDecode(c *C) {
93	s.list.Add(s.p1)
94	s.list.Add(s.p3)
95	s.list.Add(s.p5)
96	s.list.Add(s.p6)
97
98	reflist := NewPackageRefListFromPackageList(s.list)
99
100	reflist2 := &PackageRefList{}
101	err := reflist2.Decode(reflist.Encode())
102	c.Assert(err, IsNil)
103	c.Check(reflist2.Len(), Equals, reflist.Len())
104	c.Check(reflist2.Refs, DeepEquals, reflist.Refs)
105}
106
107func (s *PackageRefListSuite) TestPackageRefListForeach(c *C) {
108	s.list.Add(s.p1)
109	s.list.Add(s.p3)
110	s.list.Add(s.p5)
111	s.list.Add(s.p6)
112
113	reflist := NewPackageRefListFromPackageList(s.list)
114
115	Len := 0
116	err := reflist.ForEach(func([]byte) error {
117		Len++
118		return nil
119	})
120
121	c.Check(Len, Equals, 4)
122	c.Check(err, IsNil)
123
124	e := errors.New("b")
125
126	err = reflist.ForEach(func([]byte) error {
127		return e
128	})
129
130	c.Check(err, Equals, e)
131}
132
133func (s *PackageRefListSuite) TestHas(c *C) {
134	s.list.Add(s.p1)
135	s.list.Add(s.p3)
136	s.list.Add(s.p5)
137	reflist := NewPackageRefListFromPackageList(s.list)
138
139	c.Check(reflist.Has(s.p1), Equals, true)
140	c.Check(reflist.Has(s.p3), Equals, true)
141	c.Check(reflist.Has(s.p5), Equals, true)
142	c.Check(reflist.Has(s.p2), Equals, true)
143	c.Check(reflist.Has(s.p6), Equals, false)
144}
145
146func (s *PackageRefListSuite) TestSubstract(c *C) {
147	r1 := []byte("r1")
148	r2 := []byte("r2")
149	r3 := []byte("r3")
150	r4 := []byte("r4")
151	r5 := []byte("r5")
152
153	empty := &PackageRefList{Refs: [][]byte{}}
154	l1 := &PackageRefList{Refs: [][]byte{r1, r2, r3, r4}}
155	l2 := &PackageRefList{Refs: [][]byte{r1, r3}}
156	l3 := &PackageRefList{Refs: [][]byte{r2, r4}}
157	l4 := &PackageRefList{Refs: [][]byte{r4, r5}}
158	l5 := &PackageRefList{Refs: [][]byte{r1, r2, r3}}
159
160	c.Check(l1.Subtract(empty), DeepEquals, l1)
161	c.Check(l1.Subtract(l2), DeepEquals, l3)
162	c.Check(l1.Subtract(l3), DeepEquals, l2)
163	c.Check(l1.Subtract(l4), DeepEquals, l5)
164	c.Check(empty.Subtract(l1), DeepEquals, empty)
165	c.Check(l2.Subtract(l3), DeepEquals, l2)
166}
167
168func (s *PackageRefListSuite) TestDiff(c *C) {
169	db, _ := database.NewOpenDB(c.MkDir())
170	coll := NewPackageCollection(db)
171
172	packages := []*Package{
173		{Name: "lib", Version: "1.0", Architecture: "i386"},      //0
174		{Name: "dpkg", Version: "1.7", Architecture: "i386"},     //1
175		{Name: "data", Version: "1.1~bp1", Architecture: "all"},  //2
176		{Name: "app", Version: "1.1~bp1", Architecture: "i386"},  //3
177		{Name: "app", Version: "1.1~bp2", Architecture: "i386"},  //4
178		{Name: "app", Version: "1.1~bp2", Architecture: "amd64"}, //5
179		{Name: "xyz", Version: "3.0", Architecture: "sparc"},     //6
180	}
181
182	for _, p := range packages {
183		coll.Update(p)
184	}
185
186	listA := NewPackageList()
187	listA.Add(packages[0])
188	listA.Add(packages[1])
189	listA.Add(packages[2])
190	listA.Add(packages[3])
191	listA.Add(packages[6])
192
193	listB := NewPackageList()
194	listB.Add(packages[0])
195	listB.Add(packages[2])
196	listB.Add(packages[4])
197	listB.Add(packages[5])
198
199	reflistA := NewPackageRefListFromPackageList(listA)
200	reflistB := NewPackageRefListFromPackageList(listB)
201
202	diffAA, err := reflistA.Diff(reflistA, coll)
203	c.Check(err, IsNil)
204	c.Check(diffAA, HasLen, 0)
205
206	diffAB, err := reflistA.Diff(reflistB, coll)
207	c.Check(err, IsNil)
208	c.Check(diffAB, HasLen, 4)
209
210	c.Check(diffAB[0].Left, IsNil)
211	c.Check(diffAB[0].Right.String(), Equals, "app_1.1~bp2_amd64")
212
213	c.Check(diffAB[1].Left.String(), Equals, "app_1.1~bp1_i386")
214	c.Check(diffAB[1].Right.String(), Equals, "app_1.1~bp2_i386")
215
216	c.Check(diffAB[2].Left.String(), Equals, "dpkg_1.7_i386")
217	c.Check(diffAB[2].Right, IsNil)
218
219	c.Check(diffAB[3].Left.String(), Equals, "xyz_3.0_sparc")
220	c.Check(diffAB[3].Right, IsNil)
221
222	diffBA, err := reflistB.Diff(reflistA, coll)
223	c.Check(err, IsNil)
224	c.Check(diffBA, HasLen, 4)
225
226	c.Check(diffBA[0].Right, IsNil)
227	c.Check(diffBA[0].Left.String(), Equals, "app_1.1~bp2_amd64")
228
229	c.Check(diffBA[1].Right.String(), Equals, "app_1.1~bp1_i386")
230	c.Check(diffBA[1].Left.String(), Equals, "app_1.1~bp2_i386")
231
232	c.Check(diffBA[2].Right.String(), Equals, "dpkg_1.7_i386")
233	c.Check(diffBA[2].Left, IsNil)
234
235	c.Check(diffBA[3].Right.String(), Equals, "xyz_3.0_sparc")
236	c.Check(diffBA[3].Left, IsNil)
237
238}
239
240func (s *PackageRefListSuite) TestMerge(c *C) {
241	db, _ := database.NewOpenDB(c.MkDir())
242	coll := NewPackageCollection(db)
243
244	packages := []*Package{
245		{Name: "lib", Version: "1.0", Architecture: "i386"},                      //0
246		{Name: "dpkg", Version: "1.7", Architecture: "i386"},                     //1
247		{Name: "data", Version: "1.1~bp1", Architecture: "all"},                  //2
248		{Name: "app", Version: "1.1~bp1", Architecture: "i386"},                  //3
249		{Name: "app", Version: "1.1~bp2", Architecture: "i386"},                  //4
250		{Name: "app", Version: "1.1~bp2", Architecture: "amd64"},                 //5
251		{Name: "dpkg", Version: "1.0", Architecture: "i386"},                     //6
252		{Name: "xyz", Version: "1.0", Architecture: "sparc"},                     //7
253		{Name: "dpkg", Version: "1.0", Architecture: "i386", FilesHash: 0x34445}, //8
254		{Name: "app", Version: "1.1~bp2", Architecture: "i386", FilesHash: 0x44}, //9
255	}
256
257	for _, p := range packages {
258		p.V06Plus = true
259		coll.Update(p)
260	}
261
262	listA := NewPackageList()
263	listA.Add(packages[0])
264	listA.Add(packages[1])
265	listA.Add(packages[2])
266	listA.Add(packages[3])
267	listA.Add(packages[7])
268
269	listB := NewPackageList()
270	listB.Add(packages[0])
271	listB.Add(packages[2])
272	listB.Add(packages[4])
273	listB.Add(packages[5])
274	listB.Add(packages[6])
275
276	listC := NewPackageList()
277	listC.Add(packages[0])
278	listC.Add(packages[8])
279	listC.Add(packages[9])
280
281	reflistA := NewPackageRefListFromPackageList(listA)
282	reflistB := NewPackageRefListFromPackageList(listB)
283	reflistC := NewPackageRefListFromPackageList(listC)
284
285	mergeAB := reflistA.Merge(reflistB, true, false)
286	mergeBA := reflistB.Merge(reflistA, true, false)
287	mergeAC := reflistA.Merge(reflistC, true, false)
288	mergeBC := reflistB.Merge(reflistC, true, false)
289	mergeCB := reflistC.Merge(reflistB, true, false)
290
291	c.Check(toStrSlice(mergeAB), DeepEquals,
292		[]string{"Pall data 1.1~bp1 00000000", "Pamd64 app 1.1~bp2 00000000", "Pi386 app 1.1~bp2 00000000", "Pi386 dpkg 1.0 00000000", "Pi386 lib 1.0 00000000", "Psparc xyz 1.0 00000000"})
293	c.Check(toStrSlice(mergeBA), DeepEquals,
294		[]string{"Pall data 1.1~bp1 00000000", "Pamd64 app 1.1~bp2 00000000", "Pi386 app 1.1~bp1 00000000", "Pi386 dpkg 1.7 00000000", "Pi386 lib 1.0 00000000", "Psparc xyz 1.0 00000000"})
295	c.Check(toStrSlice(mergeAC), DeepEquals,
296		[]string{"Pall data 1.1~bp1 00000000", "Pi386 app 1.1~bp2 00000044", "Pi386 dpkg 1.0 00034445", "Pi386 lib 1.0 00000000", "Psparc xyz 1.0 00000000"})
297	c.Check(toStrSlice(mergeBC), DeepEquals,
298		[]string{"Pall data 1.1~bp1 00000000", "Pamd64 app 1.1~bp2 00000000", "Pi386 app 1.1~bp2 00000044", "Pi386 dpkg 1.0 00034445", "Pi386 lib 1.0 00000000"})
299	c.Check(toStrSlice(mergeCB), DeepEquals,
300		[]string{"Pall data 1.1~bp1 00000000", "Pamd64 app 1.1~bp2 00000000", "Pi386 app 1.1~bp2 00000000", "Pi386 dpkg 1.0 00000000", "Pi386 lib 1.0 00000000"})
301
302	mergeABall := reflistA.Merge(reflistB, false, false)
303	mergeBAall := reflistB.Merge(reflistA, false, false)
304	mergeACall := reflistA.Merge(reflistC, false, false)
305	mergeBCall := reflistB.Merge(reflistC, false, false)
306	mergeCBall := reflistC.Merge(reflistB, false, false)
307
308	c.Check(mergeABall, DeepEquals, mergeBAall)
309	c.Check(toStrSlice(mergeBAall), DeepEquals,
310		[]string{"Pall data 1.1~bp1 00000000", "Pamd64 app 1.1~bp2 00000000", "Pi386 app 1.1~bp1 00000000", "Pi386 app 1.1~bp2 00000000",
311			"Pi386 dpkg 1.0 00000000", "Pi386 dpkg 1.7 00000000", "Pi386 lib 1.0 00000000", "Psparc xyz 1.0 00000000"})
312
313	c.Check(mergeBCall, Not(DeepEquals), mergeCBall)
314	c.Check(toStrSlice(mergeACall), DeepEquals,
315		[]string{"Pall data 1.1~bp1 00000000", "Pi386 app 1.1~bp1 00000000", "Pi386 app 1.1~bp2 00000044", "Pi386 dpkg 1.0 00034445",
316			"Pi386 dpkg 1.7 00000000", "Pi386 lib 1.0 00000000", "Psparc xyz 1.0 00000000"})
317	c.Check(toStrSlice(mergeBCall), DeepEquals,
318		[]string{"Pall data 1.1~bp1 00000000", "Pamd64 app 1.1~bp2 00000000", "Pi386 app 1.1~bp2 00000044", "Pi386 dpkg 1.0 00034445",
319			"Pi386 lib 1.0 00000000"})
320
321	mergeBCwithConflicts := reflistB.Merge(reflistC, false, true)
322	c.Check(toStrSlice(mergeBCwithConflicts), DeepEquals,
323		[]string{"Pall data 1.1~bp1 00000000", "Pamd64 app 1.1~bp2 00000000", "Pi386 app 1.1~bp2 00000000", "Pi386 app 1.1~bp2 00000044",
324			"Pi386 dpkg 1.0 00000000", "Pi386 dpkg 1.0 00034445", "Pi386 lib 1.0 00000000"})
325}
326
327func (s *PackageRefListSuite) TestFilterLatestRefs(c *C) {
328	packages := []*Package{
329		{Name: "lib", Version: "1.0", Architecture: "i386"},
330		{Name: "lib", Version: "1.2~bp1", Architecture: "i386"},
331		{Name: "lib", Version: "1.2", Architecture: "i386"},
332		{Name: "dpkg", Version: "1.2", Architecture: "i386"},
333		{Name: "dpkg", Version: "1.3", Architecture: "i386"},
334		{Name: "dpkg", Version: "1.3~bp2", Architecture: "i386"},
335		{Name: "dpkg", Version: "1.5", Architecture: "i386"},
336		{Name: "dpkg", Version: "1.6", Architecture: "i386"},
337	}
338
339	rl := NewPackageList()
340	rl.Add(packages[0])
341	rl.Add(packages[1])
342	rl.Add(packages[2])
343	rl.Add(packages[3])
344	rl.Add(packages[4])
345	rl.Add(packages[5])
346	rl.Add(packages[6])
347	rl.Add(packages[7])
348
349	result := NewPackageRefListFromPackageList(rl)
350	result.FilterLatestRefs()
351
352	c.Check(toStrSlice(result), DeepEquals,
353		[]string{"Pi386 dpkg 1.6", "Pi386 lib 1.2"})
354}
355