xref: /OK3568_Linux_fs/yocto/poky/bitbake/lib/bb/tests/utils.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#
2*4882a593Smuzhiyun# BitBake Tests for utils.py
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun# Copyright (C) 2012 Richard Purdie
5*4882a593Smuzhiyun#
6*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only
7*4882a593Smuzhiyun#
8*4882a593Smuzhiyun
9*4882a593Smuzhiyunimport unittest
10*4882a593Smuzhiyunimport bb
11*4882a593Smuzhiyunimport os
12*4882a593Smuzhiyunimport tempfile
13*4882a593Smuzhiyunimport re
14*4882a593Smuzhiyun
15*4882a593Smuzhiyunclass VerCmpString(unittest.TestCase):
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun    def test_vercmpstring(self):
18*4882a593Smuzhiyun        result = bb.utils.vercmp_string('1', '2')
19*4882a593Smuzhiyun        self.assertTrue(result < 0)
20*4882a593Smuzhiyun        result = bb.utils.vercmp_string('2', '1')
21*4882a593Smuzhiyun        self.assertTrue(result > 0)
22*4882a593Smuzhiyun        result = bb.utils.vercmp_string('1', '1.0')
23*4882a593Smuzhiyun        self.assertTrue(result < 0)
24*4882a593Smuzhiyun        result = bb.utils.vercmp_string('1', '1.1')
25*4882a593Smuzhiyun        self.assertTrue(result < 0)
26*4882a593Smuzhiyun        result = bb.utils.vercmp_string('1.1', '1_p2')
27*4882a593Smuzhiyun        self.assertTrue(result < 0)
28*4882a593Smuzhiyun        result = bb.utils.vercmp_string('1.0', '1.0+1.1-beta1')
29*4882a593Smuzhiyun        self.assertTrue(result < 0)
30*4882a593Smuzhiyun        result = bb.utils.vercmp_string('1.1', '1.0+1.1-beta1')
31*4882a593Smuzhiyun        self.assertTrue(result > 0)
32*4882a593Smuzhiyun        result = bb.utils.vercmp_string('1a', '1a1')
33*4882a593Smuzhiyun        self.assertTrue(result < 0)
34*4882a593Smuzhiyun        result = bb.utils.vercmp_string('1a1', '1a')
35*4882a593Smuzhiyun        self.assertTrue(result > 0)
36*4882a593Smuzhiyun        result = bb.utils.vercmp_string('1.', '1.1')
37*4882a593Smuzhiyun        self.assertTrue(result < 0)
38*4882a593Smuzhiyun        result = bb.utils.vercmp_string('1.1', '1.')
39*4882a593Smuzhiyun        self.assertTrue(result > 0)
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun    def test_explode_dep_versions(self):
42*4882a593Smuzhiyun        correctresult = {"foo" : ["= 1.10"]}
43*4882a593Smuzhiyun        result = bb.utils.explode_dep_versions2("foo (= 1.10)")
44*4882a593Smuzhiyun        self.assertEqual(result, correctresult)
45*4882a593Smuzhiyun        result = bb.utils.explode_dep_versions2("foo (=1.10)")
46*4882a593Smuzhiyun        self.assertEqual(result, correctresult)
47*4882a593Smuzhiyun        result = bb.utils.explode_dep_versions2("foo ( = 1.10)")
48*4882a593Smuzhiyun        self.assertEqual(result, correctresult)
49*4882a593Smuzhiyun        result = bb.utils.explode_dep_versions2("foo ( =1.10)")
50*4882a593Smuzhiyun        self.assertEqual(result, correctresult)
51*4882a593Smuzhiyun        result = bb.utils.explode_dep_versions2("foo ( = 1.10 )")
52*4882a593Smuzhiyun        self.assertEqual(result, correctresult)
53*4882a593Smuzhiyun        result = bb.utils.explode_dep_versions2("foo ( =1.10 )")
54*4882a593Smuzhiyun        self.assertEqual(result, correctresult)
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun    def test_vercmp_string_op(self):
57*4882a593Smuzhiyun        compareops = [('1', '1', '=', True),
58*4882a593Smuzhiyun                      ('1', '1', '==', True),
59*4882a593Smuzhiyun                      ('1', '1', '!=', False),
60*4882a593Smuzhiyun                      ('1', '1', '>', False),
61*4882a593Smuzhiyun                      ('1', '1', '<', False),
62*4882a593Smuzhiyun                      ('1', '1', '>=', True),
63*4882a593Smuzhiyun                      ('1', '1', '<=', True),
64*4882a593Smuzhiyun                      ('1', '0', '=', False),
65*4882a593Smuzhiyun                      ('1', '0', '==', False),
66*4882a593Smuzhiyun                      ('1', '0', '!=', True),
67*4882a593Smuzhiyun                      ('1', '0', '>', True),
68*4882a593Smuzhiyun                      ('1', '0', '<', False),
69*4882a593Smuzhiyun                      ('1', '0', '>>', True),
70*4882a593Smuzhiyun                      ('1', '0', '<<', False),
71*4882a593Smuzhiyun                      ('1', '0', '>=', True),
72*4882a593Smuzhiyun                      ('1', '0', '<=', False),
73*4882a593Smuzhiyun                      ('0', '1', '=', False),
74*4882a593Smuzhiyun                      ('0', '1', '==', False),
75*4882a593Smuzhiyun                      ('0', '1', '!=', True),
76*4882a593Smuzhiyun                      ('0', '1', '>', False),
77*4882a593Smuzhiyun                      ('0', '1', '<', True),
78*4882a593Smuzhiyun                      ('0', '1', '>>', False),
79*4882a593Smuzhiyun                      ('0', '1', '<<', True),
80*4882a593Smuzhiyun                      ('0', '1', '>=', False),
81*4882a593Smuzhiyun                      ('0', '1', '<=', True)]
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun        for arg1, arg2, op, correctresult in compareops:
84*4882a593Smuzhiyun            result = bb.utils.vercmp_string_op(arg1, arg2, op)
85*4882a593Smuzhiyun            self.assertEqual(result, correctresult, 'vercmp_string_op("%s", "%s", "%s") != %s' % (arg1, arg2, op, correctresult))
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun        # Check that clearly invalid operator raises an exception
88*4882a593Smuzhiyun        self.assertRaises(bb.utils.VersionStringException, bb.utils.vercmp_string_op, '0', '0', '$')
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun
91*4882a593Smuzhiyunclass Path(unittest.TestCase):
92*4882a593Smuzhiyun    def test_unsafe_delete_path(self):
93*4882a593Smuzhiyun        checkitems = [('/', True),
94*4882a593Smuzhiyun                      ('//', True),
95*4882a593Smuzhiyun                      ('///', True),
96*4882a593Smuzhiyun                      (os.getcwd().count(os.sep) * ('..' + os.sep), True),
97*4882a593Smuzhiyun                      (os.environ.get('HOME', '/home/test'), True),
98*4882a593Smuzhiyun                      ('/home/someone', True),
99*4882a593Smuzhiyun                      ('/home/other/', True),
100*4882a593Smuzhiyun                      ('/home/other/subdir', False),
101*4882a593Smuzhiyun                      ('', False)]
102*4882a593Smuzhiyun        for arg1, correctresult in checkitems:
103*4882a593Smuzhiyun            result = bb.utils._check_unsafe_delete_path(arg1)
104*4882a593Smuzhiyun            self.assertEqual(result, correctresult, '_check_unsafe_delete_path("%s") != %s' % (arg1, correctresult))
105*4882a593Smuzhiyun
106*4882a593Smuzhiyunclass Checksum(unittest.TestCase):
107*4882a593Smuzhiyun    filler = b"Shiver me timbers square-rigged spike Gold Road galleon bilge water boatswain wherry jack pirate. Mizzenmast rum lad Privateer jack salmagundi hang the jib piracy Pieces of Eight Corsair. Parrel marooned black spot yawl provost quarterdeck cable no prey, no pay spirits lateen sail."
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun    def test_md5(self):
110*4882a593Smuzhiyun        import hashlib
111*4882a593Smuzhiyun        with tempfile.NamedTemporaryFile() as f:
112*4882a593Smuzhiyun            f.write(self.filler)
113*4882a593Smuzhiyun            f.flush()
114*4882a593Smuzhiyun            checksum = bb.utils.md5_file(f.name)
115*4882a593Smuzhiyun            self.assertEqual(checksum, "bd572cd5de30a785f4efcb6eaf5089e3")
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun    def test_sha1(self):
118*4882a593Smuzhiyun        import hashlib
119*4882a593Smuzhiyun        with tempfile.NamedTemporaryFile() as f:
120*4882a593Smuzhiyun            f.write(self.filler)
121*4882a593Smuzhiyun            f.flush()
122*4882a593Smuzhiyun            checksum = bb.utils.sha1_file(f.name)
123*4882a593Smuzhiyun            self.assertEqual(checksum, "249eb8fd654732ea836d5e702d7aa567898eca71")
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun    def test_sha256(self):
126*4882a593Smuzhiyun        import hashlib
127*4882a593Smuzhiyun        with tempfile.NamedTemporaryFile() as f:
128*4882a593Smuzhiyun            f.write(self.filler)
129*4882a593Smuzhiyun            f.flush()
130*4882a593Smuzhiyun            checksum = bb.utils.sha256_file(f.name)
131*4882a593Smuzhiyun            self.assertEqual(checksum, "fcfbae8bf6b721dbb9d2dc6a9334a58f2031a9a9b302999243f99da4d7f12d0f")
132*4882a593Smuzhiyun
133*4882a593Smuzhiyunclass EditMetadataFile(unittest.TestCase):
134*4882a593Smuzhiyun    _origfile = """
135*4882a593Smuzhiyun# A comment
136*4882a593SmuzhiyunHELLO = "oldvalue"
137*4882a593Smuzhiyun
138*4882a593SmuzhiyunTHIS = "that"
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun# Another comment
141*4882a593SmuzhiyunNOCHANGE = "samevalue"
142*4882a593SmuzhiyunOTHER = 'anothervalue'
143*4882a593Smuzhiyun
144*4882a593SmuzhiyunMULTILINE = "a1 \\
145*4882a593Smuzhiyun             a2 \\
146*4882a593Smuzhiyun             a3"
147*4882a593Smuzhiyun
148*4882a593SmuzhiyunMULTILINE2 := " \\
149*4882a593Smuzhiyun               b1 \\
150*4882a593Smuzhiyun               b2 \\
151*4882a593Smuzhiyun               b3 \\
152*4882a593Smuzhiyun               "
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun
155*4882a593SmuzhiyunMULTILINE3 = " \\
156*4882a593Smuzhiyun              c1 \\
157*4882a593Smuzhiyun              c2 \\
158*4882a593Smuzhiyun              c3 \\
159*4882a593Smuzhiyun"
160*4882a593Smuzhiyun
161*4882a593Smuzhiyundo_functionname() {
162*4882a593Smuzhiyun    command1 ${VAL1} ${VAL2}
163*4882a593Smuzhiyun    command2 ${VAL3} ${VAL4}
164*4882a593Smuzhiyun}
165*4882a593Smuzhiyun"""
166*4882a593Smuzhiyun    def _testeditfile(self, varvalues, compareto, dummyvars=None):
167*4882a593Smuzhiyun        if dummyvars is None:
168*4882a593Smuzhiyun            dummyvars = []
169*4882a593Smuzhiyun        with tempfile.NamedTemporaryFile('w', delete=False) as tf:
170*4882a593Smuzhiyun            tf.write(self._origfile)
171*4882a593Smuzhiyun            tf.close()
172*4882a593Smuzhiyun            try:
173*4882a593Smuzhiyun                varcalls = []
174*4882a593Smuzhiyun                def handle_file(varname, origvalue, op, newlines):
175*4882a593Smuzhiyun                    self.assertIn(varname, varvalues, 'Callback called for variable %s not in the list!' % varname)
176*4882a593Smuzhiyun                    self.assertNotIn(varname, dummyvars, 'Callback called for variable %s in dummy list!' % varname)
177*4882a593Smuzhiyun                    varcalls.append(varname)
178*4882a593Smuzhiyun                    return varvalues[varname]
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun                bb.utils.edit_metadata_file(tf.name, varvalues.keys(), handle_file)
181*4882a593Smuzhiyun                with open(tf.name) as f:
182*4882a593Smuzhiyun                    modfile = f.readlines()
183*4882a593Smuzhiyun                # Ensure the output matches the expected output
184*4882a593Smuzhiyun                self.assertEqual(compareto.splitlines(True), modfile)
185*4882a593Smuzhiyun                # Ensure the callback function was called for every variable we asked for
186*4882a593Smuzhiyun                # (plus allow testing behaviour when a requested variable is not present)
187*4882a593Smuzhiyun                self.assertEqual(sorted(varvalues.keys()), sorted(varcalls + dummyvars))
188*4882a593Smuzhiyun            finally:
189*4882a593Smuzhiyun                os.remove(tf.name)
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun    def test_edit_metadata_file_nochange(self):
193*4882a593Smuzhiyun        # Test file doesn't get modified with nothing to do
194*4882a593Smuzhiyun        self._testeditfile({}, self._origfile)
195*4882a593Smuzhiyun        # Test file doesn't get modified with only dummy variables
196*4882a593Smuzhiyun        self._testeditfile({'DUMMY1': ('should_not_set', None, 0, True),
197*4882a593Smuzhiyun                        'DUMMY2': ('should_not_set_again', None, 0, True)}, self._origfile, dummyvars=['DUMMY1', 'DUMMY2'])
198*4882a593Smuzhiyun        # Test file doesn't get modified with some the same values
199*4882a593Smuzhiyun        self._testeditfile({'THIS': ('that', None, 0, True),
200*4882a593Smuzhiyun                        'OTHER': ('anothervalue', None, 0, True),
201*4882a593Smuzhiyun                        'MULTILINE3': ('               c1               c2               c3 ', None, 4, False)}, self._origfile)
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun    def test_edit_metadata_file_1(self):
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun        newfile1 = """
206*4882a593Smuzhiyun# A comment
207*4882a593SmuzhiyunHELLO = "newvalue"
208*4882a593Smuzhiyun
209*4882a593SmuzhiyunTHIS = "that"
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun# Another comment
212*4882a593SmuzhiyunNOCHANGE = "samevalue"
213*4882a593SmuzhiyunOTHER = 'anothervalue'
214*4882a593Smuzhiyun
215*4882a593SmuzhiyunMULTILINE = "a1 \\
216*4882a593Smuzhiyun             a2 \\
217*4882a593Smuzhiyun             a3"
218*4882a593Smuzhiyun
219*4882a593SmuzhiyunMULTILINE2 := " \\
220*4882a593Smuzhiyun               b1 \\
221*4882a593Smuzhiyun               b2 \\
222*4882a593Smuzhiyun               b3 \\
223*4882a593Smuzhiyun               "
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun
226*4882a593SmuzhiyunMULTILINE3 = " \\
227*4882a593Smuzhiyun              c1 \\
228*4882a593Smuzhiyun              c2 \\
229*4882a593Smuzhiyun              c3 \\
230*4882a593Smuzhiyun"
231*4882a593Smuzhiyun
232*4882a593Smuzhiyundo_functionname() {
233*4882a593Smuzhiyun    command1 ${VAL1} ${VAL2}
234*4882a593Smuzhiyun    command2 ${VAL3} ${VAL4}
235*4882a593Smuzhiyun}
236*4882a593Smuzhiyun"""
237*4882a593Smuzhiyun        self._testeditfile({'HELLO': ('newvalue', None, 4, True)}, newfile1)
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun    def test_edit_metadata_file_2(self):
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun        newfile2 = """
243*4882a593Smuzhiyun# A comment
244*4882a593SmuzhiyunHELLO = "oldvalue"
245*4882a593Smuzhiyun
246*4882a593SmuzhiyunTHIS = "that"
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun# Another comment
249*4882a593SmuzhiyunNOCHANGE = "samevalue"
250*4882a593SmuzhiyunOTHER = 'anothervalue'
251*4882a593Smuzhiyun
252*4882a593SmuzhiyunMULTILINE = " \\
253*4882a593Smuzhiyun    d1 \\
254*4882a593Smuzhiyun    d2 \\
255*4882a593Smuzhiyun    d3 \\
256*4882a593Smuzhiyun    "
257*4882a593Smuzhiyun
258*4882a593SmuzhiyunMULTILINE2 := " \\
259*4882a593Smuzhiyun               b1 \\
260*4882a593Smuzhiyun               b2 \\
261*4882a593Smuzhiyun               b3 \\
262*4882a593Smuzhiyun               "
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun
265*4882a593SmuzhiyunMULTILINE3 = "nowsingle"
266*4882a593Smuzhiyun
267*4882a593Smuzhiyundo_functionname() {
268*4882a593Smuzhiyun    command1 ${VAL1} ${VAL2}
269*4882a593Smuzhiyun    command2 ${VAL3} ${VAL4}
270*4882a593Smuzhiyun}
271*4882a593Smuzhiyun"""
272*4882a593Smuzhiyun        self._testeditfile({'MULTILINE': (['d1','d2','d3'], None, 4, False),
273*4882a593Smuzhiyun                        'MULTILINE3': ('nowsingle', None, 4, True),
274*4882a593Smuzhiyun                        'NOTPRESENT': (['a', 'b'], None, 4, False)}, newfile2, dummyvars=['NOTPRESENT'])
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun    def test_edit_metadata_file_3(self):
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun        newfile3 = """
280*4882a593Smuzhiyun# A comment
281*4882a593SmuzhiyunHELLO = "oldvalue"
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun# Another comment
284*4882a593SmuzhiyunNOCHANGE = "samevalue"
285*4882a593SmuzhiyunOTHER = "yetanothervalue"
286*4882a593Smuzhiyun
287*4882a593SmuzhiyunMULTILINE = "e1 \\
288*4882a593Smuzhiyun             e2 \\
289*4882a593Smuzhiyun             e3 \\
290*4882a593Smuzhiyun             "
291*4882a593Smuzhiyun
292*4882a593SmuzhiyunMULTILINE2 := "f1 \\
293*4882a593Smuzhiyun\tf2 \\
294*4882a593Smuzhiyun\t"
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun
297*4882a593SmuzhiyunMULTILINE3 = " \\
298*4882a593Smuzhiyun              c1 \\
299*4882a593Smuzhiyun              c2 \\
300*4882a593Smuzhiyun              c3 \\
301*4882a593Smuzhiyun"
302*4882a593Smuzhiyun
303*4882a593Smuzhiyundo_functionname() {
304*4882a593Smuzhiyun    othercommand_one a b c
305*4882a593Smuzhiyun    othercommand_two d e f
306*4882a593Smuzhiyun}
307*4882a593Smuzhiyun"""
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun        self._testeditfile({'do_functionname()': (['othercommand_one a b c', 'othercommand_two d e f'], None, 4, False),
310*4882a593Smuzhiyun                        'MULTILINE2': (['f1', 'f2'], None, '\t', True),
311*4882a593Smuzhiyun                        'MULTILINE': (['e1', 'e2', 'e3'], None, -1, True),
312*4882a593Smuzhiyun                        'THIS': (None, None, 0, False),
313*4882a593Smuzhiyun                        'OTHER': ('yetanothervalue', None, 0, True)}, newfile3)
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun    def test_edit_metadata_file_4(self):
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun        newfile4 = """
319*4882a593Smuzhiyun# A comment
320*4882a593SmuzhiyunHELLO = "oldvalue"
321*4882a593Smuzhiyun
322*4882a593SmuzhiyunTHIS = "that"
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun# Another comment
325*4882a593SmuzhiyunOTHER = 'anothervalue'
326*4882a593Smuzhiyun
327*4882a593SmuzhiyunMULTILINE = "a1 \\
328*4882a593Smuzhiyun             a2 \\
329*4882a593Smuzhiyun             a3"
330*4882a593Smuzhiyun
331*4882a593SmuzhiyunMULTILINE2 := " \\
332*4882a593Smuzhiyun               b1 \\
333*4882a593Smuzhiyun               b2 \\
334*4882a593Smuzhiyun               b3 \\
335*4882a593Smuzhiyun               "
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun"""
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun        self._testeditfile({'NOCHANGE': (None, None, 0, False),
341*4882a593Smuzhiyun                        'MULTILINE3': (None, None, 0, False),
342*4882a593Smuzhiyun                        'THIS': ('that', None, 0, False),
343*4882a593Smuzhiyun                        'do_functionname()': (None, None, 0, False)}, newfile4)
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun    def test_edit_metadata(self):
347*4882a593Smuzhiyun        newfile5 = """
348*4882a593Smuzhiyun# A comment
349*4882a593SmuzhiyunHELLO = "hithere"
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun# A new comment
352*4882a593SmuzhiyunTHIS += "that"
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun# Another comment
355*4882a593SmuzhiyunNOCHANGE = "samevalue"
356*4882a593SmuzhiyunOTHER = 'anothervalue'
357*4882a593Smuzhiyun
358*4882a593SmuzhiyunMULTILINE = "a1 \\
359*4882a593Smuzhiyun             a2 \\
360*4882a593Smuzhiyun             a3"
361*4882a593Smuzhiyun
362*4882a593SmuzhiyunMULTILINE2 := " \\
363*4882a593Smuzhiyun               b1 \\
364*4882a593Smuzhiyun               b2 \\
365*4882a593Smuzhiyun               b3 \\
366*4882a593Smuzhiyun               "
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun
369*4882a593SmuzhiyunMULTILINE3 = " \\
370*4882a593Smuzhiyun              c1 \\
371*4882a593Smuzhiyun              c2 \\
372*4882a593Smuzhiyun              c3 \\
373*4882a593Smuzhiyun"
374*4882a593Smuzhiyun
375*4882a593SmuzhiyunNEWVAR = "value"
376*4882a593Smuzhiyun
377*4882a593Smuzhiyundo_functionname() {
378*4882a593Smuzhiyun    command1 ${VAL1} ${VAL2}
379*4882a593Smuzhiyun    command2 ${VAL3} ${VAL4}
380*4882a593Smuzhiyun}
381*4882a593Smuzhiyun"""
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun        def handle_var(varname, origvalue, op, newlines):
385*4882a593Smuzhiyun            if varname == 'THIS':
386*4882a593Smuzhiyun                newlines.append('# A new comment\n')
387*4882a593Smuzhiyun            elif varname == 'do_functionname()':
388*4882a593Smuzhiyun                newlines.append('NEWVAR = "value"\n')
389*4882a593Smuzhiyun                newlines.append('\n')
390*4882a593Smuzhiyun            valueitem = varvalues.get(varname, None)
391*4882a593Smuzhiyun            if valueitem:
392*4882a593Smuzhiyun                return valueitem
393*4882a593Smuzhiyun            else:
394*4882a593Smuzhiyun                return (origvalue, op, 0, True)
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun        varvalues = {'HELLO': ('hithere', None, 0, True), 'THIS': ('that', '+=', 0, True)}
397*4882a593Smuzhiyun        varlist = ['HELLO', 'THIS', 'do_functionname()']
398*4882a593Smuzhiyun        (updated, newlines) = bb.utils.edit_metadata(self._origfile.splitlines(True), varlist, handle_var)
399*4882a593Smuzhiyun        self.assertTrue(updated, 'List should be updated but isn\'t')
400*4882a593Smuzhiyun        self.assertEqual(newlines, newfile5.splitlines(True))
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun    # Make sure the orig value matches what we expect it to be
403*4882a593Smuzhiyun    def test_edit_metadata_origvalue(self):
404*4882a593Smuzhiyun        origfile = """
405*4882a593SmuzhiyunMULTILINE = "  stuff \\
406*4882a593Smuzhiyun    morestuff"
407*4882a593Smuzhiyun"""
408*4882a593Smuzhiyun        expected_value = "stuff morestuff"
409*4882a593Smuzhiyun        global value_in_callback
410*4882a593Smuzhiyun        value_in_callback = ""
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun        def handle_var(varname, origvalue, op, newlines):
413*4882a593Smuzhiyun            global value_in_callback
414*4882a593Smuzhiyun            value_in_callback = origvalue
415*4882a593Smuzhiyun            return (origvalue, op, -1, False)
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun        bb.utils.edit_metadata(origfile.splitlines(True),
418*4882a593Smuzhiyun                               ['MULTILINE'],
419*4882a593Smuzhiyun                               handle_var)
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun        testvalue = re.sub(r'\s+', ' ', value_in_callback.strip())
422*4882a593Smuzhiyun        self.assertEqual(expected_value, testvalue)
423*4882a593Smuzhiyun
424*4882a593Smuzhiyunclass EditBbLayersConf(unittest.TestCase):
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun    def _test_bblayers_edit(self, before, after, add, remove, notadded, notremoved):
427*4882a593Smuzhiyun        with tempfile.NamedTemporaryFile('w', delete=False) as tf:
428*4882a593Smuzhiyun            tf.write(before)
429*4882a593Smuzhiyun            tf.close()
430*4882a593Smuzhiyun            try:
431*4882a593Smuzhiyun                actual_notadded, actual_notremoved = bb.utils.edit_bblayers_conf(tf.name, add, remove)
432*4882a593Smuzhiyun                with open(tf.name) as f:
433*4882a593Smuzhiyun                    actual_after = f.readlines()
434*4882a593Smuzhiyun                self.assertEqual(after.splitlines(True), actual_after)
435*4882a593Smuzhiyun                self.assertEqual(notadded, actual_notadded)
436*4882a593Smuzhiyun                self.assertEqual(notremoved, actual_notremoved)
437*4882a593Smuzhiyun            finally:
438*4882a593Smuzhiyun                os.remove(tf.name)
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun    def test_bblayers_remove(self):
442*4882a593Smuzhiyun        before = r"""
443*4882a593Smuzhiyun# A comment
444*4882a593Smuzhiyun
445*4882a593SmuzhiyunBBPATH = "${TOPDIR}"
446*4882a593SmuzhiyunBBFILES ?= ""
447*4882a593SmuzhiyunBBLAYERS = " \
448*4882a593Smuzhiyun  /home/user/path/layer1 \
449*4882a593Smuzhiyun  /home/user/path/layer2 \
450*4882a593Smuzhiyun  /home/user/path/subpath/layer3 \
451*4882a593Smuzhiyun  /home/user/path/layer4 \
452*4882a593Smuzhiyun  "
453*4882a593Smuzhiyun"""
454*4882a593Smuzhiyun        after = r"""
455*4882a593Smuzhiyun# A comment
456*4882a593Smuzhiyun
457*4882a593SmuzhiyunBBPATH = "${TOPDIR}"
458*4882a593SmuzhiyunBBFILES ?= ""
459*4882a593SmuzhiyunBBLAYERS = " \
460*4882a593Smuzhiyun  /home/user/path/layer1 \
461*4882a593Smuzhiyun  /home/user/path/subpath/layer3 \
462*4882a593Smuzhiyun  /home/user/path/layer4 \
463*4882a593Smuzhiyun  "
464*4882a593Smuzhiyun"""
465*4882a593Smuzhiyun        self._test_bblayers_edit(before, after,
466*4882a593Smuzhiyun                                 None,
467*4882a593Smuzhiyun                                 '/home/user/path/layer2',
468*4882a593Smuzhiyun                                 [],
469*4882a593Smuzhiyun                                 [])
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun    def test_bblayers_add(self):
473*4882a593Smuzhiyun        before = r"""
474*4882a593Smuzhiyun# A comment
475*4882a593Smuzhiyun
476*4882a593SmuzhiyunBBPATH = "${TOPDIR}"
477*4882a593SmuzhiyunBBFILES ?= ""
478*4882a593SmuzhiyunBBLAYERS = " \
479*4882a593Smuzhiyun  /home/user/path/layer1 \
480*4882a593Smuzhiyun  /home/user/path/layer2 \
481*4882a593Smuzhiyun  /home/user/path/subpath/layer3 \
482*4882a593Smuzhiyun  /home/user/path/layer4 \
483*4882a593Smuzhiyun  "
484*4882a593Smuzhiyun"""
485*4882a593Smuzhiyun        after = r"""
486*4882a593Smuzhiyun# A comment
487*4882a593Smuzhiyun
488*4882a593SmuzhiyunBBPATH = "${TOPDIR}"
489*4882a593SmuzhiyunBBFILES ?= ""
490*4882a593SmuzhiyunBBLAYERS = " \
491*4882a593Smuzhiyun  /home/user/path/layer1 \
492*4882a593Smuzhiyun  /home/user/path/layer2 \
493*4882a593Smuzhiyun  /home/user/path/subpath/layer3 \
494*4882a593Smuzhiyun  /home/user/path/layer4 \
495*4882a593Smuzhiyun  /other/path/to/layer5 \
496*4882a593Smuzhiyun  "
497*4882a593Smuzhiyun"""
498*4882a593Smuzhiyun        self._test_bblayers_edit(before, after,
499*4882a593Smuzhiyun                                 '/other/path/to/layer5/',
500*4882a593Smuzhiyun                                 None,
501*4882a593Smuzhiyun                                 [],
502*4882a593Smuzhiyun                                 [])
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun    def test_bblayers_add_remove(self):
506*4882a593Smuzhiyun        before = r"""
507*4882a593Smuzhiyun# A comment
508*4882a593Smuzhiyun
509*4882a593SmuzhiyunBBPATH = "${TOPDIR}"
510*4882a593SmuzhiyunBBFILES ?= ""
511*4882a593SmuzhiyunBBLAYERS = " \
512*4882a593Smuzhiyun  /home/user/path/layer1 \
513*4882a593Smuzhiyun  /home/user/path/layer2 \
514*4882a593Smuzhiyun  /home/user/path/subpath/layer3 \
515*4882a593Smuzhiyun  /home/user/path/layer4 \
516*4882a593Smuzhiyun  "
517*4882a593Smuzhiyun"""
518*4882a593Smuzhiyun        after = r"""
519*4882a593Smuzhiyun# A comment
520*4882a593Smuzhiyun
521*4882a593SmuzhiyunBBPATH = "${TOPDIR}"
522*4882a593SmuzhiyunBBFILES ?= ""
523*4882a593SmuzhiyunBBLAYERS = " \
524*4882a593Smuzhiyun  /home/user/path/layer1 \
525*4882a593Smuzhiyun  /home/user/path/layer2 \
526*4882a593Smuzhiyun  /home/user/path/layer4 \
527*4882a593Smuzhiyun  /other/path/to/layer5 \
528*4882a593Smuzhiyun  "
529*4882a593Smuzhiyun"""
530*4882a593Smuzhiyun        self._test_bblayers_edit(before, after,
531*4882a593Smuzhiyun                                 ['/other/path/to/layer5', '/home/user/path/layer2/'], '/home/user/path/subpath/layer3/',
532*4882a593Smuzhiyun                                 ['/home/user/path/layer2'],
533*4882a593Smuzhiyun                                 [])
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun    def test_bblayers_add_remove_home(self):
537*4882a593Smuzhiyun        before = r"""
538*4882a593Smuzhiyun# A comment
539*4882a593Smuzhiyun
540*4882a593SmuzhiyunBBPATH = "${TOPDIR}"
541*4882a593SmuzhiyunBBFILES ?= ""
542*4882a593SmuzhiyunBBLAYERS = " \
543*4882a593Smuzhiyun  ~/path/layer1 \
544*4882a593Smuzhiyun  ~/path/layer2 \
545*4882a593Smuzhiyun  ~/otherpath/layer3 \
546*4882a593Smuzhiyun  ~/path/layer4 \
547*4882a593Smuzhiyun  "
548*4882a593Smuzhiyun"""
549*4882a593Smuzhiyun        after = r"""
550*4882a593Smuzhiyun# A comment
551*4882a593Smuzhiyun
552*4882a593SmuzhiyunBBPATH = "${TOPDIR}"
553*4882a593SmuzhiyunBBFILES ?= ""
554*4882a593SmuzhiyunBBLAYERS = " \
555*4882a593Smuzhiyun  ~/path/layer2 \
556*4882a593Smuzhiyun  ~/path/layer4 \
557*4882a593Smuzhiyun  ~/path2/layer5 \
558*4882a593Smuzhiyun  "
559*4882a593Smuzhiyun"""
560*4882a593Smuzhiyun        self._test_bblayers_edit(before, after,
561*4882a593Smuzhiyun                                 [os.environ['HOME'] + '/path/layer4', '~/path2/layer5'],
562*4882a593Smuzhiyun                                 [os.environ['HOME'] + '/otherpath/layer3', '~/path/layer1', '~/path/notinlist'],
563*4882a593Smuzhiyun                                 [os.environ['HOME'] + '/path/layer4'],
564*4882a593Smuzhiyun                                 ['~/path/notinlist'])
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun    def test_bblayers_add_remove_plusequals(self):
568*4882a593Smuzhiyun        before = r"""
569*4882a593Smuzhiyun# A comment
570*4882a593Smuzhiyun
571*4882a593SmuzhiyunBBPATH = "${TOPDIR}"
572*4882a593SmuzhiyunBBFILES ?= ""
573*4882a593SmuzhiyunBBLAYERS += " \
574*4882a593Smuzhiyun  /home/user/path/layer1 \
575*4882a593Smuzhiyun  /home/user/path/layer2 \
576*4882a593Smuzhiyun  "
577*4882a593Smuzhiyun"""
578*4882a593Smuzhiyun        after = r"""
579*4882a593Smuzhiyun# A comment
580*4882a593Smuzhiyun
581*4882a593SmuzhiyunBBPATH = "${TOPDIR}"
582*4882a593SmuzhiyunBBFILES ?= ""
583*4882a593SmuzhiyunBBLAYERS += " \
584*4882a593Smuzhiyun  /home/user/path/layer2 \
585*4882a593Smuzhiyun  /home/user/path/layer3 \
586*4882a593Smuzhiyun  "
587*4882a593Smuzhiyun"""
588*4882a593Smuzhiyun        self._test_bblayers_edit(before, after,
589*4882a593Smuzhiyun                                 '/home/user/path/layer3',
590*4882a593Smuzhiyun                                 '/home/user/path/layer1',
591*4882a593Smuzhiyun                                 [],
592*4882a593Smuzhiyun                                 [])
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun    def test_bblayers_add_remove_plusequals2(self):
596*4882a593Smuzhiyun        before = r"""
597*4882a593Smuzhiyun# A comment
598*4882a593Smuzhiyun
599*4882a593SmuzhiyunBBPATH = "${TOPDIR}"
600*4882a593SmuzhiyunBBFILES ?= ""
601*4882a593SmuzhiyunBBLAYERS += " \
602*4882a593Smuzhiyun  /home/user/path/layer1 \
603*4882a593Smuzhiyun  /home/user/path/layer2 \
604*4882a593Smuzhiyun  /home/user/path/layer3 \
605*4882a593Smuzhiyun  "
606*4882a593SmuzhiyunBBLAYERS += "/home/user/path/layer4"
607*4882a593SmuzhiyunBBLAYERS += "/home/user/path/layer5"
608*4882a593Smuzhiyun"""
609*4882a593Smuzhiyun        after = r"""
610*4882a593Smuzhiyun# A comment
611*4882a593Smuzhiyun
612*4882a593SmuzhiyunBBPATH = "${TOPDIR}"
613*4882a593SmuzhiyunBBFILES ?= ""
614*4882a593SmuzhiyunBBLAYERS += " \
615*4882a593Smuzhiyun  /home/user/path/layer2 \
616*4882a593Smuzhiyun  /home/user/path/layer3 \
617*4882a593Smuzhiyun  "
618*4882a593SmuzhiyunBBLAYERS += "/home/user/path/layer5"
619*4882a593SmuzhiyunBBLAYERS += "/home/user/otherpath/layer6"
620*4882a593Smuzhiyun"""
621*4882a593Smuzhiyun        self._test_bblayers_edit(before, after,
622*4882a593Smuzhiyun                                 ['/home/user/otherpath/layer6', '/home/user/path/layer3'], ['/home/user/path/layer1', '/home/user/path/layer4', '/home/user/path/layer7'],
623*4882a593Smuzhiyun                                 ['/home/user/path/layer3'],
624*4882a593Smuzhiyun                                 ['/home/user/path/layer7'])
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun
627*4882a593Smuzhiyunclass GetReferencedVars(unittest.TestCase):
628*4882a593Smuzhiyun    def setUp(self):
629*4882a593Smuzhiyun        self.d = bb.data.init()
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun    def check_referenced(self, expression, expected_layers):
632*4882a593Smuzhiyun        vars = bb.utils.get_referenced_vars(expression, self.d)
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun        # Do the easy check first - is every variable accounted for?
635*4882a593Smuzhiyun        expected_vars = set.union(set(), *expected_layers)
636*4882a593Smuzhiyun        got_vars = set(vars)
637*4882a593Smuzhiyun        self.assertSetEqual(got_vars, expected_vars)
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun        # Now test the order of the layers
640*4882a593Smuzhiyun        start = 0
641*4882a593Smuzhiyun        for i, expected_layer in enumerate(expected_layers):
642*4882a593Smuzhiyun            got_layer = set(vars[start:len(expected_layer)+start])
643*4882a593Smuzhiyun            start += len(expected_layer)
644*4882a593Smuzhiyun            self.assertSetEqual(got_layer, expected_layer)
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun    def test_no_vars(self):
647*4882a593Smuzhiyun        self.check_referenced("", [])
648*4882a593Smuzhiyun        self.check_referenced(" ", [])
649*4882a593Smuzhiyun        self.check_referenced(" no vars here! ", [])
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun    def test_single_layer(self):
652*4882a593Smuzhiyun        self.check_referenced("${VAR}", [{"VAR"}])
653*4882a593Smuzhiyun        self.check_referenced("${VAR} ${VAR}", [{"VAR"}])
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun    def test_two_layer(self):
656*4882a593Smuzhiyun        self.d.setVar("VAR", "${B}")
657*4882a593Smuzhiyun        self.check_referenced("${VAR}", [{"VAR"}, {"B"}])
658*4882a593Smuzhiyun        self.check_referenced("${@d.getVar('VAR')}", [{"VAR"}, {"B"}])
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun    def test_more_complicated(self):
661*4882a593Smuzhiyun        self.d["SRC_URI"] = "${QT_GIT}/${QT_MODULE}.git;name=${QT_MODULE};${QT_MODULE_BRANCH_PARAM};protocol=${QT_GIT_PROTOCOL}"
662*4882a593Smuzhiyun        self.d["QT_GIT"] = "git://code.qt.io/${QT_GIT_PROJECT}"
663*4882a593Smuzhiyun        self.d["QT_MODULE_BRANCH_PARAM"] = "branch=${QT_MODULE_BRANCH}"
664*4882a593Smuzhiyun        self.d["QT_MODULE"] = "${BPN}"
665*4882a593Smuzhiyun        self.d["BPN"] = "something to do with ${PN} and ${SPECIAL_PKGSUFFIX}"
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun        layers = [{"SRC_URI"}, {"QT_GIT", "QT_MODULE", "QT_MODULE_BRANCH_PARAM", "QT_GIT_PROTOCOL"}, {"QT_GIT_PROJECT", "QT_MODULE_BRANCH", "BPN"}, {"PN", "SPECIAL_PKGSUFFIX"}]
668*4882a593Smuzhiyun        self.check_referenced("${SRC_URI}", layers)
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun
671*4882a593Smuzhiyunclass EnvironmentTests(unittest.TestCase):
672*4882a593Smuzhiyun    def test_environment(self):
673*4882a593Smuzhiyun        os.environ["A"] = "this is A"
674*4882a593Smuzhiyun        self.assertIn("A", os.environ)
675*4882a593Smuzhiyun        self.assertEqual(os.environ["A"], "this is A")
676*4882a593Smuzhiyun        self.assertNotIn("B", os.environ)
677*4882a593Smuzhiyun
678*4882a593Smuzhiyun        with bb.utils.environment(B="this is B"):
679*4882a593Smuzhiyun            self.assertIn("A", os.environ)
680*4882a593Smuzhiyun            self.assertEqual(os.environ["A"], "this is A")
681*4882a593Smuzhiyun            self.assertIn("B", os.environ)
682*4882a593Smuzhiyun            self.assertEqual(os.environ["B"], "this is B")
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun        self.assertIn("A", os.environ)
685*4882a593Smuzhiyun        self.assertEqual(os.environ["A"], "this is A")
686*4882a593Smuzhiyun        self.assertNotIn("B", os.environ)
687