Merge ~djacobs98/checkbox-iiotg/+git/checkbox-provider-intliotg-3:cyclictest_2 into ~checkbox-dev/checkbox-iiotg/+git/checkbox-provider-intliotg:master

Proposed by Doug Jacobs
Status: Merged
Approved by: Vic Liu
Approved revision: f8185cb3c2a16c2d0de3ee6bb8d4e05aeaf2f838
Merged at revision: 58dba0648f10ab0c8db757643224c793c6679a58
Proposed branch: ~djacobs98/checkbox-iiotg/+git/checkbox-provider-intliotg-3:cyclictest_2
Merge into: ~checkbox-dev/checkbox-iiotg/+git/checkbox-provider-intliotg:master
Diff against target: 254 lines (+209/-0)
6 files modified
bin/run_cyclictest.py (+148/-0)
units/rt-performance-tests/category.pxu (+3/-0)
units/rt-performance-tests/jobs.pxu (+29/-0)
units/rt-performance-tests/test-plan.pxu (+27/-0)
units/test-plan-desktop.pxu (+1/-0)
units/test-plan-server.pxu (+1/-0)
Reviewer Review Type Date Requested Status
Vic Liu Approve
PeiYao Chang Approve
Review via email: mp+441418@code.launchpad.net

Commit message

Initial checkin.
Add cyclictest for RT to checkbox.
This includes the script that runs the test, entry in checkbox and the updates to the desktop and server test plans. For now, this will be part of the Stress test plan.

To post a comment you must log in.
Revision history for this message
Vic Liu (zongminl) wrote :

See my comments inline

review: Needs Fixing
Revision history for this message
PeiYao Chang (baconyao) wrote :

Hi @doug, please see my comments inline.

review: Needs Fixing
Revision history for this message
Doug Jacobs (djacobs98) wrote :

Squashed & Pushed changes.

Here's the new pastebin showing the updated run:
https://pastebin.canonical.com/p/fQvpMfwdbX/

Revision history for this message
Vic Liu (zongminl) wrote :

Few more suggestions inline

review: Needs Fixing
Revision history for this message
PeiYao Chang (baconyao) wrote :

LGTM. No flak8 error be observed.

review: Approve
Revision history for this message
Vic Liu (zongminl) wrote :

