blob: 3c511f214bba59949d0d61f05f2580c0f8cb9ce2 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3#
4# BitBake Tests for the Data Store (data.py/data_smart.py)
5#
6# Copyright (C) 2010 Chris Larson
7# Copyright (C) 2012 Richard Purdie
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License version 2 as
11# published by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License along
19# with this program; if not, write to the Free Software Foundation, Inc.,
20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21#
22
23import unittest
24import bb
25import bb.data
26import bb.parse
27import logging
28
29class LogRecord():
30 def __enter__(self):
31 logs = []
32 class LogHandler(logging.Handler):
33 def emit(self, record):
34 logs.append(record)
35 logger = logging.getLogger("BitBake")
36 handler = LogHandler()
37 self.handler = handler
38 logger.addHandler(handler)
39 return logs
40 def __exit__(self, type, value, traceback):
41 logger = logging.getLogger("BitBake")
42 logger.removeHandler(self.handler)
43 return
44
45def logContains(item, logs):
46 for l in logs:
47 m = l.getMessage()
48 if item in m:
49 return True
50 return False
51
52class DataExpansions(unittest.TestCase):
53 def setUp(self):
54 self.d = bb.data.init()
55 self.d["foo"] = "value_of_foo"
56 self.d["bar"] = "value_of_bar"
57 self.d["value_of_foo"] = "value_of_'value_of_foo'"
58
59 def test_one_var(self):
60 val = self.d.expand("${foo}")
61 self.assertEqual(str(val), "value_of_foo")
62
63 def test_indirect_one_var(self):
64 val = self.d.expand("${${foo}}")
65 self.assertEqual(str(val), "value_of_'value_of_foo'")
66
67 def test_indirect_and_another(self):
68 val = self.d.expand("${${foo}} ${bar}")
69 self.assertEqual(str(val), "value_of_'value_of_foo' value_of_bar")
70
71 def test_python_snippet(self):
72 val = self.d.expand("${@5*12}")
73 self.assertEqual(str(val), "60")
74
75 def test_expand_in_python_snippet(self):
76 val = self.d.expand("${@'boo ' + '${foo}'}")
77 self.assertEqual(str(val), "boo value_of_foo")
78
79 def test_python_snippet_getvar(self):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050080 val = self.d.expand("${@d.getVar('foo') + ' ${bar}'}")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050081 self.assertEqual(str(val), "value_of_foo value_of_bar")
82
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050083 def test_python_unexpanded(self):
84 self.d.setVar("bar", "${unsetvar}")
Brad Bishop6e60e8b2018-02-01 10:27:11 -050085 val = self.d.expand("${@d.getVar('foo') + ' ${bar}'}")
86 self.assertEqual(str(val), "${@d.getVar('foo') + ' ${unsetvar}'}")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050087
Patrick Williamsc124f4f2015-09-15 14:41:29 -050088 def test_python_snippet_syntax_error(self):
89 self.d.setVar("FOO", "${@foo = 5}")
90 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
91
92 def test_python_snippet_runtime_error(self):
93 self.d.setVar("FOO", "${@int('test')}")
94 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
95
96 def test_python_snippet_error_path(self):
97 self.d.setVar("FOO", "foo value ${BAR}")
98 self.d.setVar("BAR", "bar value ${@int('test')}")
99 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
100
101 def test_value_containing_value(self):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500102 val = self.d.expand("${@d.getVar('foo') + ' ${bar}'}")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500103 self.assertEqual(str(val), "value_of_foo value_of_bar")
104
105 def test_reference_undefined_var(self):
106 val = self.d.expand("${undefinedvar} meh")
107 self.assertEqual(str(val), "${undefinedvar} meh")
108
109 def test_double_reference(self):
110 self.d.setVar("BAR", "bar value")
111 self.d.setVar("FOO", "${BAR} foo ${BAR}")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500112 val = self.d.getVar("FOO")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500113 self.assertEqual(str(val), "bar value foo bar value")
114
115 def test_direct_recursion(self):
116 self.d.setVar("FOO", "${FOO}")
117 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
118
119 def test_indirect_recursion(self):
120 self.d.setVar("FOO", "${BAR}")
121 self.d.setVar("BAR", "${BAZ}")
122 self.d.setVar("BAZ", "${FOO}")
123 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
124
125 def test_recursion_exception(self):
126 self.d.setVar("FOO", "${BAR}")
127 self.d.setVar("BAR", "${${@'FOO'}}")
128 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
129
130 def test_incomplete_varexp_single_quotes(self):
131 self.d.setVar("FOO", "sed -i -e 's:IP{:I${:g' $pc")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500132 val = self.d.getVar("FOO")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500133 self.assertEqual(str(val), "sed -i -e 's:IP{:I${:g' $pc")
134
135 def test_nonstring(self):
136 self.d.setVar("TEST", 5)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500137 val = self.d.getVar("TEST")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500138 self.assertEqual(str(val), "5")
139
140 def test_rename(self):
141 self.d.renameVar("foo", "newfoo")
142 self.assertEqual(self.d.getVar("newfoo", False), "value_of_foo")
143 self.assertEqual(self.d.getVar("foo", False), None)
144
145 def test_deletion(self):
146 self.d.delVar("foo")
147 self.assertEqual(self.d.getVar("foo", False), None)
148
149 def test_keys(self):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600150 keys = list(self.d.keys())
151 self.assertCountEqual(keys, ['value_of_foo', 'foo', 'bar'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500152
153 def test_keys_deletion(self):
154 newd = bb.data.createCopy(self.d)
155 newd.delVar("bar")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600156 keys = list(newd.keys())
157 self.assertCountEqual(keys, ['value_of_foo', 'foo'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500158
159class TestNestedExpansions(unittest.TestCase):
160 def setUp(self):
161 self.d = bb.data.init()
162 self.d["foo"] = "foo"
163 self.d["bar"] = "bar"
164 self.d["value_of_foobar"] = "187"
165
166 def test_refs(self):
167 val = self.d.expand("${value_of_${foo}${bar}}")
168 self.assertEqual(str(val), "187")
169
170 #def test_python_refs(self):
171 # val = self.d.expand("${@${@3}**2 + ${@4}**2}")
172 # self.assertEqual(str(val), "25")
173
174 def test_ref_in_python_ref(self):
175 val = self.d.expand("${@'${foo}' + 'bar'}")
176 self.assertEqual(str(val), "foobar")
177
178 def test_python_ref_in_ref(self):
179 val = self.d.expand("${${@'f'+'o'+'o'}}")
180 self.assertEqual(str(val), "foo")
181
182 def test_deep_nesting(self):
183 depth = 100
184 val = self.d.expand("${" * depth + "foo" + "}" * depth)
185 self.assertEqual(str(val), "foo")
186
187 #def test_deep_python_nesting(self):
188 # depth = 50
189 # val = self.d.expand("${@" * depth + "1" + "+1}" * depth)
190 # self.assertEqual(str(val), str(depth + 1))
191
192 def test_mixed(self):
193 val = self.d.expand("${value_of_${@('${foo}'+'bar')[0:3]}${${@'BAR'.lower()}}}")
194 self.assertEqual(str(val), "187")
195
196 def test_runtime(self):
197 val = self.d.expand("${${@'value_of' + '_f'+'o'+'o'+'b'+'a'+'r'}}")
198 self.assertEqual(str(val), "187")
199
200class TestMemoize(unittest.TestCase):
201 def test_memoized(self):
202 d = bb.data.init()
203 d.setVar("FOO", "bar")
204 self.assertTrue(d.getVar("FOO", False) is d.getVar("FOO", False))
205
206 def test_not_memoized(self):
207 d1 = bb.data.init()
208 d2 = bb.data.init()
209 d1.setVar("FOO", "bar")
210 d2.setVar("FOO", "bar2")
211 self.assertTrue(d1.getVar("FOO", False) is not d2.getVar("FOO", False))
212
213 def test_changed_after_memoized(self):
214 d = bb.data.init()
215 d.setVar("foo", "value of foo")
216 self.assertEqual(str(d.getVar("foo", False)), "value of foo")
217 d.setVar("foo", "second value of foo")
218 self.assertEqual(str(d.getVar("foo", False)), "second value of foo")
219
220 def test_same_value(self):
221 d = bb.data.init()
222 d.setVar("foo", "value of")
223 d.setVar("bar", "value of")
224 self.assertEqual(d.getVar("foo", False),
225 d.getVar("bar", False))
226
227class TestConcat(unittest.TestCase):
228 def setUp(self):
229 self.d = bb.data.init()
230 self.d.setVar("FOO", "foo")
231 self.d.setVar("VAL", "val")
232 self.d.setVar("BAR", "bar")
233
234 def test_prepend(self):
235 self.d.setVar("TEST", "${VAL}")
236 self.d.prependVar("TEST", "${FOO}:")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500237 self.assertEqual(self.d.getVar("TEST"), "foo:val")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500238
239 def test_append(self):
240 self.d.setVar("TEST", "${VAL}")
241 self.d.appendVar("TEST", ":${BAR}")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500242 self.assertEqual(self.d.getVar("TEST"), "val:bar")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500243
244 def test_multiple_append(self):
245 self.d.setVar("TEST", "${VAL}")
246 self.d.prependVar("TEST", "${FOO}:")
247 self.d.appendVar("TEST", ":val2")
248 self.d.appendVar("TEST", ":${BAR}")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500249 self.assertEqual(self.d.getVar("TEST"), "foo:val:val2:bar")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500250
251class TestConcatOverride(unittest.TestCase):
252 def setUp(self):
253 self.d = bb.data.init()
254 self.d.setVar("FOO", "foo")
255 self.d.setVar("VAL", "val")
256 self.d.setVar("BAR", "bar")
257
258 def test_prepend(self):
259 self.d.setVar("TEST", "${VAL}")
260 self.d.setVar("TEST_prepend", "${FOO}:")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500261 self.assertEqual(self.d.getVar("TEST"), "foo:val")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500262
263 def test_append(self):
264 self.d.setVar("TEST", "${VAL}")
265 self.d.setVar("TEST_append", ":${BAR}")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500266 self.assertEqual(self.d.getVar("TEST"), "val:bar")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500267
268 def test_multiple_append(self):
269 self.d.setVar("TEST", "${VAL}")
270 self.d.setVar("TEST_prepend", "${FOO}:")
271 self.d.setVar("TEST_append", ":val2")
272 self.d.setVar("TEST_append", ":${BAR}")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500273 self.assertEqual(self.d.getVar("TEST"), "foo:val:val2:bar")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500274
275 def test_append_unset(self):
276 self.d.setVar("TEST_prepend", "${FOO}:")
277 self.d.setVar("TEST_append", ":val2")
278 self.d.setVar("TEST_append", ":${BAR}")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500279 self.assertEqual(self.d.getVar("TEST"), "foo::val2:bar")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500280
281 def test_remove(self):
282 self.d.setVar("TEST", "${VAL} ${BAR}")
283 self.d.setVar("TEST_remove", "val")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800284 self.assertEqual(self.d.getVar("TEST"), " bar")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500285
286 def test_remove_cleared(self):
287 self.d.setVar("TEST", "${VAL} ${BAR}")
288 self.d.setVar("TEST_remove", "val")
289 self.d.setVar("TEST", "${VAL} ${BAR}")
290 self.assertEqual(self.d.getVar("TEST"), "val bar")
291
292 # Ensure the value is unchanged if we have an inactive remove override
293 # (including that whitespace is preserved)
294 def test_remove_inactive_override(self):
295 self.d.setVar("TEST", "${VAL} ${BAR} 123")
296 self.d.setVar("TEST_remove_inactiveoverride", "val")
297 self.assertEqual(self.d.getVar("TEST"), "val bar 123")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500298
299 def test_doubleref_remove(self):
300 self.d.setVar("TEST", "${VAL} ${BAR}")
301 self.d.setVar("TEST_remove", "val")
302 self.d.setVar("TEST_TEST", "${TEST} ${TEST}")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800303 self.assertEqual(self.d.getVar("TEST_TEST"), " bar bar")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500304
305 def test_empty_remove(self):
306 self.d.setVar("TEST", "")
307 self.d.setVar("TEST_remove", "val")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500308 self.assertEqual(self.d.getVar("TEST"), "")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500309
310 def test_remove_expansion(self):
311 self.d.setVar("BAR", "Z")
312 self.d.setVar("TEST", "${BAR}/X Y")
313 self.d.setVar("TEST_remove", "${BAR}/X")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800314 self.assertEqual(self.d.getVar("TEST"), " Y")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500315
316 def test_remove_expansion_items(self):
317 self.d.setVar("TEST", "A B C D")
318 self.d.setVar("BAR", "B D")
319 self.d.setVar("TEST_remove", "${BAR}")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800320 self.assertEqual(self.d.getVar("TEST"), "A C ")
321
322 def test_remove_preserve_whitespace(self):
323 # When the removal isn't active, the original value should be preserved
324 self.d.setVar("TEST", " A B")
325 self.d.setVar("TEST_remove", "C")
326 self.assertEqual(self.d.getVar("TEST"), " A B")
327
328 def test_remove_preserve_whitespace2(self):
329 # When the removal is active preserve the whitespace
330 self.d.setVar("TEST", " A B")
331 self.d.setVar("TEST_remove", "B")
332 self.assertEqual(self.d.getVar("TEST"), " A ")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500333
334class TestOverrides(unittest.TestCase):
335 def setUp(self):
336 self.d = bb.data.init()
337 self.d.setVar("OVERRIDES", "foo:bar:local")
338 self.d.setVar("TEST", "testvalue")
339
340 def test_no_override(self):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500341 self.assertEqual(self.d.getVar("TEST"), "testvalue")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500342
343 def test_one_override(self):
344 self.d.setVar("TEST_bar", "testvalue2")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500345 self.assertEqual(self.d.getVar("TEST"), "testvalue2")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500346
347 def test_one_override_unset(self):
348 self.d.setVar("TEST2_bar", "testvalue2")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500349
350 self.assertEqual(self.d.getVar("TEST2"), "testvalue2")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600351 self.assertCountEqual(list(self.d.keys()), ['TEST', 'TEST2', 'OVERRIDES', 'TEST2_bar'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500352
353 def test_multiple_override(self):
354 self.d.setVar("TEST_bar", "testvalue2")
355 self.d.setVar("TEST_local", "testvalue3")
356 self.d.setVar("TEST_foo", "testvalue4")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500357 self.assertEqual(self.d.getVar("TEST"), "testvalue3")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600358 self.assertCountEqual(list(self.d.keys()), ['TEST', 'TEST_foo', 'OVERRIDES', 'TEST_bar', 'TEST_local'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500359
360 def test_multiple_combined_overrides(self):
361 self.d.setVar("TEST_local_foo_bar", "testvalue3")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500362 self.assertEqual(self.d.getVar("TEST"), "testvalue3")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500363
364 def test_multiple_overrides_unset(self):
365 self.d.setVar("TEST2_local_foo_bar", "testvalue3")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500366 self.assertEqual(self.d.getVar("TEST2"), "testvalue3")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500367
368 def test_keyexpansion_override(self):
369 self.d.setVar("LOCAL", "local")
370 self.d.setVar("TEST_bar", "testvalue2")
371 self.d.setVar("TEST_${LOCAL}", "testvalue3")
372 self.d.setVar("TEST_foo", "testvalue4")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500373 bb.data.expandKeys(self.d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500374 self.assertEqual(self.d.getVar("TEST"), "testvalue3")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500375
376 def test_rename_override(self):
377 self.d.setVar("ALTERNATIVE_ncurses-tools_class-target", "a")
378 self.d.setVar("OVERRIDES", "class-target")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500379 self.d.renameVar("ALTERNATIVE_ncurses-tools", "ALTERNATIVE_lib32-ncurses-tools")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500380 self.assertEqual(self.d.getVar("ALTERNATIVE_lib32-ncurses-tools"), "a")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500381
382 def test_underscore_override(self):
383 self.d.setVar("TEST_bar", "testvalue2")
384 self.d.setVar("TEST_some_val", "testvalue3")
385 self.d.setVar("TEST_foo", "testvalue4")
386 self.d.setVar("OVERRIDES", "foo:bar:some_val")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500387 self.assertEqual(self.d.getVar("TEST"), "testvalue3")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500388
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800389 def test_remove_with_override(self):
390 self.d.setVar("TEST_bar", "testvalue2")
391 self.d.setVar("TEST_some_val", "testvalue3 testvalue5")
392 self.d.setVar("TEST_some_val_remove", "testvalue3")
393 self.d.setVar("TEST_foo", "testvalue4")
394 self.d.setVar("OVERRIDES", "foo:bar:some_val")
395 self.assertEqual(self.d.getVar("TEST"), " testvalue5")
396
Brad Bishop19323692019-04-05 15:28:33 -0400397 # Test an override with _<numeric> in it based on a real world OE issue
398 def test_underscore_override(self):
399 self.d.setVar("TARGET_ARCH", "x86_64")
400 self.d.setVar("PN", "test-${TARGET_ARCH}")
401 self.d.setVar("VERSION", "1")
402 self.d.setVar("VERSION_pn-test-${TARGET_ARCH}", "2")
403 self.d.setVar("OVERRIDES", "pn-${PN}")
404 bb.data.expandKeys(self.d)
405 self.assertEqual(self.d.getVar("VERSION"), "2")
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800406
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500407class TestKeyExpansion(unittest.TestCase):
408 def setUp(self):
409 self.d = bb.data.init()
410 self.d.setVar("FOO", "foo")
411 self.d.setVar("BAR", "foo")
412
413 def test_keyexpand(self):
414 self.d.setVar("VAL_${FOO}", "A")
415 self.d.setVar("VAL_${BAR}", "B")
416 with LogRecord() as logs:
417 bb.data.expandKeys(self.d)
418 self.assertTrue(logContains("Variable key VAL_${FOO} (A) replaces original key VAL_foo (B)", logs))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500419 self.assertEqual(self.d.getVar("VAL_foo"), "A")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500420
421class TestFlags(unittest.TestCase):
422 def setUp(self):
423 self.d = bb.data.init()
424 self.d.setVar("foo", "value of foo")
425 self.d.setVarFlag("foo", "flag1", "value of flag1")
426 self.d.setVarFlag("foo", "flag2", "value of flag2")
427
428 def test_setflag(self):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500429 self.assertEqual(self.d.getVarFlag("foo", "flag1", False), "value of flag1")
430 self.assertEqual(self.d.getVarFlag("foo", "flag2", False), "value of flag2")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500431
432 def test_delflag(self):
433 self.d.delVarFlag("foo", "flag2")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500434 self.assertEqual(self.d.getVarFlag("foo", "flag1", False), "value of flag1")
435 self.assertEqual(self.d.getVarFlag("foo", "flag2", False), None)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500436
437
438class Contains(unittest.TestCase):
439 def setUp(self):
440 self.d = bb.data.init()
441 self.d.setVar("SOMEFLAG", "a b c")
442
443 def test_contains(self):
444 self.assertTrue(bb.utils.contains("SOMEFLAG", "a", True, False, self.d))
445 self.assertTrue(bb.utils.contains("SOMEFLAG", "b", True, False, self.d))
446 self.assertTrue(bb.utils.contains("SOMEFLAG", "c", True, False, self.d))
447
448 self.assertTrue(bb.utils.contains("SOMEFLAG", "a b", True, False, self.d))
449 self.assertTrue(bb.utils.contains("SOMEFLAG", "b c", True, False, self.d))
450 self.assertTrue(bb.utils.contains("SOMEFLAG", "c a", True, False, self.d))
451
452 self.assertTrue(bb.utils.contains("SOMEFLAG", "a b c", True, False, self.d))
453 self.assertTrue(bb.utils.contains("SOMEFLAG", "c b a", True, False, self.d))
454
455 self.assertFalse(bb.utils.contains("SOMEFLAG", "x", True, False, self.d))
456 self.assertFalse(bb.utils.contains("SOMEFLAG", "a x", True, False, self.d))
457 self.assertFalse(bb.utils.contains("SOMEFLAG", "x c b", True, False, self.d))
458 self.assertFalse(bb.utils.contains("SOMEFLAG", "x c b a", True, False, self.d))
459
460 def test_contains_any(self):
461 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a", True, False, self.d))
462 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "b", True, False, self.d))
463 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "c", True, False, self.d))
464
465 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a b", True, False, self.d))
466 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "b c", True, False, self.d))
467 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "c a", True, False, self.d))
468
469 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a x", True, False, self.d))
470 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "x c", True, False, self.d))
471
472 self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x", True, False, self.d))
473 self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x y z", True, False, self.d))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500474
475
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800476class TaskHash(unittest.TestCase):
477 def test_taskhashes(self):
478 def gettask_bashhash(taskname, d):
479 tasklist, gendeps, lookupcache = bb.data.generate_dependencies(d)
480 taskdeps, basehash = bb.data.generate_dependency_hash(tasklist, gendeps, lookupcache, set(), "somefile")
481 bb.warn(str(lookupcache))
482 return basehash["somefile." + taskname]
483
484 d = bb.data.init()
485 d.setVar("__BBTASKS", ["mytask"])
486 d.setVar("__exportlist", [])
487 d.setVar("mytask", "${MYCOMMAND}")
488 d.setVar("MYCOMMAND", "${VAR}; foo; bar; exit 0")
489 d.setVar("VAR", "val")
490 orighash = gettask_bashhash("mytask", d)
491
492 # Changing a variable should change the hash
493 d.setVar("VAR", "val2")
494 nexthash = gettask_bashhash("mytask", d)
495 self.assertNotEqual(orighash, nexthash)
496
497 d.setVar("VAR", "val")
498 # Adding an inactive removal shouldn't change the hash
499 d.setVar("BAR", "notbar")
500 d.setVar("MYCOMMAND_remove", "${BAR}")
501 nexthash = gettask_bashhash("mytask", d)
502 self.assertEqual(orighash, nexthash)
503
504 # Adding an active removal should change the hash
505 d.setVar("BAR", "bar;")
506 nexthash = gettask_bashhash("mytask", d)
507 self.assertNotEqual(orighash, nexthash)
508
509 # Setup an inactive contains()
510 d.setVar("VAR", "${@bb.utils.contains('VAR2', 'A', 'val', '', d)}")
511 orighash = gettask_bashhash("mytask", d)
512
513 # Activate the contains() and the hash should change
514 d.setVar("VAR2", "A")
515 nexthash = gettask_bashhash("mytask", d)
516 self.assertNotEqual(orighash, nexthash)
517
518 # The contains should be inactive but even though VAR2 has a
519 # different value the hash should match the original
520 d.setVar("VAR2", "B")
521 nexthash = gettask_bashhash("mytask", d)
522 self.assertEqual(orighash, nexthash)
523
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500524class Serialize(unittest.TestCase):
525
526 def test_serialize(self):
527 import tempfile
528 import pickle
529 d = bb.data.init()
530 d.enableTracking()
531 d.setVar('HELLO', 'world')
532 d.setVarFlag('HELLO', 'other', 'planet')
533 with tempfile.NamedTemporaryFile(delete=False) as tmpfile:
534 tmpfilename = tmpfile.name
535 pickle.dump(d, tmpfile)
536
537 with open(tmpfilename, 'rb') as f:
538 newd = pickle.load(f)
539
540 os.remove(tmpfilename)
541
542 self.assertEqual(d, newd)
543 self.assertEqual(newd.getVar('HELLO'), 'world')
544 self.assertEqual(newd.getVarFlag('HELLO', 'other'), 'planet')
545
546
547# Remote datastore tests
548# These really only test the interface, since in actual usage we have a
549# tinfoil connector that does everything over RPC, and this doesn't test
550# that.
551
552class TestConnector:
553 d = None
554 def __init__(self, d):
555 self.d = d
556 def getVar(self, name):
557 return self.d._findVar(name)
558 def getKeys(self):
559 return set(self.d.keys())
560 def getVarHistory(self, name):
561 return self.d.varhistory.variable(name)
562 def expandPythonRef(self, varname, expr, d):
563 localdata = self.d.createCopy()
564 for key in d.localkeys():
565 localdata.setVar(d.getVar(key))
566 varparse = bb.data_smart.VariableParse(varname, localdata)
567 return varparse.python_sub(expr)
568 def setVar(self, name, value):
569 self.d.setVar(name, value)
570 def setVarFlag(self, name, flag, value):
571 self.d.setVarFlag(name, flag, value)
572 def delVar(self, name):
573 self.d.delVar(name)
574 return False
575 def delVarFlag(self, name, flag):
576 self.d.delVarFlag(name, flag)
577 return False
578 def renameVar(self, name, newname):
579 self.d.renameVar(name, newname)
580 return False
581
582class Remote(unittest.TestCase):
583 def test_remote(self):
584
585 d1 = bb.data.init()
586 d1.enableTracking()
587 d2 = bb.data.init()
588 d2.enableTracking()
589 connector = TestConnector(d1)
590
591 d2.setVar('_remote_data', connector)
592
593 d1.setVar('HELLO', 'world')
594 d1.setVarFlag('OTHER', 'flagname', 'flagvalue')
595 self.assertEqual(d2.getVar('HELLO'), 'world')
596 self.assertEqual(d2.expand('${HELLO}'), 'world')
597 self.assertEqual(d2.expand('${@d.getVar("HELLO")}'), 'world')
598 self.assertIn('flagname', d2.getVarFlags('OTHER'))
599 self.assertEqual(d2.getVarFlag('OTHER', 'flagname'), 'flagvalue')
600 self.assertEqual(d1.varhistory.variable('HELLO'), d2.varhistory.variable('HELLO'))
601 # Test setVar on client side affects server
602 d2.setVar('HELLO', 'other-world')
603 self.assertEqual(d1.getVar('HELLO'), 'other-world')
604 # Test setVarFlag on client side affects server
605 d2.setVarFlag('HELLO', 'flagname', 'flagvalue')
606 self.assertEqual(d1.getVarFlag('HELLO', 'flagname'), 'flagvalue')
607 # Test client side data is incorporated in python expansion (which is done on server)
608 d2.setVar('FOO', 'bar')
609 self.assertEqual(d2.expand('${@d.getVar("FOO")}'), 'bar')
610 # Test overrides work
611 d1.setVar('FOO_test', 'baz')
612 d1.appendVar('OVERRIDES', ':test')
613 self.assertEqual(d2.getVar('FOO'), 'baz')
614
615
616# Remote equivalents of local test classes
617# Note that these aren't perfect since we only test in one direction
618
619class RemoteDataExpansions(DataExpansions):
620 def setUp(self):
621 self.d1 = bb.data.init()
622 self.d = bb.data.init()
623 self.d1["foo"] = "value_of_foo"
624 self.d1["bar"] = "value_of_bar"
625 self.d1["value_of_foo"] = "value_of_'value_of_foo'"
626 connector = TestConnector(self.d1)
627 self.d.setVar('_remote_data', connector)
628
629class TestRemoteNestedExpansions(TestNestedExpansions):
630 def setUp(self):
631 self.d1 = bb.data.init()
632 self.d = bb.data.init()
633 self.d1["foo"] = "foo"
634 self.d1["bar"] = "bar"
635 self.d1["value_of_foobar"] = "187"
636 connector = TestConnector(self.d1)
637 self.d.setVar('_remote_data', connector)
638
639class TestRemoteConcat(TestConcat):
640 def setUp(self):
641 self.d1 = bb.data.init()
642 self.d = bb.data.init()
643 self.d1.setVar("FOO", "foo")
644 self.d1.setVar("VAL", "val")
645 self.d1.setVar("BAR", "bar")
646 connector = TestConnector(self.d1)
647 self.d.setVar('_remote_data', connector)
648
649class TestRemoteConcatOverride(TestConcatOverride):
650 def setUp(self):
651 self.d1 = bb.data.init()
652 self.d = bb.data.init()
653 self.d1.setVar("FOO", "foo")
654 self.d1.setVar("VAL", "val")
655 self.d1.setVar("BAR", "bar")
656 connector = TestConnector(self.d1)
657 self.d.setVar('_remote_data', connector)
658
659class TestRemoteOverrides(TestOverrides):
660 def setUp(self):
661 self.d1 = bb.data.init()
662 self.d = bb.data.init()
663 self.d1.setVar("OVERRIDES", "foo:bar:local")
664 self.d1.setVar("TEST", "testvalue")
665 connector = TestConnector(self.d1)
666 self.d.setVar('_remote_data', connector)
667
668class TestRemoteKeyExpansion(TestKeyExpansion):
669 def setUp(self):
670 self.d1 = bb.data.init()
671 self.d = bb.data.init()
672 self.d1.setVar("FOO", "foo")
673 self.d1.setVar("BAR", "foo")
674 connector = TestConnector(self.d1)
675 self.d.setVar('_remote_data', connector)
676
677class TestRemoteFlags(TestFlags):
678 def setUp(self):
679 self.d1 = bb.data.init()
680 self.d = bb.data.init()
681 self.d1.setVar("foo", "value of foo")
682 self.d1.setVarFlag("foo", "flag1", "value of flag1")
683 self.d1.setVarFlag("foo", "flag2", "value of flag2")
684 connector = TestConnector(self.d1)
685 self.d.setVar('_remote_data', connector)