Basic node CPU scheduler tests
[tests.git] / qaapi / qa / tests / node_cpu_sched.py
1 #!/usr/bin/python
2
3 """
4 This file contains a stand-alone CPU scheduler test to be run on a node.
5 It still needs to be integrated into the testing framework.
6 """
7
8 import sys
9 import commands
10 import re
11 from threading import Thread
12
13 class CpuTest:
14     def __init__(self, ctx, cpu, resv, share, min, max, desc):
15         self.ctx = ctx
16         self.cpu = cpu
17         self.resv = resv
18         self.share = share
19         self.min = min
20         self.max = max
21         self.desc = desc
22
23
24 class Spinner(Thread):
25     def __init__(self, test):
26         Thread.__init__(self)
27
28         cmd = '/usr/bin/time ./busyloop.py 15'
29         if test.share:
30             flags = '--idle-time'
31         else:
32             flags = ''
33
34         self.cmd = 'taskset -c ' + str(test.cpu) \
35             + ' vcontext --create --xid ' + str(test.ctx) + ' --disconnect ' \
36             + '-- vsched --fill-rate ' + str(test.resv) + ' --interval 100 ' \
37             + '--fill-rate2 ' + str(test.share) + ' --interval2 1000 ' \
38             + '--tokens 100 --tokens-min 50 --tokens-max 100 --force '\
39             + flags + ' -- vattribute --flag sched_hard -- ' + cmd
40
41         self.test = test
42
43     def run(self):
44         self.output = commands.getoutput( self.cmd )
45
46     def passed(self):
47         match = re.search('elapsed (\d+)%CPU', self.output)
48         if match:
49             self.pct = int(match.group(1))
50         else:
51             print "Error parsing output: cannot get CPU%"
52             self.pct = 0
53
54         return ( self.pct >= self.test.min and self.pct <= self.test.max )
55
56
57 def run_test(testlist):
58     failures = 0
59
60     for test in testlist:
61         test.thread = Spinner(test)
62         test.thread.start()
63
64     for test in testlist:
65         test.thread.join()
66
67     for test in testlist:
68         if test.thread.passed():
69             print "[PASSED] (" + str(test.thread.pct) + "%)\t", test.desc
70         else:
71             print "[FAILED] (" + str(test.thread.pct) + "%)\t", test.desc
72             failures += 1
73
74     return failures
75
76 ### Test 1: test hard rate-limiting to 25% (should get <= 25%)
77 def test_1():
78     test = CpuTest(ctx=600, cpu=0, resv=25, share=0, min=15, max=25, 
79                    desc = "Test 1: single ctx, 25% resv")
80
81     return run_test([ test ])
82
83 ### Test 2: test share scheduling of a single task (should get 100%)
84 def test_2():
85     test = CpuTest(ctx=600, cpu=0, resv=0, share=1, min=95, max=100, 
86                    desc = "Test 2: single ctx, one share")
87
88     return run_test([ test ])
89
90 ### Test 3: test hard & share scheduling of a single task (should get 100%)
91 def test_3():
92     test = CpuTest(ctx=600, cpu=0, resv=25, share=1, min=95, max=100, 
93                    desc = "Test 3: single ctx, 25% resv, one share")
94
95     return run_test([ test ])
96
97 ### Test 4: test relative share scheduling of several tasks
98 def test_4():
99     test1 = CpuTest(ctx=600, cpu=0, resv=0, share=1, min=15, max=17, 
100                    desc = "Test 4: ctx 1, one share")
101     test2 = CpuTest(ctx=601, cpu=0, resv=0, share=2, min=32, max=34, 
102                    desc = "        ctx 2, two shares")
103     test3 = CpuTest(ctx=602, cpu=0, resv=0, share=3, min=49, max=51, 
104                    desc = "        ctx 3, three shares")
105
106     return run_test([ test1, test2, test3 ])
107
108 ### Test 5: test hard rate limit and shares
109 def test_5():
110     test1 = CpuTest(ctx=600, cpu=0, resv=0, share=1, min=14, max=16, 
111                    desc = "Test 5: ctx 1, one share")
112     test2 = CpuTest(ctx=601, cpu=0, resv=0, share=2, min=29, max=33, 
113                    desc = "        ctx 2, two shares")
114     test3 = CpuTest(ctx=602, cpu=0, resv=0, share=3, min=44, max=47, 
115                    desc = "        ctx 3, three shares")
116     test4 = CpuTest(ctx=603, cpu=0, resv=10, share=0, min=7, max=10, 
117                    desc = "        ctx 4, 10% resv")
118
119     return run_test([ test1, test2, test3, test4 ])
120
121 ### Test 6: test guarantee and shares
122 def test_6():
123     test1 = CpuTest(ctx=600, cpu=0, resv=0, share=1, min=9, max=11, 
124                    desc = "Test 6: ctx 1, one share")
125     test2 = CpuTest(ctx=601, cpu=0, resv=0, share=2, min=19, max=21, 
126                    desc = "        ctx 2, two shares")
127     test3 = CpuTest(ctx=602, cpu=0, resv=0, share=3, min=29, max=31, 
128                    desc = "        ctx 3, three shares")
129     test4 = CpuTest(ctx=603, cpu=0, resv=30, share=1, min=35, max=40, 
130                    desc = "        ctx 4, 30% resv, one share")
131
132     return run_test([ test1, test2, test3, test4 ])
133
134 ### Test 7: SMP active (both tasks should get 100% on an SMP)
135 def test_7():
136     test1 = CpuTest(ctx=600, cpu=0, resv=0, share=1, min=95, max=100, 
137                    desc = "Test 7: ctx 1, processor 1")
138     test2 = CpuTest(ctx=601, cpu=1, resv=0, share=1, min=95, max=100, 
139                    desc = "        ctx 2, processor 2")
140
141     return run_test([ test1, test2 ])
142
143 def main():
144     failures = 0
145
146     failures += test_1()
147     failures += test_2()
148     failures += test_3()
149     failures += test_4()
150     failures += test_5()
151     failures += test_6()
152     failures += test_7()
153
154     return failures
155
156 if __name__ == "__main__":
157     sys.exit(main())