diff options
Diffstat (limited to 'meta')
-rw-r--r-- | meta/classes/testimage.bbclass | 107 | ||||
-rw-r--r-- | meta/lib/oeqa/oetest.py | 17 |
2 files changed, 98 insertions, 26 deletions
diff --git a/meta/classes/testimage.bbclass b/meta/classes/testimage.bbclass index 4777e140dc..75ab716270 100644 --- a/meta/classes/testimage.bbclass +++ b/meta/classes/testimage.bbclass | |||
@@ -25,15 +25,16 @@ | |||
25 | 25 | ||
26 | TEST_LOG_DIR ?= "${WORKDIR}/testimage" | 26 | TEST_LOG_DIR ?= "${WORKDIR}/testimage" |
27 | 27 | ||
28 | TEST_EXPORT_DIR ?= "${TMPDIR}/testimage/${PN}" | ||
29 | TEST_EXPORT_ONLY ?= "0" | ||
30 | |||
28 | DEFAULT_TEST_SUITES = "ping auto" | 31 | DEFAULT_TEST_SUITES = "ping auto" |
29 | DEFAULT_TEST_SUITES_pn-core-image-minimal = "ping" | 32 | DEFAULT_TEST_SUITES_pn-core-image-minimal = "ping" |
30 | DEFAULT_TEST_SUITES_pn-core-image-sato = "ping ssh df connman syslog xorg scp vnc date rpm smart dmesg python" | 33 | DEFAULT_TEST_SUITES_pn-core-image-sato = "ping ssh df connman syslog xorg scp vnc date rpm smart dmesg python" |
31 | DEFAULT_TEST_SUITES_pn-core-image-sato-sdk = "ping ssh df connman syslog xorg scp vnc date perl ldd gcc rpm smart kernelmodule dmesg python" | 34 | DEFAULT_TEST_SUITES_pn-core-image-sato-sdk = "ping ssh df connman syslog xorg scp vnc date perl ldd gcc rpm smart kernelmodule dmesg python" |
32 | |||
33 | TEST_SUITES ?= "${DEFAULT_TEST_SUITES}" | 35 | TEST_SUITES ?= "${DEFAULT_TEST_SUITES}" |
34 | 36 | ||
35 | TEST_QEMUBOOT_TIMEOUT ?= "1000" | 37 | TEST_QEMUBOOT_TIMEOUT ?= "1000" |
36 | |||
37 | TEST_TARGET ?= "qemu" | 38 | TEST_TARGET ?= "qemu" |
38 | TEST_TARGET_IP ?= "" | 39 | TEST_TARGET_IP ?= "" |
39 | TEST_SERVER_IP ?= "" | 40 | TEST_SERVER_IP ?= "" |
@@ -85,6 +86,71 @@ def get_tests_list(d): | |||
85 | 86 | ||
86 | return testslist | 87 | return testslist |
87 | 88 | ||
89 | |||
90 | def exportTests(d,tc): | ||
91 | import json | ||
92 | import shutil | ||
93 | import pkgutil | ||
94 | |||
95 | exportpath = d.getVar("TEST_EXPORT_DIR", True) | ||
96 | |||
97 | savedata = {} | ||
98 | savedata["d"] = {} | ||
99 | savedata["target"] = {} | ||
100 | for key in tc.__dict__: | ||
101 | # special cases | ||
102 | if key != "d" and key != "target": | ||
103 | savedata[key] = getattr(tc, key) | ||
104 | savedata["target"]["ip"] = tc.target.ip or d.getVar("TEST_TARGET_IP", True) | ||
105 | savedata["target"]["server_ip"] = tc.target.server_ip or d.getVar("TEST_SERVER_IP", True) | ||
106 | |||
107 | keys = [ key for key in d.keys() if not key.startswith("_") and not key.startswith("BB") \ | ||
108 | and not key.startswith("B_pn") and not key.startswith("do_") and not d.getVarFlag(key, "func")] | ||
109 | for key in keys: | ||
110 | try: | ||
111 | savedata["d"][key] = d.getVar(key, True) | ||
112 | except bb.data_smart.ExpansionError: | ||
113 | # we don't care about those anyway | ||
114 | pass | ||
115 | |||
116 | with open(os.path.join(exportpath, "testdata.json"), "w") as f: | ||
117 | json.dump(savedata, f, skipkeys=True, indent=4, sort_keys=True) | ||
118 | |||
119 | # now start copying files | ||
120 | # we'll basically copy everything under meta/lib/oeqa, with these exceptions | ||
121 | # - oeqa/targetcontrol.py - not needed | ||
122 | # - oeqa/selftest - something else | ||
123 | # That means: | ||
124 | # - all tests from oeqa/runtime defined in TEST_SUITES (including from other layers) | ||
125 | # - the contents of oeqa/utils and oeqa/runtime/files | ||
126 | # - oeqa/oetest.py and oeqa/runexport.py (this will get copied to exportpath not exportpath/oeqa) | ||
127 | # - __init__.py files | ||
128 | bb.utils.mkdirhier(os.path.join(exportpath, "oeqa/runtime/files")) | ||
129 | bb.utils.mkdirhier(os.path.join(exportpath, "oeqa/utils")) | ||
130 | # copy test modules, this should cover tests in other layers too | ||
131 | for t in tc.testslist: | ||
132 | mod = pkgutil.get_loader(t) | ||
133 | shutil.copy2(mod.filename, os.path.join(exportpath, "oeqa/runtime")) | ||
134 | # copy __init__.py files | ||
135 | oeqadir = pkgutil.get_loader("oeqa").filename | ||
136 | shutil.copy2(os.path.join(oeqadir, "__init__.py"), os.path.join(exportpath, "oeqa")) | ||
137 | shutil.copy2(os.path.join(oeqadir, "runtime/__init__.py"), os.path.join(exportpath, "oeqa/runtime")) | ||
138 | # copy oeqa/oetest.py and oeqa/runexported.py | ||
139 | shutil.copy2(os.path.join(oeqadir, "oetest.py"), os.path.join(exportpath, "oeqa")) | ||
140 | shutil.copy2(os.path.join(oeqadir, "runexported.py"), exportpath) | ||
141 | # copy oeqa/utils/*.py | ||
142 | for root, dirs, files in os.walk(os.path.join(oeqadir, "utils")): | ||
143 | for f in files: | ||
144 | if f.endswith(".py"): | ||
145 | shutil.copy2(os.path.join(root, f), os.path.join(exportpath, "oeqa/utils")) | ||
146 | # copy oeqa/runtime/files/* | ||
147 | for root, dirs, files in os.walk(os.path.join(oeqadir, "runtime/files")): | ||
148 | for f in files: | ||
149 | shutil.copy2(os.path.join(root, f), os.path.join(exportpath, "oeqa/runtime/files")) | ||
150 | |||
151 | bb.plain("Exported tests to: %s" % exportpath) | ||
152 | |||
153 | |||
88 | def testimage_main(d): | 154 | def testimage_main(d): |
89 | import unittest | 155 | import unittest |
90 | import os | 156 | import os |
@@ -94,7 +160,11 @@ def testimage_main(d): | |||
94 | from oeqa.targetcontrol import get_target_controller | 160 | from oeqa.targetcontrol import get_target_controller |
95 | 161 | ||
96 | pn = d.getVar("PN", True) | 162 | pn = d.getVar("PN", True) |
163 | export = oe.utils.conditional("TEST_EXPORT_ONLY", "1", True, False, d) | ||
97 | bb.utils.mkdirhier(d.getVar("TEST_LOG_DIR", True)) | 164 | bb.utils.mkdirhier(d.getVar("TEST_LOG_DIR", True)) |
165 | if export: | ||
166 | bb.utils.remove(d.getVar("TEST_EXPORT_DIR", True), recurse=True) | ||
167 | bb.utils.mkdirhier(d.getVar("TEST_EXPORT_DIR", True)) | ||
98 | 168 | ||
99 | # tests in TEST_SUITES become required tests | 169 | # tests in TEST_SUITES become required tests |
100 | # they won't be skipped even if they aren't suitable for a image (like xorg for minimal) | 170 | # they won't be skipped even if they aren't suitable for a image (like xorg for minimal) |
@@ -105,13 +175,18 @@ def testimage_main(d): | |||
105 | # the robot dance | 175 | # the robot dance |
106 | target = get_target_controller(d) | 176 | target = get_target_controller(d) |
107 | 177 | ||
108 | class TestContext: | 178 | class TestContext(object): |
109 | def __init__(self): | 179 | def __init__(self): |
110 | self.d = d | 180 | self.d = d |
111 | self.testslist = testslist | 181 | self.testslist = testslist |
112 | self.testsrequired = testsrequired | 182 | self.testsrequired = testsrequired |
113 | self.filesdir = os.path.join(os.path.dirname(os.path.abspath(oeqa.runtime.__file__)),"files") | 183 | self.filesdir = os.path.join(os.path.dirname(os.path.abspath(oeqa.runtime.__file__)),"files") |
114 | self.target = target | 184 | self.target = target |
185 | self.imagefeatures = d.getVar("IMAGE_FEATURES", True).split() | ||
186 | self.distrofeatures = d.getVar("DISTRO_FEATURES", True).split() | ||
187 | manifest = os.path.join(d.getVar("DEPLOY_DIR_IMAGE", True), d.getVar("IMAGE_LINK_NAME", True) + ".manifest") | ||
188 | with open(manifest) as f: | ||
189 | self.pkgmanifest = f.read() | ||
115 | 190 | ||
116 | # test context | 191 | # test context |
117 | tc = TestContext() | 192 | tc = TestContext() |
@@ -129,19 +204,21 @@ def testimage_main(d): | |||
129 | 204 | ||
130 | try: | 205 | try: |
131 | target.start() | 206 | target.start() |
132 | # run tests and get the results | 207 | if export: |
133 | starttime = time.time() | 208 | exportTests(d,tc) |
134 | result = runTests(tc) | ||
135 | stoptime = time.time() | ||
136 | if result.wasSuccessful(): | ||
137 | bb.plain("%s - Ran %d test%s in %.3fs" % (pn, result.testsRun, result.testsRun != 1 and "s" or "", stoptime - starttime)) | ||
138 | msg = "%s - OK - All required tests passed" % pn | ||
139 | skipped = len(result.skipped) | ||
140 | if skipped: | ||
141 | msg += " (skipped=%d)" % skipped | ||
142 | bb.plain(msg) | ||
143 | else: | 209 | else: |
144 | raise bb.build.FuncFailed("%s - FAILED - check the task log and the ssh log" % pn ) | 210 | starttime = time.time() |
211 | result = runTests(tc) | ||
212 | stoptime = time.time() | ||
213 | if result.wasSuccessful(): | ||
214 | bb.plain("%s - Ran %d test%s in %.3fs" % (pn, result.testsRun, result.testsRun != 1 and "s" or "", stoptime - starttime)) | ||
215 | msg = "%s - OK - All required tests passed" % pn | ||
216 | skipped = len(result.skipped) | ||
217 | if skipped: | ||
218 | msg += " (skipped=%d)" % skipped | ||
219 | bb.plain(msg) | ||
220 | else: | ||
221 | raise bb.build.FuncFailed("%s - FAILED - check the task log and the ssh log" % pn ) | ||
145 | finally: | 222 | finally: |
146 | target.stop() | 223 | target.stop() |
147 | 224 | ||
diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py index 23a3e5d69f..0db6cb80a9 100644 --- a/meta/lib/oeqa/oetest.py +++ b/meta/lib/oeqa/oetest.py | |||
@@ -10,8 +10,6 @@ | |||
10 | import os, re, mmap | 10 | import os, re, mmap |
11 | import unittest | 11 | import unittest |
12 | import inspect | 12 | import inspect |
13 | import bb | ||
14 | from oeqa.utils.sshcontrol import SSHControl | ||
15 | 13 | ||
16 | 14 | ||
17 | def loadTests(tc): | 15 | def loadTests(tc): |
@@ -31,15 +29,14 @@ def loadTests(tc): | |||
31 | def runTests(tc): | 29 | def runTests(tc): |
32 | 30 | ||
33 | suite = loadTests(tc) | 31 | suite = loadTests(tc) |
34 | bb.note("Test modules %s" % tc.testslist) | 32 | print("Test modules %s" % tc.testslist) |
35 | bb.note("Found %s tests" % suite.countTestCases()) | 33 | print("Found %s tests" % suite.countTestCases()) |
36 | runner = unittest.TextTestRunner(verbosity=2) | 34 | runner = unittest.TextTestRunner(verbosity=2) |
37 | result = runner.run(suite) | 35 | result = runner.run(suite) |
38 | 36 | ||
39 | return result | 37 | return result |
40 | 38 | ||
41 | 39 | ||
42 | |||
43 | class oeTest(unittest.TestCase): | 40 | class oeTest(unittest.TestCase): |
44 | 41 | ||
45 | longMessage = True | 42 | longMessage = True |
@@ -60,18 +57,16 @@ class oeTest(unittest.TestCase): | |||
60 | 57 | ||
61 | @classmethod | 58 | @classmethod |
62 | def hasPackage(self, pkg): | 59 | def hasPackage(self, pkg): |
63 | manifest = os.path.join(oeTest.tc.d.getVar("DEPLOY_DIR_IMAGE", True), oeTest.tc.d.getVar("IMAGE_LINK_NAME", True) + ".manifest") | 60 | |
64 | with open(manifest) as f: | 61 | if re.search(pkg, oeTest.tc.pkgmanifest): |
65 | data = f.read() | ||
66 | if re.search(pkg, data): | ||
67 | return True | 62 | return True |
68 | return False | 63 | return False |
69 | 64 | ||
70 | @classmethod | 65 | @classmethod |
71 | def hasFeature(self,feature): | 66 | def hasFeature(self,feature): |
72 | 67 | ||
73 | if feature in oeTest.tc.d.getVar("IMAGE_FEATURES", True).split() or \ | 68 | if feature in oeTest.tc.imagefeatures or \ |
74 | feature in oeTest.tc.d.getVar("DISTRO_FEATURES", True).split(): | 69 | feature in oeTest.tc.distrofeatures: |
75 | return True | 70 | return True |
76 | else: | 71 | else: |
77 | return False | 72 | return False |