Imported Upstream version 17.23.5
[platform/upstream/libzypp.git] / tests / zypp / PoolQuery_test.cc
1 #include "TestSetup.h"
2 #include <zypp/PoolQuery.h>
3 #include <zypp/PoolQueryUtil.tcc>
4
5 #define BOOST_TEST_MODULE PoolQuery
6
7 /////////////////////////////////////////////////////////////////////////////
8 static TestSetup test( TestSetup::initLater );
9 struct TestInit {
10   TestInit() {
11     test = TestSetup( Arch_x86_64 );
12
13     // Abuse;) vbox as System repo:
14     test.loadTargetRepo( TESTS_SRC_DIR "/data/obs_virtualbox_11_1" );
15     test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" );
16     test.loadRepo( TESTS_SRC_DIR "/data/OBS_zypp_svn-11.1", "zyppsvn" );
17
18     dumpRange( USR, test.pool().knownRepositoriesBegin(),
19       test.pool().knownRepositoriesEnd() );
20     USR << "pool: " << test.pool() << endl;
21   }
22   ~TestInit() { test.reset(); }
23 };
24 BOOST_GLOBAL_FIXTURE( TestInit );
25 /////////////////////////////////////////////////////////////////////////////
26
27 static std::ofstream devNull;
28 #define COUT devNull
29
30 struct PrintAndCount
31 {
32   PrintAndCount() : _count(0) {}
33
34   bool operator()( const sat::Solvable & solvable )
35   {
36     zypp::PoolItem pi( zypp::ResPool::instance().find( solvable ) );
37     COUT << pi.resolvable() << endl;
38     ++_count;
39     return true;
40   }
41
42   unsigned _count;
43 };
44
45 void dumpQ( std::ostream & str, const PoolQuery & q, bool verbose = true )
46 {
47   q.begin();
48   str << q << endl;
49   unsigned nc = 0;
50   if ( 1 )
51   {
52     for_( it, q.begin(), q.end() )
53     {
54       ++nc;
55       if ( verbose )
56         str << it << endl;
57     }
58     str << "--> MATCHES: " << nc << endl;
59   }
60 }
61
62
63 #if 0
64 BOOST_AUTO_TEST_CASE(pool_query_experiment)
65 {
66   cout << "****experiment****"  << endl;
67
68   PoolQuery q;
69   q.addString("zypper");
70   q.addAttribute(sat::SolvAttr::name);
71
72   // should list 1 selectable?
73   cout << "****selectables****"  << endl;
74   for (PoolQuery::Selectable_iterator it = q.selectableBegin();
75        it != q.selectableEnd(); ++it)
76   {
77     ui::Selectable::Ptr s = *it;
78     cout << s->kind() << ":" << s->name() << " hasinstalled: " << s->installedEmpty() << endl;
79   }
80   cout << "****solvables****" << endl;
81   PrintAndCount cb;
82   std::for_each(q.begin(), q.end(), cb);
83 }
84 #endif
85
86 /////////////////////////////////////////////////////////////////////////////
87 //  0xx basic queries
88 /////////////////////////////////////////////////////////////////////////////
89
90 // no conditions, default query
91 // result: all available resolvables
92 BOOST_AUTO_TEST_CASE(pool_query_000)
93 {
94   cout << "****000****"  << endl;
95   PoolQuery q;
96   cout << q.size() << endl;
97   BOOST_CHECK(q.size() == 3811);
98
99   /* dumpsolv repo1.solv repo2.solv repo3.solv | \
100      grep '^name:.*\(noarch\|x86_64\|i386\|i586\|i686\|src\)$' | wc -l */
101 }
102
103 // default query + one search string
104 // q.addString("foo");
105 // result: all resolvables having at least one attribute matching foo
106 BOOST_AUTO_TEST_CASE(pool_query_001)
107 {
108   cout << "****001****"  << endl;
109   PoolQuery q;
110   q.addString("zypper");
111
112   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 11);
113 }
114
115 // default query + one attribute + one string
116 // q.addAttribute(foo, bar);
117 // should be the same as
118 // q.addAttribute(foo); q.addString(bar);
119 // result: resolvables with foo containing bar
120 BOOST_AUTO_TEST_CASE(pool_query_002)
121 {
122   cout << "****002****"  << endl;
123   PoolQuery q;
124   q.addString("zypper");
125   q.addAttribute(sat::SolvAttr::name);
126
127   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 5);
128
129   cout << endl;
130
131   PoolQuery q1;
132   q1.addAttribute(sat::SolvAttr::name, "zypper");
133
134   BOOST_CHECK(std::for_each(q1.begin(), q1.end(), PrintAndCount())._count == 5);
135 }
136
137 // kind filter
138 BOOST_AUTO_TEST_CASE(pool_query_003)
139 {
140   cout << "****003****"  << endl;
141   PoolQuery q;
142   q.addString("zypper");
143   q.addAttribute(sat::SolvAttr::name);
144   q.addKind(ResKind::package);
145
146   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 3);
147 }
148
149 // match exact
150 BOOST_AUTO_TEST_CASE(pool_query_004)
151 {
152   cout << "****004****"  << endl;
153   PoolQuery q;
154   q.addString("vim");
155   q.addAttribute(sat::SolvAttr::name);
156   q.setMatchExact();
157
158   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 1);
159
160   PoolQuery q1;
161   q1.addString("zypp");
162   q1.addAttribute(sat::SolvAttr::name);
163   q1.setMatchExact();
164
165   std::for_each(q1.begin(), q1.end(), PrintAndCount());
166   BOOST_CHECK(q1.empty());
167 }
168
169 // use globs
170 BOOST_AUTO_TEST_CASE(pool_query_005)
171 {
172   cout << "****005.1****"  << endl;
173   PoolQuery q;
174   q.addString("z?p*");
175   q.addAttribute(sat::SolvAttr::name);
176   q.setMatchGlob();
177
178   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 6);
179
180   cout << "****005.2****"  << endl;
181
182   PoolQuery q1;
183   q1.addString("*zypp*");
184   q1.addAttribute(sat::SolvAttr::name);
185   q1.setMatchGlob();
186
187   BOOST_CHECK(std::for_each(q1.begin(), q1.end(), PrintAndCount())._count == 26);
188
189   cout << "****005.3****"  << endl;
190
191   // should be the same as above
192   PoolQuery q2;
193   q2.addString("zypp");
194   q2.addAttribute(sat::SolvAttr::name);
195
196   BOOST_CHECK(q2.size() == 26);
197 }
198
199 // use regex
200 BOOST_AUTO_TEST_CASE(pool_query_006)
201 {
202   cout << "****006.1***"  << endl;
203
204   // should be the same as 005 1
205   PoolQuery q;
206   q.addString("^z.p.*");
207   q.addAttribute(sat::SolvAttr::name);
208   q.setMatchRegex();
209
210   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 6);
211
212   cout << "****006.2***"  << endl;
213
214   PoolQuery q1;
215   q1.addString("zypper|smart");
216   q1.addAttribute(sat::SolvAttr::name);
217   q1.setMatchRegex();
218
219   BOOST_CHECK(std::for_each(q1.begin(), q1.end(), PrintAndCount())._count == 8);
220
221   cout << "****006.3***"  << endl;
222
223   // invalid regex
224   PoolQuery q2;
225   q2.addString("zypp\\");
226   q2.setMatchRegex();
227   BOOST_CHECK_THROW(q2.begin(), Exception);
228 }
229
230
231 // match whole words
232 BOOST_AUTO_TEST_CASE(pool_query_007)
233 {
234   cout << "****007***"  << endl;
235
236   PoolQuery q;
237   q.addString("zypp");
238   q.addAttribute(sat::SolvAttr::name);
239   q.setMatchWord();
240
241   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 6);
242 }
243
244 // match by installed status (basically by system vs. repo)
245 BOOST_AUTO_TEST_CASE(pool_query_050)
246 {
247   cout << "****050****"  << endl;
248   PoolQuery q;
249   q.addString("yasm");
250   q.addAttribute(sat::SolvAttr::name);
251   q.setMatchExact();
252   q.setInstalledOnly();
253
254   BOOST_CHECK_EQUAL(std::for_each(q.begin(), q.end(), PrintAndCount())._count, 4);
255
256   cout << endl;
257
258   PoolQuery q1;
259   q1.addString("zypper");
260   q1.addAttribute(sat::SolvAttr::name);
261   q1.setMatchExact();
262   q1.setUninstalledOnly();
263   BOOST_CHECK_EQUAL(std::for_each(q1.begin(), q1.end(), PrintAndCount())._count, 5);
264 }
265
266 /////////////////////////////////////////////////////////////////////////////
267 //  1xx multiple attribute queries
268 /////////////////////////////////////////////////////////////////////////////
269
270
271 BOOST_AUTO_TEST_CASE(pool_query_100)
272 {
273   cout << "****100****"  << endl;
274   PoolQuery q;
275   /* This string is found sometimes only in only in summary (e.g. pgcalc)
276      and sometimes only in description (e.g. bc, lftp). We don't have
277      any package with 'revers' only in package name, but let's ignore this.
278      I didn't find a string with the same characteristics giving fewer matches
279      :-/ */
280   q.addString("revers");
281   q.addAttribute(sat::SolvAttr::name);
282   q.addAttribute(sat::SolvAttr::summary);
283   q.addAttribute(sat::SolvAttr::description);
284
285   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 5);
286
287   cout << endl;
288
289   {
290     PoolQuery q1;
291     q1.addAttribute(sat::SolvAttr::name, "zypper");
292     BOOST_CHECK_EQUAL(q1.size(),5);
293
294     PoolQuery q2;
295     q2.addAttribute(sat::SolvAttr::summary,"samba");
296     BOOST_CHECK_EQUAL(q2.size(),13);
297
298     // now summary and name in one go:
299     q1.addAttribute(sat::SolvAttr::summary,"samba");
300     BOOST_CHECK_EQUAL(q1.size(),18);
301   }
302 }
303
304
305 // multi attr (same value) substring matching (case sensitive and insensitive)
306 BOOST_AUTO_TEST_CASE(pool_query_101)
307 {
308   cout << "****101****"  << endl;
309
310   PoolQuery q;
311   q.addString("RELAX");
312   q.addAttribute(sat::SolvAttr::name);
313   q.addAttribute(sat::SolvAttr::summary);
314   q.addAttribute(sat::SolvAttr::description);
315
316   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 7);
317
318   cout << endl;
319
320   PoolQuery q2;
321   q2.addString("RELAX");
322   q2.addAttribute(sat::SolvAttr::name);
323   q2.addAttribute(sat::SolvAttr::summary);
324   q2.addAttribute(sat::SolvAttr::description);
325   q2.setCaseSensitive();
326
327   BOOST_CHECK(std::for_each(q2.begin(), q2.end(), PrintAndCount())._count == 4);
328 }
329
330
331 // multi attr (same value) glob matching (case sensitive and insensitive)
332 BOOST_AUTO_TEST_CASE(pool_query_102)
333 {
334   cout << "****102****"  << endl;
335   PoolQuery q;
336   q.addString("pack*");
337   q.addAttribute(sat::SolvAttr::name);
338   q.addAttribute(sat::SolvAttr::summary);
339   q.setMatchGlob();
340
341   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 23);
342 }
343
344
345 // multi attr (same value via addAttribute())
346 BOOST_AUTO_TEST_CASE(pool_query_103)
347 {
348   cout << "****103.1****"  << endl;
349   PoolQuery q;
350   q.addAttribute(sat::SolvAttr::name, "rest");
351   q.addAttribute(sat::SolvAttr::summary, "rest");
352
353   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 14);
354
355   cout << "****103.2****"  << endl;
356
357   PoolQuery q1;
358   q1.addString("rest");
359   q1.addAttribute(sat::SolvAttr::name);
360   q1.addAttribute(sat::SolvAttr::summary);
361
362   BOOST_CHECK(std::for_each(q1.begin(), q1.end(), PrintAndCount())._count == 14);
363 //  BOOST_CHECK(q1.size() == 42);
364
365   cout << endl;
366 }
367
368 // multiple attributes, different search strings (one string per attrbute)
369 BOOST_AUTO_TEST_CASE(pool_query_104)
370 {
371   cout << "****104****"  << endl;
372   PoolQuery q;
373   q.addAttribute(sat::SolvAttr::name, "zypper");
374   q.addAttribute(sat::SolvAttr::summary, "package management");
375
376   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 8);
377 }
378
379 // multiple attributes, different search strings (one string per attrbute), regex matching
380 BOOST_AUTO_TEST_CASE(pool_query_105)
381 {
382   cout << "****105****"  << endl;
383   PoolQuery q;
384   q.addAttribute(sat::SolvAttr::name, "zy..er");
385   q.addAttribute(sat::SolvAttr::summary, "package management");
386   q.setMatchRegex();
387
388   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 8);
389 }
390
391 /////////////////////////////////////////////////////////////////////////////
392 //  3xx repo filter queries (addRepo(alias_str))
393 /////////////////////////////////////////////////////////////////////////////
394
395 // default query + one attribute(one string) + one repo
396 BOOST_AUTO_TEST_CASE(pool_query_300)
397 {
398   cout << "****300****"  << endl;
399   PoolQuery q;
400   q.addAttribute(sat::SolvAttr::name, "zypper");
401   q.addRepo("zyppsvn");
402
403   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 4);
404 }
405
406 // default query + one repo
407 BOOST_AUTO_TEST_CASE(pool_query_301)
408 {
409   cout << "****301****"  << endl;
410   PoolQuery q;
411   q.addRepo("zyppsvn");
412
413   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 42);
414 }
415
416 // multiple repos + one attribute
417 BOOST_AUTO_TEST_CASE(pool_query_302)
418 {
419   cout << "****302****"  << endl;
420   PoolQuery q;
421   q.addString("zypper");
422   q.addAttribute(sat::SolvAttr::name);
423   q.addRepo("opensuse");
424   q.addRepo("zyppsvn");
425
426   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 5);
427 }
428
429 /////////////////////////////////////////////////////////////////////////////
430 //  4xx kind queries (addKind(ResKind))
431 /////////////////////////////////////////////////////////////////////////////
432
433 BOOST_AUTO_TEST_CASE(pool_query_400)
434 {
435   cout << "****400****"  << endl;
436   PoolQuery q;
437   q.addString("lamp_server");
438   q.addAttribute(sat::SolvAttr::name);
439   q.addKind(ResKind::pattern);
440   q.setMatchExact();
441
442   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 1);
443 }
444
445 // should find packages and patterns
446 BOOST_AUTO_TEST_CASE(pool_query_401)
447 {
448   cout << "****401****"  << endl;
449   PoolQuery q;
450   q.addString("mail*");
451   q.addAttribute(sat::SolvAttr::name);
452   q.setMatchGlob();
453
454   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 4);
455 }
456
457
458 /////////////////////////////////////////////////////////////////////////////
459 //  5xx multiple string/attribute queries
460 /////////////////////////////////////////////////////////////////////////////
461
462 // multiple strings for one attribute
463 BOOST_AUTO_TEST_CASE(pool_query_500)
464 {
465   cout << "****500.1****"  << endl;
466   PoolQuery q;
467   q.addString("zypper");
468   q.addString("yast2-packager");
469   q.addAttribute(sat::SolvAttr::name);
470   q.setMatchExact();
471   // creates: ^(apt|zypper)$
472   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 6);
473
474   cout << "****500.2****"  << endl;
475   q.addString("*bzypp");
476   q.setMatchGlob();
477   // creates: ^(.*zy.p|yast.*package.*|.*bzypp)$
478   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 11);
479
480   cout << "****500.3****"  << endl;
481   PoolQuery q1;
482   q1.addString("^libsm[a-z]*[0-9]$");
483   q1.addAttribute(sat::SolvAttr::name, "bzypp$");
484   q1.addKind(ResKind::package);
485   q1.setMatchRegex();
486   // creates: (^libsm[a-z]*[0-9]$|bzypp$)
487   BOOST_CHECK(std::for_each(q1.begin(), q1.end(), PrintAndCount())._count == 5);
488
489   cout << "****500.4****"  << endl;
490   PoolQuery q2;
491   q2.addString("Thunder");
492   q2.addAttribute(sat::SolvAttr::name, "sun");
493   q2.addKind(ResKind::package);
494   q2.addRepo("opensuse");
495   q2.setCaseSensitive();
496   // creates: (sun|Thunder)
497   BOOST_CHECK(std::for_each(q2.begin(), q2.end(), PrintAndCount())._count == 3);
498
499   cout << "****500.5****"  << endl;
500   PoolQuery q3;
501   q3.addString("audio");
502   q3.addAttribute(sat::SolvAttr::name, "zip");
503   q3.addKind(ResKind::package);
504   q3.addRepo("opensuse");
505   q3.setMatchWord();
506   // creates: \b(zip|audio)\b
507   BOOST_CHECK(std::for_each(q3.begin(), q3.end(), PrintAndCount())._count == 3);
508 }
509
510 // multiple strings, multiple attributes, same strings
511 BOOST_AUTO_TEST_CASE(pool_query_501)
512 {
513   cout << "****501****"  << endl;
514   PoolQuery q;
515   q.addString("Thunder");
516   q.addString("storm");
517   q.addAttribute(sat::SolvAttr::name);
518   q.addAttribute(sat::SolvAttr::description);
519   q.addKind(ResKind::package);
520   q.addRepo("opensuse");
521
522   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 14);
523 }
524
525 // multiple strings, multiple attributes, same strings
526 BOOST_AUTO_TEST_CASE(pool_query_502)
527 {
528   cout << "****502****"  << endl;
529   PoolQuery q;
530   q.addString("weather");
531   q.addAttribute(sat::SolvAttr::name, "thunder");
532   q.addAttribute(sat::SolvAttr::description, "storm");
533   q.addKind(ResKind::package);
534   q.addRepo("opensuse");
535
536   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 13);
537 }
538
539 /////////////////////////////////////////////////////////////////////////////
540 //  6xx queries with edition
541 /////////////////////////////////////////////////////////////////////////////
542
543 BOOST_AUTO_TEST_CASE(pool_query_X)
544 {
545   cout << "****600.1****"  << endl;
546   PoolQuery q;
547   q.addAttribute(sat::SolvAttr::name, "zypper");
548   q.setMatchExact();
549   q.setEdition(Edition("0.12.5"), Rel::GT);
550
551   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 4);
552
553   cout << "****600.2****"  << endl;
554   q.setEdition(Edition("0.12.5"), Rel::LT);
555
556   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 0);
557
558   cout << "****600.3****"  << endl;
559   q.setEdition(Edition("0.12.5"), Rel::LE);
560
561   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 1);
562
563   cout << "****600.4****"  << endl;
564   q.setEdition(Edition("0.12.5-5"), Rel::LT);
565
566   BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 1);
567 }
568
569 BOOST_AUTO_TEST_CASE(pool_query_X1)
570 {
571   cout << "****601.****"  << endl;
572   PoolQuery q;
573   q.addString("zypper");
574   q.addAttribute(sat::SolvAttr::name );
575   BOOST_CHECK_EQUAL(std::for_each(q.begin(), q.end(), PrintAndCount())._count, 5);
576
577   q.setEdition(Edition("0.12.8"), Rel::GE);
578   BOOST_CHECK_EQUAL(std::for_each(q.begin(), q.end(), PrintAndCount())._count, 4);
579 }
580
581 BOOST_AUTO_TEST_CASE(pool_query_X2)
582 {
583   cout << "****X****"  << endl;
584   PoolQuery q;
585   q.setMatchGlob();
586   q.addString("zypp*");
587   q.addAttribute(sat::SolvAttr::name);
588
589   BOOST_CHECK_EQUAL(std::for_each(q.begin(), q.end(), PrintAndCount())._count, 5);
590 }
591
592
593 BOOST_AUTO_TEST_CASE(pool_query_recovery)
594 {
595   Pathname testfile(TESTS_SRC_DIR);
596     testfile += "/zypp/data/PoolQuery/savedqueries";
597   cout << "****recovery****"  << endl;
598
599   std::vector<PoolQuery> queries;
600   std::insert_iterator<std::vector<PoolQuery> > ii( queries,queries.begin());
601   readPoolQueriesFromFile(testfile,ii);
602   BOOST_REQUIRE_MESSAGE(queries.size() == 2, "Bad count of read queries.");
603
604   BOOST_CHECK_EQUAL(queries[0].size(), 8);
605
606   PoolQuery q;
607   q.addString("ma*");
608   q.addRepo("opensuse");
609   q.addKind(ResKind::patch);
610   q.setMatchRegex();
611   q.setCaseSensitive();
612   q.setUninstalledOnly();
613   q.setEdition(Edition("0.8.3"),Rel::NE);
614   BOOST_CHECK(q == queries[1]);
615 }
616
617 BOOST_AUTO_TEST_CASE(pool_predicated_matcher)
618 {
619   cout << "****predicated_matcher****"  << endl;
620   {
621     PoolQuery q;
622     q.setMatchExact();
623
624     q.addDependency( sat::SolvAttr::name, "zy*", Rel::ANY, Edition(), Arch_empty );
625     BOOST_CHECK_EQUAL( q.size(), 0 );
626
627     q.addDependency( sat::SolvAttr::name, "zy*", Rel::ANY, Edition(), Arch_empty, Match::GLOB );
628     BOOST_CHECK_EQUAL( q.size(), 5 ); // 5 more
629
630     q.addDependency( sat::SolvAttr::name, "^kde.*-zh", Rel::ANY, Edition(), Arch_noarch, Match::REGEX );
631     BOOST_CHECK_EQUAL( q.size(), 9 ); // 4 more
632
633     q.addDependency( sat::SolvAttr::name,     "kde.*-zh", Rel::ANY, Edition(), Arch_noarch, Match::REGEX );
634     BOOST_CHECK_EQUAL( q.size(), 10 ); // 1 more
635   }
636 }
637
638 BOOST_AUTO_TEST_CASE(pool_query_serialize)
639 {
640   std::vector<PoolQuery> queries;
641   {
642     PoolQuery q;
643     q.addString( "ma" );
644     q.addAttribute( sat::SolvAttr::name );
645     q.addRepo( "factory-nonoss" );
646     q.addRepo( "zypp_svn" );
647     queries.push_back( q );
648   }
649   {
650     PoolQuery q;
651     q.addAttribute( sat::SolvAttr::name, "ma" );
652     q.addRepo( "factory-nonoss" );
653     q.addRepo( "zypp_svn" );
654     queries.push_back( q );
655   }
656   {
657     PoolQuery q;
658     q.setMatchExact();
659     q.addAttribute( sat::SolvAttr::name,      "ma" );
660     q.addDependency( sat::SolvAttr::name,     "nn", Rel::EQ, Edition("nne-nnr"), Arch_noarch );
661     q.addDependency( sat::SolvAttr::name,     "nx", Rel::EQ, Edition("nxe-nxr"), Arch_noarch, Match::REGEX );
662     q.addDependency( sat::SolvAttr::requires, "rn", Rel::EQ, Edition("rne-rnr"), Arch_noarch );
663     q.addDependency( sat::SolvAttr::requires, "rx", Rel::EQ, Edition("rxe-rxr"), Arch_noarch, Match::GLOB );
664     queries.push_back( q );
665   }
666
667   cout << "****serialize****"  << endl;
668   //   filesystem::TmpFile testfile;
669   Pathname testfile( "/tmp/testfile" );
670   writePoolQueriesToFile( testfile, queries.begin(), queries.end() );
671
672   std::vector<PoolQuery> recovered;
673   std::insert_iterator<std::vector<PoolQuery>> ii( recovered, recovered.end() );
674   readPoolQueriesFromFile( testfile, ii );
675
676   BOOST_REQUIRE_EQUAL( queries.size(), recovered.size() );
677   for ( unsigned i = 0U; i < queries.size(); ++i )
678   {
679     BOOST_CHECK_EQUAL( queries[i], recovered[i] );
680   }
681 }
682 // test matching
683 BOOST_AUTO_TEST_CASE(pool_query_equal)
684 {
685   cout << "****equal****"  << endl;
686   std::vector<PoolQuery> v;
687   {
688     PoolQuery q;
689     v.push_back( q );
690   }
691   {
692     PoolQuery q;
693     q.addAttribute( sat::SolvAttr::name, "zypper" );
694     q.setMatchExact();
695     q.setCaseSensitive(true);
696     v.push_back( q );
697   }
698   {
699     PoolQuery q;
700     q.addAttribute( sat::SolvAttr::name, "libzypp" );   // different
701     q.setMatchExact();
702     q.setCaseSensitive(true);
703     v.push_back( q );
704   }
705   {
706     PoolQuery q;
707     q.addAttribute( sat::SolvAttr::vendor, "zypper" );  // different
708     q.setMatchExact();
709     q.setCaseSensitive(true);
710     v.push_back( q );
711   }
712   {
713     PoolQuery q;
714     q.addAttribute( sat::SolvAttr::name, "zypper" );
715     q.setMatchExact();
716     q.setCaseSensitive(false);  // different
717     v.push_back( q );
718   }
719   {
720     PoolQuery q;
721     q.addAttribute( sat::SolvAttr::name, "zypper" );
722     q.setMatchSubstring();      // different
723     q.setCaseSensitive(true);
724     v.push_back( q );
725   }
726   {
727     PoolQuery q;
728     q.addDependency( sat::SolvAttr::provides, "zypper" );
729     v.push_back( q );
730   }
731   {
732     PoolQuery q;
733     q.addDependency( sat::SolvAttr::provides, "zypper", Rel::GT, Edition("1.0")  );
734     v.push_back( q );
735   }
736   {
737     PoolQuery q;
738     q.addDependency( sat::SolvAttr::provides, "zypper", Rel::GT, Edition("2.0")  );
739     v.push_back( q );
740   }
741
742   for (size_t li = 0; li < v.size(); ++li)
743   {
744     for (size_t ri = 0; ri < v.size(); ++ri)
745     {
746       COUT << li << " <> " << ri << endl;
747       bool equal( v[li] == v[ri] );
748       bool nequal( v[li] != v[ri] );
749       BOOST_CHECK_EQUAL( equal, li==ri );
750       BOOST_CHECK_EQUAL( equal, !nequal );
751     }
752   }
753 }
754
755 /////////////////////////////////////////////////////////////////////////////
756 //  Dependency Query
757 /////////////////////////////////////////////////////////////////////////////
758
759 BOOST_AUTO_TEST_CASE(addDependency)
760 {
761   {
762     cout << "****addDependency1****"  << endl;
763     PoolQuery q;
764     q.setCaseSensitive( false );
765     q.setMatchSubstring();
766     q.addString( "libzypp" );
767     q.addDependency( sat::SolvAttr::provides, "FOO" ); // ! finds 'perl(CPAN::InfoObj)' 'foO'
768     std::for_each(q.begin(), q.end(), PrintAndCount());
769     //dumpQ( std::cout, q );
770     BOOST_CHECK_EQUAL( q.size(), 13 );
771   }
772   {
773     cout << "****addDependency2****"  << endl;
774     PoolQuery q;
775     q.setCaseSensitive( false );
776     q.setMatchSubstring();
777     q.addString( "libzypp" );
778     q.addDependency( sat::SolvAttr::provides, "FOO", Rel::GT, Edition("5.0") );
779     std::for_each(q.begin(), q.end(), PrintAndCount());
780     //dumpQ( std::cout, q );
781     BOOST_CHECK_EQUAL( q.size(), 7 );
782   }
783   {
784     cout << "****addDependency2a****"  << endl;
785     PoolQuery q;
786     q.setCaseSensitive( false );
787     q.setMatchSubstring();
788     q.addDependency( sat::SolvAttr::provides, "libzypp", Rel::GT, Edition("5.0") );
789     q.addAttribute( sat::SolvAttr::arch, Arch_i586.asString() ); // OR with arch i585
790     std::for_each(q.begin(), q.end(), PrintAndCount());
791     //dumpQ( std::cout, q );
792     BOOST_CHECK_EQUAL( q.size(), 66 );
793   }
794   {
795     cout << "****addDependency2b****"  << endl;
796     PoolQuery q;
797     q.setCaseSensitive( false );
798     q.setMatchSubstring();
799     // libzypp provides yast2-packagemanager...
800     q.addDependency( sat::SolvAttr::provides, "yast2-packagemanager", Rel::GT, Edition("5.0"), Arch_i586 ); // AND with arch i585
801     std::for_each(q.begin(), q.end(), PrintAndCount());
802     //dumpQ( std::cout, q );
803     BOOST_CHECK_EQUAL( q.size(), 2 );
804   }
805   {
806     cout << "****addDependency2c****"  << endl;
807     PoolQuery q;
808     q.setCaseSensitive( false );
809     q.setMatchSubstring();
810     // but no package named yast2-packagemanager
811     q.addDependency( sat::SolvAttr::name, "yast2-packagemanager", Rel::GT, Edition("5.0"), Arch_i586 ); // AND with arch i585
812     std::for_each(q.begin(), q.end(), PrintAndCount());
813     //dumpQ( std::cout, q );
814     BOOST_CHECK_EQUAL( q.size(), 0 );
815   }
816   {
817     cout << "****addDependency2d****"  << endl;
818     PoolQuery q;
819     q.setCaseSensitive( false );
820     q.setMatchSubstring();
821     // libzypp provides yast2-packagemanager...
822     q.addDependency( sat::SolvAttr::provides, "yast2-packagemanager", Arch_i586 ); // AND with arch i585
823     std::for_each(q.begin(), q.end(), PrintAndCount());
824     //dumpQ( std::cout, q );
825     BOOST_CHECK_EQUAL( q.size(), 2 );
826   }
827   {
828     cout << "****addDependency2e****"  << endl;
829     PoolQuery q;
830     q.setCaseSensitive( false );
831     q.setMatchSubstring();
832     // but no package named yast2-packagemanager
833     q.addDependency( sat::SolvAttr::name, "yast2-packagemanager", Arch_i586 ); // AND with arch i585
834     std::for_each(q.begin(), q.end(), PrintAndCount());
835     //dumpQ( std::cout, q );
836     BOOST_CHECK_EQUAL( q.size(), 0 );
837   }
838
839   {
840     cout << "****addDependency3****"  << endl;
841     PoolQuery q;
842     // includes wine
843     q.addDependency( sat::SolvAttr::provides, "kernel" );
844     std::for_each(q.begin(), q.end(), PrintAndCount());
845     //dumpQ( std::cout, q );
846     BOOST_CHECK_EQUAL( q.size(), 12 );
847   }
848   {
849     cout << "****addDependency4****"  << endl;
850     PoolQuery q;
851     // no wine
852     q.addDependency( sat::SolvAttr::name, "kernel" );
853     std::for_each(q.begin(), q.end(), PrintAndCount());
854     //dumpQ( std::cout, q );
855     BOOST_CHECK_EQUAL( q.size(), 11 );
856   }
857   {
858     cout << "****addDependency5****"  << endl;
859     PoolQuery q;
860     // Capability always matches exact
861     q.addDependency( sat::SolvAttr::provides, Capability("kernel") );
862     std::for_each(q.begin(), q.end(), PrintAndCount());
863     //dumpQ( std::cout, q );
864     BOOST_CHECK_EQUAL( q.size(), 2 );
865   }
866   {
867     cout << "****addDependency6****"  << endl;
868     PoolQuery q;
869     // non dependecy + Capability matches solvable name!
870     q.addDependency( sat::SolvAttr::summary, Capability("kernel") );
871     std::for_each(q.begin(), q.end(), PrintAndCount());
872     //dumpQ( std::cout, q );
873     BOOST_CHECK_EQUAL( q.size(), 0 ); // non dependecy
874   }
875 }
876
877 namespace
878 {
879   std::string q2str( const PoolQuery & q_r )
880   {
881     str::Str s;
882     q_r.serialize( s.stream() );
883     return s;
884   }
885
886   template <class OutputIterator>
887   void str2q( const std::string & s_r, OutputIterator out_r )
888   {
889     std::istringstream s( s_r );
890     do {
891       PoolQuery q;
892       if ( q.recover( s ) )
893         *out_r++ = std::move(q);
894       else
895         break;
896     } while ( true );
897   }
898
899   typedef std::set<PoolQuery> Pqs;
900
901   PoolQuery str2q( const std::string & s_r )
902   {
903     Pqs ret;
904     str2q( s_r, std::insert_iterator<Pqs>( ret, ret.end() ) );
905     return *ret.begin();
906   }
907
908
909   std::string serialized( const std::string & arg_r )
910   { return "\n" + arg_r + "\n\n"; }
911
912   template <typename... Args>
913   std::string serialized( const std::string & arg_r, Args... args_r )
914   { return "\n" + arg_r + serialized( args_r... ); }
915
916
917   void testSerializeAndBack( const PoolQuery & q_r, const PoolQuery & expect_r, bool equal_r = true )
918   {
919     static unsigned i = 0;
920
921     std::string s { q2str( q_r ) };
922     PoolQuery   q { str2q( s ) };
923     BOOST_CHECK_EQUAL( (q == expect_r), equal_r );
924
925     if ( ++i && (q == expect_r) != equal_r )
926     {
927       cout << "+++" << endl;
928       cout << q << endl;
929       cout << "=== " << i << " ^v SerializeAndBack == " << equal_r << endl;
930       cout << expect_r << endl;
931       cout << "---" << endl;
932     }
933   }
934 }
935
936 BOOST_AUTO_TEST_CASE(zypperLocksSerialize)
937 {
938   // Fix/cleanup zypper locks (old style, new stule, complex) (bsc#1112911)
939   // As you may notice: locks (by now) ignore any arch component
940   cout << "****zypperLocksSerialize****"  << endl;
941   std::string n { "n*" };
942   Rel         o { Rel::EQ };
943   Edition     e { "v", "r", 1 };
944   Arch        a { "a" };
945
946   {
947     // old style
948     // solvable_name: n*
949     PoolQuery oldq;
950     oldq.addAttribute( sat::SolvAttr::name, n );
951     testSerializeAndBack( oldq, oldq );
952
953     { // new style
954       PoolQuery q;
955       q.addDependency( sat::SolvAttr::name, n, Rel::ANY, Edition(), Arch_empty );
956       testSerializeAndBack( q, oldq );
957     }
958
959     { // new style + arch rule however stays complex
960       PoolQuery q;
961       q.addDependency( sat::SolvAttr::name, n, Rel::ANY, Edition(), a );
962       testSerializeAndBack( q, oldq, false );
963       testSerializeAndBack( q, q );
964     }
965   }
966
967   {
968     // old style
969     // solvable_name: n*
970     // version: == 1:v-r
971     PoolQuery oldq;
972     oldq.addAttribute( sat::SolvAttr::name, n );
973     oldq.setEdition( e, o );
974     testSerializeAndBack( oldq, oldq );
975
976     { // new style
977       PoolQuery q;
978       q.addDependency( sat::SolvAttr::name, n, o, e, Arch_empty );
979       testSerializeAndBack( q, oldq );
980     }
981
982     { // new style + arch rule however stays complex
983       PoolQuery q;
984       q.addDependency( sat::SolvAttr::name, n, o, e, a );
985       testSerializeAndBack( q, oldq, false );
986       testSerializeAndBack( q, q );
987     }
988   }
989 }