blob: e9aab577f69292cccef21c13b1a3961479fe3dbf [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
83 def test_python_snippet_syntax_error(self):
84 self.d.setVar("FOO", "${@foo = 5}")
85 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
86
87 def test_python_snippet_runtime_error(self):
88 self.d.setVar("FOO", "${@int('test')}")
89 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
90
91 def test_python_snippet_error_path(self):
92 self.d.setVar("FOO", "foo value ${BAR}")
93 self.d.setVar("BAR", "bar value ${@int('test')}")
94 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
95
96 def test_value_containing_value(self):
97 val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
98 self.assertEqual(str(val), "value_of_foo value_of_bar")
99
100 def test_reference_undefined_var(self):
101 val = self.d.expand("${undefinedvar} meh")
102 self.assertEqual(str(val), "${undefinedvar} meh")
103
104 def test_double_reference(self):
105 self.d.setVar("BAR", "bar value")
106 self.d.setVar("FOO", "${BAR} foo ${BAR}")
107 val = self.d.getVar("FOO", True)
108 self.assertEqual(str(val), "bar value foo bar value")
109
110 def test_direct_recursion(self):
111 self.d.setVar("FOO", "${FOO}")
112 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
113
114 def test_indirect_recursion(self):
115 self.d.setVar("FOO", "${BAR}")
116 self.d.setVar("BAR", "${BAZ}")
117 self.d.setVar("BAZ", "${FOO}")
118 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
119
120 def test_recursion_exception(self):
121 self.d.setVar("FOO", "${BAR}")
122 self.d.setVar("BAR", "${${@'FOO'}}")
123 self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
124
125 def test_incomplete_varexp_single_quotes(self):
126 self.d.setVar("FOO", "sed -i -e 's:IP{:I${:g' $pc")
127 val = self.d.getVar("FOO", True)
128 self.assertEqual(str(val), "sed -i -e 's:IP{:I${:g' $pc")
129
130 def test_nonstring(self):
131 self.d.setVar("TEST", 5)
132 val = self.d.getVar("TEST", True)
133 self.assertEqual(str(val), "5")
134
135 def test_rename(self):
136 self.d.renameVar("foo", "newfoo")
137 self.assertEqual(self.d.getVar("newfoo", False), "value_of_foo")
138 self.assertEqual(self.d.getVar("foo", False), None)
139
140 def test_deletion(self):
141 self.d.delVar("foo")
142 self.assertEqual(self.d.getVar("foo", False), None)
143
144 def test_keys(self):
145 keys = self.d.keys()
146 self.assertEqual(keys, ['value_of_foo', 'foo', 'bar'])
147
148 def test_keys_deletion(self):
149 newd = bb.data.createCopy(self.d)
150 newd.delVar("bar")
151 keys = newd.keys()
152 self.assertEqual(keys, ['value_of_foo', 'foo'])
153
154class TestNestedExpansions(unittest.TestCase):
155 def setUp(self):
156 self.d = bb.data.init()
157 self.d["foo"] = "foo"
158 self.d["bar"] = "bar"
159 self.d["value_of_foobar"] = "187"
160
161 def test_refs(self):
162 val = self.d.expand("${value_of_${foo}${bar}}")
163 self.assertEqual(str(val), "187")
164
165 #def test_python_refs(self):
166 # val = self.d.expand("${@${@3}**2 + ${@4}**2}")
167 # self.assertEqual(str(val), "25")
168
169 def test_ref_in_python_ref(self):
170 val = self.d.expand("${@'${foo}' + 'bar'}")
171 self.assertEqual(str(val), "foobar")
172
173 def test_python_ref_in_ref(self):
174 val = self.d.expand("${${@'f'+'o'+'o'}}")
175 self.assertEqual(str(val), "foo")
176
177 def test_deep_nesting(self):
178 depth = 100
179 val = self.d.expand("${" * depth + "foo" + "}" * depth)
180 self.assertEqual(str(val), "foo")
181
182 #def test_deep_python_nesting(self):
183 # depth = 50
184 # val = self.d.expand("${@" * depth + "1" + "+1}" * depth)
185 # self.assertEqual(str(val), str(depth + 1))
186
187 def test_mixed(self):
188 val = self.d.expand("${value_of_${@('${foo}'+'bar')[0:3]}${${@'BAR'.lower()}}}")
189 self.assertEqual(str(val), "187")
190
191 def test_runtime(self):
192 val = self.d.expand("${${@'value_of' + '_f'+'o'+'o'+'b'+'a'+'r'}}")
193 self.assertEqual(str(val), "187")
194
195class TestMemoize(unittest.TestCase):
196 def test_memoized(self):
197 d = bb.data.init()
198 d.setVar("FOO", "bar")
199 self.assertTrue(d.getVar("FOO", False) is d.getVar("FOO", False))
200
201 def test_not_memoized(self):
202 d1 = bb.data.init()
203 d2 = bb.data.init()
204 d1.setVar("FOO", "bar")
205 d2.setVar("FOO", "bar2")
206 self.assertTrue(d1.getVar("FOO", False) is not d2.getVar("FOO", False))
207
208 def test_changed_after_memoized(self):
209 d = bb.data.init()
210 d.setVar("foo", "value of foo")
211 self.assertEqual(str(d.getVar("foo", False)), "value of foo")
212 d.setVar("foo", "second value of foo")
213 self.assertEqual(str(d.getVar("foo", False)), "second value of foo")
214
215 def test_same_value(self):
216 d = bb.data.init()
217 d.setVar("foo", "value of")
218 d.setVar("bar", "value of")
219 self.assertEqual(d.getVar("foo", False),
220 d.getVar("bar", False))
221
222class TestConcat(unittest.TestCase):
223 def setUp(self):
224 self.d = bb.data.init()
225 self.d.setVar("FOO", "foo")
226 self.d.setVar("VAL", "val")
227 self.d.setVar("BAR", "bar")
228
229 def test_prepend(self):
230 self.d.setVar("TEST", "${VAL}")
231 self.d.prependVar("TEST", "${FOO}:")
232 self.assertEqual(self.d.getVar("TEST", True), "foo:val")
233
234 def test_append(self):
235 self.d.setVar("TEST", "${VAL}")
236 self.d.appendVar("TEST", ":${BAR}")
237 self.assertEqual(self.d.getVar("TEST", True), "val:bar")
238
239 def test_multiple_append(self):
240 self.d.setVar("TEST", "${VAL}")
241 self.d.prependVar("TEST", "${FOO}:")
242 self.d.appendVar("TEST", ":val2")
243 self.d.appendVar("TEST", ":${BAR}")
244 self.assertEqual(self.d.getVar("TEST", True), "foo:val:val2:bar")
245
246class TestConcatOverride(unittest.TestCase):
247 def setUp(self):
248 self.d = bb.data.init()
249 self.d.setVar("FOO", "foo")
250 self.d.setVar("VAL", "val")
251 self.d.setVar("BAR", "bar")
252
253 def test_prepend(self):
254 self.d.setVar("TEST", "${VAL}")
255 self.d.setVar("TEST_prepend", "${FOO}:")
256 bb.data.update_data(self.d)
257 self.assertEqual(self.d.getVar("TEST", True), "foo:val")
258
259 def test_append(self):
260 self.d.setVar("TEST", "${VAL}")
261 self.d.setVar("TEST_append", ":${BAR}")
262 bb.data.update_data(self.d)
263 self.assertEqual(self.d.getVar("TEST", True), "val:bar")
264
265 def test_multiple_append(self):
266 self.d.setVar("TEST", "${VAL}")
267 self.d.setVar("TEST_prepend", "${FOO}:")
268 self.d.setVar("TEST_append", ":val2")
269 self.d.setVar("TEST_append", ":${BAR}")
270 bb.data.update_data(self.d)
271 self.assertEqual(self.d.getVar("TEST", True), "foo:val:val2:bar")
272
273 def test_append_unset(self):
274 self.d.setVar("TEST_prepend", "${FOO}:")
275 self.d.setVar("TEST_append", ":val2")
276 self.d.setVar("TEST_append", ":${BAR}")
277 bb.data.update_data(self.d)
278 self.assertEqual(self.d.getVar("TEST", True), "foo::val2:bar")
279
280 def test_remove(self):
281 self.d.setVar("TEST", "${VAL} ${BAR}")
282 self.d.setVar("TEST_remove", "val")
283 bb.data.update_data(self.d)
284 self.assertEqual(self.d.getVar("TEST", True), "bar")
285
286 def test_doubleref_remove(self):
287 self.d.setVar("TEST", "${VAL} ${BAR}")
288 self.d.setVar("TEST_remove", "val")
289 self.d.setVar("TEST_TEST", "${TEST} ${TEST}")
290 bb.data.update_data(self.d)
291 self.assertEqual(self.d.getVar("TEST_TEST", True), "bar bar")
292
293 def test_empty_remove(self):
294 self.d.setVar("TEST", "")
295 self.d.setVar("TEST_remove", "val")
296 bb.data.update_data(self.d)
297 self.assertEqual(self.d.getVar("TEST", True), "")
298
299 def test_remove_expansion(self):
300 self.d.setVar("BAR", "Z")
301 self.d.setVar("TEST", "${BAR}/X Y")
302 self.d.setVar("TEST_remove", "${BAR}/X")
303 bb.data.update_data(self.d)
304 self.assertEqual(self.d.getVar("TEST", True), "Y")
305
306 def test_remove_expansion_items(self):
307 self.d.setVar("TEST", "A B C D")
308 self.d.setVar("BAR", "B D")
309 self.d.setVar("TEST_remove", "${BAR}")
310 bb.data.update_data(self.d)
311 self.assertEqual(self.d.getVar("TEST", True), "A C")
312
313class TestOverrides(unittest.TestCase):
314 def setUp(self):
315 self.d = bb.data.init()
316 self.d.setVar("OVERRIDES", "foo:bar:local")
317 self.d.setVar("TEST", "testvalue")
318
319 def test_no_override(self):
320 bb.data.update_data(self.d)
321 self.assertEqual(self.d.getVar("TEST", True), "testvalue")
322
323 def test_one_override(self):
324 self.d.setVar("TEST_bar", "testvalue2")
325 bb.data.update_data(self.d)
326 self.assertEqual(self.d.getVar("TEST", True), "testvalue2")
327
328 def test_one_override_unset(self):
329 self.d.setVar("TEST2_bar", "testvalue2")
330 bb.data.update_data(self.d)
331 self.assertEqual(self.d.getVar("TEST2", True), "testvalue2")
332 self.assertItemsEqual(self.d.keys(), ['TEST', 'TEST2', 'OVERRIDES', 'TEST2_bar'])
333
334 def test_multiple_override(self):
335 self.d.setVar("TEST_bar", "testvalue2")
336 self.d.setVar("TEST_local", "testvalue3")
337 self.d.setVar("TEST_foo", "testvalue4")
338 bb.data.update_data(self.d)
339 self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
340 self.assertItemsEqual(self.d.keys(), ['TEST', 'TEST_foo', 'OVERRIDES', 'TEST_bar', 'TEST_local'])
341
342 def test_multiple_combined_overrides(self):
343 self.d.setVar("TEST_local_foo_bar", "testvalue3")
344 bb.data.update_data(self.d)
345 self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
346
347 def test_multiple_overrides_unset(self):
348 self.d.setVar("TEST2_local_foo_bar", "testvalue3")
349 bb.data.update_data(self.d)
350 self.assertEqual(self.d.getVar("TEST2", True), "testvalue3")
351
352 def test_keyexpansion_override(self):
353 self.d.setVar("LOCAL", "local")
354 self.d.setVar("TEST_bar", "testvalue2")
355 self.d.setVar("TEST_${LOCAL}", "testvalue3")
356 self.d.setVar("TEST_foo", "testvalue4")
357 bb.data.update_data(self.d)
358 bb.data.expandKeys(self.d)
359 self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
360
361 def test_rename_override(self):
362 self.d.setVar("ALTERNATIVE_ncurses-tools_class-target", "a")
363 self.d.setVar("OVERRIDES", "class-target")
364 bb.data.update_data(self.d)
365 self.d.renameVar("ALTERNATIVE_ncurses-tools", "ALTERNATIVE_lib32-ncurses-tools")
366 self.assertEqual(self.d.getVar("ALTERNATIVE_lib32-ncurses-tools", True), "a")
367
368 def test_underscore_override(self):
369 self.d.setVar("TEST_bar", "testvalue2")
370 self.d.setVar("TEST_some_val", "testvalue3")
371 self.d.setVar("TEST_foo", "testvalue4")
372 self.d.setVar("OVERRIDES", "foo:bar:some_val")
373 self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
374
375class TestKeyExpansion(unittest.TestCase):
376 def setUp(self):
377 self.d = bb.data.init()
378 self.d.setVar("FOO", "foo")
379 self.d.setVar("BAR", "foo")
380
381 def test_keyexpand(self):
382 self.d.setVar("VAL_${FOO}", "A")
383 self.d.setVar("VAL_${BAR}", "B")
384 with LogRecord() as logs:
385 bb.data.expandKeys(self.d)
386 self.assertTrue(logContains("Variable key VAL_${FOO} (A) replaces original key VAL_foo (B)", logs))
387 self.assertEqual(self.d.getVar("VAL_foo", True), "A")
388
389class TestFlags(unittest.TestCase):
390 def setUp(self):
391 self.d = bb.data.init()
392 self.d.setVar("foo", "value of foo")
393 self.d.setVarFlag("foo", "flag1", "value of flag1")
394 self.d.setVarFlag("foo", "flag2", "value of flag2")
395
396 def test_setflag(self):
397 self.assertEqual(self.d.getVarFlag("foo", "flag1"), "value of flag1")
398 self.assertEqual(self.d.getVarFlag("foo", "flag2"), "value of flag2")
399
400 def test_delflag(self):
401 self.d.delVarFlag("foo", "flag2")
402 self.assertEqual(self.d.getVarFlag("foo", "flag1"), "value of flag1")
403 self.assertEqual(self.d.getVarFlag("foo", "flag2"), None)
404
405
406class Contains(unittest.TestCase):
407 def setUp(self):
408 self.d = bb.data.init()
409 self.d.setVar("SOMEFLAG", "a b c")
410
411 def test_contains(self):
412 self.assertTrue(bb.utils.contains("SOMEFLAG", "a", True, False, self.d))
413 self.assertTrue(bb.utils.contains("SOMEFLAG", "b", True, False, self.d))
414 self.assertTrue(bb.utils.contains("SOMEFLAG", "c", True, False, self.d))
415
416 self.assertTrue(bb.utils.contains("SOMEFLAG", "a b", True, False, self.d))
417 self.assertTrue(bb.utils.contains("SOMEFLAG", "b c", True, False, self.d))
418 self.assertTrue(bb.utils.contains("SOMEFLAG", "c a", True, False, self.d))
419
420 self.assertTrue(bb.utils.contains("SOMEFLAG", "a b c", True, False, self.d))
421 self.assertTrue(bb.utils.contains("SOMEFLAG", "c b a", True, False, self.d))
422
423 self.assertFalse(bb.utils.contains("SOMEFLAG", "x", True, False, self.d))
424 self.assertFalse(bb.utils.contains("SOMEFLAG", "a x", True, False, self.d))
425 self.assertFalse(bb.utils.contains("SOMEFLAG", "x c b", True, False, self.d))
426 self.assertFalse(bb.utils.contains("SOMEFLAG", "x c b a", True, False, self.d))
427
428 def test_contains_any(self):
429 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a", True, False, self.d))
430 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "b", True, False, self.d))
431 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "c", True, False, self.d))
432
433 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a b", True, False, self.d))
434 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "b c", True, False, self.d))
435 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "c a", True, False, self.d))
436
437 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "a x", True, False, self.d))
438 self.assertTrue(bb.utils.contains_any("SOMEFLAG", "x c", True, False, self.d))
439
440 self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x", True, False, self.d))
441 self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x y z", True, False, self.d))