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