def test_postfile(self): postconf = os.path.join(self.builddir, 'conf/postfile.conf') self.track_for_cleanup(postconf) ftools.write_file(postconf , "TEST_POSTFILE=\"postfile\"") self.write_config("TEST_POSTFILE=\"localconf\"") result = runCmd('bitbake -R conf/postfile.conf -e | grep TEST_POSTFILE=') self.assertTrue('postfile' in result.output, "Postconfigure file \"postfile.conf\"was not taken into consideration.")
def test_postfile(self): postconf = os.path.join(self.builddir, 'conf/postfile.conf') self.track_for_cleanup(postconf) ftools.write_file(postconf , "TEST_POSTFILE=\"postfile\"") self.write_config("TEST_POSTFILE=\"localconf\"") result = runCmd('bitbake -R conf/postfile.conf -e | grep TEST_POSTFILE=') self.assertTrue('postfile' in result.output, "Postconfigure file \"postfile.conf\"was not taken into consideration.")
def test_multiconfig(self): """ Test that a simple multiconfig build works. This uses the mcextend class and the multiconfig-image-packager test recipe to build a core-image-full-cmdline image which contains a tiny core-image-minimal and a musl core-image-minimal, installed as packages. """ config = """ IMAGE_INSTALL_append_pn-core-image-full-cmdline = " multiconfig-image-packager-tiny multiconfig-image-packager-musl" BBMULTICONFIG = "tiny musl" """ self.write_config(config) muslconfig = """ MACHINE = "qemux86-64" DISTRO = "poky" TCLIBC = "musl" TMPDIR = "${TOPDIR}/tmp-mc-musl" """ tinyconfig = """ MACHINE = "qemux86" DISTRO = "poky-tiny" TMPDIR = "${TOPDIR}/tmp-mc-tiny" """ multiconfigdir = self.builddir + "/conf/multiconfig" os.makedirs(multiconfigdir, exist_ok=True) self.track_for_cleanup(multiconfigdir + "/musl.conf") ftools.write_file(multiconfigdir + "/musl.conf", muslconfig) self.track_for_cleanup(multiconfigdir + "/tiny.conf") ftools.write_file(multiconfigdir + "/tiny.conf", tinyconfig) # Build a core-image-minimal bitbake('core-image-full-cmdline')
def test_bbappend_order(self): """ Bitbake should bbappend to recipe in a predictable order """ test_recipe = 'ed' bb_vars = get_bb_vars(['SUMMARY', 'PV'], test_recipe) test_recipe_summary_before = bb_vars['SUMMARY'] test_recipe_pv = bb_vars['PV'] recipe_append_file = test_recipe + '_' + test_recipe_pv + '.bbappend' expected_recipe_summary = test_recipe_summary_before for i in range(5): recipe_append_dir = test_recipe + '_test_' + str(i) recipe_append_path = os.path.join(self.testlayer_path, 'recipes-test', recipe_append_dir, recipe_append_file) os.mkdir( os.path.join(self.testlayer_path, 'recipes-test', recipe_append_dir)) feature = 'SUMMARY += "%s"\n' % i ftools.write_file(recipe_append_path, feature) expected_recipe_summary += ' %s' % i self.add_command_to_tearDown('rm -rf %s' % os.path.join( self.testlayer_path, 'recipes-test', test_recipe + '_test_*')) test_recipe_summary_after = get_bb_var('SUMMARY', test_recipe) self.assertEqual(expected_recipe_summary, test_recipe_summary_after)
def test_multiconfig(self): """ Test that a simple multiconfig build works. This uses the mcextend class and the multiconfig-image-packager test recipe to build a core-image-full-cmdline image which contains a tiny core-image-minimal and a musl core-image-minimal, installed as packages. """ config = """ IMAGE_INSTALL_append_pn-core-image-full-cmdline = " multiconfig-image-packager-tiny multiconfig-image-packager-musl" BBMULTICONFIG = "tiny musl" """ self.write_config(config) muslconfig = """ MACHINE = "qemux86-64" DISTRO = "poky" TCLIBC = "musl" TMPDIR = "${TOPDIR}/tmp-mc-musl" """ tinyconfig = """ MACHINE = "qemux86" DISTRO = "poky-tiny" TMPDIR = "${TOPDIR}/tmp-mc-tiny" """ multiconfigdir = self.builddir + "/conf/multiconfig" os.makedirs(multiconfigdir, exist_ok=True) self.track_for_cleanup(multiconfigdir + "/musl.conf") ftools.write_file(multiconfigdir + "/musl.conf", muslconfig) self.track_for_cleanup(multiconfigdir + "/tiny.conf") ftools.write_file(multiconfigdir + "/tiny.conf", tinyconfig) # Build a core-image-minimal bitbake('core-image-full-cmdline')
def bitbake(command, ignore_status=False, timeout=None, postconfig=None, output_log=None, **options): if postconfig: postconfig_file = os.path.join(os.environ.get('BUILDDIR'), 'oeqa-post.conf') ftools.write_file(postconfig_file, postconfig) extra_args = "-R %s" % postconfig_file else: extra_args = "" if isinstance(command, str): cmd = "bitbake " + extra_args + " " + command else: cmd = ["bitbake"] + [ a for a in (command + extra_args.split(" ")) if a not in [""] ] try: return runCmd(cmd, ignore_status, timeout, output_log=output_log, **options) finally: if postconfig: os.remove(postconfig_file)
def test_postfile(self): postconf = os.path.join(self.builddir, "conf/postfile.conf") self.track_for_cleanup(postconf) ftools.write_file(postconf, 'TEST_POSTFILE="postfile"') self.append_config('TEST_POSTFILE="localconf"') result = runCmd("bitbake -R conf/postfile.conf -e | grep TEST_POSTFILE=") self.assertTrue("postfile" in result.output) self.remove_config('TEST_POSTFILE="localconf"')
def test_postfile(self): postconf = os.path.join(self.builddir, 'conf/postfile.conf') self.track_for_cleanup(postconf) ftools.write_file(postconf , "TEST_POSTFILE=\"postfile\"") self.append_config("TEST_POSTFILE=\"localconf\"") result = runCmd('bitbake -R conf/postfile.conf -e | grep TEST_POSTFILE=') self.assertTrue('postfile' in result.output) self.remove_config("TEST_POSTFILE=\"localconf\"")
def test_postfile(self): postconf = os.path.join(self.builddir, 'conf/postfile.conf') self.track_for_cleanup(postconf) ftools.write_file(postconf , "TEST_POSTFILE=\"postfile\"") self.append_config("TEST_POSTFILE=\"localconf\"") result = runCmd('bitbake -R conf/postfile.conf -e | grep TEST_POSTFILE=') self.assertTrue('postfile' in result.output) self.remove_config("TEST_POSTFILE=\"localconf\"")
def write_config(self, data): self.log.debug("Writing to: %s\n%s\n" % (self.testinc_path, data)) ftools.write_file(self.testinc_path, data) custommachine = os.getenv('CUSTOMMACHINE') if custommachine and 'MACHINE' in data: machine = get_bb_var('MACHINE') self.log.warning('MACHINE overridden: %s' % machine)
def write_config(self, data): self.log.debug("Writing to: %s\n%s\n" % (self.testinc_path, data)) ftools.write_file(self.testinc_path, data) custommachine = os.getenv('CUSTOMMACHINE') if custommachine and 'MACHINE' in data: machine = get_bb_var('MACHINE') self.log.warning('MACHINE overridden: %s' % machine)
def test_locked_signatures(self): """ Summary: Test locked signature mechanism Expected: Locked signatures will prevent task to run Product: oe-core Author: Daniel Istrate <*****@*****.**> AutomatedBy: Daniel Istrate <*****@*****.**> """ import uuid test_recipe = 'ed' locked_sigs_file = 'locked-sigs.inc' bitbake(test_recipe) # Generate locked sigs include file bitbake('-S none %s' % test_recipe) feature = 'require %s\n' % locked_sigs_file feature += 'SIGGEN_LOCKEDSIGS_TASKSIG_CHECK = "warn"\n' self.write_config(feature) # Build a locked recipe bitbake(test_recipe) templayerdir = tempfile.mkdtemp(prefix='signingqa') create_temp_layer(templayerdir, 'selftestsigning') runCmd('bitbake-layers add-layer %s' % templayerdir) # Make a change that should cause the locked task signature to change # Use uuid so hash equivalance server isn't triggered recipe_append_file = test_recipe + '_' + get_bb_var( 'PV', test_recipe) + '.bbappend' recipe_append_path = os.path.join(templayerdir, 'recipes-test', test_recipe, recipe_append_file) feature = 'SUMMARY_${PN} = "test locked signature%s"\n' % uuid.uuid4() os.mkdir(os.path.join(templayerdir, 'recipes-test')) os.mkdir(os.path.join(templayerdir, 'recipes-test', test_recipe)) write_file(recipe_append_path, feature) self.add_command_to_tearDown('bitbake-layers remove-layer %s' % templayerdir) self.add_command_to_tearDown( 'rm -f %s' % os.path.join(self.builddir, locked_sigs_file)) self.add_command_to_tearDown('rm -rf %s' % templayerdir) # Build the recipe again ret = bitbake(test_recipe) # Verify you get the warning and that the real task *isn't* run (i.e. the locked signature has worked) patt = r'The %s:do_package sig is computed to be \S+, but the sig is locked to \S+ in SIGGEN_LOCKEDSIGS\S+' % test_recipe found_warn = re.search(patt, ret.output) self.assertIsNotNone( found_warn, "Didn't find the expected warning message. Output: %s" % ret.output)
def write_config(self, data): """Write to <builddir>/conf/selftest.inc""" self.logger.debug("Writing to: %s\n%s\n" % (self.testinc_path, data)) ftools.write_file(self.testinc_path, data) if self.tc.custommachine and 'MACHINE' in data: machine = get_bb_var('MACHINE') self.logger.warning('MACHINE overridden: %s' % machine)
def test_prefile(self): preconf = os.path.join(self.builddir, 'conf/prefile.conf') self.track_for_cleanup(preconf) ftools.write_file(preconf, "TEST_PREFILE=\"prefile\"") result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=') self.assertIn('prefile', result.output) self.write_config("TEST_PREFILE=\"localconf\"") result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=') self.assertIn('localconf', result.output)
def write_config(self, data): """Write to <builddir>/conf/selftest.inc""" self.logger.debug("Writing to: %s\n%s\n" % (self.testinc_path, data)) ftools.write_file(self.testinc_path, data) if self.tc.custommachine and 'MACHINE' in data: machine = get_bb_var('MACHINE') self.logger.warning('MACHINE overridden: %s' % machine)
def test_prefile(self): preconf = os.path.join(self.builddir, 'conf/prefile.conf') self.track_for_cleanup(preconf) ftools.write_file(preconf ,"TEST_PREFILE=\"prefile\"") result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=') self.assertTrue('prefile' in result.output, "Preconfigure file \"prefile.conf\"was not taken into consideration. ") self.append_config("TEST_PREFILE=\"localconf\"") self.addCleanup(self.remove_config, "TEST_PREFILE=\"localconf\"") result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=') self.assertTrue('localconf' in result.output, "Preconfigure file \"prefile.conf\"was not taken into consideration.")
def write_config(self, data, multiconfig=None): """Write to config file""" if multiconfig: multiconfigdir = "%s/conf/multiconfig" % self.builddir os.makedirs(multiconfigdir, exist_ok=True) dest_path = '%s/%s.conf' % (multiconfigdir, multiconfig) self.track_for_cleanup(dest_path) else: dest_path = self.testinc_path self.logger.debug("Writing to: %s\n%s\n" % (dest_path, data)) ftools.write_file(dest_path, data) if not multiconfig and self.tc.custommachine and 'MACHINE' in data: machine = get_bb_var('MACHINE') self.logger.warning('MACHINE overridden: %s' % machine)
def test_prefile(self): preconf = os.path.join(self.builddir, 'conf/prefile.conf') self.track_for_cleanup(preconf) ftools.write_file(preconf, "TEST_PREFILE=\"prefile\"") result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=') self.assertTrue( 'prefile' in result.output, "Preconfigure file \"prefile.conf\"was not taken into consideration. " ) self.append_config("TEST_PREFILE=\"localconf\"") self.addCleanup(self.remove_config, "TEST_PREFILE=\"localconf\"") result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=') self.assertTrue( 'localconf' in result.output, "Preconfigure file \"prefile.conf\"was not taken into consideration." )
def test_locked_signatures(self): """ Summary: Test locked signature mechanism Expected: Locked signatures will prevent task to run Product: oe-core Author: Daniel Istrate <*****@*****.**> AutomatedBy: Daniel Istrate <*****@*****.**> """ test_recipe = 'ed' locked_sigs_file = 'locked-sigs.inc' self.add_command_to_tearDown('rm -f %s' % os.path.join(self.builddir, locked_sigs_file)) bitbake(test_recipe) # Generate locked sigs include file bitbake('-S none %s' % test_recipe) feature = 'require %s\n' % locked_sigs_file feature += 'SIGGEN_LOCKEDSIGS_TASKSIG_CHECK = "warn"\n' self.write_config(feature) # Build a locked recipe bitbake(test_recipe) # Make a change that should cause the locked task signature to change recipe_append_file = test_recipe + '_' + get_bb_var('PV', test_recipe) + '.bbappend' recipe_append_path = os.path.join(self.testlayer_path, 'recipes-test', test_recipe, recipe_append_file) feature = 'SUMMARY += "test locked signature"\n' os.mkdir(os.path.join(self.testlayer_path, 'recipes-test', test_recipe)) write_file(recipe_append_path, feature) self.add_command_to_tearDown('rm -rf %s' % os.path.join(self.testlayer_path, 'recipes-test', test_recipe)) # Build the recipe again ret = bitbake(test_recipe) # Verify you get the warning and that the real task *isn't* run (i.e. the locked signature has worked) patt = r'WARNING: The %s:do_package sig is computed to be \S+, but the sig is locked to \S+ in SIGGEN_LOCKEDSIGS\S+' % test_recipe found_warn = re.search(patt, ret.output) self.assertIsNotNone(found_warn, "Didn't find the expected warning message. Output: %s" % ret.output)
def bitbake(command, ignore_status=False, timeout=None, postconfig=None, output_log=None, **options): if postconfig: postconfig_file = os.path.join(os.environ.get('BUILDDIR'), 'oeqa-post.conf') ftools.write_file(postconfig_file, postconfig) extra_args = "-R %s" % postconfig_file else: extra_args = "" if isinstance(command, str): cmd = "bitbake " + extra_args + " " + command else: cmd = [ "bitbake" ] + [a for a in (command + extra_args.split(" ")) if a not in [""]] try: return runCmd(cmd, ignore_status, timeout, output_log=output_log, **options) finally: if postconfig: os.remove(postconfig_file)
def test_locked_signatures(self): """ Summary: Test locked signature mechanism Expected: Locked signatures will prevent task to run Product: oe-core Author: Daniel Istrate <*****@*****.**> AutomatedBy: Daniel Istrate <*****@*****.**> """ test_recipe = 'ed' locked_sigs_file = 'locked-sigs.inc' self.add_command_to_tearDown('rm -f %s' % os.path.join(self.builddir, locked_sigs_file)) bitbake(test_recipe) # Generate locked sigs include file bitbake('-S none %s' % test_recipe) feature = 'require %s\n' % locked_sigs_file feature += 'SIGGEN_LOCKEDSIGS_CHECK_LEVEL = "warn"\n' self.write_config(feature) # Build a locked recipe bitbake(test_recipe) # Make a change that should cause the locked task signature to change recipe_append_file = test_recipe + '_' + get_bb_var('PV', test_recipe) + '.bbappend' recipe_append_path = os.path.join(self.testlayer_path, 'recipes-test', test_recipe, recipe_append_file) feature = 'SUMMARY += "test locked signature"\n' os.mkdir(os.path.join(self.testlayer_path, 'recipes-test', test_recipe)) write_file(recipe_append_path, feature) self.add_command_to_tearDown('rm -rf %s' % os.path.join(self.testlayer_path, 'recipes-test', test_recipe)) # Build the recipe again ret = bitbake(test_recipe) # Verify you get the warning and that the real task *isn't* run (i.e. the locked signature has worked) patt = r'WARNING: The %s:do_package sig \S+ changed, use locked sig \S+ to instead' % test_recipe found_warn = re.search(patt, ret.output) self.assertIsNotNone(found_warn, "Didn't find the expected warning message. Output: %s" % ret.output)
def test_bbappend_order(self): """ Bitbake should bbappend to recipe in a predictable order """ test_recipe = 'ed' test_recipe_summary_before = get_bb_var('SUMMARY', test_recipe) test_recipe_pv = get_bb_var('PV', test_recipe) recipe_append_file = test_recipe + '_' + test_recipe_pv + '.bbappend' expected_recipe_summary = test_recipe_summary_before for i in range(5): recipe_append_dir = test_recipe + '_test_' + str(i) recipe_append_path = os.path.join(self.testlayer_path, 'recipes-test', recipe_append_dir, recipe_append_file) os.mkdir(os.path.join(self.testlayer_path, 'recipes-test', recipe_append_dir)) feature = 'SUMMARY += "%s"\n' % i ftools.write_file(recipe_append_path, feature) expected_recipe_summary += ' %s' % i self.add_command_to_tearDown('rm -rf %s' % os.path.join(self.testlayer_path, 'recipes-test', test_recipe + '_test_*')) test_recipe_summary_after = get_bb_var('SUMMARY', test_recipe) self.assertEqual(expected_recipe_summary, test_recipe_summary_after)
def test_layer_without_git_dir(self): """ Summary: Test that layer git revisions are displayed and do not fail without git repository Expected: The build to be successful and without "fatal" errors Product: oe-core Author: Daniel Istrate <*****@*****.**> AutomatedBy: Daniel Istrate <*****@*****.**> """ dirpath = tempfile.mkdtemp() dummy_layer_name = 'meta-dummy' dummy_layer_path = os.path.join(dirpath, dummy_layer_name) dummy_layer_conf_dir = os.path.join(dummy_layer_path, 'conf') os.makedirs(dummy_layer_conf_dir) dummy_layer_conf_path = os.path.join(dummy_layer_conf_dir, 'layer.conf') dummy_layer_content = 'BBPATH .= ":${LAYERDIR}"\n' \ 'BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"\n' \ 'BBFILE_COLLECTIONS += "%s"\n' \ 'BBFILE_PATTERN_%s = "^${LAYERDIR}/"\n' \ 'BBFILE_PRIORITY_%s = "6"\n' % (dummy_layer_name, dummy_layer_name, dummy_layer_name) ftools.write_file(dummy_layer_conf_path, dummy_layer_content) bblayers_conf = 'BBLAYERS += "%s"\n' % dummy_layer_path self.write_bblayers_config(bblayers_conf) test_recipe = 'ed' ret = bitbake('-n %s' % test_recipe) err = 'fatal: Not a git repository' shutil.rmtree(dirpath) self.assertNotIn(err, ret.output)
def test_layer_without_git_dir(self): """ Summary: Test that layer git revisions are displayed and do not fail without git repository Expected: The build to be successful and without "fatal" errors Product: oe-core Author: Daniel Istrate <*****@*****.**> AutomatedBy: Daniel Istrate <*****@*****.**> """ dirpath = tempfile.mkdtemp() dummy_layer_name = 'meta-dummy' dummy_layer_path = os.path.join(dirpath, dummy_layer_name) dummy_layer_conf_dir = os.path.join(dummy_layer_path, 'conf') os.makedirs(dummy_layer_conf_dir) dummy_layer_conf_path = os.path.join(dummy_layer_conf_dir, 'layer.conf') dummy_layer_content = 'BBPATH .= ":${LAYERDIR}"\n' \ 'BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"\n' \ 'BBFILE_COLLECTIONS += "%s"\n' \ 'BBFILE_PATTERN_%s = "^${LAYERDIR}/"\n' \ 'BBFILE_PRIORITY_%s = "6"\n' % (dummy_layer_name, dummy_layer_name, dummy_layer_name) ftools.write_file(dummy_layer_conf_path, dummy_layer_content) bblayers_conf = 'BBLAYERS += "%s"\n' % dummy_layer_path self.write_bblayers_config(bblayers_conf) test_recipe = 'ed' ret = bitbake('-n %s' % test_recipe) err = 'fatal: Not a git repository' shutil.rmtree(dirpath) self.assertNotIn(err, ret.output)
def write_recipeinc(self, recipe, data): inc_file = os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc') self.log.debug("Writing to: %s\n%s\n" % (inc_file, data)) ftools.write_file(inc_file, data)
def set_machine_config(self, data): """Write to <builddir>/conf/machine.inc""" self.logger.debug("Writing to: %s\n%s\n" % (self.machineinc_path, data)) ftools.write_file(self.machineinc_path, data)
def set_machine_config(self, data): """Write to <builddir>/conf/machine.inc""" self.logger.debug("Writing to: %s\n%s\n" % (self.machineinc_path, data)) ftools.write_file(self.machineinc_path, data)
def write_config(self, data): self.log.debug("Writing to: %s\n%s\n" % (self.testinc_path, data)) ftools.write_file(self.testinc_path, data)
def write_config(self, data): self.log.debug("Writing to: %s\n%s\n" % (self.testinc_path, data)) ftools.write_file(self.testinc_path, data)
def write_recipeinc(self, recipe, data): """Write to meta-selftest/recipes-test/<recipe>/test_recipe.inc""" inc_file = self.recipeinc(recipe) self.logger.debug("Writing to: %s\n%s\n" % (inc_file, data)) ftools.write_file(inc_file, data) return inc_file
def write_recipeinc(self, recipe, data): """Write to meta-sefltest/recipes-test/<recipe>/test_recipe.inc""" inc_file = os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc') self.logger.debug("Writing to: %s\n%s\n" % (inc_file, data)) ftools.write_file(inc_file, data)
def write_bblayers_config(self, data): """Write to <builddir>/conf/bblayers.inc""" self.logger.debug("Writing to: %s\n%s\n" % (self.testinc_bblayers_path, data)) ftools.write_file(self.testinc_bblayers_path, data)
def set_machine_config(self, data): self.log.debug("Writing to: %s\n%s\n" % (self.machineinc_path, data)) ftools.write_file(self.machineinc_path, data)
def write_recipeinc(self, recipe, data): """Write to meta-selftest/recipes-test/<recipe>/test_recipe.inc""" inc_file = self.recipeinc(recipe) self.logger.debug("Writing to: %s\n%s\n" % (inc_file, data)) ftools.write_file(inc_file, data) return inc_file
def test_sstate_samesigs(self): """ The sstate checksums off allarch packages should be independent of whichever MACHINE is set. Check this using bitbake -S. Also, rather than duplicate the test, check nativesdk stamps are the same between the two MACHINE values. Also, when building for multiple machines which share tune flag specific packages, those packages also need to have identical signatures. Based on oeqa.selftest.sstatetests.SStateTests.test_sstate_allarch_samesigs and extended to cover all IoT Reference OS Kit machines. """ topdir = get_bb_var('TOPDIR') targetos = get_bb_var('TARGET_OS') targetvendor = get_bb_var('TARGET_VENDOR') libcappend = get_bb_var('TCLIBCAPPEND') # Select subset of the machines to speed up testing. # Edison/intel-core2-32 are particularly sensitive. machines = "intel-corei7-64".split() # machines = "edison intel-quark intel-core2-32 intel-corei7-64 beaglebone".split() # machines = "edison intel-core2-32".split() first = machines[0] workdir = os.getcwd() try: pending = [] for machine in machines: builddir = '%s/build-%s' % (topdir, machine) os.mkdir(builddir) self.track_for_cleanup(builddir) os.chdir(builddir) shutil.copytree('../conf', 'conf') ftools.write_file( 'conf/selftest.inc', """ TMPDIR = \"%s/tmp-sstatesamehash-%s\" MACHINE = \"%s\" """ % (topdir, machine, machine)) # Comment out to debug with bitbake-diffstat after running the test. # In that case, remember to "rm -r tmp-*" before the next run. self.track_for_cleanup(topdir + "/tmp-sstatesamehash-%s%s" % (machine, libcappend)) # Replace build targets with individual recipes to investigate just those. pending.append( (machine, subprocess.Popen( 'bitbake world meta-toolchain -S none'.split(), stdout=open('%s/bitbake.log' % builddir, 'w'), stderr=subprocess.STDOUT))) for machine, p in pending: returncode = p.wait() if returncode: raise AssertionError( "bitbake failed for machine %s with return code %d:\n%s" % (machine, returncode, open('%s/build-%s/bitbake.log' % (topdir, machine)).read())) finally: os.chdir(workdir) def get_hashes(d, subdir): f = {} for root, dirs, files in os.walk(os.path.join(d, subdir)): for name in files: # meta-toolchain depends on cross-canadian. # Not sure about adt-installer. Hash is different, but bitbake-diffstat # shows no difference. # do_deploy is allowed to differ, it just as a performance impact because of # unnecessary rebuilding (minor in our case, not many recipes hit this). if "meta-environment" in root or "cross-canadian" in root or \ "do_populate_adt" in name and "adt-installer" in root or \ "do_populate_sdk" in name and "meta-toolchain" in root or \ "do_build" in name or \ "do_deploy" in name: continue components = name.split('.sigdata.') # Map from 'all-refkit-linux/1_1.04-r4.do_build' to '95c22ae3e1c81cdc116db37b68db10be'. # All tasks that are shared by different machines must have the same hash. f[os.path.join(os.path.relpath(root, d), components[0])] = ''.join(components[1:]) return f # Will be found when building meta-toolchain, otherwise it won't. nativesdkdir = glob.glob( topdir + ("/tmp-sstatesamehash-%s%s/stamps/*-nativesdk*-linux" % (first, libcappend))) if nativesdkdir: nativesdkdir = os.path.basename(nativesdkdir[0]) hashes = {} tasks = set() for machine in machines: hashes[machine] = {} # Only some some packages are expected to have the same signature. subdirs = [ "all" + targetvendor + "-" + targetos, # allarch "core2-32" + targetvendor + "-" + targetos, # shared between edison and intel-core2-32 ] if nativesdkdir: subdirs.append(nativesdkdir) for subdir in subdirs: hashes[machine].update( get_hashes( topdir + ("/tmp-sstatesamehash-%s%s/stamps" % (machine, libcappend)), subdir)) tasks.update(hashes[machine].keys()) errors = ['Machines have different hashes:'] analysis = [] tasks = list(tasks) tasks.sort() for task in tasks: # Find all machines sharing the same value. values = {} for machine in machines: value = hashes[machine].get(task, None) if value: values.setdefault(value, []).append(machine) values = sorted(values.items()) if len(values) > 1: errors.append( 'Not the same hash for ' + task + ': ' + ' '.join(['/'.join(m) + '=' + v for v, m in values])) # Pick the initial two values and the first machine in each where # the task differed and compare the signatures. cmd = "set -x; bitbake-diffsigs tmp-sstatesamehash-*%s*/stamps/*%s.* tmp-sstatesamehash-*%s*/stamps/*%s.*" % \ (values[0][1][0], task, values[1][1][0], task) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, stderr = p.communicate() analysis.append(stdout.decode("utf-8")) if len(errors) > 1: # If this fails, it often fails for a whole range of tasks where one depends on # the other. In this example, only the original source file was different: # # AssertionError: False is not true : Machines have different hashes: # Not the same hash for all-poky-linux/initramfs-boot/1.0-r2.do_compile: intel-core2-32=1efd21ed2f11a4a2aef1ade99e0ae523 edison=d4aa4f356187f0902cd5b9e1fed250c4 # ... # Not the same hash for all-refkit-linux/initramfs-boot/1.0-r2.do_fetch: edison=82a397e985e2c570714ab7dfa3e21a6c intel-core2-32=79b455328b0b298423cf52582cc12c7c # ... self.assertTrue(False, msg='\n'.join(errors) + '\n\n' + '\n\n'.join(analysis))
def write_bblayers_config(self, data): """Write to <builddir>/conf/bblayers.inc""" self.logger.debug("Writing to: %s\n%s\n" % (self.testinc_bblayers_path, data)) ftools.write_file(self.testinc_bblayers_path, data)
def test_sstate_samesigs(self): """ The sstate checksums off allarch packages should be independent of whichever MACHINE is set. Check this using bitbake -S. Also, rather than duplicate the test, check nativesdk stamps are the same between the two MACHINE values. Also, when building for multiple machines which share tune flag specific packages, those packages also need to have identical signatures. Based on oeqa.selftest.sstatetests.SStateTests.test_sstate_allarch_samesigs and extended to cover all Ostro OS machines. """ topdir = get_bb_var('TOPDIR') targetos = get_bb_var('TARGET_OS') targetvendor = get_bb_var('TARGET_VENDOR') libcappend = get_bb_var('TCLIBCAPPEND') # Select subset of the machines to speed up testing. # Edison/intel-core2-32 are particularly sensitive. machines = "edison intel-quark intel-core2-32 intel-corei7-64 beaglebone".split() # machines = "edison intel-core2-32".split() first = machines[0] workdir = os.getcwd() try: pending = [] for machine in machines: builddir = '%s/build-%s' % (topdir, machine) os.mkdir(builddir) self.track_for_cleanup(builddir) os.chdir(builddir) shutil.copytree('../conf', 'conf') ftools.write_file('conf/selftest.inc', """ TMPDIR = \"%s/tmp-sstatesamehash-%s\" MACHINE = \"%s\" """ % (topdir, machine, machine)) # Comment out to debug with bitbake-diffstat after running the test. # In that case, remember to "rm -r tmp-*" before the next run. self.track_for_cleanup(topdir + "/tmp-sstatesamehash-%s%s" % (machine, libcappend)) # Replace build targets with individual recipes to investigate just those. pending.append((machine, subprocess.Popen('bitbake world meta-toolchain -S none'.split(), stdout=open('%s/bitbake.log' % builddir, 'w'), stderr=subprocess.STDOUT))) for machine, p in pending: returncode = p.wait() if returncode: raise AssertionError("bitbake failed for machine %s with return code %d:\n%s" % (machine, returncode, open('%s/build-%s/bitbake.log' % (topdir, machine)).read())) finally: os.chdir(workdir) def get_hashes(d, subdir): f = {} for root, dirs, files in os.walk(os.path.join(d, subdir)): for name in files: # meta-toolchain depends on cross-canadian. # Not sure about adt-installer. Hash is different, but bitbake-diffstat # shows no difference. # do_deploy is allowed to differ, it just as a performance impact because of # unnecessary rebuilding (minor in our case, not many recipes hit this). if "meta-environment" in root or "cross-canadian" in root or \ "do_populate_adt" in name and "adt-installer" in root or \ "do_populate_sdk" in name and "meta-toolchain" in root or \ "do_build" in name or \ "do_deploy" in name: continue components = name.split('.sigdata.') # Map from 'all-ostro-linux/1_1.04-r4.do_build' to '95c22ae3e1c81cdc116db37b68db10be'. # All tasks that are shared by different machines must have the same hash. f[os.path.join(os.path.relpath(root, d), components[0])] = ''.join(components[1:]) return f # Will be found when building meta-toolchain, otherwise it won't. nativesdkdir = glob.glob(topdir + ("/tmp-sstatesamehash-%s%s/stamps/*-nativesdk*-linux" % (first, libcappend))) if nativesdkdir: nativesdkdir = os.path.basename(nativesdkdir[0]) hashes = {} tasks = set() for machine in machines: hashes[machine] = {} # Only some some packages are expected to have the same signature. subdirs = ["all" + targetvendor + "-" + targetos, # allarch "core2-32" + targetvendor + "-" + targetos, # shared between edison and intel-core2-32 ] if nativesdkdir: subdirs.append(nativesdkdir) for subdir in subdirs: hashes[machine].update(get_hashes(topdir + ("/tmp-sstatesamehash-%s%s/stamps" % (machine, libcappend)), subdir)) tasks.update(hashes[machine].keys()) errors = ['Machines have different hashes:'] analysis = [] tasks = list(tasks) tasks.sort() for task in tasks: # Find all machines sharing the same value. values = {} for machine in machines: value = hashes[machine].get(task, None) if value: values.setdefault(value, []).append(machine) values = sorted(values.items()) if len(values) > 1: errors.append('Not the same hash for ' + task + ': ' + ' '.join(['/'.join(m) + '=' + v for v, m in values])) # Pick the initial two values and the first machine in each where # the task differed and compare the signatures. cmd = "set -x; bitbake-diffsigs tmp-sstatesamehash-*%s*/stamps/*%s.* tmp-sstatesamehash-*%s*/stamps/*%s.*" % \ (values[0][1][0], task, values[1][1][0], task) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, stderr = p.communicate() analysis.append(stdout) if len(errors) > 1: # If this fails, it often fails for a whole range of tasks where one depends on # the other. In this example, only the original source file was different: # # AssertionError: False is not true : Machines have different hashes: # Not the same hash for all-poky-linux/initramfs-boot/1.0-r2.do_compile: intel-core2-32=1efd21ed2f11a4a2aef1ade99e0ae523 edison=d4aa4f356187f0902cd5b9e1fed250c4 # ... # Not the same hash for all-ostro-linux/initramfs-boot/1.0-r2.do_fetch: edison=82a397e985e2c570714ab7dfa3e21a6c intel-core2-32=79b455328b0b298423cf52582cc12c7c # ... self.assertTrue(False, msg='\n'.join(errors) + '\n\n' + '\n\n'.join(analysis))
def set_machine_config(self, data): self.log.debug("Writing to: %s\n%s\n" % (self.machineinc_path, data)) ftools.write_file(self.machineinc_path, data)
def write_recipeinc(self, recipe, data): inc_file = os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc') self.log.debug("Writing to: %s\n%s\n" % (inc_file, data)) ftools.write_file(inc_file, data)
def write_recipeinc(self, recipe, data): """Write to meta-sefltest/recipes-test/<recipe>/test_recipe.inc""" inc_file = os.path.join(self.testlayer_path, 'recipes-test', recipe, 'test_recipe.inc') self.logger.debug("Writing to: %s\n%s\n" % (inc_file, data)) ftools.write_file(inc_file, data)