summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oeqa/runtime')
-rw-r--r--meta/lib/oeqa/runtime/cases/_qemutiny.py13
-rw-r--r--meta/lib/oeqa/runtime/cases/apt.py40
-rw-r--r--meta/lib/oeqa/runtime/cases/boot.py4
-rw-r--r--meta/lib/oeqa/runtime/cases/buildcpio.py7
-rw-r--r--meta/lib/oeqa/runtime/cases/buildgalculator.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/buildlzip.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/connman.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/date.py15
-rw-r--r--meta/lib/oeqa/runtime/cases/df.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/dnf.py88
-rw-r--r--meta/lib/oeqa/runtime/cases/ethernet_ip_connman.py8
-rw-r--r--meta/lib/oeqa/runtime/cases/gcc.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/gi.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/go.py21
-rw-r--r--meta/lib/oeqa/runtime/cases/gstreamer.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/kernelmodule.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/ksample.py4
-rw-r--r--meta/lib/oeqa/runtime/cases/ldd.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/login.py116
-rw-r--r--meta/lib/oeqa/runtime/cases/logrotate.py16
-rw-r--r--meta/lib/oeqa/runtime/cases/ltp.py28
-rw-r--r--meta/lib/oeqa/runtime/cases/ltp_stress.py3
-rw-r--r--meta/lib/oeqa/runtime/cases/maturin.py58
-rw-r--r--meta/lib/oeqa/runtime/cases/multilib.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/oe_syslog.py15
-rw-r--r--meta/lib/oeqa/runtime/cases/opkg.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/pam.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/parselogs-ignores-common.txt62
-rw-r--r--meta/lib/oeqa/runtime/cases/parselogs-ignores-mipsarch.txt2
-rw-r--r--meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuall.txt27
-rw-r--r--meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuarm64.txt6
-rw-r--r--meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuarmv5.txt19
-rw-r--r--meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuppc.txt6
-rw-r--r--meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuppc64.txt4
-rw-r--r--meta/lib/oeqa/runtime/cases/parselogs-ignores-qemux86.txt2
-rw-r--r--meta/lib/oeqa/runtime/cases/parselogs-ignores-x86.txt10
l---------meta/lib/oeqa/runtime/cases/parselogs-ignores-x86_64.txt1
-rw-r--r--meta/lib/oeqa/runtime/cases/parselogs.py382
-rw-r--r--meta/lib/oeqa/runtime/cases/perl.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/ping.py25
-rw-r--r--meta/lib/oeqa/runtime/cases/ptest.py14
-rw-r--r--meta/lib/oeqa/runtime/cases/python.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/rpm.py58
-rw-r--r--meta/lib/oeqa/runtime/cases/rt.py19
-rw-r--r--meta/lib/oeqa/runtime/cases/rtc.py17
-rw-r--r--meta/lib/oeqa/runtime/cases/runlevel.py5
-rw-r--r--meta/lib/oeqa/runtime/cases/rust.py64
-rw-r--r--meta/lib/oeqa/runtime/cases/scons.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/scp.py4
-rw-r--r--meta/lib/oeqa/runtime/cases/skeletoninit.py6
-rw-r--r--meta/lib/oeqa/runtime/cases/ssh.py9
-rw-r--r--meta/lib/oeqa/runtime/cases/stap.py41
-rw-r--r--meta/lib/oeqa/runtime/cases/storage.py18
-rw-r--r--meta/lib/oeqa/runtime/cases/suspend.py7
-rw-r--r--meta/lib/oeqa/runtime/cases/systemd.py30
-rw-r--r--meta/lib/oeqa/runtime/cases/terminal.py5
-rw-r--r--meta/lib/oeqa/runtime/cases/usb_hid.py7
-rw-r--r--meta/lib/oeqa/runtime/cases/weston.py22
-rw-r--r--meta/lib/oeqa/runtime/cases/x32lib.py2
-rw-r--r--meta/lib/oeqa/runtime/cases/xorg.py2
-rw-r--r--meta/lib/oeqa/runtime/context.py48
-rw-r--r--meta/lib/oeqa/runtime/decorator/package.py18
-rw-r--r--meta/lib/oeqa/runtime/files/hello.stp1
63 files changed, 897 insertions, 512 deletions
diff --git a/meta/lib/oeqa/runtime/cases/_qemutiny.py b/meta/lib/oeqa/runtime/cases/_qemutiny.py
index 6886e36502..816fd4a7cb 100644
--- a/meta/lib/oeqa/runtime/cases/_qemutiny.py
+++ b/meta/lib/oeqa/runtime/cases/_qemutiny.py
@@ -1,12 +1,19 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
5from oeqa.runtime.case import OERuntimeTestCase 7from oeqa.runtime.case import OERuntimeTestCase
8from oeqa.core.target.qemu import OEQemuTarget
6 9
7class QemuTinyTest(OERuntimeTestCase): 10class QemuTinyTest(OERuntimeTestCase):
8 11
9 def test_boot_tiny(self): 12 def test_boot_tiny(self):
10 status, output = self.target.run_serial('uname -a') 13 # Until the target has explicit run_serial support, check that the
11 msg = "Cannot detect poky tiny boot!" 14 # target is the qemu runner
12 self.assertTrue("yocto-tiny" in output, msg) 15 if isinstance(self.target, OEQemuTarget):
16 status, output = self.target.runner.run_serial('uname -a')
17 self.assertIn("Linux", output)
18 else:
19 self.skipTest("Target %s is not OEQemuTarget" % self.target)
diff --git a/meta/lib/oeqa/runtime/cases/apt.py b/meta/lib/oeqa/runtime/cases/apt.py
index 53745df93f..8000645843 100644
--- a/meta/lib/oeqa/runtime/cases/apt.py
+++ b/meta/lib/oeqa/runtime/cases/apt.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -21,7 +23,7 @@ class AptRepoTest(AptTest):
21 23
22 @classmethod 24 @classmethod
23 def setUpClass(cls): 25 def setUpClass(cls):
24 service_repo = os.path.join(cls.tc.td['DEPLOY_DIR_DEB'], 'all') 26 service_repo = os.path.join(cls.tc.td['DEPLOY_DIR_DEB'], '')
25 cls.repo_server = HTTPService(service_repo, 27 cls.repo_server = HTTPService(service_repo,
26 '0.0.0.0', port=cls.tc.target.server_port, 28 '0.0.0.0', port=cls.tc.target.server_port,
27 logger=cls.tc.logger) 29 logger=cls.tc.logger)
@@ -34,20 +36,44 @@ class AptRepoTest(AptTest):
34 def setup_source_config_for_package_install(self): 36 def setup_source_config_for_package_install(self):
35 apt_get_source_server = 'http://%s:%s/' % (self.tc.target.server_ip, self.repo_server.port) 37 apt_get_source_server = 'http://%s:%s/' % (self.tc.target.server_ip, self.repo_server.port)
36 apt_get_sourceslist_dir = '/etc/apt/' 38 apt_get_sourceslist_dir = '/etc/apt/'
37 self.target.run('cd %s; echo deb [ allow-insecure=yes ] %s ./ > sources.list' % (apt_get_sourceslist_dir, apt_get_source_server)) 39 self.target.run('cd %s; echo deb [ allow-insecure=yes ] %s/all ./ > sources.list' % (apt_get_sourceslist_dir, apt_get_source_server))
40
41 def setup_source_config_for_package_install_signed(self):
42 apt_get_source_server = 'http://%s:%s' % (self.tc.target.server_ip, self.repo_server.port)
43 apt_get_sourceslist_dir = '/etc/apt/'
44 self.target.run("cd %s; cp sources.list sources.list.bak; sed -i 's|\[trusted=yes\] http://bogus_ip:bogus_port|%s|g' sources.list" % (apt_get_sourceslist_dir, apt_get_source_server))
38 45
39 def cleanup_source_config_for_package_install(self): 46 def cleanup_source_config_for_package_install(self):
40 apt_get_sourceslist_dir = '/etc/apt/' 47 apt_get_sourceslist_dir = '/etc/apt/'
41 self.target.run('cd %s; rm sources.list' % (apt_get_sourceslist_dir)) 48 self.target.run('cd %s; rm sources.list' % (apt_get_sourceslist_dir))
42 49
50 def cleanup_source_config_for_package_install_signed(self):
51 apt_get_sourceslist_dir = '/etc/apt/'
52 self.target.run('cd %s; mv sources.list.bak sources.list' % (apt_get_sourceslist_dir))
53
54 def setup_key(self):
55 # the key is found on the target /etc/pki/packagefeed-gpg/
56 # named PACKAGEFEED-GPG-KEY-poky-branch
57 self.target.run('cd %s; apt-key add P*' % ('/etc/pki/packagefeed-gpg'))
58
43 @skipIfNotFeature('package-management', 59 @skipIfNotFeature('package-management',
44 'Test requires package-management to be in IMAGE_FEATURES') 60 'Test requires package-management to be in IMAGE_FEATURES')
45 @skipIfNotDataVar('IMAGE_PKGTYPE', 'deb', 61 @skipIfNotDataVar('IMAGE_PKGTYPE', 'deb',
46 'DEB is not the primary package manager') 62 'DEB is not the primary package manager')
47 @OEHasPackage(['apt']) 63 @OEHasPackage(['apt'])
48 def test_apt_install_from_repo(self): 64 def test_apt_install_from_repo(self):
49 self.setup_source_config_for_package_install() 65 if not self.tc.td.get('PACKAGE_FEED_GPG_NAME'):
50 self.pkg('update') 66 self.setup_source_config_for_package_install()
51 self.pkg('remove --yes run-postinsts-dev') 67 self.pkg('update')
52 self.pkg('install --yes --allow-unauthenticated run-postinsts-dev') 68 self.pkg('remove --yes run-postinsts-dev')
53 self.cleanup_source_config_for_package_install() 69 self.pkg('install --yes --allow-unauthenticated run-postinsts-dev')
70 self.cleanup_source_config_for_package_install()
71 else:
72 # when we are here a key has been set to sign the package feed and
73 # public key and gnupg installed on the image by test_testimage_apt
74 self.setup_source_config_for_package_install_signed()
75 self.setup_key()
76 self.pkg('update')
77 self.pkg('install --yes run-postinsts-dev')
78 self.pkg('remove --yes run-postinsts-dev')
79 self.cleanup_source_config_for_package_install_signed()
diff --git a/meta/lib/oeqa/runtime/cases/boot.py b/meta/lib/oeqa/runtime/cases/boot.py
index 2142f400a0..dcee3311f7 100644
--- a/meta/lib/oeqa/runtime/cases/boot.py
+++ b/meta/lib/oeqa/runtime/cases/boot.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -13,7 +15,7 @@ from oeqa.core.decorator.data import skipIfQemu
13class BootTest(OERuntimeTestCase): 15class BootTest(OERuntimeTestCase):
14 16
15 @OETimeout(120) 17 @OETimeout(120)
16 @skipIfQemu('qemuall', 'Test only runs on real hardware') 18 @skipIfQemu()
17 @OETestDepends(['ssh.SSHTest.test_ssh']) 19 @OETestDepends(['ssh.SSHTest.test_ssh'])
18 def test_reboot(self): 20 def test_reboot(self):
19 output = '' 21 output = ''
diff --git a/meta/lib/oeqa/runtime/cases/buildcpio.py b/meta/lib/oeqa/runtime/cases/buildcpio.py
index e29bf16ccb..7be734cb4f 100644
--- a/meta/lib/oeqa/runtime/cases/buildcpio.py
+++ b/meta/lib/oeqa/runtime/cases/buildcpio.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -12,7 +14,7 @@ class BuildCpioTest(OERuntimeTestCase):
12 14
13 @classmethod 15 @classmethod
14 def setUpClass(cls): 16 def setUpClass(cls):
15 uri = 'https://downloads.yoctoproject.org/mirror/sources/cpio-2.13.tar.gz' 17 uri = 'https://downloads.yoctoproject.org/mirror/sources/cpio-2.15.tar.gz'
16 cls.project = TargetBuildProject(cls.tc.target, 18 cls.project = TargetBuildProject(cls.tc.target,
17 uri, 19 uri,
18 dl_dir = cls.tc.td['DL_DIR']) 20 dl_dir = cls.tc.td['DL_DIR'])
@@ -27,7 +29,6 @@ class BuildCpioTest(OERuntimeTestCase):
27 @OEHasPackage(['autoconf']) 29 @OEHasPackage(['autoconf'])
28 def test_cpio(self): 30 def test_cpio(self):
29 self.project.download_archive() 31 self.project.download_archive()
30 self.project.run_configure('--disable-maintainer-mode', 32 self.project.run_configure()
31 'sed -i -e "/char \*program_name/d" src/global.c;')
32 self.project.run_make() 33 self.project.run_make()
33 self.project.run_install() 34 self.project.run_install()
diff --git a/meta/lib/oeqa/runtime/cases/buildgalculator.py b/meta/lib/oeqa/runtime/cases/buildgalculator.py
index e5cc3e2888..2cfb3243dc 100644
--- a/meta/lib/oeqa/runtime/cases/buildgalculator.py
+++ b/meta/lib/oeqa/runtime/cases/buildgalculator.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/buildlzip.py b/meta/lib/oeqa/runtime/cases/buildlzip.py
index bc70b41461..44f4f1be71 100644
--- a/meta/lib/oeqa/runtime/cases/buildlzip.py
+++ b/meta/lib/oeqa/runtime/cases/buildlzip.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/connman.py b/meta/lib/oeqa/runtime/cases/connman.py
index f0d15fac9b..a488752e3f 100644
--- a/meta/lib/oeqa/runtime/cases/connman.py
+++ b/meta/lib/oeqa/runtime/cases/connman.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/date.py b/meta/lib/oeqa/runtime/cases/date.py
index fdd2a6ae58..a2523de67a 100644
--- a/meta/lib/oeqa/runtime/cases/date.py
+++ b/meta/lib/oeqa/runtime/cases/date.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -13,12 +15,12 @@ class DateTest(OERuntimeTestCase):
13 def setUp(self): 15 def setUp(self):
14 if self.tc.td.get('VIRTUAL-RUNTIME_init_manager') == 'systemd': 16 if self.tc.td.get('VIRTUAL-RUNTIME_init_manager') == 'systemd':
15 self.logger.debug('Stopping systemd-timesyncd daemon') 17 self.logger.debug('Stopping systemd-timesyncd daemon')
16 self.target.run('systemctl disable --now systemd-timesyncd') 18 self.target.run('systemctl disable --now --runtime systemd-timesyncd')
17 19
18 def tearDown(self): 20 def tearDown(self):
19 if self.tc.td.get('VIRTUAL-RUNTIME_init_manager') == 'systemd': 21 if self.tc.td.get('VIRTUAL-RUNTIME_init_manager') == 'systemd':
20 self.logger.debug('Starting systemd-timesyncd daemon') 22 self.logger.debug('Starting systemd-timesyncd daemon')
21 self.target.run('systemctl enable --now systemd-timesyncd') 23 self.target.run('systemctl enable --now --runtime systemd-timesyncd')
22 24
23 @OETestDepends(['ssh.SSHTest.test_ssh']) 25 @OETestDepends(['ssh.SSHTest.test_ssh'])
24 @OEHasPackage(['coreutils', 'busybox']) 26 @OEHasPackage(['coreutils', 'busybox'])
@@ -28,14 +30,13 @@ class DateTest(OERuntimeTestCase):
28 self.assertEqual(status, 0, msg=msg) 30 self.assertEqual(status, 0, msg=msg)
29 oldDate = output 31 oldDate = output
30 32
31 sampleDate = '"2016-08-09 10:00:00"' 33 sampleTimestamp = 1488800000
32 (status, output) = self.target.run("date -s %s" % sampleDate) 34 (status, output) = self.target.run("date -s @%d" % sampleTimestamp)
33 self.assertEqual(status, 0, msg='Date set failed, output: %s' % output) 35 self.assertEqual(status, 0, msg='Date set failed, output: %s' % output)
34 36
35 (status, output) = self.target.run("date -R") 37 (status, output) = self.target.run('date +"%s"')
36 p = re.match('Tue, 09 Aug 2016 10:00:.. \+0000', output)
37 msg = 'The date was not set correctly, output: %s' % output 38 msg = 'The date was not set correctly, output: %s' % output
38 self.assertTrue(p, msg=msg) 39 self.assertTrue(int(output) - sampleTimestamp < 300, msg=msg)
39 40
40 (status, output) = self.target.run('date -s "%s"' % oldDate) 41 (status, output) = self.target.run('date -s "%s"' % oldDate)
41 msg = 'Failed to reset date, output: %s' % output 42 msg = 'Failed to reset date, output: %s' % output
diff --git a/meta/lib/oeqa/runtime/cases/df.py b/meta/lib/oeqa/runtime/cases/df.py
index bb155c9cf9..43e0ebf9ea 100644
--- a/meta/lib/oeqa/runtime/cases/df.py
+++ b/meta/lib/oeqa/runtime/cases/df.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/dnf.py b/meta/lib/oeqa/runtime/cases/dnf.py
index f40c63026e..3ccb18ce83 100644
--- a/meta/lib/oeqa/runtime/cases/dnf.py
+++ b/meta/lib/oeqa/runtime/cases/dnf.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -73,48 +75,43 @@ class DnfRepoTest(DnfTest):
73 def test_dnf_makecache(self): 75 def test_dnf_makecache(self):
74 self.dnf_with_repo('makecache') 76 self.dnf_with_repo('makecache')
75 77
76
77# Does not work when repo is specified on the command line
78# @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache'])
79# def test_dnf_repolist(self):
80# self.dnf_with_repo('repolist')
81
82 @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache']) 78 @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache'])
83 def test_dnf_repoinfo(self): 79 def test_dnf_repoinfo(self):
84 self.dnf_with_repo('repoinfo') 80 self.dnf_with_repo('repoinfo')
85 81
86 @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache']) 82 @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache'])
87 def test_dnf_install(self): 83 def test_dnf_install(self):
88 output = self.dnf_with_repo('list run-postinsts-dev') 84 self.dnf_with_repo('remove -y dnf-test-*')
89 if 'Installed Packages' in output: 85 self.dnf_with_repo('install -y dnf-test-dep')
90 self.dnf_with_repo('remove -y run-postinsts-dev')
91 self.dnf_with_repo('install -y run-postinsts-dev')
92 86
93 @OETestDepends(['dnf.DnfRepoTest.test_dnf_install']) 87 @OETestDepends(['dnf.DnfRepoTest.test_dnf_install'])
94 def test_dnf_install_dependency(self): 88 def test_dnf_install_dependency(self):
95 self.dnf_with_repo('remove -y run-postinsts') 89 self.dnf_with_repo('remove -y dnf-test-*')
96 self.dnf_with_repo('install -y run-postinsts-dev') 90 self.dnf_with_repo('install -y dnf-test-main')
91 output = self.dnf('list --installed dnf-test-*')
92 self.assertIn("dnf-test-main.", output)
93 self.assertIn("dnf-test-dep.", output)
97 94
98 @OETestDepends(['dnf.DnfRepoTest.test_dnf_install_dependency']) 95 @OETestDepends(['dnf.DnfRepoTest.test_dnf_install_dependency'])
99 def test_dnf_install_from_disk(self): 96 def test_dnf_install_from_disk(self):
100 self.dnf_with_repo('remove -y run-postinsts-dev') 97 self.dnf_with_repo('remove -y dnf-test-dep')
101 self.dnf_with_repo('install -y --downloadonly run-postinsts-dev') 98 self.dnf_with_repo('install -y --downloadonly dnf-test-dep')
102 status, output = self.target.run('find /var/cache/dnf -name run-postinsts-dev*rpm', 1500) 99 status, output = self.target.run('find /var/cache/dnf -name dnf-test-dep*rpm')
103 self.assertEqual(status, 0, output) 100 self.assertEqual(status, 0, output)
104 self.dnf_with_repo('install -y %s' % output) 101 self.dnf_with_repo('install -y %s' % output)
105 102
106 @OETestDepends(['dnf.DnfRepoTest.test_dnf_install_from_disk']) 103 @OETestDepends(['dnf.DnfRepoTest.test_dnf_install_from_disk'])
107 def test_dnf_install_from_http(self): 104 def test_dnf_install_from_http(self):
108 output = subprocess.check_output('%s %s -name run-postinsts-dev*' % (bb.utils.which(os.getenv('PATH'), "find"), 105 output = subprocess.check_output('%s %s -name dnf-test-dep*' % (bb.utils.which(os.getenv('PATH'), "find"),
109 os.path.join(self.tc.td['WORKDIR'], 'oe-testimage-repo')), shell=True).decode("utf-8") 106 os.path.join(self.tc.td['WORKDIR'], 'oe-testimage-repo')), shell=True).decode("utf-8")
110 rpm_path = output.split("/")[-2] + "/" + output.split("/")[-1] 107 rpm_path = output.split("/")[-2] + "/" + output.split("/")[-1]
111 url = 'http://%s:%s/%s' %(self.target.server_ip, self.repo_server.port, rpm_path) 108 url = 'http://%s:%s/%s' %(self.target.server_ip, self.repo_server.port, rpm_path)
112 self.dnf_with_repo('remove -y run-postinsts-dev') 109 self.dnf_with_repo('remove -y dnf-test-dep')
113 self.dnf_with_repo('install -y %s' % url) 110 self.dnf_with_repo('install -y %s' % url)
114 111
115 @OETestDepends(['dnf.DnfRepoTest.test_dnf_install']) 112 @OETestDepends(['dnf.DnfRepoTest.test_dnf_install'])
116 def test_dnf_reinstall(self): 113 def test_dnf_reinstall(self):
117 self.dnf_with_repo('reinstall -y run-postinsts-dev') 114 self.dnf_with_repo('reinstall -y dnf-test-main')
118 115
119 @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache']) 116 @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache'])
120 @skipIfInDataVar('DISTRO_FEATURES', 'usrmerge', 'Test run when not enable usrmerge') 117 @skipIfInDataVar('DISTRO_FEATURES', 'usrmerge', 'Test run when not enable usrmerge')
@@ -137,55 +134,40 @@ class DnfRepoTest(DnfTest):
137 self.target.run('cp -r /etc/dnf %s/etc' % rootpath, 1500) 134 self.target.run('cp -r /etc/dnf %s/etc' % rootpath, 1500)
138 self.target.run('cp /bin/sh %s/bin' % rootpath, 1500) 135 self.target.run('cp /bin/sh %s/bin' % rootpath, 1500)
139 self.target.run('mount -o bind /dev %s/dev/' % rootpath, 1500) 136 self.target.run('mount -o bind /dev %s/dev/' % rootpath, 1500)
140 self.dnf_with_repo('install --installroot=%s -v -y --rpmverbosity=debug busybox run-postinsts' % rootpath) 137 self.dnf_with_repo('install --installroot=%s -v -y --rpmverbosity=debug busybox' % rootpath)
141 status, output = self.target.run('test -e %s/var/cache/dnf' % rootpath, 1500) 138 status, output = self.target.run('test -e %s/var/cache/dnf' % rootpath, 1500)
142 self.assertEqual(0, status, output) 139 self.assertEqual(0, status, output)
143 status, output = self.target.run('test -e %s/bin/busybox' % rootpath, 1500) 140 status, output = self.target.run('test -e %s/bin/busybox' % rootpath, 1500)
144 self.assertEqual(0, status, output) 141 self.assertEqual(0, status, output)
145 142
146 @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache']) 143 @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache'])
147 @skipIfNotInDataVar('DISTRO_FEATURES', 'usrmerge', 'Test run when enable usrmege') 144 @skipIfNotInDataVar('DISTRO_FEATURES', 'usrmerge', 'Test run when enable usrmerge')
148 @OEHasPackage('busybox') 145 @OEHasPackage('busybox')
149 def test_dnf_installroot_usrmerge(self): 146 def test_dnf_installroot_usrmerge(self):
150 rootpath = '/home/root/chroot/test' 147 rootpath = '/home/root/chroot/test'
151 #Copy necessary files to avoid errors with not yet installed tools on 148 #Copy necessary files to avoid errors with not yet installed tools on
152 #installroot directory. 149 #installroot directory.
153 self.target.run('mkdir -p %s/etc' % rootpath, 1500) 150 self.target.run('mkdir -p %s/etc' % rootpath)
154 self.target.run('mkdir -p %s/usr/bin %s/usr/sbin' % (rootpath, rootpath), 1500) 151 self.target.run('mkdir -p %s/usr/bin %s/usr/sbin' % (rootpath, rootpath))
155 self.target.run('ln -sf -r %s/usr/bin %s/bin' % (rootpath, rootpath), 1500) 152 self.target.run('ln -sf usr/bin %s/bin' % (rootpath))
156 self.target.run('ln -sf -r %s/usr/sbin %s/sbin' % (rootpath, rootpath), 1500) 153 self.target.run('ln -sf usr/sbin %s/sbin' % (rootpath))
157 self.target.run('mkdir -p %s/dev' % rootpath, 1500) 154 self.target.run('mkdir -p %s/dev' % rootpath)
158 #Handle different architectures lib dirs 155 #Handle different architectures lib dirs
159 self.target.run('mkdir -p %s/usr/lib' % rootpath, 1500) 156 self.target.run("for l in /lib*; do mkdir -p %s/usr/$l; ln -s usr/$l %s/$l; done" % (rootpath, rootpath))
160 self.target.run('mkdir -p %s/usr/libx32' % rootpath, 1500) 157 self.target.run('cp -r /etc/rpm %s/etc' % rootpath)
161 self.target.run('mkdir -p %s/usr/lib64' % rootpath, 1500) 158 self.target.run('cp -r /etc/dnf %s/etc' % rootpath)
162 self.target.run('cp /lib/libtinfo.so.5 %s/usr/lib' % rootpath, 1500) 159 self.target.run('cp /bin/busybox %s/bin/sh' % rootpath)
163 self.target.run('cp /libx32/libtinfo.so.5 %s/usr/libx32' % rootpath, 1500) 160 self.target.run('mount -o bind /dev %s/dev/' % rootpath)
164 self.target.run('cp /lib64/libtinfo.so.5 %s/usr/lib64' % rootpath, 1500) 161 self.dnf_with_repo('install --installroot=%s -v -y --rpmverbosity=debug busybox' % rootpath)
165 self.target.run('ln -sf -r %s/lib %s/usr/lib' % (rootpath,rootpath), 1500) 162 status, output = self.target.run('test -e %s/var/cache/dnf' % rootpath)
166 self.target.run('ln -sf -r %s/libx32 %s/usr/libx32' % (rootpath,rootpath), 1500)
167 self.target.run('ln -sf -r %s/lib64 %s/usr/lib64' % (rootpath,rootpath), 1500)
168 self.target.run('cp -r /etc/rpm %s/etc' % rootpath, 1500)
169 self.target.run('cp -r /etc/dnf %s/etc' % rootpath, 1500)
170 self.target.run('cp /bin/sh %s/bin' % rootpath, 1500)
171 self.target.run('mount -o bind /dev %s/dev/' % rootpath, 1500)
172 self.dnf_with_repo('install --installroot=%s -v -y --rpmverbosity=debug busybox run-postinsts' % rootpath)
173 status, output = self.target.run('test -e %s/var/cache/dnf' % rootpath, 1500)
174 self.assertEqual(0, status, output) 163 self.assertEqual(0, status, output)
175 status, output = self.target.run('test -e %s/bin/busybox' % rootpath, 1500) 164 status, output = self.target.run('test -e %s/bin/busybox' % rootpath)
176 self.assertEqual(0, status, output) 165 self.assertEqual(0, status, output)
177 166
178 @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache']) 167 @OETestDepends(['dnf.DnfRepoTest.test_dnf_makecache'])
179 def test_dnf_exclude(self): 168 def test_dnf_exclude(self):
180 excludepkg = 'curl-dev' 169 self.dnf_with_repo('remove -y dnf-test-*')
181 self.dnf_with_repo('install -y curl*') 170 self.dnf_with_repo('install -y --exclude=dnf-test-dep dnf-test-*')
182 self.dnf('list %s' % excludepkg, 0) 171 output = self.dnf('list --installed dnf-test-*')
183 #Avoid remove dependencies to skip some errors on different archs and images 172 self.assertIn("dnf-test-main.", output)
184 self.dnf_with_repo('remove --setopt=clean_requirements_on_remove=0 -y curl*') 173 self.assertNotIn("dnf-test-dev.", output)
185 #check curl-dev is not installed adter removing all curl occurrences
186 status, output = self.target.run('dnf list --installed | grep %s'% excludepkg, 1500)
187 self.assertEqual(1, status, "%s was not removed, is listed as installed"%excludepkg)
188 self.dnf_with_repo('install -y --exclude=%s --exclude=curl-staticdev curl*' % excludepkg)
189 #check curl-dev is not installed after being excluded
190 status, output = self.target.run('dnf list --installed | grep %s'% excludepkg , 1500)
191 self.assertEqual(1, status, "%s was not excluded, is listed as installed"%excludepkg)
diff --git a/meta/lib/oeqa/runtime/cases/ethernet_ip_connman.py b/meta/lib/oeqa/runtime/cases/ethernet_ip_connman.py
index e010612838..eac8f2d082 100644
--- a/meta/lib/oeqa/runtime/cases/ethernet_ip_connman.py
+++ b/meta/lib/oeqa/runtime/cases/ethernet_ip_connman.py
@@ -1,3 +1,8 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
1from oeqa.runtime.case import OERuntimeTestCase 6from oeqa.runtime.case import OERuntimeTestCase
2from oeqa.core.decorator.depends import OETestDepends 7from oeqa.core.decorator.depends import OETestDepends
3from oeqa.core.decorator.data import skipIfQemu 8from oeqa.core.decorator.data import skipIfQemu
@@ -11,7 +16,7 @@ class Ethernet_Test(OERuntimeTestCase):
11 x = '.'.join(x) 16 x = '.'.join(x)
12 return x 17 return x
13 18
14 @skipIfQemu('qemuall', 'Test only runs on real hardware') 19 @skipIfQemu()
15 @OETestDepends(['ssh.SSHTest.test_ssh']) 20 @OETestDepends(['ssh.SSHTest.test_ssh'])
16 def test_set_virtual_ip(self): 21 def test_set_virtual_ip(self):
17 (status, output) = self.target.run("ifconfig eth0 | grep 'inet ' | awk '{print $2}'") 22 (status, output) = self.target.run("ifconfig eth0 | grep 'inet ' | awk '{print $2}'")
@@ -22,6 +27,7 @@ class Ethernet_Test(OERuntimeTestCase):
22 (status, output) = self.target.run("ifconfig eth0:1 %s netmask 255.255.255.0 && sleep 2 && ping -c 5 %s && ifconfig eth0:1 down" % (virtual_ip,virtual_ip)) 27 (status, output) = self.target.run("ifconfig eth0:1 %s netmask 255.255.255.0 && sleep 2 && ping -c 5 %s && ifconfig eth0:1 down" % (virtual_ip,virtual_ip))
23 self.assertEqual(status, 0, msg='Failed to create virtual ip address, output: %s' % output) 28 self.assertEqual(status, 0, msg='Failed to create virtual ip address, output: %s' % output)
24 29
30 @skipIfQemu()
25 @OETestDepends(['ethernet_ip_connman.Ethernet_Test.test_set_virtual_ip']) 31 @OETestDepends(['ethernet_ip_connman.Ethernet_Test.test_set_virtual_ip'])
26 def test_get_ip_from_dhcp(self): 32 def test_get_ip_from_dhcp(self):
27 (status, output) = self.target.run("connmanctl services | grep -E '*AO Wired|*AR Wired' | awk '{print $3}'") 33 (status, output) = self.target.run("connmanctl services | grep -E '*AO Wired|*AR Wired' | awk '{print $3}'")
diff --git a/meta/lib/oeqa/runtime/cases/gcc.py b/meta/lib/oeqa/runtime/cases/gcc.py
index 1b6e431bf4..17b1483e8d 100644
--- a/meta/lib/oeqa/runtime/cases/gcc.py
+++ b/meta/lib/oeqa/runtime/cases/gcc.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/gi.py b/meta/lib/oeqa/runtime/cases/gi.py
index 42bd100a31..78c7ddda2c 100644
--- a/meta/lib/oeqa/runtime/cases/gi.py
+++ b/meta/lib/oeqa/runtime/cases/gi.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/go.py b/meta/lib/oeqa/runtime/cases/go.py
new file mode 100644
index 0000000000..39a80f4dca
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/go.py
@@ -0,0 +1,21 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7from oeqa.runtime.case import OERuntimeTestCase
8from oeqa.core.decorator.depends import OETestDepends
9from oeqa.runtime.decorator.package import OEHasPackage
10
11class GoHelloworldTest(OERuntimeTestCase):
12 @OETestDepends(['ssh.SSHTest.test_ssh'])
13 @OEHasPackage(['go-helloworld'])
14 def test_gohelloworld(self):
15 cmd = "go-helloworld"
16 status, output = self.target.run(cmd)
17 msg = 'Exit status was not 0. Output: %s' % output
18 self.assertEqual(status, 0, msg=msg)
19
20 msg = 'Incorrect output: %s' % output
21 self.assertEqual(output, "Hello, world!", msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/gstreamer.py b/meta/lib/oeqa/runtime/cases/gstreamer.py
index f735f82e3b..2295769cfd 100644
--- a/meta/lib/oeqa/runtime/cases/gstreamer.py
+++ b/meta/lib/oeqa/runtime/cases/gstreamer.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/kernelmodule.py b/meta/lib/oeqa/runtime/cases/kernelmodule.py
index 47fd2f850c..9c42fcc586 100644
--- a/meta/lib/oeqa/runtime/cases/kernelmodule.py
+++ b/meta/lib/oeqa/runtime/cases/kernelmodule.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/ksample.py b/meta/lib/oeqa/runtime/cases/ksample.py
index a9a1620ebd..b6848762e3 100644
--- a/meta/lib/oeqa/runtime/cases/ksample.py
+++ b/meta/lib/oeqa/runtime/cases/ksample.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -10,7 +12,7 @@ from oeqa.core.decorator.depends import OETestDepends
10from oeqa.core.decorator.data import skipIfNotFeature 12from oeqa.core.decorator.data import skipIfNotFeature
11 13
12# need some kernel fragments 14# need some kernel fragments
13# echo "KERNEL_FEATURES_append += \" features\/kernel\-sample\/kernel\-sample.scc\"" >> local.conf 15# echo "KERNEL_FEATURES:append = \" features\/kernel\-sample\/kernel\-sample.scc\"" >> local.conf
14class KSample(OERuntimeTestCase): 16class KSample(OERuntimeTestCase):
15 def cmd_and_check(self, cmd='', match_string=''): 17 def cmd_and_check(self, cmd='', match_string=''):
16 status, output = self.target.run(cmd) 18 status, output = self.target.run(cmd)
diff --git a/meta/lib/oeqa/runtime/cases/ldd.py b/meta/lib/oeqa/runtime/cases/ldd.py
index 9c2caa8f65..f6841c6675 100644
--- a/meta/lib/oeqa/runtime/cases/ldd.py
+++ b/meta/lib/oeqa/runtime/cases/ldd.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/login.py b/meta/lib/oeqa/runtime/cases/login.py
new file mode 100644
index 0000000000..e1bc60d49b
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/login.py
@@ -0,0 +1,116 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7import shutil
8import subprocess
9import tempfile
10import time
11import os
12from datetime import datetime
13from oeqa.runtime.case import OERuntimeTestCase
14from oeqa.runtime.decorator.package import OEHasPackage
15
16### Status of qemu images.
17# - runqemu qemuppc64 comes up blank. (skip)
18# - qemuarmv5 comes up with multiple heads but sending "head" to screendump.
19# seems to create a png with a bad header? (skip for now, but come back to fix)
20# - qemuriscv32 and qemuloongarch64 doesn't work with testimage apparently? (skip)
21# - qemumips64 is missing mouse icon.
22# - qemumips takes forever to render and is missing mouse icon.
23# - qemuarm and qemuppc are odd as they don't resize so we need to just set width.
24# - All images have home and screen flipper icons not always rendered fully at first.
25# the sleep seems to help this out some, depending on machine load.
26###
27
28class LoginTest(OERuntimeTestCase):
29 @OEHasPackage(['matchbox-desktop', 'dbus-wait'])
30 def test_screenshot(self):
31 if self.td.get('MACHINE') in ("qemuppc64", "qemuarmv5", "qemuriscv32", "qemuriscv64", "qemuloongarch64"):
32 self.skipTest("{0} is not currently supported.".format(self.td.get('MACHINE')))
33
34 pn = self.td.get('PN')
35
36 ourenv = os.environ.copy()
37 origpath = self.td.get("ORIGPATH")
38 if origpath:
39 ourenv['PATH'] = ourenv['PATH'] + ":" + origpath
40
41 for cmd in ["identify.im7", "convert.im7", "compare.im7"]:
42 try:
43 subprocess.check_output(["which", cmd], env=ourenv)
44 except subprocess.CalledProcessError:
45 self.skipTest("%s (from imagemagick) not available" % cmd)
46
47
48 # Store images so we can debug them if needed
49 saved_screenshots_dir = self.td.get('T') + "/saved-screenshots/"
50
51 ###
52 # This is a really horrible way of doing this but I've not found the
53 # right event to determine "The system is loaded and screen is rendered"
54 #
55 # Using dbus-wait for matchbox is the wrong answer because while it
56 # ensures the system is up, it doesn't mean the screen is rendered.
57 #
58 # Checking the qmp socket doesn't work afaik either.
59 #
60 # One way to do this is to do compares of known good screendumps until
61 # we either get expected or close to expected or we time out. Part of the
62 # issue here with that is that there is a very fine difference in the
63 # diff between a screendump where the icons haven't loaded yet and
64 # one where they won't load. I'll look at that next, but, for now, this.
65 #
66 # Which is ugly and I hate it but it 'works' for various definitions of
67 # 'works'.
68 ###
69 # RP: if the signal is sent before we run this, it will never be seen and we'd timeout
70 #status, output = self.target.run('dbus-wait org.matchbox_project.desktop Loaded')
71 #if status != 0 or "Timeout" in output:
72 # self.fail('dbus-wait failed (%s, %s). This could mean that the image never loaded the matchbox desktop.' % (status, output))
73
74 # Start taking screenshots every 2 seconds until diff=0 or timeout is 60 seconds
75 timeout = time.time() + 60
76 diff = True
77 with tempfile.NamedTemporaryFile(prefix="oeqa-screenshot-login", suffix=".png") as t:
78 while diff != 0 and time.time() < timeout:
79 time.sleep(2)
80 ret = self.target.runner.run_monitor("screendump", args={"filename": t.name, "format":"png"})
81
82 # Find out size of image so we can determine where to blank out clock.
83 # qemuarm and qemuppc are odd as it doesn't resize the window and returns
84 # incorrect widths
85 if self.td.get('MACHINE') == "qemuarm" or self.td.get('MACHINE') == "qemuppc":
86 width = "640"
87 else:
88 cmd = "identify.im7 -ping -format '%w' {0}".format(t.name)
89 width = subprocess.check_output(cmd, shell=True, env=ourenv).decode()
90
91 rblank = int(float(width))
92 lblank = rblank-80
93
94 # Use the meta-oe version of convert, along with it's suffix. This blanks out the clock.
95 cmd = "convert.im7 {0} -fill white -draw 'rectangle {1},4 {2},28' {3}".format(t.name, str(rblank), str(lblank), t.name)
96 convert_out=subprocess.check_output(cmd, shell=True, env=ourenv).decode()
97
98 bb.utils.mkdirhier(saved_screenshots_dir)
99 savedfile = "{0}/saved-{1}-{2}-{3}.png".format(saved_screenshots_dir, \
100 datetime.timestamp(datetime.now()), \
101 pn, \
102 self.td.get('MACHINE'))
103 shutil.copy2(t.name, savedfile)
104
105 refimage = self.td.get('COREBASE') + "/meta/files/screenshot-tests/" + pn + "-" + self.td.get('MACHINE') +".png"
106 if not os.path.exists(refimage):
107 self.skipTest("No reference image for comparision (%s)" % refimage)
108
109 cmd = "compare.im7 -metric MSE {0} {1} /dev/null".format(t.name, refimage)
110 compare_out = subprocess.run(cmd, shell=True, capture_output=True, text=True, env=ourenv)
111 diff=float(compare_out.stderr.replace("(", "").replace(")","").split()[1])
112 if diff > 0:
113 # Keep a copy of the failed screenshot so we can see what happened.
114 self.fail("Screenshot diff is {0}. Failed image stored in {1}".format(str(diff), savedfile))
115 else:
116 self.assertEqual(0, diff, "Screenshot diff is {0}.".format(str(diff)))
diff --git a/meta/lib/oeqa/runtime/cases/logrotate.py b/meta/lib/oeqa/runtime/cases/logrotate.py
index a4efcd07c0..6ad980cb6a 100644
--- a/meta/lib/oeqa/runtime/cases/logrotate.py
+++ b/meta/lib/oeqa/runtime/cases/logrotate.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -17,7 +19,7 @@ class LogrotateTest(OERuntimeTestCase):
17 19
18 @classmethod 20 @classmethod
19 def tearDownClass(cls): 21 def tearDownClass(cls):
20 cls.tc.target.run('mv -f $HOME/wtmp.oeqabak /etc/logrotate.d/wtmp && rm -rf $HOME/logrotate_dir') 22 cls.tc.target.run('mv -f $HOME/wtmp.oeqabak /etc/logrotate.d/wtmp && rm -rf /var/log//logrotate_dir')
21 cls.tc.target.run('rm -rf /var/log/logrotate_testfile && rm -rf /etc/logrotate.d/logrotate_testfile') 23 cls.tc.target.run('rm -rf /var/log/logrotate_testfile && rm -rf /etc/logrotate.d/logrotate_testfile')
22 24
23 @OETestDepends(['ssh.SSHTest.test_ssh']) 25 @OETestDepends(['ssh.SSHTest.test_ssh'])
@@ -29,17 +31,17 @@ class LogrotateTest(OERuntimeTestCase):
29 msg = ('Could not create/update /var/log/wtmp with touch') 31 msg = ('Could not create/update /var/log/wtmp with touch')
30 self.assertEqual(status, 0, msg = msg) 32 self.assertEqual(status, 0, msg = msg)
31 33
32 status, output = self.target.run('mkdir $HOME/logrotate_dir') 34 status, output = self.target.run('mkdir /var/log//logrotate_dir')
33 msg = ('Could not create logrotate_dir. Output: %s' % output) 35 msg = ('Could not create logrotate_dir. Output: %s' % output)
34 self.assertEqual(status, 0, msg = msg) 36 self.assertEqual(status, 0, msg = msg)
35 37
36 status, output = self.target.run('echo "create \n olddir $HOME/logrotate_dir \n include /etc/logrotate.d/wtmp" > /tmp/logrotate-test.conf') 38 status, output = self.target.run('echo "create \n olddir /var/log//logrotate_dir \n include /etc/logrotate.d/wtmp" > /tmp/logrotate-test.conf')
37 msg = ('Could not write to /tmp/logrotate-test.conf') 39 msg = ('Could not write to /tmp/logrotate-test.conf')
38 self.assertEqual(status, 0, msg = msg) 40 self.assertEqual(status, 0, msg = msg)
39 41
40 # If logrotate fails to rotate the log, view the verbose output of logrotate to see what prevented it 42 # If logrotate fails to rotate the log, view the verbose output of logrotate to see what prevented it
41 _, logrotate_output = self.target.run('logrotate -vf /tmp/logrotate-test.conf') 43 _, logrotate_output = self.target.run('logrotate -vf /tmp/logrotate-test.conf')
42 status, _ = self.target.run('find $HOME/logrotate_dir -type f | grep wtmp.1') 44 status, _ = self.target.run('find /var/log//logrotate_dir -type f | grep wtmp.1')
43 msg = ("logrotate did not successfully rotate the wtmp log. Output from logrotate -vf: \n%s" % (logrotate_output)) 45 msg = ("logrotate did not successfully rotate the wtmp log. Output from logrotate -vf: \n%s" % (logrotate_output))
44 self.assertEqual(status, 0, msg = msg) 46 self.assertEqual(status, 0, msg = msg)
45 47
@@ -54,17 +56,17 @@ class LogrotateTest(OERuntimeTestCase):
54 msg = ('Could not write to /etc/logrotate.d/logrotate_testfile') 56 msg = ('Could not write to /etc/logrotate.d/logrotate_testfile')
55 self.assertEqual(status, 0, msg = msg) 57 self.assertEqual(status, 0, msg = msg)
56 58
57 status, output = self.target.run('echo "create \n olddir $HOME/logrotate_dir \n include /etc/logrotate.d/logrotate_testfile" > /tmp/logrotate-test2.conf') 59 status, output = self.target.run('echo "create \n olddir /var/log//logrotate_dir \n include /etc/logrotate.d/logrotate_testfile" > /tmp/logrotate-test2.conf')
58 msg = ('Could not write to /tmp/logrotate_test2.conf') 60 msg = ('Could not write to /tmp/logrotate_test2.conf')
59 self.assertEqual(status, 0, msg = msg) 61 self.assertEqual(status, 0, msg = msg)
60 62
61 status, output = self.target.run('find $HOME/logrotate_dir -type f | grep logrotate_testfile.1') 63 status, output = self.target.run('find /var/log//logrotate_dir -type f | grep logrotate_testfile.1')
62 msg = ('A rotated log for logrotate_testfile is already present in logrotate_dir') 64 msg = ('A rotated log for logrotate_testfile is already present in logrotate_dir')
63 self.assertEqual(status, 1, msg = msg) 65 self.assertEqual(status, 1, msg = msg)
64 66
65 # If logrotate fails to rotate the log, view the verbose output of logrotate instead of just listing the files in olddir 67 # If logrotate fails to rotate the log, view the verbose output of logrotate instead of just listing the files in olddir
66 _, logrotate_output = self.target.run('logrotate -vf /tmp/logrotate-test2.conf') 68 _, logrotate_output = self.target.run('logrotate -vf /tmp/logrotate-test2.conf')
67 status, _ = self.target.run('find $HOME/logrotate_dir -type f | grep logrotate_testfile.1') 69 status, _ = self.target.run('find /var/log//logrotate_dir -type f | grep logrotate_testfile.1')
68 msg = ('logrotate did not successfully rotate the logrotate_test log. Output from logrotate -vf: \n%s' % (logrotate_output)) 70 msg = ('logrotate did not successfully rotate the logrotate_test log. Output from logrotate -vf: \n%s' % (logrotate_output))
69 self.assertEqual(status, 0, msg = msg) 71 self.assertEqual(status, 0, msg = msg)
70 72
diff --git a/meta/lib/oeqa/runtime/cases/ltp.py b/meta/lib/oeqa/runtime/cases/ltp.py
index a66d5d13d7..f588a93200 100644
--- a/meta/lib/oeqa/runtime/cases/ltp.py
+++ b/meta/lib/oeqa/runtime/cases/ltp.py
@@ -57,37 +57,47 @@ class LtpTestBase(OERuntimeTestCase):
57 57
58class LtpTest(LtpTestBase): 58class LtpTest(LtpTestBase):
59 59
60 ltp_groups = ["math", "syscalls", "dio", "io", "mm", "ipc", "sched", "nptl", "pty", "containers", "controllers", "filecaps", "cap_bounds", "fcntl-locktests", "connectors", "commands", "net.ipv6_lib", "input","fs_perms_simple"] 60 ltp_groups = ["math", "syscalls", "dio", "io", "mm", "ipc", "sched", "nptl", "pty", "containers", "controllers", "filecaps", "cap_bounds", "fcntl-locktests", "commands", "net.ipv6_lib", "input","fs_perms_simple", "cve", "crypto", "ima", "net.nfs", "net_stress.ipsec_icmp", "net.ipv6", "numa", "uevent", "ltp-aiodio.part1", "ltp-aiodio.part2", "ltp-aiodio.part3", "ltp-aiodio.part4"]
61 61
62 ltp_fs = ["fs", "fsx", "fs_bind"] 62 ltp_fs = ["fs", "fs_bind"]
63 # skip kernel cpuhotplug 63 # skip kernel cpuhotplug
64 ltp_kernel = ["power_management_tests", "hyperthreading ", "kernel_misc", "hugetlb"] 64 ltp_kernel = ["power_management_tests", "hyperthreading ", "kernel_misc", "hugetlb"]
65 ltp_groups += ltp_fs 65 ltp_groups += ltp_fs
66 66
67 def runltp(self, ltp_group): 67 def runltp(self, ltp_group):
68 cmd = '/opt/ltp/runltp -f %s -p -q -r /opt/ltp -l /opt/ltp/results/%s -I 1 -d /opt/ltp' % (ltp_group, ltp_group) 68 # LTP appends to log files, so ensure we start with a clean log
69 self.target.deleteFiles("/opt/ltp/results/", ltp_group)
70
71 cmd = '/opt/ltp/runltp -f %s -q -r /opt/ltp -l /opt/ltp/results/%s -I 1 -d /opt/ltp' % (ltp_group, ltp_group)
72
69 starttime = time.time() 73 starttime = time.time()
70 (status, output) = self.target.run(cmd) 74 (status, output) = self.target.run(cmd, timeout=1200)
71 endtime = time.time() 75 endtime = time.time()
72 76
77 # status of 1 is 'just' tests failing. 255 likely was a command output timeout
78 if status and status != 1:
79 msg = 'Command %s returned exit code %s' % (cmd, status)
80 self.target.logger.warning(msg)
81
82 # Write the console log to disk for convenience
73 with open(os.path.join(self.ltptest_log_dir, "%s-raw.log" % ltp_group), 'w') as f: 83 with open(os.path.join(self.ltptest_log_dir, "%s-raw.log" % ltp_group), 'w') as f:
74 f.write(output) 84 f.write(output)
75 85
86 # Also put the console log into the test result JSON
76 self.extras['ltpresult.rawlogs']['log'] = self.extras['ltpresult.rawlogs']['log'] + output 87 self.extras['ltpresult.rawlogs']['log'] = self.extras['ltpresult.rawlogs']['log'] + output
77 88
78 # copy nice log from DUT 89 # Copy the machine-readable test results locally so we can parse it
79 dst = os.path.join(self.ltptest_log_dir, "%s" % ltp_group ) 90 dst = os.path.join(self.ltptest_log_dir, ltp_group)
80 remote_src = "/opt/ltp/results/%s" % ltp_group 91 remote_src = "/opt/ltp/results/%s" % ltp_group
81 (status, output) = self.target.copyFrom(remote_src, dst, True) 92 (status, output) = self.target.copyFrom(remote_src, dst, True)
82 msg = 'File could not be copied. Output: %s' % output
83 if status: 93 if status:
94 msg = 'File could not be copied. Output: %s' % output
84 self.target.logger.warning(msg) 95 self.target.logger.warning(msg)
85 96
86 parser = LtpParser() 97 parser = LtpParser()
87 results, sections = parser.parse(dst) 98 results, sections = parser.parse(dst)
88 99
89 runtime = int(endtime-starttime) 100 sections['duration'] = int(endtime-starttime)
90 sections['duration'] = runtime
91 self.sections[ltp_group] = sections 101 self.sections[ltp_group] = sections
92 102
93 failed_tests = {} 103 failed_tests = {}
diff --git a/meta/lib/oeqa/runtime/cases/ltp_stress.py b/meta/lib/oeqa/runtime/cases/ltp_stress.py
index 2445ffbc93..ce6f4bf59d 100644
--- a/meta/lib/oeqa/runtime/cases/ltp_stress.py
+++ b/meta/lib/oeqa/runtime/cases/ltp_stress.py
@@ -89,8 +89,7 @@ class LtpStressTest(LtpStressBase):
89 89
90 # LTP stress runtime tests 90 # LTP stress runtime tests
91 # 91 #
92 @skipIfQemu('qemuall', 'Test only runs on real hardware') 92 @skipIfQemu()
93
94 @OETestDepends(['ssh.SSHTest.test_ssh']) 93 @OETestDepends(['ssh.SSHTest.test_ssh'])
95 @OEHasPackage(["ltp"]) 94 @OEHasPackage(["ltp"])
96 def test_ltp_stress(self): 95 def test_ltp_stress(self):
diff --git a/meta/lib/oeqa/runtime/cases/maturin.py b/meta/lib/oeqa/runtime/cases/maturin.py
new file mode 100644
index 0000000000..4e6384fe5e
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/maturin.py
@@ -0,0 +1,58 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7import os
8
9from oeqa.runtime.case import OERuntimeTestCase
10from oeqa.core.decorator.depends import OETestDepends
11from oeqa.runtime.decorator.package import OEHasPackage
12
13
14class MaturinTest(OERuntimeTestCase):
15 @OETestDepends(['ssh.SSHTest.test_ssh', 'python.PythonTest.test_python3'])
16 @OEHasPackage(['python3-maturin'])
17 def test_maturin_list_python(self):
18 status, output = self.target.run("maturin list-python")
19 self.assertEqual(status, 0)
20 _, py_major = self.target.run("python3 -c 'import sys; print(sys.version_info.major)'")
21 _, py_minor = self.target.run("python3 -c 'import sys; print(sys.version_info.minor)'")
22 python_version = "%s.%s" % (py_major, py_minor)
23 self.assertEqual(output, "🐍 1 python interpreter found:\n"
24 " - CPython %s at /usr/bin/python%s" % (python_version, python_version))
25
26
27class MaturinDevelopTest(OERuntimeTestCase):
28 @classmethod
29 def setUp(cls):
30 dst = '/tmp'
31 src = os.path.join(cls.tc.files_dir, "maturin/guessing-game")
32 cls.tc.target.copyTo(src, dst)
33
34 @classmethod
35 def tearDown(cls):
36 cls.tc.target.run('rm -rf %s' % '/tmp/guessing-game/target')
37
38 @OETestDepends(['ssh.SSHTest.test_ssh', 'python.PythonTest.test_python3'])
39 @OEHasPackage(['python3-maturin'])
40 def test_maturin_develop(self):
41 """
42 This test case requires:
43 (1) that a .venv can been created.
44 (2) DNS nameserver to resolve crate URIs for fetching
45 (3) a functional 'rustc' and 'cargo'
46 """
47 targetdir = os.path.join("/tmp", "guessing-game")
48 self.target.run("cd %s; python3 -m venv .venv" % targetdir)
49 self.target.run("echo 'nameserver 8.8.8.8' > /etc/resolv.conf")
50 cmd = "cd %s; maturin develop" % targetdir
51 status, output = self.target.run(cmd)
52 self.assertRegex(output, r"🔗 Found pyo3 bindings with abi3 support for Python ≥ 3.8")
53 self.assertRegex(output, r"🐍 Not using a specific python interpreter")
54 self.assertRegex(output, r"📡 Using build options features from pyproject.toml")
55 self.assertRegex(output, r"Compiling guessing-game v0.1.0")
56 self.assertRegex(output, r"📦 Built wheel for abi3 Python ≥ 3.8")
57 self.assertRegex(output, r"🛠 Installed guessing-game-0.1.0")
58 self.assertEqual(status, 0)
diff --git a/meta/lib/oeqa/runtime/cases/multilib.py b/meta/lib/oeqa/runtime/cases/multilib.py
index 0d1b9ae2c9..68556e45c5 100644
--- a/meta/lib/oeqa/runtime/cases/multilib.py
+++ b/meta/lib/oeqa/runtime/cases/multilib.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/oe_syslog.py b/meta/lib/oeqa/runtime/cases/oe_syslog.py
index f3c2bedbaf..adb876160d 100644
--- a/meta/lib/oeqa/runtime/cases/oe_syslog.py
+++ b/meta/lib/oeqa/runtime/cases/oe_syslog.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -114,18 +116,23 @@ class SyslogTestConfig(OERuntimeTestCase):
114 @OETestDepends(['oe_syslog.SyslogTestConfig.test_syslog_logger']) 116 @OETestDepends(['oe_syslog.SyslogTestConfig.test_syslog_logger'])
115 @OEHasPackage(["busybox-syslog"]) 117 @OEHasPackage(["busybox-syslog"])
116 @skipIfDataVar('VIRTUAL-RUNTIME_init_manager', 'systemd', 118 @skipIfDataVar('VIRTUAL-RUNTIME_init_manager', 'systemd',
117 'Not appropiate for systemd image') 119 'Not appropriate for systemd image')
118 def test_syslog_startup_config(self): 120 def test_syslog_startup_config(self):
119 cmd = 'echo "LOGFILE=/var/log/test" >> /etc/syslog-startup.conf' 121 cmd = 'echo "LOGFILE=/var/log/test" >> /etc/syslog-startup.conf'
120 self.target.run(cmd) 122 self.target.run(cmd)
121 123
122 self.test_syslog_restart() 124 self.test_syslog_restart()
123 125
124 cmd = 'logger foobar && grep foobar /var/log/test' 126 cmd = 'logger foobar'
125 status,output = self.target.run(cmd) 127 status, output = self.target.run(cmd)
126 msg = 'Test log string not found. Output: %s ' % output 128 msg = 'Logger command failed, %s. Output: %s ' % (status, output)
127 self.assertEqual(status, 0, msg=msg) 129 self.assertEqual(status, 0, msg=msg)
128 130
131 cmd = 'cat /var/log/test'
132 status, output = self.target.run(cmd)
133 if "foobar" not in output or status:
134 self.fail("'foobar' not found in logfile, status %s, contents %s" % (status, output))
135
129 cmd = "sed -i 's#LOGFILE=/var/log/test##' /etc/syslog-startup.conf" 136 cmd = "sed -i 's#LOGFILE=/var/log/test##' /etc/syslog-startup.conf"
130 self.target.run(cmd) 137 self.target.run(cmd)
131 self.test_syslog_restart() 138 self.test_syslog_restart()
diff --git a/meta/lib/oeqa/runtime/cases/opkg.py b/meta/lib/oeqa/runtime/cases/opkg.py
index 9cfee1cd88..a29c93e59a 100644
--- a/meta/lib/oeqa/runtime/cases/opkg.py
+++ b/meta/lib/oeqa/runtime/cases/opkg.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/pam.py b/meta/lib/oeqa/runtime/cases/pam.py
index a482ded945..b3e8b56c3c 100644
--- a/meta/lib/oeqa/runtime/cases/pam.py
+++ b/meta/lib/oeqa/runtime/cases/pam.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/parselogs-ignores-common.txt b/meta/lib/oeqa/runtime/cases/parselogs-ignores-common.txt
new file mode 100644
index 0000000000..f91abbc941
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/parselogs-ignores-common.txt
@@ -0,0 +1,62 @@
1# Xserver explains what the short codes mean
2(WW) warning, (EE) error, (NI) not implemented, (??) unknown.
3
4# Xserver warns if compiled with ACPI but no acpid running
5Open ACPI failed (/var/run/acpid.socket) (No such file or directory)
6
7# Some machines (eg qemux86) don't enable PAE (they probably should though)
8NX (Execute Disable) protection cannot be enabled: non-PAE kernel!
9
10# Connman's pacrunner warns if external connectivity isn't available
11Failed to find URL:http://ipv4.connman.net/online/status.html
12Failed to find URL:http://ipv6.connman.net/online/status.html
13
14# x86 on 6.6+ outputs this message, it is informational, not an error
15ACPI: _OSC evaluation for CPUs failed, trying _PDC
16
17# These should be reviewed to see if they are still needed
18dma timeout
19can\'t add hid device:
20usbhid: probe of
21_OSC failed (AE_ERROR)
22_OSC failed (AE_SUPPORT)
23AE_ALREADY_EXISTS
24ACPI _OSC request failed (AE_SUPPORT)
25can\'t disable ASPM
26Failed to load module "vesa"
27Failed to load module "modesetting"
28Failed to load module "glx"
29Failed to load module "fbdev"
30Failed to load module "ati"
31[drm] Cannot find any crtc or sizes
32_OSC failed (AE_NOT_FOUND); disabling ASPM
33hd.: possibly failed opcode
34NETLINK INITIALIZATION FAILED
35kernel: Cannot find map file
36omap_hwmod: debugss: _wait_target_disable failed
37VGA arbiter: cannot open kernel arbiter, no multi-card support
38Online check failed for
39netlink init failed
40Fast TSC calibration
41controller can't do DEVSLP, turning off
42stmmac_dvr_probe: warning: cannot get CSR clock
43error: couldn\'t mount because of unsupported optional features
44GPT: Use GNU Parted to correct GPT errors
45Cannot set xattr user.Librepo.DownloadInProgress
46Failed to read /var/lib/nfs/statd/state: Success
47error retry time-out =
48logind: cannot setup systemd-logind helper (-61), using legacy fallback
49Failed to rename network interface
50Failed to process device, ignoring: Device or resource busy
51Cannot find a map file
52[rdrand]: Initialization Failed
53[rndr ]: Initialization Failed
54[pulseaudio] authkey.c: Failed to open cookie file
55[pulseaudio] authkey.c: Failed to load authentication key
56was skipped because of a failed condition check
57was skipped because all trigger condition checks failed
58xf86OpenConsole: Switching VT failed
59Failed to read LoaderConfigTimeoutOneShot variable, ignoring: Operation not supported
60Failed to read LoaderEntryOneShot variable, ignoring: Operation not supported
61Direct firmware load for regulatory.db
62failed to load regulatory.db
diff --git a/meta/lib/oeqa/runtime/cases/parselogs-ignores-mipsarch.txt b/meta/lib/oeqa/runtime/cases/parselogs-ignores-mipsarch.txt
new file mode 100644
index 0000000000..2c0bd9a247
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/parselogs-ignores-mipsarch.txt
@@ -0,0 +1,2 @@
1# These should be reviewed to see if they are still needed
2cacheinfo: Failed to find cpu0 device node
diff --git a/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuall.txt b/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuall.txt
new file mode 100644
index 0000000000..b0c0fc9ddf
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuall.txt
@@ -0,0 +1,27 @@
1# psplash
2FBIOPUT_VSCREENINFO failed, double buffering disabled
3
4# PCI host bridge to bus 0000:00
5# pci_bus 0000:00: root bus resource [mem 0x10000000-0x17ffffff]
6# pci_bus 0000:00: root bus resource [io 0x1000-0x1fffff]
7# pci_bus 0000:00: No busn resource found for root bus, will use [bus 00-ff]
8# pci 0000:00:00.0: [2046:ab11] type 00 class 0x100000
9# pci 0000:00:00.0: [Firmware Bug]: reg 0x10: invalid BAR (can't size)
10# pci 0000:00:00.0: [Firmware Bug]: reg 0x14: invalid BAR (can't size)
11# pci 0000:00:00.0: [Firmware Bug]: reg 0x18: invalid BAR (can't size)
12# pci 0000:00:00.0: [Firmware Bug]: reg 0x1c: invalid BAR (can't size)
13# pci 0000:00:00.0: [Firmware Bug]: reg 0x20: invalid BAR (can't size)
14# pci 0000:00:00.0: [Firmware Bug]: reg 0x24: invalid BAR (can't size)
15invalid BAR (can't size)
16
17# These should be reviewed to see if they are still needed
18wrong ELF class
19fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge
20can't claim BAR
21amd_nb: Cannot enumerate AMD northbridges
22tsc: HPET/PMTIMER calibration failed
23modeset(0): Failed to initialize the DRI2 extension
24glamor initialization failed
25blk_update_request: I/O error, dev fd0, sector 0 op 0x0:(READ)
26floppy: error
27failed to IDENTIFY (I/O error, err_mask=0x4)
diff --git a/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuarm64.txt b/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuarm64.txt
new file mode 100644
index 0000000000..260cdde620
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuarm64.txt
@@ -0,0 +1,6 @@
1# These should be reviewed to see if they are still needed
2Fatal server error:
3(EE) Server terminated with error (1). Closing log file.
4dmi: Firmware registration failed.
5irq: type mismatch, failed to map hwirq-27 for /intc
6logind: failed to get session seat \ No newline at end of file
diff --git a/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuarmv5.txt b/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuarmv5.txt
new file mode 100644
index 0000000000..ed91107b7d
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuarmv5.txt
@@ -0,0 +1,19 @@
1# Code is 2 JENT_ECOARSETIME: Timer too coarse for RNG.
2jitterentropy: Initialization failed with host not compliant with requirements: 2
3
4# These should be reviewed to see if they are still needed
5mmci-pl18x: probe of fpga:05 failed with error -22
6mmci-pl18x: probe of fpga:0b failed with error -22
7
8OF: amba_device_add() failed (-19) for /amba/smc@10100000
9OF: amba_device_add() failed (-19) for /amba/mpmc@10110000
10OF: amba_device_add() failed (-19) for /amba/sctl@101e0000
11OF: amba_device_add() failed (-19) for /amba/watchdog@101e1000
12OF: amba_device_add() failed (-19) for /amba/sci@101f0000
13OF: amba_device_add() failed (-19) for /amba/spi@101f4000
14OF: amba_device_add() failed (-19) for /amba/ssp@101f4000
15OF: amba_device_add() failed (-19) for /amba/fpga/sci@a000
16Failed to initialize '/amba/timer@101e3000': -22
17
18clcd-pl11x: probe of 10120000.display failed with error -2
19arm-charlcd 10008000.lcd: error -ENXIO: IRQ index 0 not found
diff --git a/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuppc.txt b/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuppc.txt
new file mode 100644
index 0000000000..d9b58b58f1
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuppc.txt
@@ -0,0 +1,6 @@
1# These should be reviewed to see if they are still needed
2PCI 0000:00 Cannot reserve Legacy IO [io 0x0000-0x0fff]
3host side 80-wire cable detection failed, limiting max speed
4mode "640x480" test failed
5can't handle BAR above 4GB
6Cannot reserve Legacy IO \ No newline at end of file
diff --git a/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuppc64.txt b/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuppc64.txt
new file mode 100644
index 0000000000..b736a2aeb7
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemuppc64.txt
@@ -0,0 +1,4 @@
1# These should be reviewed to see if they are still needed
2vio vio: uevent: failed to send synthetic uevent
3synth uevent: /devices/vio: failed to send uevent
4PCI 0000:00 Cannot reserve Legacy IO [io 0x10000-0x10fff] \ No newline at end of file
diff --git a/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemux86.txt b/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemux86.txt
new file mode 100644
index 0000000000..ebb76f1221
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/parselogs-ignores-qemux86.txt
@@ -0,0 +1,2 @@
1# These should be reviewed to see if they are still needed
2Failed to access perfctr msr (MSR
diff --git a/meta/lib/oeqa/runtime/cases/parselogs-ignores-x86.txt b/meta/lib/oeqa/runtime/cases/parselogs-ignores-x86.txt
new file mode 100644
index 0000000000..5985247daf
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/parselogs-ignores-x86.txt
@@ -0,0 +1,10 @@
1# These should be reviewed to see if they are still needed
2[drm:psb_do_init] *ERROR* Debug is
3wrong ELF class
4Could not enable PowerButton event
5probe of LNXPWRBN:00 failed with error -22
6pmd_set_huge: Cannot satisfy
7failed to setup card detect gpio
8amd_nb: Cannot enumerate AMD northbridges
9failed to retrieve link info, disabling eDP
10Direct firmware load for iwlwifi
diff --git a/meta/lib/oeqa/runtime/cases/parselogs-ignores-x86_64.txt b/meta/lib/oeqa/runtime/cases/parselogs-ignores-x86_64.txt
new file mode 120000
index 0000000000..404e384c32
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/parselogs-ignores-x86_64.txt
@@ -0,0 +1 @@
parselogs-ignores-x86.txt \ No newline at end of file
diff --git a/meta/lib/oeqa/runtime/cases/parselogs.py b/meta/lib/oeqa/runtime/cases/parselogs.py
index a1791b5cca..6966923c94 100644
--- a/meta/lib/oeqa/runtime/cases/parselogs.py
+++ b/meta/lib/oeqa/runtime/cases/parselogs.py
@@ -1,204 +1,49 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
7import collections
5import os 8import os
9import sys
6 10
7from subprocess import check_output
8from shutil import rmtree 11from shutil import rmtree
9from oeqa.runtime.case import OERuntimeTestCase 12from oeqa.runtime.case import OERuntimeTestCase
10from oeqa.core.decorator.depends import OETestDepends 13from oeqa.core.decorator.depends import OETestDepends
11from oeqa.core.decorator.data import skipIfDataVar
12from oeqa.runtime.decorator.package import OEHasPackage
13
14#in the future these lists could be moved outside of module
15errors = ["error", "cannot", "can\'t", "failed"]
16
17common_errors = [
18 "(WW) warning, (EE) error, (NI) not implemented, (??) unknown.",
19 "dma timeout",
20 "can\'t add hid device:",
21 "usbhid: probe of ",
22 "_OSC failed (AE_ERROR)",
23 "_OSC failed (AE_SUPPORT)",
24 "AE_ALREADY_EXISTS",
25 "ACPI _OSC request failed (AE_SUPPORT)",
26 "can\'t disable ASPM",
27 "Failed to load module \"vesa\"",
28 "Failed to load module vesa",
29 "Failed to load module \"modesetting\"",
30 "Failed to load module modesetting",
31 "Failed to load module \"glx\"",
32 "Failed to load module \"fbdev\"",
33 "Failed to load module fbdev",
34 "Failed to load module glx",
35 "[drm] Cannot find any crtc or sizes - going 1024x768",
36 "_OSC failed (AE_NOT_FOUND); disabling ASPM",
37 "Open ACPI failed (/var/run/acpid.socket) (No such file or directory)",
38 "NX (Execute Disable) protection cannot be enabled: non-PAE kernel!",
39 "hd.: possibly failed opcode",
40 'NETLINK INITIALIZATION FAILED',
41 'kernel: Cannot find map file',
42 'omap_hwmod: debugss: _wait_target_disable failed',
43 'VGA arbiter: cannot open kernel arbiter, no multi-card support',
44 'Failed to find URL:http://ipv4.connman.net/online/status.html',
45 'Online check failed for',
46 'netlink init failed',
47 'Fast TSC calibration',
48 "BAR 0-9",
49 "Failed to load module \"ati\"",
50 "controller can't do DEVSLP, turning off",
51 "stmmac_dvr_probe: warning: cannot get CSR clock",
52 "error: couldn\'t mount because of unsupported optional features",
53 "GPT: Use GNU Parted to correct GPT errors",
54 "Cannot set xattr user.Librepo.DownloadInProgress",
55 "Failed to read /var/lib/nfs/statd/state: Success",
56 "error retry time-out =",
57 "logind: cannot setup systemd-logind helper (-61), using legacy fallback",
58 "Failed to rename network interface",
59 "Failed to process device, ignoring: Device or resource busy",
60 "Cannot find a map file",
61 "[rdrand]: Initialization Failed",
62 "[pulseaudio] authkey.c: Failed to open cookie file",
63 "[pulseaudio] authkey.c: Failed to load authentication key",
64 ]
65 14
66video_related = [ 15# importlib.resources.open_text in Python <3.10 doesn't search all directories
67] 16# when a package is split across multiple directories. Until we can rely on
17# 3.10+, reimplement the searching logic.
18if sys.version_info < (3, 10):
19 def _open_text(package, resource):
20 import importlib, pathlib
21 module = importlib.import_module(package)
22 for path in module.__path__:
23 candidate = pathlib.Path(path) / resource
24 if candidate.exists():
25 return candidate.open(encoding='utf-8')
26 raise FileNotFoundError
27else:
28 from importlib.resources import open_text as _open_text
68 29
69x86_common = [
70 '[drm:psb_do_init] *ERROR* Debug is',
71 'wrong ELF class',
72 'Could not enable PowerButton event',
73 'probe of LNXPWRBN:00 failed with error -22',
74 'pmd_set_huge: Cannot satisfy',
75 'failed to setup card detect gpio',
76 'amd_nb: Cannot enumerate AMD northbridges',
77 'failed to retrieve link info, disabling eDP',
78 'Direct firmware load for iwlwifi',
79 'Direct firmware load for regulatory.db',
80 'failed to load regulatory.db',
81] + common_errors
82 30
83qemux86_common = [ 31class ParseLogsTest(OERuntimeTestCase):
84 'wrong ELF class',
85 "fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge.",
86 "can't claim BAR ",
87 'amd_nb: Cannot enumerate AMD northbridges',
88 'tsc: HPET/PMTIMER calibration failed',
89 "modeset(0): Failed to initialize the DRI2 extension",
90 "glamor initialization failed",
91] + common_errors
92 32
93ignore_errors = { 33 # Which log files should be collected
94 'default' : common_errors, 34 log_locations = ["/var/log/", "/var/log/dmesg", "/tmp/dmesg_output.log"]
95 'qemux86' : [
96 'Failed to access perfctr msr (MSR',
97 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
98 ] + qemux86_common,
99 'qemux86-64' : qemux86_common,
100 'qemumips' : [
101 'Failed to load module "glx"',
102 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
103 'cacheinfo: Failed to find cpu0 device node',
104 ] + common_errors,
105 'qemumips64' : [
106 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
107 'cacheinfo: Failed to find cpu0 device node',
108 ] + common_errors,
109 'qemuppc' : [
110 'PCI 0000:00 Cannot reserve Legacy IO [io 0x0000-0x0fff]',
111 'host side 80-wire cable detection failed, limiting max speed',
112 'mode "640x480" test failed',
113 'Failed to load module "glx"',
114 'can\'t handle BAR above 4GB',
115 'Cannot reserve Legacy IO',
116 ] + common_errors,
117 'qemuarm' : [
118 'mmci-pl18x: probe of fpga:05 failed with error -22',
119 'mmci-pl18x: probe of fpga:0b failed with error -22',
120 'Failed to load module "glx"',
121 'OF: amba_device_add() failed (-19) for /amba/smc@10100000',
122 'OF: amba_device_add() failed (-19) for /amba/mpmc@10110000',
123 'OF: amba_device_add() failed (-19) for /amba/sctl@101e0000',
124 'OF: amba_device_add() failed (-19) for /amba/watchdog@101e1000',
125 'OF: amba_device_add() failed (-19) for /amba/sci@101f0000',
126 'OF: amba_device_add() failed (-19) for /amba/spi@101f4000',
127 'OF: amba_device_add() failed (-19) for /amba/ssp@101f4000',
128 'OF: amba_device_add() failed (-19) for /amba/fpga/sci@a000',
129 'Failed to initialize \'/amba/timer@101e3000\': -22',
130 'jitterentropy: Initialization failed with host not compliant with requirements: 2',
131 ] + common_errors,
132 'qemuarm64' : [
133 'Fatal server error:',
134 '(EE) Server terminated with error (1). Closing log file.',
135 'dmi: Firmware registration failed.',
136 'irq: type mismatch, failed to map hwirq-27 for /intc',
137 'logind: failed to get session seat',
138 ] + common_errors,
139 'intel-core2-32' : [
140 'ACPI: No _BQC method, cannot determine initial brightness',
141 '[Firmware Bug]: ACPI: No _BQC method, cannot determine initial brightness',
142 '(EE) Failed to load module "psb"',
143 '(EE) Failed to load module psb',
144 '(EE) Failed to load module "psbdrv"',
145 '(EE) Failed to load module psbdrv',
146 '(EE) open /dev/fb0: No such file or directory',
147 '(EE) AIGLX: reverting to software rendering',
148 'dmi: Firmware registration failed.',
149 'ioremap error for 0x78',
150 ] + x86_common,
151 'intel-corei7-64' : [
152 'can\'t set Max Payload Size to 256',
153 'intel_punit_ipc: can\'t request region for resource',
154 '[drm] parse error at position 4 in video mode \'efifb\'',
155 'ACPI Error: Could not enable RealTimeClock event',
156 'ACPI Warning: Could not enable fixed event - RealTimeClock',
157 'hci_intel INT33E1:00: Unable to retrieve gpio',
158 'hci_intel: probe of INT33E1:00 failed',
159 'can\'t derive routing for PCI INT A',
160 'failed to read out thermal zone',
161 'Bluetooth: hci0: Setting Intel event mask failed',
162 'ttyS2 - failed to request DMA',
163 'Bluetooth: hci0: Failed to send firmware data (-38)',
164 'atkbd serio0: Failed to enable keyboard on isa0060/serio0',
165 ] + x86_common,
166 'genericx86' : x86_common,
167 'genericx86-64' : [
168 'Direct firmware load for i915',
169 'Failed to load firmware i915',
170 'Failed to fetch GuC',
171 'Failed to initialize GuC',
172 'Failed to load DMC firmware',
173 'The driver is built-in, so to load the firmware you need to',
174 ] + x86_common,
175 'edgerouter' : [
176 'not creating \'/sys/firmware/fdt\'',
177 'Failed to find cpu0 device node',
178 'Fatal server error:',
179 'Server terminated with error',
180 ] + common_errors,
181 'beaglebone-yocto' : [
182 'Direct firmware load for regulatory.db',
183 'failed to load regulatory.db',
184 'l4_wkup_cm',
185 'Failed to load module "glx"',
186 'Failed to make EGL context current',
187 'glamor initialization failed',
188 ] + common_errors,
189}
190 35
191log_locations = ["/var/log/","/var/log/dmesg", "/tmp/dmesg_output.log"] 36 # The keywords that identify error messages in the log files
37 errors = ["error", "cannot", "can't", "failed"]
192 38
193class ParseLogsTest(OERuntimeTestCase): 39 # A list of error messages that should be ignored
40 ignore_errors = []
194 41
195 @classmethod 42 @classmethod
196 def setUpClass(cls): 43 def setUpClass(cls):
197 cls.errors = errors
198
199 # When systemd is enabled we need to notice errors on 44 # When systemd is enabled we need to notice errors on
200 # circular dependencies in units. 45 # circular dependencies in units.
201 if 'systemd' in cls.td.get('DISTRO_FEATURES', ''): 46 if 'systemd' in cls.td.get('DISTRO_FEATURES'):
202 cls.errors.extend([ 47 cls.errors.extend([
203 'Found ordering cycle on', 48 'Found ordering cycle on',
204 'Breaking ordering cycle by deleting job', 49 'Breaking ordering cycle by deleting job',
@@ -206,48 +51,22 @@ class ParseLogsTest(OERuntimeTestCase):
206 'Ordering cycle found, skipping', 51 'Ordering cycle found, skipping',
207 ]) 52 ])
208 53
209 cls.ignore_errors = ignore_errors 54 cls.errors = [s.casefold() for s in cls.errors]
210 cls.log_locations = log_locations
211 cls.msg = ''
212 is_lsb, _ = cls.tc.target.run("which LSB_Test.sh")
213 if is_lsb == 0:
214 for machine in cls.ignore_errors:
215 cls.ignore_errors[machine] = cls.ignore_errors[machine] \
216 + video_related
217
218 def getMachine(self):
219 return self.td.get('MACHINE', '')
220
221 def getWorkdir(self):
222 return self.td.get('WORKDIR', '')
223
224 # Get some information on the CPU of the machine to display at the
225 # beginning of the output. This info might be useful in some cases.
226 def getHardwareInfo(self):
227 hwi = ""
228 cmd = ('cat /proc/cpuinfo | grep "model name" | head -n1 | '
229 " awk 'BEGIN{FS=\":\"}{print $2}'")
230 _, cpu_name = self.target.run(cmd)
231
232 cmd = ('cat /proc/cpuinfo | grep "cpu cores" | head -n1 | '
233 "awk {'print $4'}")
234 _, cpu_physical_cores = self.target.run(cmd)
235
236 cmd = 'cat /proc/cpuinfo | grep "processor" | wc -l'
237 _, cpu_logical_cores = self.target.run(cmd)
238
239 _, cpu_arch = self.target.run('uname -m')
240 55
241 hwi += 'Machine information: \n' 56 cls.load_machine_ignores()
242 hwi += '*******************************\n'
243 hwi += 'Machine name: ' + self.getMachine() + '\n'
244 hwi += 'CPU: ' + str(cpu_name) + '\n'
245 hwi += 'Arch: ' + str(cpu_arch)+ '\n'
246 hwi += 'Physical cores: ' + str(cpu_physical_cores) + '\n'
247 hwi += 'Logical cores: ' + str(cpu_logical_cores) + '\n'
248 hwi += '*******************************\n'
249 57
250 return hwi 58 @classmethod
59 def load_machine_ignores(cls):
60 # Add TARGET_ARCH explicitly as not every machine has that in MACHINEOVERRDES (eg qemux86-64)
61 for candidate in ["common", cls.td.get("TARGET_ARCH")] + cls.td.get("MACHINEOVERRIDES").split(":"):
62 try:
63 name = f"parselogs-ignores-{candidate}.txt"
64 for line in _open_text("oeqa.runtime.cases", name):
65 line = line.strip()
66 if line and not line.startswith("#"):
67 cls.ignore_errors.append(line.casefold())
68 except FileNotFoundError:
69 pass
251 70
252 # Go through the log locations provided and if it's a folder 71 # Go through the log locations provided and if it's a folder
253 # create a list with all the .log files in it, if it's a file 72 # create a list with all the .log files in it, if it's a file
@@ -255,23 +74,23 @@ class ParseLogsTest(OERuntimeTestCase):
255 def getLogList(self, log_locations): 74 def getLogList(self, log_locations):
256 logs = [] 75 logs = []
257 for location in log_locations: 76 for location in log_locations:
258 status, _ = self.target.run('test -f ' + str(location)) 77 status, _ = self.target.run('test -f %s' % location)
259 if status == 0: 78 if status == 0:
260 logs.append(str(location)) 79 logs.append(location)
261 else: 80 else:
262 status, _ = self.target.run('test -d ' + str(location)) 81 status, _ = self.target.run('test -d %s' % location)
263 if status == 0: 82 if status == 0:
264 cmd = 'find ' + str(location) + '/*.log -maxdepth 1 -type f' 83 cmd = 'find %s -name \\*.log -maxdepth 1 -type f' % location
265 status, output = self.target.run(cmd) 84 status, output = self.target.run(cmd)
266 if status == 0: 85 if status == 0:
267 output = output.splitlines() 86 output = output.splitlines()
268 for logfile in output: 87 for logfile in output:
269 logs.append(os.path.join(location, str(logfile))) 88 logs.append(os.path.join(location, logfile))
270 return logs 89 return logs
271 90
272 # Copy the log files to be parsed locally 91 # Copy the log files to be parsed locally
273 def transfer_logs(self, log_list): 92 def transfer_logs(self, log_list):
274 workdir = self.getWorkdir() 93 workdir = self.td.get('WORKDIR')
275 self.target_logs = workdir + '/' + 'target_logs' 94 self.target_logs = workdir + '/' + 'target_logs'
276 target_logs = self.target_logs 95 target_logs = self.target_logs
277 if os.path.exists(target_logs): 96 if os.path.exists(target_logs):
@@ -288,65 +107,55 @@ class ParseLogsTest(OERuntimeTestCase):
288 logs = [f for f in dir_files if os.path.isfile(f)] 107 logs = [f for f in dir_files if os.path.isfile(f)]
289 return logs 108 return logs
290 109
291 # Build the grep command to be used with filters and exclusions 110 def get_context(self, lines, index, before=6, after=3):
292 def build_grepcmd(self, errors, ignore_errors, log): 111 """
293 grepcmd = 'grep ' 112 Given a set of lines and the index of the line that is important, return
294 grepcmd += '-Ei "' 113 a number of lines surrounding that line.
295 for error in errors: 114 """
296 grepcmd += '\<' + error + '\>' + '|' 115 last = len(lines)
297 grepcmd = grepcmd[:-1] 116
298 grepcmd += '" ' + str(log) + " | grep -Eiv \'" 117 start = index - before
299 118 end = index + after + 1
300 try: 119
301 errorlist = ignore_errors[self.getMachine()] 120 if start < 0:
302 except KeyError: 121 end -= start
303 self.msg += 'No ignore list found for this machine, using default\n' 122 start = 0
304 errorlist = ignore_errors['default'] 123 if end > last:
305 124 start -= end - last
306 for ignore_error in errorlist: 125 end = last
307 ignore_error = ignore_error.replace('(', '\(') 126
308 ignore_error = ignore_error.replace(')', '\)') 127 return lines[start:end]
309 ignore_error = ignore_error.replace("'", '.') 128
310 ignore_error = ignore_error.replace('?', '\?') 129 def test_get_context(self):
311 ignore_error = ignore_error.replace('[', '\[') 130 """
312 ignore_error = ignore_error.replace(']', '\]') 131 A test case for the test case.
313 ignore_error = ignore_error.replace('*', '\*') 132 """
314 ignore_error = ignore_error.replace('0-9', '[0-9]') 133 lines = list(range(0,10))
315 grepcmd += ignore_error + '|' 134 self.assertEqual(self.get_context(lines, 0, 2, 1), [0, 1, 2, 3])
316 grepcmd = grepcmd[:-1] 135 self.assertEqual(self.get_context(lines, 5, 2, 1), [3, 4, 5, 6])
317 grepcmd += "\'" 136 self.assertEqual(self.get_context(lines, 9, 2, 1), [6, 7, 8, 9])
318 137
319 return grepcmd 138 def parse_logs(self, logs, lines_before=10, lines_after=10):
320 139 """
321 # Grep only the errors so that their context could be collected. 140 Search the log files @logs looking for error lines (marked by
322 # Default context is 10 lines before and after the error itself 141 @self.errors), ignoring anything listed in @self.ignore_errors.
323 def parse_logs(self, errors, ignore_errors, logs, 142
324 lines_before = 10, lines_after = 10): 143 Returns a dictionary of log filenames to a dictionary of error lines to
325 results = {} 144 the error context (controlled by @lines_before and @lines_after).
326 rez = [] 145 """
327 grep_output = '' 146 results = collections.defaultdict(dict)
328 147
329 for log in logs: 148 for log in logs:
330 result = None 149 with open(log) as f:
331 thegrep = self.build_grepcmd(errors, ignore_errors, log) 150 lines = f.readlines()
332 151
333 try: 152 for i, line in enumerate(lines):
334 result = check_output(thegrep, shell=True).decode('utf-8') 153 line = line.strip()
335 except: 154 line_lower = line.casefold()
336 pass
337 155
338 if result is not None: 156 if any(keyword in line_lower for keyword in self.errors):
339 results[log] = {} 157 if not any(ignore in line_lower for ignore in self.ignore_errors):
340 rez = result.splitlines() 158 results[log][line] = "".join(self.get_context(lines, i, lines_before, lines_after))
341
342 for xrez in rez:
343 try:
344 cmd = ['grep', '-F', xrez, '-B', str(lines_before)]
345 cmd += ['-A', str(lines_after), log]
346 grep_output = check_output(cmd).decode('utf-8')
347 except:
348 pass
349 results[log][xrez]=grep_output
350 159
351 return results 160 return results
352 161
@@ -359,17 +168,18 @@ class ParseLogsTest(OERuntimeTestCase):
359 def test_parselogs(self): 168 def test_parselogs(self):
360 self.write_dmesg() 169 self.write_dmesg()
361 log_list = self.get_local_log_list(self.log_locations) 170 log_list = self.get_local_log_list(self.log_locations)
362 result = self.parse_logs(self.errors, self.ignore_errors, log_list) 171 result = self.parse_logs(log_list)
363 print(self.getHardwareInfo()) 172
364 errcount = 0 173 errcount = 0
174 self.msg = ""
365 for log in result: 175 for log in result:
366 self.msg += 'Log: ' + log + '\n' 176 self.msg += 'Log: ' + log + '\n'
367 self.msg += '-----------------------\n' 177 self.msg += '-----------------------\n'
368 for error in result[log]: 178 for error in result[log]:
369 errcount += 1 179 errcount += 1
370 self.msg += 'Central error: ' + str(error) + '\n' 180 self.msg += 'Central error: ' + error + '\n'
371 self.msg += '***********************\n' 181 self.msg += '***********************\n'
372 self.msg += result[str(log)][str(error)] + '\n' 182 self.msg += result[log][error] + '\n'
373 self.msg += '***********************\n' 183 self.msg += '***********************\n'
374 self.msg += '%s errors found in logs.' % errcount 184 self.msg += '%s errors found in logs.' % errcount
375 self.assertEqual(errcount, 0, msg=self.msg) 185 self.assertEqual(errcount, 0, msg=self.msg)
diff --git a/meta/lib/oeqa/runtime/cases/perl.py b/meta/lib/oeqa/runtime/cases/perl.py
index 2c6b3b7846..f11b300836 100644
--- a/meta/lib/oeqa/runtime/cases/perl.py
+++ b/meta/lib/oeqa/runtime/cases/perl.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/ping.py b/meta/lib/oeqa/runtime/cases/ping.py
index f6603f75ec..f72460e7f3 100644
--- a/meta/lib/oeqa/runtime/cases/ping.py
+++ b/meta/lib/oeqa/runtime/cases/ping.py
@@ -1,11 +1,15 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
5from subprocess import Popen, PIPE 7from subprocess import Popen, PIPE
8from time import sleep
6 9
7from oeqa.runtime.case import OERuntimeTestCase 10from oeqa.runtime.case import OERuntimeTestCase
8from oeqa.core.decorator.oetimeout import OETimeout 11from oeqa.core.decorator.oetimeout import OETimeout
12from oeqa.core.exception import OEQATimeoutError
9 13
10class PingTest(OERuntimeTestCase): 14class PingTest(OERuntimeTestCase):
11 15
@@ -13,14 +17,19 @@ class PingTest(OERuntimeTestCase):
13 def test_ping(self): 17 def test_ping(self):
14 output = '' 18 output = ''
15 count = 0 19 count = 0
16 while count < 5: 20 self.assertNotEqual(len(self.target.ip), 0, msg="No target IP address set")
17 cmd = 'ping -c 1 %s' % self.target.ip 21 try:
18 proc = Popen(cmd, shell=True, stdout=PIPE) 22 while count < 5:
19 output += proc.communicate()[0].decode('utf-8') 23 cmd = 'ping -c 1 %s' % self.target.ip
20 if proc.poll() == 0: 24 proc = Popen(cmd, shell=True, stdout=PIPE)
21 count += 1 25 output += proc.communicate()[0].decode('utf-8')
22 else: 26 if proc.poll() == 0:
23 count = 0 27 count += 1
28 else:
29 count = 0
30 sleep(1)
31 except OEQATimeoutError:
32 self.fail("Ping timeout error for address %s, count %s, output: %s" % (self.target.ip, count, output))
24 msg = ('Expected 5 consecutive, got %d.\n' 33 msg = ('Expected 5 consecutive, got %d.\n'
25 'ping output is:\n%s' % (count,output)) 34 'ping output is:\n%s' % (count,output))
26 self.assertEqual(count, 5, msg = msg) 35 self.assertEqual(count, 5, msg = msg)
diff --git a/meta/lib/oeqa/runtime/cases/ptest.py b/meta/lib/oeqa/runtime/cases/ptest.py
index 0800f3c27f..fbaeb84d00 100644
--- a/meta/lib/oeqa/runtime/cases/ptest.py
+++ b/meta/lib/oeqa/runtime/cases/ptest.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -57,7 +59,7 @@ class PtestRunnerTest(OERuntimeTestCase):
57 ptest_dirs = [ '/usr/lib' ] 59 ptest_dirs = [ '/usr/lib' ]
58 if not libdir in ptest_dirs: 60 if not libdir in ptest_dirs:
59 ptest_dirs.append(libdir) 61 ptest_dirs.append(libdir)
60 status, output = self.target.run('ptest-runner -d \"{}\"'.format(' '.join(ptest_dirs)), 0) 62 status, output = self.target.run('ptest-runner -t 450 -d \"{}\"'.format(' '.join(ptest_dirs)), 0)
61 os.makedirs(ptest_log_dir) 63 os.makedirs(ptest_log_dir)
62 with open(ptest_runner_log, 'w') as f: 64 with open(ptest_runner_log, 'w') as f:
63 f.write(output) 65 f.write(output)
@@ -81,17 +83,20 @@ class PtestRunnerTest(OERuntimeTestCase):
81 83
82 extras['ptestresult.sections'] = sections 84 extras['ptestresult.sections'] = sections
83 85
86 zerolength = []
84 trans = str.maketrans("()", "__") 87 trans = str.maketrans("()", "__")
85 for section in results: 88 for section in results:
86 for test in results[section]: 89 for test in results[section]:
87 result = results[section][test] 90 result = results[section][test]
88 testname = "ptestresult." + (section or "No-section") + "." + "_".join(test.translate(trans).split()) 91 testname = "ptestresult." + (section or "No-section") + "." + "_".join(test.translate(trans).split())
89 extras[testname] = {'status': result} 92 extras[testname] = {'status': result}
93 if not results[section]:
94 zerolength.append(section)
90 95
91 failed_tests = {} 96 failed_tests = {}
92 97
93 for section in sections: 98 for section in sections:
94 if 'exitcode' in sections[section].keys(): 99 if 'exitcode' in sections[section].keys() or 'timeout' in sections[section].keys():
95 failed_tests[section] = sections[section]["log"] 100 failed_tests[section] = sections[section]["log"]
96 101
97 for section in results: 102 for section in results:
@@ -105,7 +110,10 @@ class PtestRunnerTest(OERuntimeTestCase):
105 failmsg = "ERROR: Processes were killed by the OOM Killer:\n%s\n" % output 110 failmsg = "ERROR: Processes were killed by the OOM Killer:\n%s\n" % output
106 111
107 if failed_tests: 112 if failed_tests:
108 failmsg = failmsg + "Failed ptests:\n%s" % pprint.pformat(failed_tests) 113 failmsg = failmsg + "\nFailed ptests:\n%s\n" % pprint.pformat(failed_tests)
114
115 if zerolength:
116 failmsg = failmsg + "\nptests which had no test results:\n%s" % pprint.pformat(zerolength)
109 117
110 if failmsg: 118 if failmsg:
111 self.logger.warning("There were failing ptests.") 119 self.logger.warning("There were failing ptests.")
diff --git a/meta/lib/oeqa/runtime/cases/python.py b/meta/lib/oeqa/runtime/cases/python.py
index ec54f1e1db..5d6d133480 100644
--- a/meta/lib/oeqa/runtime/cases/python.py
+++ b/meta/lib/oeqa/runtime/cases/python.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/rpm.py b/meta/lib/oeqa/runtime/cases/rpm.py
index 8e18b426f8..ea5619ffea 100644
--- a/meta/lib/oeqa/runtime/cases/rpm.py
+++ b/meta/lib/oeqa/runtime/cases/rpm.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -49,21 +51,20 @@ class RpmBasicTest(OERuntimeTestCase):
49 msg = 'status: %s. Cannot run rpm -qa: %s' % (status, output) 51 msg = 'status: %s. Cannot run rpm -qa: %s' % (status, output)
50 self.assertEqual(status, 0, msg=msg) 52 self.assertEqual(status, 0, msg=msg)
51 53
52 def check_no_process_for_user(u): 54 def wait_for_no_process_for_user(u, timeout = 120):
53 _, output = self.target.run(self.tc.target_cmds['ps']) 55 timeout_at = time.time() + timeout
54 if u + ' ' in output: 56 while time.time() < timeout_at:
55 return False 57 _, output = self.target.run(self.tc.target_cmds['ps'])
56 else: 58 if u + ' ' not in output:
57 return True 59 return
60 time.sleep(1)
61 user_pss = [ps for ps in output.split("\n") if u + ' ' in ps]
62 msg = "User %s has processes still running: %s" % (u, "\n".join(user_pss))
63 self.fail(msg=msg)
58 64
59 def unset_up_test_user(u): 65 def unset_up_test_user(u):
60 # ensure no test1 process in running 66 # ensure no test1 process in running
61 timeout = time.time() + 30 67 wait_for_no_process_for_user(u)
62 while time.time() < timeout:
63 if check_no_process_for_user(u):
64 break
65 else:
66 time.sleep(1)
67 status, output = self.target.run('userdel -r %s' % u) 68 status, output = self.target.run('userdel -r %s' % u)
68 msg = 'Failed to erase user: %s' % output 69 msg = 'Failed to erase user: %s' % output
69 self.assertTrue(status == 0, msg=msg) 70 self.assertTrue(status == 0, msg=msg)
@@ -79,21 +80,24 @@ class RpmBasicTest(OERuntimeTestCase):
79 80
80class RpmInstallRemoveTest(OERuntimeTestCase): 81class RpmInstallRemoveTest(OERuntimeTestCase):
81 82
82 @classmethod 83 def _find_test_file(self):
83 def setUpClass(cls): 84 pkgarch = self.td['TUNE_PKGARCH'].replace('-', '_')
84 pkgarch = cls.td['TUNE_PKGARCH'].replace('-', '_') 85 rpmdir = os.path.join(self.tc.td['DEPLOY_DIR'], 'rpm', pkgarch)
85 rpmdir = os.path.join(cls.tc.td['DEPLOY_DIR'], 'rpm', pkgarch)
86 # Pick base-passwd-doc as a test file to get installed, because it's small 86 # Pick base-passwd-doc as a test file to get installed, because it's small
87 # and it will always be built for standard targets 87 # and it will always be built for standard targets
88 rpm_doc = 'base-passwd-doc-*.%s.rpm' % pkgarch 88 rpm_doc = 'base-passwd-doc-*.%s.rpm' % pkgarch
89 if not os.path.exists(rpmdir): 89 if not os.path.exists(rpmdir):
90 return 90 self.fail("Rpm directory {} does not exist".format(rpmdir))
91 for f in fnmatch.filter(os.listdir(rpmdir), rpm_doc): 91 for f in fnmatch.filter(os.listdir(rpmdir), rpm_doc):
92 cls.test_file = os.path.join(rpmdir, f) 92 self.test_file = os.path.join(rpmdir, f)
93 cls.dst = '/tmp/base-passwd-doc.rpm' 93 break
94 else:
95 self.fail("Couldn't find the test rpm file {} in {}".format(rpm_doc, rpmdir))
96 self.dst = '/tmp/base-passwd-doc.rpm'
94 97
95 @OETestDepends(['rpm.RpmBasicTest.test_rpm_query']) 98 @OETestDepends(['rpm.RpmBasicTest.test_rpm_query'])
96 def test_rpm_install(self): 99 def test_rpm_install(self):
100 self._find_test_file()
97 self.tc.target.copyTo(self.test_file, self.dst) 101 self.tc.target.copyTo(self.test_file, self.dst)
98 status, output = self.target.run('rpm -ivh /tmp/base-passwd-doc.rpm') 102 status, output = self.target.run('rpm -ivh /tmp/base-passwd-doc.rpm')
99 msg = 'Failed to install base-passwd-doc package: %s' % output 103 msg = 'Failed to install base-passwd-doc package: %s' % output
@@ -116,12 +120,13 @@ class RpmInstallRemoveTest(OERuntimeTestCase):
116 Author: Alexander Kanavin <alex.kanavin@gmail.com> 120 Author: Alexander Kanavin <alex.kanavin@gmail.com>
117 AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com> 121 AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
118 """ 122 """
119 db_files_cmd = 'ls /var/lib/rpm/__db.*' 123 self._find_test_file()
124 db_files_cmd = 'ls /var/lib/rpm/rpmdb.sqlite*'
120 check_log_cmd = "grep RPM /var/log/messages | wc -l" 125 check_log_cmd = "grep RPM /var/log/messages | wc -l"
121 126
122 # Make sure that some database files are under /var/lib/rpm as '__db.xxx' 127 # Make sure that some database files are under /var/lib/rpm as 'rpmdb.sqlite'
123 status, output = self.target.run(db_files_cmd) 128 status, output = self.target.run(db_files_cmd)
124 msg = 'Failed to find database files under /var/lib/rpm/ as __db.xxx' 129 msg = 'Failed to find database files under /var/lib/rpm/ as rpmdb.sqlite'
125 self.assertEqual(0, status, msg=msg) 130 self.assertEqual(0, status, msg=msg)
126 131
127 self.tc.target.copyTo(self.test_file, self.dst) 132 self.tc.target.copyTo(self.test_file, self.dst)
@@ -141,13 +146,4 @@ class RpmInstallRemoveTest(OERuntimeTestCase):
141 146
142 self.tc.target.run('rm -f %s' % self.dst) 147 self.tc.target.run('rm -f %s' % self.dst)
143 148
144 # if using systemd this should ensure all entries are flushed to /var
145 status, output = self.target.run("journalctl --sync")
146 # Get the amount of entries in the log file
147 status, output = self.target.run(check_log_cmd)
148 msg = 'Failed to get the final size of the log file.'
149 self.assertEqual(0, status, msg=msg)
150 149
151 # Check that there's enough of them
152 self.assertGreaterEqual(int(output), 80,
153 'Cound not find sufficient amount of rpm entries in /var/log/messages, found {} entries'.format(output))
diff --git a/meta/lib/oeqa/runtime/cases/rt.py b/meta/lib/oeqa/runtime/cases/rt.py
new file mode 100644
index 0000000000..15ab4dbbbb
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/rt.py
@@ -0,0 +1,19 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7from oeqa.runtime.case import OERuntimeTestCase
8from oeqa.core.decorator.depends import OETestDepends
9
10class RtTest(OERuntimeTestCase):
11 @OETestDepends(['ssh.SSHTest.test_ssh'])
12 def test_is_rt(self):
13 """
14 Check that the kernel has CONFIG_PREEMPT_RT enabled.
15 """
16 status, output = self.target.run("uname -a")
17 self.assertEqual(status, 0, msg=output)
18 # Split so we don't get a substring false-positive
19 self.assertIn("PREEMPT_RT", output.split())
diff --git a/meta/lib/oeqa/runtime/cases/rtc.py b/meta/lib/oeqa/runtime/cases/rtc.py
index a34c101a9d..6e45c5db4f 100644
--- a/meta/lib/oeqa/runtime/cases/rtc.py
+++ b/meta/lib/oeqa/runtime/cases/rtc.py
@@ -1,5 +1,11 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
1from oeqa.runtime.case import OERuntimeTestCase 6from oeqa.runtime.case import OERuntimeTestCase
2from oeqa.core.decorator.depends import OETestDepends 7from oeqa.core.decorator.depends import OETestDepends
8from oeqa.core.decorator.data import skipIfFeature
3from oeqa.runtime.decorator.package import OEHasPackage 9from oeqa.runtime.decorator.package import OEHasPackage
4 10
5import re 11import re
@@ -9,19 +15,21 @@ class RTCTest(OERuntimeTestCase):
9 def setUp(self): 15 def setUp(self):
10 if self.tc.td.get('VIRTUAL-RUNTIME_init_manager') == 'systemd': 16 if self.tc.td.get('VIRTUAL-RUNTIME_init_manager') == 'systemd':
11 self.logger.debug('Stopping systemd-timesyncd daemon') 17 self.logger.debug('Stopping systemd-timesyncd daemon')
12 self.target.run('systemctl disable --now systemd-timesyncd') 18 self.target.run('systemctl disable --now --runtime systemd-timesyncd')
13 19
14 def tearDown(self): 20 def tearDown(self):
15 if self.tc.td.get('VIRTUAL-RUNTIME_init_manager') == 'systemd': 21 if self.tc.td.get('VIRTUAL-RUNTIME_init_manager') == 'systemd':
16 self.logger.debug('Starting systemd-timesyncd daemon') 22 self.logger.debug('Starting systemd-timesyncd daemon')
17 self.target.run('systemctl enable --now systemd-timesyncd') 23 self.target.run('systemctl enable --now --runtime systemd-timesyncd')
18 24
25 @skipIfFeature('read-only-rootfs',
26 'Test does not work with read-only-rootfs in IMAGE_FEATURES')
19 @OETestDepends(['ssh.SSHTest.test_ssh']) 27 @OETestDepends(['ssh.SSHTest.test_ssh'])
20 @OEHasPackage(['coreutils', 'busybox']) 28 @OEHasPackage(['coreutils', 'busybox'])
21 def test_rtc(self): 29 def test_rtc(self):
22 (status, output) = self.target.run('hwclock -r') 30 (status, output) = self.target.run('hwclock -r')
23 self.assertEqual(status, 0, msg='Failed to get RTC time, output: %s' % output) 31 self.assertEqual(status, 0, msg='Failed to get RTC time, output: %s' % output)
24 32
25 (status, current_datetime) = self.target.run('date +"%m%d%H%M%Y"') 33 (status, current_datetime) = self.target.run('date +"%m%d%H%M%Y"')
26 self.assertEqual(status, 0, msg='Failed to get system current date & time, output: %s' % current_datetime) 34 self.assertEqual(status, 0, msg='Failed to get system current date & time, output: %s' % current_datetime)
27 35
@@ -32,7 +40,6 @@ class RTCTest(OERuntimeTestCase):
32 40
33 (status, output) = self.target.run('date %s' % current_datetime) 41 (status, output) = self.target.run('date %s' % current_datetime)
34 self.assertEqual(status, 0, msg='Failed to reset system date & time, output: %s' % output) 42 self.assertEqual(status, 0, msg='Failed to reset system date & time, output: %s' % output)
35 43
36 (status, output) = self.target.run('hwclock -w') 44 (status, output) = self.target.run('hwclock -w')
37 self.assertEqual(status, 0, msg='Failed to reset RTC time, output: %s' % output) 45 self.assertEqual(status, 0, msg='Failed to reset RTC time, output: %s' % output)
38
diff --git a/meta/lib/oeqa/runtime/cases/runlevel.py b/meta/lib/oeqa/runtime/cases/runlevel.py
index 3a4df8ace1..6734b0f5ed 100644
--- a/meta/lib/oeqa/runtime/cases/runlevel.py
+++ b/meta/lib/oeqa/runtime/cases/runlevel.py
@@ -1,3 +1,8 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
1from oeqa.runtime.case import OERuntimeTestCase 6from oeqa.runtime.case import OERuntimeTestCase
2from oeqa.core.decorator.depends import OETestDepends 7from oeqa.core.decorator.depends import OETestDepends
3 8
diff --git a/meta/lib/oeqa/runtime/cases/rust.py b/meta/lib/oeqa/runtime/cases/rust.py
new file mode 100644
index 0000000000..123c942012
--- /dev/null
+++ b/meta/lib/oeqa/runtime/cases/rust.py
@@ -0,0 +1,64 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7from oeqa.runtime.case import OERuntimeTestCase
8from oeqa.core.decorator.depends import OETestDepends
9from oeqa.runtime.decorator.package import OEHasPackage
10
11class RustCompileTest(OERuntimeTestCase):
12
13 @classmethod
14 def setUp(cls):
15 dst = '/tmp/'
16 src = os.path.join(cls.tc.files_dir, 'test.rs')
17 cls.tc.target.copyTo(src, dst)
18
19 @classmethod
20 def tearDown(cls):
21 files = '/tmp/test.rs /tmp/test'
22 cls.tc.target.run('rm %s' % files)
23 dirs = '/tmp/hello'
24 cls.tc.target.run('rm -r %s' % dirs)
25
26 @OETestDepends(['ssh.SSHTest.test_ssh'])
27 @OEHasPackage('rust')
28 @OEHasPackage('openssh-scp')
29 def test_rust_compile(self):
30 status, output = self.target.run('rustc /tmp/test.rs -o /tmp/test')
31 msg = 'rust compile failed, output: %s' % output
32 self.assertEqual(status, 0, msg=msg)
33
34 status, output = self.target.run('/tmp/test')
35 msg = 'running compiled file failed, output: %s' % output
36 self.assertEqual(status, 0, msg=msg)
37
38 @OETestDepends(['ssh.SSHTest.test_ssh'])
39 @OEHasPackage('cargo')
40 @OEHasPackage('openssh-scp')
41 def test_cargo_compile(self):
42 status, output = self.target.run('cargo new /tmp/hello')
43 msg = 'cargo new failed, output: %s' % output
44 self.assertEqual(status, 0, msg=msg)
45
46 status, output = self.target.run('cargo build --manifest-path=/tmp/hello/Cargo.toml')
47 msg = 'cargo build failed, output: %s' % output
48 self.assertEqual(status, 0, msg=msg)
49
50 status, output = self.target.run('cargo run --manifest-path=/tmp/hello/Cargo.toml')
51 msg = 'running compiled file failed, output: %s' % output
52 self.assertEqual(status, 0, msg=msg)
53
54class RustCLibExampleTest(OERuntimeTestCase):
55 @OETestDepends(['ssh.SSHTest.test_ssh'])
56 @OEHasPackage('rust-c-lib-example-bin')
57 def test_rust_c_lib_example(self):
58 cmd = "rust-c-lib-example-bin test"
59 status, output = self.target.run(cmd)
60 msg = 'Exit status was not 0. Output: %s' % output
61 self.assertEqual(status, 0, msg=msg)
62
63 msg = 'Incorrect output: %s' % output
64 self.assertEqual(output, "Hello world in rust from C!", msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/scons.py b/meta/lib/oeqa/runtime/cases/scons.py
index 3c7c7f7270..4a8d4d40ba 100644
--- a/meta/lib/oeqa/runtime/cases/scons.py
+++ b/meta/lib/oeqa/runtime/cases/scons.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/scp.py b/meta/lib/oeqa/runtime/cases/scp.py
index 3a5f292152..ee97b8ef66 100644
--- a/meta/lib/oeqa/runtime/cases/scp.py
+++ b/meta/lib/oeqa/runtime/cases/scp.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -23,7 +25,7 @@ class ScpTest(OERuntimeTestCase):
23 os.remove(cls.tmp_path) 25 os.remove(cls.tmp_path)
24 26
25 @OETestDepends(['ssh.SSHTest.test_ssh']) 27 @OETestDepends(['ssh.SSHTest.test_ssh'])
26 @OEHasPackage(['openssh-scp', 'dropbear']) 28 @OEHasPackage(['openssh-scp'])
27 def test_scp_file(self): 29 def test_scp_file(self):
28 dst = '/tmp/test_scp_file' 30 dst = '/tmp/test_scp_file'
29 31
diff --git a/meta/lib/oeqa/runtime/cases/skeletoninit.py b/meta/lib/oeqa/runtime/cases/skeletoninit.py
index 4779cd6bb4..d0fdcbded9 100644
--- a/meta/lib/oeqa/runtime/cases/skeletoninit.py
+++ b/meta/lib/oeqa/runtime/cases/skeletoninit.py
@@ -1,10 +1,12 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
5# This test should cover https://bugzilla.yoctoproject.org/tr_show_case.cgi?case_id=284 7# This test should cover https://bugzilla.yoctoproject.org/tr_show_case.cgi?case_id=284
6# testcase. Image under test must have meta-skeleton layer in bblayers and 8# testcase. Image under test must have meta-skeleton layer in bblayers and
7# IMAGE_INSTALL_append = " service" in local.conf 9# IMAGE_INSTALL:append = " service" in local.conf
8from oeqa.runtime.case import OERuntimeTestCase 10from oeqa.runtime.case import OERuntimeTestCase
9from oeqa.core.decorator.depends import OETestDepends 11from oeqa.core.decorator.depends import OETestDepends
10from oeqa.core.decorator.data import skipIfDataVar 12from oeqa.core.decorator.data import skipIfDataVar
@@ -15,7 +17,7 @@ class SkeletonBasicTest(OERuntimeTestCase):
15 @OETestDepends(['ssh.SSHTest.test_ssh']) 17 @OETestDepends(['ssh.SSHTest.test_ssh'])
16 @OEHasPackage(['service']) 18 @OEHasPackage(['service'])
17 @skipIfDataVar('VIRTUAL-RUNTIME_init_manager', 'systemd', 19 @skipIfDataVar('VIRTUAL-RUNTIME_init_manager', 'systemd',
18 'Not appropiate for systemd image') 20 'Not appropriate for systemd image')
19 def test_skeleton_availability(self): 21 def test_skeleton_availability(self):
20 status, output = self.target.run('ls /etc/init.d/skeleton') 22 status, output = self.target.run('ls /etc/init.d/skeleton')
21 msg = 'skeleton init script not found. Output:\n%s' % output 23 msg = 'skeleton init script not found. Output:\n%s' % output
diff --git a/meta/lib/oeqa/runtime/cases/ssh.py b/meta/lib/oeqa/runtime/cases/ssh.py
index 60a5fbbfbf..cdbef59500 100644
--- a/meta/lib/oeqa/runtime/cases/ssh.py
+++ b/meta/lib/oeqa/runtime/cases/ssh.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -11,9 +13,12 @@ class SSHTest(OERuntimeTestCase):
11 @OETestDepends(['ping.PingTest.test_ping']) 13 @OETestDepends(['ping.PingTest.test_ping'])
12 @OEHasPackage(['dropbear', 'openssh-sshd']) 14 @OEHasPackage(['dropbear', 'openssh-sshd'])
13 def test_ssh(self): 15 def test_ssh(self):
16 (status, output) = self.target.run('sleep 20', timeout=2)
17 msg='run() timed out but return code was zero.'
18 self.assertNotEqual(status, 0, msg=msg)
14 (status, output) = self.target.run('uname -a') 19 (status, output) = self.target.run('uname -a')
15 self.assertEqual(status, 0, msg='SSH Test failed: %s' % output) 20 self.assertEqual(status, 0, msg='SSH Test failed: %s' % output)
16 (status, output) = self.target.run('cat /etc/masterimage') 21 (status, output) = self.target.run('cat /etc/controllerimage')
17 msg = "This isn't the right image - /etc/masterimage " \ 22 msg = "This isn't the right image - /etc/controllerimage " \
18 "shouldn't be here %s" % output 23 "shouldn't be here %s" % output
19 self.assertEqual(status, 1, msg=msg) 24 self.assertEqual(status, 1, msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/stap.py b/meta/lib/oeqa/runtime/cases/stap.py
index 5342f6ac34..3be4162108 100644
--- a/meta/lib/oeqa/runtime/cases/stap.py
+++ b/meta/lib/oeqa/runtime/cases/stap.py
@@ -1,37 +1,34 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
5import os 7import os
6 8
7from oeqa.runtime.case import OERuntimeTestCase 9from oeqa.runtime.case import OERuntimeTestCase
8from oeqa.core.decorator.depends import OETestDepends
9from oeqa.core.decorator.data import skipIfNotFeature 10from oeqa.core.decorator.data import skipIfNotFeature
10from oeqa.runtime.decorator.package import OEHasPackage 11from oeqa.runtime.decorator.package import OEHasPackage
11 12
12class StapTest(OERuntimeTestCase): 13class StapTest(OERuntimeTestCase):
13 14 @skipIfNotFeature('tools-profile', 'Test requires tools-profile to be in IMAGE_FEATURES')
14 @classmethod
15 def setUp(cls):
16 src = os.path.join(cls.tc.runtime_files_dir, 'hello.stp')
17 dst = '/tmp/hello.stp'
18 cls.tc.target.copyTo(src, dst)
19
20 @classmethod
21 def tearDown(cls):
22 files = '/tmp/hello.stp'
23 cls.tc.target.run('rm %s' % files)
24
25 @skipIfNotFeature('tools-profile',
26 'Test requires tools-profile to be in IMAGE_FEATURES')
27 @OETestDepends(['kernelmodule.KernelModuleTest.test_kernel_module'])
28 @OEHasPackage(['systemtap']) 15 @OEHasPackage(['systemtap'])
16 @OEHasPackage(['gcc-symlinks'])
17 @OEHasPackage(['kernel-devsrc'])
29 def test_stap(self): 18 def test_stap(self):
30 cmds = [ 19 try:
31 'cd /usr/src/kernel && make scripts prepare', 20 cmd = 'make -j -C /usr/src/kernel scripts prepare'
32 'cd /lib/modules/`uname -r` && (if [ ! -e build ]; then ln -s /usr/src/kernel build; fi)',
33 'stap --disable-cache -DSTP_NO_VERREL_CHECK /tmp/hello.stp'
34 ]
35 for cmd in cmds:
36 status, output = self.target.run(cmd, 900) 21 status, output = self.target.run(cmd, 900)
37 self.assertEqual(status, 0, msg='\n'.join([cmd, output])) 22 self.assertEqual(status, 0, msg='\n'.join([cmd, output]))
23
24 cmd = 'stap -v -p4 -m stap-hello --disable-cache -DSTP_NO_VERREL_CHECK -e \'probe oneshot { print("Hello, "); println("SystemTap!") }\''
25 status, output = self.target.run(cmd, 900)
26 self.assertEqual(status, 0, msg='\n'.join([cmd, output]))
27
28 cmd = 'staprun -v -R -b1 stap-hello.ko'
29 self.assertEqual(status, 0, msg='\n'.join([cmd, output]))
30 self.assertIn('Hello, SystemTap!', output, msg='\n'.join([cmd, output]))
31 except:
32 status, dmesg = self.target.run('dmesg')
33 if status == 0:
34 print(dmesg)
diff --git a/meta/lib/oeqa/runtime/cases/storage.py b/meta/lib/oeqa/runtime/cases/storage.py
index 166d26b252..b05622fea8 100644
--- a/meta/lib/oeqa/runtime/cases/storage.py
+++ b/meta/lib/oeqa/runtime/cases/storage.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -91,24 +93,24 @@ class UsbTest(StorageBase):
91 self.test_file = "usb.tst" 93 self.test_file = "usb.tst"
92 self.test_dir = os.path.join(self.mount_point, "oeqa") 94 self.test_dir = os.path.join(self.mount_point, "oeqa")
93 95
94 @skipIfQemu('qemuall', 'Test only runs on real hardware') 96 @skipIfQemu()
95 @OETestDepends(['ssh.SSHTest.test_ssh']) 97 @OETestDepends(['ssh.SSHTest.test_ssh'])
96 def test_usb_mount(self): 98 def test_usb_mount(self):
97 self.storage_umount(2) 99 self.storage_umount(2)
98 self.storage_mount(5) 100 self.storage_mount(5)
99 101
100 @skipIfQemu('qemuall', 'Test only runs on real hardware') 102 @skipIfQemu()
101 @OETestDepends(['storage.UsbTest.test_usb_mount']) 103 @OETestDepends(['storage.UsbTest.test_usb_mount'])
102 def test_usb_basic_operations(self): 104 def test_usb_basic_operations(self):
103 self.storage_basic() 105 self.storage_basic()
104 106
105 @skipIfQemu('qemuall', 'Test only runs on real hardware') 107 @skipIfQemu()
106 @OETestDepends(['storage.UsbTest.test_usb_basic_operations']) 108 @OETestDepends(['storage.UsbTest.test_usb_basic_operations'])
107 def test_usb_basic_rw(self): 109 def test_usb_basic_rw(self):
108 self.storage_write() 110 self.storage_write()
109 self.storage_read() 111 self.storage_read()
110 112
111 @skipIfQemu('qemuall', 'Test only runs on real hardware') 113 @skipIfQemu()
112 @OETestDepends(['storage.UsbTest.test_usb_mount']) 114 @OETestDepends(['storage.UsbTest.test_usb_mount'])
113 def test_usb_umount(self): 115 def test_usb_umount(self):
114 self.storage_umount(2) 116 self.storage_umount(2)
@@ -126,24 +128,24 @@ class MMCTest(StorageBase):
126 self.test_file = "mmc.tst" 128 self.test_file = "mmc.tst"
127 self.test_dir = os.path.join(self.mount_point, "oeqa") 129 self.test_dir = os.path.join(self.mount_point, "oeqa")
128 130
129 @skipIfQemu('qemuall', 'Test only runs on real hardware') 131 @skipIfQemu()
130 @OETestDepends(['ssh.SSHTest.test_ssh']) 132 @OETestDepends(['ssh.SSHTest.test_ssh'])
131 def test_mmc_mount(self): 133 def test_mmc_mount(self):
132 self.storage_umount(2) 134 self.storage_umount(2)
133 self.storage_mount() 135 self.storage_mount()
134 136
135 @skipIfQemu('qemuall', 'Test only runs on real hardware') 137 @skipIfQemu()
136 @OETestDepends(['storage.MMCTest.test_mmc_mount']) 138 @OETestDepends(['storage.MMCTest.test_mmc_mount'])
137 def test_mmc_basic_operations(self): 139 def test_mmc_basic_operations(self):
138 self.storage_basic() 140 self.storage_basic()
139 141
140 @skipIfQemu('qemuall', 'Test only runs on real hardware') 142 @skipIfQemu()
141 @OETestDepends(['storage.MMCTest.test_mmc_basic_operations']) 143 @OETestDepends(['storage.MMCTest.test_mmc_basic_operations'])
142 def test_mmc_basic_rw(self): 144 def test_mmc_basic_rw(self):
143 self.storage_write() 145 self.storage_write()
144 self.storage_read() 146 self.storage_read()
145 147
146 @skipIfQemu('qemuall', 'Test only runs on real hardware') 148 @skipIfQemu()
147 @OETestDepends(['storage.MMCTest.test_mmc_mount']) 149 @OETestDepends(['storage.MMCTest.test_mmc_mount'])
148 def test_mmc_umount(self): 150 def test_mmc_umount(self):
149 self.storage_umount(2) 151 self.storage_umount(2)
diff --git a/meta/lib/oeqa/runtime/cases/suspend.py b/meta/lib/oeqa/runtime/cases/suspend.py
index 67b6f7e56f..a625cc5901 100644
--- a/meta/lib/oeqa/runtime/cases/suspend.py
+++ b/meta/lib/oeqa/runtime/cases/suspend.py
@@ -1,3 +1,8 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
1from oeqa.runtime.case import OERuntimeTestCase 6from oeqa.runtime.case import OERuntimeTestCase
2from oeqa.core.decorator.depends import OETestDepends 7from oeqa.core.decorator.depends import OETestDepends
3from oeqa.core.decorator.data import skipIfQemu 8from oeqa.core.decorator.data import skipIfQemu
@@ -23,7 +28,7 @@ class Suspend_Test(OERuntimeTestCase):
23 (status, output) = self.target.run('sudo rtcwake -m mem -s 10') 28 (status, output) = self.target.run('sudo rtcwake -m mem -s 10')
24 self.assertEqual(status, 0, msg = 'Failed to suspends your system to RAM, output : %s' % output) 29 self.assertEqual(status, 0, msg = 'Failed to suspends your system to RAM, output : %s' % output)
25 30
26 @skipIfQemu('qemuall', 'Test only runs on real hardware') 31 @skipIfQemu()
27 @OETestDepends(['ssh.SSHTest.test_ssh']) 32 @OETestDepends(['ssh.SSHTest.test_ssh'])
28 def test_suspend(self): 33 def test_suspend(self):
29 self.test_date() 34 self.test_date()
diff --git a/meta/lib/oeqa/runtime/cases/systemd.py b/meta/lib/oeqa/runtime/cases/systemd.py
index 7c44abe8ed..5481e1d840 100644
--- a/meta/lib/oeqa/runtime/cases/systemd.py
+++ b/meta/lib/oeqa/runtime/cases/systemd.py
@@ -1,8 +1,11 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
5import re 7import re
8import threading
6import time 9import time
7 10
8from oeqa.runtime.case import OERuntimeTestCase 11from oeqa.runtime.case import OERuntimeTestCase
@@ -66,8 +69,8 @@ class SystemdBasicTests(SystemdTest):
66 """ 69 """
67 endtime = time.time() + (60 * 2) 70 endtime = time.time() + (60 * 2)
68 while True: 71 while True:
69 status, output = self.target.run('SYSTEMD_BUS_TIMEOUT=240s systemctl --state=activating') 72 status, output = self.target.run('SYSTEMD_BUS_TIMEOUT=240s systemctl is-system-running')
70 if "0 loaded units listed" in output: 73 if "running" in output or "degraded" in output:
71 return (True, '') 74 return (True, '')
72 if time.time() >= endtime: 75 if time.time() >= endtime:
73 return (False, output) 76 return (False, output)
@@ -134,6 +137,27 @@ class SystemdServiceTests(SystemdTest):
134 status = self.target.run('mount -oro,remount /')[0] 137 status = self.target.run('mount -oro,remount /')[0]
135 self.assertTrue(status == 0, msg='Remounting / as r/o failed') 138 self.assertTrue(status == 0, msg='Remounting / as r/o failed')
136 139
140 @OETestDepends(['systemd.SystemdBasicTests.test_systemd_basic'])
141 @skipIfNotFeature('minidebuginfo', 'Test requires minidebuginfo to be in DISTRO_FEATURES')
142 @OEHasPackage(['busybox'])
143 def test_systemd_coredump_minidebuginfo(self):
144 """
145 Verify that call-stacks generated by systemd-coredump contain symbolicated call-stacks,
146 extracted from the minidebuginfo metadata (.gnu_debugdata elf section).
147 """
148 t_thread = threading.Thread(target=self.target.run, args=("ulimit -c unlimited && sleep 1000",))
149 t_thread.start()
150 time.sleep(1)
151
152 status, output = self.target.run('pidof sleep')
153 # cause segfault on purpose
154 self.target.run('kill -SEGV %s' % output)
155 self.assertEqual(status, 0, msg = 'Not able to find process that runs sleep, output : %s' % output)
156
157 (status, output) = self.target.run('coredumpctl info')
158 self.assertEqual(status, 0, msg='MiniDebugInfo Test failed: %s' % output)
159 self.assertEqual('sleep_for_duration (busybox.nosuid' in output, True, msg='Call stack is missing minidebuginfo symbols (functions shown as "n/a"): %s' % output)
160
137class SystemdJournalTests(SystemdTest): 161class SystemdJournalTests(SystemdTest):
138 162
139 @OETestDepends(['systemd.SystemdBasicTests.test_systemd_basic']) 163 @OETestDepends(['systemd.SystemdBasicTests.test_systemd_basic'])
@@ -152,7 +176,7 @@ class SystemdJournalTests(SystemdTest):
152 """ 176 """
153 177
154 # The expression chain that uniquely identifies the time boot message. 178 # The expression chain that uniquely identifies the time boot message.
155 expr_items=['Startup finished', 'kernel', 'userspace','\.$'] 179 expr_items=['Startup finished', 'kernel', 'userspace', r'\.$']
156 try: 180 try:
157 output = self.journalctl(args='-o cat --reverse') 181 output = self.journalctl(args='-o cat --reverse')
158 except AssertionError: 182 except AssertionError:
diff --git a/meta/lib/oeqa/runtime/cases/terminal.py b/meta/lib/oeqa/runtime/cases/terminal.py
index 8fcca99f47..96ba3c3195 100644
--- a/meta/lib/oeqa/runtime/cases/terminal.py
+++ b/meta/lib/oeqa/runtime/cases/terminal.py
@@ -1,3 +1,8 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
1from oeqa.runtime.case import OERuntimeTestCase 6from oeqa.runtime.case import OERuntimeTestCase
2from oeqa.core.decorator.depends import OETestDepends 7from oeqa.core.decorator.depends import OETestDepends
3from oeqa.runtime.decorator.package import OEHasPackage 8from oeqa.runtime.decorator.package import OEHasPackage
diff --git a/meta/lib/oeqa/runtime/cases/usb_hid.py b/meta/lib/oeqa/runtime/cases/usb_hid.py
index 3c292cf661..6f23d2ff51 100644
--- a/meta/lib/oeqa/runtime/cases/usb_hid.py
+++ b/meta/lib/oeqa/runtime/cases/usb_hid.py
@@ -1,3 +1,8 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
1from oeqa.runtime.case import OERuntimeTestCase 6from oeqa.runtime.case import OERuntimeTestCase
2from oeqa.core.decorator.depends import OETestDepends 7from oeqa.core.decorator.depends import OETestDepends
3from oeqa.core.decorator.data import skipIfQemu 8from oeqa.core.decorator.data import skipIfQemu
@@ -14,7 +19,7 @@ class USB_HID_Test(OERuntimeTestCase):
14 return self.assertEqual(status, 0, msg = 'Failed to suspends your system to RAM, output : %s' % output) 19 return self.assertEqual(status, 0, msg = 'Failed to suspends your system to RAM, output : %s' % output)
15 20
16 @OEHasPackage(['xdotool']) 21 @OEHasPackage(['xdotool'])
17 @skipIfQemu('qemuall', 'Test only runs on real hardware') 22 @skipIfQemu()
18 @OETestDepends(['ssh.SSHTest.test_ssh']) 23 @OETestDepends(['ssh.SSHTest.test_ssh'])
19 def test_USB_Hid_input(self): 24 def test_USB_Hid_input(self):
20 self.keyboard_mouse_simulation() 25 self.keyboard_mouse_simulation()
diff --git a/meta/lib/oeqa/runtime/cases/weston.py b/meta/lib/oeqa/runtime/cases/weston.py
index a1c7183213..ee4d336482 100644
--- a/meta/lib/oeqa/runtime/cases/weston.py
+++ b/meta/lib/oeqa/runtime/cases/weston.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
@@ -10,7 +12,7 @@ import threading
10import time 12import time
11 13
12class WestonTest(OERuntimeTestCase): 14class WestonTest(OERuntimeTestCase):
13 weston_log_file = '/tmp/weston.log' 15 weston_log_file = '/tmp/weston-2.log'
14 16
15 @classmethod 17 @classmethod
16 def tearDownClass(cls): 18 def tearDownClass(cls):
@@ -31,13 +33,13 @@ class WestonTest(OERuntimeTestCase):
31 return output.split(" ") 33 return output.split(" ")
32 34
33 def get_weston_command(self, cmd): 35 def get_weston_command(self, cmd):
34 return 'export XDG_RUNTIME_DIR=/run/user/0; export WAYLAND_DISPLAY=wayland-0; %s' % cmd 36 return 'export XDG_RUNTIME_DIR=/run/user/`id -u weston`; export WAYLAND_DISPLAY=wayland-1; %s' % cmd
35 37
36 def run_weston_init(self): 38 def run_weston_init(self):
37 if 'systemd' in self.tc.td['VIRTUAL-RUNTIME_init_manager']: 39 if 'systemd' in self.tc.td['VIRTUAL-RUNTIME_init_manager']:
38 self.target.run('systemd-run --collect --unit=weston-ptest.service --uid=0 -p PAMName=login -p TTYPath=/dev/tty6 -E XDG_RUNTIME_DIR=/tmp -E WAYLAND_DISPLAY=wayland-0 /usr/bin/weston --socket=wayland-1 --log=%s' % self.weston_log_file) 40 self.target.run('systemd-run --collect --unit=weston-ptest.service --uid=0 -p PAMName=login -p TTYPath=/dev/tty6 -E XDG_RUNTIME_DIR=/tmp -E WAYLAND_DISPLAY=wayland-0 /usr/bin/weston --socket=wayland-1 --log=%s' % self.weston_log_file)
39 else: 41 else:
40 self.target.run(self.get_weston_command('openvt -- weston --socket=wayland-1 --log=%s' % self.weston_log_file)) 42 self.target.run(self.get_weston_command('openvt -- weston --socket=wayland-2 --log=%s' % self.weston_log_file))
41 43
42 def get_new_wayland_processes(self, existing_wl_processes): 44 def get_new_wayland_processes(self, existing_wl_processes):
43 try_cnt = 0 45 try_cnt = 0
@@ -53,7 +55,11 @@ class WestonTest(OERuntimeTestCase):
53 55
54 @OEHasPackage(['wayland-utils']) 56 @OEHasPackage(['wayland-utils'])
55 def test_wayland_info(self): 57 def test_wayland_info(self):
56 status, output = self.target.run(self.get_weston_command('wayland-info')) 58 if 'systemd' in self.tc.td['VIRTUAL-RUNTIME_init_manager']:
59 command = 'XDG_RUNTIME_DIR=/run wayland-info'
60 else:
61 command = self.get_weston_command('wayland-info')
62 status, output = self.target.run(command)
57 self.assertEqual(status, 0, msg='wayland-info error: %s' % output) 63 self.assertEqual(status, 0, msg='wayland-info error: %s' % output)
58 64
59 @OEHasPackage(['weston']) 65 @OEHasPackage(['weston'])
@@ -73,3 +79,11 @@ class WestonTest(OERuntimeTestCase):
73 self.target.run('kill -9 %s' % w) 79 self.target.run('kill -9 %s' % w)
74 __, weston_log = self.target.run('cat %s' % self.weston_log_file) 80 __, weston_log = self.target.run('cat %s' % self.weston_log_file)
75 self.assertTrue(new_wl_processes, msg='Could not get new weston-desktop-shell processes (%s, try_cnt:%s) weston log: %s' % (new_wl_processes, try_cnt, weston_log)) 81 self.assertTrue(new_wl_processes, msg='Could not get new weston-desktop-shell processes (%s, try_cnt:%s) weston log: %s' % (new_wl_processes, try_cnt, weston_log))
82
83 @skipIfNotFeature('x11', 'Test requires x11 to be in DISTRO_FEATURES')
84 @OEHasPackage(['weston'])
85 def test_weston_supports_xwayland(self):
86 cmd ='cat %s | grep "xserver listening on display"' % self.weston_log_file
87 status, output = self.target.run(cmd)
88 msg = ('xwayland does not appear to be running')
89 self.assertEqual(status, 0, msg=msg)
diff --git a/meta/lib/oeqa/runtime/cases/x32lib.py b/meta/lib/oeqa/runtime/cases/x32lib.py
index f419c8f181..014da4b386 100644
--- a/meta/lib/oeqa/runtime/cases/x32lib.py
+++ b/meta/lib/oeqa/runtime/cases/x32lib.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/cases/xorg.py b/meta/lib/oeqa/runtime/cases/xorg.py
index d6845587c2..09afb1e3d1 100644
--- a/meta/lib/oeqa/runtime/cases/xorg.py
+++ b/meta/lib/oeqa/runtime/cases/xorg.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: MIT 4# SPDX-License-Identifier: MIT
3# 5#
4 6
diff --git a/meta/lib/oeqa/runtime/context.py b/meta/lib/oeqa/runtime/context.py
index 3826f27642..cb7227a8df 100644
--- a/meta/lib/oeqa/runtime/context.py
+++ b/meta/lib/oeqa/runtime/context.py
@@ -5,11 +5,11 @@
5# 5#
6 6
7import os 7import os
8import sys
8 9
9from oeqa.core.context import OETestContext, OETestContextExecutor 10from oeqa.core.context import OETestContext, OETestContextExecutor
10from oeqa.core.target.ssh import OESSHTarget 11from oeqa.core.target.ssh import OESSHTarget
11from oeqa.core.target.qemu import OEQemuTarget 12from oeqa.core.target.qemu import OEQemuTarget
12from oeqa.utils.dump import HostDumper
13 13
14from oeqa.runtime.loader import OERuntimeTestLoader 14from oeqa.runtime.loader import OERuntimeTestLoader
15 15
@@ -19,12 +19,11 @@ class OERuntimeTestContext(OETestContext):
19 os.path.dirname(os.path.abspath(__file__)), "files") 19 os.path.dirname(os.path.abspath(__file__)), "files")
20 20
21 def __init__(self, td, logger, target, 21 def __init__(self, td, logger, target,
22 host_dumper, image_packages, extract_dir): 22 image_packages, extract_dir):
23 super(OERuntimeTestContext, self).__init__(td, logger) 23 super(OERuntimeTestContext, self).__init__(td, logger)
24 24
25 self.target = target 25 self.target = target
26 self.image_packages = image_packages 26 self.image_packages = image_packages
27 self.host_dumper = host_dumper
28 self.extract_dir = extract_dir 27 self.extract_dir = extract_dir
29 self._set_target_cmds() 28 self._set_target_cmds()
30 29
@@ -66,11 +65,11 @@ class OERuntimeTestContextExecutor(OETestContextExecutor):
66 % self.default_target_type) 65 % self.default_target_type)
67 runtime_group.add_argument('--target-ip', action='store', 66 runtime_group.add_argument('--target-ip', action='store',
68 default=self.default_target_ip, 67 default=self.default_target_ip,
69 help="IP address of device under test, default: %s" \ 68 help="IP address and optionally ssh port (default 22) of device under test, for example '192.168.0.7:22'. Default: %s" \
70 % self.default_target_ip) 69 % self.default_target_ip)
71 runtime_group.add_argument('--server-ip', action='store', 70 runtime_group.add_argument('--server-ip', action='store',
72 default=self.default_target_ip, 71 default=self.default_target_ip,
73 help="IP address of device under test, default: %s" \ 72 help="IP address of the test host from test target machine, default: %s" \
74 % self.default_server_ip) 73 % self.default_server_ip)
75 74
76 runtime_group.add_argument('--host-dumper-dir', action='store', 75 runtime_group.add_argument('--host-dumper-dir', action='store',
@@ -119,8 +118,7 @@ class OERuntimeTestContextExecutor(OETestContextExecutor):
119 # XXX: Don't base your targets on this code it will be refactored 118 # XXX: Don't base your targets on this code it will be refactored
120 # in the near future. 119 # in the near future.
121 # Custom target module loading 120 # Custom target module loading
122 target_modules_path = kwargs.get('target_modules_path', '') 121 controller = OERuntimeTestContextExecutor.getControllerModule(target_type)
123 controller = OERuntimeTestContextExecutor.getControllerModule(target_type, target_modules_path)
124 target = controller(logger, target_ip, server_ip, **kwargs) 122 target = controller(logger, target_ip, server_ip, **kwargs)
125 123
126 return target 124 return target
@@ -130,15 +128,15 @@ class OERuntimeTestContextExecutor(OETestContextExecutor):
130 # AttributeError raised if not found. 128 # AttributeError raised if not found.
131 # ImportError raised if a provided module can not be imported. 129 # ImportError raised if a provided module can not be imported.
132 @staticmethod 130 @staticmethod
133 def getControllerModule(target, target_modules_path): 131 def getControllerModule(target):
134 controllerslist = OERuntimeTestContextExecutor._getControllerModulenames(target_modules_path) 132 controllerslist = OERuntimeTestContextExecutor._getControllerModulenames()
135 controller = OERuntimeTestContextExecutor._loadControllerFromName(target, controllerslist) 133 controller = OERuntimeTestContextExecutor._loadControllerFromName(target, controllerslist)
136 return controller 134 return controller
137 135
138 # Return a list of all python modules in lib/oeqa/controllers for each 136 # Return a list of all python modules in lib/oeqa/controllers for each
139 # layer in bbpath 137 # layer in bbpath
140 @staticmethod 138 @staticmethod
141 def _getControllerModulenames(target_modules_path): 139 def _getControllerModulenames():
142 140
143 controllerslist = [] 141 controllerslist = []
144 142
@@ -153,9 +151,12 @@ class OERuntimeTestContextExecutor(OETestContextExecutor):
153 else: 151 else:
154 raise RuntimeError("Duplicate controller module found for %s. Layers should create unique controller module names" % module) 152 raise RuntimeError("Duplicate controller module found for %s. Layers should create unique controller module names" % module)
155 153
156 extpath = target_modules_path.split(':') 154 # sys.path can contain duplicate paths, but because of the login in
157 for p in extpath: 155 # add_controller_list this doesn't work and causes testimage to abort.
158 controllerpath = os.path.join(p, 'lib', 'oeqa', 'controllers') 156 # Remove duplicates using an intermediate dictionary to ensure this
157 # doesn't happen.
158 for p in list(dict.fromkeys(sys.path)):
159 controllerpath = os.path.join(p, 'oeqa', 'controllers')
159 if os.path.exists(controllerpath): 160 if os.path.exists(controllerpath):
160 add_controller_list(controllerpath) 161 add_controller_list(controllerpath)
161 return controllerslist 162 return controllerslist
@@ -175,16 +176,12 @@ class OERuntimeTestContextExecutor(OETestContextExecutor):
175 # Search for and return a controller or None from given module name 176 # Search for and return a controller or None from given module name
176 @staticmethod 177 @staticmethod
177 def _loadControllerFromModule(target, modulename): 178 def _loadControllerFromModule(target, modulename):
178 obj = None
179 # import module, allowing it to raise import exception
180 module = __import__(modulename, globals(), locals(), [target])
181 # look for target class in the module, catching any exceptions as it
182 # is valid that a module may not have the target class.
183 try: 179 try:
184 obj = getattr(module, target) 180 import importlib
185 except: 181 module = importlib.import_module(modulename)
186 obj = None 182 return getattr(module, target)
187 return obj 183 except AttributeError:
184 return None
188 185
189 @staticmethod 186 @staticmethod
190 def readPackagesManifest(manifest): 187 def readPackagesManifest(manifest):
@@ -200,10 +197,6 @@ class OERuntimeTestContextExecutor(OETestContextExecutor):
200 197
201 return image_packages 198 return image_packages
202 199
203 @staticmethod
204 def getHostDumper(cmds, directory):
205 return HostDumper(cmds, directory)
206
207 def _process_args(self, logger, args): 200 def _process_args(self, logger, args):
208 if not args.packages_manifest: 201 if not args.packages_manifest:
209 raise TypeError('Manifest file not provided') 202 raise TypeError('Manifest file not provided')
@@ -216,9 +209,6 @@ class OERuntimeTestContextExecutor(OETestContextExecutor):
216 self.tc_kwargs['init']['target'] = \ 209 self.tc_kwargs['init']['target'] = \
217 OERuntimeTestContextExecutor.getTarget(args.target_type, 210 OERuntimeTestContextExecutor.getTarget(args.target_type,
218 None, args.target_ip, args.server_ip, **target_kwargs) 211 None, args.target_ip, args.server_ip, **target_kwargs)
219 self.tc_kwargs['init']['host_dumper'] = \
220 OERuntimeTestContextExecutor.getHostDumper(None,
221 args.host_dumper_dir)
222 self.tc_kwargs['init']['image_packages'] = \ 212 self.tc_kwargs['init']['image_packages'] = \
223 OERuntimeTestContextExecutor.readPackagesManifest( 213 OERuntimeTestContextExecutor.readPackagesManifest(
224 args.packages_manifest) 214 args.packages_manifest)
diff --git a/meta/lib/oeqa/runtime/decorator/package.py b/meta/lib/oeqa/runtime/decorator/package.py
index 57178655cc..b78ac9fc38 100644
--- a/meta/lib/oeqa/runtime/decorator/package.py
+++ b/meta/lib/oeqa/runtime/decorator/package.py
@@ -5,7 +5,6 @@
5# 5#
6 6
7from oeqa.core.decorator import OETestDecorator, registerDecorator 7from oeqa.core.decorator import OETestDecorator, registerDecorator
8from oeqa.core.utils.misc import strToSet
9 8
10@registerDecorator 9@registerDecorator
11class OEHasPackage(OETestDecorator): 10class OEHasPackage(OETestDecorator):
@@ -34,25 +33,30 @@ class OEHasPackage(OETestDecorator):
34 def setUpDecorator(self): 33 def setUpDecorator(self):
35 need_pkgs = set() 34 need_pkgs = set()
36 unneed_pkgs = set() 35 unneed_pkgs = set()
37 pkgs = strToSet(self.need_pkgs) 36
38 for pkg in pkgs: 37 # Turn literal strings into a list so we can just iterate over it
38 if isinstance(self.need_pkgs, str):
39 self.need_pkgs = [self.need_pkgs,]
40
41 mlprefix = self.case.td.get("MLPREFIX")
42 for pkg in self.need_pkgs:
39 if pkg.startswith('!'): 43 if pkg.startswith('!'):
40 unneed_pkgs.add(pkg[1:]) 44 unneed_pkgs.add(mlprefix + pkg[1:])
41 else: 45 else:
42 need_pkgs.add(pkg) 46 need_pkgs.add(mlprefix + pkg)
43 47
44 if unneed_pkgs: 48 if unneed_pkgs:
45 msg = 'Checking if %s is not installed' % ', '.join(unneed_pkgs) 49 msg = 'Checking if %s is not installed' % ', '.join(unneed_pkgs)
46 self.logger.debug(msg) 50 self.logger.debug(msg)
47 if not self.case.tc.image_packages.isdisjoint(unneed_pkgs): 51 if not self.case.tc.image_packages.isdisjoint(unneed_pkgs):
48 msg = "Test can't run with %s installed" % ', or'.join(unneed_pkgs) 52 msg = "Test can't run with %s installed" % ', or '.join(unneed_pkgs)
49 self._decorator_fail(msg) 53 self._decorator_fail(msg)
50 54
51 if need_pkgs: 55 if need_pkgs:
52 msg = 'Checking if at least one of %s is installed' % ', '.join(need_pkgs) 56 msg = 'Checking if at least one of %s is installed' % ', '.join(need_pkgs)
53 self.logger.debug(msg) 57 self.logger.debug(msg)
54 if self.case.tc.image_packages.isdisjoint(need_pkgs): 58 if self.case.tc.image_packages.isdisjoint(need_pkgs):
55 msg = "Test requires %s to be installed" % ', or'.join(need_pkgs) 59 msg = "Test requires %s to be installed" % ', or '.join(need_pkgs)
56 self._decorator_fail(msg) 60 self._decorator_fail(msg)
57 61
58 def _decorator_fail(self, msg): 62 def _decorator_fail(self, msg):
diff --git a/meta/lib/oeqa/runtime/files/hello.stp b/meta/lib/oeqa/runtime/files/hello.stp
deleted file mode 100644
index 3677147162..0000000000
--- a/meta/lib/oeqa/runtime/files/hello.stp
+++ /dev/null
@@ -1 +0,0 @@
1probe oneshot { println("hello world") }