blob: 206168ed00943278dca06098a49a24f0ca049863 [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
2# SPDX-License-Identifier: MIT
3#
4
Brad Bishopd7bf8c12018-02-25 22:55:05 -05005import os
6import re
7import time
8import logging
9import bb.tinfoil
10
11from oeqa.selftest.case import OESelftestTestCase
12from oeqa.utils.commands import runCmd
Brad Bishopd7bf8c12018-02-25 22:55:05 -050013
14class TinfoilTests(OESelftestTestCase):
15 """ Basic tests for the tinfoil API """
16
Brad Bishopd7bf8c12018-02-25 22:55:05 -050017 def test_getvar(self):
18 with bb.tinfoil.Tinfoil() as tinfoil:
19 tinfoil.prepare(True)
20 machine = tinfoil.config_data.getVar('MACHINE')
21 if not machine:
22 self.fail('Unable to get MACHINE value - returned %s' % machine)
23
Brad Bishopd7bf8c12018-02-25 22:55:05 -050024 def test_expand(self):
25 with bb.tinfoil.Tinfoil() as tinfoil:
26 tinfoil.prepare(True)
27 expr = '${@os.getpid()}'
28 pid = tinfoil.config_data.expand(expr)
29 if not pid:
30 self.fail('Unable to expand "%s" - returned %s' % (expr, pid))
31
Brad Bishopd7bf8c12018-02-25 22:55:05 -050032 def test_getvar_bb_origenv(self):
33 with bb.tinfoil.Tinfoil() as tinfoil:
34 tinfoil.prepare(True)
35 origenv = tinfoil.config_data.getVar('BB_ORIGENV', False)
36 if not origenv:
37 self.fail('Unable to get BB_ORIGENV value - returned %s' % origenv)
38 self.assertEqual(origenv.getVar('HOME', False), os.environ['HOME'])
39
Brad Bishopd7bf8c12018-02-25 22:55:05 -050040 def test_parse_recipe(self):
41 with bb.tinfoil.Tinfoil() as tinfoil:
42 tinfoil.prepare(config_only=False, quiet=2)
43 testrecipe = 'mdadm'
44 best = tinfoil.find_best_provider(testrecipe)
45 if not best:
46 self.fail('Unable to find recipe providing %s' % testrecipe)
47 rd = tinfoil.parse_recipe_file(best[3])
48 self.assertEqual(testrecipe, rd.getVar('PN'))
49
Brad Bishopd7bf8c12018-02-25 22:55:05 -050050 def test_parse_recipe_copy_expand(self):
51 with bb.tinfoil.Tinfoil() as tinfoil:
52 tinfoil.prepare(config_only=False, quiet=2)
53 testrecipe = 'mdadm'
54 best = tinfoil.find_best_provider(testrecipe)
55 if not best:
56 self.fail('Unable to find recipe providing %s' % testrecipe)
57 rd = tinfoil.parse_recipe_file(best[3])
58 # Check we can get variable values
59 self.assertEqual(testrecipe, rd.getVar('PN'))
60 # Check that expanding a value that includes a variable reference works
61 self.assertEqual(testrecipe, rd.getVar('BPN'))
62 # Now check that changing the referenced variable's value in a copy gives that
63 # value when expanding
64 localdata = bb.data.createCopy(rd)
65 localdata.setVar('PN', 'hello')
66 self.assertEqual('hello', localdata.getVar('BPN'))
67
Brad Bishopd7bf8c12018-02-25 22:55:05 -050068 def test_list_recipes(self):
69 with bb.tinfoil.Tinfoil() as tinfoil:
70 tinfoil.prepare(config_only=False, quiet=2)
71 # Check pkg_pn
72 checkpns = ['tar', 'automake', 'coreutils', 'm4-native', 'nativesdk-gcc']
73 pkg_pn = tinfoil.cooker.recipecaches[''].pkg_pn
74 for pn in checkpns:
75 self.assertIn(pn, pkg_pn)
76 # Check pkg_fn
77 checkfns = {'nativesdk-gcc': '^virtual:nativesdk:.*', 'coreutils': '.*/coreutils_.*.bb'}
78 for fn, pn in tinfoil.cooker.recipecaches[''].pkg_fn.items():
79 if pn in checkpns:
80 if pn in checkfns:
81 self.assertTrue(re.match(checkfns[pn], fn), 'Entry for %s: %s did not match %s' % (pn, fn, checkfns[pn]))
82 checkpns.remove(pn)
83 if checkpns:
84 self.fail('Unable to find pkg_fn entries for: %s' % ', '.join(checkpns))
85
Brad Bishopd7bf8c12018-02-25 22:55:05 -050086 def test_wait_event(self):
87 with bb.tinfoil.Tinfoil() as tinfoil:
88 tinfoil.prepare(config_only=True)
89
90 tinfoil.set_event_mask(['bb.event.FilesMatchingFound', 'bb.command.CommandCompleted'])
91
92 # Need to drain events otherwise events that were masked may still be in the queue
93 while tinfoil.wait_event():
94 pass
95
96 pattern = 'conf'
97 res = tinfoil.run_command('findFilesMatchingInDir', pattern, 'conf/machine')
98 self.assertTrue(res)
99
100 eventreceived = False
101 commandcomplete = False
102 start = time.time()
Andrew Geissler635e0e42020-08-21 15:58:33 -0500103 # Wait for 10s in total so we'd detect spurious heartbeat events for example
104 # The test is IO load sensitive too
105 while time.time() - start < 10:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500106 event = tinfoil.wait_event(1)
107 if event:
108 if isinstance(event, bb.command.CommandCompleted):
109 commandcomplete = True
110 elif isinstance(event, bb.event.FilesMatchingFound):
111 self.assertEqual(pattern, event._pattern)
112 self.assertIn('qemuarm.conf', event._matches)
113 eventreceived = True
114 elif isinstance(event, logging.LogRecord):
115 continue
116 else:
117 self.fail('Unexpected event: %s' % event)
118
119 self.assertTrue(commandcomplete, 'Timed out waiting for CommandCompleted event from bitbake server')
120 self.assertTrue(eventreceived, 'Did not receive FilesMatchingFound event from bitbake server')
121
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500122 def test_setvariable_clean(self):
123 # First check that setVariable affects the datastore
124 with bb.tinfoil.Tinfoil() as tinfoil:
125 tinfoil.prepare(config_only=True)
126 tinfoil.run_command('setVariable', 'TESTVAR', 'specialvalue')
127 self.assertEqual(tinfoil.config_data.getVar('TESTVAR'), 'specialvalue', 'Value set using setVariable is not reflected in client-side getVar()')
128
129 # Now check that the setVariable's effects are no longer present
130 # (this may legitimately break in future if we stop reinitialising
131 # the datastore, in which case we'll have to reconsider use of
132 # setVariable entirely)
133 with bb.tinfoil.Tinfoil() as tinfoil:
134 tinfoil.prepare(config_only=True)
135 self.assertNotEqual(tinfoil.config_data.getVar('TESTVAR'), 'specialvalue', 'Value set using setVariable is still present!')
136
137 # Now check that setVar on the main datastore works (uses setVariable internally)
138 with bb.tinfoil.Tinfoil() as tinfoil:
139 tinfoil.prepare(config_only=True)
140 tinfoil.config_data.setVar('TESTVAR', 'specialvalue')
141 value = tinfoil.run_command('getVariable', 'TESTVAR')
142 self.assertEqual(value, 'specialvalue', 'Value set using config_data.setVar() is not reflected in config_data.getVar()')
143
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500144 def test_datastore_operations(self):
145 with bb.tinfoil.Tinfoil() as tinfoil:
146 tinfoil.prepare(config_only=True)
147 # Test setVarFlag() / getVarFlag()
148 tinfoil.config_data.setVarFlag('TESTVAR', 'flagname', 'flagval')
149 value = tinfoil.config_data.getVarFlag('TESTVAR', 'flagname')
150 self.assertEqual(value, 'flagval', 'Value set using config_data.setVarFlag() is not reflected in config_data.getVarFlag()')
151 # Test delVarFlag()
152 tinfoil.config_data.setVarFlag('TESTVAR', 'otherflag', 'othervalue')
153 tinfoil.config_data.delVarFlag('TESTVAR', 'flagname')
154 value = tinfoil.config_data.getVarFlag('TESTVAR', 'flagname')
155 self.assertEqual(value, None, 'Varflag deleted using config_data.delVarFlag() is not reflected in config_data.getVarFlag()')
156 value = tinfoil.config_data.getVarFlag('TESTVAR', 'otherflag')
157 self.assertEqual(value, 'othervalue', 'Varflag deleted using config_data.delVarFlag() caused unrelated flag to be removed')
158 # Test delVar()
159 tinfoil.config_data.setVar('TESTVAR', 'varvalue')
160 value = tinfoil.config_data.getVar('TESTVAR')
161 self.assertEqual(value, 'varvalue', 'Value set using config_data.setVar() is not reflected in config_data.getVar()')
162 tinfoil.config_data.delVar('TESTVAR')
163 value = tinfoil.config_data.getVar('TESTVAR')
164 self.assertEqual(value, None, 'Variable deleted using config_data.delVar() appears to still have a value')
165 # Test renameVar()
166 tinfoil.config_data.setVar('TESTVAROLD', 'origvalue')
167 tinfoil.config_data.renameVar('TESTVAROLD', 'TESTVARNEW')
168 value = tinfoil.config_data.getVar('TESTVAROLD')
169 self.assertEqual(value, None, 'Variable renamed using config_data.renameVar() still seems to exist')
170 value = tinfoil.config_data.getVar('TESTVARNEW')
171 self.assertEqual(value, 'origvalue', 'Variable renamed using config_data.renameVar() does not appear with new name')
172 # Test overrides
173 tinfoil.config_data.setVar('TESTVAR', 'original')
174 tinfoil.config_data.setVar('TESTVAR_overrideone', 'one')
175 tinfoil.config_data.setVar('TESTVAR_overridetwo', 'two')
176 tinfoil.config_data.appendVar('OVERRIDES', ':overrideone')
177 value = tinfoil.config_data.getVar('TESTVAR')
178 self.assertEqual(value, 'one', 'Variable overrides not functioning correctly')
179
180 def test_variable_history(self):
181 # Basic test to ensure that variable history works when tracking=True
182 with bb.tinfoil.Tinfoil(tracking=True) as tinfoil:
183 tinfoil.prepare(config_only=False, quiet=2)
184 # Note that _tracking for any datastore we get will be
185 # false here, that's currently expected - so we can't check
186 # for that
187 history = tinfoil.config_data.varhistory.variable('DL_DIR')
188 for entry in history:
189 if entry['file'].endswith('/bitbake.conf'):
190 if entry['op'] in ['set', 'set?']:
191 break
192 else:
193 self.fail('Did not find history entry setting DL_DIR in bitbake.conf. History: %s' % history)
194 # Check it works for recipes as well
195 testrecipe = 'zlib'
196 rd = tinfoil.parse_recipe(testrecipe)
197 history = rd.varhistory.variable('LICENSE')
198 bbfound = -1
199 recipefound = -1
200 for i, entry in enumerate(history):
201 if entry['file'].endswith('/bitbake.conf'):
202 if entry['detail'] == 'INVALID' and entry['op'] in ['set', 'set?']:
203 bbfound = i
204 elif entry['file'].endswith('.bb'):
205 if entry['op'] == 'set':
206 recipefound = i
207 if bbfound == -1:
208 self.fail('Did not find history entry setting LICENSE in bitbake.conf parsing %s recipe. History: %s' % (testrecipe, history))
209 if recipefound == -1:
210 self.fail('Did not find history entry setting LICENSE in %s recipe. History: %s' % (testrecipe, history))
211 if bbfound > recipefound:
212 self.fail('History entry setting LICENSE in %s recipe and in bitbake.conf in wrong order. History: %s' % (testrecipe, history))