@@ -66,9 +66,9 @@ class LtpTest(LtpTestBase):
def runltp(self, ltp_group):
# LTP appends to log files, so ensure we start with a clean log
- self.target.deleteFiles("/opt/ltp/results/", ltp_group)
+ self.target.deleteFiles("/opt/ltp/results/", "%s.json" % ltp_group)
- cmd = '/opt/ltp/runltp -f %s -q -r /opt/ltp -l /opt/ltp/results/%s -I 1 -d /opt/ltp' % (ltp_group, ltp_group)
+ cmd = 'kirk --run-suite %s --json-report /opt/ltp/results/%s.json -n -d /opt/ltp --exec-timeout 20m' % (ltp_group, ltp_group)
starttime = time.time()
(status, output) = self.target.run(cmd, timeout=1200)
@@ -87,8 +87,8 @@ class LtpTest(LtpTestBase):
self.extras['ltpresult.rawlogs']['log'] = self.extras['ltpresult.rawlogs']['log'] + output
# Copy the machine-readable test results locally so we can parse it
- dst = os.path.join(self.ltptest_log_dir, ltp_group)
- remote_src = "/opt/ltp/results/%s" % ltp_group
+ dst = os.path.join(self.ltptest_log_dir, "%s.json" % ltp_group)
+ remote_src = "/opt/ltp/results/%s.json" % ltp_group
(status, output) = self.target.copyFrom(remote_src, dst, True)
if status:
msg = 'File could not be copied. Output: %s' % output
@@ -113,16 +113,21 @@ class LtpTest(LtpTestBase):
# LTP runtime tests
@OETestDepends(['ssh.SSHTest.test_ssh'])
- @OEHasPackage(["ltp"])
+ @OEHasPackage(["ltp", "python3-kirk"])
def test_ltp_help(self):
- (status, output) = self.target.run('/opt/ltp/runltp --help')
+ (status, output) = self.target.run('kirk --help')
msg = 'Failed to get ltp help. Output: %s' % output
self.assertEqual(status, 0, msg=msg)
@OETestDepends(['ltp.LtpTest.test_ltp_help'])
def test_ltp_groups(self):
- for ltp_group in self.ltp_groups:
- self.runltp(ltp_group)
+ for ltp_group in self.ltp_groups:
+ try:
+ self.runltp(ltp_group)
+ except Exception as e:
+ self.extras['ltpresult.%s' % ltp_group] = {'status': 'FAILED'}
+ self.failmsg = self.failmsg + "Suite %s crashed: %s\n" % (ltp_group, e)
+ self.target.logger.warning("Suite %s crashed, continuing: %s" % (ltp_group, e))
@OETestDepends(['ltp.LtpTest.test_ltp_groups'])
def test_ltp_runltp_cve(self):
@@ -60,7 +60,7 @@ class LtpStressBase(OERuntimeTestCase):
class LtpStressTest(LtpStressBase):
def runltp(self, stress_group):
- cmd = '/opt/ltp/runltp -f %s -p -q 2>@1 | tee /opt/ltp/results/%s' % (stress_group, stress_group)
+ cmd = 'kirk --run-suite %s --json-report /opt/ltp/results/%s.json -n -d /opt/ltp' % (stress_group, stress_group)
starttime = time.time()
(status, output) = self.target.run(cmd)
endtime = time.time()
@@ -69,8 +69,16 @@ class LtpStressTest(LtpStressBase):
self.extras['ltpstressresult.rawlogs']['log'] = self.extras['ltpstressresult.rawlogs']['log'] + output
+ # Copy kirk JSON report from target
+ dst = os.path.join(self.ltptest_log_dir, "%s.json" % stress_group)
+ remote_src = "/opt/ltp/results/%s.json" % stress_group
+ (status, output) = self.target.copyFrom(remote_src, dst, True)
+ if status:
+ msg = 'File could not be copied. Output: %s' % output
+ self.target.logger.warning(msg)
+
parser = LtpParser()
- results, sections = parser.parse(os.path.join(self.ltptest_log_dir, "%s" % stress_group))
+ results, sections = parser.parse(dst)
runtime = int(endtime-starttime)
sections['duration'] = runtime
@@ -4,7 +4,7 @@
# SPDX-License-Identifier: MIT
#
-import enum
+import json
import os
import re
@@ -116,44 +116,29 @@ class PtestParser(object):
class LtpParser:
"""
- Parse the machine-readable LTP log output into a ptest-friendly data structure.
+ Parse kirk JSON report into a ptest-friendly data structure.
"""
+
+ STATUS_MAP = {
+ "pass": "PASSED",
+ "fail": "FAILED",
+ "brok": "FAILED",
+ "conf": "SKIPPED",
+ "warn": "PASSED",
+ }
+
def parse(self, logfile):
+ with open(logfile, errors="replace") as f:
+ report = json.load(f)
+
results = {}
- # Aaccumulate the duration here but as the log rounds quick tests down
- # to 0 seconds this is very much a lower bound. The caller can replace
- # the value.
section = {"duration": 0, "log": ""}
- class LtpExitCode(enum.IntEnum):
- # Exit codes as defined in ltp/include/tst_res_flags.h
- TPASS = 0 # Test passed flag
- TFAIL = 1 # Test failed flag
- TBROK = 2 # Test broken flag
- TWARN = 4 # Test warning flag
- TINFO = 16 # Test information flag
- TCONF = 32 # Test not appropriate for configuration flag
-
- with open(logfile, errors="replace") as f:
- # Lines look like this:
- # tag=cfs_bandwidth01 stime=1689762564 dur=0 exit=exited stat=32 core=no cu=0 cs=0
- for line in f:
- if not line.startswith("tag="):
- continue
+ for entry in report.get("results", []):
+ results[entry["test_fqn"]] = self.STATUS_MAP.get(entry.get("status", ""), "FAILED")
+ section["log"] += entry.get("test", {}).get("log", "")
- values = dict(s.split("=") for s in line.strip().split())
-
- section["duration"] += int(values["dur"])
- exitcode = int(values["stat"])
- if values["exit"] == "exited" and exitcode == LtpExitCode.TCONF:
- # Exited normally with the "invalid configuration" code
- results[values["tag"]] = "SKIPPED"
- elif exitcode == LtpExitCode.TPASS:
- # Successful exit
- results[values["tag"]] = "PASSED"
- else:
- # Other exit
- results[values["tag"]] = "FAILED"
+ section["duration"] = int(report.get("stats", {}).get("runtime", 0))
return results, section
@@ -113,6 +113,7 @@ RDEPENDS:${PN} = "\
net-tools \
perl \
python3-core \
+ python3-kirk \
procps \
quota \
unzip \