2322b49400065e4ec16d67e95c6cc0dc21ab1a87
[platform/upstream/libzypp.git] / tests / zypp / CpeId_test.cc
1 #include <boost/test/auto_unit_test.hpp>
2 #include <iostream>
3 #include "zypp/CpeId.h"
4
5 using std::cout;
6 using std::endl;
7
8 using zypp::SetCompare;
9 using zypp::SetRelation;
10 using zypp::CpeId;
11 typedef CpeId::Value Value;
12
13 ///////////////////////////////////////////////////////////////////
14 /// Symmetric attribute compare if wildcards are involved!
15 /// The specs define any comarison with a wildcarded attribute as
16 /// target to return \c uncomparable:
17 /// \code
18 ///    wildcardfree  <=>  wildcarded    ==>  uncomparable,
19 ///    wildcarded    <=>  wildcardfree  ==>  superset or disjoint
20 /// \endcode
21 /// But a symmetric result is much more intuitive:
22 /// \code
23 ///    wildcardfree  <=>  wildcarded    ==>  subset or disjoint
24 ///    wildcarded    <=>  wildcardfree  ==>  superset or disjoint
25 /// \endcode
26 ///////////////////////////////////////////////////////////////////
27 #define WFN_STRICT_SPEC 0
28
29 #define defVALUE(N,S)                   \
30   const std::string N##Str( S );        \
31   Value N( N##Str );
32
33 defVALUE( wildcardfree,                 "STrv\\*al\\?" );       // '\?'         quoted?
34 const std::string wildcardfreeUri(      "STrv%2aal%3f" );
35 const std::string wildcardfreeFs(       "STrv\\*al\\?" );
36
37 defVALUE( wildcardfree2,                "stRV\\*al\\\\\\?" );   // '\\\?'       backslash, quoted?
38
39 defVALUE( wildcarded,                   "strv\\*AL?" );         // '?'          ?
40 const std::string wildcardedUri(        "strv%2aAL%01" );
41 const std::string wildcardedFs(         "strv\\*AL?" );
42
43 defVALUE( wildcarded2,                  "strv\\*AL\\\\?" );     // '\\?'        backslash, ?
44
45
46
47 BOOST_AUTO_TEST_CASE(cpeid_value_ANY)
48 {
49   for ( const auto & c : { Value(), Value(nullptr), Value("*"), Value::ANY } )
50   {
51     BOOST_CHECK( c.isANY() );
52     BOOST_CHECK( ! c.isNA() );
53     BOOST_CHECK( c.isLogical() );
54     BOOST_CHECK( ! c.isString() );
55     BOOST_CHECK( c == Value::ANY );
56     BOOST_CHECK( c == nullptr );        // ANY
57     BOOST_CHECK( c != Value::NA );
58     BOOST_CHECK( c != wildcardfree );
59     BOOST_CHECK( c != wildcarded );
60     BOOST_CHECK( ! c.isWildcardfree() );
61     BOOST_CHECK( ! c.isWildcarded() );
62     BOOST_CHECK_EQUAL( c.asFs(), "*" );
63     BOOST_CHECK_EQUAL( c.asUri(), "" );
64     BOOST_CHECK_EQUAL( c.asWfn(), "*" );
65     BOOST_CHECK_EQUAL( c.asString(), c.asWfn() );
66   }
67 }
68
69 BOOST_AUTO_TEST_CASE(cpeid_value_NA)
70 {
71   for ( const auto & c : { Value(""), Value::NA } )
72   {
73     BOOST_CHECK( ! c.isANY() );
74     BOOST_CHECK( c.isNA() );
75     BOOST_CHECK( c.isLogical() );
76     BOOST_CHECK( ! c.isString() );
77     BOOST_CHECK( c != Value::ANY );
78     BOOST_CHECK( c == Value::NA );
79     BOOST_CHECK( c == std::string() );  // NA
80     BOOST_CHECK( c == "" );             // NA
81     BOOST_CHECK( c != wildcardfree );
82     BOOST_CHECK( c != wildcarded );
83     BOOST_CHECK( ! c.isWildcardfree() );
84     BOOST_CHECK( ! c.isWildcarded() );
85     BOOST_CHECK_EQUAL( c.asFs(), "-" );
86     BOOST_CHECK_EQUAL( c.asUri(), "-" );
87     BOOST_CHECK_EQUAL( c.asWfn(), "" );
88     BOOST_CHECK_EQUAL( c.asString(), c.asWfn() );
89   }
90 }
91
92 BOOST_AUTO_TEST_CASE(cpeid_value_string_wildcardfree)
93 {
94   for ( const auto & c : { wildcardfree } )
95   {
96     BOOST_CHECK( ! c.isANY() );
97     BOOST_CHECK( ! c.isNA() );
98     BOOST_CHECK( ! c.isLogical() );
99     BOOST_CHECK( c.isString() );
100     BOOST_CHECK( c != Value::ANY );
101     BOOST_CHECK( c != Value::NA );
102     BOOST_CHECK( c == wildcardfree );
103     BOOST_CHECK( c == wildcardfreeStr );
104     BOOST_CHECK( c == wildcardfreeStr.c_str() );
105     BOOST_CHECK( c != wildcarded );
106     BOOST_CHECK( c.isWildcardfree() );
107     BOOST_CHECK( ! c.isWildcarded() );
108     BOOST_CHECK_EQUAL( c.asFs(), wildcardfreeFs );
109     BOOST_CHECK_EQUAL( c.asUri(), wildcardfreeUri );
110     BOOST_CHECK_EQUAL( c.asWfn(), wildcardfreeStr );
111     BOOST_CHECK_EQUAL( c.asString(), c.asWfn() );
112   }
113
114   BOOST_CHECK( wildcardfree2 == wildcardfree2 );
115   BOOST_CHECK( wildcardfree2 != wildcardfree );
116   BOOST_CHECK( wildcardfree2 != wildcarded );
117   BOOST_CHECK( wildcardfree2.isWildcardfree() );
118   BOOST_CHECK( ! wildcardfree2.isWildcarded() );
119 }
120
121 BOOST_AUTO_TEST_CASE(cpeid_value_string_wildcarded)
122 {
123   for ( const auto & c : { wildcarded } )
124   {
125     BOOST_CHECK( ! c.isANY() );
126     BOOST_CHECK( ! c.isNA() );
127     BOOST_CHECK( ! c.isLogical() );
128     BOOST_CHECK( c.isString() );
129     BOOST_CHECK( c != Value::ANY );
130     BOOST_CHECK( c != Value::NA );
131     BOOST_CHECK( c != wildcardfree );
132 #if WFN_STRICT_SPEC
133     BOOST_CHECK( c != wildcarded );     // !!! According to the CPE Name Matching Specification Version 2.3
134                                         // unquoted wildcard characters yield an undefined result (not ==).
135 #else
136     BOOST_CHECK( c == wildcarded );
137 #endif
138     BOOST_CHECK( ! c.isWildcardfree() );
139     BOOST_CHECK( c.isWildcarded() );
140     BOOST_CHECK_EQUAL( c.asFs(), wildcardedFs );
141     BOOST_CHECK_EQUAL( c.asUri(), wildcardedUri );
142     BOOST_CHECK_EQUAL( c.asWfn(), wildcardedStr );
143     BOOST_CHECK_EQUAL( c.asString(), c.asWfn() );
144   }
145
146 #if WFN_STRICT_SPEC
147   BOOST_CHECK( wildcarded2 != wildcarded2 );    // unquoted wildcard characters yield an undefined result (not ==).
148 #else
149   BOOST_CHECK( wildcarded2 == wildcarded2 );
150 #endif
151   BOOST_CHECK( wildcarded2 != wildcardfree );
152   BOOST_CHECK( wildcarded2 != wildcarded );
153   BOOST_CHECK( ! wildcarded2.isWildcardfree() );
154   BOOST_CHECK( wildcarded2.isWildcarded() );
155
156
157 }
158
159 BOOST_AUTO_TEST_CASE(cpeid_value_valid)
160 {
161   static const char *const hdig = "0123456789abcdef";
162
163   for ( char ch = 0; ch < CHAR_MAX; ++ch )
164   {
165     // cout << "==== " << unsigned(ch) << endl;
166     char qchstr[] = { '\\', ch, '\0' };
167     std::string chstr( qchstr+1 );
168     char pchstr[] = { '%', hdig[(unsigned char)(ch)/16], hdig[(unsigned char)(ch)%16], '\0' };
169
170     if ( ch == '\0' )
171     {
172       BOOST_CHECK( Value( chstr ).isNA() );
173       BOOST_CHECK_THROW( (Value( chstr, Value::fsFormat )), std::invalid_argument );
174       BOOST_CHECK( Value( chstr, Value::uriFormat ).isANY() );
175     }
176     else if ( ch <= ' ' || '~' < ch )
177     {
178       BOOST_CHECK_THROW( (Value( chstr )), std::invalid_argument );
179       BOOST_CHECK_THROW( (Value( chstr, Value::fsFormat )), std::invalid_argument );
180       BOOST_CHECK_THROW( (Value( chstr, Value::uriFormat )), std::invalid_argument );
181     }
182     else if ( ( '0' <= ch && ch <= '9' )
183            || ( 'A' <= ch && ch <= 'Z' )
184            || ( 'a' <= ch && ch <= 'z' )
185            || ch == '_' )
186     {
187       BOOST_CHECK( Value( chstr ).isString() );
188       BOOST_CHECK( Value( chstr, Value::fsFormat ).isString() );
189       BOOST_CHECK( Value( chstr, Value::uriFormat ).isString() );
190
191       BOOST_CHECK_THROW( (Value( qchstr )), std::invalid_argument );
192       BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() );
193       BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() );
194
195       BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() );
196     }
197     else if ( ch == '*' )
198     {
199       BOOST_CHECK( Value( chstr ).isANY() );
200       BOOST_CHECK( Value( chstr, Value::fsFormat ).isANY() );
201       BOOST_CHECK( Value( chstr, Value::uriFormat ).isString() );
202
203       BOOST_CHECK( Value( qchstr ).isString() );
204       BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() );
205       BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() );
206
207       BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() );
208     }
209     else if ( ch == '?' )
210     {
211       BOOST_CHECK( Value( chstr ).isString() );
212       BOOST_CHECK( Value( chstr, Value::fsFormat ).isString() );
213       BOOST_CHECK( Value( chstr, Value::uriFormat ).isString() );
214
215       BOOST_CHECK( Value( qchstr ).isString() );
216       BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() );
217       BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() );
218
219       BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() );
220     }
221     else if ( ch == '-' )
222     {
223       BOOST_CHECK_THROW( (Value( chstr )), std::invalid_argument );
224       BOOST_CHECK( Value( chstr, Value::fsFormat ).isNA() );
225       BOOST_CHECK( Value( chstr, Value::uriFormat ).isNA() );
226
227       BOOST_CHECK_THROW( (Value( qchstr )), std::invalid_argument );
228       BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() );
229       BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() );
230
231       BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() );
232     }
233     else if ( ch == '\\' )
234     {
235       BOOST_CHECK_THROW( (Value( chstr )), std::invalid_argument );
236       BOOST_CHECK_THROW( (Value( chstr, Value::fsFormat )), std::invalid_argument );
237       BOOST_CHECK( (Value( chstr, Value::uriFormat )).isString() );
238
239       BOOST_CHECK( Value( qchstr ).isString() );
240       BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() );
241       BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() );
242
243       BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() );
244     }
245     else
246     {
247       BOOST_CHECK_THROW( (Value( chstr )), std::invalid_argument );
248       Value f( chstr, Value::fsFormat );
249       BOOST_CHECK( f.isString() );
250       Value u( chstr, Value::uriFormat );
251       BOOST_CHECK( u.isString() );
252
253       BOOST_CHECK_EQUAL( f.asString(), u.asString() );
254       if ( ch == '.' )
255       {
256         BOOST_CHECK_EQUAL( f.asFs(), chstr );
257         BOOST_CHECK_EQUAL( f.asUri(), chstr );
258       }
259       else
260       {
261         BOOST_CHECK_EQUAL( f.asFs(), qchstr );
262         BOOST_CHECK_EQUAL( f.asUri(), pchstr );
263       }
264
265       BOOST_CHECK( Value( qchstr ).isString() );
266       BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() );
267       BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() );
268
269       BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() );
270     }
271   }
272
273   BOOST_CHECK_THROW( Value( "\\!\\a\\-\\_\\.\\!" ), std::invalid_argument );
274   BOOST_CHECK_EQUAL( Value( "\\!\\a\\-\\_\\.\\!", Value::fsFormat ).asFs(), "\\!a-_.\\!" );
275 }
276
277 BOOST_AUTO_TEST_CASE(cpeid_type_checks)
278 {
279   for ( const auto & c : { Value::ANY, Value::NA, wildcardfree, wildcarded } )
280   {
281     BOOST_CHECK_EQUAL( c.isANY(),               c.type() == Value::Type::ANY );
282     BOOST_CHECK_EQUAL( c.isNA(),                c.type() == Value::Type::NA );
283     BOOST_CHECK_EQUAL( c.isWildcardfree(),      c.type() == Value::Type::wildcardfree );
284     BOOST_CHECK_EQUAL( c.isWildcarded(),        c.type() == Value::Type::wildcarded );
285     BOOST_CHECK_EQUAL( c.isLogical(),           c.isLogical( c.type() ) );
286     BOOST_CHECK_EQUAL( c.isString(),            c.isString( c.type() ) );
287     BOOST_CHECK_EQUAL( c.isLogical(),           ! c.isString() );
288   }
289 }
290
291 BOOST_AUTO_TEST_CASE(cpeid_compare)
292 {
293   BOOST_CHECK( compare( Value::ANY,     Value::ANY,     SetCompare::equal               ) );
294   BOOST_CHECK( compare( Value::ANY,     Value::NA,      SetCompare::properSuperset      ) );
295   BOOST_CHECK( compare( Value::ANY,     wildcardfree,   SetCompare::properSuperset      ) );
296 #if WFN_STRICT_SPEC
297   BOOST_CHECK( compare( Value::ANY,     wildcarded,     SetCompare::uncomparable        ) );
298 #else
299   BOOST_CHECK( compare( Value::ANY,     wildcarded,     SetCompare::properSuperset      ) );
300 #endif
301
302   BOOST_CHECK( compare( Value::NA,      Value::ANY,     SetCompare::properSubset        ) );
303   BOOST_CHECK( compare( Value::NA,      Value::NA,      SetCompare::equal               ) );
304   BOOST_CHECK( compare( Value::NA,      wildcardfree,   SetCompare::disjoint            ) );
305 #if WFN_STRICT_SPEC
306   BOOST_CHECK( compare( Value::NA,      wildcarded,     SetCompare::uncomparable        ) );
307 #else
308   BOOST_CHECK( compare( Value::NA,      wildcarded,     SetCompare::disjoint            ) );
309 #endif
310
311   BOOST_CHECK( compare( wildcardfree,   Value::ANY,     SetCompare::properSubset        ) );
312   BOOST_CHECK( compare( wildcardfree,   Value::NA,      SetCompare::disjoint            ) );
313   //BOOST_CHECK( compare( wildcardfree, wildcardfree,   _NeedsCloserLook,       // equal or disjoint
314   BOOST_CHECK( compare( wildcardfree,   wildcardfree,   SetCompare::equal               ) );
315   BOOST_CHECK( compare( wildcardfree,   wildcardfree2,  SetCompare::disjoint            ) );
316 #if WFN_STRICT_SPEC
317   BOOST_CHECK( compare( wildcardfree,   wildcarded,     SetCompare::uncomparable        ) );
318 #else
319   //BOOST_CHECK( compare( wildcardfree, wildcarded,     _NeedsCloserLook,       // subset or disjoint
320   BOOST_CHECK( compare( wildcardfree,   wildcarded,     SetCompare::properSubset        ) );
321   BOOST_CHECK( compare( wildcardfree,   wildcarded2,    SetCompare::disjoint            ) );
322 #endif
323
324   BOOST_CHECK( compare( wildcarded,     Value::ANY,     SetCompare::properSubset        ) );
325   BOOST_CHECK( compare( wildcarded,     Value::NA,      SetCompare::disjoint            ) );
326   //BOOST_CHECK( compare( wildcarded,   wildcardfree,   _NeedsCloserLook,       // superset or disjoint
327   BOOST_CHECK( compare( wildcarded,     wildcardfree,   SetCompare::properSuperset      ) );
328   BOOST_CHECK( compare( wildcarded,     wildcardfree2,  SetCompare::disjoint            ) );
329 #if WFN_STRICT_SPEC
330   BOOST_CHECK( compare( wildcarded,     wildcarded,     SetCompare::uncomparable        ) );
331 #else
332   //BOOST_CHECK( compare( wildcarded,   wildcarded,     _NeedsCloserLook,       // equal or uncomparable
333   BOOST_CHECK( compare( wildcarded,     wildcarded,     SetCompare::equal               ) );
334   BOOST_CHECK( compare( wildcarded,     wildcarded2,    SetCompare::uncomparable        ) );
335 #endif
336 }
337
338
339 BOOST_AUTO_TEST_CASE(cpeid_value_string_wildcard)
340 {
341   for ( const auto & c : { Value( "a" ), Value( "\\*" ), Value( "\\?" ) } )
342   {
343     BOOST_CHECK( c.isWildcardfree() );
344     BOOST_CHECK( !c.isWildcarded() );
345   }
346
347   for ( const auto & c : { Value( "*\\*" ), Value( "\\**" ), Value( "?" ), Value( "??\\?" ), Value( "\\???" ) } )
348   {
349     BOOST_CHECK( !c.isWildcardfree() );
350     BOOST_CHECK( c.isWildcarded() );
351   }
352 }
353
354 ///////////////////////////////////////////////////////////////////
355 ///////////////////////////////////////////////////////////////////
356
357 BOOST_AUTO_TEST_CASE(cpeid_basics)
358 {
359   BOOST_CHECK_THROW( CpeId( "malformed" ), std::invalid_argument );
360   CpeId none( "malformed", CpeId::noThrow );
361   BOOST_CHECK_EQUAL( CpeId::NoThrowType::lastMalformed, "malformed" );
362   CpeId( "", CpeId::noThrow );
363   BOOST_CHECK_EQUAL( CpeId::NoThrowType::lastMalformed, "" );
364
365   for ( const auto & c : { CpeId(), CpeId( nullptr ), CpeId( "" ), CpeId( std::string() ), CpeId( "cpe:2.3:" ), CpeId( "cpe:/" ) } )
366   {
367     BOOST_CHECK( ! c );                 // evaluate false in boolean context
368     BOOST_CHECK_EQUAL( c.asString(), c.asFs() );
369     BOOST_CHECK_EQUAL( c.asFs(),  "cpe:2.3:*:*:*:*:*:*:*:*:*:*:*" );
370     BOOST_CHECK_EQUAL( c.asUri(), "cpe:/" );
371     BOOST_CHECK_EQUAL( c.asWfn(), "wfn:[]" );
372     BOOST_CHECK_EQUAL( c, none );       // matching!!
373   }
374
375   for ( const auto & c : { CpeId( "cpe:/o:sle" ), CpeId( "cpe:/o:*" ) } )
376   {
377     BOOST_CHECK( c );                   // evaluate true in boolean context
378     BOOST_CHECK( ! c.asString().empty() );// empty string rep
379     BOOST_CHECK_EQUAL( c, c );          // matching!!
380   }
381 }
382
383 void testStrconv( const std::string & fs, const std::string & uri, const std::string & wfn )
384 {
385   CpeId fromFS( fs ) ;
386   CpeId fromURI( uri );
387
388   BOOST_CHECK_EQUAL( fromFS, fromURI );
389
390   for ( const auto & c : { fromFS, fromURI } )
391   {
392     BOOST_CHECK_EQUAL( c.asFs(), fs );
393     BOOST_CHECK_EQUAL( c.asUri(), uri );
394     BOOST_CHECK_EQUAL( c.asWfn(), wfn );
395   }
396 }
397
398 BOOST_AUTO_TEST_CASE(cpeid_strconv)
399 {
400   // colon embedded in product value
401   testStrconv ( "cpe:2.3:a:opensuse:lib\\:zypp:14.16.0:beta:*:*:*:*:*:-",
402                 "cpe:/a:opensuse:lib%3azypp:14.16.0:beta:~~~~~-",
403                 "wfn:[part=\"a\",vendor=\"opensuse\",product=\"lib\\:zypp\",version=\"14\\.16\\.0\",update=\"beta\",other=NA]" );
404
405   testStrconv ( "cpe:2.3:a:hp:insight_diagnostics:7.4.0.1570:-:*:*:online:win2003:x64:*",
406                 "cpe:/a:hp:insight_diagnostics:7.4.0.1570:-:~~online~win2003~x64~",
407                 "wfn:[part=\"a\",vendor=\"hp\",product=\"insight_diagnostics\",version=\"7\\.4\\.0\\.1570\",update=NA,sw_edition=\"online\",target_sw=\"win2003\",target_hw=\"x64\"]" );
408
409   testStrconv ( "cpe:2.3:a:hp:openview_network_manager:7.51:*:*:*:*:linux:*:*",
410                 "cpe:/a:hp:openview_network_manager:7.51::~~~linux~~",
411                 "wfn:[part=\"a\",vendor=\"hp\",product=\"openview_network_manager\",version=\"7\\.51\",target_sw=\"linux\"]" );
412
413   testStrconv ( "cpe:2.3:a:foo\\\\bar:big\\$money_manager_2010:*:*:*:*:special:ipod_touch:80gb:*",
414                 "cpe:/a:foo%5cbar:big%24money_manager_2010:::~~special~ipod_touch~80gb~",
415                 "wfn:[part=\"a\",vendor=\"foo\\\\bar\",product=\"big\\$money_manager_2010\",sw_edition=\"special\",target_sw=\"ipod_touch\",target_hw=\"80gb\"]" );
416
417   BOOST_CHECK_THROW( (CpeId( "cpe:/x:" )), std::invalid_argument );     // illegal part 'x'
418   BOOST_CHECK_THROW( CpeId( "cpe:/a:foo%5cbar:big%24money_2010%07:::~~special~ipod_touch~80gb~" ), std::invalid_argument );     // illegal %07
419   BOOST_CHECK_EQUAL( CpeId( "cpe:/a:foo~bar:big%7emoney_2010" ).asUri(), "cpe:/a:foo%7ebar:big%7emoney_2010" ); // unescaped ~ is ok but not preferred
420 }
421
422 BOOST_AUTO_TEST_CASE(cpeid_matches)
423 {
424   CpeId sle( "cpe:/o:sles" );
425   CpeId win( "cpe:/o:windows" );
426   CpeId any;
427   CpeId ons( "cpe:2.3:o:??????s" );
428   CpeId oops( "cpe:2.3:o:?????s" );
429
430   BOOST_CHECK_EQUAL( compare( sle, win ), SetRelation::disjoint );
431
432   BOOST_CHECK_EQUAL( compare( sle, any ), SetRelation::subset );
433   BOOST_CHECK_EQUAL( compare( win, any ), SetRelation::subset );
434
435   BOOST_CHECK_EQUAL( compare( any, sle ), SetRelation::superset );
436   BOOST_CHECK_EQUAL( compare( any, win ), SetRelation::superset );
437
438 #if WFN_STRICT_SPEC
439   BOOST_CHECK_EQUAL( compare( sle, ons ), SetRelation::uncomparable );
440   BOOST_CHECK_EQUAL( compare( win, ons ), SetRelation::uncomparable );
441 #else
442   BOOST_CHECK_EQUAL( compare( sle, ons ), SetRelation::subset );
443   BOOST_CHECK_EQUAL( compare( win, ons ), SetRelation::subset );
444 #endif
445
446   BOOST_CHECK_EQUAL( compare( ons, sle ), SetRelation::superset );
447   BOOST_CHECK_EQUAL( compare( ons, win ), SetRelation::superset );
448
449   BOOST_CHECK_EQUAL( compare( oops, sle ), SetRelation::superset );
450   BOOST_CHECK_EQUAL( compare( oops, win ), SetRelation::disjoint );
451
452 }