1package deb
2
3import (
4	"errors"
5	"regexp"
6	"sort"
7	"strings"
8
9	. "gopkg.in/check.v1"
10)
11
12type containsChecker struct {
13	*CheckerInfo
14}
15
16func (c *containsChecker) Check(params []interface{}, names []string) (result bool, error string) {
17	var (
18		pkgSlice1 []*Package
19		pkgSlice2 []*Package
20		ok        bool
21	)
22
23	pkgMap := make(map[*Package]bool)
24
25	pkgSlice1, ok = params[0].([]*Package)
26	if !ok {
27		return false, "The first parameter is not a Package slice"
28	}
29	pkgSlice2, ok = params[1].([]*Package)
30	if !ok {
31		return false, "The second parameter is not a Package slice"
32	}
33
34	for _, pkg := range pkgSlice2 {
35		pkgMap[pkg] = true
36	}
37
38	for _, pkg := range pkgSlice1 {
39		if _, ok := pkgMap[pkg]; !ok {
40			return false, ""
41		}
42	}
43	return true, ""
44}
45
46var Contains = &containsChecker{&CheckerInfo{Name: "Contains", Params: []string{"Container", "Expected to contain"}}}
47
48type PackageListSuite struct {
49	// Simple list with "real" packages from stanzas
50	list                   *PackageList
51	p1, p2, p3, p4, p5, p6 *Package
52
53	// Mocked packages in list
54	packages       []*Package
55	packages2      []*Package
56	sourcePackages []*Package
57	il             *PackageList
58	il2            *PackageList
59}
60
61var _ = Suite(&PackageListSuite{})
62
63func (s *PackageListSuite) SetUpTest(c *C) {
64	s.list = NewPackageList()
65
66	s.p1 = NewPackageFromControlFile(packageStanza.Copy())
67	s.p2 = NewPackageFromControlFile(packageStanza.Copy())
68	stanza := packageStanza.Copy()
69	stanza["Package"] = "mars-invaders"
70	s.p3 = NewPackageFromControlFile(stanza)
71	stanza = packageStanza.Copy()
72	stanza["Source"] = "unknown-planet"
73	s.p4 = NewPackageFromControlFile(stanza)
74	stanza = packageStanza.Copy()
75	stanza["Package"] = "lonely-strangers"
76	s.p5 = NewPackageFromControlFile(stanza)
77	stanza = packageStanza.Copy()
78	stanza["Version"] = "99.1"
79	s.p6 = NewPackageFromControlFile(stanza)
80
81	s.il = NewPackageList()
82	s.packages = []*Package{
83		{Name: "lib", Version: "1.0", Architecture: "i386", Source: "lib (0.9)", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"mail-agent"}}},
84		{Name: "dpkg", Version: "1.7", Architecture: "i386", Provides: []string{"package-installer"}, deps: &PackageDependencies{}},
85		{Name: "data", Version: "1.1~bp1", Architecture: "all", Source: "app", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}}},
86		{Name: "app", Version: "1.1~bp1", Architecture: "i386", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}},
87		{Name: "mailer", Version: "3.5.8", Architecture: "i386", Source: "postfix (1.3)", Provides: []string{"mail-agent"}, deps: &PackageDependencies{}},
88		{Name: "app", Version: "1.1~bp1", Architecture: "amd64", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}},
89		{Name: "app", Version: "1.1~bp1", Architecture: "arm", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9) | libx (>= 1.5)", "data (>= 1.0) | mail-agent"}}},
90		{Name: "app", Version: "1.0", Architecture: "s390", deps: &PackageDependencies{PreDepends: []string{"dpkg >= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}},
91		{Name: "aa", Version: "2.0-1", Architecture: "i386", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}}},
92		{Name: "dpkg", Version: "1.6.1-3", Architecture: "amd64", Provides: []string{"package-installer"}, deps: &PackageDependencies{}},
93		{Name: "libx", Version: "1.5", Architecture: "arm", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}}},
94		{Name: "dpkg", Version: "1.6.1-3", Architecture: "arm", Provides: []string{"package-installer"}, deps: &PackageDependencies{}},
95		{Name: "dpkg", Version: "1.6.1-3", Architecture: "source", SourceArchitecture: "any", IsSource: true, deps: &PackageDependencies{}},
96		{Name: "dpkg", Version: "1.7", Architecture: "source", SourceArchitecture: "any", IsSource: true, deps: &PackageDependencies{}},
97	}
98	for _, p := range s.packages {
99		s.il.Add(p)
100	}
101	s.il.PrepareIndex()
102
103	s.il2 = NewPackageList()
104	s.packages2 = []*Package{
105		{Name: "mailer", Version: "3.5.8", Architecture: "amd64", Source: "postfix (1.3)", Provides: []string{"mail-agent"}, deps: &PackageDependencies{}},
106		{Name: "sendmail", Version: "1.0", Architecture: "amd64", Source: "postfix (1.3)", Provides: []string{"mail-agent"}, deps: &PackageDependencies{}},
107		{Name: "app", Version: "1.1-bp1", Architecture: "amd64", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}},
108		{Name: "app", Version: "1.1-bp2", Architecture: "amd64", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}},
109		{Name: "app", Version: "1.2", Architecture: "amd64", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}, Depends: []string{"lib (>> 0.9) | libx (>= 1.5)", "data (>= 1.0) | mail-agent"}}},
110		{Name: "app", Version: "3.0", Architecture: "amd64", deps: &PackageDependencies{PreDepends: []string{"dpkg >= 1.6)"}, Depends: []string{"lib (>> 0.9)", "data (>= 1.0)"}}},
111	}
112	for _, p := range s.packages2 {
113		s.il2.Add(p)
114	}
115	s.il2.PrepareIndex()
116
117	s.sourcePackages = []*Package{
118		{Name: "postfix", Version: "1.3", Architecture: "source", SourceArchitecture: "any", IsSource: true, deps: &PackageDependencies{}},
119		{Name: "app", Version: "1.1~bp1", Architecture: "source", SourceArchitecture: "any", IsSource: true, deps: &PackageDependencies{}},
120		{Name: "aa", Version: "2.0-1", Architecture: "source", SourceArchitecture: "any", IsSource: true, deps: &PackageDependencies{}},
121		{Name: "lib", Version: "0.9", Architecture: "source", SourceArchitecture: "any", IsSource: true, deps: &PackageDependencies{}},
122	}
123
124}
125
126func (s *PackageListSuite) TestAddLen(c *C) {
127	c.Check(s.list.Len(), Equals, 0)
128	c.Check(s.list.Add(s.p1), IsNil)
129	c.Check(s.list.Len(), Equals, 1)
130	c.Check(s.list.Add(s.p2), IsNil)
131	c.Check(s.list.Len(), Equals, 1)
132	c.Check(s.list.Add(s.p3), IsNil)
133	c.Check(s.list.Len(), Equals, 2)
134	c.Check(s.list.Add(s.p4), ErrorMatches, "conflict in package.*")
135}
136
137func (s *PackageListSuite) TestRemove(c *C) {
138	c.Check(s.list.Add(s.p1), IsNil)
139	c.Check(s.list.Add(s.p3), IsNil)
140	c.Check(s.list.Len(), Equals, 2)
141
142	s.list.Remove(s.p1)
143	c.Check(s.list.Len(), Equals, 1)
144}
145
146func (s *PackageListSuite) TestAddWhenIndexed(c *C) {
147	c.Check(s.list.Len(), Equals, 0)
148	s.list.PrepareIndex()
149
150	c.Check(s.list.Add(&Package{Name: "a1st", Version: "1.0", Architecture: "i386", Provides: []string{"fa", "fb"}}), IsNil)
151	c.Check(s.list.packagesIndex[0].Name, Equals, "a1st")
152	c.Check(s.list.providesIndex["fa"][0].Name, Equals, "a1st")
153	c.Check(s.list.providesIndex["fb"][0].Name, Equals, "a1st")
154
155	c.Check(s.list.Add(&Package{Name: "c3rd", Version: "1.0", Architecture: "i386", Provides: []string{"fa"}}), IsNil)
156	c.Check(s.list.packagesIndex[0].Name, Equals, "a1st")
157	c.Check(s.list.packagesIndex[1].Name, Equals, "c3rd")
158	c.Check(s.list.providesIndex["fa"][0].Name, Equals, "a1st")
159	c.Check(s.list.providesIndex["fa"][1].Name, Equals, "c3rd")
160	c.Check(s.list.providesIndex["fb"][0].Name, Equals, "a1st")
161
162	c.Check(s.list.Add(&Package{Name: "b2nd", Version: "1.0", Architecture: "i386"}), IsNil)
163	c.Check(s.list.packagesIndex[0].Name, Equals, "a1st")
164	c.Check(s.list.packagesIndex[1].Name, Equals, "b2nd")
165	c.Check(s.list.packagesIndex[2].Name, Equals, "c3rd")
166	c.Check(s.list.providesIndex["fa"][0].Name, Equals, "a1st")
167	c.Check(s.list.providesIndex["fa"][1].Name, Equals, "c3rd")
168	c.Check(s.list.providesIndex["fb"][0].Name, Equals, "a1st")
169}
170
171func (s *PackageListSuite) TestRemoveWhenIndexed(c *C) {
172	s.il.Remove(s.packages[0])
173	names := make([]string, s.il.Len())
174	for i, p := range s.il.packagesIndex {
175		names[i] = p.Name
176	}
177	c.Check(names, DeepEquals, []string{"aa", "app", "app", "app", "app", "data", "dpkg", "dpkg", "dpkg", "dpkg", "dpkg", "libx", "mailer"})
178
179	s.il.Remove(s.packages[4])
180	names = make([]string, s.il.Len())
181	for i, p := range s.il.packagesIndex {
182		names[i] = p.Name
183	}
184	c.Check(names, DeepEquals, []string{"aa", "app", "app", "app", "app", "data", "dpkg", "dpkg", "dpkg", "dpkg", "dpkg", "libx"})
185	c.Check(s.il.providesIndex["mail-agent"], DeepEquals, []*Package{})
186
187	s.il.Remove(s.packages[9])
188	names = make([]string, s.il.Len())
189	for i, p := range s.il.packagesIndex {
190		names[i] = p.Name
191	}
192	c.Check(names, DeepEquals, []string{"aa", "app", "app", "app", "app", "data", "dpkg", "dpkg", "dpkg", "dpkg", "libx"})
193	c.Check(s.il.providesIndex["package-installer"], HasLen, 2)
194
195	s.il.Remove(s.packages[1])
196	names = make([]string, s.il.Len())
197	for i, p := range s.il.packagesIndex {
198		names[i] = p.Name
199	}
200	c.Check(names, DeepEquals, []string{"aa", "app", "app", "app", "app", "data", "dpkg", "dpkg", "dpkg", "libx"})
201	c.Check(s.il.providesIndex["package-installer"], DeepEquals, []*Package{s.packages[11]})
202}
203
204func (s *PackageListSuite) TestForeach(c *C) {
205	s.list.Add(s.p1)
206	s.list.Add(s.p3)
207
208	Len := 0
209	err := s.list.ForEach(func(*Package) error {
210		Len++
211		return nil
212	})
213
214	c.Check(Len, Equals, 2)
215	c.Check(err, IsNil)
216
217	e := errors.New("a")
218
219	err = s.list.ForEach(func(*Package) error {
220		return e
221	})
222
223	c.Check(err, Equals, e)
224
225}
226
227func (s *PackageListSuite) TestIndex(c *C) {
228	c.Check(len(s.il.providesIndex), Equals, 2)
229	c.Check(len(s.il.providesIndex["mail-agent"]), Equals, 1)
230	c.Check(len(s.il.providesIndex["package-installer"]), Equals, 3)
231	c.Check(s.il.packagesIndex[0], Equals, s.packages[8])
232}
233
234func (s *PackageListSuite) TestAppend(c *C) {
235	s.list.Add(s.p1)
236	s.list.Add(s.p3)
237
238	err := s.list.Append(s.il)
239	c.Check(err, IsNil)
240	c.Check(s.list.Len(), Equals, 16)
241
242	list := NewPackageList()
243	list.Add(s.p4)
244
245	err = s.list.Append(list)
246	c.Check(err, ErrorMatches, "conflict.*")
247
248	s.list.PrepareIndex()
249	c.Check(func() { s.list.Append(s.il) }, Panics, "Append not supported when indexed")
250}
251
252func (s *PackageListSuite) TestSearch(c *C) {
253	//allMatches = False
254	c.Check(func() { s.list.Search(Dependency{Architecture: "i386", Pkg: "app"}, false) }, Panics, "list not indexed, can't search")
255
256	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app"}, false), DeepEquals, []*Package{s.packages[3]})
257	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "mail-agent"}, false), DeepEquals, []*Package{s.packages[4]})
258	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "puppy"}, false), IsNil)
259
260	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionEqual, Version: "1.1~bp1"}, false), DeepEquals, []*Package{s.packages[3]})
261	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionEqual, Version: "1.1~bp2"}, false), IsNil)
262
263	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLess, Version: "1.1"}, false), DeepEquals, []*Package{s.packages[3]})
264	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLess, Version: "1.1~~"}, false), IsNil)
265
266	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1"}, false), DeepEquals, []*Package{s.packages[3]})
267	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1~bp1"}, false), DeepEquals, []*Package{s.packages[3]})
268	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1~~"}, false), IsNil)
269
270	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreater, Version: "1.0"}, false), DeepEquals, []*Package{s.packages[3]})
271	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreater, Version: "1.2"}, false), IsNil)
272
273	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.0"}, false), DeepEquals, []*Package{s.packages[3]})
274	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.1~bp1"}, false), DeepEquals, []*Package{s.packages[3]})
275	c.Check(s.il.Search(Dependency{Architecture: "i386", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.2"}, false), IsNil)
276
277	// search w/o version should return package with latest version
278	c.Check(s.il.Search(Dependency{Architecture: "source", Pkg: "dpkg"}, false), DeepEquals, []*Package{s.packages[13]})
279
280	// allMatches = True
281	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app"}, true), Contains, []*Package{s.packages2[2], s.packages2[3], s.packages2[4], s.packages2[5]})
282	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "mail-agent"}, true), Contains, []*Package{s.packages2[0], s.packages2[1]})
283	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "puppy"}, true), IsNil)
284
285	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionEqual, Version: "1.1"}, true), Contains, []*Package{s.packages2[2], s.packages2[3]})
286
287	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionEqual, Version: "1.1"}, true), Contains, []*Package{s.packages2[2], s.packages2[3]})
288	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionEqual, Version: "3"}, true), Contains, []*Package{s.packages2[5]})
289
290	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionLess, Version: "1.2"}, true), Contains, []*Package{s.packages2[2], s.packages2[3]})
291	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionLess, Version: "1.1~"}, true), IsNil)
292
293	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.2"}, true), Contains, []*Package{s.packages2[2], s.packages2[3], s.packages2[4]})
294	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.1-bp1"}, true), Contains, []*Package{s.packages2[2]})
295	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionLessOrEqual, Version: "1.0"}, true), IsNil)
296
297	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionGreater, Version: "1.1"}, true), Contains, []*Package{s.packages2[2], s.packages2[3], s.packages2[4], s.packages2[5]})
298	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionGreater, Version: "5.0"}, true), IsNil)
299
300	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.2"}, true), Contains, []*Package{s.packages2[4], s.packages2[5]})
301	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.1~bp1"}, true), Contains, []*Package{s.packages2[2], s.packages2[3], s.packages2[4], s.packages2[5]})
302	c.Check(s.il2.Search(Dependency{Architecture: "amd64", Pkg: "app", Relation: VersionGreaterOrEqual, Version: "5.0"}, true), IsNil)
303}
304
305func (s *PackageListSuite) TestFilter(c *C) {
306	c.Check(func() { s.list.Filter([]PackageQuery{&PkgQuery{"abcd", "0.3", "i386"}}, false, nil, 0, nil) }, Panics, "list not indexed, can't filter")
307
308	plString := func(l *PackageList) string {
309		list := make([]string, 0, l.Len())
310		for _, p := range l.packages {
311			list = append(list, p.String())
312		}
313
314		sort.Strings(list)
315
316		return strings.Join(list, " ")
317	}
318
319	result, err := s.il.Filter([]PackageQuery{&PkgQuery{"app", "1.1~bp1", "i386"}}, false, nil, 0, nil)
320	c.Check(err, IsNil)
321	c.Check(plString(result), Equals, "app_1.1~bp1_i386")
322
323	result, err = s.il.Filter([]PackageQuery{&PkgQuery{"app", "1.1~bp1", "i386"}, &PkgQuery{"dpkg", "1.7", "source"},
324		&PkgQuery{"dpkg", "1.8", "amd64"}}, false, nil, 0, nil)
325	c.Check(err, IsNil)
326	c.Check(plString(result), Equals, "app_1.1~bp1_i386 dpkg_1.7_source")
327
328	result, err = s.il.Filter([]PackageQuery{
329		&DependencyQuery{Dep: Dependency{Pkg: "app"}},
330		&DependencyQuery{Dep: Dependency{Pkg: "dpkg", Relation: VersionGreater, Version: "1.6.1-3"}},
331		&DependencyQuery{Dep: Dependency{Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.0"}},
332		&DependencyQuery{Dep: Dependency{Pkg: "xyz"}},
333		&DependencyQuery{Dep: Dependency{Pkg: "aa", Relation: VersionGreater, Version: "3.0"}}}, false, nil, 0, nil)
334	c.Check(err, IsNil)
335	c.Check(plString(result), Equals, "app_1.0_s390 app_1.1~bp1_amd64 app_1.1~bp1_arm app_1.1~bp1_i386 dpkg_1.7_i386 dpkg_1.7_source")
336
337	result, err = s.il.Filter([]PackageQuery{&DependencyQuery{Dep: Dependency{Pkg: "app", Architecture: "i386"}}}, true, NewPackageList(), 0, []string{"i386"})
338	c.Check(err, IsNil)
339	c.Check(plString(result), Equals, "app_1.1~bp1_i386 data_1.1~bp1_all dpkg_1.7_i386 lib_1.0_i386 mailer_3.5.8_i386")
340
341	result, err = s.il.Filter([]PackageQuery{
342		&DependencyQuery{Dep: Dependency{Pkg: "app", Relation: VersionGreaterOrEqual, Version: "0.9"}},
343		&DependencyQuery{Dep: Dependency{Pkg: "lib"}},
344		&DependencyQuery{Dep: Dependency{Pkg: "data"}}}, true, NewPackageList(), 0, []string{"i386", "amd64"})
345	c.Check(err, IsNil)
346	c.Check(plString(result), Equals, "app_1.0_s390 app_1.1~bp1_amd64 app_1.1~bp1_arm app_1.1~bp1_i386 data_1.1~bp1_all dpkg_1.6.1-3_amd64 dpkg_1.7_i386 lib_1.0_i386 mailer_3.5.8_i386")
347
348	result, err = s.il.Filter([]PackageQuery{&OrQuery{&PkgQuery{"app", "1.1~bp1", "i386"},
349		&DependencyQuery{Dep: Dependency{Pkg: "dpkg", Relation: VersionGreater, Version: "1.6.1-3"}}}}, false, nil, 0, nil)
350	c.Check(err, IsNil)
351	c.Check(plString(result), Equals, "app_1.1~bp1_i386 dpkg_1.7_i386 dpkg_1.7_source")
352
353	result, err = s.il.Filter([]PackageQuery{&AndQuery{&PkgQuery{"app", "1.1~bp1", "i386"},
354		&DependencyQuery{Dep: Dependency{Pkg: "dpkg", Relation: VersionGreater, Version: "1.6.1-3"}}}}, false, nil, 0, nil)
355	c.Check(err, IsNil)
356	c.Check(plString(result), Equals, "")
357
358	result, err = s.il.Filter([]PackageQuery{&OrQuery{&PkgQuery{"app", "1.1~bp1", "i386"},
359		&FieldQuery{Field: "$Architecture", Relation: VersionEqual, Value: "s390"}}}, false, nil, 0, nil)
360	c.Check(err, IsNil)
361	c.Check(plString(result), Equals, "app_1.0_s390 app_1.1~bp1_i386 data_1.1~bp1_all")
362
363	result, err = s.il.Filter([]PackageQuery{&AndQuery{&FieldQuery{Field: "Version", Relation: VersionGreaterOrEqual, Value: "1.0"},
364		&FieldQuery{Field: "$Architecture", Relation: VersionEqual, Value: "s390"}}}, false, nil, 0, nil)
365	c.Check(err, IsNil)
366	c.Check(plString(result), Equals, "app_1.0_s390 data_1.1~bp1_all")
367
368	result, err = s.il.Filter([]PackageQuery{&AndQuery{
369		&FieldQuery{Field: "$Architecture", Relation: VersionPatternMatch, Value: "i*6"}, &PkgQuery{"app", "1.1~bp1", "i386"}}}, false, nil, 0, nil)
370	c.Check(err, IsNil)
371	c.Check(plString(result), Equals, "app_1.1~bp1_i386")
372
373	result, err = s.il.Filter([]PackageQuery{&NotQuery{
374		&FieldQuery{Field: "$Architecture", Relation: VersionPatternMatch, Value: "i*6"}}}, false, nil, 0, nil)
375	c.Check(err, IsNil)
376	c.Check(plString(result), Equals, "app_1.0_s390 app_1.1~bp1_amd64 app_1.1~bp1_arm data_1.1~bp1_all dpkg_1.6.1-3_amd64 dpkg_1.6.1-3_arm dpkg_1.6.1-3_source dpkg_1.7_source libx_1.5_arm")
377
378	result, err = s.il.Filter([]PackageQuery{&AndQuery{
379		&FieldQuery{Field: "$Architecture", Relation: VersionRegexp, Value: "i.*6", Regexp: regexp.MustCompile("i.*6")}, &PkgQuery{"app", "1.1~bp1", "i386"}}}, false, nil, 0, nil)
380	c.Check(err, IsNil)
381	c.Check(plString(result), Equals, "app_1.1~bp1_i386")
382
383	result, err = s.il.Filter([]PackageQuery{&AndQuery{
384		&FieldQuery{Field: "Name", Relation: VersionRegexp, Value: "a", Regexp: regexp.MustCompile("a")},
385		&NotQuery{Q: &FieldQuery{Field: "Name", Relation: VersionEqual, Value: "data"}},
386	}}, false, nil, 0, nil)
387	c.Check(err, IsNil)
388	c.Check(plString(result), Equals, "aa_2.0-1_i386 app_1.0_s390 app_1.1~bp1_amd64 app_1.1~bp1_arm app_1.1~bp1_i386 mailer_3.5.8_i386")
389
390	result, err = s.il.Filter([]PackageQuery{&AndQuery{
391		&NotQuery{Q: &FieldQuery{Field: "Name", Relation: VersionEqual, Value: "data"}},
392		&FieldQuery{Field: "Name", Relation: VersionRegexp, Value: "a", Regexp: regexp.MustCompile("a")},
393	}}, false, nil, 0, nil)
394	c.Check(err, IsNil)
395	c.Check(plString(result), Equals, "aa_2.0-1_i386 app_1.0_s390 app_1.1~bp1_amd64 app_1.1~bp1_arm app_1.1~bp1_i386 mailer_3.5.8_i386")
396}
397
398func (s *PackageListSuite) TestVerifyDependencies(c *C) {
399	missing, err := s.il.VerifyDependencies(0, []string{"i386"}, s.il, nil)
400	c.Check(err, IsNil)
401	c.Check(missing, DeepEquals, []Dependency{})
402
403	missing, err = s.il.VerifyDependencies(0, []string{"i386", "amd64"}, s.il, nil)
404	c.Check(err, IsNil)
405	c.Check(missing, DeepEquals, []Dependency{{Pkg: "lib", Relation: VersionGreater, Version: "0.9", Architecture: "amd64"}})
406
407	missing, err = s.il.VerifyDependencies(0, []string{"arm"}, s.il, nil)
408	c.Check(err, IsNil)
409	c.Check(missing, DeepEquals, []Dependency{})
410
411	missing, err = s.il.VerifyDependencies(DepFollowAllVariants, []string{"arm"}, s.il, nil)
412	c.Check(err, IsNil)
413	c.Check(missing, DeepEquals, []Dependency{{Pkg: "lib", Relation: VersionGreater, Version: "0.9", Architecture: "arm"},
414		{Pkg: "mail-agent", Relation: VersionDontCare, Version: "", Architecture: "arm"}})
415
416	for _, p := range s.sourcePackages {
417		s.il.Add(p)
418	}
419
420	missing, err = s.il.VerifyDependencies(DepFollowSource, []string{"i386", "amd64"}, s.il, nil)
421	c.Check(err, IsNil)
422	c.Check(missing, DeepEquals, []Dependency{{Pkg: "lib", Relation: VersionGreater, Version: "0.9", Architecture: "amd64"}})
423
424	missing, err = s.il.VerifyDependencies(DepFollowSource, []string{"arm"}, s.il, nil)
425	c.Check(err, IsNil)
426	c.Check(missing, DeepEquals, []Dependency{{Pkg: "libx", Relation: VersionEqual, Version: "1.5", Architecture: "source"}})
427
428	_, err = s.il.VerifyDependencies(0, []string{"i386", "amd64", "s390"}, s.il, nil)
429	c.Check(err, ErrorMatches, "unable to process package app_1.0_s390:.*")
430}
431
432func (s *PackageListSuite) TestArchitectures(c *C) {
433	archs := s.il.Architectures(true)
434	sort.Strings(archs)
435	c.Check(archs, DeepEquals, []string{"amd64", "arm", "i386", "s390", "source"})
436
437	archs = s.il.Architectures(false)
438	sort.Strings(archs)
439	c.Check(archs, DeepEquals, []string{"amd64", "arm", "i386", "s390"})
440}
441