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", "flag2", "value of flag2") 454 455 def test_setflag(self): 456 self.assertEqual(self.d.getVarFlag("foo", "flag1", False), "value of flag1") 457 self.assertEqual(self.d.getVarFlag("foo", "flag2", False), "value of flag2") 458 459 def test_delflag(self): 460 self.d.delVarFlag("foo", "flag2") 461 self.assertEqual(self.d.getVarFlag("foo", "flag1", False), "value of flag1") 462 self.assertEqual(self.d.getVarFlag("foo", "flag2", False), None) 463 464 465class Contains(unittest.TestCase): 466 def setUp(self): 467 self.d = bb.data.init() 468 self.d.setVar("SOMEFLAG", "a b c") 469 470 def test_contains(self): 471 self.assertTrue(bb.utils.contains("SOMEFLAG", "a", True, False, self.d)) 472 self.assertTrue(bb.utils.contains("SOMEFLAG", "b", True, False, self.d)) 473 self.assertTrue(bb.utils.contains("SOMEFLAG", "c", True, False, self.d)) 474 475 self.assertTrue(bb.utils.contains("SOMEFLAG", "a b", True, False, self.d)) 476 self.assertTrue(bb.utils.contains("SOMEFLAG", "b c", True, False, self.d)) 477 self.assertTrue(bb.utils.contains("SOMEFLAG", "c a", True, False, self.d)) 478 479 self.assertTrue(bb.utils.contains("SOMEFLAG", "a b c", True, False, self.d)) 480 self.assertTrue(bb.utils.contains("SOMEFLAG", "c b a", True, False, self.d)) 481 482 self.assertFalse(bb.utils.contains("SOMEFLAG", "x", True, False, self.d)) 483 self.assertFalse(bb.utils.contains("SOMEFLAG", "a x", True, False, self.d)) 484 self.assertFalse(bb.utils.contains("SOMEFLAG", "x c b", True, False, self.d)) 485 self.assertFalse(bb.utils.contains("SOMEFLAG", "x c b a", True, False, self.d)) 486 487 def test_contains_any(self): 488 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a", True, False, self.d)) 489 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "b", True, False, self.d)) 490 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "c", True, False, self.d)) 491 492 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a b", True, False, self.d)) 493 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "b c", True, False, self.d)) 494 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "c a", True, False, self.d)) 495 496 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a x", True, False, self.d)) 497 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "x c", True, False, self.d)) 498 499 self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x", True, False, self.d)) 500 self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x y z", True, False, self.d)) 501 502 503class TaskHash(unittest.TestCase): 504 def test_taskhashes(self): 505 def gettask_bashhash(taskname, d): 506 tasklist, gendeps, lookupcache = bb.data.generate_dependencies(d, set()) 507 taskdeps, basehash = bb.data.generate_dependency_hash(tasklist, gendeps, lookupcache, set(), "somefile") 508 bb.warn(str(lookupcache)) 509 return basehash["somefile:" + taskname] 510 511 d = bb.data.init() 512 d.setVar("__BBTASKS", ["mytask"]) 513 d.setVar("__exportlist", []) 514 d.setVar("mytask", "${MYCOMMAND}") 515 d.setVar("MYCOMMAND", "${VAR}; foo; bar; exit 0") 516 d.setVar("VAR", "val") 517 orighash = gettask_bashhash("mytask", d) 518 519 # Changing a variable should change the hash 520 d.setVar("VAR", "val2") 521 nexthash = gettask_bashhash("mytask", d) 522 self.assertNotEqual(orighash, nexthash) 523 524 d.setVar("VAR", "val") 525 # Adding an inactive removal shouldn't change the hash 526 d.setVar("BAR", "notbar") 527 d.setVar("MYCOMMAND:remove", "${BAR}") 528 nexthash = gettask_bashhash("mytask", d) 529 self.assertEqual(orighash, nexthash) 530 531 # Adding an active removal should change the hash 532 d.setVar("BAR", "bar;") 533 nexthash = gettask_bashhash("mytask", d) 534 self.assertNotEqual(orighash, nexthash) 535 536 # Setup an inactive contains() 537 d.setVar("VAR", "${@bb.utils.contains('VAR2', 'A', 'val', '', d)}") 538 orighash = gettask_bashhash("mytask", d) 539 540 # Activate the contains() and the hash should change 541 d.setVar("VAR2", "A") 542 nexthash = gettask_bashhash("mytask", d) 543 self.assertNotEqual(orighash, nexthash) 544 545 # The contains should be inactive but even though VAR2 has a 546 # different value the hash should match the original 547 d.setVar("VAR2", "B") 548 nexthash = gettask_bashhash("mytask", d) 549 self.assertEqual(orighash, nexthash) 550 551class Serialize(unittest.TestCase): 552 553 def test_serialize(self): 554 import tempfile 555 import pickle 556 d = bb.data.init() 557 d.enableTracking() 558 d.setVar('HELLO', 'world') 559 d.setVarFlag('HELLO', 'other', 'planet') 560 with tempfile.NamedTemporaryFile(delete=False) as tmpfile: 561 tmpfilename = tmpfile.name 562 pickle.dump(d, tmpfile) 563 564 with open(tmpfilename, 'rb') as f: 565 newd = pickle.load(f) 566 567 os.remove(tmpfilename) 568 569 self.assertEqual(d, newd) 570 self.assertEqual(newd.getVar('HELLO'), 'world') 571 self.assertEqual(newd.getVarFlag('HELLO', 'other'), 'planet') 572 573 574