summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/selftest
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oeqa/selftest')
-rw-r--r--meta/lib/oeqa/selftest/cases/archiver.py16
-rw-r--r--meta/lib/oeqa/selftest/cases/bblayers.py5
-rw-r--r--meta/lib/oeqa/selftest/cases/bbtests.py13
-rw-r--r--meta/lib/oeqa/selftest/cases/buildoptions.py6
-rw-r--r--meta/lib/oeqa/selftest/cases/cve_check.py186
-rw-r--r--meta/lib/oeqa/selftest/cases/devtool.py19
-rw-r--r--meta/lib/oeqa/selftest/cases/diffoscope/A/file.txt1
-rw-r--r--meta/lib/oeqa/selftest/cases/diffoscope/B/file.txt1
-rw-r--r--meta/lib/oeqa/selftest/cases/distrodata.py2
-rw-r--r--meta/lib/oeqa/selftest/cases/glibc.py8
-rw-r--r--meta/lib/oeqa/selftest/cases/gotoolchain.py6
-rw-r--r--meta/lib/oeqa/selftest/cases/imagefeatures.py2
-rw-r--r--meta/lib/oeqa/selftest/cases/oelib/utils.py3
-rw-r--r--meta/lib/oeqa/selftest/cases/oescripts.py3
-rw-r--r--meta/lib/oeqa/selftest/cases/prservice.py2
-rw-r--r--meta/lib/oeqa/selftest/cases/recipetool.py6
-rw-r--r--meta/lib/oeqa/selftest/cases/reproducible.py125
-rw-r--r--meta/lib/oeqa/selftest/cases/runcmd.py4
-rw-r--r--meta/lib/oeqa/selftest/cases/runqemu.py9
-rw-r--r--meta/lib/oeqa/selftest/cases/runtime_test.py43
-rw-r--r--meta/lib/oeqa/selftest/cases/sstatetests.py14
-rw-r--r--meta/lib/oeqa/selftest/cases/tinfoil.py28
-rw-r--r--meta/lib/oeqa/selftest/cases/wic.py18
23 files changed, 432 insertions, 88 deletions
diff --git a/meta/lib/oeqa/selftest/cases/archiver.py b/meta/lib/oeqa/selftest/cases/archiver.py
index bc5447d2a3..6a5c8ec71e 100644
--- a/meta/lib/oeqa/selftest/cases/archiver.py
+++ b/meta/lib/oeqa/selftest/cases/archiver.py
@@ -35,11 +35,11 @@ class Archiver(OESelftestTestCase):
35 src_path = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['TARGET_SYS']) 35 src_path = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['TARGET_SYS'])
36 36
37 # Check that include_recipe was included 37 # Check that include_recipe was included
38 included_present = len(glob.glob(src_path + '/%s-*' % include_recipe)) 38 included_present = len(glob.glob(src_path + '/%s-*/*' % include_recipe))
39 self.assertTrue(included_present, 'Recipe %s was not included.' % include_recipe) 39 self.assertTrue(included_present, 'Recipe %s was not included.' % include_recipe)
40 40
41 # Check that exclude_recipe was excluded 41 # Check that exclude_recipe was excluded
42 excluded_present = len(glob.glob(src_path + '/%s-*' % exclude_recipe)) 42 excluded_present = len(glob.glob(src_path + '/%s-*/*' % exclude_recipe))
43 self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % exclude_recipe) 43 self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % exclude_recipe)
44 44
45 def test_archiver_filters_by_type(self): 45 def test_archiver_filters_by_type(self):
@@ -67,11 +67,11 @@ class Archiver(OESelftestTestCase):
67 src_path_native = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['BUILD_SYS']) 67 src_path_native = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['BUILD_SYS'])
68 68
69 # Check that target_recipe was included 69 # Check that target_recipe was included
70 included_present = len(glob.glob(src_path_target + '/%s-*' % target_recipe)) 70 included_present = len(glob.glob(src_path_target + '/%s-*/*' % target_recipe))
71 self.assertTrue(included_present, 'Recipe %s was not included.' % target_recipe) 71 self.assertTrue(included_present, 'Recipe %s was not included.' % target_recipe)
72 72
73 # Check that native_recipe was excluded 73 # Check that native_recipe was excluded
74 excluded_present = len(glob.glob(src_path_native + '/%s-*' % native_recipe)) 74 excluded_present = len(glob.glob(src_path_native + '/%s-*/*' % native_recipe))
75 self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % native_recipe) 75 self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % native_recipe)
76 76
77 def test_archiver_filters_by_type_and_name(self): 77 def test_archiver_filters_by_type_and_name(self):
@@ -104,17 +104,17 @@ class Archiver(OESelftestTestCase):
104 src_path_native = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['BUILD_SYS']) 104 src_path_native = os.path.join(bb_vars['DEPLOY_DIR_SRC'], bb_vars['BUILD_SYS'])
105 105
106 # Check that target_recipe[0] and native_recipes[1] were included 106 # Check that target_recipe[0] and native_recipes[1] were included
107 included_present = len(glob.glob(src_path_target + '/%s-*' % target_recipes[0])) 107 included_present = len(glob.glob(src_path_target + '/%s-*/*' % target_recipes[0]))
108 self.assertTrue(included_present, 'Recipe %s was not included.' % target_recipes[0]) 108 self.assertTrue(included_present, 'Recipe %s was not included.' % target_recipes[0])
109 109
110 included_present = len(glob.glob(src_path_native + '/%s-*' % native_recipes[1])) 110 included_present = len(glob.glob(src_path_native + '/%s-*/*' % native_recipes[1]))
111 self.assertTrue(included_present, 'Recipe %s was not included.' % native_recipes[1]) 111 self.assertTrue(included_present, 'Recipe %s was not included.' % native_recipes[1])
112 112
113 # Check that native_recipes[0] and target_recipes[1] were excluded 113 # Check that native_recipes[0] and target_recipes[1] were excluded
114 excluded_present = len(glob.glob(src_path_native + '/%s-*' % native_recipes[0])) 114 excluded_present = len(glob.glob(src_path_native + '/%s-*/*' % native_recipes[0]))
115 self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % native_recipes[0]) 115 self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % native_recipes[0])
116 116
117 excluded_present = len(glob.glob(src_path_target + '/%s-*' % target_recipes[1])) 117 excluded_present = len(glob.glob(src_path_target + '/%s-*/*' % target_recipes[1]))
118 self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % target_recipes[1]) 118 self.assertFalse(excluded_present, 'Recipe %s was not excluded.' % target_recipes[1])
119 119
120 120
diff --git a/meta/lib/oeqa/selftest/cases/bblayers.py b/meta/lib/oeqa/selftest/cases/bblayers.py
index f131d9856c..7d74833f61 100644
--- a/meta/lib/oeqa/selftest/cases/bblayers.py
+++ b/meta/lib/oeqa/selftest/cases/bblayers.py
@@ -12,6 +12,11 @@ from oeqa.selftest.case import OESelftestTestCase
12 12
13class BitbakeLayers(OESelftestTestCase): 13class BitbakeLayers(OESelftestTestCase):
14 14
15 def test_bitbakelayers_layerindexshowdepends(self):
16 result = runCmd('bitbake-layers layerindex-show-depends meta-poky')
17 find_in_contents = re.search("openembedded-core", result.output)
18 self.assertTrue(find_in_contents, msg = "openembedded-core should have been listed at this step. bitbake-layers layerindex-show-depends meta-poky output: %s" % result.output)
19
15 def test_bitbakelayers_showcrossdepends(self): 20 def test_bitbakelayers_showcrossdepends(self):
16 result = runCmd('bitbake-layers show-cross-depends') 21 result = runCmd('bitbake-layers show-cross-depends')
17 self.assertIn('aspell', result.output) 22 self.assertIn('aspell', result.output)
diff --git a/meta/lib/oeqa/selftest/cases/bbtests.py b/meta/lib/oeqa/selftest/cases/bbtests.py
index dc423ec439..0b88316950 100644
--- a/meta/lib/oeqa/selftest/cases/bbtests.py
+++ b/meta/lib/oeqa/selftest/cases/bbtests.py
@@ -148,9 +148,6 @@ INHERIT_remove = \"report-error\"
148 self.delete_recipeinc('man-db') 148 self.delete_recipeinc('man-db')
149 self.assertEqual(result.status, 1, msg="Command succeded when it should have failed. bitbake output: %s" % result.output) 149 self.assertEqual(result.status, 1, msg="Command succeded when it should have failed. bitbake output: %s" % result.output)
150 self.assertIn('Fetcher failure: Unable to find file file://invalid anywhere. The paths that were searched were:', result.output) 150 self.assertIn('Fetcher failure: Unable to find file file://invalid anywhere. The paths that were searched were:', result.output)
151 line = self.getline(result, 'Fetcher failure for URL: \'file://invalid\'. Unable to fetch URL from any source.')
152 self.assertTrue(line and line.startswith("ERROR:"), msg = "\"invalid\" file \
153doesn't exist, yet fetcher didn't report any error. bitbake output: %s" % result.output)
154 151
155 def test_rename_downloaded_file(self): 152 def test_rename_downloaded_file(self):
156 # TODO unique dldir instead of using cleanall 153 # TODO unique dldir instead of using cleanall
@@ -160,7 +157,7 @@ SSTATE_DIR = \"${TOPDIR}/download-selftest\"
160""") 157""")
161 self.track_for_cleanup(os.path.join(self.builddir, "download-selftest")) 158 self.track_for_cleanup(os.path.join(self.builddir, "download-selftest"))
162 159
163 data = 'SRC_URI = "${GNU_MIRROR}/aspell/aspell-${PV}.tar.gz;downloadfilename=test-aspell.tar.gz"' 160 data = 'SRC_URI = "https://downloads.yoctoproject.org/mirror/sources/aspell-${PV}.tar.gz;downloadfilename=test-aspell.tar.gz"'
164 self.write_recipeinc('aspell', data) 161 self.write_recipeinc('aspell', data)
165 result = bitbake('-f -c fetch aspell', ignore_status=True) 162 result = bitbake('-f -c fetch aspell', ignore_status=True)
166 self.delete_recipeinc('aspell') 163 self.delete_recipeinc('aspell')
@@ -188,6 +185,10 @@ SSTATE_DIR = \"${TOPDIR}/download-selftest\"
188 self.assertTrue(find, "No version returned for searched recipe. bitbake output: %s" % result.output) 185 self.assertTrue(find, "No version returned for searched recipe. bitbake output: %s" % result.output)
189 186
190 def test_prefile(self): 187 def test_prefile(self):
188 # Test when the prefile does not exist
189 result = runCmd('bitbake -r conf/prefile.conf', ignore_status=True)
190 self.assertEqual(1, result.status, "bitbake didn't error and should have when a specified prefile didn't exist: %s" % result.output)
191 # Test when the prefile exists
191 preconf = os.path.join(self.builddir, 'conf/prefile.conf') 192 preconf = os.path.join(self.builddir, 'conf/prefile.conf')
192 self.track_for_cleanup(preconf) 193 self.track_for_cleanup(preconf)
193 ftools.write_file(preconf ,"TEST_PREFILE=\"prefile\"") 194 ftools.write_file(preconf ,"TEST_PREFILE=\"prefile\"")
@@ -198,6 +199,10 @@ SSTATE_DIR = \"${TOPDIR}/download-selftest\"
198 self.assertIn('localconf', result.output) 199 self.assertIn('localconf', result.output)
199 200
200 def test_postfile(self): 201 def test_postfile(self):
202 # Test when the postfile does not exist
203 result = runCmd('bitbake -R conf/postfile.conf', ignore_status=True)
204 self.assertEqual(1, result.status, "bitbake didn't error and should have when a specified postfile didn't exist: %s" % result.output)
205 # Test when the postfile exists
201 postconf = os.path.join(self.builddir, 'conf/postfile.conf') 206 postconf = os.path.join(self.builddir, 'conf/postfile.conf')
202 self.track_for_cleanup(postconf) 207 self.track_for_cleanup(postconf)
203 ftools.write_file(postconf , "TEST_POSTFILE=\"postfile\"") 208 ftools.write_file(postconf , "TEST_POSTFILE=\"postfile\"")
diff --git a/meta/lib/oeqa/selftest/cases/buildoptions.py b/meta/lib/oeqa/selftest/cases/buildoptions.py
index e91f0bd18f..b1b9ea7e55 100644
--- a/meta/lib/oeqa/selftest/cases/buildoptions.py
+++ b/meta/lib/oeqa/selftest/cases/buildoptions.py
@@ -57,15 +57,15 @@ class ImageOptionsTests(OESelftestTestCase):
57class DiskMonTest(OESelftestTestCase): 57class DiskMonTest(OESelftestTestCase):
58 58
59 def test_stoptask_behavior(self): 59 def test_stoptask_behavior(self):
60 self.write_config('BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},100000G,100K"') 60 self.write_config('BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"')
61 res = bitbake("delay -c delay", ignore_status = True) 61 res = bitbake("delay -c delay", ignore_status = True)
62 self.assertTrue('ERROR: No new tasks can be executed since the disk space monitor action is "STOPTASKS"!' in res.output, msg = "Tasks should have stopped. Disk monitor is set to STOPTASK: %s" % res.output) 62 self.assertTrue('ERROR: No new tasks can be executed since the disk space monitor action is "STOPTASKS"!' in res.output, msg = "Tasks should have stopped. Disk monitor is set to STOPTASK: %s" % res.output)
63 self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) 63 self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output))
64 self.write_config('BB_DISKMON_DIRS = "ABORT,${TMPDIR},100000G,100K"') 64 self.write_config('BB_DISKMON_DIRS = "ABORT,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"')
65 res = bitbake("delay -c delay", ignore_status = True) 65 res = bitbake("delay -c delay", ignore_status = True)
66 self.assertTrue('ERROR: Immediately abort since the disk space monitor action is "ABORT"!' in res.output, "Tasks should have been aborted immediatelly. Disk monitor is set to ABORT: %s" % res.output) 66 self.assertTrue('ERROR: Immediately abort since the disk space monitor action is "ABORT"!' in res.output, "Tasks should have been aborted immediatelly. Disk monitor is set to ABORT: %s" % res.output)
67 self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) 67 self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output))
68 self.write_config('BB_DISKMON_DIRS = "WARN,${TMPDIR},100000G,100K"') 68 self.write_config('BB_DISKMON_DIRS = "WARN,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"')
69 res = bitbake("delay -c delay") 69 res = bitbake("delay -c delay")
70 self.assertTrue('WARNING: The free space' in res.output, msg = "A warning should have been displayed for disk monitor is set to WARN: %s" %res.output) 70 self.assertTrue('WARNING: The free space' in res.output, msg = "A warning should have been displayed for disk monitor is set to WARN: %s" %res.output)
71 71
diff --git a/meta/lib/oeqa/selftest/cases/cve_check.py b/meta/lib/oeqa/selftest/cases/cve_check.py
index 3f343a2841..22ffeffd29 100644
--- a/meta/lib/oeqa/selftest/cases/cve_check.py
+++ b/meta/lib/oeqa/selftest/cases/cve_check.py
@@ -1,9 +1,13 @@
1from oe.cve_check import Version 1import json
2import os
2from oeqa.selftest.case import OESelftestTestCase 3from oeqa.selftest.case import OESelftestTestCase
4from oeqa.utils.commands import bitbake, get_bb_vars
3 5
4class CVECheck(OESelftestTestCase): 6class CVECheck(OESelftestTestCase):
5 7
6 def test_version_compare(self): 8 def test_version_compare(self):
9 from oe.cve_check import Version
10
7 result = Version("100") > Version("99") 11 result = Version("100") > Version("99")
8 self.assertTrue( result, msg="Failed to compare version '100' > '99'") 12 self.assertTrue( result, msg="Failed to compare version '100' > '99'")
9 result = Version("2.3.1") > Version("2.2.3") 13 result = Version("2.3.1") > Version("2.2.3")
@@ -34,3 +38,183 @@ class CVECheck(OESelftestTestCase):
34 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' < '1.0r'") 38 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' < '1.0r'")
35 result = Version("1.0b","alphabetical") > Version("1.0","alphabetical") 39 result = Version("1.0b","alphabetical") > Version("1.0","alphabetical")
36 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' > '1.0'") 40 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' > '1.0'")
41
42 # consider the trailing "p" and "patch" as patched released when comparing
43 result = Version("1.0","patch") < Version("1.0p1","patch")
44 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0' < '1.0p1'")
45 result = Version("1.0p2","patch") > Version("1.0p1","patch")
46 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0p2' > '1.0p1'")
47 result = Version("1.0_patch2","patch") < Version("1.0_patch3","patch")
48 self.assertTrue( result ,msg="Failed to compare version with suffix '1.0_patch2' < '1.0_patch3'")
49
50
51 def test_convert_cve_version(self):
52 from oe.cve_check import convert_cve_version
53
54 # Default format
55 self.assertEqual(convert_cve_version("8.3"), "8.3")
56 self.assertEqual(convert_cve_version(""), "")
57
58 # OpenSSL format version
59 self.assertEqual(convert_cve_version("1.1.1t"), "1.1.1t")
60
61 # OpenSSH format
62 self.assertEqual(convert_cve_version("8.3_p1"), "8.3p1")
63 self.assertEqual(convert_cve_version("8.3_p22"), "8.3p22")
64
65 # Linux kernel format
66 self.assertEqual(convert_cve_version("6.2_rc8"), "6.2-rc8")
67 self.assertEqual(convert_cve_version("6.2_rc31"), "6.2-rc31")
68
69
70 def test_recipe_report_json(self):
71 config = """
72INHERIT += "cve-check"
73CVE_CHECK_FORMAT_JSON = "1"
74"""
75 self.write_config(config)
76
77 vars = get_bb_vars(["CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
78 summary_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
79 recipe_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], "m4-native_cve.json")
80
81 try:
82 os.remove(summary_json)
83 os.remove(recipe_json)
84 except FileNotFoundError:
85 pass
86
87 bitbake("m4-native -c cve_check")
88
89 def check_m4_json(filename):
90 with open(filename) as f:
91 report = json.load(f)
92 self.assertEqual(report["version"], "1")
93 self.assertEqual(len(report["package"]), 1)
94 package = report["package"][0]
95 self.assertEqual(package["name"], "m4-native")
96 found_cves = { issue["id"]: issue["status"] for issue in package["issue"]}
97 self.assertIn("CVE-2008-1687", found_cves)
98 self.assertEqual(found_cves["CVE-2008-1687"], "Patched")
99
100 self.assertExists(summary_json)
101 check_m4_json(summary_json)
102 self.assertExists(recipe_json)
103 check_m4_json(recipe_json)
104
105
106 def test_image_json(self):
107 config = """
108INHERIT += "cve-check"
109CVE_CHECK_FORMAT_JSON = "1"
110"""
111 self.write_config(config)
112
113 vars = get_bb_vars(["CVE_CHECK_DIR", "CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
114 report_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
115 print(report_json)
116 try:
117 os.remove(report_json)
118 except FileNotFoundError:
119 pass
120
121 bitbake("core-image-minimal-initramfs")
122 self.assertExists(report_json)
123
124 # Check that the summary report lists at least one package
125 with open(report_json) as f:
126 report = json.load(f)
127 self.assertEqual(report["version"], "1")
128 self.assertGreater(len(report["package"]), 1)
129
130 # Check that a random recipe wrote a recipe report to deploy/cve/
131 recipename = report["package"][0]["name"]
132 recipe_report = os.path.join(vars["CVE_CHECK_DIR"], recipename + "_cve.json")
133 self.assertExists(recipe_report)
134 with open(recipe_report) as f:
135 report = json.load(f)
136 self.assertEqual(report["version"], "1")
137 self.assertEqual(len(report["package"]), 1)
138 self.assertEqual(report["package"][0]["name"], recipename)
139
140
141 def test_recipe_report_json_unpatched(self):
142 config = """
143INHERIT += "cve-check"
144CVE_CHECK_FORMAT_JSON = "1"
145CVE_CHECK_REPORT_PATCHED = "0"
146"""
147 self.write_config(config)
148
149 vars = get_bb_vars(["CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
150 summary_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
151 recipe_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], "m4-native_cve.json")
152
153 try:
154 os.remove(summary_json)
155 os.remove(recipe_json)
156 except FileNotFoundError:
157 pass
158
159 bitbake("m4-native -c cve_check")
160
161 def check_m4_json(filename):
162 with open(filename) as f:
163 report = json.load(f)
164 self.assertEqual(report["version"], "1")
165 self.assertEqual(len(report["package"]), 1)
166 package = report["package"][0]
167 self.assertEqual(package["name"], "m4-native")
168 #m4 had only Patched CVEs, so the issues array will be empty
169 self.assertEqual(package["issue"], [])
170
171 self.assertExists(summary_json)
172 check_m4_json(summary_json)
173 self.assertExists(recipe_json)
174 check_m4_json(recipe_json)
175
176
177 def test_recipe_report_json_ignored(self):
178 config = """
179INHERIT += "cve-check"
180CVE_CHECK_FORMAT_JSON = "1"
181CVE_CHECK_REPORT_PATCHED = "1"
182"""
183 self.write_config(config)
184
185 vars = get_bb_vars(["CVE_CHECK_SUMMARY_DIR", "CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
186 summary_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], vars["CVE_CHECK_SUMMARY_FILE_NAME_JSON"])
187 recipe_json = os.path.join(vars["CVE_CHECK_SUMMARY_DIR"], "logrotate_cve.json")
188
189 try:
190 os.remove(summary_json)
191 os.remove(recipe_json)
192 except FileNotFoundError:
193 pass
194
195 bitbake("logrotate -c cve_check")
196
197 def check_m4_json(filename):
198 with open(filename) as f:
199 report = json.load(f)
200 self.assertEqual(report["version"], "1")
201 self.assertEqual(len(report["package"]), 1)
202 package = report["package"][0]
203 self.assertEqual(package["name"], "logrotate")
204 found_cves = { issue["id"]: issue["status"] for issue in package["issue"]}
205 # m4 CVE should not be in logrotate
206 self.assertNotIn("CVE-2008-1687", found_cves)
207 # logrotate has both Patched and Ignored CVEs
208 self.assertIn("CVE-2011-1098", found_cves)
209 self.assertEqual(found_cves["CVE-2011-1098"], "Patched")
210 self.assertIn("CVE-2011-1548", found_cves)
211 self.assertEqual(found_cves["CVE-2011-1548"], "Ignored")
212 self.assertIn("CVE-2011-1549", found_cves)
213 self.assertEqual(found_cves["CVE-2011-1549"], "Ignored")
214 self.assertIn("CVE-2011-1550", found_cves)
215 self.assertEqual(found_cves["CVE-2011-1550"], "Ignored")
216
217 self.assertExists(summary_json)
218 check_m4_json(summary_json)
219 self.assertExists(recipe_json)
220 check_m4_json(recipe_json)
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 0985434238..9efe342a0d 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -8,6 +8,7 @@ import shutil
8import tempfile 8import tempfile
9import glob 9import glob
10import fnmatch 10import fnmatch
11import unittest
11 12
12import oeqa.utils.ftools as ftools 13import oeqa.utils.ftools as ftools
13from oeqa.selftest.case import OESelftestTestCase 14from oeqa.selftest.case import OESelftestTestCase
@@ -38,6 +39,13 @@ def setUpModule():
38 canonical_layerpath = os.path.realpath(canonical_layerpath) + '/' 39 canonical_layerpath = os.path.realpath(canonical_layerpath) + '/'
39 edited_layers.append(layerpath) 40 edited_layers.append(layerpath)
40 oldmetapath = os.path.realpath(layerpath) 41 oldmetapath = os.path.realpath(layerpath)
42
43 # when downloading poky from tar.gz some tests will be skipped (BUG 12389)
44 try:
45 runCmd('git rev-parse --is-inside-work-tree', cwd=canonical_layerpath)
46 except:
47 raise unittest.SkipTest("devtool tests require folder to be a git repo")
48
41 result = runCmd('git rev-parse --show-toplevel', cwd=canonical_layerpath) 49 result = runCmd('git rev-parse --show-toplevel', cwd=canonical_layerpath)
42 oldreporoot = result.output.rstrip() 50 oldreporoot = result.output.rstrip()
43 newmetapath = os.path.join(corecopydir, os.path.relpath(oldmetapath, oldreporoot)) 51 newmetapath = os.path.join(corecopydir, os.path.relpath(oldmetapath, oldreporoot))
@@ -340,7 +348,7 @@ class DevtoolAddTests(DevtoolBase):
340 checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263' 348 checkvars['LIC_FILES_CHKSUM'] = 'file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263'
341 checkvars['S'] = '${WORKDIR}/git' 349 checkvars['S'] = '${WORKDIR}/git'
342 checkvars['PV'] = '0.1+git${SRCPV}' 350 checkvars['PV'] = '0.1+git${SRCPV}'
343 checkvars['SRC_URI'] = 'git://git.yoctoproject.org/git/dbus-wait;protocol=https' 351 checkvars['SRC_URI'] = 'git://git.yoctoproject.org/git/dbus-wait;protocol=https;branch=master'
344 checkvars['SRCREV'] = srcrev 352 checkvars['SRCREV'] = srcrev
345 checkvars['DEPENDS'] = set(['dbus']) 353 checkvars['DEPENDS'] = set(['dbus'])
346 self._test_recipe_contents(recipefile, checkvars, []) 354 self._test_recipe_contents(recipefile, checkvars, [])
@@ -442,6 +450,7 @@ class DevtoolAddTests(DevtoolBase):
442 tempdir = tempfile.mkdtemp(prefix='devtoolqa') 450 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
443 self.track_for_cleanup(tempdir) 451 self.track_for_cleanup(tempdir)
444 url = 'gitsm://git.yoctoproject.org/mraa' 452 url = 'gitsm://git.yoctoproject.org/mraa'
453 url_branch = '%s;branch=master' % url
445 checkrev = 'ae127b19a50aa54255e4330ccfdd9a5d058e581d' 454 checkrev = 'ae127b19a50aa54255e4330ccfdd9a5d058e581d'
446 testrecipe = 'mraa' 455 testrecipe = 'mraa'
447 srcdir = os.path.join(tempdir, testrecipe) 456 srcdir = os.path.join(tempdir, testrecipe)
@@ -462,7 +471,7 @@ class DevtoolAddTests(DevtoolBase):
462 checkvars = {} 471 checkvars = {}
463 checkvars['S'] = '${WORKDIR}/git' 472 checkvars['S'] = '${WORKDIR}/git'
464 checkvars['PV'] = '1.0+git${SRCPV}' 473 checkvars['PV'] = '1.0+git${SRCPV}'
465 checkvars['SRC_URI'] = url 474 checkvars['SRC_URI'] = url_branch
466 checkvars['SRCREV'] = '${AUTOREV}' 475 checkvars['SRCREV'] = '${AUTOREV}'
467 self._test_recipe_contents(recipefile, checkvars, []) 476 self._test_recipe_contents(recipefile, checkvars, [])
468 # Try with revision and version specified 477 # Try with revision and version specified
@@ -481,7 +490,7 @@ class DevtoolAddTests(DevtoolBase):
481 checkvars = {} 490 checkvars = {}
482 checkvars['S'] = '${WORKDIR}/git' 491 checkvars['S'] = '${WORKDIR}/git'
483 checkvars['PV'] = '1.5+git${SRCPV}' 492 checkvars['PV'] = '1.5+git${SRCPV}'
484 checkvars['SRC_URI'] = url 493 checkvars['SRC_URI'] = url_branch
485 checkvars['SRCREV'] = checkrev 494 checkvars['SRCREV'] = checkrev
486 self._test_recipe_contents(recipefile, checkvars, []) 495 self._test_recipe_contents(recipefile, checkvars, [])
487 496
@@ -880,7 +889,7 @@ class DevtoolUpdateTests(DevtoolBase):
880 self._check_repo_status(os.path.dirname(recipefile), expected_status) 889 self._check_repo_status(os.path.dirname(recipefile), expected_status)
881 890
882 result = runCmd('git diff %s' % os.path.basename(recipefile), cwd=os.path.dirname(recipefile)) 891 result = runCmd('git diff %s' % os.path.basename(recipefile), cwd=os.path.dirname(recipefile))
883 addlines = ['SRCREV = ".*"', 'SRC_URI = "git://git.infradead.org/mtd-utils.git"'] 892 addlines = ['SRCREV = ".*"', 'SRC_URI = "git://git.infradead.org/mtd-utils.git;branch=master"']
884 srcurilines = src_uri.split() 893 srcurilines = src_uri.split()
885 srcurilines[0] = 'SRC_URI = "' + srcurilines[0] 894 srcurilines[0] = 'SRC_URI = "' + srcurilines[0]
886 srcurilines.append('"') 895 srcurilines.append('"')
@@ -1322,7 +1331,7 @@ class DevtoolExtractTests(DevtoolBase):
1322 # Now really test deploy-target 1331 # Now really test deploy-target
1323 result = runCmd('devtool deploy-target -c %s root@%s' % (testrecipe, qemu.ip)) 1332 result = runCmd('devtool deploy-target -c %s root@%s' % (testrecipe, qemu.ip))
1324 # Run a test command to see if it was installed properly 1333 # Run a test command to see if it was installed properly
1325 sshargs = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' 1334 sshargs = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o HostKeyAlgorithms=+ssh-rsa'
1326 result = runCmd('ssh %s root@%s %s' % (sshargs, qemu.ip, testcommand)) 1335 result = runCmd('ssh %s root@%s %s' % (sshargs, qemu.ip, testcommand))
1327 # Check if it deployed all of the files with the right ownership/perms 1336 # Check if it deployed all of the files with the right ownership/perms
1328 # First look on the host - need to do this under pseudo to get the correct ownership/perms 1337 # First look on the host - need to do this under pseudo to get the correct ownership/perms
diff --git a/meta/lib/oeqa/selftest/cases/diffoscope/A/file.txt b/meta/lib/oeqa/selftest/cases/diffoscope/A/file.txt
new file mode 100644
index 0000000000..f70f10e4db
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/diffoscope/A/file.txt
@@ -0,0 +1 @@
A
diff --git a/meta/lib/oeqa/selftest/cases/diffoscope/B/file.txt b/meta/lib/oeqa/selftest/cases/diffoscope/B/file.txt
new file mode 100644
index 0000000000..223b7836fb
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/diffoscope/B/file.txt
@@ -0,0 +1 @@
B
diff --git a/meta/lib/oeqa/selftest/cases/distrodata.py b/meta/lib/oeqa/selftest/cases/distrodata.py
index e1cfc3b621..8e5e24db3d 100644
--- a/meta/lib/oeqa/selftest/cases/distrodata.py
+++ b/meta/lib/oeqa/selftest/cases/distrodata.py
@@ -63,7 +63,7 @@ but their recipes claim otherwise by setting UPSTREAM_VERSION_UNKNOWN. Please re
63 return True 63 return True
64 return False 64 return False
65 65
66 feature = 'require conf/distro/include/maintainers.inc\nLICENSE_FLAGS_WHITELIST += " commercial"\nPARSE_ALL_RECIPES = "1"\n' 66 feature = 'require conf/distro/include/maintainers.inc\nLICENSE_FLAGS_WHITELIST += " commercial"\nPARSE_ALL_RECIPES = "1"\nPACKAGE_CLASSES = "package_ipk package_deb package_rpm"\n'
67 self.write_config(feature) 67 self.write_config(feature)
68 68
69 with bb.tinfoil.Tinfoil() as tinfoil: 69 with bb.tinfoil.Tinfoil() as tinfoil:
diff --git a/meta/lib/oeqa/selftest/cases/glibc.py b/meta/lib/oeqa/selftest/cases/glibc.py
index c687f6ef93..c1f6e4c1fb 100644
--- a/meta/lib/oeqa/selftest/cases/glibc.py
+++ b/meta/lib/oeqa/selftest/cases/glibc.py
@@ -33,7 +33,7 @@ class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase):
33 33
34 ptestsuite = "glibc-user" if ssh is None else "glibc" 34 ptestsuite = "glibc-user" if ssh is None else "glibc"
35 self.ptest_section(ptestsuite) 35 self.ptest_section(ptestsuite)
36 with open(os.path.join(builddir, "tests.sum"), "r") as f: 36 with open(os.path.join(builddir, "tests.sum"), "r", errors='replace') as f:
37 for test, result in parse_values(f): 37 for test, result in parse_values(f):
38 self.ptest_result(ptestsuite, test, result) 38 self.ptest_result(ptestsuite, test, result)
39 39
@@ -41,7 +41,7 @@ class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase):
41 with contextlib.ExitStack() as s: 41 with contextlib.ExitStack() as s:
42 # use the base work dir, as the nfs mount, since the recipe directory may not exist 42 # use the base work dir, as the nfs mount, since the recipe directory may not exist
43 tmpdir = get_bb_var("BASE_WORKDIR") 43 tmpdir = get_bb_var("BASE_WORKDIR")
44 nfsport, mountport = s.enter_context(unfs_server(tmpdir)) 44 nfsport, mountport = s.enter_context(unfs_server(tmpdir, udp = False))
45 45
46 # build core-image-minimal with required packages 46 # build core-image-minimal with required packages
47 default_installed_packages = [ 47 default_installed_packages = [
@@ -61,7 +61,7 @@ class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase):
61 bitbake("core-image-minimal") 61 bitbake("core-image-minimal")
62 62
63 # start runqemu 63 # start runqemu
64 qemu = s.enter_context(runqemu("core-image-minimal", runqemuparams = "nographic")) 64 qemu = s.enter_context(runqemu("core-image-minimal", runqemuparams = "nographic", qemuparams = "-m 1024"))
65 65
66 # validate that SSH is working 66 # validate that SSH is working
67 status, _ = qemu.run("uname") 67 status, _ = qemu.run("uname")
@@ -70,7 +70,7 @@ class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase):
70 # setup nfs mount 70 # setup nfs mount
71 if qemu.run("mkdir -p \"{0}\"".format(tmpdir))[0] != 0: 71 if qemu.run("mkdir -p \"{0}\"".format(tmpdir))[0] != 0:
72 raise Exception("Failed to setup NFS mount directory on target") 72 raise Exception("Failed to setup NFS mount directory on target")
73 mountcmd = "mount -o noac,nfsvers=3,port={0},udp,mountport={1} \"{2}:{3}\" \"{3}\"".format(nfsport, mountport, qemu.server_ip, tmpdir) 73 mountcmd = "mount -o noac,nfsvers=3,port={0},mountport={1} \"{2}:{3}\" \"{3}\"".format(nfsport, mountport, qemu.server_ip, tmpdir)
74 status, output = qemu.run(mountcmd) 74 status, output = qemu.run(mountcmd)
75 if status != 0: 75 if status != 0:
76 raise Exception("Failed to setup NFS mount on target ({})".format(repr(output))) 76 raise Exception("Failed to setup NFS mount on target ({})".format(repr(output)))
diff --git a/meta/lib/oeqa/selftest/cases/gotoolchain.py b/meta/lib/oeqa/selftest/cases/gotoolchain.py
index 3119520f0d..59f80aad28 100644
--- a/meta/lib/oeqa/selftest/cases/gotoolchain.py
+++ b/meta/lib/oeqa/selftest/cases/gotoolchain.py
@@ -43,6 +43,12 @@ class oeGoToolchainSelfTest(OESelftestTestCase):
43 43
44 @classmethod 44 @classmethod
45 def tearDownClass(cls): 45 def tearDownClass(cls):
46 # Go creates file which are readonly
47 for dirpath, dirnames, filenames in os.walk(cls.tmpdir_SDKQA):
48 for filename in filenames + dirnames:
49 f = os.path.join(dirpath, filename)
50 if not os.path.islink(f):
51 os.chmod(f, 0o775)
46 shutil.rmtree(cls.tmpdir_SDKQA, ignore_errors=True) 52 shutil.rmtree(cls.tmpdir_SDKQA, ignore_errors=True)
47 super(oeGoToolchainSelfTest, cls).tearDownClass() 53 super(oeGoToolchainSelfTest, cls).tearDownClass()
48 54
diff --git a/meta/lib/oeqa/selftest/cases/imagefeatures.py b/meta/lib/oeqa/selftest/cases/imagefeatures.py
index 2b9c4998f7..535d80cb86 100644
--- a/meta/lib/oeqa/selftest/cases/imagefeatures.py
+++ b/meta/lib/oeqa/selftest/cases/imagefeatures.py
@@ -240,7 +240,7 @@ USERADD_GID_TABLES += "files/static-group"
240 def test_no_busybox_base_utils(self): 240 def test_no_busybox_base_utils(self):
241 config = """ 241 config = """
242# Enable x11 242# Enable x11
243DISTRO_FEATURES_append += "x11" 243DISTRO_FEATURES_append = " x11"
244 244
245# Switch to systemd 245# Switch to systemd
246DISTRO_FEATURES += "systemd" 246DISTRO_FEATURES += "systemd"
diff --git a/meta/lib/oeqa/selftest/cases/oelib/utils.py b/meta/lib/oeqa/selftest/cases/oelib/utils.py
index a7214beb4c..bbf67bf9c9 100644
--- a/meta/lib/oeqa/selftest/cases/oelib/utils.py
+++ b/meta/lib/oeqa/selftest/cases/oelib/utils.py
@@ -64,7 +64,7 @@ class TestMultiprocessLaunch(TestCase):
64 import bb 64 import bb
65 65
66 def testfunction(item, d): 66 def testfunction(item, d):
67 if item == "2" or item == "1": 67 if item == "2":
68 raise KeyError("Invalid number %s" % item) 68 raise KeyError("Invalid number %s" % item)
69 return "Found %s" % item 69 return "Found %s" % item
70 70
@@ -99,5 +99,4 @@ class TestMultiprocessLaunch(TestCase):
99 # Assert the function prints exceptions 99 # Assert the function prints exceptions
100 with captured_output() as (out, err): 100 with captured_output() as (out, err):
101 self.assertRaises(bb.BBHandledException, multiprocess_launch, testfunction, ["1", "2", "3", "4", "5", "6"], d, extraargs=(d,)) 101 self.assertRaises(bb.BBHandledException, multiprocess_launch, testfunction, ["1", "2", "3", "4", "5", "6"], d, extraargs=(d,))
102 self.assertIn("KeyError: 'Invalid number 1'", out.getvalue())
103 self.assertIn("KeyError: 'Invalid number 2'", out.getvalue()) 102 self.assertIn("KeyError: 'Invalid number 2'", out.getvalue())
diff --git a/meta/lib/oeqa/selftest/cases/oescripts.py b/meta/lib/oeqa/selftest/cases/oescripts.py
index 726daff7c6..fb99be447e 100644
--- a/meta/lib/oeqa/selftest/cases/oescripts.py
+++ b/meta/lib/oeqa/selftest/cases/oescripts.py
@@ -133,7 +133,8 @@ class OEListPackageconfigTests(OEScriptTests):
133 def check_endlines(self, results, expected_endlines): 133 def check_endlines(self, results, expected_endlines):
134 for line in results.output.splitlines(): 134 for line in results.output.splitlines():
135 for el in expected_endlines: 135 for el in expected_endlines:
136 if line.split() == el.split(): 136 if line and line.split()[0] == el.split()[0] and \
137 ' '.join(sorted(el.split())) in ' '.join(sorted(line.split())):
137 expected_endlines.remove(el) 138 expected_endlines.remove(el)
138 break 139 break
139 140
diff --git a/meta/lib/oeqa/selftest/cases/prservice.py b/meta/lib/oeqa/selftest/cases/prservice.py
index 578b2b4dd9..fdc1e40058 100644
--- a/meta/lib/oeqa/selftest/cases/prservice.py
+++ b/meta/lib/oeqa/selftest/cases/prservice.py
@@ -75,7 +75,7 @@ class BitbakePrTests(OESelftestTestCase):
75 exported_db_path = os.path.join(self.builddir, 'export.inc') 75 exported_db_path = os.path.join(self.builddir, 'export.inc')
76 export_result = runCmd("bitbake-prserv-tool export %s" % exported_db_path, ignore_status=True) 76 export_result = runCmd("bitbake-prserv-tool export %s" % exported_db_path, ignore_status=True)
77 self.assertEqual(export_result.status, 0, msg="PR Service database export failed: %s" % export_result.output) 77 self.assertEqual(export_result.status, 0, msg="PR Service database export failed: %s" % export_result.output)
78 self.assertTrue(os.path.exists(exported_db_path)) 78 self.assertTrue(os.path.exists(exported_db_path), msg="%s didn't exist, tool output %s" % (exported_db_path, export_result.output))
79 79
80 if replace_current_db: 80 if replace_current_db:
81 current_db_path = os.path.join(get_bb_var('PERSISTENT_DIR'), 'prserv.sqlite3') 81 current_db_path = os.path.join(get_bb_var('PERSISTENT_DIR'), 'prserv.sqlite3')
diff --git a/meta/lib/oeqa/selftest/cases/recipetool.py b/meta/lib/oeqa/selftest/cases/recipetool.py
index c2ade2543a..e8aeea3023 100644
--- a/meta/lib/oeqa/selftest/cases/recipetool.py
+++ b/meta/lib/oeqa/selftest/cases/recipetool.py
@@ -370,7 +370,7 @@ class RecipetoolTests(RecipetoolBase):
370 tempsrc = os.path.join(self.tempdir, 'srctree') 370 tempsrc = os.path.join(self.tempdir, 'srctree')
371 os.makedirs(tempsrc) 371 os.makedirs(tempsrc)
372 recipefile = os.path.join(self.tempdir, 'libmatchbox.bb') 372 recipefile = os.path.join(self.tempdir, 'libmatchbox.bb')
373 srcuri = 'git://git.yoctoproject.org/libmatchbox' 373 srcuri = 'git://git.yoctoproject.org/libmatchbox;branch=master'
374 result = runCmd(['recipetool', 'create', '-o', recipefile, srcuri + ";rev=9f7cf8895ae2d39c465c04cc78e918c157420269", '-x', tempsrc]) 374 result = runCmd(['recipetool', 'create', '-o', recipefile, srcuri + ";rev=9f7cf8895ae2d39c465c04cc78e918c157420269", '-x', tempsrc])
375 self.assertTrue(os.path.isfile(recipefile), 'recipetool did not create recipe file; output:\n%s' % result.output) 375 self.assertTrue(os.path.isfile(recipefile), 'recipetool did not create recipe file; output:\n%s' % result.output)
376 checkvars = {} 376 checkvars = {}
@@ -456,7 +456,7 @@ class RecipetoolTests(RecipetoolBase):
456 self.assertTrue(os.path.isfile(recipefile)) 456 self.assertTrue(os.path.isfile(recipefile))
457 checkvars = {} 457 checkvars = {}
458 checkvars['LICENSE'] = set(['Apache-2.0']) 458 checkvars['LICENSE'] = set(['Apache-2.0'])
459 checkvars['SRC_URI'] = 'git://github.com/mesonbuild/meson;protocol=https' 459 checkvars['SRC_URI'] = 'git://github.com/mesonbuild/meson;protocol=https;branch=master'
460 inherits = ['setuptools3'] 460 inherits = ['setuptools3']
461 self._test_recipe_contents(recipefile, checkvars, inherits) 461 self._test_recipe_contents(recipefile, checkvars, inherits)
462 462
@@ -523,7 +523,7 @@ class RecipetoolTests(RecipetoolBase):
523 self.assertTrue(os.path.isfile(recipefile)) 523 self.assertTrue(os.path.isfile(recipefile))
524 checkvars = {} 524 checkvars = {}
525 checkvars['LICENSE'] = set(['GPLv2']) 525 checkvars['LICENSE'] = set(['GPLv2'])
526 checkvars['SRC_URI'] = 'git://git.yoctoproject.org/git/matchbox-terminal;protocol=http' 526 checkvars['SRC_URI'] = 'git://git.yoctoproject.org/git/matchbox-terminal;protocol=http;branch=master'
527 inherits = ['pkgconfig', 'autotools'] 527 inherits = ['pkgconfig', 'autotools']
528 self._test_recipe_contents(recipefile, checkvars, inherits) 528 self._test_recipe_contents(recipefile, checkvars, inherits)
529 529
diff --git a/meta/lib/oeqa/selftest/cases/reproducible.py b/meta/lib/oeqa/selftest/cases/reproducible.py
index d4800022df..be4cdcc429 100644
--- a/meta/lib/oeqa/selftest/cases/reproducible.py
+++ b/meta/lib/oeqa/selftest/cases/reproducible.py
@@ -17,6 +17,57 @@ import stat
17import os 17import os
18import datetime 18import datetime
19 19
20# For sample packages, see:
21# https://autobuilder.yocto.io/pub/repro-fail/oe-reproducible-20201127-0t7wr_oo/
22# https://autobuilder.yocto.io/pub/repro-fail/oe-reproducible-20201127-4s9ejwyp/
23# https://autobuilder.yocto.io/pub/repro-fail/oe-reproducible-20201127-haiwdlbr/
24# https://autobuilder.yocto.io/pub/repro-fail/oe-reproducible-20201127-hwds3mcl/
25# https://autobuilder.yocto.io/pub/repro-fail/oe-reproducible-20201203-sua0pzvc/
26# (both packages/ and packages-excluded/)
27exclude_packages = [
28 'acpica-src',
29 'babeltrace2-ptest',
30 'bind',
31 'bootchart2-doc',
32 'epiphany',
33 'gcr',
34 'glide',
35 'go-dep',
36 'go-helloworld',
37 'go-runtime',
38 'go_',
39 'gstreamer1.0-python',
40 'hwlatdetect',
41 'kernel-devsrc',
42 'libcap-ng',
43 'libjson',
44 'libproxy',
45 'lttng-tools-dbg',
46 'lttng-tools-ptest',
47 'ltp',
48 'ovmf-shell-efi',
49 'parted-ptest',
50 'perf',
51 'piglit',
52 'pybootchartgui',
53 'qemu',
54 'quilt-ptest',
55 'rsync',
56 'ruby',
57 'stress-ng',
58 'systemd-bootchart',
59 'systemtap',
60 'valgrind-ptest',
61 'webkitgtk',
62 ]
63
64def is_excluded(package):
65 package_name = os.path.basename(package)
66 for i in exclude_packages:
67 if package_name.startswith(i):
68 return i
69 return None
70
20MISSING = 'MISSING' 71MISSING = 'MISSING'
21DIFFERENT = 'DIFFERENT' 72DIFFERENT = 'DIFFERENT'
22SAME = 'SAME' 73SAME = 'SAME'
@@ -39,14 +90,21 @@ class PackageCompareResults(object):
39 self.total = [] 90 self.total = []
40 self.missing = [] 91 self.missing = []
41 self.different = [] 92 self.different = []
93 self.different_excluded = []
42 self.same = [] 94 self.same = []
95 self.active_exclusions = set()
43 96
44 def add_result(self, r): 97 def add_result(self, r):
45 self.total.append(r) 98 self.total.append(r)
46 if r.status == MISSING: 99 if r.status == MISSING:
47 self.missing.append(r) 100 self.missing.append(r)
48 elif r.status == DIFFERENT: 101 elif r.status == DIFFERENT:
49 self.different.append(r) 102 exclusion = is_excluded(r.reference)
103 if exclusion:
104 self.different_excluded.append(r)
105 self.active_exclusions.add(exclusion)
106 else:
107 self.different.append(r)
50 else: 108 else:
51 self.same.append(r) 109 self.same.append(r)
52 110
@@ -54,10 +112,14 @@ class PackageCompareResults(object):
54 self.total.sort() 112 self.total.sort()
55 self.missing.sort() 113 self.missing.sort()
56 self.different.sort() 114 self.different.sort()
115 self.different_excluded.sort()
57 self.same.sort() 116 self.same.sort()
58 117
59 def __str__(self): 118 def __str__(self):
60 return 'same=%i different=%i missing=%i total=%i' % (len(self.same), len(self.different), len(self.missing), len(self.total)) 119 return 'same=%i different=%i different_excluded=%i missing=%i total=%i\nunused_exclusions=%s' % (len(self.same), len(self.different), len(self.different_excluded), len(self.missing), len(self.total), self.unused_exclusions())
120
121 def unused_exclusions(self):
122 return sorted(set(exclude_packages) - self.active_exclusions)
61 123
62def compare_file(reference, test, diffutils_sysroot): 124def compare_file(reference, test, diffutils_sysroot):
63 result = CompareResult() 125 result = CompareResult()
@@ -68,7 +130,7 @@ def compare_file(reference, test, diffutils_sysroot):
68 result.status = MISSING 130 result.status = MISSING
69 return result 131 return result
70 132
71 r = runCmd(['cmp', '--quiet', reference, test], native_sysroot=diffutils_sysroot, ignore_status=True) 133 r = runCmd(['cmp', '--quiet', reference, test], native_sysroot=diffutils_sysroot, ignore_status=True, sync=False)
72 134
73 if r.status: 135 if r.status:
74 result.status = DIFFERENT 136 result.status = DIFFERENT
@@ -77,9 +139,41 @@ def compare_file(reference, test, diffutils_sysroot):
77 result.status = SAME 139 result.status = SAME
78 return result 140 return result
79 141
142def run_diffoscope(a_dir, b_dir, html_dir, **kwargs):
143 return runCmd(['diffoscope', '--no-default-limits', '--exclude-directory-metadata', 'yes', '--html-dir', html_dir, a_dir, b_dir],
144 **kwargs)
145
146class DiffoscopeTests(OESelftestTestCase):
147 diffoscope_test_files = os.path.join(os.path.dirname(os.path.abspath(__file__)), "diffoscope")
148
149 def test_diffoscope(self):
150 bitbake("diffoscope-native -c addto_recipe_sysroot")
151 diffoscope_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", "diffoscope-native")
152
153 # Check that diffoscope doesn't return an error when the files compare
154 # the same (a general check that diffoscope is working)
155 with tempfile.TemporaryDirectory() as tmpdir:
156 run_diffoscope('A', 'A', tmpdir,
157 native_sysroot=diffoscope_sysroot, cwd=self.diffoscope_test_files)
158
159 # Check that diffoscope generates an index.html file when the files are
160 # different
161 with tempfile.TemporaryDirectory() as tmpdir:
162 r = run_diffoscope('A', 'B', tmpdir,
163 native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=self.diffoscope_test_files)
164
165 self.assertNotEqual(r.status, 0, msg="diffoscope was successful when an error was expected")
166 self.assertTrue(os.path.exists(os.path.join(tmpdir, 'index.html')), "HTML index not found!")
167
80class ReproducibleTests(OESelftestTestCase): 168class ReproducibleTests(OESelftestTestCase):
169 # Test the reproducibility of whatever is built between sstate_targets and targets
170
81 package_classes = ['deb', 'ipk'] 171 package_classes = ['deb', 'ipk']
82 images = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline'] 172
173 # targets are the things we want to test the reproducibility of
174 targets = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline', 'world']
175 # sstate targets are things to pull from sstate to potentially cut build/debugging time
176 sstate_targets = []
83 save_results = False 177 save_results = False
84 if 'OEQA_DEBUGGING_SAVED_OUTPUT' in os.environ: 178 if 'OEQA_DEBUGGING_SAVED_OUTPUT' in os.environ:
85 save_results = os.environ['OEQA_DEBUGGING_SAVED_OUTPUT'] 179 save_results = os.environ['OEQA_DEBUGGING_SAVED_OUTPUT']
@@ -94,7 +188,7 @@ class ReproducibleTests(OESelftestTestCase):
94 188
95 def setUpLocal(self): 189 def setUpLocal(self):
96 super().setUpLocal() 190 super().setUpLocal()
97 needed_vars = ['TOPDIR', 'TARGET_PREFIX', 'BB_NUMBER_THREADS'] 191 needed_vars = ['TOPDIR', 'TARGET_PREFIX', 'BB_NUMBER_THREADS', 'BB_HASHSERVE']
98 bb_vars = get_bb_vars(needed_vars) 192 bb_vars = get_bb_vars(needed_vars)
99 for v in needed_vars: 193 for v in needed_vars:
100 setattr(self, v.lower(), bb_vars[v]) 194 setattr(self, v.lower(), bb_vars[v])
@@ -150,21 +244,29 @@ class ReproducibleTests(OESelftestTestCase):
150 PACKAGE_CLASSES = "{package_classes}" 244 PACKAGE_CLASSES = "{package_classes}"
151 INHIBIT_PACKAGE_STRIP = "1" 245 INHIBIT_PACKAGE_STRIP = "1"
152 TMPDIR = "{tmpdir}" 246 TMPDIR = "{tmpdir}"
247 LICENSE_FLAGS_WHITELIST = "commercial"
248 DISTRO_FEATURES_append = ' systemd pam'
153 ''').format(package_classes=' '.join('package_%s' % c for c in self.package_classes), 249 ''').format(package_classes=' '.join('package_%s' % c for c in self.package_classes),
154 tmpdir=tmpdir) 250 tmpdir=tmpdir)
155 251
156 if not use_sstate: 252 if not use_sstate:
253 if self.sstate_targets:
254 self.logger.info("Building prebuild for %s (sstate allowed)..." % (name))
255 self.write_config(config)
256 bitbake(' '.join(self.sstate_targets))
257
157 # This config fragment will disable using shared and the sstate 258 # This config fragment will disable using shared and the sstate
158 # mirror, forcing a complete build from scratch 259 # mirror, forcing a complete build from scratch
159 config += textwrap.dedent('''\ 260 config += textwrap.dedent('''\
160 SSTATE_DIR = "${TMPDIR}/sstate" 261 SSTATE_DIR = "${TMPDIR}/sstate"
161 SSTATE_MIRRORS = "" 262 SSTATE_MIRRORS = "file://.*/.*-native.* http://sstate.yoctoproject.org/all/PATH;downloadfilename=PATH file://.*/.*-cross.* http://sstate.yoctoproject.org/all/PATH;downloadfilename=PATH"
162 ''') 263 ''')
163 264
164 self.logger.info("Building %s (sstate%s allowed)..." % (name, '' if use_sstate else ' NOT')) 265 self.logger.info("Building %s (sstate%s allowed)..." % (name, '' if use_sstate else ' NOT'))
165 self.write_config(config) 266 self.write_config(config)
166 d = get_bb_vars(capture_vars) 267 d = get_bb_vars(capture_vars)
167 bitbake(' '.join(self.images)) 268 # targets used to be called images
269 bitbake(' '.join(getattr(self, 'images', self.targets)))
168 return d 270 return d
169 271
170 def test_reproducible_builds(self): 272 def test_reproducible_builds(self):
@@ -212,6 +314,7 @@ class ReproducibleTests(OESelftestTestCase):
212 314
213 self.write_package_list(package_class, 'missing', result.missing) 315 self.write_package_list(package_class, 'missing', result.missing)
214 self.write_package_list(package_class, 'different', result.different) 316 self.write_package_list(package_class, 'different', result.different)
317 self.write_package_list(package_class, 'different_excluded', result.different_excluded)
215 self.write_package_list(package_class, 'same', result.same) 318 self.write_package_list(package_class, 'same', result.same)
216 319
217 if self.save_results: 320 if self.save_results:
@@ -219,8 +322,12 @@ class ReproducibleTests(OESelftestTestCase):
219 self.copy_file(d.reference, '/'.join([save_dir, 'packages', strip_topdir(d.reference)])) 322 self.copy_file(d.reference, '/'.join([save_dir, 'packages', strip_topdir(d.reference)]))
220 self.copy_file(d.test, '/'.join([save_dir, 'packages', strip_topdir(d.test)])) 323 self.copy_file(d.test, '/'.join([save_dir, 'packages', strip_topdir(d.test)]))
221 324
325 for d in result.different_excluded:
326 self.copy_file(d.reference, '/'.join([save_dir, 'packages-excluded', strip_topdir(d.reference)]))
327 self.copy_file(d.test, '/'.join([save_dir, 'packages-excluded', strip_topdir(d.test)]))
328
222 if result.missing or result.different: 329 if result.missing or result.different:
223 fails.append("The following %s packages are missing or different: %s" % 330 fails.append("The following %s packages are missing or different and not in exclusion list: %s" %
224 (c, '\n'.join(r.test for r in (result.missing + result.different)))) 331 (c, '\n'.join(r.test for r in (result.missing + result.different))))
225 332
226 # Clean up empty directories 333 # Clean up empty directories
@@ -235,7 +342,7 @@ class ReproducibleTests(OESelftestTestCase):
235 # Copy jquery to improve the diffoscope output usability 342 # Copy jquery to improve the diffoscope output usability
236 self.copy_file(os.path.join(jquery_sysroot, 'usr/share/javascript/jquery/jquery.min.js'), os.path.join(package_html_dir, 'jquery.js')) 343 self.copy_file(os.path.join(jquery_sysroot, 'usr/share/javascript/jquery/jquery.min.js'), os.path.join(package_html_dir, 'jquery.js'))
237 344
238 runCmd(['diffoscope', '--no-default-limits', '--exclude-directory-metadata', '--html-dir', package_html_dir, 'reproducibleA', 'reproducibleB'], 345 run_diffoscope('reproducibleA', 'reproducibleB', package_html_dir,
239 native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=package_dir) 346 native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=package_dir)
240 347
241 if fails: 348 if fails:
diff --git a/meta/lib/oeqa/selftest/cases/runcmd.py b/meta/lib/oeqa/selftest/cases/runcmd.py
index fa6113d7fa..e9612389fe 100644
--- a/meta/lib/oeqa/selftest/cases/runcmd.py
+++ b/meta/lib/oeqa/selftest/cases/runcmd.py
@@ -27,8 +27,8 @@ class RunCmdTests(OESelftestTestCase):
27 27
28 # The delta is intentionally smaller than the timeout, to detect cases where 28 # The delta is intentionally smaller than the timeout, to detect cases where
29 # we incorrectly apply the timeout more than once. 29 # we incorrectly apply the timeout more than once.
30 TIMEOUT = 5 30 TIMEOUT = 10
31 DELTA = 3 31 DELTA = 8
32 32
33 def test_result_okay(self): 33 def test_result_okay(self):
34 result = runCmd("true") 34 result = runCmd("true")
diff --git a/meta/lib/oeqa/selftest/cases/runqemu.py b/meta/lib/oeqa/selftest/cases/runqemu.py
index 7e676bcb41..da22f77b27 100644
--- a/meta/lib/oeqa/selftest/cases/runqemu.py
+++ b/meta/lib/oeqa/selftest/cases/runqemu.py
@@ -163,12 +163,11 @@ class QemuTest(OESelftestTestCase):
163 bitbake(cls.recipe) 163 bitbake(cls.recipe)
164 164
165 def _start_qemu_shutdown_check_if_shutdown_succeeded(self, qemu, timeout): 165 def _start_qemu_shutdown_check_if_shutdown_succeeded(self, qemu, timeout):
166 # Allow the runner's LoggingThread instance to exit without errors
167 # (such as the exception "Console connection closed unexpectedly")
168 # as qemu will disappear when we shut it down
169 qemu.runner.allowexit()
166 qemu.run_serial("shutdown -h now") 170 qemu.run_serial("shutdown -h now")
167 # Stop thread will stop the LoggingThread instance used for logging
168 # qemu through serial console, stop thread will prevent this code
169 # from facing exception (Console connection closed unexpectedly)
170 # when qemu was shutdown by the above shutdown command
171 qemu.runner.stop_thread()
172 time_track = 0 171 time_track = 0
173 try: 172 try:
174 while True: 173 while True:
diff --git a/meta/lib/oeqa/selftest/cases/runtime_test.py b/meta/lib/oeqa/selftest/cases/runtime_test.py
index 976b513727..cc4190c1d6 100644
--- a/meta/lib/oeqa/selftest/cases/runtime_test.py
+++ b/meta/lib/oeqa/selftest/cases/runtime_test.py
@@ -14,11 +14,6 @@ from oeqa.core.decorator.data import skipIfNotQemu
14 14
15class TestExport(OESelftestTestCase): 15class TestExport(OESelftestTestCase):
16 16
17 @classmethod
18 def tearDownClass(cls):
19 runCmd("rm -rf /tmp/sdk")
20 super(TestExport, cls).tearDownClass()
21
22 def test_testexport_basic(self): 17 def test_testexport_basic(self):
23 """ 18 """
24 Summary: Check basic testexport functionality with only ping test enabled. 19 Summary: Check basic testexport functionality with only ping test enabled.
@@ -95,19 +90,20 @@ class TestExport(OESelftestTestCase):
95 msg = "Couldn't find SDK tarball: %s" % tarball_path 90 msg = "Couldn't find SDK tarball: %s" % tarball_path
96 self.assertEqual(os.path.isfile(tarball_path), True, msg) 91 self.assertEqual(os.path.isfile(tarball_path), True, msg)
97 92
98 # Extract SDK and run tar from SDK 93 with tempfile.TemporaryDirectory() as tmpdirname:
99 result = runCmd("%s -y -d /tmp/sdk" % tarball_path) 94 # Extract SDK and run tar from SDK
100 self.assertEqual(0, result.status, "Couldn't extract SDK") 95 result = runCmd("%s -y -d %s" % (tarball_path, tmpdirname))
96 self.assertEqual(0, result.status, "Couldn't extract SDK")
101 97
102 env_script = result.output.split()[-1] 98 env_script = result.output.split()[-1]
103 result = runCmd(". %s; which tar" % env_script, shell=True) 99 result = runCmd(". %s; which tar" % env_script, shell=True)
104 self.assertEqual(0, result.status, "Couldn't setup SDK environment") 100 self.assertEqual(0, result.status, "Couldn't setup SDK environment")
105 is_sdk_tar = True if "/tmp/sdk" in result.output else False 101 is_sdk_tar = True if tmpdirname in result.output else False
106 self.assertTrue(is_sdk_tar, "Couldn't setup SDK environment") 102 self.assertTrue(is_sdk_tar, "Couldn't setup SDK environment")
107 103
108 tar_sdk = result.output 104 tar_sdk = result.output
109 result = runCmd("%s --version" % tar_sdk) 105 result = runCmd("%s --version" % tar_sdk)
110 self.assertEqual(0, result.status, "Couldn't run tar from SDK") 106 self.assertEqual(0, result.status, "Couldn't run tar from SDK")
111 107
112 108
113class TestImage(OESelftestTestCase): 109class TestImage(OESelftestTestCase):
@@ -179,12 +175,24 @@ class TestImage(OESelftestTestCase):
179 if "DISPLAY" not in os.environ: 175 if "DISPLAY" not in os.environ:
180 self.skipTest("virgl gtk test must be run inside a X session") 176 self.skipTest("virgl gtk test must be run inside a X session")
181 distro = oe.lsb.distro_identifier() 177 distro = oe.lsb.distro_identifier()
178 if distro and distro.startswith('almalinux'):
179 self.skipTest('virgl isn\'t working with Alma Linux')
180 if distro and distro.startswith('rocky'):
181 self.skipTest('virgl isn\'t working with Rocky Linux')
182 if distro and distro == 'debian-8': 182 if distro and distro == 'debian-8':
183 self.skipTest('virgl isn\'t working with Debian 8') 183 self.skipTest('virgl isn\'t working with Debian 8')
184 if distro and distro == 'centos-7': 184 if distro and distro == 'centos-7':
185 self.skipTest('virgl isn\'t working with Centos 7') 185 self.skipTest('virgl isn\'t working with Centos 7')
186 if distro and distro == 'centos-8':
187 self.skipTest('virgl isn\'t working with Centos 8')
188 if distro and distro.startswith('fedora'):
189 self.skipTest('virgl isn\'t working with Fedora')
186 if distro and distro == 'opensuseleap-15.0': 190 if distro and distro == 'opensuseleap-15.0':
187 self.skipTest('virgl isn\'t working with Opensuse 15.0') 191 self.skipTest('virgl isn\'t working with Opensuse 15.0')
192 if distro and distro == 'ubuntu-22.04':
193 self.skipTest('virgl isn\'t working with Ubuntu 22.04')
194 if distro and distro == 'ubuntu-22.10':
195 self.skipTest('virgl isn\'t working with Ubuntu 22.10')
188 196
189 qemu_packageconfig = get_bb_var('PACKAGECONFIG', 'qemu-system-native') 197 qemu_packageconfig = get_bb_var('PACKAGECONFIG', 'qemu-system-native')
190 sdl_packageconfig = get_bb_var('PACKAGECONFIG', 'libsdl2-native') 198 sdl_packageconfig = get_bb_var('PACKAGECONFIG', 'libsdl2-native')
@@ -220,6 +228,7 @@ class TestImage(OESelftestTestCase):
220 Author: Alexander Kanavin <alex.kanavin@gmail.com> 228 Author: Alexander Kanavin <alex.kanavin@gmail.com>
221 """ 229 """
222 import subprocess, os 230 import subprocess, os
231 self.skipTest("Crashes in mesa observed with this test on dunfell: https://bugzilla.yoctoproject.org/show_bug.cgi?id=14527")
223 try: 232 try:
224 content = os.listdir("/dev/dri") 233 content = os.listdir("/dev/dri")
225 if len([i for i in content if i.startswith('render')]) == 0: 234 if len([i for i in content if i.startswith('render')]) == 0:
@@ -227,7 +236,7 @@ class TestImage(OESelftestTestCase):
227 except FileNotFoundError: 236 except FileNotFoundError:
228 self.skipTest("/dev/dri directory does not exist; no render nodes available on this machine.") 237 self.skipTest("/dev/dri directory does not exist; no render nodes available on this machine.")
229 try: 238 try:
230 dripath = subprocess.check_output("pkg-config --variable=dridriverdir dri", shell=True) 239 dripath = subprocess.check_output("PATH=/bin:/usr/bin:$PATH pkg-config --variable=dridriverdir dri", shell=True)
231 except subprocess.CalledProcessError as e: 240 except subprocess.CalledProcessError as e:
232 self.skipTest("Could not determine the path to dri drivers on the host via pkg-config.\nPlease install Mesa development files (particularly, dri.pc) on the host machine.") 241 self.skipTest("Could not determine the path to dri drivers on the host via pkg-config.\nPlease install Mesa development files (particularly, dri.pc) on the host machine.")
233 qemu_packageconfig = get_bb_var('PACKAGECONFIG', 'qemu-system-native') 242 qemu_packageconfig = get_bb_var('PACKAGECONFIG', 'qemu-system-native')
diff --git a/meta/lib/oeqa/selftest/cases/sstatetests.py b/meta/lib/oeqa/selftest/cases/sstatetests.py
index c46e8ba489..1bfe88c87d 100644
--- a/meta/lib/oeqa/selftest/cases/sstatetests.py
+++ b/meta/lib/oeqa/selftest/cases/sstatetests.py
@@ -39,7 +39,7 @@ class SStateTests(SStateBase):
39 39
40 recipefile = os.path.join(tempdir, "recipes-test", "dbus-wait-test", 'dbus-wait-test_git.bb') 40 recipefile = os.path.join(tempdir, "recipes-test", "dbus-wait-test", 'dbus-wait-test_git.bb')
41 os.makedirs(os.path.dirname(recipefile)) 41 os.makedirs(os.path.dirname(recipefile))
42 srcuri = 'git://' + srcdir + ';protocol=file' 42 srcuri = 'git://' + srcdir + ';protocol=file;branch=master'
43 result = runCmd(['recipetool', 'create', '-o', recipefile, srcuri]) 43 result = runCmd(['recipetool', 'create', '-o', recipefile, srcuri])
44 self.assertTrue(os.path.isfile(recipefile), 'recipetool did not create recipe file; output:\n%s' % result.output) 44 self.assertTrue(os.path.isfile(recipefile), 'recipetool did not create recipe file; output:\n%s' % result.output)
45 45
@@ -137,7 +137,7 @@ class SStateTests(SStateBase):
137 filtered_results.append(r) 137 filtered_results.append(r)
138 self.assertTrue(filtered_results == [], msg="Found distro non-specific sstate for: %s (%s)" % (', '.join(map(str, targets)), str(filtered_results))) 138 self.assertTrue(filtered_results == [], msg="Found distro non-specific sstate for: %s (%s)" % (', '.join(map(str, targets)), str(filtered_results)))
139 file_tracker_1 = self.search_sstate('|'.join(map(str, [s + r'.*?\.tgz$' for s in targets])), distro_specific=True, distro_nonspecific=False) 139 file_tracker_1 = self.search_sstate('|'.join(map(str, [s + r'.*?\.tgz$' for s in targets])), distro_specific=True, distro_nonspecific=False)
140 self.assertTrue(len(file_tracker_1) >= len(targets), msg = "Not all sstate files ware created for: %s" % ', '.join(map(str, targets))) 140 self.assertTrue(len(file_tracker_1) >= len(targets), msg = "Not all sstate files were created for: %s" % ', '.join(map(str, targets)))
141 141
142 self.track_for_cleanup(self.distro_specific_sstate + "_old") 142 self.track_for_cleanup(self.distro_specific_sstate + "_old")
143 shutil.copytree(self.distro_specific_sstate, self.distro_specific_sstate + "_old") 143 shutil.copytree(self.distro_specific_sstate, self.distro_specific_sstate + "_old")
@@ -146,13 +146,13 @@ class SStateTests(SStateBase):
146 bitbake(['-cclean'] + targets) 146 bitbake(['-cclean'] + targets)
147 bitbake(targets) 147 bitbake(targets)
148 file_tracker_2 = self.search_sstate('|'.join(map(str, [s + r'.*?\.tgz$' for s in targets])), distro_specific=True, distro_nonspecific=False) 148 file_tracker_2 = self.search_sstate('|'.join(map(str, [s + r'.*?\.tgz$' for s in targets])), distro_specific=True, distro_nonspecific=False)
149 self.assertTrue(len(file_tracker_2) >= len(targets), msg = "Not all sstate files ware created for: %s" % ', '.join(map(str, targets))) 149 self.assertTrue(len(file_tracker_2) >= len(targets), msg = "Not all sstate files were created for: %s" % ', '.join(map(str, targets)))
150 150
151 not_recreated = [x for x in file_tracker_1 if x not in file_tracker_2] 151 not_recreated = [x for x in file_tracker_1 if x not in file_tracker_2]
152 self.assertTrue(not_recreated == [], msg="The following sstate files ware not recreated: %s" % ', '.join(map(str, not_recreated))) 152 self.assertTrue(not_recreated == [], msg="The following sstate files were not recreated: %s" % ', '.join(map(str, not_recreated)))
153 153
154 created_once = [x for x in file_tracker_2 if x not in file_tracker_1] 154 created_once = [x for x in file_tracker_2 if x not in file_tracker_1]
155 self.assertTrue(created_once == [], msg="The following sstate files ware created only in the second run: %s" % ', '.join(map(str, created_once))) 155 self.assertTrue(created_once == [], msg="The following sstate files were created only in the second run: %s" % ', '.join(map(str, created_once)))
156 156
157 def test_rebuild_distro_specific_sstate_cross_native_targets(self): 157 def test_rebuild_distro_specific_sstate_cross_native_targets(self):
158 self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + self.tune_arch, 'binutils-native'], temp_sstate_location=True) 158 self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + self.tune_arch, 'binutils-native'], temp_sstate_location=True)
@@ -202,9 +202,9 @@ class SStateTests(SStateBase):
202 actual_remaining_sstate = [x for x in self.search_sstate(target + r'.*?\.tgz$') if not any(pattern in x for pattern in ignore_patterns)] 202 actual_remaining_sstate = [x for x in self.search_sstate(target + r'.*?\.tgz$') if not any(pattern in x for pattern in ignore_patterns)]
203 203
204 actual_not_expected = [x for x in actual_remaining_sstate if x not in expected_remaining_sstate] 204 actual_not_expected = [x for x in actual_remaining_sstate if x not in expected_remaining_sstate]
205 self.assertFalse(actual_not_expected, msg="Files should have been removed but ware not: %s" % ', '.join(map(str, actual_not_expected))) 205 self.assertFalse(actual_not_expected, msg="Files should have been removed but were not: %s" % ', '.join(map(str, actual_not_expected)))
206 expected_not_actual = [x for x in expected_remaining_sstate if x not in actual_remaining_sstate] 206 expected_not_actual = [x for x in expected_remaining_sstate if x not in actual_remaining_sstate]
207 self.assertFalse(expected_not_actual, msg="Extra files ware removed: %s" ', '.join(map(str, expected_not_actual))) 207 self.assertFalse(expected_not_actual, msg="Extra files were removed: %s" ', '.join(map(str, expected_not_actual)))
208 208
209 def test_sstate_cache_management_script_using_pr_1(self): 209 def test_sstate_cache_management_script_using_pr_1(self):
210 global_config = [] 210 global_config = []
diff --git a/meta/lib/oeqa/selftest/cases/tinfoil.py b/meta/lib/oeqa/selftest/cases/tinfoil.py
index a51c6048d3..6668d7cdc8 100644
--- a/meta/lib/oeqa/selftest/cases/tinfoil.py
+++ b/meta/lib/oeqa/selftest/cases/tinfoil.py
@@ -65,6 +65,20 @@ class TinfoilTests(OESelftestTestCase):
65 localdata.setVar('PN', 'hello') 65 localdata.setVar('PN', 'hello')
66 self.assertEqual('hello', localdata.getVar('BPN')) 66 self.assertEqual('hello', localdata.getVar('BPN'))
67 67
68 # The config_data API tp parse_recipe_file is used by:
69 # layerindex-web layerindex/update_layer.py
70 def test_parse_recipe_custom_data(self):
71 with bb.tinfoil.Tinfoil() as tinfoil:
72 tinfoil.prepare(config_only=False, quiet=2)
73 localdata = bb.data.createCopy(tinfoil.config_data)
74 localdata.setVar("TESTVAR", "testval")
75 testrecipe = 'mdadm'
76 best = tinfoil.find_best_provider(testrecipe)
77 if not best:
78 self.fail('Unable to find recipe providing %s' % testrecipe)
79 rd = tinfoil.parse_recipe_file(best[3], config_data=localdata)
80 self.assertEqual("testval", rd.getVar('TESTVAR'))
81
68 def test_list_recipes(self): 82 def test_list_recipes(self):
69 with bb.tinfoil.Tinfoil() as tinfoil: 83 with bb.tinfoil.Tinfoil() as tinfoil:
70 tinfoil.prepare(config_only=False, quiet=2) 84 tinfoil.prepare(config_only=False, quiet=2)
@@ -87,23 +101,22 @@ class TinfoilTests(OESelftestTestCase):
87 with bb.tinfoil.Tinfoil() as tinfoil: 101 with bb.tinfoil.Tinfoil() as tinfoil:
88 tinfoil.prepare(config_only=True) 102 tinfoil.prepare(config_only=True)
89 103
90 tinfoil.set_event_mask(['bb.event.FilesMatchingFound', 'bb.command.CommandCompleted']) 104 tinfoil.set_event_mask(['bb.event.FilesMatchingFound', 'bb.command.CommandCompleted', 'bb.command.CommandFailed', 'bb.command.CommandExit'])
91 105
92 # Need to drain events otherwise events that were masked may still be in the queue 106 # Need to drain events otherwise events that were masked may still be in the queue
93 while tinfoil.wait_event(): 107 while tinfoil.wait_event():
94 pass 108 pass
95 109
96 pattern = 'conf' 110 pattern = 'conf'
97 res = tinfoil.run_command('findFilesMatchingInDir', pattern, 'conf/machine') 111 res = tinfoil.run_command('testCookerCommandEvent', pattern, handle_events=False)
98 self.assertTrue(res) 112 self.assertTrue(res)
99 113
100 eventreceived = False 114 eventreceived = False
101 commandcomplete = False 115 commandcomplete = False
102 start = time.time() 116 start = time.time()
103 # Wait for maximum 60s in total so we'd detect spurious heartbeat events for example 117 # Wait for maximum 120s in total so we'd detect spurious heartbeat events for example
104 # The test is IO load sensitive too
105 while (not (eventreceived == True and commandcomplete == True) 118 while (not (eventreceived == True and commandcomplete == True)
106 and (time.time() - start < 60)): 119 and (time.time() - start < 120)):
107 # if we received both events (on let's say a good day), we are done 120 # if we received both events (on let's say a good day), we are done
108 event = tinfoil.wait_event(1) 121 event = tinfoil.wait_event(1)
109 if event: 122 if event:
@@ -111,14 +124,15 @@ class TinfoilTests(OESelftestTestCase):
111 commandcomplete = True 124 commandcomplete = True
112 elif isinstance(event, bb.event.FilesMatchingFound): 125 elif isinstance(event, bb.event.FilesMatchingFound):
113 self.assertEqual(pattern, event._pattern) 126 self.assertEqual(pattern, event._pattern)
114 self.assertIn('qemuarm.conf', event._matches) 127 self.assertIn('A', event._matches)
128 self.assertIn('B', event._matches)
115 eventreceived = True 129 eventreceived = True
116 elif isinstance(event, logging.LogRecord): 130 elif isinstance(event, logging.LogRecord):
117 continue 131 continue
118 else: 132 else:
119 self.fail('Unexpected event: %s' % event) 133 self.fail('Unexpected event: %s' % event)
120 134
121 self.assertTrue(commandcomplete, 'Timed out waiting for CommandCompleted event from bitbake server') 135 self.assertTrue(commandcomplete, 'Timed out waiting for CommandCompleted event from bitbake server (Matching event received: %s)' % str(eventreceived))
122 self.assertTrue(eventreceived, 'Did not receive FilesMatchingFound event from bitbake server') 136 self.assertTrue(eventreceived, 'Did not receive FilesMatchingFound event from bitbake server')
123 137
124 def test_setvariable_clean(self): 138 def test_setvariable_clean(self):
diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py
index 0435aa29c9..f7abdba015 100644
--- a/meta/lib/oeqa/selftest/cases/wic.py
+++ b/meta/lib/oeqa/selftest/cases/wic.py
@@ -905,14 +905,18 @@ class Wic2(WicTestCase):
905 @only_for_arch(['i586', 'i686', 'x86_64']) 905 @only_for_arch(['i586', 'i686', 'x86_64'])
906 def test_rawcopy_plugin_qemu(self): 906 def test_rawcopy_plugin_qemu(self):
907 """Test rawcopy plugin in qemu""" 907 """Test rawcopy plugin in qemu"""
908 # build ext4 and wic images 908 # build ext4 and then use it for a wic image
909 for fstype in ("ext4", "wic"): 909 config = 'IMAGE_FSTYPES = "ext4"\n'
910 config = 'IMAGE_FSTYPES = "%s"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n' % fstype 910 self.append_config(config)
911 self.append_config(config) 911 self.assertEqual(0, bitbake('core-image-minimal').status)
912 self.assertEqual(0, bitbake('core-image-minimal').status) 912 self.remove_config(config)
913 self.remove_config(config)
914 913
915 with runqemu('core-image-minimal', ssh=False, image_fstype='wic') as qemu: 914 config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n'
915 self.append_config(config)
916 self.assertEqual(0, bitbake('core-image-minimal-mtdutils').status)
917 self.remove_config(config)
918
919 with runqemu('core-image-minimal-mtdutils', ssh=False, image_fstype='wic') as qemu:
916 cmd = "grep sda. /proc/partitions |wc -l" 920 cmd = "grep sda. /proc/partitions |wc -l"
917 status, output = qemu.run_serial(cmd) 921 status, output = qemu.run_serial(cmd)
918 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) 922 self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output))