aboutsummaryrefslogtreecommitdiffstats
path: root/lib/bb/tests/data.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bb/tests/data.py')
-rw-r--r--lib/bb/tests/data.py346
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)