1 #include <boost/test/auto_unit_test.hpp>
2 #include "zypp/CpeId.h"
7 using zypp::SetCompare;
8 using zypp::SetRelation;
10 typedef CpeId::Value Value;
12 #define defVALUE(N,S) \
13 const std::string N##Str( S ); \
16 defVALUE( wildcardfree, "STrv\\*al\\?" ); // '\?' quoted?
17 const std::string wildcardfreeUri( "STrv%2aal%3f" );
18 const std::string wildcardfreeFs( "STrv\\*al\\?" );
20 defVALUE( wildcardfree2, "stRV\\*al\\\\\\?" ); // '\\\?' backslash, quoted?
22 defVALUE( wildcarded, "strv\\*AL?" ); // '?' ?
23 const std::string wildcardedUri( "strv%2aAL%01" );
24 const std::string wildcardedFs( "strv\\*AL?" );
26 defVALUE( wildcarded2, "strv\\*AL\\\\?" ); // '\\?' backslash, ?
30 BOOST_AUTO_TEST_CASE(cpeid_value_ANY)
32 for ( const auto & c : { Value(), Value(nullptr), Value("*"), Value::ANY } )
34 BOOST_CHECK( c.isANY() );
35 BOOST_CHECK( ! c.isNA() );
36 BOOST_CHECK( c.isLogical() );
37 BOOST_CHECK( ! c.isString() );
38 BOOST_CHECK( c == Value::ANY );
39 BOOST_CHECK( c == nullptr ); // ANY
40 BOOST_CHECK( c != Value::NA );
41 BOOST_CHECK( c != wildcardfree );
42 BOOST_CHECK( c != wildcarded );
43 BOOST_CHECK( ! c.isWildcardfree() );
44 BOOST_CHECK( ! c.isWildcarded() );
45 BOOST_CHECK_EQUAL( c.asFs(), "*" );
46 BOOST_CHECK_EQUAL( c.asUri(), "" );
47 BOOST_CHECK_EQUAL( c.asWfn(), "*" );
48 BOOST_CHECK_EQUAL( c.asString(), c.asWfn() );
52 BOOST_AUTO_TEST_CASE(cpeid_value_NA)
54 for ( const auto & c : { Value(""), Value::NA } )
56 BOOST_CHECK( ! c.isANY() );
57 BOOST_CHECK( c.isNA() );
58 BOOST_CHECK( c.isLogical() );
59 BOOST_CHECK( ! c.isString() );
60 BOOST_CHECK( c != Value::ANY );
61 BOOST_CHECK( c == Value::NA );
62 BOOST_CHECK( c == std::string() ); // NA
63 BOOST_CHECK( c == "" ); // NA
64 BOOST_CHECK( c != wildcardfree );
65 BOOST_CHECK( c != wildcarded );
66 BOOST_CHECK( ! c.isWildcardfree() );
67 BOOST_CHECK( ! c.isWildcarded() );
68 BOOST_CHECK_EQUAL( c.asFs(), "-" );
69 BOOST_CHECK_EQUAL( c.asUri(), "-" );
70 BOOST_CHECK_EQUAL( c.asWfn(), "" );
71 BOOST_CHECK_EQUAL( c.asString(), c.asWfn() );
75 BOOST_AUTO_TEST_CASE(cpeid_value_string_wildcardfree)
77 for ( const auto & c : { wildcardfree } )
79 BOOST_CHECK( ! c.isANY() );
80 BOOST_CHECK( ! c.isNA() );
81 BOOST_CHECK( ! c.isLogical() );
82 BOOST_CHECK( c.isString() );
83 BOOST_CHECK( c != Value::ANY );
84 BOOST_CHECK( c != Value::NA );
85 BOOST_CHECK( c == wildcardfree );
86 BOOST_CHECK( c == wildcardfreeStr );
87 BOOST_CHECK( c == wildcardfreeStr.c_str() );
88 BOOST_CHECK( c != wildcarded );
89 BOOST_CHECK( c.isWildcardfree() );
90 BOOST_CHECK( ! c.isWildcarded() );
91 BOOST_CHECK_EQUAL( c.asFs(), wildcardfreeFs );
92 BOOST_CHECK_EQUAL( c.asUri(), wildcardfreeUri );
93 BOOST_CHECK_EQUAL( c.asWfn(), wildcardfreeStr );
94 BOOST_CHECK_EQUAL( c.asString(), c.asWfn() );
97 BOOST_CHECK( wildcardfree2 == wildcardfree2 );
98 BOOST_CHECK( wildcardfree2 != wildcardfree );
99 BOOST_CHECK( wildcardfree2 != wildcarded );
100 BOOST_CHECK( wildcardfree2.isWildcardfree() );
101 BOOST_CHECK( ! wildcardfree2.isWildcarded() );
104 BOOST_AUTO_TEST_CASE(cpeid_value_string_wildcarded)
106 for ( const auto & c : { wildcarded } )
108 BOOST_CHECK( ! c.isANY() );
109 BOOST_CHECK( ! c.isNA() );
110 BOOST_CHECK( ! c.isLogical() );
111 BOOST_CHECK( c.isString() );
112 BOOST_CHECK( c != Value::ANY );
113 BOOST_CHECK( c != Value::NA );
114 BOOST_CHECK( c != wildcardfree );
115 BOOST_CHECK( c != wildcarded ); // !!! According to the CPE Name Matching Specification Version 2.3
116 // unquoted wildcard characters yield an undefined result (not ==).
117 BOOST_CHECK( ! c.isWildcardfree() );
118 BOOST_CHECK( c.isWildcarded() );
119 BOOST_CHECK_EQUAL( c.asFs(), wildcardedFs );
120 BOOST_CHECK_EQUAL( c.asUri(), wildcardedUri );
121 BOOST_CHECK_EQUAL( c.asWfn(), wildcardedStr );
122 BOOST_CHECK_EQUAL( c.asString(), c.asWfn() );
125 BOOST_CHECK( wildcarded2 != wildcarded2 ); // unquoted wildcard characters yield an undefined result (not ==).
126 BOOST_CHECK( wildcarded2 != wildcardfree );
127 BOOST_CHECK( wildcarded2 != wildcarded );
128 BOOST_CHECK( ! wildcarded2.isWildcardfree() );
129 BOOST_CHECK( wildcarded2.isWildcarded() );
134 BOOST_AUTO_TEST_CASE(cpeid_value_valid)
136 static const char *const hdig = "0123456789abcdef";
138 for ( char ch = 0x00; ch >= 0; ++ch )
140 // cout << "==== " << unsigned(ch) << endl;
141 char qchstr[] = { '\\', ch, '\0' };
142 std::string chstr( qchstr+1 );
143 char pchstr[] = { '%', hdig[(unsigned char)(ch)/16], hdig[(unsigned char)(ch)%16], '\0' };
147 BOOST_CHECK( Value( chstr ).isNA() );
148 BOOST_CHECK_THROW( (Value( chstr, Value::fsFormat )), std::invalid_argument );
149 BOOST_CHECK( Value( chstr, Value::uriFormat ).isANY() );
151 else if ( ch <= ' ' || '~' < ch )
153 BOOST_CHECK_THROW( (Value( chstr )), std::invalid_argument );
154 BOOST_CHECK_THROW( (Value( chstr, Value::fsFormat )), std::invalid_argument );
155 BOOST_CHECK_THROW( (Value( chstr, Value::uriFormat )), std::invalid_argument );
157 else if ( ( '0' <= ch && ch <= '9' )
158 || ( 'A' <= ch && ch <= 'Z' )
159 || ( 'a' <= ch && ch <= 'z' )
162 BOOST_CHECK( Value( chstr ).isString() );
163 BOOST_CHECK( Value( chstr, Value::fsFormat ).isString() );
164 BOOST_CHECK( Value( chstr, Value::uriFormat ).isString() );
166 BOOST_CHECK_THROW( (Value( qchstr )), std::invalid_argument );
167 BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() );
168 BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() );
170 BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() );
172 else if ( ch == '*' )
174 BOOST_CHECK( Value( chstr ).isANY() );
175 BOOST_CHECK( Value( chstr, Value::fsFormat ).isANY() );
176 BOOST_CHECK( Value( chstr, Value::uriFormat ).isString() );
178 BOOST_CHECK( Value( qchstr ).isString() );
179 BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() );
180 BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() );
182 BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() );
184 else if ( ch == '?' )
186 BOOST_CHECK( Value( chstr ).isString() );
187 BOOST_CHECK( Value( chstr, Value::fsFormat ).isString() );
188 BOOST_CHECK( Value( chstr, Value::uriFormat ).isString() );
190 BOOST_CHECK( Value( qchstr ).isString() );
191 BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() );
192 BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() );
194 BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() );
196 else if ( ch == '-' )
198 BOOST_CHECK_THROW( (Value( chstr )), std::invalid_argument );
199 BOOST_CHECK( Value( chstr, Value::fsFormat ).isNA() );
200 BOOST_CHECK( Value( chstr, Value::uriFormat ).isNA() );
202 BOOST_CHECK_THROW( (Value( qchstr )), std::invalid_argument );
203 BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() );
204 BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() );
206 BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() );
208 else if ( ch == '\\' )
210 BOOST_CHECK_THROW( (Value( chstr )), std::invalid_argument );
211 BOOST_CHECK_THROW( (Value( chstr, Value::fsFormat )), std::invalid_argument );
212 BOOST_CHECK( (Value( chstr, Value::uriFormat )).isString() );
214 BOOST_CHECK( Value( qchstr ).isString() );
215 BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() );
216 BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() );
218 BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() );
222 BOOST_CHECK_THROW( (Value( chstr )), std::invalid_argument );
223 Value f( chstr, Value::fsFormat );
224 BOOST_CHECK( f.isString() );
225 Value u( chstr, Value::uriFormat );
226 BOOST_CHECK( u.isString() );
228 BOOST_CHECK_EQUAL( f.asString(), u.asString() );
231 BOOST_CHECK_EQUAL( f.asFs(), chstr );
232 BOOST_CHECK_EQUAL( f.asUri(), chstr );
236 BOOST_CHECK_EQUAL( f.asFs(), qchstr );
237 BOOST_CHECK_EQUAL( f.asUri(), pchstr );
240 BOOST_CHECK( Value( qchstr ).isString() );
241 BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() );
242 BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() );
244 BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() );
248 BOOST_CHECK_THROW( Value( "\\!\\a\\-\\_\\.\\!" ), std::invalid_argument );
249 BOOST_CHECK_EQUAL( Value( "\\!\\a\\-\\_\\.\\!", Value::fsFormat ).asFs(), "\\!a-_.\\!" );
252 BOOST_AUTO_TEST_CASE(cpeid_type_checks)
254 for ( const auto & c : { Value::ANY, Value::NA, wildcardfree, wildcarded } )
256 BOOST_CHECK_EQUAL( c.isANY(), c.type() == Value::Type::ANY );
257 BOOST_CHECK_EQUAL( c.isNA(), c.type() == Value::Type::NA );
258 BOOST_CHECK_EQUAL( c.isWildcardfree(), c.type() == Value::Type::wildcardfree );
259 BOOST_CHECK_EQUAL( c.isWildcarded(), c.type() == Value::Type::wildcarded );
260 BOOST_CHECK_EQUAL( c.isLogical(), c.isLogical( c.type() ) );
261 BOOST_CHECK_EQUAL( c.isString(), c.isString( c.type() ) );
262 BOOST_CHECK_EQUAL( c.isLogical(), ! c.isString() );
266 BOOST_AUTO_TEST_CASE(cpeid_compare)
268 BOOST_CHECK( compare( Value::ANY, Value::ANY, SetCompare::equal ) );
269 BOOST_CHECK( compare( Value::ANY, Value::NA, SetCompare::properSuperset ) );
270 BOOST_CHECK( compare( Value::ANY, wildcardfree, SetCompare::properSuperset ) );
271 BOOST_CHECK( compare( Value::ANY, wildcarded, SetCompare::uncomparable ) );
273 BOOST_CHECK( compare( Value::NA, Value::ANY, SetCompare::properSubset ) );
274 BOOST_CHECK( compare( Value::NA, Value::NA, SetCompare::equal ) );
275 BOOST_CHECK( compare( Value::NA, wildcardfree, SetCompare::disjoint ) );
276 BOOST_CHECK( compare( Value::NA, wildcarded, SetCompare::uncomparable ) );
278 BOOST_CHECK( compare( wildcardfree, Value::ANY, SetCompare::properSubset ) );
279 BOOST_CHECK( compare( wildcardfree, Value::NA, SetCompare::disjoint ) );
280 //BOOST_CHECK( compare( wildcardfree, wildcardfree, _NeedsCloserLook, // equal or disjoint
281 BOOST_CHECK( compare( wildcardfree, wildcardfree, SetCompare::equal ) );
282 BOOST_CHECK( compare( wildcardfree, wildcardfree2, SetCompare::disjoint ) );
283 BOOST_CHECK( compare( wildcardfree, wildcarded, SetCompare::uncomparable ) );
285 BOOST_CHECK( compare( wildcarded, Value::ANY, SetCompare::properSubset ) );
286 BOOST_CHECK( compare( wildcarded, Value::NA, SetCompare::disjoint ) );
287 //BOOST_CHECK( compare( wildcarded, wildcardfree, _NeedsCloserLook, // superset or disjoint
288 BOOST_CHECK( compare( wildcarded, wildcardfree, SetCompare::properSuperset ) );
289 BOOST_CHECK( compare( wildcarded, wildcardfree2, SetCompare::disjoint ) );
290 BOOST_CHECK( compare( wildcarded, wildcarded, SetCompare::uncomparable ) );
294 BOOST_AUTO_TEST_CASE(cpeid_value_string_wildcard)
296 for ( const auto & c : { Value( "a" ), Value( "\\*" ), Value( "\\?" ) } )
298 BOOST_CHECK( c.isWildcardfree() );
299 BOOST_CHECK( !c.isWildcarded() );
302 for ( const auto & c : { Value( "*\\*" ), Value( "\\**" ), Value( "?" ), Value( "??\\?" ), Value( "\\???" ) } )
304 BOOST_CHECK( !c.isWildcardfree() );
305 BOOST_CHECK( c.isWildcarded() );
309 ///////////////////////////////////////////////////////////////////
310 ///////////////////////////////////////////////////////////////////
312 BOOST_AUTO_TEST_CASE(cpeid_basics)
314 BOOST_CHECK_THROW( CpeId( "malformed" ), std::invalid_argument );
315 CpeId none( "malformed", CpeId::noThrow );
317 for ( const auto & c : { CpeId(), CpeId( nullptr ), CpeId( "" ), CpeId( std::string() ) } )
319 BOOST_CHECK( ! c ); // evaluate false in boolean context
320 BOOST_CHECK_EQUAL( c.asString(), c.asFs() );
321 BOOST_CHECK_EQUAL( c.asFs(), "cpe:2.3:*:*:*:*:*:*:*:*:*:*:*" );
322 BOOST_CHECK_EQUAL( c.asUri(), "cpe:/" );
323 BOOST_CHECK_EQUAL( c.asWfn(), "wfn:[]" );
324 BOOST_CHECK_EQUAL( c, none ); // matching!!
327 for ( const auto & c : { CpeId( "cpe:/o:sle" ), CpeId( "cpe:/o:*" ) } )
329 BOOST_CHECK( c ); // evaluate true in boolean context
330 BOOST_CHECK( ! c.asString().empty() );// empty string rep
331 BOOST_CHECK_EQUAL( c, c ); // matching!!
335 void testStrconv( const std::string & fs, const std::string & uri, const std::string & wfn )
338 CpeId fromURI( uri );
340 BOOST_CHECK_EQUAL( fromFS, fromURI );
342 for ( const auto & c : { fromFS, fromURI } )
344 BOOST_CHECK_EQUAL( c.asFs(), fs );
345 BOOST_CHECK_EQUAL( c.asUri(), uri );
346 BOOST_CHECK_EQUAL( c.asWfn(), wfn );
350 BOOST_AUTO_TEST_CASE(cpeid_strconv)
352 // colon embedded in product value
353 testStrconv ( "cpe:2.3:a:opensuse:lib\\:zypp:14.16.0:beta:*:*:*:*:*:-",
354 "cpe:/a:opensuse:lib%3azypp:14.16.0:beta:~~~~~-",
355 "wfn:[part=\"a\",vendor=\"opensuse\",product=\"lib\\:zypp\",version=\"14\\.16\\.0\",update=\"beta\",other=NA]" );
357 testStrconv ( "cpe:2.3:a:hp:insight_diagnostics:7.4.0.1570:-:*:*:online:win2003:x64:*",
358 "cpe:/a:hp:insight_diagnostics:7.4.0.1570:-:~~online~win2003~x64~",
359 "wfn:[part=\"a\",vendor=\"hp\",product=\"insight_diagnostics\",version=\"7\\.4\\.0\\.1570\",update=NA,sw_edition=\"online\",target_sw=\"win2003\",target_hw=\"x64\"]" );
361 testStrconv ( "cpe:2.3:a:hp:openview_network_manager:7.51:*:*:*:*:linux:*:*",
362 "cpe:/a:hp:openview_network_manager:7.51::~~~linux~~",
363 "wfn:[part=\"a\",vendor=\"hp\",product=\"openview_network_manager\",version=\"7\\.51\",target_sw=\"linux\"]" );
365 testStrconv ( "cpe:2.3:a:foo\\\\bar:big\\$money_manager_2010:*:*:*:*:special:ipod_touch:80gb:*",
366 "cpe:/a:foo%5cbar:big%24money_manager_2010:::~~special~ipod_touch~80gb~",
367 "wfn:[part=\"a\",vendor=\"foo\\\\bar\",product=\"big\\$money_manager_2010\",sw_edition=\"special\",target_sw=\"ipod_touch\",target_hw=\"80gb\"]" );
369 BOOST_CHECK_THROW( (CpeId( "cpe:/x:" )), std::invalid_argument ); // illegal part 'x'
370 BOOST_CHECK_THROW( CpeId( "cpe:/a:foo%5cbar:big%24money_2010%07:::~~special~ipod_touch~80gb~" ), std::invalid_argument ); // illegal %07
371 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
374 BOOST_AUTO_TEST_CASE(cpeid_matches)
376 CpeId sle( "cpe:/o:sles" );
377 CpeId win( "cpe:/o:windows" );
379 CpeId ons( "cpe:2.3:o:??????s" );
381 BOOST_CHECK_EQUAL( compare( sle, win ), SetRelation::disjoint );
383 BOOST_CHECK_EQUAL( compare( sle, any ), SetRelation::subset );
384 BOOST_CHECK_EQUAL( compare( win, any ), SetRelation::subset );
386 BOOST_CHECK_EQUAL( compare( any, sle ), SetRelation::superset );
387 BOOST_CHECK_EQUAL( compare( any, win ), SetRelation::superset );
389 BOOST_CHECK_EQUAL( compare( sle, ons ), SetRelation::uncomparable );
390 BOOST_CHECK_EQUAL( compare( win, ons ), SetRelation::uncomparable );
392 BOOST_CHECK_EQUAL( compare( ons, sle ), SetRelation::superset );
393 BOOST_CHECK_EQUAL( compare( ons, win ), SetRelation::superset );