1# 2# BitBake Tests for the Data Store (data.py/data_smart.py) 3# 4# Copyright (C) 2010 Chris Larson 5# Copyright (C) 2012 Richard Purdie 6# 7# SPDX-License-Identifier: GPL-2.0-only 8# 9 10import unittest 11import bb 12import bb.data 13import bb.parse 14import logging 15import os 16 17class LogRecord(): 18 def __enter__(self): 19 logs = [] 20 class LogHandler(logging.Handler): 21 def emit(self, record): 22 logs.append(record) 23 logger = logging.getLogger("BitBake") 24 handler = LogHandler() 25 self.handler = handler 26 logger.addHandler(handler) 27 return logs 28 def __exit__(self, type, value, traceback): 29 logger = logging.getLogger("BitBake") 30 logger.removeHandler(self.handler) 31 return 32 33def logContains(item, logs): 34 for l in logs: 35 m = l.getMessage() 36 if item in m: 37 return True 38 return False 39 40class DataExpansions(unittest.TestCase): 41 def setUp(self): 42 self.d = bb.data.init() 43 self.d["foo"] = "value_of_foo" 44 self.d["bar"] = "value_of_bar" 45 self.d["value_of_foo"] = "value_of_'value_of_foo'" 46 47 def test_one_var(self): 48 val = self.d.expand("${foo}") 49 self.assertEqual(str(val), "value_of_foo") 50 51 def test_indirect_one_var(self): 52 val = self.d.expand("${${foo}}") 53 self.assertEqual(str(val), "value_of_'value_of_foo'") 54 55 def test_indirect_and_another(self): 56 val = self.d.expand("${${foo}} ${bar}") 57 self.assertEqual(str(val), "value_of_'value_of_foo' value_of_bar") 58 59 def test_python_snippet(self): 60 val = self.d.expand("${@5*12}") 61 self.assertEqual(str(val), "60") 62 63 def test_python_snippet_w_dict(self): 64 val = self.d.expand("${@{ 'green': 1, 'blue': 2 }['green']}") 65 self.assertEqual(str(val), "1") 66 67 def test_python_unexpanded_multi(self): 68 self.d.setVar("bar", "${unsetvar}") 69 val = self.d.expand("${@2*2},${foo},${@d.getVar('foo') + ' ${bar}'},${foo}") 70 self.assertEqual(str(val), "4,value_of_foo,${@d.getVar('foo') + ' ${unsetvar}'},value_of_foo") 71 72 def test_expand_in_python_snippet(self): 73 val = self.d.expand("${@'boo ' + '${foo}'}") 74 self.assertEqual(str(val), "boo value_of_foo") 75 76 def test_python_snippet_getvar(self): 77 val = self.d.expand("${@d.getVar('foo') + ' ${bar}'}") 78 self.assertEqual(str(val), "value_of_foo value_of_bar") 79 80 def test_python_snippet_function_reference(self): 81 self.d.setVar("TESTVAL", "testvalue") 82 self.d.setVar("testfunc", 'd.getVar("TESTVAL")') 83 context = bb.utils.get_context() 84 context["testfunc"] = lambda d: d.getVar("TESTVAL") 85 val = self.d.expand("${@testfunc(d)}") 86 self.assertEqual(str(val), "testvalue") 87 88 def test_python_snippet_builtin_metadata(self): 89 self.d.setVar("eval", "INVALID") 90 self.d.expand("${@eval('3')}") 91 92 def test_python_unexpanded(self): 93 self.d.setVar("bar", "${unsetvar}") 94 val = self.d.expand("${@d.getVar('foo') + ' ${bar}'}") 95 self.assertEqual(str(val), "${@d.getVar('foo') + ' ${unsetvar}'}") 96 97 def test_python_snippet_syntax_error(self): 98 self.d.setVar("FOO", "${@foo = 5}") 99 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True) 100 101 def test_python_snippet_runtime_error(self): 102 self.d.setVar("FOO", "${@int('test')}") 103 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True) 104 105 def test_python_snippet_error_path(self): 106 self.d.setVar("FOO", "foo value ${BAR}") 107 self.d.setVar("BAR", "bar value ${@int('test')}") 108 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True) 109 110 def test_value_containing_value(self): 111 val = self.d.expand("${@d.getVar('foo') + ' ${bar}'}") 112 self.assertEqual(str(val), "value_of_foo value_of_bar") 113 114 def test_reference_undefined_var(self): 115 val = self.d.expand("${undefinedvar} meh") 116 self.assertEqual(str(val), "${undefinedvar} meh") 117 118 def test_double_reference(self): 119 self.d.setVar("BAR", "bar value") 120 self.d.setVar("FOO", "${BAR} foo ${BAR}") 121 val = self.d.getVar("FOO") 122 self.assertEqual(str(val), "bar value foo bar value") 123 124 def test_direct_recursion(self): 125 self.d.setVar("FOO", "${FOO}") 126 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True) 127 128 def test_indirect_recursion(self): 129 self.d.setVar("FOO", "${BAR}") 130 self.d.setVar("BAR", "${BAZ}") 131 self.d.setVar("BAZ", "${FOO}") 132 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True) 133 134 def test_recursion_exception(self): 135 self.d.setVar("FOO", "${BAR}") 136 self.d.setVar("BAR", "${${@'FOO'}}") 137 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True) 138 139 def test_incomplete_varexp_single_quotes(self): 140 self.d.setVar("FOO", "sed -i -e 's:IP{:I${:g' $pc") 141 val = self.d.getVar("FOO") 142 self.assertEqual(str(val), "sed -i -e 's:IP{:I${:g' $pc") 143 144 def test_nonstring(self): 145 self.d.setVar("TEST", 5) 146 val = self.d.getVar("TEST") 147 self.assertEqual(str(val), "5") 148 149 def test_rename(self): 150 self.d.renameVar("foo", "newfoo") 151 self.assertEqual(self.d.getVar("newfoo", False), "value_of_foo") 152 self.assertEqual(self.d.getVar("foo", False), None) 153 154 def test_deletion(self): 155 self.d.delVar("foo") 156 self.assertEqual(self.d.getVar("foo", False), None) 157 158 def test_keys(self): 159 keys = list(self.d.keys()) 160 self.assertCountEqual(keys, ['value_of_foo', 'foo', 'bar']) 161 162 def test_keys_deletion(self): 163 newd = bb.data.createCopy(self.d) 164 newd.delVar("bar") 165 keys = list(newd.keys()) 166 self.assertCountEqual(keys, ['value_of_foo', 'foo']) 167 168class TestNestedExpansions(unittest.TestCase): 169 def setUp(self): 170 self.d = bb.data.init() 171 self.d["foo"] = "foo" 172 self.d["bar"] = "bar" 173 self.d["value_of_foobar"] = "187" 174 175 def test_refs(self): 176 val = self.d.expand("${value_of_${foo}${bar}}") 177 self.assertEqual(str(val), "187") 178 179 #def test_python_refs(self): 180 # val = self.d.expand("${@${@3}**2 + ${@4}**2}") 181 # self.assertEqual(str(val), "25") 182 183 def test_ref_in_python_ref(self): 184 val = self.d.expand("${@'${foo}' + 'bar'}") 185 self.assertEqual(str(val), "foobar") 186 187 def test_python_ref_in_ref(self): 188 val = self.d.expand("${${@'f'+'o'+'o'}}") 189 self.assertEqual(str(val), "foo") 190 191 def test_deep_nesting(self): 192 depth = 100 193 val = self.d.expand("${" * depth + "foo" + "}" * depth) 194 self.assertEqual(str(val), "foo") 195 196 #def test_deep_python_nesting(self): 197 # depth = 50 198 # val = self.d.expand("${@" * depth + "1" + "+1}" * depth) 199 # self.assertEqual(str(val), str(depth + 1)) 200 201 def test_mixed(self): 202 val = self.d.expand("${value_of_${@('${foo}'+'bar')[0:3]}${${@'BAR'.lower()}}}") 203 self.assertEqual(str(val), "187") 204 205 def test_runtime(self): 206 val = self.d.expand("${${@'value_of' + '_f'+'o'+'o'+'b'+'a'+'r'}}") 207 self.assertEqual(str(val), "187") 208 209class TestMemoize(unittest.TestCase): 210 def test_memoized(self): 211 d = bb.data.init() 212 d.setVar("FOO", "bar") 213 self.assertTrue(d.getVar("FOO", False) is d.getVar("FOO", False)) 214 215 def test_not_memoized(self): 216 d1 = bb.data.init() 217 d2 = bb.data.init() 218 d1.setVar("FOO", "bar") 219 d2.setVar("FOO", "bar2") 220 self.assertTrue(d1.getVar("FOO", False) is not d2.getVar("FOO", False)) 221 222 def test_changed_after_memoized(self): 223 d = bb.data.init() 224 d.setVar("foo", "value of foo") 225 self.assertEqual(str(d.getVar("foo", False)), "value of foo") 226 d.setVar("foo", "second value of foo") 227 self.assertEqual(str(d.getVar("foo", False)), "second value of foo") 228 229 def test_same_value(self): 230 d = bb.data.init() 231 d.setVar("foo", "value of") 232 d.setVar("bar", "value of") 233 self.assertEqual(d.getVar("foo", False), 234 d.getVar("bar", False)) 235 236class TestConcat(unittest.TestCase): 237 def setUp(self): 238 self.d = bb.data.init() 239 self.d.setVar("FOO", "foo") 240 self.d.setVar("VAL", "val") 241 self.d.setVar("BAR", "bar") 242 243 def test_prepend(self): 244 self.d.setVar("TEST", "${VAL}") 245 self.d.prependVar("TEST", "${FOO}:") 246 self.assertEqual(self.d.getVar("TEST"), "foo:val") 247 248 def test_append(self): 249 self.d.setVar("TEST", "${VAL}") 250 self.d.appendVar("TEST", ":${BAR}") 251 self.assertEqual(self.d.getVar("TEST"), "val:bar") 252 253 def test_multiple_append(self): 254 self.d.setVar("TEST", "${VAL}") 255 self.d.prependVar("TEST", "${FOO}:") 256 self.d.appendVar("TEST", ":val2") 257 self.d.appendVar("TEST", ":${BAR}") 258 self.assertEqual(self.d.getVar("TEST"), "foo:val:val2:bar") 259 260class TestConcatOverride(unittest.TestCase): 261 def setUp(self): 262 self.d = bb.data.init() 263 self.d.setVar("FOO", "foo") 264 self.d.setVar("VAL", "val") 265 self.d.setVar("BAR", "bar") 266 267 def test_prepend(self): 268 self.d.setVar("TEST", "${VAL}") 269 self.d.setVar("TEST:prepend", "${FOO}:") 270 self.assertEqual(self.d.getVar("TEST"), "foo:val") 271 272 def test_append(self): 273 self.d.setVar("TEST", "${VAL}") 274 self.d.setVar("TEST:append", ":${BAR}") 275 self.assertEqual(self.d.getVar("TEST"), "val:bar") 276 277 def test_multiple_append(self): 278 self.d.setVar("TEST", "${VAL}") 279 self.d.setVar("TEST:prepend", "${FOO}:") 280 self.d.setVar("TEST:append", ":val2") 281 self.d.setVar("TEST:append", ":${BAR}") 282 self.assertEqual(self.d.getVar("TEST"), "foo:val:val2:bar") 283 284 def test_append_unset(self): 285 self.d.setVar("TEST:prepend", "${FOO}:") 286 self.d.setVar("TEST:append", ":val2") 287 self.d.setVar("TEST:append", ":${BAR}") 288 self.assertEqual(self.d.getVar("TEST"), "foo::val2:bar") 289 290 def test_remove(self): 291 self.d.setVar("TEST", "${VAL} ${BAR}") 292 self.d.setVar("TEST:remove", "val") 293 self.assertEqual(self.d.getVar("TEST"), " bar") 294 295 def test_remove_cleared(self): 296 self.d.setVar("TEST", "${VAL} ${BAR}") 297 self.d.setVar("TEST:remove", "val") 298 self.d.setVar("TEST", "${VAL} ${BAR}") 299 self.assertEqual(self.d.getVar("TEST"), "val bar") 300 301 # Ensure the value is unchanged if we have an inactive remove override 302 # (including that whitespace is preserved) 303 def test_remove_inactive_override(self): 304 self.d.setVar("TEST", "${VAL} ${BAR} 123") 305 self.d.setVar("TEST:remove:inactiveoverride", "val") 306 self.assertEqual(self.d.getVar("TEST"), "val bar 123") 307 308 def test_doubleref_remove(self): 309 self.d.setVar("TEST", "${VAL} ${BAR}") 310 self.d.setVar("TEST:remove", "val") 311 self.d.setVar("TEST_TEST", "${TEST} ${TEST}") 312 self.assertEqual(self.d.getVar("TEST_TEST"), " bar bar") 313 314 def test_empty_remove(self): 315 self.d.setVar("TEST", "") 316 self.d.setVar("TEST:remove", "val") 317 self.assertEqual(self.d.getVar("TEST"), "") 318 319 def test_remove_expansion(self): 320 self.d.setVar("BAR", "Z") 321 self.d.setVar("TEST", "${BAR}/X Y") 322 self.d.setVar("TEST:remove", "${BAR}/X") 323 self.assertEqual(self.d.getVar("TEST"), " Y") 324 325 def test_remove_expansion_items(self): 326 self.d.setVar("TEST", "A B C D") 327 self.d.setVar("BAR", "B D") 328 self.d.setVar("TEST:remove", "${BAR}") 329 self.assertEqual(self.d.getVar("TEST"), "A C ") 330 331 def test_remove_preserve_whitespace(self): 332 # When the removal isn't active, the original value should be preserved 333 self.d.setVar("TEST", " A B") 334 self.d.setVar("TEST:remove", "C") 335 self.assertEqual(self.d.getVar("TEST"), " A B") 336 337 def test_remove_preserve_whitespace2(self): 338 # When the removal is active preserve the whitespace 339 self.d.setVar("TEST", " A B") 340 self.d.setVar("TEST:remove", "B") 341 self.assertEqual(self.d.getVar("TEST"), " A ") 342 343class TestOverrides(unittest.TestCase): 344 def setUp(self): 345 self.d = bb.data.init() 346 self.d.setVar("OVERRIDES", "foo:bar:local") 347 self.d.setVar("TEST", "testvalue") 348 349 def test_no_override(self): 350 self.assertEqual(self.d.getVar("TEST"), "testvalue") 351 352 def test_one_override(self): 353 self.d.setVar("TEST:bar", "testvalue2") 354 self.assertEqual(self.d.getVar("TEST"), "testvalue2") 355 356 def test_one_override_unset(self): 357 self.d.setVar("TEST2:bar", "testvalue2") 358 359 self.assertEqual(self.d.getVar("TEST2"), "testvalue2") 360 self.assertCountEqual(list(self.d.keys()), ['TEST', 'TEST2', 'OVERRIDES', 'TEST2:bar']) 361 362 def test_multiple_override(self): 363 self.d.setVar("TEST:bar", "testvalue2") 364 self.d.setVar("TEST:local", "testvalue3") 365 self.d.setVar("TEST:foo", "testvalue4") 366 self.assertEqual(self.d.getVar("TEST"), "testvalue3") 367 self.assertCountEqual(list(self.d.keys()), ['TEST', 'TEST:foo', 'OVERRIDES', 'TEST:bar', 'TEST:local']) 368 369 def test_multiple_combined_overrides(self): 370 self.d.setVar("TEST:local:foo:bar", "testvalue3") 371 self.assertEqual(self.d.getVar("TEST"), "testvalue3") 372 373 def test_multiple_overrides_unset(self): 374 self.d.setVar("TEST2:local:foo:bar", "testvalue3") 375 self.assertEqual(self.d.getVar("TEST2"), "testvalue3") 376 377 def test_keyexpansion_override(self): 378 self.d.setVar("LOCAL", "local") 379 self.d.setVar("TEST:bar", "testvalue2") 380 self.d.setVar("TEST:${LOCAL}", "testvalue3") 381 self.d.setVar("TEST:foo", "testvalue4") 382 bb.data.expandKeys(self.d) 383 self.assertEqual(self.d.getVar("TEST"), "testvalue3") 384 385 def test_rename_override(self): 386 self.d.setVar("ALTERNATIVE:ncurses-tools:class-target", "a") 387 self.d.setVar("OVERRIDES", "class-target") 388 self.d.renameVar("ALTERNATIVE:ncurses-tools", "ALTERNATIVE:lib32-ncurses-tools") 389 self.assertEqual(self.d.getVar("ALTERNATIVE:lib32-ncurses-tools"), "a") 390 391 def test_underscore_override(self): 392 self.d.setVar("TEST:bar", "testvalue2") 393 self.d.setVar("TEST:some_val", "testvalue3") 394 self.d.setVar("TEST:foo", "testvalue4") 395 self.d.setVar("OVERRIDES", "foo:bar:some_val") 396 self.assertEqual(self.d.getVar("TEST"), "testvalue3") 397 398 # Test an override with _<numeric> in it based on a real world OE issue 399 def test_underscore_override_2(self): 400 self.d.setVar("TARGET_ARCH", "x86_64") 401 self.d.setVar("PN", "test-${TARGET_ARCH}") 402 self.d.setVar("VERSION", "1") 403 self.d.setVar("VERSION:pn-test-${TARGET_ARCH}", "2") 404 self.d.setVar("OVERRIDES", "pn-${PN}") 405 bb.data.expandKeys(self.d) 406 self.assertEqual(self.d.getVar("VERSION"), "2") 407 408 def test_remove_with_override(self): 409 self.d.setVar("TEST:bar", "testvalue2") 410 self.d.setVar("TEST:some_val", "testvalue3 testvalue5") 411 self.d.setVar("TEST:some_val:remove", "testvalue3") 412 self.d.setVar("TEST:foo", "testvalue4") 413 self.d.setVar("OVERRIDES", "foo:bar:some_val") 414 self.assertEqual(self.d.getVar("TEST"), " testvalue5") 415 416 def test_append_and_override_1(self): 417 self.d.setVar("TEST:append", "testvalue2") 418 self.d.setVar("TEST:bar", "testvalue3") 419 self.assertEqual(self.d.getVar("TEST"), "testvalue3testvalue2") 420 421 def test_append_and_override_2(self): 422 self.d.setVar("TEST:append:bar", "testvalue2") 423 self.assertEqual(self.d.getVar("TEST"), "testvaluetestvalue2") 424 425 def test_append_and_override_3(self): 426 self.d.setVar("TEST:bar:append", "testvalue2") 427 self.assertEqual(self.d.getVar("TEST"), "testvalue2") 428 429 def test_append_and_unused_override(self): 430 # Had a bug where an unused override append could return "" instead of None 431 self.d.setVar("BAR:append:unusedoverride", "testvalue2") 432 self.assertEqual(self.d.getVar("BAR"), None) 433 434class TestKeyExpansion(unittest.TestCase): 435 def setUp(self): 436 self.d = bb.data.init() 437 self.d.setVar("FOO", "foo") 438 self.d.setVar("BAR", "foo") 439 440 def test_keyexpand(self): 441 self.d.setVar("VAL_${FOO}", "A") 442 self.d.setVar("VAL_${BAR}", "B") 443 with LogRecord() as logs: 444 bb.data.expandKeys(self.d) 445 self.assertTrue(logContains("Variable key VAL_${FOO} (A) replaces original key VAL_foo (B)", logs)) 446 self.assertEqual(self.d.getVar("VAL_foo"), "A") 447 448class TestFlags(unittest.TestCase): 449 def setUp(self): 450 self.d = bb.data.init() 451 self.d.setVar("foo", "value of foo") 452 self.d.setVarFlag("foo", "flag1", "value of flag1") 453 self.d.setVarFlag("foo", "_defaultval_flag_flag1", "default of flag1") 454 self.d.setVarFlag("foo", "flag2", "value of flag2") 455 self.d.setVarFlag("foo", "_defaultval_flag_flag2", "default of flag2") 456 self.d.setVarFlag("foo", "flag3", "value of flag3") 457 self.d.setVarFlag("foo", "_defaultval_flag_flagnovalue", "default of flagnovalue") 458 459 def test_setflag(self): 460 self.assertEqual(self.d.getVarFlag("foo", "flag1", False), "value of flag1") 461 self.assertEqual(self.d.getVarFlag("foo", "flag2", False), "value of flag2") 462 self.assertDictEqual( 463 self.d.getVarFlags("foo"), 464 { 465 "flag1": "value of flag1", 466 "flag2": "value of flag2", 467 "flag3": "value of flag3", 468 "flagnovalue": "default of flagnovalue", 469 } 470 ) 471 self.assertDictEqual( 472 self.d.getVarFlags("foo", internalflags=True), 473 { 474 "_content": "value of foo", 475 "flag1": "value of flag1", 476 "flag2": "value of flag2", 477 "flag3": "value of flag3", 478 "_defaultval_flag_flag1": "default of flag1", 479 "_defaultval_flag_flag2": "default of flag2", 480 "_defaultval_flag_flagnovalue": "default of flagnovalue", 481 } 482 ) 483 484 def test_delflag(self): 485 self.d.delVarFlag("foo", "flag2") 486 self.d.delVarFlag("foo", "flag3") 487 self.assertEqual(self.d.getVarFlag("foo", "flag1", False), "value of flag1") 488 self.assertEqual(self.d.getVarFlag("foo", "flag2", False), None) 489 self.assertDictEqual( 490 self.d.getVarFlags("foo"), 491 { 492 "flag1": "value of flag1", 493 "flagnovalue": "default of flagnovalue", 494 } 495 ) 496 self.assertDictEqual( 497 self.d.getVarFlags("foo", internalflags=True), 498 { 499 "_content": "value of foo", 500 "flag1": "value of flag1", 501 "_defaultval_flag_flag1": "default of flag1", 502 "_defaultval_flag_flagnovalue": "default of flagnovalue", 503 } 504 ) 505 506 def test_delvar(self): 507 self.d.delVar("foo") 508 self.assertEqual(self.d.getVarFlag("foo", "flag1", False), None) 509 self.assertEqual(self.d.getVarFlag("foo", "flag2", False), None) 510 self.assertEqual(self.d.getVarFlags("foo", internalflags=True), None) 511 512class Contains(unittest.TestCase): 513 def setUp(self): 514 self.d = bb.data.init() 515 self.d.setVar("SOMEFLAG", "a b c") 516 517 def test_contains(self): 518 self.assertTrue(bb.utils.contains("SOMEFLAG", "a", True, False, self.d)) 519 self.assertTrue(bb.utils.contains("SOMEFLAG", "b", True, False, self.d)) 520 self.assertTrue(bb.utils.contains("SOMEFLAG", "c", True, False, self.d)) 521 522 self.assertTrue(bb.utils.contains("SOMEFLAG", "a b", True, False, self.d)) 523 self.assertTrue(bb.utils.contains("SOMEFLAG", "b c", True, False, self.d)) 524 self.assertTrue(bb.utils.contains("SOMEFLAG", "c a", True, False, self.d)) 525 526 self.assertTrue(bb.utils.contains("SOMEFLAG", "a b c", True, False, self.d)) 527 self.assertTrue(bb.utils.contains("SOMEFLAG", "c b a", True, False, self.d)) 528 529 self.assertFalse(bb.utils.contains("SOMEFLAG", "x", True, False, self.d)) 530 self.assertFalse(bb.utils.contains("SOMEFLAG", "a x", True, False, self.d)) 531 self.assertFalse(bb.utils.contains("SOMEFLAG", "x c b", True, False, self.d)) 532 self.assertFalse(bb.utils.contains("SOMEFLAG", "x c b a", True, False, self.d)) 533 534 def test_contains_any(self): 535 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a", True, False, self.d)) 536 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "b", True, False, self.d)) 537 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "c", True, False, self.d)) 538 539 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a b", True, False, self.d)) 540 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "b c", True, False, self.d)) 541 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "c a", True, False, self.d)) 542 543 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a x", True, False, self.d)) 544 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "x c", True, False, self.d)) 545 546 self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x", True, False, self.d)) 547 self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x y z", True, False, self.d)) 548 549 550class TaskHash(unittest.TestCase): 551 def test_taskhashes(self): 552 def gettask_bashhash(taskname, d): 553 tasklist, gendeps, lookupcache = bb.data.generate_dependencies(d, set()) 554 taskdeps, basehash = bb.data.generate_dependency_hash(tasklist, gendeps, lookupcache, set(), "somefile") 555 bb.warn(str(lookupcache)) 556 return basehash["somefile:" + taskname] 557 558 d = bb.data.init() 559 d.setVar("__BBTASKS", ["mytask"]) 560 d.setVar("__exportlist", []) 561 d.setVar("mytask", "${MYCOMMAND}") 562 d.setVar("MYCOMMAND", "${VAR}; foo; bar; exit 0") 563 d.setVar("VAR", "val") 564 orighash = gettask_bashhash("mytask", d) 565 566 # Changing a variable should change the hash 567 d.setVar("VAR", "val2") 568 nexthash = gettask_bashhash("mytask", d) 569 self.assertNotEqual(orighash, nexthash) 570 571 d.setVar("VAR", "val") 572 # Adding an inactive removal shouldn't change the hash 573 d.setVar("BAR", "notbar") 574 d.setVar("MYCOMMAND:remove", "${BAR}") 575 nexthash = gettask_bashhash("mytask", d) 576 self.assertEqual(orighash, nexthash) 577 578 # Adding an active removal should change the hash 579 d.setVar("BAR", "bar;") 580 nexthash = gettask_bashhash("mytask", d) 581 self.assertNotEqual(orighash, nexthash) 582 583 # Setup an inactive contains() 584 d.setVar("VAR", "${@bb.utils.contains('VAR2', 'A', 'val', '', d)}") 585 orighash = gettask_bashhash("mytask", d) 586 587 # Activate the contains() and the hash should change 588 d.setVar("VAR2", "A") 589 nexthash = gettask_bashhash("mytask", d) 590 self.assertNotEqual(orighash, nexthash) 591 592 # The contains should be inactive but even though VAR2 has a 593 # different value the hash should match the original 594 d.setVar("VAR2", "B") 595 nexthash = gettask_bashhash("mytask", d) 596 self.assertEqual(orighash, nexthash) 597 598class Serialize(unittest.TestCase): 599 600 def test_serialize(self): 601 import tempfile 602 import pickle 603 d = bb.data.init() 604 d.enableTracking() 605 d.setVar('HELLO', 'world') 606 d.setVarFlag('HELLO', 'other', 'planet') 607 with tempfile.NamedTemporaryFile(delete=False) as tmpfile: 608 tmpfilename = tmpfile.name 609 pickle.dump(d, tmpfile) 610 611 with open(tmpfilename, 'rb') as f: 612 newd = pickle.load(f) 613 614 os.remove(tmpfilename) 615 616 self.assertEqual(d, newd) 617 self.assertEqual(newd.getVar('HELLO'), 'world') 618 self.assertEqual(newd.getVarFlag('HELLO', 'other'), 'planet') 619 620 621