diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2018-07-19 20:31:35 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2018-07-24 11:52:27 +0100 |
commit | 6d66b574090dbfa17f840e45c9920895c4e2784a (patch) | |
tree | 2aa6692e9e486c86ac98bd0802eacec008c4e615 /meta/lib/oeqa | |
parent | 4c67ffef2e50b6e0be1530ea332e69afa025574c (diff) | |
download | poky-6d66b574090dbfa17f840e45c9920895c4e2784a.tar.gz |
utils: Add multiprocess_launch API and testcase
The current methods of spawning processes for parallel execution have
issues around collection of results or exceptions.
Take the code from package_ipk/deb, make it generic, add a results
collection mechanism, fix the exception handling and for it into a
standard library function.
Also add a test case which tests both the success and failure modes
of operation to stop this functionality regressiing again.
In particular, compared to multiprocess_exec, this fork off the parent
approach means we can pass in the datastore and functions work in the
same scope as the parent. This removes some of the complexities
found trying to scale multiprocess_exec to wider use.
(From OE-Core rev: 88f0c214e593a45566df5131bda4c946f5ccc8c2)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/oeqa')
-rw-r--r-- | meta/lib/oeqa/selftest/cases/oelib/utils.py | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/meta/lib/oeqa/selftest/cases/oelib/utils.py b/meta/lib/oeqa/selftest/cases/oelib/utils.py index 9fb6c1576e..275aeda74e 100644 --- a/meta/lib/oeqa/selftest/cases/oelib/utils.py +++ b/meta/lib/oeqa/selftest/cases/oelib/utils.py | |||
@@ -1,5 +1,8 @@ | |||
1 | import sys | ||
1 | from unittest.case import TestCase | 2 | from unittest.case import TestCase |
2 | from oe.utils import packages_filter_out_system, trim_version | 3 | from contextlib import contextmanager |
4 | from io import StringIO | ||
5 | from oe.utils import packages_filter_out_system, trim_version, multiprocess_launch | ||
3 | 6 | ||
4 | class TestPackagesFilterOutSystem(TestCase): | 7 | class TestPackagesFilterOutSystem(TestCase): |
5 | def test_filter(self): | 8 | def test_filter(self): |
@@ -49,3 +52,44 @@ class TestTrimVersion(TestCase): | |||
49 | self.assertEqual(trim_version("1.2.3", 2), "1.2") | 52 | self.assertEqual(trim_version("1.2.3", 2), "1.2") |
50 | self.assertEqual(trim_version("1.2.3", 3), "1.2.3") | 53 | self.assertEqual(trim_version("1.2.3", 3), "1.2.3") |
51 | self.assertEqual(trim_version("1.2.3", 4), "1.2.3") | 54 | self.assertEqual(trim_version("1.2.3", 4), "1.2.3") |
55 | |||
56 | |||
57 | class TestMultiprocessLaunch(TestCase): | ||
58 | |||
59 | def test_multiprocesslaunch(self): | ||
60 | import bb | ||
61 | |||
62 | def testfunction(item, d): | ||
63 | if item == "2" or item == "1": | ||
64 | raise KeyError("Invalid number %s" % item) | ||
65 | return "Found %s" % item | ||
66 | |||
67 | def dummyerror(msg): | ||
68 | print("ERROR: %s" % msg) | ||
69 | |||
70 | @contextmanager | ||
71 | def captured_output(): | ||
72 | new_out, new_err = StringIO(), StringIO() | ||
73 | old_out, old_err = sys.stdout, sys.stderr | ||
74 | try: | ||
75 | sys.stdout, sys.stderr = new_out, new_err | ||
76 | yield sys.stdout, sys.stderr | ||
77 | finally: | ||
78 | sys.stdout, sys.stderr = old_out, old_err | ||
79 | |||
80 | d = bb.data_smart.DataSmart() | ||
81 | bb.error = dummyerror | ||
82 | |||
83 | # Assert the function returns the right results | ||
84 | result = multiprocess_launch(testfunction, ["3", "4", "5", "6"], d, extraargs=(d,)) | ||
85 | self.assertIn("Found 3", result) | ||
86 | self.assertIn("Found 4", result) | ||
87 | self.assertIn("Found 5", result) | ||
88 | self.assertIn("Found 6", result) | ||
89 | self.assertEqual(len(result), 4) | ||
90 | |||
91 | # Assert the function prints exceptions | ||
92 | with captured_output() as (out, err): | ||
93 | self.assertRaises(bb.BBHandledException, multiprocess_launch, testfunction, ["1", "2", "3", "4", "5", "6"], d, extraargs=(d,)) | ||
94 | self.assertIn("KeyError: 'Invalid number 1'", out.getvalue()) | ||
95 | self.assertIn("KeyError: 'Invalid number 2'", out.getvalue()) | ||