diff options
Diffstat (limited to 'lib/bb/tests/data.py')
-rw-r--r-- | lib/bb/tests/data.py | 346 |
1 files changed, 156 insertions, 190 deletions
diff --git a/lib/bb/tests/data.py b/lib/bb/tests/data.py index a4a9dd30f..cbc7c1ecd 100644 --- a/lib/bb/tests/data.py +++ b/lib/bb/tests/data.py @@ -1,23 +1,10 @@ -# ex:ts=4:sw=4:sts=4:et -# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- # # BitBake Tests for the Data Store (data.py/data_smart.py) # # Copyright (C) 2010 Chris Larson # Copyright (C) 2012 Richard Purdie # -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# SPDX-License-Identifier: GPL-2.0-only # import unittest @@ -25,6 +12,7 @@ import bb import bb.data import bb.parse import logging +import os class LogRecord(): def __enter__(self): @@ -72,6 +60,15 @@ class DataExpansions(unittest.TestCase): val = self.d.expand("${@5*12}") self.assertEqual(str(val), "60") + def test_python_snippet_w_dict(self): + val = self.d.expand("${@{ 'green': 1, 'blue': 2 }['green']}") + self.assertEqual(str(val), "1") + + def test_python_unexpanded_multi(self): + self.d.setVar("bar", "${unsetvar}") + val = self.d.expand("${@2*2},${foo},${@d.getVar('foo') + ' ${bar}'},${foo}") + self.assertEqual(str(val), "4,value_of_foo,${@d.getVar('foo') + ' ${unsetvar}'},value_of_foo") + def test_expand_in_python_snippet(self): val = self.d.expand("${@'boo ' + '${foo}'}") self.assertEqual(str(val), "boo value_of_foo") @@ -80,6 +77,18 @@ class DataExpansions(unittest.TestCase): val = self.d.expand("${@d.getVar('foo') + ' ${bar}'}") self.assertEqual(str(val), "value_of_foo value_of_bar") + def test_python_snippet_function_reference(self): + self.d.setVar("TESTVAL", "testvalue") + self.d.setVar("testfunc", 'd.getVar("TESTVAL")') + context = bb.utils.get_context() + context["testfunc"] = lambda d: d.getVar("TESTVAL") + val = self.d.expand("${@testfunc(d)}") + self.assertEqual(str(val), "testvalue") + + def test_python_snippet_builtin_metadata(self): + self.d.setVar("eval", "INVALID") + self.d.expand("${@eval('3')}") + def test_python_unexpanded(self): self.d.setVar("bar", "${unsetvar}") val = self.d.expand("${@d.getVar('foo') + ' ${bar}'}") @@ -257,35 +266,35 @@ class TestConcatOverride(unittest.TestCase): def test_prepend(self): self.d.setVar("TEST", "${VAL}") - self.d.setVar("TEST_prepend", "${FOO}:") + self.d.setVar("TEST:prepend", "${FOO}:") self.assertEqual(self.d.getVar("TEST"), "foo:val") def test_append(self): self.d.setVar("TEST", "${VAL}") - self.d.setVar("TEST_append", ":${BAR}") + self.d.setVar("TEST:append", ":${BAR}") self.assertEqual(self.d.getVar("TEST"), "val:bar") def test_multiple_append(self): self.d.setVar("TEST", "${VAL}") - self.d.setVar("TEST_prepend", "${FOO}:") - self.d.setVar("TEST_append", ":val2") - self.d.setVar("TEST_append", ":${BAR}") + self.d.setVar("TEST:prepend", "${FOO}:") + self.d.setVar("TEST:append", ":val2") + self.d.setVar("TEST:append", ":${BAR}") self.assertEqual(self.d.getVar("TEST"), "foo:val:val2:bar") def test_append_unset(self): - self.d.setVar("TEST_prepend", "${FOO}:") - self.d.setVar("TEST_append", ":val2") - self.d.setVar("TEST_append", ":${BAR}") + self.d.setVar("TEST:prepend", "${FOO}:") + self.d.setVar("TEST:append", ":val2") + self.d.setVar("TEST:append", ":${BAR}") self.assertEqual(self.d.getVar("TEST"), "foo::val2:bar") def test_remove(self): self.d.setVar("TEST", "${VAL} ${BAR}") - self.d.setVar("TEST_remove", "val") - self.assertEqual(self.d.getVar("TEST"), "bar") + self.d.setVar("TEST:remove", "val") + self.assertEqual(self.d.getVar("TEST"), " bar") def test_remove_cleared(self): self.d.setVar("TEST", "${VAL} ${BAR}") - self.d.setVar("TEST_remove", "val") + self.d.setVar("TEST:remove", "val") self.d.setVar("TEST", "${VAL} ${BAR}") self.assertEqual(self.d.getVar("TEST"), "val bar") @@ -293,31 +302,43 @@ class TestConcatOverride(unittest.TestCase): # (including that whitespace is preserved) def test_remove_inactive_override(self): self.d.setVar("TEST", "${VAL} ${BAR} 123") - self.d.setVar("TEST_remove_inactiveoverride", "val") + self.d.setVar("TEST:remove:inactiveoverride", "val") self.assertEqual(self.d.getVar("TEST"), "val bar 123") def test_doubleref_remove(self): self.d.setVar("TEST", "${VAL} ${BAR}") - self.d.setVar("TEST_remove", "val") + self.d.setVar("TEST:remove", "val") self.d.setVar("TEST_TEST", "${TEST} ${TEST}") - self.assertEqual(self.d.getVar("TEST_TEST"), "bar bar") + self.assertEqual(self.d.getVar("TEST_TEST"), " bar bar") def test_empty_remove(self): self.d.setVar("TEST", "") - self.d.setVar("TEST_remove", "val") + self.d.setVar("TEST:remove", "val") self.assertEqual(self.d.getVar("TEST"), "") def test_remove_expansion(self): self.d.setVar("BAR", "Z") self.d.setVar("TEST", "${BAR}/X Y") - self.d.setVar("TEST_remove", "${BAR}/X") - self.assertEqual(self.d.getVar("TEST"), "Y") + self.d.setVar("TEST:remove", "${BAR}/X") + self.assertEqual(self.d.getVar("TEST"), " Y") def test_remove_expansion_items(self): self.d.setVar("TEST", "A B C D") self.d.setVar("BAR", "B D") - self.d.setVar("TEST_remove", "${BAR}") - self.assertEqual(self.d.getVar("TEST"), "A C") + self.d.setVar("TEST:remove", "${BAR}") + self.assertEqual(self.d.getVar("TEST"), "A C ") + + def test_remove_preserve_whitespace(self): + # When the removal isn't active, the original value should be preserved + self.d.setVar("TEST", " A B") + self.d.setVar("TEST:remove", "C") + self.assertEqual(self.d.getVar("TEST"), " A B") + + def test_remove_preserve_whitespace2(self): + # When the removal is active preserve the whitespace + self.d.setVar("TEST", " A B") + self.d.setVar("TEST:remove", "B") + self.assertEqual(self.d.getVar("TEST"), " A ") class TestOverrides(unittest.TestCase): def setUp(self): @@ -329,51 +350,87 @@ class TestOverrides(unittest.TestCase): self.assertEqual(self.d.getVar("TEST"), "testvalue") def test_one_override(self): - self.d.setVar("TEST_bar", "testvalue2") + self.d.setVar("TEST:bar", "testvalue2") self.assertEqual(self.d.getVar("TEST"), "testvalue2") def test_one_override_unset(self): - self.d.setVar("TEST2_bar", "testvalue2") + self.d.setVar("TEST2:bar", "testvalue2") self.assertEqual(self.d.getVar("TEST2"), "testvalue2") - self.assertCountEqual(list(self.d.keys()), ['TEST', 'TEST2', 'OVERRIDES', 'TEST2_bar']) + self.assertCountEqual(list(self.d.keys()), ['TEST', 'TEST2', 'OVERRIDES', 'TEST2:bar']) def test_multiple_override(self): - self.d.setVar("TEST_bar", "testvalue2") - self.d.setVar("TEST_local", "testvalue3") - self.d.setVar("TEST_foo", "testvalue4") + self.d.setVar("TEST:bar", "testvalue2") + self.d.setVar("TEST:local", "testvalue3") + self.d.setVar("TEST:foo", "testvalue4") self.assertEqual(self.d.getVar("TEST"), "testvalue3") - self.assertCountEqual(list(self.d.keys()), ['TEST', 'TEST_foo', 'OVERRIDES', 'TEST_bar', 'TEST_local']) + self.assertCountEqual(list(self.d.keys()), ['TEST', 'TEST:foo', 'OVERRIDES', 'TEST:bar', 'TEST:local']) def test_multiple_combined_overrides(self): - self.d.setVar("TEST_local_foo_bar", "testvalue3") + self.d.setVar("TEST:local:foo:bar", "testvalue3") self.assertEqual(self.d.getVar("TEST"), "testvalue3") def test_multiple_overrides_unset(self): - self.d.setVar("TEST2_local_foo_bar", "testvalue3") + self.d.setVar("TEST2:local:foo:bar", "testvalue3") self.assertEqual(self.d.getVar("TEST2"), "testvalue3") def test_keyexpansion_override(self): self.d.setVar("LOCAL", "local") - self.d.setVar("TEST_bar", "testvalue2") - self.d.setVar("TEST_${LOCAL}", "testvalue3") - self.d.setVar("TEST_foo", "testvalue4") + self.d.setVar("TEST:bar", "testvalue2") + self.d.setVar("TEST:${LOCAL}", "testvalue3") + self.d.setVar("TEST:foo", "testvalue4") bb.data.expandKeys(self.d) self.assertEqual(self.d.getVar("TEST"), "testvalue3") def test_rename_override(self): - self.d.setVar("ALTERNATIVE_ncurses-tools_class-target", "a") + self.d.setVar("ALTERNATIVE:ncurses-tools:class-target", "a") self.d.setVar("OVERRIDES", "class-target") - self.d.renameVar("ALTERNATIVE_ncurses-tools", "ALTERNATIVE_lib32-ncurses-tools") - self.assertEqual(self.d.getVar("ALTERNATIVE_lib32-ncurses-tools"), "a") + self.d.renameVar("ALTERNATIVE:ncurses-tools", "ALTERNATIVE:lib32-ncurses-tools") + self.assertEqual(self.d.getVar("ALTERNATIVE:lib32-ncurses-tools"), "a") def test_underscore_override(self): - self.d.setVar("TEST_bar", "testvalue2") - self.d.setVar("TEST_some_val", "testvalue3") - self.d.setVar("TEST_foo", "testvalue4") + self.d.setVar("TEST:bar", "testvalue2") + self.d.setVar("TEST:some_val", "testvalue3") + self.d.setVar("TEST:foo", "testvalue4") self.d.setVar("OVERRIDES", "foo:bar:some_val") self.assertEqual(self.d.getVar("TEST"), "testvalue3") + # Test an override with _<numeric> in it based on a real world OE issue + def test_underscore_override_2(self): + self.d.setVar("TARGET_ARCH", "x86_64") + self.d.setVar("PN", "test-${TARGET_ARCH}") + self.d.setVar("VERSION", "1") + self.d.setVar("VERSION:pn-test-${TARGET_ARCH}", "2") + self.d.setVar("OVERRIDES", "pn-${PN}") + bb.data.expandKeys(self.d) + self.assertEqual(self.d.getVar("VERSION"), "2") + + def test_remove_with_override(self): + self.d.setVar("TEST:bar", "testvalue2") + self.d.setVar("TEST:some_val", "testvalue3 testvalue5") + self.d.setVar("TEST:some_val:remove", "testvalue3") + self.d.setVar("TEST:foo", "testvalue4") + self.d.setVar("OVERRIDES", "foo:bar:some_val") + self.assertEqual(self.d.getVar("TEST"), " testvalue5") + + def test_append_and_override_1(self): + self.d.setVar("TEST:append", "testvalue2") + self.d.setVar("TEST:bar", "testvalue3") + self.assertEqual(self.d.getVar("TEST"), "testvalue3testvalue2") + + def test_append_and_override_2(self): + self.d.setVar("TEST:append:bar", "testvalue2") + self.assertEqual(self.d.getVar("TEST"), "testvaluetestvalue2") + + def test_append_and_override_3(self): + self.d.setVar("TEST:bar:append", "testvalue2") + self.assertEqual(self.d.getVar("TEST"), "testvalue2") + + def test_append_and_unused_override(self): + # Had a bug where an unused override append could return "" instead of None + self.d.setVar("BAR:append:unusedoverride", "testvalue2") + self.assertEqual(self.d.getVar("BAR"), None) + class TestKeyExpansion(unittest.TestCase): def setUp(self): self.d = bb.data.init() @@ -443,6 +500,54 @@ class Contains(unittest.TestCase): self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x y z", True, False, self.d)) +class TaskHash(unittest.TestCase): + def test_taskhashes(self): + def gettask_bashhash(taskname, d): + tasklist, gendeps, lookupcache = bb.data.generate_dependencies(d, set()) + taskdeps, basehash = bb.data.generate_dependency_hash(tasklist, gendeps, lookupcache, set(), "somefile") + bb.warn(str(lookupcache)) + return basehash["somefile:" + taskname] + + d = bb.data.init() + d.setVar("__BBTASKS", ["mytask"]) + d.setVar("__exportlist", []) + d.setVar("mytask", "${MYCOMMAND}") + d.setVar("MYCOMMAND", "${VAR}; foo; bar; exit 0") + d.setVar("VAR", "val") + orighash = gettask_bashhash("mytask", d) + + # Changing a variable should change the hash + d.setVar("VAR", "val2") + nexthash = gettask_bashhash("mytask", d) + self.assertNotEqual(orighash, nexthash) + + d.setVar("VAR", "val") + # Adding an inactive removal shouldn't change the hash + d.setVar("BAR", "notbar") + d.setVar("MYCOMMAND:remove", "${BAR}") + nexthash = gettask_bashhash("mytask", d) + self.assertEqual(orighash, nexthash) + + # Adding an active removal should change the hash + d.setVar("BAR", "bar;") + nexthash = gettask_bashhash("mytask", d) + self.assertNotEqual(orighash, nexthash) + + # Setup an inactive contains() + d.setVar("VAR", "${@bb.utils.contains('VAR2', 'A', 'val', '', d)}") + orighash = gettask_bashhash("mytask", d) + + # Activate the contains() and the hash should change + d.setVar("VAR2", "A") + nexthash = gettask_bashhash("mytask", d) + self.assertNotEqual(orighash, nexthash) + + # The contains should be inactive but even though VAR2 has a + # different value the hash should match the original + d.setVar("VAR2", "B") + nexthash = gettask_bashhash("mytask", d) + self.assertEqual(orighash, nexthash) + class Serialize(unittest.TestCase): def test_serialize(self): @@ -466,142 +571,3 @@ class Serialize(unittest.TestCase): self.assertEqual(newd.getVarFlag('HELLO', 'other'), 'planet') -# Remote datastore tests -# These really only test the interface, since in actual usage we have a -# tinfoil connector that does everything over RPC, and this doesn't test -# that. - -class TestConnector: - d = None - def __init__(self, d): - self.d = d - def getVar(self, name): - return self.d._findVar(name) - def getKeys(self): - return set(self.d.keys()) - def getVarHistory(self, name): - return self.d.varhistory.variable(name) - def expandPythonRef(self, varname, expr, d): - localdata = self.d.createCopy() - for key in d.localkeys(): - localdata.setVar(d.getVar(key)) - varparse = bb.data_smart.VariableParse(varname, localdata) - return varparse.python_sub(expr) - def setVar(self, name, value): - self.d.setVar(name, value) - def setVarFlag(self, name, flag, value): - self.d.setVarFlag(name, flag, value) - def delVar(self, name): - self.d.delVar(name) - return False - def delVarFlag(self, name, flag): - self.d.delVarFlag(name, flag) - return False - def renameVar(self, name, newname): - self.d.renameVar(name, newname) - return False - -class Remote(unittest.TestCase): - def test_remote(self): - - d1 = bb.data.init() - d1.enableTracking() - d2 = bb.data.init() - d2.enableTracking() - connector = TestConnector(d1) - - d2.setVar('_remote_data', connector) - - d1.setVar('HELLO', 'world') - d1.setVarFlag('OTHER', 'flagname', 'flagvalue') - self.assertEqual(d2.getVar('HELLO'), 'world') - self.assertEqual(d2.expand('${HELLO}'), 'world') - self.assertEqual(d2.expand('${@d.getVar("HELLO")}'), 'world') - self.assertIn('flagname', d2.getVarFlags('OTHER')) - self.assertEqual(d2.getVarFlag('OTHER', 'flagname'), 'flagvalue') - self.assertEqual(d1.varhistory.variable('HELLO'), d2.varhistory.variable('HELLO')) - # Test setVar on client side affects server - d2.setVar('HELLO', 'other-world') - self.assertEqual(d1.getVar('HELLO'), 'other-world') - # Test setVarFlag on client side affects server - d2.setVarFlag('HELLO', 'flagname', 'flagvalue') - self.assertEqual(d1.getVarFlag('HELLO', 'flagname'), 'flagvalue') - # Test client side data is incorporated in python expansion (which is done on server) - d2.setVar('FOO', 'bar') - self.assertEqual(d2.expand('${@d.getVar("FOO")}'), 'bar') - # Test overrides work - d1.setVar('FOO_test', 'baz') - d1.appendVar('OVERRIDES', ':test') - self.assertEqual(d2.getVar('FOO'), 'baz') - - -# Remote equivalents of local test classes -# Note that these aren't perfect since we only test in one direction - -class RemoteDataExpansions(DataExpansions): - def setUp(self): - self.d1 = bb.data.init() - self.d = bb.data.init() - self.d1["foo"] = "value_of_foo" - self.d1["bar"] = "value_of_bar" - self.d1["value_of_foo"] = "value_of_'value_of_foo'" - connector = TestConnector(self.d1) - self.d.setVar('_remote_data', connector) - -class TestRemoteNestedExpansions(TestNestedExpansions): - def setUp(self): - self.d1 = bb.data.init() - self.d = bb.data.init() - self.d1["foo"] = "foo" - self.d1["bar"] = "bar" - self.d1["value_of_foobar"] = "187" - connector = TestConnector(self.d1) - self.d.setVar('_remote_data', connector) - -class TestRemoteConcat(TestConcat): - def setUp(self): - self.d1 = bb.data.init() - self.d = bb.data.init() - self.d1.setVar("FOO", "foo") - self.d1.setVar("VAL", "val") - self.d1.setVar("BAR", "bar") - connector = TestConnector(self.d1) - self.d.setVar('_remote_data', connector) - -class TestRemoteConcatOverride(TestConcatOverride): - def setUp(self): - self.d1 = bb.data.init() - self.d = bb.data.init() - self.d1.setVar("FOO", "foo") - self.d1.setVar("VAL", "val") - self.d1.setVar("BAR", "bar") - connector = TestConnector(self.d1) - self.d.setVar('_remote_data', connector) - -class TestRemoteOverrides(TestOverrides): - def setUp(self): - self.d1 = bb.data.init() - self.d = bb.data.init() - self.d1.setVar("OVERRIDES", "foo:bar:local") - self.d1.setVar("TEST", "testvalue") - connector = TestConnector(self.d1) - self.d.setVar('_remote_data', connector) - -class TestRemoteKeyExpansion(TestKeyExpansion): - def setUp(self): - self.d1 = bb.data.init() - self.d = bb.data.init() - self.d1.setVar("FOO", "foo") - self.d1.setVar("BAR", "foo") - connector = TestConnector(self.d1) - self.d.setVar('_remote_data', connector) - -class TestRemoteFlags(TestFlags): - def setUp(self): - self.d1 = bb.data.init() - self.d = bb.data.init() - self.d1.setVar("foo", "value of foo") - self.d1.setVarFlag("foo", "flag1", "value of flag1") - self.d1.setVarFlag("foo", "flag2", "value of flag2") - connector = TestConnector(self.d1) - self.d.setVar('_remote_data', connector) |