blob: 12232305c3ab2b345130a3b0055229b05fde9a38 [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):
80 val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
81 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}")
85 val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
86 self.assertEqual(str(val), "${@d.getVar('foo', True) + ' ${unsetvar}'}")
87
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):
102 val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
103 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}")
112 val = self.d.getVar("FOO", True)
113 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")
132 val = self.d.getVar("FOO", True)
133 self.assertEqual(str(val), "sed -i -e 's:IP{:I${:g' $pc")
134
135 def test_nonstring(self):
136 self.d.setVar("TEST", 5)
137 val = self.d.getVar("TEST", True)
138 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):
150 keys = self.d.keys()
151 self.assertEqual(keys, ['value_of_foo', 'foo', 'bar'])
152
153 def test_keys_deletion(self):
154 newd = bb.data.createCopy(self.d)
155 newd.delVar("bar")
156 keys = newd.keys()
157 self.assertEqual(keys, ['value_of_foo', 'foo'])
158
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}:")
237 self.assertEqual(self.d.getVar("TEST", True), "foo:val")
238
239 def test_append(self):
240 self.d.setVar("TEST", "${VAL}")
241 self.d.appendVar("TEST", ":${BAR}")
242 self.assertEqual(self.d.getVar("TEST", True), "val:bar")
243
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}")
249 self.assertEqual(self.d.getVar("TEST", True), "foo:val:val2:bar")
250
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}:")
261 bb.data.update_data(self.d)
262 self.assertEqual(self.d.getVar("TEST", True), "foo:val")
263
264 def test_append(self):
265 self.d.setVar("TEST", "${VAL}")
266 self.d.setVar("TEST_append", ":${BAR}")
267 bb.data.update_data(self.d)
268 self.assertEqual(self.d.getVar("TEST", True), "val:bar")
269
270 def test_multiple_append(self):
271 self.d.setVar("TEST", "${VAL}")
272 self.d.setVar("TEST_prepend", "${FOO}:")
273 self.d.setVar("TEST_append", ":val2")
274 self.d.setVar("TEST_append", ":${BAR}")
275 bb.data.update_data(self.d)
276 self.assertEqual(self.d.getVar("TEST", True), "foo:val:val2:bar")
277
278 def test_append_unset(self):
279 self.d.setVar("TEST_prepend", "${FOO}:")
280 self.d.setVar("TEST_append", ":val2")
281 self.d.setVar("TEST_append", ":${BAR}")
282 bb.data.update_data(self.d)
283 self.assertEqual(self.d.getVar("TEST", True), "foo::val2:bar")
284
285 def test_remove(self):
286 self.d.setVar("TEST", "${VAL} ${BAR}")
287 self.d.setVar("TEST_remove", "val")
288 bb.data.update_data(self.d)
289 self.assertEqual(self.d.getVar("TEST", True), "bar")
290
291 def test_doubleref_remove(self):
292 self.d.setVar("TEST", "${VAL} ${BAR}")
293 self.d.setVar("TEST_remove", "val")
294 self.d.setVar("TEST_TEST", "${TEST} ${TEST}")
295 bb.data.update_data(self.d)
296 self.assertEqual(self.d.getVar("TEST_TEST", True), "bar bar")
297
298 def test_empty_remove(self):
299 self.d.setVar("TEST", "")
300 self.d.setVar("TEST_remove", "val")
301 bb.data.update_data(self.d)
302 self.assertEqual(self.d.getVar("TEST", True), "")
303
304 def test_remove_expansion(self):
305 self.d.setVar("BAR", "Z")
306 self.d.setVar("TEST", "${BAR}/X Y")
307 self.d.setVar("TEST_remove", "${BAR}/X")
308 bb.data.update_data(self.d)
309 self.assertEqual(self.d.getVar("TEST", True), "Y")
310
311 def test_remove_expansion_items(self):
312 self.d.setVar("TEST", "A B C D")
313 self.d.setVar("BAR", "B D")
314 self.d.setVar("TEST_remove", "${BAR}")
315 bb.data.update_data(self.d)
316 self.assertEqual(self.d.getVar("TEST", True), "A C")
317
318class TestOverrides(unittest.TestCase):
319 def setUp(self):
320 self.d = bb.data.init()
321 self.d.setVar("OVERRIDES", "foo:bar:local")
322 self.d.setVar("TEST", "testvalue")
323
324 def test_no_override(self):
325 bb.data.update_data(self.d)
326 self.assertEqual(self.d.getVar("TEST", True), "testvalue")
327
328 def test_one_override(self):
329 self.d.setVar("TEST_bar", "testvalue2")
330 bb.data.update_data(self.d)
331 self.assertEqual(self.d.getVar("TEST", True), "testvalue2")
332
333 def test_one_override_unset(self):
334 self.d.setVar("TEST2_bar", "testvalue2")
335 bb.data.update_data(self.d)
336 self.assertEqual(self.d.getVar("TEST2", True), "testvalue2")
337 self.assertItemsEqual(self.d.keys(), ['TEST', 'TEST2', 'OVERRIDES', 'TEST2_bar'])
338
339 def test_multiple_override(self):
340 self.d.setVar("TEST_bar", "testvalue2")
341 self.d.setVar("TEST_local", "testvalue3")
342 self.d.setVar("TEST_foo", "testvalue4")
343 bb.data.update_data(self.d)
344 self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
345 self.assertItemsEqual(self.d.keys(), ['TEST', 'TEST_foo', 'OVERRIDES', 'TEST_bar', 'TEST_local'])
346
347 def test_multiple_combined_overrides(self):
348 self.d.setVar("TEST_local_foo_bar", "testvalue3")
349 bb.data.update_data(self.d)
350 self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
351
352 def test_multiple_overrides_unset(self):
353 self.d.setVar("TEST2_local_foo_bar", "testvalue3")
354 bb.data.update_data(self.d)
355 self.assertEqual(self.d.getVar("TEST2", True), "testvalue3")
356
357 def test_keyexpansion_override(self):
358 self.d.setVar("LOCAL", "local")
359 self.d.setVar("TEST_bar", "testvalue2")
360 self.d.setVar("TEST_${LOCAL}", "testvalue3")
361 self.d.setVar("TEST_foo", "testvalue4")
362 bb.data.update_data(self.d)
363 bb.data.expandKeys(self.d)
364 self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
365
366 def test_rename_override(self):
367 self.d.setVar("ALTERNATIVE_ncurses-tools_class-target", "a")
368 self.d.setVar("OVERRIDES", "class-target")
369 bb.data.update_data(self.d)
370 self.d.renameVar("ALTERNATIVE_ncurses-tools", "ALTERNATIVE_lib32-ncurses-tools")
371 self.assertEqual(self.d.getVar("ALTERNATIVE_lib32-ncurses-tools", True), "a")
372
373 def test_underscore_override(self):
374 self.d.setVar("TEST_bar", "testvalue2")
375 self.d.setVar("TEST_some_val", "testvalue3")
376 self.d.setVar("TEST_foo", "testvalue4")
377 self.d.setVar("OVERRIDES", "foo:bar:some_val")
378 self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
379
380class TestKeyExpansion(unittest.TestCase):
381 def setUp(self):
382 self.d = bb.data.init()
383 self.d.setVar("FOO", "foo")
384 self.d.setVar("BAR", "foo")
385
386 def test_keyexpand(self):
387 self.d.setVar("VAL_${FOO}", "A")
388 self.d.setVar("VAL_${BAR}", "B")
389 with LogRecord() as logs:
390 bb.data.expandKeys(self.d)
391 self.assertTrue(logContains("Variable key VAL_${FOO} (A) replaces original key VAL_foo (B)", logs))
392 self.assertEqual(self.d.getVar("VAL_foo", True), "A")
393
394class TestFlags(unittest.TestCase):
395 def setUp(self):
396 self.d = bb.data.init()
397 self.d.setVar("foo", "value of foo")
398 self.d.setVarFlag("foo", "flag1", "value of flag1")
399 self.d.setVarFlag("foo", "flag2", "value of flag2")
400
401 def test_setflag(self):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500402 self.assertEqual(self.d.getVarFlag("foo", "flag1", False), "value of flag1")
403 self.assertEqual(self.d.getVarFlag("foo", "flag2", False), "value of flag2")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500404
405 def test_delflag(self):
406 self.d.delVarFlag("foo", "flag2")
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500407 self.assertEqual(self.d.getVarFlag("foo", "flag1", False), "value of flag1")
408 self.assertEqual(self.d.getVarFlag("foo", "flag2", False), None)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500409
410
411class Contains(unittest.TestCase):
412 def setUp(self):
413 self.d = bb.data.init()
414 self.d.setVar("SOMEFLAG", "a b c")
415
416 def test_contains(self):
417 self.assertTrue(bb.utils.contains("SOMEFLAG", "a", True, False, self.d))
418 self.assertTrue(bb.utils.contains("SOMEFLAG", "b", True, False, self.d))
419 self.assertTrue(bb.utils.contains("SOMEFLAG", "c", True, False, self.d))
420
421 self.assertTrue(bb.utils.contains("SOMEFLAG", "a b", True, False, self.d))
422 self.assertTrue(bb.utils.contains("SOMEFLAG", "b c", True, False, self.d))
423 self.assertTrue(bb.utils.contains("SOMEFLAG", "c a", True, False, self.d))
424
425 self.assertTrue(bb.utils.contains("SOMEFLAG", "a b c", True, False, self.d))
426 self.assertTrue(bb.utils.contains("SOMEFLAG", "c b a", True, False, self.d))
427
428 self.assertFalse(bb.utils.contains("SOMEFLAG", "x", True, False, self.d))
429 self.assertFalse(bb.utils.contains("SOMEFLAG", "a x", True, False, self.d))
430 self.assertFalse(bb.utils.contains("SOMEFLAG", "x c b", True, False, self.d))
431 self.assertFalse(bb.utils.contains("SOMEFLAG", "x c b a", True, False, self.d))
432
433 def test_contains_any(self):
434 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a", True, False, self.d))
435 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "b", True, False, self.d))
436 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "c", True, False, self.d))
437
438 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a b", True, False, self.d))
439 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "b c", True, False, self.d))
440 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "c a", True, False, self.d))
441
442 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a x", True, False, self.d))
443 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "x c", True, False, self.d))
444
445 self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x", True, False, self.d))
446 self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x y z", True, False, self.d))