Revive ptest and add result to buildhistory
cover Revive ptest and add result to buildhistory
We can get the regression result by:
$ git show HEAD ptest_log/pass.fail.skip.*
Can we add ptest to default TEST_SUITES, please ?
// Robert
The following changes since commit a2ab288bd002ebb6e64d46e941fb122e1157ff49:
uninative: Update to 1.7 uninative release (2017-07-30 08:45:49 +0100)
are available in the git repository at:
git://git.openembedded.org/openembedded-core-contrib rbt/ptest
http://cgit.openembedded.org/openembedded-core-contrib/log/?h=rbt/ptest
Robert Yang (10):
oeqa/targetcontrol.py: simplify checking for qemu_use_kvm runtime/cases/_ptest.py: revive it oeqa/utils/logparser.py: add skip status runtime/cases/_ptest.py: add skip status runtime/cases/_ptest.py: rename it to ptest.py utils/logparser.py: fix section check core/target/ssh.py: replace decode errors buildhistory.bbclass: print message when no commit buildhistory.bbclass: add ptest_log testimage.bbclass: update comments
meta/classes/buildhistory.bbclass | 30 ++++++++++ meta/classes/testimage.bbclass | 4 +- meta/lib/oeqa/core/target/ssh.py | 4 +- meta/lib/oeqa/runtime/cases/_ptest.py | 103 ---------------------------------- meta/lib/oeqa/runtime/cases/ptest.py | 82 +++++++++++++++++++++++++++ meta/lib/oeqa/targetcontrol.py | 5 +- meta/lib/oeqa/utils/logparser.py | 7 ++- 7 files changed, 122 insertions(+), 113 deletions(-) delete mode 100644 meta/lib/oeqa/runtime/cases/_ptest.py create mode 100644 meta/lib/oeqa/runtime/cases/ptest.py
Signature · 1 line
2.11.0
PATCH 1/10 oeqa/targetcontrol.py: simplify checking for qemu_use_kvm
The "if qemu_use_kvm" is not needed.
--- meta/lib/oeqa/targetcontrol.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
meta/lib/oeqa/targetcontrol.py +2 -3
@@ -132,9 +132,8 @@ class QemuTarget(BaseTarget): dump_host_cmds = d.getVar("testimage_dump_host") dump_dir = d.getVar("TESTIMAGE_DUMP_DIR") qemu_use_kvm = d.getVar("QEMU_USE_KVM") - if qemu_use_kvm and \ - (qemu_use_kvm == "True" and "x86" in d.getVar("MACHINE") or \ - d.getVar("MACHINE") in qemu_use_kvm.split()): + if qemu_use_kvm == "True" and "x86" in d.getVar("MACHINE") or \ + d.getVar("MACHINE") in qemu_use_kvm.split(): use_kvm = True else: use_kvm = False
Signature · 1 line
2.11.0
Re: [PATCH 01/10] oeqa/targetcontrol.py: simplify checking for qemu_use_kvm
Quoted 21 lines · Robert Yang
The "if
qemu_use_kvm" is not needed.Signed-off-by Robert Yang <[email protected]>---
meta/lib/oeqa/targetcontrol.py | 5 ++---1 file changed, 2 insertions(+), 3 deletions(-)meta/lib/oeqa/targetcontrol.py +2
-3@@ -132,9 +132,8 @@ class QemuTarget(BaseTarget): dump_host_cmds = d.getVar("testimage_dump_host") dump_dir = d.getVar("TESTIMAGE_DUMP_DIR") qemu_use_kvm = d.getVar("QEMU_USE_KVM") - if qemu_use_kvm and \ - (qemu_use_kvm == "True" and "x86" in d.getVar("MACHINE") or \ - d.getVar("MACHINE") in qemu_use_kvm.split()): + if qemu_use_kvm == "True" and "x86" in d.getVar("MACHINE") or \ + d.getVar("MACHINE") in qemu_use_kvm.split():
Quoted 4 lines
use_kvm = True
else:
use_kvm = False
It is needed since qemu_use_kvm could be None and None.split() will cause an error.
Cheers,
Richard
Re: [PATCH 01/10] oeqa/targetcontrol.py: simplify checking for qemu_use_kvm
Quoted 21 lines · Richard Purdie
Quoted 20 lines · Robert Yang
The "if
qemu_use_kvm" is not needed.Signed-off-by Robert Yang <[email protected]>--- meta/lib/oeqa/targetcontrol.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)meta/lib/oeqa/targetcontrol.py +1
-3@@ -132,9 +132,8 @@ class QemuTarget(BaseTarget): dump_host_cmds = d.getVar("testimage_dump_host") dump_dir = d.getVar("TESTIMAGE_DUMP_DIR") qemu_use_kvm = d.getVar("QEMU_USE_KVM") - if qemu_use_kvm and \ - (qemu_use_kvm == "True" and "x86" in d.getVar("MACHINE") or \ - d.getVar("MACHINE") in qemu_use_kvm.split()): + if qemu_use_kvm == "True" and "x86" in d.getVar("MACHINE") or \
Quoted 8 lines
meta/lib/oeqa/targetcontrol.py class QemuTarget(BaseTarget): · line 139
Quoted 5 lines
meta/lib/oeqa/targetcontrol.py +1
-0+ d.getVar("MACHINE") in qemu_use_kvm.split(): use_kvm = True else: use_kvm = FalseIt is needed since
qemu_use_kvmcould be None andNone.split()will cause an error.
Thanks, I removed from the repo:
git://git.openembedded.org/openembedded-core-contrib rbt/ptest
http://cgit.openembedded.org/openembedded-core-contrib/log/?h=rbt/ptest
// Robert
Quoted 5 lines
Cheers,
Richard
Re: [PATCH 01/10] oeqa/targetcontrol.py: simplify checking for qemu_use_kvm
Ping.
// Robert
Quoted 45 lines · Robert Yang
Quoted 21 lines · Richard Purdie
Quoted 20 lines · Robert Yang
The "if
qemu_use_kvm" is not needed.Signed-off-by Robert Yang <[email protected]>--- meta/lib/oeqa/targetcontrol.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)meta/lib/oeqa/targetcontrol.py +1
-3@@ -132,9 +132,8 @@ class QemuTarget(BaseTarget): dump_host_cmds = d.getVar("testimage_dump_host") dump_dir = d.getVar("TESTIMAGE_DUMP_DIR") qemu_use_kvm = d.getVar("QEMU_USE_KVM") - if qemu_use_kvm and \ - (qemu_use_kvm == "True" and "x86" in d.getVar("MACHINE") or \ - d.getVar("MACHINE") in qemu_use_kvm.split()): + if qemu_use_kvm == "True" and "x86" in d.getVar("MACHINE") or \Quoted 8 lines
meta/lib/oeqa/targetcontrol.py class QemuTarget(BaseTarget): · line 139
Quoted 5 lines
meta/lib/oeqa/targetcontrol.py +1
-0+ d.getVar("MACHINE") in qemu_use_kvm.split(): use_kvm = True else: use_kvm = FalseIt is needed since
qemu_use_kvmcould be None andNone.split()will cause an error.Thanks, I removed from the repo:
git://git.openembedded.org/openembedded-core-contribrbt/ptest
http://cgit.openembedded.org/openembedded-core-contrib/log/?h=rbt/ptest// Robert
Quoted 5 lines
Cheers,
Richard
Re: [PATCH 01/10] oeqa/targetcontrol.py: simplify checking for qemu_use_kvm
Quoted 1 line · Robert Yang
Ping.
Can you repost this series please? I suspect you've changed the patches as per the feedback from Paul but I'd like to see another round of review before we consider this.
Just repushing is fine for minor changes but more significant things should be resubmitted.
Cheers,
Richard
Re: [PATCH 01/10] oeqa/targetcontrol.py: simplify checking for qemu_use_kvm
Quoted 4 lines · Richard Purdie
Quoted 1 line · Robert Yang
Ping.
Can you repost this series please? I suspect you've changed the patches
Thanks, I will repost them. And Yes, I had fixed Paul's comments.
// Robert
Quoted 10 lines
as per the feedback from Paul but I'd like to see another round of review before we consider this.
Just repushing is fine for minor changes but more significant things should be resubmitted.
Cheers,
Richard
Re: [PATCH 01/10] oeqa/targetcontrol.py: simplify checking for qemu_use_kvm
In reply to Richard PurdieQuoted 21 lines · Richard Purdie
Quoted 20 lines · Robert Yang
The "if
qemu_use_kvm" is not needed.Signed-off-by Robert Yang <[email protected]>--- meta/lib/oeqa/targetcontrol.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)meta/lib/oeqa/targetcontrol.py +1
-3@@ -132,9 +132,8 @@ class QemuTarget(BaseTarget): dump_host_cmds = d.getVar("testimage_dump_host") dump_dir = d.getVar("TESTIMAGE_DUMP_DIR") qemu_use_kvm = d.getVar("QEMU_USE_KVM") - if qemu_use_kvm and \ - (qemu_use_kvm == "True" and "x86" in d.getVar("MACHINE") or \ - d.getVar("MACHINE") in qemu_use_kvm.split()): + if qemu_use_kvm == "True" and "x86" in d.getVar("MACHINE") or \
Quoted 8 lines
meta/lib/oeqa/targetcontrol.py class QemuTarget(BaseTarget): · line 139
Quoted 5 lines
meta/lib/oeqa/targetcontrol.py +1
-0+ d.getVar("MACHINE") in qemu_use_kvm.split(): use_kvm = True else: use_kvm = FalseIt is needed since
qemu_use_kvmcould be None andNone.split()will cause an error.
Thanks, I removed it from the repo:
git://git.openembedded.org/openembedded-core-contrib rbt/ptest
http://cgit.openembedded.org/openembedded-core-contrib/log/?h=rbt/ptest
// Robert
Quoted 5 lines
Cheers,
Richard
PATCH 2/10 runtime/cases/_ptest.py: revive it
In reply to Robert Yang* Make it work with current oeqa
* Skip the test if ptest is not in DISTRO_FEATURES
* Skip the test if ptest-pkgs is not in IMAGE_FEATURES
* The logs are saved to:
testimage/ptest_log -> testimage/ptest_log.<datetime>
* Will write a tool to make regression check
[YOCTO #11547]
--- meta/lib/oeqa/runtime/cases/_ptest.py | 96 +++++++++++++---------------------- 1 file changed, 35 insertions(+), 61 deletions(-)
meta/lib/oeqa/runtime/cases/_ptest.py +35 -61
@@ -1,28 +1,10 @@ -import os -import shutil -import subprocess - from oeqa.runtime.case import OERuntimeTestCase from oeqa.core.decorator.depends import OETestDepends from oeqa.core.decorator.oeid import OETestID -from oeqa.core.decorator.data import skipIfNotDataVar, skipIfNotFeature -from oeqa.runtime.decorator.package import OEHasPackage - -from oeqa.runtime.cases.dnf import DnfTest -from oeqa.utils.logparser import * -from oeqa.utils.httpserver import HTTPService - -class PtestRunnerTest(DnfTest): +from oeqa.core.decorator.data import skipIfNotFeature +from oeqa.utils.logparser import Lparser, Result - @classmethod - def setUpClass(cls): - rpm_deploy = os.path.join(cls.tc.td['DEPLOY_DIR'], 'rpm') - cls.repo_server = HTTPService(rpm_deploy, cls.tc.target.server_ip) - cls.repo_server.start() - - @classmethod - def tearDownClass(cls): - cls.repo_server.stop() +class PtestRunnerTest(OERuntimeTestCase): # a ptest log parser def parse_ptest(self, logfile):
@@ -59,45 +41,37 @@ class PtestRunnerTest(DnfTest): result.sort_tests() return result - def _install_ptest_packages(self): - # Get ptest packages that can be installed in the image. - packages_dir = os.path.join(self.tc.td['DEPLOY_DIR'], 'rpm') - ptest_pkgs = [pkg[:pkg.find('-ptest')+6] - for _, _, filenames in os.walk(packages_dir) - for pkg in filenames - if 'ptest' in pkg - and pkg[:pkg.find('-ptest')] in self.tc.image_packages] - - repo_url = 'http://%s:%s' % (self.target.server_ip, - self.repo_server.port) - dnf_options = ('--repofrompath=oe-ptest-repo,%s ' - '--nogpgcheck ' - 'install -y' % repo_url) - self.dnf('%s %s ptest-runner' % (dnf_options, ' '.join(ptest_pkgs))) - - @skipIfNotFeature('package-management', - 'Test requires package-management to be in DISTRO_FEATURES') - @skipIfNotFeature('ptest', - 'Test requires package-management to be in DISTRO_FEATURES') - @skipIfNotDataVar('IMAGE_PKGTYPE', 'rpm', - 'RPM is not the primary package manager') - @OEHasPackage(['dnf']) + @OETestID(1600) + @skipIfNotFeature('ptest', 'Test requires ptest to be in DISTRO_FEATURES') + @skipIfNotFeature('ptest-pkgs', 'Test requires ptest-pkgs to be in IMAGE_FEATURES') @OETestDepends(['ssh.SSHTest.test_ssh']) def test_ptestrunner(self): - self.ptest_log = os.path.join(self.tc.td['TEST_LOG_DIR'], - 'ptest-%s.log' % self.tc.td['DATETIME']) - self._install_ptest_packages() - - (runnerstatus, result) = self.target.run('/usr/bin/ptest-runner > /tmp/ptest.log 2>&1', 0) - #exit code is !=0 even if ptest-runner executes because some ptest tests fail. - self.assertTrue(runnerstatus != 127, msg="Cannot execute ptest-runner!") - self.target.copyFrom('/tmp/ptest.log', self.ptest_log) - shutil.copyfile(self.ptest_log, "ptest.log") - - result = self.parse_ptest("ptest.log") - log_results_to_location = "./results" - if os.path.exists(log_results_to_location): - shutil.rmtree(log_results_to_location) - os.makedirs(log_results_to_location) - - result.log_as_files(log_results_to_location, test_status = ['pass','fail']) + import datetime + + test_log_dir = self.td.get('TEST_LOG_DIR', '') + # The TEST_LOG_DIR maybe NULL when testimage is added after + # testdata.json is generated. + if not test_log_dir: + test_log_dir = os.path.join(self.td.get('WORKDIR', ''), 'testimage') + # Don't use self.td.get('DATETIME'), it's from testdata.json, not + # up-to-date, and may cause "File exists" when re-reun. + datetime = datetime.datetime.now().strftime('%Y%m%d%H%M%S') + ptest_log_dir_link = os.path.join(test_log_dir, 'ptest_log') + ptest_log_dir = '%s.%s' % (ptest_log_dir_link, datetime) + ptest_runner_log = os.path.join(ptest_log_dir, 'ptest-runner.log') + + status, output = self.target.run('ptest-runner', 0) + os.makedirs(ptest_log_dir) + with open(ptest_runner_log, 'w') as f: + f.write(output) + + # status != 0 is OK since some ptest tests may fail + self.assertTrue(status != 127, msg="Cannot execute ptest-runner!") + + # Parse and save results + parse_result = self.parse_ptest(ptest_runner_log) + parse_result.log_as_files(ptest_log_dir, test_status = ['pass','fail']) + if os.path.exists(ptest_log_dir_link): + # Remove the old link to create a new one + os.remove(ptest_log_dir_link) + os.symlink(os.path.basename(ptest_log_dir), ptest_log_dir_link)
Signature · 1 line
2.11.0
Re: [PATCH 02/10] runtime/cases/_ptest.py: revive it
Quoted 1 line · CEST Robert Yang
* Will write a tool to make regression check
This commit doesn't do this and it's not completely covered by the rest of the series. I think you could say perhaps more appropriately "This provides data that could be used to detect regressions in ptest results" or similar assuming you need to mention it at all.
Cheers,
Paul
Signature · 2 lines
Paul Eggleton Intel Open Source Technology Centre
Re: [PATCH 02/10] runtime/cases/_ptest.py: revive it
Quoted 7 lines · Paul Eggleton
Quoted 1 line · CEST Robert Yang
* Will write a tool to make regression check
This commit doesn't do this and it's not completely covered by the rest of the series. I think you could say perhaps more appropriately "This provides data that could be used to detect regressions in ptest results" or similar assuming you need to mention it at all.
Sorry, I will update it, it was written when I didn't plan to use buildhistory, now I save the data into buildhistory, so the tool is not needed any more.
// Robert
Quoted 4 lines
Cheers,
Paul
PATCH 3/10 oeqa/utils/logparser.py: add skip status
In reply to Robert YangSome test cases maybe skipped, let's parse it.
[YOCTO #11547]
--- meta/lib/oeqa/utils/logparser.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
meta/lib/oeqa/utils/logparser.py +3 -2
@@ -9,7 +9,7 @@ from . import ftools # A parser that can be used to identify weather a line is a test result or a section statement. class Lparser(object): - def __init__(self, test_0_pass_regex, test_0_fail_regex, section_0_begin_regex=None, section_0_end_regex=None, **kwargs): + def __init__(self, test_0_pass_regex, test_0_fail_regex, test_0_skip_regex, section_0_begin_regex=None, section_0_end_regex=None, **kwargs): # Initialize the arguments dictionary if kwargs: self.args = kwargs
@@ -19,12 +19,13 @@ class Lparser(object): # Add the default args to the dictionary self.args['test_0_pass_regex'] = test_0_pass_regex self.args['test_0_fail_regex'] = test_0_fail_regex + self.args['test_0_skip_regex'] = test_0_skip_regex if section_0_begin_regex: self.args['section_0_begin_regex'] = section_0_begin_regex if section_0_end_regex: self.args['section_0_end_regex'] = section_0_end_regex - self.test_possible_status = ['pass', 'fail', 'error'] + self.test_possible_status = ['pass', 'fail', 'error', 'skip'] self.section_possible_status = ['begin', 'end'] self.initialized = False
Signature · 1 line
2.11.0
PATCH 4/10 runtime/cases/_ptest.py: add skip status
In reply to Robert YangThe packages' test cases maybe skipped, check and save them.
[YOCTO #11547]
--- meta/lib/oeqa/runtime/cases/_ptest.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
meta/lib/oeqa/runtime/cases/_ptest.py +6 -1
@@ -10,6 +10,7 @@ class PtestRunnerTest(OERuntimeTestCase): def parse_ptest(self, logfile): parser = Lparser(test_0_pass_regex="^PASS:(.+)", test_0_fail_regex="^FAIL:(.+)", + test_0_skip_regex="^SKIP:(.+)", section_0_begin_regex="^BEGIN: .*/(.+)/ptest", section_0_end_regex="^END: .*/(.+)/ptest") parser.init()
@@ -38,6 +39,10 @@ class PtestRunnerTest(OERuntimeTestCase): result.store(current_section, name, status) continue + if line_type == 'test' and status == 'skip': + result.store(current_section, name, status) + continue + result.sort_tests() return result
@@ -70,7 +75,7 @@ class PtestRunnerTest(OERuntimeTestCase): # Parse and save results parse_result = self.parse_ptest(ptest_runner_log) - parse_result.log_as_files(ptest_log_dir, test_status = ['pass','fail']) + parse_result.log_as_files(ptest_log_dir, test_status = ['pass','fail', 'skip']) if os.path.exists(ptest_log_dir_link): # Remove the old link to create a new one os.remove(ptest_log_dir_link)
Signature · 1 line
2.11.0
PATCH 5/10 runtime/cases/_ptest.py: rename it to ptest.py
In reply to Robert YangIt works now.
[YOCTO #11547]
---
meta/lib/oeqa/runtime/cases/{_ptest.py => ptest.py} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename meta/lib/oeqa/runtime/cases/{_ptest.py => ptest.py} (100%)meta/lib/oeqa/runtime/cases/ptest.py renamed from meta/lib/oeqa/runtime/cases/_ptest.py +0 -0
Signature · 1 line
2.11.0
PATCH 6/10 utils/logparser.py: fix section check
In reply to Robert YangThe section might be None or '', so use "if section" for it.
Fixed:
File "/buildarea/lyang1/poky/meta/lib/oeqa/utils/logparser.py", line 113, in log_as_files
prefix += section
TypeError: Can't convert 'NoneType' object to str implicitly
[YOCTO #11547]
--- meta/lib/oeqa/utils/logparser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
meta/lib/oeqa/utils/logparser.py +1 -1
@@ -109,7 +109,7 @@ class Result(object): prefix = '' for x in test_status: prefix +=x+'.' - if (section != ''): + if section: prefix += section section_file = os.path.join(target_dir, prefix) # purge the file contents if it exists
Signature · 1 line
2.11.0
PATCH 7/10 core/target/ssh.py: replace decode errors
In reply to Robert YangThere might be wild strings when read from target (especially when reading ptest results), replace the errors to avoid breaking the test.
Fixed: (Not always happen)
$ bitbake core-image-sato -ctestimage
[snip]
status, output = self.target.run('ptest-runner', 0)
File "/buildarea/lyang1/poky/meta/lib/oeqa/core/target/ssh.py", line 84, in run
status, output = self._run(sshCmd, processTimeout, True)
File "/buildarea/lyang1/poky/meta/lib/oeqa/core/target/ssh.py", line 55, in _run
status, output = SSHCall(command, self.logger, timeout)
File "/buildarea/lyang1/poky/meta/lib/oeqa/core/target/ssh.py", line 258, in SSHCall
run()
File "/buildarea/lyang1/poky/meta/lib/oeqa/core/target/ssh.py", line 236, in run
output = process.communicate()[0].decode("utf-8")
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc3 in position 4906: invalid continuation byte[YOCTO #11547]
--- meta/lib/oeqa/core/target/ssh.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
meta/lib/oeqa/core/target/ssh.py +2 -2
@@ -211,7 +211,7 @@ def SSHCall(command, logger, timeout=None, **opts): process.stdout.close() eof = True else: - data = data.decode("utf-8") + data = data.decode("utf-8", errors='replace') output += data logger.debug('Partial data from SSH call: %s' % data) endtime = time.time() + timeout
@@ -233,7 +233,7 @@ def SSHCall(command, logger, timeout=None, **opts): output += lastline else: - output = process.communicate()[0].decode("utf-8") + output = process.communicate()[0].decode("utf-8", errors='replace') logger.debug('Data from SSH call: %s' % output.rstrip()) options = {
Signature · 1 line
2.11.0
PATCH 8/10 buildhistory.bbclass: print message when no commit
In reply to Robert YangThis makes the user easier to know how to make commit in buildhistory.
[YOCTO #11547]
--- meta/classes/buildhistory.bbclass | 2 ++ 1 file changed, 2 insertions(+)
meta/classes/buildhistory.bbclass +2 -0
@@ -824,6 +824,8 @@ python buildhistory_eventhandler() { interrupted = getattr(e, '_interrupted', 0) localdata.setVar('BUILDHISTORY_BUILD_INTERRUPTED', str(interrupted)) bb.build.exec_func("buildhistory_commit", localdata) + else: + bb.note("No commit since BUILDHISTORY_COMMIT != '1'") } addhandler buildhistory_eventhandler
Signature · 1 line
2.11.0
PATCH 9/10 buildhistory.bbclass: add ptest_log
In reply to Robert YangThe ptest log will be saved to buildhistory/ptest_log, we can easily get the regression result between builds by:
$ git show HEAD ptest_log/pass.fail.skip.*
[YOCTO #11547]
--- meta/classes/buildhistory.bbclass | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
meta/classes/buildhistory.bbclass +28 -0
@@ -912,3 +912,31 @@ def write_latest_srcrev(d, pkghistdir): else: if os.path.exists(srcrevfile): os.remove(srcrevfile) + +do_testimage[postfuncs] += "write_ptest_result" +do_testimage[vardepsexclude] += "write_ptest_result" + +python write_ptest_result() { + write_latest_ptest_result(d, d.getVar('BUILDHISTORY_DIR')) +} + +def write_latest_ptest_result(d, histdir): + import glob + import subprocess + test_log_dir = d.getVar('TEST_LOG_DIR') + input_ptest_log = os.path.join(test_log_dir, 'ptest_log') + output_ptest_log = os.path.join(histdir, 'ptest_log') + if os.path.exists(input_ptest_log): + # Lock it avoid race issue + lock = bb.utils.lockfile(output_ptest_log + "/ptest_log.lock") + bb.utils.mkdirhier(output_ptest_log) + oe.path.copytree(input_ptest_log, output_ptest_log) + # Sort test result + for result in glob.glob('%s/pass.fail.*' % output_ptest_log): + bb.debug(1, 'Processing %s' % result) + cmd = "sort %s -o %s" % (result, result) + bb.debug(1, 'Running %s' % cmd) + ret = subprocess.call(cmd, shell=True) + if ret != 0: + bb.error('Failed to run %s!' % cmd) + bb.utils.unlockfile(lock)
Signature · 1 line
2.11.0
Re: [PATCH 09/10] buildhistory.bbclass: add ptest_log
Hi Robert,
A few minor comments below.
meta/classes/
Quoted 12 lines · CEST Robert Yang
The ptest log will be saved to buildhistory/ptest_log, we can easily get the regression result between builds by:
$ git show HEAD ptest_log/pass.fail.skip.*[YOCTO #11547]
Signed-off-by Robert Yang <[email protected]>--- meta/classes/buildhistory.bbclass | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)meta/classes/ renamed from meta/classes/buildhistory.bbclass +0
-0
buildhistory.bbclass
Quoted 11 lines
index
a3e4c7a734a..26430a63d31100644meta/classes/buildhistory.bbclass +4
-0@@ -912,3 +912,31 @@ def write_latest_srcrev(d, pkghistdir): else: if os.path.exists(srcrevfile): os.remove(srcrevfile) + +do_testimage[postfuncs] += "write_ptest_result" +do_testimage[vardepsexclude] += "write_ptest_result" +
meta/classes/buildhistory.bbclass def write_latest_srcrev(d, pkghistdir): · line 928
Quoted 10 lines
meta/classes/buildhistory.bbclass +10
-0+python write_ptest_result() { + write_latest_ptest_result(d, d.getVar('BUILDHISTORY_DIR')) +} + +def write_latest_ptest_result(d, histdir): + import glob + import subprocess + test_log_dir = d.getVar('TEST_LOG_DIR') + input_ptest_log = os.path.join(test_log_dir, 'ptest_log') + output_ptest_log = os.path.join(histdir, 'ptest_log')
Would it be reasonable for this to just be "ptest"? To ask the question a different way, would you expect to save other types of ptest information into buildhistory, or is this likely to be it?
meta/classes/buildhistory.bbclass def write_latest_srcrev(d, pkghistdir): · line 939
Quoted 11 lines
meta/classes/buildhistory.bbclass +11
-0+ if os.path.exists(input_ptest_log): + # Lock it avoid race issue + lock = bb.utils.lockfile(output_ptest_log + "/ptest_log.lock") + bb.utils.mkdirhier(output_ptest_log) + oe.path.copytree(input_ptest_log, output_ptest_log) + # Sort test result + for result in glob.glob('%s/pass.fail.*' % output_ptest_log): + bb.debug(1, 'Processing %s' % result) + cmd = "sort %s -o %s" % (result, result) + bb.debug(1, 'Running %s' % cmd) + ret = subprocess.call(cmd, shell=True)
As a matter of good practice and since it's easy to do here I'd suggest not using shell=True and passing the command as a list instead, that way there can't be any issues with spaces or other shell interpretations.
meta/classes/buildhistory.bbclass def write_latest_srcrev(d, pkghistdir): · line 942
Quoted 3 lines
meta/classes/buildhistory.bbclass +3
-0+ if ret != 0: + bb.error('Failed to run %s!' % cmd) + bb.utils.unlockfile(lock)
Shouldn't you be using try...finally here to ensure the lockfile gets unlocked in the case of exceptions?
Cheers,
Paul
Signature · 2 lines
Paul Eggleton Intel Open Source Technology Centre
Re: [PATCH 09/10] buildhistory.bbclass: add ptest_log
Quoted 35 lines · Paul Eggleton
Hi Robert,
A few minor comments below.
meta/classes/
Quoted 12 lines · CEST Robert Yang
The ptest log will be saved to buildhistory/ptest_log, we can easily get the regression result between builds by:
$ git show HEAD ptest_log/pass.fail.skip.*[YOCTO #11547]
Signed-off-by Robert Yang <[email protected]>--- meta/classes/buildhistory.bbclass | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)meta/classes/ renamed from meta/classes/buildhistory.bbclass +0
-0buildhistory.bbclass
Quoted 17 lines
index
a3e4c7a734a..26430a63d31100644meta/classes/buildhistory.bbclass +10
-0@@ -912,3 +912,31 @@ def write_latest_srcrev(d, pkghistdir): else: if os.path.exists(srcrevfile): os.remove(srcrevfile) + +do_testimage[postfuncs] += "write_ptest_result" +do_testimage[vardepsexclude] += "write_ptest_result" + +python write_ptest_result() { + write_latest_ptest_result(d, d.getVar('BUILDHISTORY_DIR')) +} + +def write_latest_ptest_result(d, histdir): + import glob
Quoted 8 lines
meta/classes/buildhistory.bbclass def write_latest_srcrev(d, pkghistdir): · line 928
Quoted 4 lines
meta/classes/buildhistory.bbclass +4
-0+ import subprocess + test_log_dir = d.getVar('TEST_LOG_DIR') + input_ptest_log = os.path.join(test_log_dir, 'ptest_log') + output_ptest_log = os.path.join(histdir, 'ptest_log')Would it be reasonable for this to just be "ptest"? To ask the question a different way, would you expect to save other types of ptest information into buildhistory, or is this likely to be it?
I'm not sure atm, so use "ptest" sounds reasonable. I will update it.
Quoted 13 lines
meta/classes/buildhistory.bbclass def write_latest_srcrev(d, pkghistdir): · line 939
Quoted 12 lines
meta/classes/buildhistory.bbclass +11
-0+ if os.path.exists(input_ptest_log): + # Lock it avoid race issue + lock = bb.utils.lockfile(output_ptest_log + "/ptest_log.lock") + bb.utils.mkdirhier(output_ptest_log) + oe.path.copytree(input_ptest_log, output_ptest_log) + # Sort test result + for result in glob.glob('%s/pass.fail.*' % output_ptest_log): + bb.debug(1, 'Processing %s' % result) + cmd = "sort %s -o %s" % (result, result) + bb.debug(1, 'Running %s' % cmd) + ret = subprocess.call(cmd, shell=True)
Quoted 3 lines
As a matter of good practice and since it's easy to do here I'd suggest not using shell=True and passing the command as a list instead, that way there can't be any issues with spaces or other shell interpretations.
Thanks, I will update it.
Quoted 7 lines
meta/classes/buildhistory.bbclass def write_latest_srcrev(d, pkghistdir): · line 942
Quoted 4 lines
meta/classes/buildhistory.bbclass +3
-0+ if ret != 0: + bb.error('Failed to run %s!' % cmd) + bb.utils.unlockfile(lock)Shouldn't you be using try...finally here to ensure the lockfile gets unlocked in the case of exceptions?
Yes, good idea.
// Robert
Quoted 5 lines
Cheers,
Paul
PATCH 10/10 testimage.bbclass: update comments
In reply to Robert YangIt's very important to add IMAGE_CLASSES += "testimage" in local.conf firstly, otherwise the var like TEST_LOG_DIR (defined in testimage.bbclass) will not be in testdata.json.
[YOCTO #11547]
--- meta/classes/testimage.bbclass | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
meta/classes/testimage.bbclass +2 -2
@@ -7,8 +7,8 @@ # Most of the tests are commands run on target image over ssh. # To use it add testimage to global inherit and call your target image with -c testimage # You can try it out like this: -# - first build a qemu core-image-sato -# - add IMAGE_CLASSES += "testimage" in local.conf +# - first add IMAGE_CLASSES += "testimage" in local.conf +# - build a qemu core-image-sato # - then bitbake core-image-sato -c testimage. That will run a standard suite of tests. # You can set (or append to) TEST_SUITES in local.conf to select the tests
Signature · 1 line
2.11.0
Quoted 4 lines · CEST Robert Yang
We can get the regression result by:
$ git show HEAD ptest_log/pass.fail.skip.*Can we add ptest to default
TEST_SUITES, please ?
Is it possible to get an idea of the time impact if we did so?
Cheers,
Paul
Signature · 2 lines
Paul Eggleton Intel Open Source Technology Centre
Quoted 7 lines · Paul Eggleton
Quoted 4 lines · CEST Robert Yang
We can get the regression result by:
$ git show HEAD ptest_log/pass.fail.skip.*Can we add ptest to default
TEST_SUITES, please ?Is it possible to get an idea of the time impact if we did so?
The ptest cost about 18 minutes (qemux86 +QEMU_USE_KVM) when test core-image-sato. My host is 32 core * 2.6GHz, and 128G MEM. I didn't customize qemu settings, just used the default.
I fixed all your comments and put them into the repo:
git://git.openembedded.org/openembedded-core-contrib rbt/ptest
http://cgit.openembedded.org/openembedded-core-contrib/log/?h=rbt/ptest
Robert Yang (10):
oeqa/targetcontrol.py: simplify checking for qemu_use_kvm runtime/cases/_ptest.py: revive it oeqa/utils/logparser.py: add skip status runtime/cases/_ptest.py: add skip status runtime/cases/_ptest.py: rename it to ptest.py utils/logparser.py: fix section check core/target/ssh.py: replace decode errors buildhistory.bbclass: print message when no commit buildhistory.bbclass: add ptest testimage.bbclass: update comments
Quoted 4 lines
Cheers,
Paul