blob: 4d788281a73709248f43856f1225c4615df92a33 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#
2# BitBake Tests for utils.py
3#
4# Copyright (C) 2012 Richard Purdie
5#
Brad Bishopc342db32019-05-15 21:57:59 -04006# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -05007#
8
9import unittest
10import bb
11import os
12import tempfile
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050013import re
Patrick Williamsc124f4f2015-09-15 14:41:29 -050014
15class VerCmpString(unittest.TestCase):
16
17 def test_vercmpstring(self):
18 result = bb.utils.vercmp_string('1', '2')
19 self.assertTrue(result < 0)
20 result = bb.utils.vercmp_string('2', '1')
21 self.assertTrue(result > 0)
22 result = bb.utils.vercmp_string('1', '1.0')
23 self.assertTrue(result < 0)
24 result = bb.utils.vercmp_string('1', '1.1')
25 self.assertTrue(result < 0)
26 result = bb.utils.vercmp_string('1.1', '1_p2')
27 self.assertTrue(result < 0)
28 result = bb.utils.vercmp_string('1.0', '1.0+1.1-beta1')
29 self.assertTrue(result < 0)
30 result = bb.utils.vercmp_string('1.1', '1.0+1.1-beta1')
31 self.assertTrue(result > 0)
Brad Bishop19323692019-04-05 15:28:33 -040032 result = bb.utils.vercmp_string('1.', '1.1')
33 self.assertTrue(result < 0)
34 result = bb.utils.vercmp_string('1.1', '1.')
35 self.assertTrue(result > 0)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050036
37 def test_explode_dep_versions(self):
38 correctresult = {"foo" : ["= 1.10"]}
39 result = bb.utils.explode_dep_versions2("foo (= 1.10)")
40 self.assertEqual(result, correctresult)
41 result = bb.utils.explode_dep_versions2("foo (=1.10)")
42 self.assertEqual(result, correctresult)
43 result = bb.utils.explode_dep_versions2("foo ( = 1.10)")
44 self.assertEqual(result, correctresult)
45 result = bb.utils.explode_dep_versions2("foo ( =1.10)")
46 self.assertEqual(result, correctresult)
47 result = bb.utils.explode_dep_versions2("foo ( = 1.10 )")
48 self.assertEqual(result, correctresult)
49 result = bb.utils.explode_dep_versions2("foo ( =1.10 )")
50 self.assertEqual(result, correctresult)
51
52 def test_vercmp_string_op(self):
53 compareops = [('1', '1', '=', True),
54 ('1', '1', '==', True),
55 ('1', '1', '!=', False),
56 ('1', '1', '>', False),
57 ('1', '1', '<', False),
58 ('1', '1', '>=', True),
59 ('1', '1', '<=', True),
60 ('1', '0', '=', False),
61 ('1', '0', '==', False),
62 ('1', '0', '!=', True),
63 ('1', '0', '>', True),
64 ('1', '0', '<', False),
65 ('1', '0', '>>', True),
66 ('1', '0', '<<', False),
67 ('1', '0', '>=', True),
68 ('1', '0', '<=', False),
69 ('0', '1', '=', False),
70 ('0', '1', '==', False),
71 ('0', '1', '!=', True),
72 ('0', '1', '>', False),
73 ('0', '1', '<', True),
74 ('0', '1', '>>', False),
75 ('0', '1', '<<', True),
76 ('0', '1', '>=', False),
77 ('0', '1', '<=', True)]
78
79 for arg1, arg2, op, correctresult in compareops:
80 result = bb.utils.vercmp_string_op(arg1, arg2, op)
81 self.assertEqual(result, correctresult, 'vercmp_string_op("%s", "%s", "%s") != %s' % (arg1, arg2, op, correctresult))
82
83 # Check that clearly invalid operator raises an exception
84 self.assertRaises(bb.utils.VersionStringException, bb.utils.vercmp_string_op, '0', '0', '$')
85
86
87class Path(unittest.TestCase):
88 def test_unsafe_delete_path(self):
89 checkitems = [('/', True),
90 ('//', True),
91 ('///', True),
92 (os.getcwd().count(os.sep) * ('..' + os.sep), True),
93 (os.environ.get('HOME', '/home/test'), True),
94 ('/home/someone', True),
95 ('/home/other/', True),
96 ('/home/other/subdir', False),
97 ('', False)]
98 for arg1, correctresult in checkitems:
99 result = bb.utils._check_unsafe_delete_path(arg1)
100 self.assertEqual(result, correctresult, '_check_unsafe_delete_path("%s") != %s' % (arg1, correctresult))
101
102
103class EditMetadataFile(unittest.TestCase):
104 _origfile = """
105# A comment
106HELLO = "oldvalue"
107
108THIS = "that"
109
110# Another comment
111NOCHANGE = "samevalue"
112OTHER = 'anothervalue'
113
114MULTILINE = "a1 \\
115 a2 \\
116 a3"
117
118MULTILINE2 := " \\
119 b1 \\
120 b2 \\
121 b3 \\
122 "
123
124
125MULTILINE3 = " \\
126 c1 \\
127 c2 \\
128 c3 \\
129"
130
131do_functionname() {
132 command1 ${VAL1} ${VAL2}
133 command2 ${VAL3} ${VAL4}
134}
135"""
136 def _testeditfile(self, varvalues, compareto, dummyvars=None):
137 if dummyvars is None:
138 dummyvars = []
139 with tempfile.NamedTemporaryFile('w', delete=False) as tf:
140 tf.write(self._origfile)
141 tf.close()
142 try:
143 varcalls = []
144 def handle_file(varname, origvalue, op, newlines):
145 self.assertIn(varname, varvalues, 'Callback called for variable %s not in the list!' % varname)
146 self.assertNotIn(varname, dummyvars, 'Callback called for variable %s in dummy list!' % varname)
147 varcalls.append(varname)
148 return varvalues[varname]
149
150 bb.utils.edit_metadata_file(tf.name, varvalues.keys(), handle_file)
151 with open(tf.name) as f:
152 modfile = f.readlines()
153 # Ensure the output matches the expected output
154 self.assertEqual(compareto.splitlines(True), modfile)
155 # Ensure the callback function was called for every variable we asked for
156 # (plus allow testing behaviour when a requested variable is not present)
157 self.assertEqual(sorted(varvalues.keys()), sorted(varcalls + dummyvars))
158 finally:
159 os.remove(tf.name)
160
161
162 def test_edit_metadata_file_nochange(self):
163 # Test file doesn't get modified with nothing to do
164 self._testeditfile({}, self._origfile)
165 # Test file doesn't get modified with only dummy variables
166 self._testeditfile({'DUMMY1': ('should_not_set', None, 0, True),
167 'DUMMY2': ('should_not_set_again', None, 0, True)}, self._origfile, dummyvars=['DUMMY1', 'DUMMY2'])
168 # Test file doesn't get modified with some the same values
169 self._testeditfile({'THIS': ('that', None, 0, True),
170 'OTHER': ('anothervalue', None, 0, True),
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500171 'MULTILINE3': (' c1 c2 c3 ', None, 4, False)}, self._origfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500172
173 def test_edit_metadata_file_1(self):
174
175 newfile1 = """
176# A comment
177HELLO = "newvalue"
178
179THIS = "that"
180
181# Another comment
182NOCHANGE = "samevalue"
183OTHER = 'anothervalue'
184
185MULTILINE = "a1 \\
186 a2 \\
187 a3"
188
189MULTILINE2 := " \\
190 b1 \\
191 b2 \\
192 b3 \\
193 "
194
195
196MULTILINE3 = " \\
197 c1 \\
198 c2 \\
199 c3 \\
200"
201
202do_functionname() {
203 command1 ${VAL1} ${VAL2}
204 command2 ${VAL3} ${VAL4}
205}
206"""
207 self._testeditfile({'HELLO': ('newvalue', None, 4, True)}, newfile1)
208
209
210 def test_edit_metadata_file_2(self):
211
212 newfile2 = """
213# A comment
214HELLO = "oldvalue"
215
216THIS = "that"
217
218# Another comment
219NOCHANGE = "samevalue"
220OTHER = 'anothervalue'
221
222MULTILINE = " \\
223 d1 \\
224 d2 \\
225 d3 \\
226 "
227
228MULTILINE2 := " \\
229 b1 \\
230 b2 \\
231 b3 \\
232 "
233
234
235MULTILINE3 = "nowsingle"
236
237do_functionname() {
238 command1 ${VAL1} ${VAL2}
239 command2 ${VAL3} ${VAL4}
240}
241"""
242 self._testeditfile({'MULTILINE': (['d1','d2','d3'], None, 4, False),
243 'MULTILINE3': ('nowsingle', None, 4, True),
244 'NOTPRESENT': (['a', 'b'], None, 4, False)}, newfile2, dummyvars=['NOTPRESENT'])
245
246
247 def test_edit_metadata_file_3(self):
248
249 newfile3 = """
250# A comment
251HELLO = "oldvalue"
252
253# Another comment
254NOCHANGE = "samevalue"
255OTHER = "yetanothervalue"
256
257MULTILINE = "e1 \\
258 e2 \\
259 e3 \\
260 "
261
262MULTILINE2 := "f1 \\
263\tf2 \\
264\t"
265
266
267MULTILINE3 = " \\
268 c1 \\
269 c2 \\
270 c3 \\
271"
272
273do_functionname() {
274 othercommand_one a b c
275 othercommand_two d e f
276}
277"""
278
279 self._testeditfile({'do_functionname()': (['othercommand_one a b c', 'othercommand_two d e f'], None, 4, False),
280 'MULTILINE2': (['f1', 'f2'], None, '\t', True),
281 'MULTILINE': (['e1', 'e2', 'e3'], None, -1, True),
282 'THIS': (None, None, 0, False),
283 'OTHER': ('yetanothervalue', None, 0, True)}, newfile3)
284
285
286 def test_edit_metadata_file_4(self):
287
288 newfile4 = """
289# A comment
290HELLO = "oldvalue"
291
292THIS = "that"
293
294# Another comment
295OTHER = 'anothervalue'
296
297MULTILINE = "a1 \\
298 a2 \\
299 a3"
300
301MULTILINE2 := " \\
302 b1 \\
303 b2 \\
304 b3 \\
305 "
306
307
308"""
309
310 self._testeditfile({'NOCHANGE': (None, None, 0, False),
311 'MULTILINE3': (None, None, 0, False),
312 'THIS': ('that', None, 0, False),
313 'do_functionname()': (None, None, 0, False)}, newfile4)
314
315
316 def test_edit_metadata(self):
317 newfile5 = """
318# A comment
319HELLO = "hithere"
320
321# A new comment
322THIS += "that"
323
324# Another comment
325NOCHANGE = "samevalue"
326OTHER = 'anothervalue'
327
328MULTILINE = "a1 \\
329 a2 \\
330 a3"
331
332MULTILINE2 := " \\
333 b1 \\
334 b2 \\
335 b3 \\
336 "
337
338
339MULTILINE3 = " \\
340 c1 \\
341 c2 \\
342 c3 \\
343"
344
345NEWVAR = "value"
346
347do_functionname() {
348 command1 ${VAL1} ${VAL2}
349 command2 ${VAL3} ${VAL4}
350}
351"""
352
353
354 def handle_var(varname, origvalue, op, newlines):
355 if varname == 'THIS':
356 newlines.append('# A new comment\n')
357 elif varname == 'do_functionname()':
358 newlines.append('NEWVAR = "value"\n')
359 newlines.append('\n')
360 valueitem = varvalues.get(varname, None)
361 if valueitem:
362 return valueitem
363 else:
364 return (origvalue, op, 0, True)
365
366 varvalues = {'HELLO': ('hithere', None, 0, True), 'THIS': ('that', '+=', 0, True)}
367 varlist = ['HELLO', 'THIS', 'do_functionname()']
368 (updated, newlines) = bb.utils.edit_metadata(self._origfile.splitlines(True), varlist, handle_var)
369 self.assertTrue(updated, 'List should be updated but isn\'t')
370 self.assertEqual(newlines, newfile5.splitlines(True))
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500371
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500372 # Make sure the orig value matches what we expect it to be
373 def test_edit_metadata_origvalue(self):
374 origfile = """
375MULTILINE = " stuff \\
376 morestuff"
377"""
378 expected_value = "stuff morestuff"
379 global value_in_callback
380 value_in_callback = ""
381
382 def handle_var(varname, origvalue, op, newlines):
383 global value_in_callback
384 value_in_callback = origvalue
385 return (origvalue, op, -1, False)
386
387 bb.utils.edit_metadata(origfile.splitlines(True),
388 ['MULTILINE'],
389 handle_var)
390
391 testvalue = re.sub('\s+', ' ', value_in_callback.strip())
392 self.assertEqual(expected_value, testvalue)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500393
394class EditBbLayersConf(unittest.TestCase):
395
396 def _test_bblayers_edit(self, before, after, add, remove, notadded, notremoved):
397 with tempfile.NamedTemporaryFile('w', delete=False) as tf:
398 tf.write(before)
399 tf.close()
400 try:
401 actual_notadded, actual_notremoved = bb.utils.edit_bblayers_conf(tf.name, add, remove)
402 with open(tf.name) as f:
403 actual_after = f.readlines()
404 self.assertEqual(after.splitlines(True), actual_after)
405 self.assertEqual(notadded, actual_notadded)
406 self.assertEqual(notremoved, actual_notremoved)
407 finally:
408 os.remove(tf.name)
409
410
411 def test_bblayers_remove(self):
412 before = r"""
413# A comment
414
415BBPATH = "${TOPDIR}"
416BBFILES ?= ""
417BBLAYERS = " \
418 /home/user/path/layer1 \
419 /home/user/path/layer2 \
420 /home/user/path/subpath/layer3 \
421 /home/user/path/layer4 \
422 "
423"""
424 after = r"""
425# A comment
426
427BBPATH = "${TOPDIR}"
428BBFILES ?= ""
429BBLAYERS = " \
430 /home/user/path/layer1 \
431 /home/user/path/subpath/layer3 \
432 /home/user/path/layer4 \
433 "
434"""
435 self._test_bblayers_edit(before, after,
436 None,
437 '/home/user/path/layer2',
438 [],
439 [])
440
441
442 def test_bblayers_add(self):
443 before = r"""
444# A comment
445
446BBPATH = "${TOPDIR}"
447BBFILES ?= ""
448BBLAYERS = " \
449 /home/user/path/layer1 \
450 /home/user/path/layer2 \
451 /home/user/path/subpath/layer3 \
452 /home/user/path/layer4 \
453 "
454"""
455 after = r"""
456# A comment
457
458BBPATH = "${TOPDIR}"
459BBFILES ?= ""
460BBLAYERS = " \
461 /home/user/path/layer1 \
462 /home/user/path/layer2 \
463 /home/user/path/subpath/layer3 \
464 /home/user/path/layer4 \
465 /other/path/to/layer5 \
466 "
467"""
468 self._test_bblayers_edit(before, after,
469 '/other/path/to/layer5/',
470 None,
471 [],
472 [])
473
474
475 def test_bblayers_add_remove(self):
476 before = r"""
477# A comment
478
479BBPATH = "${TOPDIR}"
480BBFILES ?= ""
481BBLAYERS = " \
482 /home/user/path/layer1 \
483 /home/user/path/layer2 \
484 /home/user/path/subpath/layer3 \
485 /home/user/path/layer4 \
486 "
487"""
488 after = r"""
489# A comment
490
491BBPATH = "${TOPDIR}"
492BBFILES ?= ""
493BBLAYERS = " \
494 /home/user/path/layer1 \
495 /home/user/path/layer2 \
496 /home/user/path/layer4 \
497 /other/path/to/layer5 \
498 "
499"""
500 self._test_bblayers_edit(before, after,
501 ['/other/path/to/layer5', '/home/user/path/layer2/'], '/home/user/path/subpath/layer3/',
502 ['/home/user/path/layer2'],
503 [])
504
505
506 def test_bblayers_add_remove_home(self):
507 before = r"""
508# A comment
509
510BBPATH = "${TOPDIR}"
511BBFILES ?= ""
512BBLAYERS = " \
513 ~/path/layer1 \
514 ~/path/layer2 \
515 ~/otherpath/layer3 \
516 ~/path/layer4 \
517 "
518"""
519 after = r"""
520# A comment
521
522BBPATH = "${TOPDIR}"
523BBFILES ?= ""
524BBLAYERS = " \
525 ~/path/layer2 \
526 ~/path/layer4 \
527 ~/path2/layer5 \
528 "
529"""
530 self._test_bblayers_edit(before, after,
531 [os.environ['HOME'] + '/path/layer4', '~/path2/layer5'],
532 [os.environ['HOME'] + '/otherpath/layer3', '~/path/layer1', '~/path/notinlist'],
533 [os.environ['HOME'] + '/path/layer4'],
534 ['~/path/notinlist'])
535
536
537 def test_bblayers_add_remove_plusequals(self):
538 before = r"""
539# A comment
540
541BBPATH = "${TOPDIR}"
542BBFILES ?= ""
543BBLAYERS += " \
544 /home/user/path/layer1 \
545 /home/user/path/layer2 \
546 "
547"""
548 after = r"""
549# A comment
550
551BBPATH = "${TOPDIR}"
552BBFILES ?= ""
553BBLAYERS += " \
554 /home/user/path/layer2 \
555 /home/user/path/layer3 \
556 "
557"""
558 self._test_bblayers_edit(before, after,
559 '/home/user/path/layer3',
560 '/home/user/path/layer1',
561 [],
562 [])
563
564
565 def test_bblayers_add_remove_plusequals2(self):
566 before = r"""
567# A comment
568
569BBPATH = "${TOPDIR}"
570BBFILES ?= ""
571BBLAYERS += " \
572 /home/user/path/layer1 \
573 /home/user/path/layer2 \
574 /home/user/path/layer3 \
575 "
576BBLAYERS += "/home/user/path/layer4"
577BBLAYERS += "/home/user/path/layer5"
578"""
579 after = r"""
580# A comment
581
582BBPATH = "${TOPDIR}"
583BBFILES ?= ""
584BBLAYERS += " \
585 /home/user/path/layer2 \
586 /home/user/path/layer3 \
587 "
588BBLAYERS += "/home/user/path/layer5"
589BBLAYERS += "/home/user/otherpath/layer6"
590"""
591 self._test_bblayers_edit(before, after,
592 ['/home/user/otherpath/layer6', '/home/user/path/layer3'], ['/home/user/path/layer1', '/home/user/path/layer4', '/home/user/path/layer7'],
593 ['/home/user/path/layer3'],
594 ['/home/user/path/layer7'])