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