xref: /OK3568_Linux_fs/yocto/poky/bitbake/lib/bb/tests/data.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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