summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/selftest/cases
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oeqa/selftest/cases')
-rw-r--r--meta/lib/oeqa/selftest/cases/buildhistory.py61
-rw-r--r--meta/lib/oeqa/selftest/cases/buildoptions.py38
-rw-r--r--meta/lib/oeqa/selftest/cases/devtool.py24
-rw-r--r--meta/lib/oeqa/selftest/cases/distrodata.py2
-rw-r--r--meta/lib/oeqa/selftest/cases/esdk.py6
-rw-r--r--meta/lib/oeqa/selftest/cases/fitimage.py406
-rw-r--r--meta/lib/oeqa/selftest/cases/liboe.py37
-rw-r--r--meta/lib/oeqa/selftest/cases/oescripts.py24
-rw-r--r--meta/lib/oeqa/selftest/cases/pokybleeding.py32
-rw-r--r--meta/lib/oeqa/selftest/cases/recipetool.py14
-rw-r--r--meta/lib/oeqa/selftest/cases/recipeutils.py4
-rw-r--r--meta/lib/oeqa/selftest/cases/rust.py2
-rw-r--r--meta/lib/oeqa/selftest/cases/sstatetests.py99
-rw-r--r--meta/lib/oeqa/selftest/cases/toolchain.py71
-rw-r--r--meta/lib/oeqa/selftest/cases/uboot.py59
-rw-r--r--meta/lib/oeqa/selftest/cases/wic.py45
16 files changed, 666 insertions, 258 deletions
diff --git a/meta/lib/oeqa/selftest/cases/buildhistory.py b/meta/lib/oeqa/selftest/cases/buildhistory.py
index 2d55994916..511c666554 100644
--- a/meta/lib/oeqa/selftest/cases/buildhistory.py
+++ b/meta/lib/oeqa/selftest/cases/buildhistory.py
@@ -9,10 +9,10 @@ import re
9import datetime 9import datetime
10 10
11from oeqa.selftest.case import OESelftestTestCase 11from oeqa.selftest.case import OESelftestTestCase
12from oeqa.utils.commands import bitbake, get_bb_vars 12from oeqa.utils.commands import bitbake, get_bb_vars, get_bb_var, runCmd
13 13
14 14
15class BuildhistoryBase(OESelftestTestCase): 15class BuildhistoryTests(OESelftestTestCase):
16 16
17 def config_buildhistory(self, tmp_bh_location=False): 17 def config_buildhistory(self, tmp_bh_location=False):
18 bb_vars = get_bb_vars(['USER_CLASSES', 'INHERIT']) 18 bb_vars = get_bb_vars(['USER_CLASSES', 'INHERIT'])
@@ -48,5 +48,58 @@ class BuildhistoryBase(OESelftestTestCase):
48 else: 48 else:
49 self.assertEqual(result.status, 0, msg="Command 'bitbake %s' has failed unexpectedly: %s" % (target, result.output)) 49 self.assertEqual(result.status, 0, msg="Command 'bitbake %s' has failed unexpectedly: %s" % (target, result.output))
50 50
51 # No tests should be added to the base class. 51
52 # Please create a new class that inherit this one, or use one of those already available for adding tests. 52 def test_buildhistory_basic(self):
53 self.run_buildhistory_operation('xcursor-transparent-theme')
54 self.assertTrue(os.path.isdir(get_bb_var('BUILDHISTORY_DIR')), "buildhistory dir was not created.")
55
56 def test_buildhistory_buildtime_pr_backwards(self):
57 target = 'xcursor-transparent-theme'
58 error = "ERROR:.*QA Issue: Package version for package %s went backwards which would break package feeds \(from .*-r1.* to .*-r0.*\)" % target
59 self.run_buildhistory_operation(target, target_config="PR = \"r1\"", change_bh_location=True)
60 self.run_buildhistory_operation(target, target_config="PR = \"r0\"", change_bh_location=False, expect_error=True, error_regex=error)
61
62 def test_fileinfo(self):
63 self.config_buildhistory()
64 bitbake('hicolor-icon-theme')
65 history_dir = get_bb_var('BUILDHISTORY_DIR_PACKAGE', 'hicolor-icon-theme')
66 self.assertTrue(os.path.isdir(history_dir), 'buildhistory dir was not created.')
67
68 def load_bh(f):
69 d = {}
70 for line in open(f):
71 split = [s.strip() for s in line.split('=', 1)]
72 if len(split) > 1:
73 d[split[0]] = split[1]
74 return d
75
76 data = load_bh(os.path.join(history_dir, 'hicolor-icon-theme', 'latest'))
77 self.assertIn('FILELIST', data)
78 self.assertEqual(data['FILELIST'], '/usr/share/icons/hicolor/index.theme')
79 self.assertGreater(int(data['PKGSIZE']), 0)
80
81 data = load_bh(os.path.join(history_dir, 'hicolor-icon-theme-dev', 'latest'))
82 if 'FILELIST' in data:
83 self.assertEqual(data['FILELIST'], '/usr/share/pkgconfig/default-icon-theme.pc')
84 self.assertGreater(int(data['PKGSIZE']), 0)
85
86 def test_buildhistory_diff(self):
87 target = 'xcursor-transparent-theme'
88 self.run_buildhistory_operation(target, target_config="PR = \"r1\"", change_bh_location=True)
89 self.run_buildhistory_operation(target, target_config="PR = \"r0\"", change_bh_location=False, expect_error=True)
90 result = runCmd("oe-pkgdata-util read-value PKGV %s" % target)
91 pkgv = result.output.rstrip()
92 result = runCmd("buildhistory-diff -p %s" % get_bb_var('BUILDHISTORY_DIR'))
93 expected_endlines = [
94 "xcursor-transparent-theme-dev: RRECOMMENDS: removed \"xcursor-transparent-theme (['= %s-r1'])\", added \"xcursor-transparent-theme (['= %s-r0'])\"" % (pkgv, pkgv),
95 "xcursor-transparent-theme-staticdev: RDEPENDS: removed \"xcursor-transparent-theme-dev (['= %s-r1'])\", added \"xcursor-transparent-theme-dev (['= %s-r0'])\"" % (pkgv, pkgv)
96 ]
97 for line in result.output.splitlines():
98 for el in expected_endlines:
99 if line.endswith(el):
100 expected_endlines.remove(el)
101 break
102 else:
103 self.fail('Unexpected line:\n%s\nExpected line endings:\n %s' % (line, '\n '.join(expected_endlines)))
104 if expected_endlines:
105 self.fail('Missing expected line endings:\n %s' % '\n '.join(expected_endlines)) \ No newline at end of file
diff --git a/meta/lib/oeqa/selftest/cases/buildoptions.py b/meta/lib/oeqa/selftest/cases/buildoptions.py
index b509bcf951..767e19bd88 100644
--- a/meta/lib/oeqa/selftest/cases/buildoptions.py
+++ b/meta/lib/oeqa/selftest/cases/buildoptions.py
@@ -10,7 +10,6 @@ import glob as g
10import shutil 10import shutil
11import tempfile 11import tempfile
12from oeqa.selftest.case import OESelftestTestCase 12from oeqa.selftest.case import OESelftestTestCase
13from oeqa.selftest.cases.buildhistory import BuildhistoryBase
14from oeqa.core.decorator.data import skipIfMachine 13from oeqa.core.decorator.data import skipIfMachine
15from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars 14from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars
16import oeqa.utils.ftools as ftools 15import oeqa.utils.ftools as ftools
@@ -139,43 +138,6 @@ class SanityOptionsTest(OESelftestTestCase):
139 138
140 self.assertNotIn(err, ret.output) 139 self.assertNotIn(err, ret.output)
141 140
142
143class BuildhistoryTests(BuildhistoryBase):
144
145 def test_buildhistory_basic(self):
146 self.run_buildhistory_operation('xcursor-transparent-theme')
147 self.assertTrue(os.path.isdir(get_bb_var('BUILDHISTORY_DIR')), "buildhistory dir was not created.")
148
149 def test_buildhistory_buildtime_pr_backwards(self):
150 target = 'xcursor-transparent-theme'
151 error = "ERROR:.*QA Issue: Package version for package %s went backwards which would break package feeds \(from .*-r1.* to .*-r0.*\)" % target
152 self.run_buildhistory_operation(target, target_config="PR = \"r1\"", change_bh_location=True)
153 self.run_buildhistory_operation(target, target_config="PR = \"r0\"", change_bh_location=False, expect_error=True, error_regex=error)
154
155 def test_fileinfo(self):
156 self.config_buildhistory()
157 bitbake('hicolor-icon-theme')
158 history_dir = get_bb_var('BUILDHISTORY_DIR_PACKAGE', 'hicolor-icon-theme')
159 self.assertTrue(os.path.isdir(history_dir), 'buildhistory dir was not created.')
160
161 def load_bh(f):
162 d = {}
163 for line in open(f):
164 split = [s.strip() for s in line.split('=', 1)]
165 if len(split) > 1:
166 d[split[0]] = split[1]
167 return d
168
169 data = load_bh(os.path.join(history_dir, 'hicolor-icon-theme', 'latest'))
170 self.assertIn('FILELIST', data)
171 self.assertEqual(data['FILELIST'], '/usr/share/icons/hicolor/index.theme')
172 self.assertGreater(int(data['PKGSIZE']), 0)
173
174 data = load_bh(os.path.join(history_dir, 'hicolor-icon-theme-dev', 'latest'))
175 if 'FILELIST' in data:
176 self.assertEqual(data['FILELIST'], '/usr/share/pkgconfig/default-icon-theme.pc')
177 self.assertGreater(int(data['PKGSIZE']), 0)
178
179class ArchiverTest(OESelftestTestCase): 141class ArchiverTest(OESelftestTestCase):
180 def test_arch_work_dir_and_export_source(self): 142 def test_arch_work_dir_and_export_source(self):
181 """ 143 """
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 0155ee62ee..74a7727cc0 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -469,7 +469,7 @@ class DevtoolAddTests(DevtoolBase):
469 checkvars = {} 469 checkvars = {}
470 checkvars['LICENSE'] = 'GPL-2.0-only' 470 checkvars['LICENSE'] = 'GPL-2.0-only'
471 checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263' 471 checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263'
472 checkvars['S'] = '${WORKDIR}/git' 472 checkvars['S'] = None
473 checkvars['PV'] = '0.1+git' 473 checkvars['PV'] = '0.1+git'
474 checkvars['SRC_URI'] = 'git://git.yoctoproject.org/git/dbus-wait;protocol=https;branch=master' 474 checkvars['SRC_URI'] = 'git://git.yoctoproject.org/git/dbus-wait;protocol=https;branch=master'
475 checkvars['SRCREV'] = srcrev 475 checkvars['SRCREV'] = srcrev
@@ -565,7 +565,7 @@ class DevtoolAddTests(DevtoolBase):
565 recipefile = get_bb_var('FILE', testrecipe) 565 recipefile = get_bb_var('FILE', testrecipe)
566 self.assertIn('%s_%s.bb' % (testrecipe, testver), recipefile, 'Recipe file incorrectly named') 566 self.assertIn('%s_%s.bb' % (testrecipe, testver), recipefile, 'Recipe file incorrectly named')
567 checkvars = {} 567 checkvars = {}
568 checkvars['S'] = '${WORKDIR}/MarkupSafe-${PV}' 568 checkvars['S'] = '${UNPACKDIR}/MarkupSafe-${PV}'
569 checkvars['SRC_URI'] = url.replace(testver, '${PV}') 569 checkvars['SRC_URI'] = url.replace(testver, '${PV}')
570 self._test_recipe_contents(recipefile, checkvars, []) 570 self._test_recipe_contents(recipefile, checkvars, [])
571 # Try with version specified 571 # Try with version specified
@@ -582,7 +582,7 @@ class DevtoolAddTests(DevtoolBase):
582 recipefile = get_bb_var('FILE', testrecipe) 582 recipefile = get_bb_var('FILE', testrecipe)
583 self.assertIn('%s_%s.bb' % (testrecipe, fakever), recipefile, 'Recipe file incorrectly named') 583 self.assertIn('%s_%s.bb' % (testrecipe, fakever), recipefile, 'Recipe file incorrectly named')
584 checkvars = {} 584 checkvars = {}
585 checkvars['S'] = '${WORKDIR}/MarkupSafe-%s' % testver 585 checkvars['S'] = '${UNPACKDIR}/MarkupSafe-%s' % testver
586 checkvars['SRC_URI'] = url 586 checkvars['SRC_URI'] = url
587 self._test_recipe_contents(recipefile, checkvars, []) 587 self._test_recipe_contents(recipefile, checkvars, [])
588 588
@@ -609,7 +609,7 @@ class DevtoolAddTests(DevtoolBase):
609 recipefile = get_bb_var('FILE', testrecipe) 609 recipefile = get_bb_var('FILE', testrecipe)
610 self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named') 610 self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named')
611 checkvars = {} 611 checkvars = {}
612 checkvars['S'] = '${WORKDIR}/git' 612 checkvars['S'] = None
613 checkvars['PV'] = '1.0+git' 613 checkvars['PV'] = '1.0+git'
614 checkvars['SRC_URI'] = url_branch 614 checkvars['SRC_URI'] = url_branch
615 checkvars['SRCREV'] = '${AUTOREV}' 615 checkvars['SRCREV'] = '${AUTOREV}'
@@ -628,7 +628,7 @@ class DevtoolAddTests(DevtoolBase):
628 recipefile = get_bb_var('FILE', testrecipe) 628 recipefile = get_bb_var('FILE', testrecipe)
629 self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named') 629 self.assertIn('_git.bb', recipefile, 'Recipe file incorrectly named')
630 checkvars = {} 630 checkvars = {}
631 checkvars['S'] = '${WORKDIR}/git' 631 checkvars['S'] = None
632 checkvars['PV'] = '1.5+git' 632 checkvars['PV'] = '1.5+git'
633 checkvars['SRC_URI'] = url_branch 633 checkvars['SRC_URI'] = url_branch
634 checkvars['SRCREV'] = checkrev 634 checkvars['SRCREV'] = checkrev
@@ -1627,12 +1627,12 @@ class DevtoolUpdateTests(DevtoolBase):
1627 # Check preconditions 1627 # Check preconditions
1628 testrecipe = 'dos2unix' 1628 testrecipe = 'dos2unix'
1629 self.append_config('ERROR_QA:remove:pn-dos2unix = "patch-status"\n') 1629 self.append_config('ERROR_QA:remove:pn-dos2unix = "patch-status"\n')
1630 bb_vars = get_bb_vars(['SRC_URI', 'S', 'WORKDIR', 'FILE'], testrecipe) 1630 bb_vars = get_bb_vars(['SRC_URI', 'S', 'UNPACKDIR', 'FILE', 'BB_GIT_DEFAULT_DESTSUFFIX'], testrecipe)
1631 self.assertIn('git://', bb_vars['SRC_URI'], 'This test expects the %s recipe to be a git recipe' % testrecipe) 1631 self.assertIn('git://', bb_vars['SRC_URI'], 'This test expects the %s recipe to be a git recipe' % testrecipe)
1632 workdir_git = '%s/git/' % bb_vars['WORKDIR'] 1632 unpackdir_git = '%s/%s/' % (bb_vars['UNPACKDIR'], bb_vars['BB_GIT_DEFAULT_DESTSUFFIX'])
1633 if not bb_vars['S'].startswith(workdir_git): 1633 if not bb_vars['S'].startswith(unpackdir_git):
1634 self.fail('This test expects the %s recipe to be building from a subdirectory of the git repo' % testrecipe) 1634 self.fail('This test expects the %s recipe to be building from a subdirectory of the git repo' % testrecipe)
1635 subdir = bb_vars['S'].split(workdir_git, 1)[1] 1635 subdir = bb_vars['S'].split(unpackdir_git, 1)[1]
1636 # Clean up anything in the workdir/sysroot/sstate cache 1636 # Clean up anything in the workdir/sysroot/sstate cache
1637 bitbake('%s -c cleansstate' % testrecipe) 1637 bitbake('%s -c cleansstate' % testrecipe)
1638 # Try modifying a recipe 1638 # Try modifying a recipe
@@ -2414,7 +2414,7 @@ class DevtoolUpgradeTests(DevtoolBase):
2414 newsrctree = os.path.join(self.workspacedir, 'sources', newrecipename) 2414 newsrctree = os.path.join(self.workspacedir, 'sources', newrecipename)
2415 self.assertExists(newsrctree, 'Source directory not renamed') 2415 self.assertExists(newsrctree, 'Source directory not renamed')
2416 checkvars = {} 2416 checkvars = {}
2417 checkvars['S'] = '${WORKDIR}/%s-%s' % (recipename, recipever) 2417 checkvars['S'] = '${UNPACKDIR}/%s-%s' % (recipename, recipever)
2418 checkvars['SRC_URI'] = url 2418 checkvars['SRC_URI'] = url
2419 self._test_recipe_contents(newrecipefile, checkvars, []) 2419 self._test_recipe_contents(newrecipefile, checkvars, [])
2420 # Try again - change just name this time 2420 # Try again - change just name this time
@@ -2426,7 +2426,7 @@ class DevtoolUpgradeTests(DevtoolBase):
2426 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipename), 'Old recipe directory still exists') 2426 self.assertNotExists(os.path.join(self.workspacedir, 'recipes', recipename), 'Old recipe directory still exists')
2427 self.assertExists(os.path.join(self.workspacedir, 'sources', newrecipename), 'Source directory not renamed') 2427 self.assertExists(os.path.join(self.workspacedir, 'sources', newrecipename), 'Source directory not renamed')
2428 checkvars = {} 2428 checkvars = {}
2429 checkvars['S'] = '${WORKDIR}/%s-${PV}' % recipename 2429 checkvars['S'] = '${UNPACKDIR}/%s-${PV}' % recipename
2430 checkvars['SRC_URI'] = url.replace(recipever, '${PV}') 2430 checkvars['SRC_URI'] = url.replace(recipever, '${PV}')
2431 self._test_recipe_contents(newrecipefile, checkvars, []) 2431 self._test_recipe_contents(newrecipefile, checkvars, [])
2432 # Try again - change just version this time 2432 # Try again - change just version this time
@@ -2437,7 +2437,7 @@ class DevtoolUpgradeTests(DevtoolBase):
2437 self.assertExists(newrecipefile, 'Recipe file not renamed') 2437 self.assertExists(newrecipefile, 'Recipe file not renamed')
2438 self.assertExists(os.path.join(self.workspacedir, 'sources', recipename), 'Source directory no longer exists') 2438 self.assertExists(os.path.join(self.workspacedir, 'sources', recipename), 'Source directory no longer exists')
2439 checkvars = {} 2439 checkvars = {}
2440 checkvars['S'] = '${WORKDIR}/${BPN}-%s' % recipever 2440 checkvars['S'] = '${UNPACKDIR}/${BPN}-%s' % recipever
2441 checkvars['SRC_URI'] = url 2441 checkvars['SRC_URI'] = url
2442 self._test_recipe_contents(newrecipefile, checkvars, []) 2442 self._test_recipe_contents(newrecipefile, checkvars, [])
2443 2443
diff --git a/meta/lib/oeqa/selftest/cases/distrodata.py b/meta/lib/oeqa/selftest/cases/distrodata.py
index 1e88ea82e6..f2c6124d70 100644
--- a/meta/lib/oeqa/selftest/cases/distrodata.py
+++ b/meta/lib/oeqa/selftest/cases/distrodata.py
@@ -56,7 +56,7 @@ but their recipes claim otherwise by setting UPSTREAM_VERSION_UNKNOWN. Please re
56 56
57 def is_maintainer_exception(entry): 57 def is_maintainer_exception(entry):
58 exceptions = ["musl", "newlib", "picolibc", "linux-yocto", "linux-dummy", "mesa-gl", "libgfortran", "libx11-compose-data", 58 exceptions = ["musl", "newlib", "picolibc", "linux-yocto", "linux-dummy", "mesa-gl", "libgfortran", "libx11-compose-data",
59 "cve-update-nvd2-native", "barebox"] 59 "cve-update-nvd2-native", "barebox", "libglvnd"]
60 for i in exceptions: 60 for i in exceptions:
61 if i in entry: 61 if i in entry:
62 return True 62 return True
diff --git a/meta/lib/oeqa/selftest/cases/esdk.py b/meta/lib/oeqa/selftest/cases/esdk.py
index 9f5de2cde7..7a5fe00a08 100644
--- a/meta/lib/oeqa/selftest/cases/esdk.py
+++ b/meta/lib/oeqa/selftest/cases/esdk.py
@@ -27,11 +27,7 @@ class oeSDKExtSelfTest(OESelftestTestCase):
27 return glob.glob(pattern)[0] 27 return glob.glob(pattern)[0]
28 28
29 @staticmethod 29 @staticmethod
30 def run_esdk_cmd(env_eSDK, tmpdir_eSDKQA, cmd, postconfig=None, **options): 30 def run_esdk_cmd(env_eSDK, tmpdir_eSDKQA, cmd, **options):
31 if postconfig:
32 esdk_conf_file = os.path.join(tmpdir_eSDKQA, 'conf', 'local.conf')
33 with open(esdk_conf_file, 'a+') as f:
34 f.write(postconfig)
35 if not options: 31 if not options:
36 options = {} 32 options = {}
37 if not 'shell' in options: 33 if not 'shell' in options:
diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py
index b39f2622df..3c40857747 100644
--- a/meta/lib/oeqa/selftest/cases/fitimage.py
+++ b/meta/lib/oeqa/selftest/cases/fitimage.py
@@ -4,13 +4,36 @@
4# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
5# 5#
6 6
7from oeqa.selftest.case import OESelftestTestCase
8from oeqa.utils.commands import runCmd, bitbake, get_bb_vars
9import os 7import os
10import re 8import re
11import shlex 9import shlex
12import logging 10import logging
13import pprint 11import pprint
12import tempfile
13
14import oe.fitimage
15
16from oeqa.selftest.case import OESelftestTestCase
17from oeqa.utils.commands import runCmd, bitbake, get_bb_vars, get_bb_var
18
19
20class BbVarsMockGenKeys:
21 def __init__(self, keydir, gen_keys="0", sign_enabled="0", keyname="", sign_ind="0", img_keyname=""):
22 self.bb_vars = {
23 'FIT_GENERATE_KEYS': gen_keys,
24 'FIT_KEY_GENRSA_ARGS': "-F4",
25 'FIT_KEY_REQ_ARGS': "-batch -new",
26 'FIT_KEY_SIGN_PKCS': "-x509",
27 'FIT_SIGN_INDIVIDUAL': sign_ind,
28 'FIT_SIGN_NUMBITS': "2048",
29 'UBOOT_SIGN_ENABLE': sign_enabled,
30 'UBOOT_SIGN_IMG_KEYNAME': img_keyname,
31 'UBOOT_SIGN_KEYDIR': keydir,
32 'UBOOT_SIGN_KEYNAME': keyname,
33 }
34
35 def getVar(self, var):
36 return self.bb_vars[var]
14 37
15class FitImageTestCase(OESelftestTestCase): 38class FitImageTestCase(OESelftestTestCase):
16 """Test functions usable for testing kernel-fitimage.bbclass and uboot-sign.bbclass 39 """Test functions usable for testing kernel-fitimage.bbclass and uboot-sign.bbclass
@@ -161,10 +184,23 @@ class FitImageTestCase(OESelftestTestCase):
161 184
162 @staticmethod 185 @staticmethod
163 def _get_dtb_files(bb_vars): 186 def _get_dtb_files(bb_vars):
187 """Return a list of devicetree names
188
189 The list should be used to check the dtb and conf nodes in the FIT image or its file.
190 In addition to the entries from KERNEL_DEVICETREE, the external devicetree and the
191 external devicetree overlay added by the test recipe bbb-dtbs-as-ext are handled as well.
192 """
164 kernel_devicetree = bb_vars.get('KERNEL_DEVICETREE') 193 kernel_devicetree = bb_vars.get('KERNEL_DEVICETREE')
194 all_dtbs = []
195 dtb_symlinks = []
165 if kernel_devicetree: 196 if kernel_devicetree:
166 return [os.path.basename(dtb) for dtb in kernel_devicetree.split()] 197 all_dtbs += [os.path.basename(dtb) for dtb in kernel_devicetree.split()]
167 return [] 198 # Support only the test recipe which provides 1 devicetree and 1 devicetree overlay
199 pref_prov_dtb = bb_vars.get('PREFERRED_PROVIDER_virtual/dtb')
200 if pref_prov_dtb == "bbb-dtbs-as-ext":
201 all_dtbs += ["am335x-bonegreen-ext.dtb", "BBORG_RELAY-00A2.dtbo"]
202 dtb_symlinks.append("am335x-bonegreen-ext-alias.dtb")
203 return (all_dtbs, dtb_symlinks)
168 204
169 def _is_req_dict_in_dict(self, found_dict, req_dict): 205 def _is_req_dict_in_dict(self, found_dict, req_dict):
170 """ 206 """
@@ -243,7 +279,7 @@ class FitImageTestCase(OESelftestTestCase):
243 self.logger.debug("sigs:\n%s\n" % pprint.pformat(sigs, indent=4)) 279 self.logger.debug("sigs:\n%s\n" % pprint.pformat(sigs, indent=4))
244 if req_sigvalues_config or req_sigvalues_image: 280 if req_sigvalues_config or req_sigvalues_image:
245 for its_path, values in sigs.items(): 281 for its_path, values in sigs.items():
246 if 'conf-' in its_path: 282 if bb_vars.get('FIT_CONF_PREFIX', "conf-") in its_path:
247 reqsigvalues = req_sigvalues_config 283 reqsigvalues = req_sigvalues_config
248 else: 284 else:
249 reqsigvalues = req_sigvalues_image 285 reqsigvalues = req_sigvalues_image
@@ -356,9 +392,8 @@ class FitImageTestCase(OESelftestTestCase):
356 # Verify the FIT image 392 # Verify the FIT image
357 self._check_fitimage(bb_vars, fitimage_path, uboot_tools_bindir) 393 self._check_fitimage(bb_vars, fitimage_path, uboot_tools_bindir)
358 394
359 395class KernelFitImageBase(FitImageTestCase):
360class KernelFitImageTests(FitImageTestCase): 396 """Test cases for the linux-yocto-fitimage recipe"""
361 """Test cases for the kernel-fitimage bbclass"""
362 397
363 def _fit_get_bb_vars(self, additional_vars=[]): 398 def _fit_get_bb_vars(self, additional_vars=[]):
364 """Retrieve BitBake variables specific to the test case. 399 """Retrieve BitBake variables specific to the test case.
@@ -367,6 +402,8 @@ class KernelFitImageTests(FitImageTestCase):
367 """ 402 """
368 internal_used = { 403 internal_used = {
369 'DEPLOY_DIR_IMAGE', 404 'DEPLOY_DIR_IMAGE',
405 'FIT_CONF_DEFAULT_DTB',
406 'FIT_CONF_PREFIX',
370 'FIT_DESC', 407 'FIT_DESC',
371 'FIT_HASH_ALG', 408 'FIT_HASH_ALG',
372 'FIT_KERNEL_COMP_ALG', 409 'FIT_KERNEL_COMP_ALG',
@@ -376,9 +413,11 @@ class KernelFitImageTests(FitImageTestCase):
376 'INITRAMFS_IMAGE_BUNDLE', 413 'INITRAMFS_IMAGE_BUNDLE',
377 'INITRAMFS_IMAGE_NAME', 414 'INITRAMFS_IMAGE_NAME',
378 'INITRAMFS_IMAGE', 415 'INITRAMFS_IMAGE',
416 'KERNEL_DEPLOYSUBDIR',
379 'KERNEL_DEVICETREE', 417 'KERNEL_DEVICETREE',
380 'KERNEL_FIT_LINK_NAME', 418 'KERNEL_FIT_LINK_NAME',
381 'MACHINE', 419 'MACHINE',
420 'PREFERRED_PROVIDER_virtual/dtb',
382 'UBOOT_ARCH', 421 'UBOOT_ARCH',
383 'UBOOT_ENTRYPOINT', 422 'UBOOT_ENTRYPOINT',
384 'UBOOT_LOADADDRESS', 423 'UBOOT_LOADADDRESS',
@@ -391,10 +430,19 @@ class KernelFitImageTests(FitImageTestCase):
391 'UBOOT_SIGN_KEYDIR', 430 'UBOOT_SIGN_KEYDIR',
392 'UBOOT_SIGN_KEYNAME', 431 'UBOOT_SIGN_KEYNAME',
393 } 432 }
394 bb_vars = get_bb_vars(list(internal_used | set(additional_vars)), "virtual/kernel") 433 bb_vars = get_bb_vars(list(internal_used | set(additional_vars)), self.kernel_recipe)
395 self.logger.debug("bb_vars: %s" % pprint.pformat(bb_vars, indent=4)) 434 self.logger.debug("bb_vars: %s" % pprint.pformat(bb_vars, indent=4))
396 return bb_vars 435 return bb_vars
397 436
437 def _config_add_kernel_classes(self, config):
438 config += '# Use kernel-fit-extra-artifacts.bbclass for the creation of the vmlinux artifact' + os.linesep
439 config += 'KERNEL_CLASSES = "kernel-fit-extra-artifacts"' + os.linesep
440 return config
441
442 @property
443 def kernel_recipe(self):
444 return "linux-yocto-fitimage"
445
398 def _config_add_uboot_env(self, config): 446 def _config_add_uboot_env(self, config):
399 """Generate an u-boot environment 447 """Generate an u-boot environment
400 448
@@ -408,7 +456,7 @@ class KernelFitImageTests(FitImageTestCase):
408 config += '# Add an u-boot script to the fitImage' + os.linesep 456 config += '# Add an u-boot script to the fitImage' + os.linesep
409 config += 'FIT_UBOOT_ENV = "%s"' % fit_uenv_file + os.linesep 457 config += 'FIT_UBOOT_ENV = "%s"' % fit_uenv_file + os.linesep
410 config += 'FILESEXTRAPATHS:prepend := "${TOPDIR}/%s:"' % test_files_dir + os.linesep 458 config += 'FILESEXTRAPATHS:prepend := "${TOPDIR}/%s:"' % test_files_dir + os.linesep
411 config += 'SRC_URI:append:pn-linux-yocto = " file://${FIT_UBOOT_ENV}"' + os.linesep 459 config += 'SRC_URI:append:pn-%s = " file://${FIT_UBOOT_ENV}"' % self.kernel_recipe + os.linesep
412 460
413 if not os.path.isdir(test_files_dir): 461 if not os.path.isdir(test_files_dir):
414 os.makedirs(test_files_dir) 462 os.makedirs(test_files_dir)
@@ -420,7 +468,7 @@ class KernelFitImageTests(FitImageTestCase):
420 468
421 def _bitbake_fit_image(self, bb_vars): 469 def _bitbake_fit_image(self, bb_vars):
422 """Bitbake the kernel and return the paths to the its file and the FIT image""" 470 """Bitbake the kernel and return the paths to the its file and the FIT image"""
423 bitbake("virtual/kernel") 471 bitbake(self.kernel_recipe)
424 472
425 # Find the right its file and the final fitImage and check if both files are available 473 # Find the right its file and the final fitImage and check if both files are available
426 deploy_dir_image = bb_vars['DEPLOY_DIR_IMAGE'] 474 deploy_dir_image = bb_vars['DEPLOY_DIR_IMAGE']
@@ -439,8 +487,13 @@ class KernelFitImageTests(FitImageTestCase):
439 fitimage_name = "fitImage" # or fitImage-${KERNEL_IMAGE_LINK_NAME}${KERNEL_IMAGE_BIN_EXT} 487 fitimage_name = "fitImage" # or fitImage-${KERNEL_IMAGE_LINK_NAME}${KERNEL_IMAGE_BIN_EXT}
440 else: 488 else:
441 self.fail('Invalid configuration: INITRAMFS_IMAGE_BUNDLE = "1" and not INITRAMFS_IMAGE') 489 self.fail('Invalid configuration: INITRAMFS_IMAGE_BUNDLE = "1" and not INITRAMFS_IMAGE')
442 fitimage_its_path = os.path.realpath(os.path.join(deploy_dir_image, fitimage_its_name)) 490 kernel_deploysubdir = bb_vars['KERNEL_DEPLOYSUBDIR']
443 fitimage_path = os.path.realpath(os.path.join(deploy_dir_image, fitimage_name)) 491 if kernel_deploysubdir:
492 fitimage_its_path = os.path.realpath(os.path.join(deploy_dir_image, kernel_deploysubdir, fitimage_its_name))
493 fitimage_path = os.path.realpath(os.path.join(deploy_dir_image, kernel_deploysubdir, fitimage_name))
494 else:
495 fitimage_its_path = os.path.realpath(os.path.join(deploy_dir_image, fitimage_its_name))
496 fitimage_path = os.path.realpath(os.path.join(deploy_dir_image, fitimage_name))
444 return (fitimage_its_path, fitimage_path) 497 return (fitimage_its_path, fitimage_path)
445 498
446 def _get_req_its_paths(self, bb_vars): 499 def _get_req_its_paths(self, bb_vars):
@@ -452,7 +505,7 @@ class KernelFitImageTests(FitImageTestCase):
452 ['/', 'images', 'kernel-1', 'signature-1'], 505 ['/', 'images', 'kernel-1', 'signature-1'],
453 ] 506 ]
454 """ 507 """
455 dtb_files = FitImageTestCase._get_dtb_files(bb_vars) 508 dtb_files, dtb_symlinks = FitImageTestCase._get_dtb_files(bb_vars)
456 fit_sign_individual = bb_vars['FIT_SIGN_INDIVIDUAL'] 509 fit_sign_individual = bb_vars['FIT_SIGN_INDIVIDUAL']
457 fit_uboot_env = bb_vars['FIT_UBOOT_ENV'] 510 fit_uboot_env = bb_vars['FIT_UBOOT_ENV']
458 initramfs_image = bb_vars['INITRAMFS_IMAGE'] 511 initramfs_image = bb_vars['INITRAMFS_IMAGE']
@@ -470,11 +523,11 @@ class KernelFitImageTests(FitImageTestCase):
470 if initramfs_image and initramfs_image_bundle != "1": 523 if initramfs_image and initramfs_image_bundle != "1":
471 images.append('ramdisk-1') 524 images.append('ramdisk-1')
472 525
473 # configuration nodes 526 # configuration nodes (one per DTB and also one per symlink)
474 if dtb_files: 527 if dtb_files:
475 configurations = [ 'conf-' + conf for conf in dtb_files ] 528 configurations = [bb_vars['FIT_CONF_PREFIX'] + conf for conf in dtb_files + dtb_symlinks]
476 else: 529 else:
477 configurations = [ 'conf-1' ] 530 configurations = [bb_vars['FIT_CONF_PREFIX'] + '1']
478 531
479 # Create a list of paths for all image and configuration nodes 532 # Create a list of paths for all image and configuration nodes
480 req_its_paths = [] 533 req_its_paths = []
@@ -497,11 +550,11 @@ class KernelFitImageTests(FitImageTestCase):
497 its_field_check = [ 550 its_field_check = [
498 'description = "%s";' % bb_vars['FIT_DESC'], 551 'description = "%s";' % bb_vars['FIT_DESC'],
499 'description = "Linux kernel";', 552 'description = "Linux kernel";',
500 'data = /incbin/("linux.bin");',
501 'type = "' + str(bb_vars['UBOOT_MKIMAGE_KERNEL_TYPE']) + '";', 553 'type = "' + str(bb_vars['UBOOT_MKIMAGE_KERNEL_TYPE']) + '";',
554 # 'compression = "' + str(bb_vars['FIT_KERNEL_COMP_ALG']) + '";', defined based on files in TMPDIR, not ideal...
555 'data = /incbin/("linux.bin");',
502 'arch = "' + str(bb_vars['UBOOT_ARCH']) + '";', 556 'arch = "' + str(bb_vars['UBOOT_ARCH']) + '";',
503 'os = "linux";', 557 'os = "linux";',
504 # 'compression = "' + str(bb_vars['FIT_KERNEL_COMP_ALG']) + '";', defined based on files in TMPDIR, not ideal...
505 'load = <' + str(bb_vars['UBOOT_LOADADDRESS']) + '>;', 558 'load = <' + str(bb_vars['UBOOT_LOADADDRESS']) + '>;',
506 'entry = <' + str(bb_vars['UBOOT_ENTRYPOINT']) + '>;', 559 'entry = <' + str(bb_vars['UBOOT_ENTRYPOINT']) + '>;',
507 ] 560 ]
@@ -511,10 +564,14 @@ class KernelFitImageTests(FitImageTestCase):
511 its_field_check.append("load = <%s>;" % uboot_rd_loadaddress) 564 its_field_check.append("load = <%s>;" % uboot_rd_loadaddress)
512 if uboot_rd_entrypoint: 565 if uboot_rd_entrypoint:
513 its_field_check.append("entry = <%s>;" % uboot_rd_entrypoint) 566 its_field_check.append("entry = <%s>;" % uboot_rd_entrypoint)
514 its_field_check += [ 567
515 # 'default = "conf-1";', needs more work 568 fit_conf_default_dtb = bb_vars.get('FIT_CONF_DEFAULT_DTB')
516 'kernel = "kernel-1";', 569 if fit_conf_default_dtb:
517 ] 570 fit_conf_prefix = bb_vars.get('FIT_CONF_PREFIX', "conf-")
571 its_field_check.append('default = "' + fit_conf_prefix + fit_conf_default_dtb + '";')
572
573 its_field_check.append('kernel = "kernel-1";')
574
518 if initramfs_image and initramfs_image_bundle != "1": 575 if initramfs_image and initramfs_image_bundle != "1":
519 its_field_check.append('ramdisk = "ramdisk-1";') 576 its_field_check.append('ramdisk = "ramdisk-1";')
520 577
@@ -548,7 +605,7 @@ class KernelFitImageTests(FitImageTestCase):
548 605
549 def _get_req_sections(self, bb_vars): 606 def _get_req_sections(self, bb_vars):
550 """Generate a dictionary of expected sections in the output of dumpimage""" 607 """Generate a dictionary of expected sections in the output of dumpimage"""
551 dtb_files = FitImageTestCase._get_dtb_files(bb_vars) 608 dtb_files, dtb_symlinks = FitImageTestCase._get_dtb_files(bb_vars)
552 fit_hash_alg = bb_vars['FIT_HASH_ALG'] 609 fit_hash_alg = bb_vars['FIT_HASH_ALG']
553 fit_sign_alg = bb_vars['FIT_SIGN_ALG'] 610 fit_sign_alg = bb_vars['FIT_SIGN_ALG']
554 fit_sign_individual = bb_vars['FIT_SIGN_INDIVIDUAL'] 611 fit_sign_individual = bb_vars['FIT_SIGN_INDIVIDUAL']
@@ -584,25 +641,36 @@ class KernelFitImageTests(FitImageTestCase):
584 } 641 }
585 # Create a configuration section for each DTB 642 # Create a configuration section for each DTB
586 if dtb_files: 643 if dtb_files:
587 for dtb in dtb_files: 644 for dtb in dtb_files + dtb_symlinks:
588 req_sections['conf-' + dtb] = { 645 conf_name = bb_vars['FIT_CONF_PREFIX'] + dtb
589 "Kernel": "kernel-1", 646 # Assume that DTBs with an "-alias" in its name are symlink DTBs created e.g. by the
590 "FDT": 'fdt-' + dtb, 647 # bbb-dtbs-as-ext test recipe. Make the configuration node pointing to the real DTB.
591 } 648 real_dtb = dtb.replace("-alias", "")
649 # dtb overlays do not refer to a kernel (yet?)
650 if dtb.endswith('.dtbo'):
651 req_sections[conf_name] = {
652 "FDT": 'fdt-' + real_dtb,
653 }
654 else:
655 req_sections[conf_name] = {
656 "Kernel": "kernel-1",
657 "FDT": 'fdt-' + real_dtb,
658 }
592 if initramfs_image and initramfs_image_bundle != "1": 659 if initramfs_image and initramfs_image_bundle != "1":
593 req_sections['conf-' + dtb]['Init Ramdisk'] = "ramdisk-1" 660 req_sections[conf_name]['Init Ramdisk'] = "ramdisk-1"
594 else: 661 else:
595 req_sections['conf-1'] = { 662 conf_name = bb_vars['FIT_CONF_PREFIX'] + '1'
663 req_sections[conf_name] = {
596 "Kernel": "kernel-1" 664 "Kernel": "kernel-1"
597 } 665 }
598 if initramfs_image and initramfs_image_bundle != "1": 666 if initramfs_image and initramfs_image_bundle != "1":
599 req_sections['conf-1']['Init Ramdisk'] = "ramdisk-1" 667 req_sections[conf_name]['Init Ramdisk'] = "ramdisk-1"
600 668
601 # Add signing related properties if needed 669 # Add signing related properties if needed
602 if uboot_sign_enable == "1": 670 if uboot_sign_enable == "1":
603 for section in req_sections: 671 for section in req_sections:
604 req_sections[section]['Hash algo'] = fit_hash_alg 672 req_sections[section]['Hash algo'] = fit_hash_alg
605 if section.startswith('conf-'): 673 if section.startswith(bb_vars['FIT_CONF_PREFIX']):
606 req_sections[section]['Hash value'] = "unavailable" 674 req_sections[section]['Hash value'] = "unavailable"
607 req_sections[section]['Sign algo'] = "%s,%s:%s" % (fit_hash_alg, fit_sign_alg, uboot_sign_keyname) 675 req_sections[section]['Sign algo'] = "%s,%s:%s" % (fit_hash_alg, fit_sign_alg, uboot_sign_keyname)
608 num_signatures += 1 676 num_signatures += 1
@@ -624,18 +692,26 @@ class KernelFitImageTests(FitImageTestCase):
624 uboot_sign_keyname = bb_vars['UBOOT_SIGN_KEYNAME'] 692 uboot_sign_keyname = bb_vars['UBOOT_SIGN_KEYNAME']
625 uboot_sign_img_keyname = bb_vars['UBOOT_SIGN_IMG_KEYNAME'] 693 uboot_sign_img_keyname = bb_vars['UBOOT_SIGN_IMG_KEYNAME']
626 deploy_dir_image = bb_vars['DEPLOY_DIR_IMAGE'] 694 deploy_dir_image = bb_vars['DEPLOY_DIR_IMAGE']
695 kernel_deploysubdir = bb_vars['KERNEL_DEPLOYSUBDIR']
627 fit_sign_individual = bb_vars['FIT_SIGN_INDIVIDUAL'] 696 fit_sign_individual = bb_vars['FIT_SIGN_INDIVIDUAL']
628 fit_hash_alg_len = FitImageTestCase.MKIMAGE_HASH_LENGTHS[fit_hash_alg] 697 fit_hash_alg_len = FitImageTestCase.MKIMAGE_HASH_LENGTHS[fit_hash_alg]
629 fit_sign_alg_len = FitImageTestCase.MKIMAGE_SIGNATURE_LENGTHS[fit_sign_alg] 698 fit_sign_alg_len = FitImageTestCase.MKIMAGE_SIGNATURE_LENGTHS[fit_sign_alg]
630 for section, values in sections.items(): 699 for section, values in sections.items():
631 # Configuration nodes are always signed with UBOOT_SIGN_KEYNAME (if UBOOT_SIGN_ENABLE = "1") 700 # Configuration nodes are always signed with UBOOT_SIGN_KEYNAME (if UBOOT_SIGN_ENABLE = "1")
632 if section.startswith("conf"): 701 if section.startswith(bb_vars['FIT_CONF_PREFIX']):
633 sign_algo = values.get('Sign algo', None) 702 sign_algo = values.get('Sign algo', None)
634 req_sign_algo = "%s,%s:%s" % (fit_hash_alg, fit_sign_alg, uboot_sign_keyname) 703 req_sign_algo = "%s,%s:%s" % (fit_hash_alg, fit_sign_alg, uboot_sign_keyname)
635 self.assertEqual(sign_algo, req_sign_algo, 'Signature algorithm for %s not expected value' % section) 704 self.assertEqual(sign_algo, req_sign_algo, 'Signature algorithm for %s not expected value' % section)
636 sign_value = values.get('Sign value', None) 705 sign_value = values.get('Sign value', None)
637 self.assertEqual(len(sign_value), fit_sign_alg_len, 'Signature value for section %s not expected length' % section) 706 self.assertEqual(len(sign_value), fit_sign_alg_len, 'Signature value for section %s not expected length' % section)
638 dtb_path = os.path.join(deploy_dir_image, section.replace('conf-', '')) 707 dtb_file_name = section.replace(bb_vars['FIT_CONF_PREFIX'], '')
708 dtb_path = os.path.join(deploy_dir_image, dtb_file_name)
709 if kernel_deploysubdir:
710 dtb_path = os.path.join(deploy_dir_image, kernel_deploysubdir, dtb_file_name)
711 # External devicetrees created by devicetree.bbclass are in a subfolder and have priority
712 dtb_path_ext = os.path.join(deploy_dir_image, "devicetree", dtb_file_name)
713 if os.path.exists(dtb_path_ext):
714 dtb_path = dtb_path_ext
639 self._verify_fit_image_signature(uboot_tools_bindir, fitimage_path, dtb_path, section) 715 self._verify_fit_image_signature(uboot_tools_bindir, fitimage_path, dtb_path, section)
640 else: 716 else:
641 # Image nodes always need a hash which gets indirectly signed by the config signature 717 # Image nodes always need a hash which gets indirectly signed by the config signature
@@ -660,6 +736,8 @@ class KernelFitImageTests(FitImageTestCase):
660 self.assertEqual(found_comments, num_signatures, "Expected %d signed and commented (%s) sections in the fitImage." % 736 self.assertEqual(found_comments, num_signatures, "Expected %d signed and commented (%s) sections in the fitImage." %
661 (num_signatures, a_comment)) 737 (num_signatures, a_comment))
662 738
739class KernelFitImageRecipeTests(KernelFitImageBase):
740 """Test cases for the kernel-fitimage bbclass"""
663 741
664 def test_fit_image(self): 742 def test_fit_image(self):
665 """ 743 """
@@ -675,10 +753,7 @@ class KernelFitImageTests(FitImageTestCase):
675 Author: Usama Arif <usama.arif@arm.com> 753 Author: Usama Arif <usama.arif@arm.com>
676 """ 754 """
677 config = """ 755 config = """
678# Enable creation of fitImage
679KERNEL_IMAGETYPE = "Image" 756KERNEL_IMAGETYPE = "Image"
680KERNEL_IMAGETYPES += " fitImage "
681KERNEL_CLASSES = " kernel-fitimage "
682 757
683# RAM disk variables including load address and entrypoint for kernel and RAM disk 758# RAM disk variables including load address and entrypoint for kernel and RAM disk
684IMAGE_FSTYPES += "cpio.gz" 759IMAGE_FSTYPES += "cpio.gz"
@@ -690,8 +765,76 @@ UBOOT_RD_ENTRYPOINT = "0x88000000"
690UBOOT_LOADADDRESS = "0x80080000" 765UBOOT_LOADADDRESS = "0x80080000"
691UBOOT_ENTRYPOINT = "0x80080000" 766UBOOT_ENTRYPOINT = "0x80080000"
692FIT_DESC = "A model description" 767FIT_DESC = "A model description"
768FIT_CONF_PREFIX = "foo-"
769"""
770 config = self._config_add_kernel_classes(config)
771 self.write_config(config)
772 bb_vars = self._fit_get_bb_vars()
773 self._test_fitimage(bb_vars)
774
775 def test_get_compatible_from_dtb(self):
776 """Test the oe.fitimage.get_compatible_from_dtb function
777
778 1. bitbake bbb-dtbs-as-ext
779 2. Check if symlink_points_below returns the path to the DTB
780 3. Check if the expected compatible string is found by get_compatible_from_dtb()
781 """
782 DTB_RECIPE = "bbb-dtbs-as-ext"
783 DTB_FILE = "am335x-bonegreen-ext.dtb"
784 DTB_SYMLINK = "am335x-bonegreen-ext-alias.dtb"
785 DTBO_FILE = "BBORG_RELAY-00A2.dtbo"
786 EXPECTED_COMP = ["ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx"]
787
788 config = """
789DISTRO = "poky"
790MACHINE = "beaglebone-yocto"
693""" 791"""
694 self.write_config(config) 792 self.write_config(config)
793
794 # Provide the fdtget command called by get_compatible_from_dtb
795 dtc_bindir = FitImageTestCase._setup_native('dtc-native')
796 fdtget_path = os.path.join(dtc_bindir, "fdtget")
797 self.assertExists(fdtget_path)
798
799 # bitbake an external DTB with a symlink to it and a DTB overlay
800 bitbake(DTB_RECIPE)
801 deploy_dir_image = get_bb_var("DEPLOY_DIR_IMAGE", DTB_RECIPE)
802 devicetree_dir = os.path.join(deploy_dir_image, "devicetree")
803 dtb_path = os.path.join(devicetree_dir, DTB_FILE)
804 dtb_alias_path = os.path.join(devicetree_dir, DTB_SYMLINK)
805 dtbo_file = os.path.join(devicetree_dir, DTBO_FILE)
806 self.assertExists(dtb_path)
807 self.assertExists(dtb_alias_path)
808 self.assertExists(dtbo_file)
809
810 # Test symlink_points_below
811 linked_dtb = oe.fitimage.symlink_points_below(dtb_alias_path, devicetree_dir)
812 self.assertEqual(linked_dtb, DTB_FILE)
813
814 # Check if get_compatible_from_dtb finds the expected compatible string in the DTBs
815 comp = oe.fitimage.get_compatible_from_dtb(dtb_path, fdtget_path)
816 self.assertEqual(comp, EXPECTED_COMP)
817 comp_alias = oe.fitimage.get_compatible_from_dtb(dtb_alias_path, fdtget_path)
818 self.assertEqual(comp_alias, EXPECTED_COMP)
819 # The alias is a symlink, therefore the compatible string is equal
820 self.assertEqual(comp_alias, comp)
821
822 def test_fit_image_ext_dtb_dtbo(self):
823 """
824 Summary: Check if FIT image and Image Tree Source (its) are created correctly.
825 Expected: 1) its and FIT image are built successfully
826 2) The its file contains also the external devicetree overlay
827 3) Dumping the FIT image indicates the devicetree overlay
828 """
829 config = """
830# Enable creation of fitImage
831MACHINE = "beaglebone-yocto"
832# Add a devicetree overlay which does not need kernel sources
833PREFERRED_PROVIDER_virtual/dtb = "bbb-dtbs-as-ext"
834"""
835 config = self._config_add_kernel_classes(config)
836 config = self._config_add_uboot_env(config)
837 self.write_config(config)
695 bb_vars = self._fit_get_bb_vars() 838 bb_vars = self._fit_get_bb_vars()
696 self._test_fitimage(bb_vars) 839 self._test_fitimage(bb_vars)
697 840
@@ -702,8 +845,7 @@ FIT_DESC = "A model description"
702 and the configuration nodes are signed correctly. 845 and the configuration nodes are signed correctly.
703 Expected: 1) its and FIT image are built successfully 846 Expected: 1) its and FIT image are built successfully
704 2) Scanning the its file indicates signing is enabled 847 2) Scanning the its file indicates signing is enabled
705 as requested by UBOOT_SIGN_ENABLE (using 1 key 848 as requested by UBOOT_SIGN_ENABLE
706 generated by the test not via FIT_GENERATE_KEYS)
707 3) Dumping the FIT image indicates signature values 849 3) Dumping the FIT image indicates signature values
708 are present (only for the configuration nodes as 850 are present (only for the configuration nodes as
709 FIT_SIGN_INDIVIDUAL is disabled) 851 FIT_SIGN_INDIVIDUAL is disabled)
@@ -714,13 +856,13 @@ FIT_DESC = "A model description"
714 config = """ 856 config = """
715# Enable creation of fitImage 857# Enable creation of fitImage
716MACHINE = "beaglebone-yocto" 858MACHINE = "beaglebone-yocto"
717KERNEL_IMAGETYPES += " fitImage "
718KERNEL_CLASSES = " kernel-fitimage "
719UBOOT_SIGN_ENABLE = "1" 859UBOOT_SIGN_ENABLE = "1"
720UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" 860UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
721UBOOT_SIGN_KEYNAME = "dev" 861UBOOT_SIGN_KEYNAME = "dev"
722UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" 862UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
863FIT_CONF_DEFAULT_DTB = "am335x-bonegreen.dtb"
723""" 864"""
865 config = self._config_add_kernel_classes(config)
724 config = self._config_add_uboot_env(config) 866 config = self._config_add_uboot_env(config)
725 self.write_config(config) 867 self.write_config(config)
726 868
@@ -733,10 +875,7 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
733 'UBOOT_SIGN_KEYDIR', 875 'UBOOT_SIGN_KEYDIR',
734 ]) 876 ])
735 877
736 # Do not use the random keys generated by FIT_GENERATE_KEYS.
737 # Using a static key is probably a more realistic scenario.
738 self._gen_signing_key(bb_vars) 878 self._gen_signing_key(bb_vars)
739
740 self._test_fitimage(bb_vars) 879 self._test_fitimage(bb_vars)
741 880
742 def test_sign_fit_image_individual(self): 881 def test_sign_fit_image_individual(self):
@@ -745,11 +884,11 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
745 and all nodes are signed correctly. 884 and all nodes are signed correctly.
746 Expected: 1) its and FIT image are built successfully 885 Expected: 1) its and FIT image are built successfully
747 2) Scanning the its file indicates signing is enabled 886 2) Scanning the its file indicates signing is enabled
748 as requested by UBOOT_SIGN_ENABLE (using 2 keys 887 as requested by UBOOT_SIGN_ENABLE
749 generated via FIT_GENERATE_KEYS)
750 3) Dumping the FIT image indicates signature values 888 3) Dumping the FIT image indicates signature values
751 are present (including for images as enabled via 889 are present (including for images as enabled via
752 FIT_SIGN_INDIVIDUAL) 890 FIT_SIGN_INDIVIDUAL)
891 This also implies that FIT_GENERATE_KEYS = "1" works.
753 4) Verify the FIT image contains the comments passed via 892 4) Verify the FIT image contains the comments passed via
754 UBOOT_MKIMAGE_SIGN_ARGS once per image and per 893 UBOOT_MKIMAGE_SIGN_ARGS once per image and per
755 configuration node. 894 configuration node.
@@ -765,8 +904,6 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
765 config = """ 904 config = """
766# Enable creation of fitImage 905# Enable creation of fitImage
767MACHINE = "beaglebone-yocto" 906MACHINE = "beaglebone-yocto"
768KERNEL_IMAGETYPES += " fitImage "
769KERNEL_CLASSES = " kernel-fitimage "
770UBOOT_SIGN_ENABLE = "1" 907UBOOT_SIGN_ENABLE = "1"
771FIT_GENERATE_KEYS = "1" 908FIT_GENERATE_KEYS = "1"
772UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys" 909UBOOT_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
@@ -775,9 +912,14 @@ UBOOT_SIGN_KEYNAME = "cfg-oe-selftest"
775FIT_SIGN_INDIVIDUAL = "1" 912FIT_SIGN_INDIVIDUAL = "1"
776UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" 913UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
777""" 914"""
915 config = self._config_add_kernel_classes(config)
778 config = self._config_add_uboot_env(config) 916 config = self._config_add_uboot_env(config)
779 self.write_config(config) 917 self.write_config(config)
780 bb_vars = self._fit_get_bb_vars() 918 bb_vars = self._fit_get_bb_vars()
919
920 # Ensure new keys are generated and FIT_GENERATE_KEYS = "1" is tested
921 bitbake("kernel-signing-keys-native -c compile -f")
922
781 self._test_fitimage(bb_vars) 923 self._test_fitimage(bb_vars)
782 924
783 def test_fit_image_sign_initramfs(self): 925 def test_fit_image_sign_initramfs(self):
@@ -796,13 +938,11 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'"
796 """ 938 """
797 939
798 config = """ 940 config = """
799DISTRO="poky" 941DISTRO = "poky"
800MACHINE = "beaglebone-yocto" 942MACHINE = "beaglebone-yocto"
801INITRAMFS_IMAGE = "core-image-minimal-initramfs" 943INITRAMFS_IMAGE = "core-image-minimal-initramfs"
802INITRAMFS_SCRIPTS = "" 944INITRAMFS_SCRIPTS = ""
803UBOOT_MACHINE = "am335x_evm_defconfig" 945UBOOT_MACHINE = "am335x_evm_defconfig"
804KERNEL_CLASSES = " kernel-fitimage "
805KERNEL_IMAGETYPES = "fitImage"
806UBOOT_SIGN_ENABLE = "1" 946UBOOT_SIGN_ENABLE = "1"
807UBOOT_SIGN_KEYNAME = "beaglebonekey" 947UBOOT_SIGN_KEYNAME = "beaglebonekey"
808UBOOT_SIGN_KEYDIR ?= "${DEPLOY_DIR_IMAGE}" 948UBOOT_SIGN_KEYDIR ?= "${DEPLOY_DIR_IMAGE}"
@@ -816,11 +956,11 @@ UBOOT_ARCH = "arm"
816UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" 956UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
817UBOOT_MKIMAGE_KERNEL_TYPE = "kernel" 957UBOOT_MKIMAGE_KERNEL_TYPE = "kernel"
818UBOOT_EXTLINUX = "0" 958UBOOT_EXTLINUX = "0"
819FIT_GENERATE_KEYS = "1"
820KERNEL_IMAGETYPE_REPLACEMENT = "zImage" 959KERNEL_IMAGETYPE_REPLACEMENT = "zImage"
821FIT_KERNEL_COMP_ALG = "none" 960FIT_KERNEL_COMP_ALG = "none"
822FIT_HASH_ALG = "sha256" 961FIT_HASH_ALG = "sha256"
823""" 962"""
963 config = self._config_add_kernel_classes(config)
824 config = self._config_add_uboot_env(config) 964 config = self._config_add_uboot_env(config)
825 self.write_config(config) 965 self.write_config(config)
826 966
@@ -833,10 +973,7 @@ FIT_HASH_ALG = "sha256"
833 'UBOOT_SIGN_KEYDIR', 973 'UBOOT_SIGN_KEYDIR',
834 ]) 974 ])
835 975
836 # Do not use the random keys generated by FIT_GENERATE_KEYS.
837 # Using a static key is probably a more realistic scenario.
838 self._gen_signing_key(bb_vars) 976 self._gen_signing_key(bb_vars)
839
840 self._test_fitimage(bb_vars) 977 self._test_fitimage(bb_vars)
841 978
842 def test_fit_image_sign_initramfs_bundle(self): 979 def test_fit_image_sign_initramfs_bundle(self):
@@ -855,14 +992,12 @@ FIT_HASH_ALG = "sha256"
855 """ 992 """
856 993
857 config = """ 994 config = """
858DISTRO="poky" 995DISTRO = "poky"
859MACHINE = "beaglebone-yocto" 996MACHINE = "beaglebone-yocto"
860INITRAMFS_IMAGE_BUNDLE = "1" 997INITRAMFS_IMAGE_BUNDLE = "1"
861INITRAMFS_IMAGE = "core-image-minimal-initramfs" 998INITRAMFS_IMAGE = "core-image-minimal-initramfs"
862INITRAMFS_SCRIPTS = "" 999INITRAMFS_SCRIPTS = ""
863UBOOT_MACHINE = "am335x_evm_defconfig" 1000UBOOT_MACHINE = "am335x_evm_defconfig"
864KERNEL_CLASSES = " kernel-fitimage "
865KERNEL_IMAGETYPES = "fitImage"
866UBOOT_SIGN_ENABLE = "1" 1001UBOOT_SIGN_ENABLE = "1"
867UBOOT_SIGN_KEYNAME = "beaglebonekey" 1002UBOOT_SIGN_KEYNAME = "beaglebonekey"
868UBOOT_SIGN_KEYDIR ?= "${DEPLOY_DIR_IMAGE}" 1003UBOOT_SIGN_KEYDIR ?= "${DEPLOY_DIR_IMAGE}"
@@ -874,20 +1009,124 @@ UBOOT_ARCH = "arm"
874UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" 1009UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000"
875UBOOT_MKIMAGE_KERNEL_TYPE = "kernel" 1010UBOOT_MKIMAGE_KERNEL_TYPE = "kernel"
876UBOOT_EXTLINUX = "0" 1011UBOOT_EXTLINUX = "0"
877FIT_GENERATE_KEYS = "1"
878KERNEL_IMAGETYPE_REPLACEMENT = "zImage" 1012KERNEL_IMAGETYPE_REPLACEMENT = "zImage"
879FIT_KERNEL_COMP_ALG = "none" 1013FIT_KERNEL_COMP_ALG = "none"
880FIT_HASH_ALG = "sha256" 1014FIT_HASH_ALG = "sha256"
881""" 1015"""
1016 config = self._config_add_kernel_classes(config)
882 config = self._config_add_uboot_env(config) 1017 config = self._config_add_uboot_env(config)
883 self.write_config(config) 1018 self.write_config(config)
884 bb_vars = self._fit_get_bb_vars() 1019 bb_vars = self._fit_get_bb_vars()
1020 self._gen_signing_key(bb_vars)
885 self._test_fitimage(bb_vars) 1021 self._test_fitimage(bb_vars)
886 1022
1023class FitImagePyTests(KernelFitImageBase):
1024 """Test cases for the fitimage.py module without calling bitbake"""
1025
1026 def _test_fitimage_py(self, bb_vars_overrides=None):
1027 topdir = os.path.join(os.environ['BUILDDIR'])
1028 fitimage_its_path = os.path.join(topdir, self._testMethodName + '.its')
1029
1030 # Provide variables without calling bitbake
1031 bb_vars = {
1032 # image-fitimage.conf
1033 'FIT_DESC': "Kernel fitImage for a dummy distro",
1034 'FIT_HASH_ALG': "sha256",
1035 'FIT_SIGN_ALG': "rsa2048",
1036 'FIT_PAD_ALG': "pkcs-1.5",
1037 'FIT_GENERATE_KEYS': "0",
1038 'FIT_SIGN_NUMBITS': "2048",
1039 'FIT_KEY_GENRSA_ARGS': "-F4",
1040 'FIT_KEY_REQ_ARGS': "-batch -new",
1041 'FIT_KEY_SIGN_PKCS': "-x509",
1042 'FIT_SIGN_INDIVIDUAL': "0",
1043 'FIT_CONF_PREFIX': "conf-",
1044 'FIT_SUPPORTED_INITRAMFS_FSTYPES': "cpio.lz4 cpio.lzo cpio.lzma cpio.xz cpio.zst cpio.gz ext2.gz cpio",
1045 'FIT_CONF_DEFAULT_DTB': "",
1046 'FIT_ADDRESS_CELLS': "1",
1047 'FIT_UBOOT_ENV': "",
1048 # kernel.bbclass
1049 'UBOOT_ENTRYPOINT': "0x20008000",
1050 'UBOOT_LOADADDRESS': "0x20008000",
1051 'INITRAMFS_IMAGE': "",
1052 'INITRAMFS_IMAGE_BUNDLE': "",
1053 # kernel-uboot.bbclass
1054 'FIT_KERNEL_COMP_ALG': "gzip",
1055 'FIT_KERNEL_COMP_ALG_EXTENSION': ".gz",
1056 'UBOOT_MKIMAGE_KERNEL_TYPE': "kernel",
1057 # uboot-config.bbclass
1058 'UBOOT_MKIMAGE_DTCOPTS': "",
1059 'UBOOT_MKIMAGE': "uboot-mkimage",
1060 'UBOOT_MKIMAGE_SIGN': "uboot-mkimage",
1061 'UBOOT_MKIMAGE_SIGN_ARGS': "",
1062 'UBOOT_SIGN_ENABLE': "0",
1063 'UBOOT_SIGN_KEYDIR': None,
1064 'UBOOT_SIGN_KEYNAME': None,
1065 'UBOOT_SIGN_IMG_KEYNAME': None,
1066 # others
1067 'MACHINE': "qemux86-64",
1068 'UBOOT_ARCH': "x86",
1069 'HOST_PREFIX': "x86_64-poky-linux-"
1070 }
1071 if bb_vars_overrides:
1072 bb_vars.update(bb_vars_overrides)
1073
1074 root_node = oe.fitimage.ItsNodeRootKernel(
1075 bb_vars["FIT_DESC"], bb_vars["FIT_ADDRESS_CELLS"],
1076 bb_vars['HOST_PREFIX'], bb_vars['UBOOT_ARCH'], bb_vars["FIT_CONF_PREFIX"],
1077 oe.types.boolean(bb_vars['UBOOT_SIGN_ENABLE']), bb_vars["UBOOT_SIGN_KEYDIR"],
1078 bb_vars["UBOOT_MKIMAGE"], bb_vars["UBOOT_MKIMAGE_DTCOPTS"],
1079 bb_vars["UBOOT_MKIMAGE_SIGN"], bb_vars["UBOOT_MKIMAGE_SIGN_ARGS"],
1080 bb_vars['FIT_HASH_ALG'], bb_vars['FIT_SIGN_ALG'], bb_vars['FIT_PAD_ALG'],
1081 bb_vars['UBOOT_SIGN_KEYNAME'],
1082 oe.types.boolean(bb_vars['FIT_SIGN_INDIVIDUAL']), bb_vars['UBOOT_SIGN_IMG_KEYNAME']
1083 )
1084
1085 root_node.fitimage_emit_section_kernel("kernel-1", "linux.bin", "none",
1086 bb_vars.get('UBOOT_LOADADDRESS'), bb_vars.get('UBOOT_ENTRYPOINT'),
1087 bb_vars.get('UBOOT_MKIMAGE_KERNEL_TYPE'), bb_vars.get("UBOOT_ENTRYSYMBOL")
1088 )
1089
1090 dtb_files, _ = FitImageTestCase._get_dtb_files(bb_vars)
1091 for dtb in dtb_files:
1092 root_node.fitimage_emit_section_dtb(dtb, os.path.join("a-dir", dtb),
1093 bb_vars.get("UBOOT_DTB_LOADADDRESS"), bb_vars.get("UBOOT_DTBO_LOADADDRESS"))
1094
1095 if bb_vars.get('FIT_UBOOT_ENV'):
1096 root_node.fitimage_emit_section_boot_script(
1097 "bootscr-" + bb_vars['FIT_UBOOT_ENV'], bb_vars['FIT_UBOOT_ENV'])
1098
1099 if bb_vars['MACHINE'] == "qemux86-64": # Not really the right if
1100 root_node.fitimage_emit_section_setup("setup-1", "setup1.bin")
1101
1102 if bb_vars.get('INITRAMFS_IMAGE') and bb_vars.get("INITRAMFS_IMAGE_BUNDLE") != "1":
1103 root_node.fitimage_emit_section_ramdisk("ramdisk-1", "a-dir/a-initramfs-1",
1104 "core-image-minimal-initramfs",
1105 bb_vars.get("UBOOT_RD_LOADADDRESS"), bb_vars.get("UBOOT_RD_ENTRYPOINT"))
1106
1107 root_node.fitimage_emit_section_config(bb_vars['FIT_CONF_DEFAULT_DTB'])
1108 root_node.write_its_file(fitimage_its_path)
1109
1110 self.assertExists(fitimage_its_path, "%s image tree source doesn't exist" % (fitimage_its_path))
1111 self.logger.debug("Checking its: %s" % fitimage_its_path)
1112 self._check_its_file(bb_vars, fitimage_its_path)
1113
1114 def test_fitimage_py_default(self):
1115 self._test_fitimage_py()
1116
1117 def test_fitimage_py_default_dtb(self):
1118 bb_vars_overrides = {
1119 'KERNEL_DEVICETREE': "one.dtb two.dtb three.dtb",
1120 'FIT_CONF_DEFAULT_DTB': "two.dtb"
1121 }
1122 self._test_fitimage_py(bb_vars_overrides)
1123
887 1124
888class UBootFitImageTests(FitImageTestCase): 1125class UBootFitImageTests(FitImageTestCase):
889 """Test cases for the uboot-sign bbclass""" 1126 """Test cases for the uboot-sign bbclass"""
890 1127
1128 BOOTLOADER_RECIPE = "virtual/bootloader"
1129
891 def _fit_get_bb_vars(self, additional_vars=[]): 1130 def _fit_get_bb_vars(self, additional_vars=[]):
892 """Get bb_vars as needed by _test_sign_fit_image 1131 """Get bb_vars as needed by _test_sign_fit_image
893 1132
@@ -929,13 +1168,13 @@ class UBootFitImageTests(FitImageTestCase):
929 'UBOOT_SIGN_KEYDIR', 1168 'UBOOT_SIGN_KEYDIR',
930 'UBOOT_SIGN_KEYNAME', 1169 'UBOOT_SIGN_KEYNAME',
931 } 1170 }
932 bb_vars = get_bb_vars(list(internal_used | set(additional_vars)), "virtual/bootloader") 1171 bb_vars = get_bb_vars(list(internal_used | set(additional_vars)), UBootFitImageTests.BOOTLOADER_RECIPE)
933 self.logger.debug("bb_vars: %s" % pprint.pformat(bb_vars, indent=4)) 1172 self.logger.debug("bb_vars: %s" % pprint.pformat(bb_vars, indent=4))
934 return bb_vars 1173 return bb_vars
935 1174
936 def _bitbake_fit_image(self, bb_vars): 1175 def _bitbake_fit_image(self, bb_vars):
937 """Bitbake the bootloader and return the paths to the its file and the FIT image""" 1176 """Bitbake the bootloader and return the paths to the its file and the FIT image"""
938 bitbake("virtual/bootloader") 1177 bitbake(UBootFitImageTests.BOOTLOADER_RECIPE)
939 1178
940 deploy_dir_image = bb_vars['DEPLOY_DIR_IMAGE'] 1179 deploy_dir_image = bb_vars['DEPLOY_DIR_IMAGE']
941 machine = bb_vars['MACHINE'] 1180 machine = bb_vars['MACHINE']
@@ -1286,9 +1525,7 @@ UBOOT_SIGN_KEYNAME = "cfg-oe-selftest"
1286 self.write_config(config) 1525 self.write_config(config)
1287 bb_vars = self._fit_get_bb_vars() 1526 bb_vars = self._fit_get_bb_vars()
1288 1527
1289 # Using a static key. FIT_GENERATE_KEYS = "1" does not work without kernel-fitimage.bbclass
1290 self._gen_signing_key(bb_vars) 1528 self._gen_signing_key(bb_vars)
1291
1292 self._test_fitimage(bb_vars) 1529 self._test_fitimage(bb_vars)
1293 self._check_kernel_dtb(bb_vars) 1530 self._check_kernel_dtb(bb_vars)
1294 1531
@@ -1449,11 +1686,46 @@ FIT_SIGN_INDIVIDUAL = "1"
1449""" 1686"""
1450 self.write_config(config) 1687 self.write_config(config)
1451 bb_vars = self._fit_get_bb_vars() 1688 bb_vars = self._fit_get_bb_vars()
1452
1453 # Using a static key. FIT_GENERATE_KEYS = "1" does not work without kernel-fitimage.bbclass
1454 self._gen_signing_key(bb_vars) 1689 self._gen_signing_key(bb_vars)
1455 1690
1456 bitbake("virtual/bootloader") 1691 bitbake(UBootFitImageTests.BOOTLOADER_RECIPE)
1457 1692
1458 # Just check the DTB of u-boot since there is no u-boot FIT image 1693 # Just check the DTB of u-boot since there is no u-boot FIT image
1459 self._check_kernel_dtb(bb_vars) 1694 self._check_kernel_dtb(bb_vars)
1695
1696
1697 def test_sign_uboot_fit_image_without_spl(self):
1698 """
1699 Summary: Check if U-Boot FIT image and Image Tree Source (its) are
1700 created and signed correctly for the scenario where only
1701 the U-Boot proper fitImage is being created and signed
1702 (no SPL included).
1703 Expected: 1) U-Boot its and FIT image are built successfully
1704 2) Scanning the its file indicates signing is enabled
1705 as requested by SPL_SIGN_ENABLE (using keys generated
1706 via UBOOT_FIT_GENERATE_KEYS)
1707 3) Dumping the FIT image indicates signature values
1708 are present
1709 4) Examination of the do_uboot_assemble_fitimage
1710 runfile/logfile indicate that UBOOT_MKIMAGE and
1711 UBOOT_MKIMAGE_SIGN are working as expected.
1712 Product: oe-core
1713 Author: Jamin Lin <jamin_lin@aspeedtech.com>
1714 """
1715 config = """
1716# There's no U-boot defconfig with CONFIG_FIT_SIGNATURE yet, so we need at
1717# least CONFIG_SPL_LOAD_FIT and CONFIG_SPL_OF_CONTROL set
1718MACHINE = "qemuarm"
1719UBOOT_MACHINE = "am57xx_evm_defconfig"
1720# Enable creation and signing of the U-Boot fitImage (no SPL)
1721UBOOT_FITIMAGE_ENABLE = "1"
1722SPL_DTB_BINARY = ""
1723SPL_SIGN_ENABLE = "1"
1724SPL_SIGN_KEYNAME = "spl-oe-selftest"
1725SPL_SIGN_KEYDIR = "${TOPDIR}/signing-keys"
1726UBOOT_FIT_GENERATE_KEYS = "1"
1727"""
1728 self.write_config(config)
1729 bb_vars = self._fit_get_bb_vars()
1730 self._test_fitimage(bb_vars)
1731
diff --git a/meta/lib/oeqa/selftest/cases/liboe.py b/meta/lib/oeqa/selftest/cases/liboe.py
index d5ffffdcb4..930354c931 100644
--- a/meta/lib/oeqa/selftest/cases/liboe.py
+++ b/meta/lib/oeqa/selftest/cases/liboe.py
@@ -9,11 +9,11 @@ from oeqa.utils.commands import get_bb_var, get_bb_vars, bitbake, runCmd
9import oe.path 9import oe.path
10import os 10import os
11 11
12class LibOE(OESelftestTestCase): 12class CopyTreeTests(OESelftestTestCase):
13 13
14 @classmethod 14 @classmethod
15 def setUpClass(cls): 15 def setUpClass(cls):
16 super(LibOE, cls).setUpClass() 16 super().setUpClass()
17 cls.tmp_dir = get_bb_var('TMPDIR') 17 cls.tmp_dir = get_bb_var('TMPDIR')
18 18
19 def test_copy_tree_special(self): 19 def test_copy_tree_special(self):
@@ -102,3 +102,36 @@ class LibOE(OESelftestTestCase):
102 self.assertEqual(dstcnt, len(testfiles), "Number of files in dst (%s) differs from number of files in src(%s)." % (dstcnt, srccnt)) 102 self.assertEqual(dstcnt, len(testfiles), "Number of files in dst (%s) differs from number of files in src(%s)." % (dstcnt, srccnt))
103 103
104 oe.path.remove(testloc) 104 oe.path.remove(testloc)
105
106class SubprocessTests(OESelftestTestCase):
107
108 def test_subprocess_tweak(self):
109 """
110 Test that the string representation of
111 oeqa.utils.subprocesstweak.OETestCalledProcessError includes stdout and
112 stderr, as expected.
113 """
114 script = """
115#! /bin/sh
116echo Ivn fgqbhg | tr '[a-zA-Z]' '[n-za-mN-ZA-M]'
117echo Ivn fgqree | tr '[a-zA-Z]' '[n-za-mN-ZA-M]' >&2
118exit 42
119 """
120
121 import subprocess
122 import unittest.mock
123 from oeqa.utils.subprocesstweak import OETestCalledProcessError
124
125 with self.assertRaises(OETestCalledProcessError) as cm:
126 with unittest.mock.patch("subprocess.CalledProcessError", OETestCalledProcessError):
127 subprocess.run(["bash", "-"], input=script, text=True, capture_output=True, check=True)
128
129 e = cm.exception
130 self.assertEqual(e.returncode, 42)
131 self.assertEqual("Via stdout\n", e.stdout)
132 self.assertEqual("Via stderr\n", e.stderr)
133
134 string = str(e)
135 self.assertIn("exit status 42", string)
136 self.assertIn("Standard Output: Via stdout", string)
137 self.assertIn("Standard Error: Via stderr", string)
diff --git a/meta/lib/oeqa/selftest/cases/oescripts.py b/meta/lib/oeqa/selftest/cases/oescripts.py
index bfbc33b08d..3f9899b289 100644
--- a/meta/lib/oeqa/selftest/cases/oescripts.py
+++ b/meta/lib/oeqa/selftest/cases/oescripts.py
@@ -9,33 +9,9 @@ import shutil
9import importlib 9import importlib
10import unittest 10import unittest
11from oeqa.selftest.case import OESelftestTestCase 11from oeqa.selftest.case import OESelftestTestCase
12from oeqa.selftest.cases.buildhistory import BuildhistoryBase
13from oeqa.utils.commands import runCmd, bitbake, get_bb_var 12from oeqa.utils.commands import runCmd, bitbake, get_bb_var
14from oeqa.utils import CommandError 13from oeqa.utils import CommandError
15 14
16class BuildhistoryDiffTests(BuildhistoryBase):
17
18 def test_buildhistory_diff(self):
19 target = 'xcursor-transparent-theme'
20 self.run_buildhistory_operation(target, target_config="PR = \"r1\"", change_bh_location=True)
21 self.run_buildhistory_operation(target, target_config="PR = \"r0\"", change_bh_location=False, expect_error=True)
22 result = runCmd("oe-pkgdata-util read-value PKGV %s" % target)
23 pkgv = result.output.rstrip()
24 result = runCmd("buildhistory-diff -p %s" % get_bb_var('BUILDHISTORY_DIR'))
25 expected_endlines = [
26 "xcursor-transparent-theme-dev: RRECOMMENDS: removed \"xcursor-transparent-theme (['= %s-r1'])\", added \"xcursor-transparent-theme (['= %s-r0'])\"" % (pkgv, pkgv),
27 "xcursor-transparent-theme-staticdev: RDEPENDS: removed \"xcursor-transparent-theme-dev (['= %s-r1'])\", added \"xcursor-transparent-theme-dev (['= %s-r0'])\"" % (pkgv, pkgv)
28 ]
29 for line in result.output.splitlines():
30 for el in expected_endlines:
31 if line.endswith(el):
32 expected_endlines.remove(el)
33 break
34 else:
35 self.fail('Unexpected line:\n%s\nExpected line endings:\n %s' % (line, '\n '.join(expected_endlines)))
36 if expected_endlines:
37 self.fail('Missing expected line endings:\n %s' % '\n '.join(expected_endlines))
38
39@unittest.skipUnless(importlib.util.find_spec("cairo"), "Python cairo module is not present") 15@unittest.skipUnless(importlib.util.find_spec("cairo"), "Python cairo module is not present")
40class OEPybootchartguyTests(OESelftestTestCase): 16class OEPybootchartguyTests(OESelftestTestCase):
41 17
diff --git a/meta/lib/oeqa/selftest/cases/pokybleeding.py b/meta/lib/oeqa/selftest/cases/pokybleeding.py
deleted file mode 100644
index d0940d680d..0000000000
--- a/meta/lib/oeqa/selftest/cases/pokybleeding.py
+++ /dev/null
@@ -1,32 +0,0 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7from oeqa.utils.commands import bitbake, get_bb_var
8from oeqa.selftest.case import OESelftestTestCase
9
10class PokyBleeding(OESelftestTestCase):
11
12 def test_poky_bleeding_autorev(self):
13 """
14 Test that poky-bleeding.bbclass sets SRCREV to "AUTOINC" for recipe
15 with a single scm in SRC_URI and for recipe with two scm's in SRC_URI.
16 """
17
18 self.assertNotEqual( get_bb_var('SRCREV', 'pseudo'), "AUTOINC")
19
20 self.assertNotEqual( get_bb_var('SRCREV', 'hello-rs'), "AUTOINC")
21 self.assertNotEqual( get_bb_var('SRCREV_hello-lib', 'hello-rs'), "AUTOINC")
22
23 features = '''
24INHERIT += "poky-bleeding"
25POKY_AUTOREV_RECIPES = "hello-rs pseudo"
26'''
27 self.write_config(features)
28
29 self.assertEqual( get_bb_var('SRCREV', 'pseudo'), "AUTOINC")
30
31 self.assertEqual( get_bb_var('SRCREV', 'hello-rs'), "AUTOINC")
32 self.assertEqual( get_bb_var('SRCREV_hello-lib', 'hello-rs'), "AUTOINC")
diff --git a/meta/lib/oeqa/selftest/cases/recipetool.py b/meta/lib/oeqa/selftest/cases/recipetool.py
index 36557f270f..2a91f6c7ae 100644
--- a/meta/lib/oeqa/selftest/cases/recipetool.py
+++ b/meta/lib/oeqa/selftest/cases/recipetool.py
@@ -385,7 +385,7 @@ class RecipetoolCreateTests(RecipetoolBase):
385 checkvars = {} 385 checkvars = {}
386 checkvars['LICENSE'] = 'LGPL-2.1-only' 386 checkvars['LICENSE'] = 'LGPL-2.1-only'
387 checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=7fbc338309ac38fefcd64b04bb903e34' 387 checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=7fbc338309ac38fefcd64b04bb903e34'
388 checkvars['S'] = '${WORKDIR}/git' 388 checkvars['S'] = None
389 checkvars['PV'] = '1.11+git' 389 checkvars['PV'] = '1.11+git'
390 checkvars['SRC_URI'] = srcuri + ';branch=master' 390 checkvars['SRC_URI'] = srcuri + ';branch=master'
391 checkvars['DEPENDS'] = set(['libcheck', 'libjpeg-turbo', 'libpng', 'libx11', 'libxext', 'pango']) 391 checkvars['DEPENDS'] = set(['libcheck', 'libjpeg-turbo', 'libpng', 'libx11', 'libxext', 'pango'])
@@ -1144,10 +1144,10 @@ class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase):
1144 1144
1145 def test_recipetool_appendsrcfile_srcdir_basic(self): 1145 def test_recipetool_appendsrcfile_srcdir_basic(self):
1146 testrecipe = 'bash' 1146 testrecipe = 'bash'
1147 bb_vars = get_bb_vars(['S', 'WORKDIR'], testrecipe) 1147 bb_vars = get_bb_vars(['S', 'UNPACKDIR'], testrecipe)
1148 srcdir = bb_vars['S'] 1148 srcdir = bb_vars['S']
1149 workdir = bb_vars['WORKDIR'] 1149 unpackdir = bb_vars['UNPACKDIR']
1150 subdir = os.path.relpath(srcdir, workdir) 1150 subdir = os.path.relpath(srcdir, unpackdir)
1151 self._test_appendsrcfile(testrecipe, 'a-file', srcdir=subdir) 1151 self._test_appendsrcfile(testrecipe, 'a-file', srcdir=subdir)
1152 1152
1153 def test_recipetool_appendsrcfile_existing_in_src_uri(self): 1153 def test_recipetool_appendsrcfile_existing_in_src_uri(self):
@@ -1196,10 +1196,10 @@ class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase):
1196 def test_recipetool_appendsrcfile_replace_file_srcdir(self): 1196 def test_recipetool_appendsrcfile_replace_file_srcdir(self):
1197 testrecipe = 'bash' 1197 testrecipe = 'bash'
1198 filepath = 'Makefile.in' 1198 filepath = 'Makefile.in'
1199 bb_vars = get_bb_vars(['S', 'WORKDIR'], testrecipe) 1199 bb_vars = get_bb_vars(['S', 'UNPACKDIR'], testrecipe)
1200 srcdir = bb_vars['S'] 1200 srcdir = bb_vars['S']
1201 workdir = bb_vars['WORKDIR'] 1201 unpackdir = bb_vars['UNPACKDIR']
1202 subdir = os.path.relpath(srcdir, workdir) 1202 subdir = os.path.relpath(srcdir, unpackdir)
1203 1203
1204 self._test_appendsrcfile(testrecipe, filepath, srcdir=subdir) 1204 self._test_appendsrcfile(testrecipe, filepath, srcdir=subdir)
1205 bitbake('%s:do_unpack' % testrecipe) 1205 bitbake('%s:do_unpack' % testrecipe)
diff --git a/meta/lib/oeqa/selftest/cases/recipeutils.py b/meta/lib/oeqa/selftest/cases/recipeutils.py
index 9949737172..e697fd2920 100644
--- a/meta/lib/oeqa/selftest/cases/recipeutils.py
+++ b/meta/lib/oeqa/selftest/cases/recipeutils.py
@@ -72,7 +72,7 @@ class RecipeUtilsTests(OESelftestTestCase):
72 expected_patch = """ 72 expected_patch = """
73--- a/recipes-test/recipeutils/recipeutils-test_1.2.bb 73--- a/recipes-test/recipeutils/recipeutils-test_1.2.bb
74+++ b/recipes-test/recipeutils/recipeutils-test_1.2.bb 74+++ b/recipes-test/recipeutils/recipeutils-test_1.2.bb
75@@ -11,6 +11,4 @@ 75@@ -10,6 +10,4 @@
76 76
77 BBCLASSEXTEND = "native nativesdk" 77 BBCLASSEXTEND = "native nativesdk"
78 78
@@ -97,7 +97,7 @@ class RecipeUtilsTests(OESelftestTestCase):
97 expected_patch = """ 97 expected_patch = """
98--- a/recipes-test/recipeutils/recipeutils-test_1.2.bb 98--- a/recipes-test/recipeutils/recipeutils-test_1.2.bb
99+++ b/recipes-test/recipeutils/recipeutils-test_1.2.bb 99+++ b/recipes-test/recipeutils/recipeutils-test_1.2.bb
100@@ -11,6 +11,3 @@ 100@@ -10,6 +10,3 @@
101 101
102 BBCLASSEXTEND = "native nativesdk" 102 BBCLASSEXTEND = "native nativesdk"
103 103
diff --git a/meta/lib/oeqa/selftest/cases/rust.py b/meta/lib/oeqa/selftest/cases/rust.py
index 806ddf6982..d99a58d6b9 100644
--- a/meta/lib/oeqa/selftest/cases/rust.py
+++ b/meta/lib/oeqa/selftest/cases/rust.py
@@ -104,7 +104,7 @@ class RustSelfTestSystemEmulated(OESelftestTestCase, OEPTestResultTestCase):
104 # Copy remote-test-server to image through scp 104 # Copy remote-test-server to image through scp
105 host_sys = get_bb_var("RUST_BUILD_SYS", "rust") 105 host_sys = get_bb_var("RUST_BUILD_SYS", "rust")
106 ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user="root") 106 ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user="root")
107 ssh.copy_to(builddir + "/build/" + host_sys + "/stage1-tools-bin/remote-test-server","~/") 107 ssh.copy_to(builddir + "/build/" + host_sys + "/stage2-tools-bin/remote-test-server","~/")
108 # Execute remote-test-server on image through background ssh 108 # Execute remote-test-server on image through background ssh
109 command = '~/remote-test-server --bind 0.0.0.0:12345 -v' 109 command = '~/remote-test-server --bind 0.0.0.0:12345 -v'
110 sshrun=subprocess.Popen(("ssh", '-o', 'UserKnownHostsFile=/dev/null', '-o', 'StrictHostKeyChecking=no', '-f', "root@%s" % qemu.ip, command), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 110 sshrun=subprocess.Popen(("ssh", '-o', 'UserKnownHostsFile=/dev/null', '-o', 'StrictHostKeyChecking=no', '-f', "root@%s" % qemu.ip, command), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
diff --git a/meta/lib/oeqa/selftest/cases/sstatetests.py b/meta/lib/oeqa/selftest/cases/sstatetests.py
index 681a57f4db..08f94b168a 100644
--- a/meta/lib/oeqa/selftest/cases/sstatetests.py
+++ b/meta/lib/oeqa/selftest/cases/sstatetests.py
@@ -27,17 +27,15 @@ class SStateBase(OESelftestTestCase):
27 def setUpLocal(self): 27 def setUpLocal(self):
28 super(SStateBase, self).setUpLocal() 28 super(SStateBase, self).setUpLocal()
29 self.temp_sstate_location = None 29 self.temp_sstate_location = None
30 needed_vars = ['SSTATE_DIR', 'NATIVELSBSTRING', 'TCLIBC', 'TUNE_ARCH', 30 needed_vars = ['SSTATE_DIR', 'TCLIBC', 'TUNE_ARCH',
31 'TOPDIR', 'TARGET_VENDOR', 'TARGET_OS'] 31 'TOPDIR', 'TARGET_VENDOR', 'TARGET_OS']
32 bb_vars = get_bb_vars(needed_vars) 32 bb_vars = get_bb_vars(needed_vars)
33 self.sstate_path = bb_vars['SSTATE_DIR'] 33 self.sstate_path = bb_vars['SSTATE_DIR']
34 self.hostdistro = bb_vars['NATIVELSBSTRING']
35 self.tclibc = bb_vars['TCLIBC'] 34 self.tclibc = bb_vars['TCLIBC']
36 self.tune_arch = bb_vars['TUNE_ARCH'] 35 self.tune_arch = bb_vars['TUNE_ARCH']
37 self.topdir = bb_vars['TOPDIR'] 36 self.topdir = bb_vars['TOPDIR']
38 self.target_vendor = bb_vars['TARGET_VENDOR'] 37 self.target_vendor = bb_vars['TARGET_VENDOR']
39 self.target_os = bb_vars['TARGET_OS'] 38 self.target_os = bb_vars['TARGET_OS']
40 self.distro_specific_sstate = os.path.join(self.sstate_path, self.hostdistro)
41 39
42 def track_for_cleanup(self, path): 40 def track_for_cleanup(self, path):
43 if not keep_temp_files: 41 if not keep_temp_files:
@@ -52,10 +50,7 @@ class SStateBase(OESelftestTestCase):
52 config_temp_sstate = "SSTATE_DIR = \"%s\"" % temp_sstate_path 50 config_temp_sstate = "SSTATE_DIR = \"%s\"" % temp_sstate_path
53 self.append_config(config_temp_sstate) 51 self.append_config(config_temp_sstate)
54 self.track_for_cleanup(temp_sstate_path) 52 self.track_for_cleanup(temp_sstate_path)
55 bb_vars = get_bb_vars(['SSTATE_DIR', 'NATIVELSBSTRING']) 53 self.sstate_path = get_bb_var('SSTATE_DIR')
56 self.sstate_path = bb_vars['SSTATE_DIR']
57 self.hostdistro = bb_vars['NATIVELSBSTRING']
58 self.distro_specific_sstate = os.path.join(self.sstate_path, self.hostdistro)
59 54
60 if add_local_mirrors: 55 if add_local_mirrors:
61 config_set_sstate_if_not_set = 'SSTATE_MIRRORS ?= ""' 56 config_set_sstate_if_not_set = 'SSTATE_MIRRORS ?= ""'
@@ -65,8 +60,16 @@ class SStateBase(OESelftestTestCase):
65 config_sstate_mirror = "SSTATE_MIRRORS += \"file://.* file:///%s/PATH\"" % local_mirror 60 config_sstate_mirror = "SSTATE_MIRRORS += \"file://.* file:///%s/PATH\"" % local_mirror
66 self.append_config(config_sstate_mirror) 61 self.append_config(config_sstate_mirror)
67 62
63 def set_hostdistro(self):
64 # This needs to be read after a BuildStarted event in case it gets changed by event
65 # handling in uninative.bbclass
66 self.hostdistro = get_bb_var('NATIVELSBSTRING')
67 self.distro_specific_sstate = os.path.join(self.sstate_path, self.hostdistro)
68
68 # Returns a list containing sstate files 69 # Returns a list containing sstate files
69 def search_sstate(self, filename_regex, distro_specific=True, distro_nonspecific=True): 70 def search_sstate(self, filename_regex, distro_specific=True, distro_nonspecific=True):
71 self.set_hostdistro()
72
70 result = [] 73 result = []
71 for root, dirs, files in os.walk(self.sstate_path): 74 for root, dirs, files in os.walk(self.sstate_path):
72 if distro_specific and re.search(r"%s/%s/[a-z0-9]{2}/[a-z0-9]{2}$" % (self.sstate_path, self.hostdistro), root): 75 if distro_specific and re.search(r"%s/%s/[a-z0-9]{2}/[a-z0-9]{2}$" % (self.sstate_path, self.hostdistro), root):
@@ -80,55 +83,43 @@ class SStateBase(OESelftestTestCase):
80 return result 83 return result
81 84
82 # Test sstate files creation and their location and directory perms 85 # Test sstate files creation and their location and directory perms
83 def run_test_sstate_creation(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True, should_pass=True): 86 def run_test_sstate_creation(self, targets, hostdistro_specific):
84 self.config_sstate(temp_sstate_location, [self.sstate_path]) 87 self.config_sstate(True, [self.sstate_path])
88
89 bitbake(['-cclean'] + targets)
85 90
86 if self.temp_sstate_location:
87 bitbake(['-cclean'] + targets)
88 else:
89 bitbake(['-ccleansstate'] + targets)
90
91 # We need to test that the env umask have does not effect sstate directory creation
92 # So, first, we'll get the current umask and set it to something we know incorrect
93 # See: sstate_task_postfunc for correct umask of os.umask(0o002)
94 import os
95 def current_umask():
96 current_umask = os.umask(0)
97 os.umask(current_umask)
98 return current_umask
99
100 orig_umask = current_umask()
101 # Set it to a umask we know will be 'wrong' 91 # Set it to a umask we know will be 'wrong'
102 os.umask(0o022) 92 with bb.utils.umask(0o022):
93 bitbake(targets)
103 94
104 bitbake(targets) 95 # Distro specific files
105 file_tracker = [] 96 distro_specific_files = self.search_sstate('|'.join(map(str, targets)), True, False)
106 results = self.search_sstate('|'.join(map(str, targets)), distro_specific, distro_nonspecific) 97
107 if distro_nonspecific: 98 # Distro non-specific
108 for r in results: 99 distro_non_specific_files = []
109 if r.endswith(("_populate_lic.tar.zst", "_populate_lic.tar.zst.siginfo", "_fetch.tar.zst.siginfo", "_unpack.tar.zst.siginfo", "_patch.tar.zst.siginfo")): 100 results = self.search_sstate('|'.join(map(str, targets)), False, True)
110 continue 101 for r in results:
111 file_tracker.append(r) 102 if r.endswith(("_populate_lic.tar.zst", "_populate_lic.tar.zst.siginfo", "_fetch.tar.zst.siginfo", "_unpack.tar.zst.siginfo", "_patch.tar.zst.siginfo")):
112 else: 103 continue
113 file_tracker = results 104 distro_non_specific_files.append(r)
114 105
115 if should_pass: 106 if hostdistro_specific:
116 self.assertTrue(file_tracker , msg="Could not find sstate files for: %s" % ', '.join(map(str, targets))) 107 self.assertTrue(distro_specific_files , msg="Could not find sstate files for: %s" % ', '.join(map(str, targets)))
108 self.assertFalse(distro_non_specific_files, msg="Found sstate files in the wrong place for: %s (found %s)" % (', '.join(map(str, targets)), str(distro_non_specific_files)))
117 else: 109 else:
118 self.assertTrue(not file_tracker , msg="Found sstate files in the wrong place for: %s (found %s)" % (', '.join(map(str, targets)), str(file_tracker))) 110 self.assertTrue(distro_non_specific_files , msg="Could not find sstate files for: %s" % ', '.join(map(str, targets)))
111 self.assertFalse(distro_specific_files, msg="Found sstate files in the wrong place for: %s (found %s)" % (', '.join(map(str, targets)), str(distro_specific_files)))
119 112
120 # Now we'll walk the tree to check the mode and see if things are incorrect. 113 # Now we'll walk the tree to check the mode and see if things are incorrect.
121 badperms = [] 114 badperms = []
122 for root, dirs, files in os.walk(self.sstate_path): 115 for root, dirs, files in os.walk(self.sstate_path):
123 for directory in dirs: 116 for directory in dirs:
124 if (os.stat(os.path.join(root, directory)).st_mode & 0o777) != 0o775: 117 mode = os.stat(os.path.join(root, directory)).st_mode & 0o777
125 badperms.append(os.path.join(root, directory)) 118 if mode != 0o775:
126 119 badperms.append("%s: %s vs %s" % (os.path.join(root, directory), mode, 0o775))
127 # Return to original umask
128 os.umask(orig_umask)
129 120
130 if should_pass: 121 # Check badperms is empty
131 self.assertTrue(badperms , msg="Found sstate directories with the wrong permissions: %s (found %s)" % (', '.join(map(str, targets)), str(badperms))) 122 self.assertFalse(badperms , msg="Found sstate directories with the wrong permissions: %s (found %s)" % (', '.join(map(str, targets)), str(badperms)))
132 123
133 # Test the sstate files deletion part of the do_cleansstate task 124 # Test the sstate files deletion part of the do_cleansstate task
134 def run_test_cleansstate_task(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True): 125 def run_test_cleansstate_task(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True):
@@ -153,6 +144,8 @@ class SStateBase(OESelftestTestCase):
153 144
154 bitbake(['-ccleansstate'] + targets) 145 bitbake(['-ccleansstate'] + targets)
155 146
147 self.set_hostdistro()
148
156 bitbake(targets) 149 bitbake(targets)
157 results = self.search_sstate('|'.join(map(str, [s + r'.*?\.tar.zst$' for s in targets])), distro_specific=False, distro_nonspecific=True) 150 results = self.search_sstate('|'.join(map(str, [s + r'.*?\.tar.zst$' for s in targets])), distro_specific=False, distro_nonspecific=True)
158 filtered_results = [] 151 filtered_results = []
@@ -251,17 +244,11 @@ class SStateTests(SStateBase):
251 bitbake("dbus-wait-test -c unpack") 244 bitbake("dbus-wait-test -c unpack")
252 245
253class SStateCreation(SStateBase): 246class SStateCreation(SStateBase):
254 def test_sstate_creation_distro_specific_pass(self): 247 def test_sstate_creation_distro_specific(self):
255 self.run_test_sstate_creation(['binutils-cross-'+ self.tune_arch, 'binutils-native'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True) 248 self.run_test_sstate_creation(['binutils-cross-'+ self.tune_arch, 'binutils-native'], hostdistro_specific=True)
256
257 def test_sstate_creation_distro_specific_fail(self):
258 self.run_test_sstate_creation(['binutils-cross-'+ self.tune_arch, 'binutils-native'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True, should_pass=False)
259
260 def test_sstate_creation_distro_nonspecific_pass(self):
261 self.run_test_sstate_creation(['linux-libc-headers'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True)
262 249
263 def test_sstate_creation_distro_nonspecific_fail(self): 250 def test_sstate_creation_distro_nonspecific(self):
264 self.run_test_sstate_creation(['linux-libc-headers'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True, should_pass=False) 251 self.run_test_sstate_creation(['linux-libc-headers'], hostdistro_specific=False)
265 252
266class SStateCleanup(SStateBase): 253class SStateCleanup(SStateBase):
267 def test_cleansstate_task_distro_specific_nonspecific(self): 254 def test_cleansstate_task_distro_specific_nonspecific(self):
@@ -972,7 +959,7 @@ class SStateMirrors(SStateCheckObjectPresence):
972 self.append_config(""" 959 self.append_config("""
973MACHINE = "{}" 960MACHINE = "{}"
974BB_HASHSERVE_UPSTREAM = "hashserv.yoctoproject.org:8686" 961BB_HASHSERVE_UPSTREAM = "hashserv.yoctoproject.org:8686"
975SSTATE_MIRRORS ?= "file://.* http://cdn.jsdelivr.net/yocto/sstate/all/PATH;downloadfilename=PATH" 962SSTATE_MIRRORS ?= "file://.* http://sstate.yoctoproject.org/all/PATH;downloadfilename=PATH"
976""".format(machine)) 963""".format(machine))
977 else: 964 else:
978 self.append_config(""" 965 self.append_config("""
diff --git a/meta/lib/oeqa/selftest/cases/toolchain.py b/meta/lib/oeqa/selftest/cases/toolchain.py
new file mode 100644
index 0000000000..b4b280d037
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/toolchain.py
@@ -0,0 +1,71 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7import shutil
8import subprocess
9import tempfile
10from types import SimpleNamespace
11
12import oe.path
13from oeqa.selftest.case import OESelftestTestCase
14from oeqa.utils.commands import bitbake, get_bb_var, get_bb_vars
15
16class ToolchainTests(OESelftestTestCase):
17
18 def test_toolchain_switching(self):
19 """
20 Test that a configuration that uses GCC by default but clang for one
21 specific recipe does infact do that.
22 """
23
24 def extract_comment(objcopy, filename):
25 """
26 Using the specified `objcopy`, return the .comment segment from
27 `filename` as a bytes().
28 """
29 with tempfile.NamedTemporaryFile(prefix="comment-") as f:
30 cmd = [objcopy, "--dump-section", ".comment=" + f.name, filename]
31 subprocess.run(cmd, check=True)
32 # clang's objcopy writes to a temporary file and renames, so we need to re-open.
33 with open(f.name, "rb") as f2:
34 return f2.read()
35
36 def check_recipe(recipe, filename, override, comment_present, comment_absent=None):
37 """
38 Check that `filename` in `recipe`'s bindir contains `comment`, and
39 the overrides contain `override`.
40 """
41 d = SimpleNamespace(**get_bb_vars(("D", "bindir", "OBJCOPY", "OVERRIDES", "PATH"), target=recipe))
42
43 self.assertIn(override, d.OVERRIDES)
44
45 binary = oe.path.join(d.D, d.bindir, filename)
46
47 objcopy = shutil.which(d.OBJCOPY, path=d.PATH)
48 self.assertIsNotNone(objcopy)
49
50 comment = extract_comment(objcopy, binary)
51 self.assertIn(comment_present, comment)
52 if comment_absent:
53 self.assertNotIn(comment_absent, comment)
54
55
56 # GCC by default, clang for selftest-hello.
57 self.write_config("""
58TOOLCHAIN = "gcc"
59TOOLCHAIN:pn-selftest-hello = "clang"
60 """)
61
62 # Force these recipes to re-install so we can extract the .comments from
63 # the install directory, as they're stripped out of the final packages.
64 bitbake("m4 selftest-hello -C install")
65
66 # m4 should be built with GCC and only GCC
67 check_recipe("m4", "m4", "toolchain-gcc", b"GCC: (GNU)", b"clang")
68
69 # helloworld should be built with clang. We can't assert that GCC is not
70 # present as it will be linked against glibc which is built with GCC.
71 check_recipe("selftest-hello", "helloworld", "toolchain-clang", b"clang version")
diff --git a/meta/lib/oeqa/selftest/cases/uboot.py b/meta/lib/oeqa/selftest/cases/uboot.py
index 96da4efb06..980ea327f0 100644
--- a/meta/lib/oeqa/selftest/cases/uboot.py
+++ b/meta/lib/oeqa/selftest/cases/uboot.py
@@ -6,8 +6,8 @@
6# 6#
7 7
8from oeqa.selftest.case import OESelftestTestCase 8from oeqa.selftest.case import OESelftestTestCase
9from oeqa.utils.commands import bitbake, runqemu 9from oeqa.utils.commands import bitbake, runqemu, get_bb_var, get_bb_vars, runCmd
10from oeqa.core.decorator.data import skipIfNotArch 10from oeqa.core.decorator.data import skipIfNotArch, skipIfNotBuildArch
11from oeqa.core.decorator import OETestTag 11from oeqa.core.decorator import OETestTag
12 12
13uboot_boot_patterns = { 13uboot_boot_patterns = {
@@ -41,3 +41,58 @@ QEMU_USE_KVM = "False"
41 status, output = qemu.run_serial(cmd) 41 status, output = qemu.run_serial(cmd)
42 self.assertEqual(status, 1, msg=output) 42 self.assertEqual(status, 1, msg=output)
43 self.assertTrue("U-Boot" in output, msg=output) 43 self.assertTrue("U-Boot" in output, msg=output)
44
45 @skipIfNotArch(['aarch64'])
46 @skipIfNotBuildArch(['aarch64'])
47 @OETestTag("runqemu")
48 def test_boot_uboot_kvm_to_full_target(self):
49 """
50 Tests building u-boot and booting it with QEMU and KVM.
51 Requires working KVM on build host. See "kvm-ok" output.
52 """
53
54 runCmd("kvm-ok")
55
56 image = "core-image-minimal"
57 vars = get_bb_vars(['HOST_ARCH', 'BUILD_ARCH'], image)
58 host_arch = vars['HOST_ARCH']
59 build_arch = vars['BUILD_ARCH']
60
61 self.assertEqual(host_arch, build_arch, 'HOST_ARCH %s and BUILD_ARCH %s must match for KVM' % (host_arch, build_arch))
62
63 self.write_config("""
64QEMU_USE_KVM = "1"
65
66# Using u-boot in EFI mode, need ESP partition for grub/systemd-boot/kernel etc
67IMAGE_FSTYPES:pn-core-image-minimal:append = " wic"
68
69# easiest to follow genericarm64 setup with wks file, initrd and EFI loader
70INITRAMFS_IMAGE = "core-image-initramfs-boot"
71EFI_PROVIDER = "${@bb.utils.contains("DISTRO_FEATURES", "systemd", "systemd-boot", "grub-efi", d)}"
72WKS_FILE = "genericarm64.wks.in"
73
74# use wic image with ESP for u-boot, not ext4
75QB_DEFAULT_FSTYPE = "wic"
76
77PREFERRED_PROVIDER_virtual/bootloader = "u-boot"
78QB_DEFAULT_BIOS = "u-boot.bin"
79
80# let u-boot or EFI loader load kernel from ESP
81QB_DEFAULT_KERNEL = "none"
82
83# virt pci, not scsi because support not in u-boot to find ESP
84QB_DRIVE_TYPE = "/dev/vd"
85""")
86 bitbake("virtual/bootloader %s" % image)
87
88 runqemu_params = get_bb_var('TEST_RUNQEMUPARAMS', image) or ""
89 with runqemu(image, ssh=False, runqemuparams='nographic kvm %s' % runqemu_params) as qemu:
90
91 # boot to target and login worked, should have been fast with kvm
92 cmd = "dmesg"
93 status, output = qemu.run_serial(cmd)
94 self.assertEqual(status, 1, msg=output)
95 # Machine is qemu
96 self.assertTrue("Machine model: linux,dummy-virt" in output, msg=output)
97 # with KVM enabled
98 self.assertTrue("KVM: hypervisor services detected" in output, msg=output)
diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py
index 1a67b6df51..680f99d381 100644
--- a/meta/lib/oeqa/selftest/cases/wic.py
+++ b/meta/lib/oeqa/selftest/cases/wic.py
@@ -153,7 +153,7 @@ class Wic(WicTestCase):
153 # create a temporary file for the WKS content 153 # create a temporary file for the WKS content
154 with NamedTemporaryFile("w", suffix=".wks") as wks: 154 with NamedTemporaryFile("w", suffix=".wks") as wks:
155 wks.write( 155 wks.write(
156 'part --source bootimg-efi ' 156 'part --source bootimg_efi '
157 '--sourceparams="loader=grub-efi,install-kernel-into-boot-dir=false" ' 157 '--sourceparams="loader=grub-efi,install-kernel-into-boot-dir=false" '
158 '--label boot --active\n' 158 '--label boot --active\n'
159 ) 159 )
@@ -186,7 +186,7 @@ class Wic(WicTestCase):
186 # create a temporary file for the WKS content 186 # create a temporary file for the WKS content
187 with NamedTemporaryFile("w", suffix=".wks") as wks: 187 with NamedTemporaryFile("w", suffix=".wks") as wks:
188 wks.write( 188 wks.write(
189 'part --source bootimg-efi ' 189 'part --source bootimg_efi '
190 '--sourceparams="loader=grub-efi,install-kernel-into-boot-dir=true" ' 190 '--sourceparams="loader=grub-efi,install-kernel-into-boot-dir=true" '
191 '--label boot --active\n' 191 '--label boot --active\n'
192 ) 192 )
@@ -1021,6 +1021,18 @@ class Wic2(WicTestCase):
1021 """Test building wic images by bitbake""" 1021 """Test building wic images by bitbake"""
1022 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\ 1022 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\
1023 'MACHINE_FEATURES:append = " efi"\n' 1023 'MACHINE_FEATURES:append = " efi"\n'
1024 image_recipe_append = """
1025do_image_wic[postfuncs] += "run_wic_cmd"
1026run_wic_cmd() {
1027 echo "test" >> ${WORKDIR}/test.wic-cp
1028 wic cp --vars "${STAGING_DIR}/${MACHINE}/imgdata/" -e "${IMAGE_BASENAME}" ${WORKDIR}/test.wic-cp ${IMGDEPLOYDIR}/${IMAGE_NAME}.wic:1/
1029 wic ls --vars "${STAGING_DIR}/${MACHINE}/imgdata/" -e "${IMAGE_BASENAME}" ${IMGDEPLOYDIR}/${IMAGE_NAME}.wic:1/
1030 wic rm --vars "${STAGING_DIR}/${MACHINE}/imgdata/" -e "${IMAGE_BASENAME}" ${IMGDEPLOYDIR}/${IMAGE_NAME}.wic:1/test.wic-cp
1031 wic cp --vars "${STAGING_DIR}/${MACHINE}/imgdata/" -e "${IMAGE_BASENAME}" ${WORKDIR}/test.wic-cp ${IMGDEPLOYDIR}/${IMAGE_NAME}.wic:1/
1032}
1033"""
1034 self.write_recipeinc('images', image_recipe_append)
1035
1024 self.append_config(config) 1036 self.append_config(config)
1025 image = 'wic-image-minimal' 1037 image = 'wic-image-minimal'
1026 bitbake(image) 1038 bitbake(image)
@@ -1029,6 +1041,11 @@ class Wic2(WicTestCase):
1029 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_LINK_NAME'], image) 1041 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_LINK_NAME'], image)
1030 prefix = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], '%s.' % bb_vars['IMAGE_LINK_NAME']) 1042 prefix = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], '%s.' % bb_vars['IMAGE_LINK_NAME'])
1031 1043
1044 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1045 # check if file is there
1046 result = runCmd("wic ls %s:1/ -n %s" % (prefix+"wic", sysroot))
1047 self.assertIn("test.wic-cp", result.output)
1048
1032 # check if we have result image and manifests symlinks 1049 # check if we have result image and manifests symlinks
1033 # pointing to existing files 1050 # pointing to existing files
1034 for suffix in ('wic', 'manifest'): 1051 for suffix in ('wic', 'manifest'):
@@ -1044,7 +1061,25 @@ class Wic2(WicTestCase):
1044 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\ 1061 config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "wic-image-minimal"\n'\
1045 'MACHINE_FEATURES:append = " efi"\n' 1062 'MACHINE_FEATURES:append = " efi"\n'
1046 self.append_config(config) 1063 self.append_config(config)
1064 image_recipe_append = """
1065do_image_wic[postfuncs] += "run_wic_cmd"
1066run_wic_cmd() {
1067 echo "test" >> ${WORKDIR}/test.wic-cp
1068 wic cp --vars "${STAGING_DIR}/${MACHINE}/imgdata/" -e "${IMAGE_BASENAME}" ${WORKDIR}/test.wic-cp ${IMGDEPLOYDIR}/${IMAGE_NAME}.wic:1/
1069 wic ls --vars "${STAGING_DIR}/${MACHINE}/imgdata/" -e "${IMAGE_BASENAME}" ${IMGDEPLOYDIR}/${IMAGE_NAME}.wic:1/
1070 wic rm --vars "${STAGING_DIR}/${MACHINE}/imgdata/" -e "${IMAGE_BASENAME}" ${IMGDEPLOYDIR}/${IMAGE_NAME}.wic:1/test.wic-cp
1071 wic cp --vars "${STAGING_DIR}/${MACHINE}/imgdata/" -e "${IMAGE_BASENAME}" ${WORKDIR}/test.wic-cp ${IMGDEPLOYDIR}/${IMAGE_NAME}.wic:1/
1072}
1073"""
1074 self.write_recipeinc('images', image_recipe_append)
1047 bitbake('wic-image-minimal') 1075 bitbake('wic-image-minimal')
1076
1077 sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'wic-tools')
1078 bb_vars = get_bb_vars(['DEPLOY_DIR_IMAGE', 'IMAGE_LINK_NAME'], "wic-image-minimal")
1079 image_path = os.path.join(bb_vars['DEPLOY_DIR_IMAGE'], bb_vars['IMAGE_LINK_NAME'])
1080 # check if file is there
1081 result = runCmd("wic ls %s:1/ -n %s" % (image_path+".wic", sysroot))
1082 self.assertIn("test.wic-cp", result.output)
1048 self.remove_config(config) 1083 self.remove_config(config)
1049 1084
1050 runqemu_params = get_bb_var('TEST_RUNQEMUPARAMS', 'wic-image-minimal') or "" 1085 runqemu_params = get_bb_var('TEST_RUNQEMUPARAMS', 'wic-image-minimal') or ""
@@ -1358,7 +1393,7 @@ class Wic2(WicTestCase):
1358 def test_biosplusefi_plugin(self): 1393 def test_biosplusefi_plugin(self):
1359 """Test biosplusefi plugin""" 1394 """Test biosplusefi plugin"""
1360 # Wic generation below may fail depending on the order of the unittests 1395 # Wic generation below may fail depending on the order of the unittests
1361 # This is because bootimg-pcbios (that bootimg-biosplusefi uses) generate its MBR inside STAGING_DATADIR directory 1396 # This is because bootimg_pcbios (that bootimg_biosplusefi uses) generate its MBR inside STAGING_DATADIR directory
1362 # which may or may not exists depending on what was built already 1397 # which may or may not exists depending on what was built already
1363 # If an image hasn't been built yet, directory ${STAGING_DATADIR}/syslinux won't exists and _get_bootimg_dir() 1398 # If an image hasn't been built yet, directory ${STAGING_DATADIR}/syslinux won't exists and _get_bootimg_dir()
1364 # will raise with "Couldn't find correct bootimg_dir" 1399 # will raise with "Couldn't find correct bootimg_dir"
@@ -1370,7 +1405,7 @@ class Wic2(WicTestCase):
1370 1405
1371 img = 'core-image-minimal' 1406 img = 'core-image-minimal'
1372 with NamedTemporaryFile("w", suffix=".wks") as wks: 1407 with NamedTemporaryFile("w", suffix=".wks") as wks:
1373 wks.writelines(['part /boot --active --source bootimg-biosplusefi --sourceparams="loader=grub-efi"\n', 1408 wks.writelines(['part /boot --active --source bootimg_biosplusefi --sourceparams="loader=grub-efi"\n',
1374 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\ 1409 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\
1375 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n']) 1410 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n'])
1376 wks.flush() 1411 wks.flush()
@@ -1390,7 +1425,7 @@ class Wic2(WicTestCase):
1390 1425
1391 img = 'core-image-minimal' 1426 img = 'core-image-minimal'
1392 with NamedTemporaryFile("w", suffix=".wks") as wks: 1427 with NamedTemporaryFile("w", suffix=".wks") as wks:
1393 wks.writelines(['part /boot --source bootimg-efi --sourceparams="loader=uefi-kernel"\n' 1428 wks.writelines(['part /boot --source bootimg_efi --sourceparams="loader=uefi-kernel"\n'
1394 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\ 1429 'part / --source rootfs --fstype=ext4 --align 1024 --use-uuid\n'\
1395 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n']) 1430 'bootloader --timeout=0 --append="console=ttyS0,115200n8"\n'])
1396 wks.flush() 1431 wks.flush()