summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/classes-recipe/testimage.bbclass41
-rw-r--r--meta/lib/oeqa/utils/postactions.py68
2 files changed, 70 insertions, 39 deletions
diff --git a/meta/classes-recipe/testimage.bbclass b/meta/classes-recipe/testimage.bbclass
index 959c226072..ad040ee8f0 100644
--- a/meta/classes-recipe/testimage.bbclass
+++ b/meta/classes-recipe/testimage.bbclass
@@ -170,40 +170,6 @@ def get_testimage_boot_patterns(d):
170 boot_patterns[flag] = flagval.encode().decode('unicode-escape') 170 boot_patterns[flag] = flagval.encode().decode('unicode-escape')
171 return boot_patterns 171 return boot_patterns
172 172
173def get_artifacts_list(target, raw_list):
174 result = []
175 # Passed list may contains patterns in paths, expand them directly on target
176 for raw_path in raw_list.split():
177 cmd = f"for p in {raw_path}; do if [ -e $p ]; then echo $p; fi; done"
178 try:
179 status, output = target.run(cmd)
180 if status != 0 or not output:
181 raise Exception()
182 result += output.split()
183 except:
184 bb.note(f"No file/directory matching path {raw_path}")
185
186 return result
187
188def retrieve_test_artifacts(target, artifacts_list, target_dir):
189 import shutil
190
191 local_artifacts_dir = os.path.join(target_dir, "artifacts")
192 if os.path.isdir(local_artifacts_dir):
193 shutil.rmtree(local_artifacts_dir)
194
195 os.makedirs(local_artifacts_dir)
196 for artifact_path in artifacts_list:
197 if not os.path.isabs(artifact_path):
198 bb.warn(f"{artifact_path} is not an absolute path")
199 continue
200 try:
201 dest_dir = os.path.join(local_artifacts_dir, os.path.dirname(artifact_path[1:]))
202 os.makedirs(dest_dir, exist_ok=True)
203 target.copyFrom(artifact_path, dest_dir)
204 except Exception as e:
205 bb.warn(f"Can not retrieve {artifact_path} from test target: {e}")
206
207def testimage_main(d): 173def testimage_main(d):
208 import os 174 import os
209 import json 175 import json
@@ -218,6 +184,7 @@ def testimage_main(d):
218 from oeqa.core.utils.test import getSuiteCases 184 from oeqa.core.utils.test import getSuiteCases
219 from oeqa.utils import make_logger_bitbake_compatible 185 from oeqa.utils import make_logger_bitbake_compatible
220 from oeqa.utils import get_json_result_dir 186 from oeqa.utils import get_json_result_dir
187 from oeqa.utils.postactions import run_failed_tests_post_actions
221 188
222 def sigterm_exception(signum, stackframe): 189 def sigterm_exception(signum, stackframe):
223 """ 190 """
@@ -400,11 +367,7 @@ def testimage_main(d):
400 results = tc.runTests() 367 results = tc.runTests()
401 complete = True 368 complete = True
402 if results.hasAnyFailingTest(): 369 if results.hasAnyFailingTest():
403 artifacts_list = get_artifacts_list(tc.target, d.getVar("TESTIMAGE_FAILED_QA_ARTIFACTS")) 370 run_failed_tests_post_actions(d, tc)
404 if not artifacts_list:
405 bb.warn("Could not load artifacts list, skip artifacts retrieval")
406 else:
407 retrieve_test_artifacts(tc.target, artifacts_list, get_testimage_json_result_dir(d))
408 except (KeyboardInterrupt, BlockingIOError) as err: 371 except (KeyboardInterrupt, BlockingIOError) as err:
409 if isinstance(err, KeyboardInterrupt): 372 if isinstance(err, KeyboardInterrupt):
410 bb.error('testimage interrupted, shutting down...') 373 bb.error('testimage interrupted, shutting down...')
diff --git a/meta/lib/oeqa/utils/postactions.py b/meta/lib/oeqa/utils/postactions.py
new file mode 100644
index 0000000000..09c338ef68
--- /dev/null
+++ b/meta/lib/oeqa/utils/postactions.py
@@ -0,0 +1,68 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: MIT
5#
6
7# Run a set of actions after tests. The runner provides internal data
8# dictionary as well as test context to any action to run.
9
10from oeqa.utils import get_json_result_dir
11
12##################################################################
13# Artifacts retrieval
14##################################################################
15
16def get_artifacts_list(target, raw_list):
17 result = []
18 # Passed list may contains patterns in paths, expand them directly on target
19 for raw_path in raw_list.split():
20 cmd = f"for p in {raw_path}; do if [ -e $p ]; then echo $p; fi; done"
21 try:
22 status, output = target.run(cmd)
23 if status != 0 or not output:
24 raise Exception()
25 result += output.split()
26 except:
27 bb.note(f"No file/directory matching path {raw_path}")
28
29 return result
30
31def retrieve_test_artifacts(target, artifacts_list, target_dir):
32 import shutil
33
34 local_artifacts_dir = os.path.join(target_dir, "artifacts")
35 if os.path.isdir(local_artifacts_dir):
36 shutil.rmtree(local_artifacts_dir)
37
38 os.makedirs(local_artifacts_dir)
39 for artifact_path in artifacts_list:
40 if not os.path.isabs(artifact_path):
41 bb.warn(f"{artifact_path} is not an absolute path")
42 continue
43 try:
44 dest_dir = os.path.join(local_artifacts_dir, os.path.dirname(artifact_path[1:]))
45 os.makedirs(dest_dir, exist_ok=True)
46 target.copyFrom(artifact_path, dest_dir)
47 except Exception as e:
48 bb.warn(f"Can not retrieve {artifact_path} from test target: {e}")
49
50def list_and_fetch_failed_tests_artifacts(d, tc):
51 artifacts_list = get_artifacts_list(tc.target, d.getVar("TESTIMAGE_FAILED_QA_ARTIFACTS"))
52 if not artifacts_list:
53 bb.warn("Could not load artifacts list, skip artifacts retrieval")
54 else:
55 retrieve_test_artifacts(tc.target, artifacts_list, get_json_result_dir(d))
56
57
58##################################################################
59# General post actions runner
60##################################################################
61
62def run_failed_tests_post_actions(d, tc):
63 post_actions=[
64 list_and_fetch_failed_tests_artifacts
65 ]
66
67 for action in post_actions:
68 action(d, tc)