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