- enable regex matching for different per-attribute values
[platform/upstream/libzypp.git] / tests / zypp / PoolQuery_test.cc
1 #include <stdio.h>
2 #include <iostream>
3 #include <iterator>
4 #include <boost/test/auto_unit_test.hpp>
5 #include <list>
6
7 #include "zypp/ZYppFactory.h"
8 #include "zypp/PoolQuery.h"
9 #include "zypp/PoolQueryUtil.tcc"
10 #include "zypp/TmpPath.h"
11
12 #define BOOST_TEST_MODULE PoolQuery
13
14 using std::cout;
15 using std::endl;
16 using std::string;
17 using namespace zypp;
18 using namespace boost::unit_test;
19
20 bool result_cb( const sat::Solvable & solvable )
21 {
22   zypp::PoolItem pi( zypp::ResPool::instance().find( solvable ) );
23   cout << pi.resolvable() << endl;
24   // name: yast2-sound 2.16.2-9 i586
25   return true;
26 }
27
28 static void init_pool()
29 {
30   Pathname dir(TESTS_SRC_DIR);
31   dir += "/zypp/data/PoolQuery";
32
33   ZYpp::Ptr z = getZYpp();
34   ZConfig::instance().setSystemArchitecture(Arch("i586"));
35
36   RepoInfo i1; i1.setAlias("factory");
37   sat::Pool::instance().addRepoSolv(dir / "factory.solv", i1);
38   RepoInfo i2; i2.setAlias("factory-nonoss");
39   sat::Pool::instance().addRepoSolv(dir / "factory-nonoss.solv", i2);
40   RepoInfo i3; i3.setAlias("zypp_svn");
41   sat::Pool::instance().addRepoSolv(dir / "zypp_svn.solv", i3);
42   RepoInfo i4; i4.setAlias("@System");
43   sat::Pool::instance().addRepoSolv(dir / "@System.solv", i4);
44 }
45
46 BOOST_AUTO_TEST_CASE(pool_query_init)
47 {
48   init_pool();
49 }
50
51 BOOST_AUTO_TEST_CASE(pool_query_exp)
52 {
53   cout << "****exp****"  << endl;
54   
55   PoolQuery q;
56   q.addString("zypper");
57   q.addAttribute(sat::SolvAttr::name);
58
59   // should list 2 selectables
60   for (PoolQuery::Selectable_iterator it = q.selectableBegin();
61        it != q.selectableEnd(); ++it)
62   {
63     ui::Selectable::Ptr s = *it;
64     cout << s->kind() << ":" << s->name() << " hasinstalled: " << s->installedEmpty() << endl;
65   }
66
67   std::for_each(q.begin(), q.end(), &result_cb);
68 }
69
70 /////////////////////////////////////////////////////////////////////////////
71 //  0xx basic queries
72 /////////////////////////////////////////////////////////////////////////////
73
74 // no conditions, default query
75 // result: all available resolvables
76 BOOST_AUTO_TEST_CASE(pool_query_000)
77 {
78   cout << "****000****"  << endl;
79   PoolQuery q;
80   cout << q.size() << endl;
81   BOOST_CHECK(q.size() == 11451);
82   /**!\todo should be 11453 probably according to:
83    * dumpsolv factory.solv factory-nonoss.solv zypp_svn.solv \@System.solv | \
84    * grep '^name:.*\(noarch\|i386\|i586\|i686\|src\)$' | wc -l
85    */
86 }
87
88 // default query + one search string
89 // q.addString("foo");
90 // result: all resolvables having at least one attribute matching foo
91 BOOST_AUTO_TEST_CASE(pool_query_001)
92 {
93   cout << "****001****"  << endl;
94   PoolQuery q;
95   q.addString("zypper");
96
97   std::for_each(q.begin(), q.end(), &result_cb);
98   BOOST_CHECK(q.size() == 16);
99 }
100
101 // default query + one attribute + one string
102 // q.addAttribute(foo, bar);
103 // should be the same as
104 // q.addAttribute(foo); q.addString(bar);
105 // result: resolvables with foo containing bar
106 BOOST_AUTO_TEST_CASE(pool_query_002)
107 {
108   cout << "****002****"  << endl;
109   PoolQuery q;
110   q.addString("zypper");
111   q.addAttribute(sat::SolvAttr::name);
112
113   std::for_each(q.begin(), q.end(), &result_cb);
114   BOOST_CHECK(q.size() == 6);
115
116   cout << endl;
117
118   PoolQuery q1;
119   q1.addAttribute(sat::SolvAttr::name, "zypper");
120
121   std::for_each(q1.begin(), q1.end(), &result_cb);
122   BOOST_CHECK(q1.size() == 6);
123 }
124
125 // kind filter
126 BOOST_AUTO_TEST_CASE(pool_query_003)
127 {
128   cout << "****003****"  << endl;
129   PoolQuery q;
130   q.addString("zypper");
131   q.addAttribute(sat::SolvAttr::name);
132   q.addKind(ResTraits<Package>::kind);
133
134   std::for_each(q.begin(), q.end(), &result_cb);
135   BOOST_CHECK(q.size() == 3);
136 }
137
138 // match exact
139 BOOST_AUTO_TEST_CASE(pool_query_004)
140 {
141   cout << "****004****"  << endl;
142   PoolQuery q;
143   q.addString("vim");
144   q.addAttribute(sat::SolvAttr::name);
145   q.setMatchExact();
146
147   std::for_each(q.begin(), q.end(), &result_cb);
148   BOOST_CHECK(q.size() == 3);
149
150   PoolQuery q1;
151   q1.addString("zypp");
152   q1.addAttribute(sat::SolvAttr::name);
153   q1.setMatchExact();
154
155   std::for_each(q1.begin(), q1.end(), &result_cb);
156   BOOST_CHECK(q1.empty());
157 }
158
159 // use globs
160 BOOST_AUTO_TEST_CASE(pool_query_005)
161 {
162   cout << "****005.1****"  << endl;
163   PoolQuery q;
164   q.addString("z?p*");
165   q.addAttribute(sat::SolvAttr::name);
166   q.setMatchGlob();
167
168   std::for_each(q.begin(), q.end(), &result_cb);
169   BOOST_CHECK(q.size() == 11);
170
171   cout << "****005.2****"  << endl;
172
173   PoolQuery q1;
174   q1.addString("*zypp*");
175   q1.addAttribute(sat::SolvAttr::name);
176   q1.setMatchGlob();
177
178   std::for_each(q1.begin(), q1.end(), &result_cb);
179   BOOST_CHECK(q1.size() == 28);
180
181   cout << "****005.3****"  << endl;
182
183   // should be the same as above
184   PoolQuery q2;
185   q2.addString("zypp");
186   q2.addAttribute(sat::SolvAttr::name);
187
188   BOOST_CHECK(q2.size() == 28);
189 }
190
191 // use regex
192 BOOST_AUTO_TEST_CASE(pool_query_006)
193 {
194   cout << "****006.1***"  << endl;
195
196   // should be the same as 005 1
197   PoolQuery q;
198   q.addString("^z.p.*");
199   q.addAttribute(sat::SolvAttr::name);
200   q.setMatchRegex();
201
202   std::for_each(q.begin(), q.end(), &result_cb);
203   BOOST_CHECK(q.size() == 11);
204
205   cout << "****006.2***"  << endl;
206
207   PoolQuery q1;
208   q1.addString("zypper|smart");
209   q1.addAttribute(sat::SolvAttr::name);
210   q1.setMatchRegex();
211
212   std::for_each(q1.begin(), q1.end(), &result_cb);
213   BOOST_CHECK(q1.size() == 21);
214
215   cout << "****006.3***"  << endl;
216
217   // invalid regex
218   PoolQuery q2;
219   q2.addString("zypp\\");
220   q2.setMatchRegex();
221   BOOST_CHECK_THROW(q2.size(), Exception);
222 }
223
224
225 // match by installed status (basically by system vs. repo)
226 BOOST_AUTO_TEST_CASE(pool_query_050)
227 {
228   cout << "****050****"  << endl;
229   PoolQuery q;
230   q.addString("zypper");
231   q.addAttribute(sat::SolvAttr::name);
232   q.setMatchExact();
233   q.setInstalledOnly();
234
235   std::for_each(q.begin(), q.end(), &result_cb);
236   BOOST_CHECK(q.size() == 1);
237
238   cout << endl;
239
240   PoolQuery q1;
241   q1.addString("zypper");
242   q1.addAttribute(sat::SolvAttr::name);
243   q1.setMatchExact();
244   q1.setUninstalledOnly();
245
246   std::for_each(q1.begin(), q1.end(), &result_cb);
247   BOOST_CHECK(q1.size() == 5);
248 }
249
250
251 /////////////////////////////////////////////////////////////////////////////
252 //  1xx multiple attribute queries
253 /////////////////////////////////////////////////////////////////////////////
254
255
256 BOOST_AUTO_TEST_CASE(pool_query_100)
257 {
258   cout << "****100****"  << endl;
259   PoolQuery q;
260   /* This string is found sometimes only in solvable names (e.g. novell-lum),
261      sometimes only in summary (e.g. yast2-casa-ats) and sometimes only
262      in descriptions (e.g. beagle-quickfinder).  novell-lum doesn't exist
263      in our test solv file, but let's ignore this.  I didn't find a string
264      with the same characteristics giving fewer matches :-/  */
265   q.addString("novell");
266   q.addAttribute(sat::SolvAttr::name);
267   q.addAttribute(sat::SolvAttr::summary);
268   q.addAttribute(sat::SolvAttr::description);
269
270   std::for_each(q.begin(), q.end(), &result_cb);
271   BOOST_CHECK(q.size() == 74);
272
273   cout << endl;
274
275   PoolQuery q1;
276   q1.addString("mp3");
277   q1.addAttribute(sat::SolvAttr::name);
278
279   std::for_each(q1.begin(), q1.end(), &result_cb);
280   BOOST_CHECK(q1.size() == 7);
281 }
282
283
284 // multi attr (same value) substring matching (case sensitive and insensitive)
285 BOOST_AUTO_TEST_CASE(pool_query_101)
286 {
287   cout << "****101****"  << endl;
288
289   PoolQuery q;
290   q.addString("ZYpp");
291   q.addAttribute(sat::SolvAttr::name);
292   q.addAttribute(sat::SolvAttr::summary);
293   q.addAttribute(sat::SolvAttr::description);
294
295   std::for_each(q.begin(), q.end(), &result_cb);
296   BOOST_CHECK(q.size() == 30);
297
298   cout << endl;
299
300   PoolQuery q2;
301   q2.addString("ZYpp");
302   q2.addAttribute(sat::SolvAttr::name);
303   q2.addAttribute(sat::SolvAttr::summary);
304   q2.addAttribute(sat::SolvAttr::description);
305   q2.setCaseSensitive();
306
307   std::for_each(q2.begin(), q2.end(), &result_cb);
308   BOOST_CHECK(q2.size() == 2);
309 }
310
311
312 // multi attr (same value) glob matching (case sensitive and insensitive)
313 BOOST_AUTO_TEST_CASE(pool_query_102)
314 {
315   cout << "****102****"  << endl;
316   PoolQuery q;
317   q.addString("pack*");
318   q.addAttribute(sat::SolvAttr::name);
319   q.addAttribute(sat::SolvAttr::summary);
320   q.setMatchGlob();
321
322   std::for_each(q.begin(), q.end(), &result_cb);
323   BOOST_CHECK(q.size() == 35);
324 }
325
326
327 // multi attr (same value via addAttribute())
328 BOOST_AUTO_TEST_CASE(pool_query_103)
329 {
330   cout << "****103.1****"  << endl;
331   PoolQuery q;
332   q.addAttribute(sat::SolvAttr::name, "novell");
333   q.addAttribute(sat::SolvAttr::summary, "novell");
334
335 //  std::for_each(q.begin(), q.end(), &result_cb);
336   BOOST_CHECK(q.size() == 42);
337
338   cout << "****103.2****"  << endl;
339
340   PoolQuery q1;
341   q1.addString("novell");
342   q1.addAttribute(sat::SolvAttr::name);
343   q1.addAttribute(sat::SolvAttr::summary);
344
345 //  std::for_each(q1.begin(), q1.end(), &result_cb);
346   BOOST_CHECK(q1.size() == 42);
347
348   cout << endl;
349 }
350
351 // multiple attributes, different search strings (one string per attrbute)
352 BOOST_AUTO_TEST_CASE(pool_query_104)
353 {
354   cout << "****104****"  << endl;
355   PoolQuery q;
356   q.addAttribute(sat::SolvAttr::name, "novell");
357   q.addAttribute(sat::SolvAttr::summary, "package management");
358
359   std::for_each(q.begin(), q.end(), &result_cb);
360   BOOST_CHECK(q.size() == 22);
361 }
362
363 // multiple attributes, different search strings (one string per attrbute), regex matching
364 BOOST_AUTO_TEST_CASE(pool_query_105)
365 {
366   cout << "****105****"  << endl;
367   PoolQuery q;
368   q.addAttribute(sat::SolvAttr::name, "no.ell");
369   q.addAttribute(sat::SolvAttr::summary, "package management");
370   q.setMatchRegex();
371
372   std::for_each(q.begin(), q.end(), &result_cb);
373   BOOST_CHECK(q.size() == 22);
374 }
375
376 /////////////////////////////////////////////////////////////////////////////
377 //  3xx repo filter queries (addRepo(alias_str))
378 /////////////////////////////////////////////////////////////////////////////
379
380 // default query + one attribute(one string) + one repo
381 BOOST_AUTO_TEST_CASE(pool_query_300)
382 {
383   cout << "****300****"  << endl;
384   PoolQuery q;
385   q.addAttribute(sat::SolvAttr::name, "zypper");
386   q.addRepo("zypp_svn");
387
388   std::for_each(q.begin(), q.end(), &result_cb);
389   BOOST_CHECK(q.size() == 3);
390 }
391
392 // default query + one repo
393 BOOST_AUTO_TEST_CASE(pool_query_301)
394 {
395   cout << "****301****"  << endl;
396   PoolQuery q;
397   q.addRepo("zypp_svn");
398
399   std::for_each(q.begin(), q.end(), &result_cb);
400   BOOST_CHECK(q.size() == 21);
401 }
402
403 // multiple repos + one attribute
404 BOOST_AUTO_TEST_CASE(pool_query_302)
405 {
406   cout << "****302****"  << endl;
407   PoolQuery q;
408   q.addString("ma");
409   q.addAttribute(sat::SolvAttr::name);
410   q.addRepo("factory-nonoss");
411   q.addRepo("zypp_svn");
412
413   std::for_each(q.begin(), q.end(), &result_cb);
414   BOOST_CHECK(q.size() == 8);
415 }
416
417 /*
418 BOOST_AUTO_TEST_CASE(pool_query_X)
419 {
420   cout << "****X****"  << endl;
421   PoolQuery q;
422   q.addString("pack*");
423   q.addAttribute(sat::SolvAttr::name);
424
425   std::for_each(q.begin(), q.end(), &result_cb);
426   BOOST_CHECK(q.size() == 28);
427 }
428 */
429
430 // test matching
431 BOOST_AUTO_TEST_CASE(pool_query_equal)
432 {
433   cout << "****equal****"  << endl;
434   PoolQuery q;
435   q.addString("zypp");
436   q.addAttribute(sat::SolvAttr::name);
437   q.setMatchGlob();
438   PoolQuery q2;
439   q2.addString("zypp");
440   q2.addAttribute(sat::SolvAttr::name);
441   q2.setMatchGlob();
442   PoolQuery q3;
443   q3.addString("zypp");
444   q3.addAttribute(sat::SolvAttr::name);
445   q3.setMatchGlob();
446   q3.setRequireAll(true);
447   PoolQuery q4;
448   q4.addAttribute(sat::SolvAttr::name,"zypp");
449   q4.setMatchGlob();
450
451   BOOST_CHECK(q==q2);
452   BOOST_CHECK(q!=q3);
453   BOOST_CHECK(q==q4);
454   BOOST_CHECK(q4!=q3);
455 }
456
457 // save/load query
458 BOOST_AUTO_TEST_CASE(pool_query_save_restore)
459 {
460 #warning CAN NOT USE A FIX SOLV FILE
461 // must store some raw metadata and generate the solv file
462 // otherwise trestcases break whenever the solv format changes
463 #if 0
464   Pathname dir(TESTS_SRC_DIR);
465   dir += "/zypp/data/PoolQuery";
466
467   ZYpp::Ptr z = getZYpp();
468
469   sat::Pool::instance().addRepoSolv(dir + "foo.solv");
470
471   PoolQuery query;
472   //query.setInstalledOnly();
473   query.execute("kde", &result_cb);
474
475   cout << "search done." << endl;
476
477   query.setMatchExact(true);
478   query.execute("kde", &result_cb);
479
480   cout << "search done." << endl;
481 #endif
482
483 //test recovery from file
484   Pathname pathToQueries(TESTS_SRC_DIR);
485   pathToQueries += "/zypp/data/PoolQuery/savedqueries";
486
487   std::list<PoolQuery> savedQueries;
488
489   std::insert_iterator<std::list<PoolQuery> > ii(savedQueries, savedQueries.end());
490   readPoolQueriesFromFile(pathToQueries,ii);
491   BOOST_CHECK( savedQueries.size() == 2 );
492
493   filesystem::TmpFile tmp;
494   Pathname tmpPath = tmp.path();
495
496   savedQueries.clear();
497
498   PoolQuery q1;
499   PoolQuery q2;
500
501   q1.addKind( Resolvable::Kind::patch );
502   q2.addKind( Resolvable::Kind::patch );
503   q2.addKind( Resolvable::Kind::pattern );
504
505   savedQueries.push_front( q1 );
506   savedQueries.push_front( q2 );
507
508   writePoolQueriesToFile ( tmpPath, savedQueries.begin(), savedQueries.end() );
509   std::insert_iterator<std::list<PoolQuery> > ii2(savedQueries,
510       savedQueries.end());
511   //reread writed queries
512   readPoolQueriesFromFile( tmpPath, ii2);
513   //TODO test if 0==2 and 1==3
514   BOOST_CHECK( savedQueries.size() == 4 );
515
516 }