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