Skip to content

Commit b5d9510

Browse files
author
Yihao Wu
committed
tests: add SLI continuity test
Test whether SLI jumps when installing/removing scheduler Now usr%, sys%, nr_running is covered. Signed-off-by: Yihao Wu <wuyihao@linux.alibaba.com>
1 parent c9d528d commit b5d9510

3 files changed

Lines changed: 162 additions & 0 deletions

File tree

‎tests/bundles/ci‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ cpu_throttle
55
domain_rebuild
66
sched_syscall
77
mem_pressure
8+
sli_continuity

‎tests/test_sli_continuity/assert‎

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
import sys
5+
import sh
6+
from sh import yum, cat, RunningCommand, getconf, rpm, grep, lsmod, killall, awk
7+
from time import sleep, time
8+
from glob import glob
9+
10+
epsilon = 0.05
11+
12+
def near(n, m):
13+
return abs(n - m) < epsilon
14+
15+
def positive(n):
16+
return n > 0
17+
18+
def overflow(n):
19+
return n > 1.0 + epsilon
20+
21+
def near_greater_equal(n, m):
22+
return n >= m and n < m + epsilon
23+
24+
class TestSLI:
25+
def setup_class(self):
26+
yum('install', 'stress-ng', assumeyes=True)
27+
self.rpm = self.get_rpm()
28+
print("SLI continuity test")
29+
self.HZ = int(getconf('CLK_TCK'))
30+
31+
def get_rpm(self):
32+
scheduler_rpm = glob(os.path.join('/tmp/work', 'scheduler*.rpm'))
33+
if len(scheduler_rpm) != 1:
34+
print("Please check your scheduler rpm");
35+
sys.exit(1)
36+
return scheduler_rpm
37+
38+
def task_usage(self, pid:int):
39+
procf = '/proc/%d/stat' % pid
40+
fields = cat(procf).split()
41+
utime = float(fields[13]) / self.HZ
42+
stime = float(fields[14]) / self.HZ
43+
return utime, stime, time()
44+
45+
def test_util(self, *args, **kwargs):
46+
stress:RunningCommand = sh.stress_ng(**kwargs, _bg=True)
47+
sleep(5)
48+
master = stress.process.pid
49+
worker = int(cat('/proc/{pid}/task/{pid}/children'.format(pid=master)).strip())
50+
51+
u0, s0, t0 = self.task_usage(worker)
52+
sleep(5)
53+
u1, s1, t1 = self.task_usage(worker)
54+
rpm(self.rpm, install=True)
55+
sleep(1)
56+
u2, s2, t2 = self.task_usage(worker)
57+
sleep(5)
58+
u3, s3, t3 = self.task_usage(worker)
59+
60+
U0 = (u1 - u0) / (t1 - t0)
61+
S0 = (s1 - s0) / (t1 - t0)
62+
U1 = (u2 - u1) / (t2 - t1)
63+
S1 = (s2 - s1) / (t2 - t1)
64+
U2 = (u3 - u2) / (t3 - t2)
65+
S2 = (s3 - s2) / (t3 - t2)
66+
67+
return (U0, S0), (U1, S1), (U2, S2)
68+
69+
def test_usr(self):
70+
(U0, S0), (U1, S1), (U2,S2) = self.test_util(cpu=1, cpu_load=75)
71+
72+
# Characteristic of 2nd period:
73+
# Don't know exact range, because of stop_machine
74+
# But at least don't exceed 100%
75+
if not positive(U1) or overflow(U1):
76+
self.error_handler('U1', U1)
77+
78+
# Characteristic of 3rd period:
79+
if not near(U2, U0) or overflow(U2):
80+
self.error_handler('U2', U2)
81+
82+
# Characteristic of all periods:
83+
if not near_greater_equal(S0, 0) or overflow(S0):
84+
self.error_handler('S0', S0)
85+
if not near_greater_equal(S1, 0) or overflow(S1):
86+
self.error_handler('S1', S1)
87+
if not near_greater_equal(S2, 0) or overflow(S2):
88+
self.error_handler('S2', S2)
89+
90+
killall('stress-ng-cpu', _ok_code=[0,1])
91+
rpm('scheduler-xxx', erase=True)
92+
93+
def test_sys(self):
94+
(U0, S0), (U1, S1), (U2,S2) = self.test_util(urandom=1)
95+
96+
# Characteristic of 1st period:
97+
if not near(S0, 1) or overflow(S0):
98+
self.error_handler('S0', S0)
99+
100+
# Characteristic of 2nd period:
101+
# Don't know exact range, because of stop_machine
102+
# But at least don't exceed 100%
103+
if not positive(S1) or overflow(S1):
104+
self.error_handler('S1', S1)
105+
106+
# Characteristic of 3rd period:
107+
if not near(S2, S0) or overflow(S2):
108+
self.error_handler('S2', S2)
109+
110+
# Characteristic of all periods:
111+
if not near_greater_equal(U0, 0) or overflow(U0):
112+
self.error_handler('U0', U0)
113+
if not near_greater_equal(U1, 0) or overflow(U1):
114+
self.error_handler('U1', U1)
115+
if not near_greater_equal(U2, 0) or overflow(U2):
116+
self.error_handler('U2', U2)
117+
118+
killall('stress-ng-urand', _ok_code=[0,1])
119+
rpm('scheduler-xxx', erase=True)
120+
121+
def test_nr_running(self):
122+
nr_tasks = 500
123+
stress:RunningCommand = sh.stress_ng(fork=nr_tasks, _bg=True)
124+
sleep(5)
125+
nr_running_0 = float(awk(cat('/proc/stat'), '/procs_running/{print $2}')) / nr_tasks
126+
rpm(self.rpm, install=True)
127+
sleep(1)
128+
nr_running_1 = float(awk(cat('/proc/stat'), '/procs_running/{print $2}')) / nr_tasks
129+
rpm('scheduler-xxx', erase=True)
130+
nr_running_2 = float(awk(cat('/proc/stat'), '/procs_running/{print $2}')) / nr_tasks
131+
if not near(nr_running_0, 1.0):
132+
self.error_handler('nr_running_0', nr_running_0)
133+
if not near(nr_running_1, 1.0):
134+
self.error_handler('nr_running_1', nr_running_1)
135+
if not near(nr_running_2, 1.0):
136+
self.error_handler('nr_running_2', nr_running_2)
137+
138+
killall('stress-ng-fork', _ok_code=[0,1])
139+
140+
def test_all(self):
141+
self.test_usr()
142+
self.test_sys()
143+
self.test_nr_running()
144+
145+
def teardown_class(self):
146+
killall('stress-ng-cpu', _ok_code=[0,1])
147+
killall('stress-ng-urand', _ok_code=[0,1])
148+
killall('stress-ng-fork', _ok_code=[0,1])
149+
if grep(lsmod(), 'scheduler', word_regexp=True, _ok_code=[0,1]).exit_code == 0:
150+
rpm('scheduler-xxx', erase=True)
151+
152+
def error_handler(self, obj, value):
153+
print("Failed becaused {} = {}".format(obj, value))
154+
self.teardown_class()
155+
raise
156+
157+
if __name__ == '__main__':
158+
test_unit = TestSLI()
159+
test_unit.setup_class()
160+
test_unit.test_all()
161+
test_unit.teardown_class()

‎tests/test_sli_continuity/patch.diff‎

Whitespace-only changes.

0 commit comments

Comments
 (0)