+1, thank you

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/bin/run_cyclictest.py b/bin/run_cyclictest.py
2new file mode 100755
3index 0000000..e7adc3f
4--- /dev/null
5+++ b/bin/run_cyclictest.py
6@@ -0,0 +1,148 @@
7+#!/usr/bin/env python3
8+# Copyright Canonical 2023
9+# run_cyclictest.py
10+#
11+# Uses the cyclictest binary to run cyclictest and measure process latency.
12+# This test needs to run for at least 24 hours in order to provide useful data.
13+#
14+# The output from the test, as well as any errors, are then dumped into a file
15+# so the second part can check the results. A passing test will depend on the
16+# maximum latency observed and whether that is an acceptable number. This
17+# value depends on the DUT's platform and CPU. These values are provided by
18+# Intel as part of the Real Time Key Performance Indicator (RT KPI) document.
19+#
20+# Pass conditions:
21+# * Max latency is equal to or lower than the expected value for the DUT's HW
22+# * 0 overflows (caused by a process waiting too long. also called a "miss")
23+#
24+# Fail conditions:
25+# * Any errors from the test.
26+# * Unacceptable values for Max Latency or Overflows.
27+
28+import argparse
29+import subprocess
30+
31+
32+def run_it(duration):
33+ """
34+ This function runs the cyclictest command, and captures output and also
35+ stores the output in a file for processing.
36+
37+ Inputs:
38+ filename - the path and filename of the output file.
39+ duration - the desired duration of the test in seconds.
40+ """
41+
42+ # timeout must be larger than the test duration, otherwise the test will be
43+ # interrupted
44+ test_timeout = duration + 1
45+
46+ cmd = ["chrt", "-f", "99", "cyclictest", "-a2-3", "-t2", "-m", "-p99",
47+ "-i250", "-h700", "-q", "-D", str(duration)]
48+
49+ try:
50+ result = subprocess.run(
51+ cmd, capture_output=True, text=True, timeout=test_timeout,
52+ check=True)
53+ except Exception as err:
54+ raise SystemExit(err)
55+
56+ # Note: A returncode of 0 simply means the command executed successfully.
57+ # It does NOT mean the test passed (or failed.)
58+ # That will be determined by a separate function.
59+ return result
60+
61+
62+def lookup_max_latency():
63+ """
64+ The expected maximum latency is based on the HW platform and CPU.
65+ For instance, ADL-S with an i7-12700 has an expected maximum latency of
66+ 11ms
67+
68+ However, some hardware may not proper identification yet.
69+ In this case just return the largest latency listed in the document.
70+ """
71+
72+ # In case we cannot determine the HW or the CPU of the DUT, use the largest
73+ # value from the table of expected maximum latency.
74+ MAX_ALLOWED_LATENCY = 17
75+
76+ # TODO: Implement the methods to determine the platform and CPU, and use
77+ # that to lookup the expected maximum latency.
78+ #
79+ # For now, just return MAX_ALLOWED_LATENCY
80+
81+ return MAX_ALLOWED_LATENCY
82+
83+
84+def verify_cyclictest_results(result):
85+ """
86+ This function takes output from the call to subprocess containing the
87+ output from a run of cyclictest and looks at std out to verify two things:
88+ 1. The maximum latency from each thread did not exceed the maximum latency
89+ specified by Intel for the DUT's HW Platform and CPU.
90+
91+ 2. The number of overflows (scheduling misses) was 0 for each thread.
92+
93+ Both conditions must be true for this function to return success (0)
94+
95+ Sample output for these lines looks like:
96+ # Max Latencies: 00041 00046
97+ # Histogram Overflows: 00000 00000
98+ The values after these strings are the results from each thread.
99+
100+ All other lines are ignored.
101+ """
102+ max_latency = lookup_max_latency()
103+ print("Maximum latency allowed: " + str(max_latency))
104+ # list of latencies, from each thread
105+ latencies = []
106+
107+ # list of overflows (scheduling misses) from each thread
108+ overflows = []
109+
110+ return_code = 0
111+
112+ std_output = result.stdout.split("\n")
113+ for line in std_output:
114+
115+ if "# Max Latencies" in line:
116+ latencies = line.split(":")[1].split()
117+ for latency in latencies:
118+ if int(latency) > max_latency:
119+ print("Test fails.\tLatency : " + latency +
120+ "\t-- Maximum Latency value of: " +
121+ str(max_latency) + " exceeded.")
122+ return_code = 1
123+ else:
124+ print("Test passes.\tLatency : " + latency + " -- OK.")
125+
126+ elif "# Histogram Overflows" in line:
127+ overflows = line.split(":")[1].split()
128+ for overflow in overflows:
129+ if int(overflow) > 0:
130+ print("Test fails.\tOverflow: " + overflow +
131+ " -- 0 Overflows expected.")
132+ return_code = 1
133+ else:
134+ print("Test passes.\tOverflow: " + overflow + " -- OK.")
135+ continue
136+
137+ return return_code
138+
139+
140+if __name__ == "__main__":
141+ return_code = 0
142+
143+ parser = argparse.ArgumentParser()
144+ # default duration is 86400 seconds = 24hr
145+ parser.add_argument("--duration", type=int, default=86400)
146+ args = parser.parse_args()
147+
148+ result = run_it(args.duration)
149+ print("stdout: {}".format(result.stdout))
150+ print("stderr: {}\n".format(result.stderr))
151+
152+ return_code = verify_cyclictest_results(result)
153+
154+ raise SystemExit(return_code)
155diff --git a/units/rt-performance-tests/category.pxu b/units/rt-performance-tests/category.pxu
156new file mode 100644
157index 0000000..43649f2
158--- /dev/null
159+++ b/units/rt-performance-tests/category.pxu
160@@ -0,0 +1,3 @@
161+unit: category
162+id: rt-performance-tests
163+_name: RT Performance Tests
164diff --git a/units/rt-performance-tests/jobs.pxu b/units/rt-performance-tests/jobs.pxu
165new file mode 100644
166index 0000000..43c02d8
167--- /dev/null
168+++ b/units/rt-performance-tests/jobs.pxu
169@@ -0,0 +1,29 @@
170+# test based on Intel's document "Real-Time Key Performance Indicators (KPIs)
171+# Latest version: https://drive.google.com/drive/u/0/folders/1oP5YaynNkB1TEUp8hz0iPPfswZK3N5_O
172+#
173+# Add to stress tests (for now)
174+
175+# Test case: cyclictest__rt_latency
176+# Purpose: Test scheduling latency by running the cyclictest tool.
177+# Test described in Intel's document on Real-Time Key Performance Indicators.
178+#
179+# It is suggested duration of this is 24hrs, or 86440 seconds.
180+#
181+# The expected Maximum Latency will vary based on the Platform and CPU that the
182+# test is run on. However for now, just use the largest value of 17 microseconds.
183+#
184+# This test will pass if:
185+# * The maximum latency is 17 microseconds or lower.
186+# * There are no overflows.
187+#
188+# Otherwise the test will fails.
189+
190+id: rt-performance-tests/cyclictest_rt_latency
191+category_id: rt-performance-tests
192+_summary:
193+ Run cyclictest to test scheduling latency. Default run time is 24 hours.
194+plugin: shell
195+user: root
196+environ: CYCLICTEST_DURATION
197+command:
198+ run_cyclictest.py --duration "${CYLICTEST_DURATION:-86400}"
199diff --git a/units/rt-performance-tests/test-plan.pxu b/units/rt-performance-tests/test-plan.pxu
200new file mode 100644
201index 0000000..6e5c59e
202--- /dev/null
203+++ b/units/rt-performance-tests/test-plan.pxu
204@@ -0,0 +1,27 @@
205+id: rt-performance-tests-full
206+_name: Realtime Peformance Tests (Full)
207+unit: test plan
208+include:
209+nested_part:
210+ rt-performance-tests-manual
211+ rt-performance-tests-automated
212+ rt-performance-tests-stress
213+
214+id: rt-performance-tests-manual
215+_name: Realtime Performance Tests (Manual)
216+unit: test plan
217+include:
218+bootstrap_include:
219+
220+id: rt-performance-tests-automated
221+_name: Realtime Performance Tests (Automated)
222+unit: test plan
223+include:
224+bootstrap_include:
225+
226+id: rt-performance-tests-stress
227+_name: Realtime Performance Tests (Stress)
228+unit: test plan
229+include:
230+ rt-performance-tests/cyclictest_rt_latency
231+bootstrap_include:
232diff --git a/units/test-plan-desktop.pxu b/units/test-plan-desktop.pxu
233index 23c0390..506e3d2 100644
234--- a/units/test-plan-desktop.pxu
235+++ b/units/test-plan-desktop.pxu
236@@ -135,6 +135,7 @@ include:
237 nested_part:
238 com.canonical.certification::stress-iperf3-automated # keep if ethernet is supported
239 com.canonical.certification::client-cert-iot-server-22-04-stress
240+ rt-performance-tests-stress
241 exclude:
242 com.canonical.certification::stress-tests/hibernate.*
243
244diff --git a/units/test-plan-server.pxu b/units/test-plan-server.pxu
245index d8c0f95..8e4288b 100644
246--- a/units/test-plan-server.pxu
247+++ b/units/test-plan-server.pxu
248@@ -124,6 +124,7 @@ include:
249 nested_part:
250 com.canonical.certification::stress-iperf3-automated # keep if ethernet is supported
251 com.canonical.certification::client-cert-iot-server-22-04-stress
252+ rt-performance-tests-stress
253 exclude:
254 com.canonical.certification::stress-tests/hibernate.*
255

Subscribers

People subscribed via source and target branches