blob: f9fa389a0a5137df5eedb56b80b4c96d84813382 [file] [log] [blame]
koder aka kdanilov0c598a12015-04-21 03:01:40 +03001import os.path
2import unittest
3
4
5from oktest import ok, main, test
6
7
8from wally.suits.io import agent
9
10code_test_defaults = """
11[defaults]
12wait_for_previous
13buffered=0
14iodepth=2
15RUNTIME=20
16
17[sec1]
18group_reporting
19time_based
20softrandommap=1
21filename=/tmp/xxx
22size=5G
23ramp_time=20
24runtime={RUNTIME}
25blocksize=1m
26rw=read
27direct=1
28numjobs=1
29some_extra=1.2314
30
31[sec2]
32group_reporting
33time_based
34iodepth=1
35softrandommap=1
36filename=/tmp/xxx
37size=5G
38ramp_time=20
39runtime={RUNTIME}
40blocksize=1m
41rw=read
42direct=1
43numjobs=1
44some_extra=1.2314
45"""
46
47defaults = """
48[defaults]
49wait_for_previous
50group_reporting
51time_based
52buffered=0
53iodepth=1
54softrandommap=1
55filename=/tmp/xxx
56size=5G
57ramp_time=20
58runtime=20
59blocksize=1m
60rw=read
61direct=1
62numjobs=1
63"""
64
65code_test_auto_params_1 = defaults + """
66[defaults]
67RUNTIME=30
68
69[sec1_{TEST_SUMM}]
70ramp_time={% 20, 40 %}
71runtime={RUNTIME}
72blocksize={% 4k, 4m %}
73"""
74
75
76code_test_uniq = defaults + """
77[defaults]
78REPCOUNT=2
79RUNTIME=30
80
81[sec1_{TEST_SUMM}_{UNIQ} * 3]
82
83[sec2_{TEST_SUMM}_{UNIQ} * {REPCOUNT}]
84"""
85
86code_test_cycles_default = defaults + """
87[defaults]
88REPCOUNT=2
89RUNTIME={% 30, 60 %}
90
91[sec1_{TEST_SUMM}_{UNIQ} * 3]
92runtime={RUNTIME}
93blocksize={% 4k, 4m %}
94"""
95
96
97P = agent.parse_all_in_1
98
99
100class AgentTest(unittest.TestCase):
101 @test("test_parse_value")
102 def test_parse_value(self):
103 x = "asdfasd adsd d"
104 ok(agent.parse_value(x)) == x
105 ok(agent.parse_value("10 2")) == "10 2"
106 ok(agent.parse_value(None)).is_(None)
107 ok(agent.parse_value("10")) == 10
108 ok(agent.parse_value("20")) == 20
109 ok(agent.parse_value("10.1") - 10.1) < 1E-7
110 ok(agent.parse_value("{% 10, 20 %}")) == [10, 20]
111 ok(agent.parse_value("{% 10,20 %}")) == [10, 20]
112
113 code_test_compile_simplest = defaults + """
114[sec1]
115some_extra=1.2314
116"""
117
118 @test("test_compile_simplest")
119 def test_compile_simplest(self):
120 sections = P(self.code_test_compile_simplest, {})
121 sections = list(sections)
122
123 ok(len(sections)) == 1
124 sec1 = sections[0]
125 ok(sec1.name) == "sec1"
126 vals = sec1.vals
127 ok(vals['wait_for_previous']).is_(None)
128 ok(vals['iodepth']) == 1
129 ok(vals['some_extra'] - 1.2314) < 1E-7
130
131 code_test_params_in_defaults = defaults + """
132[defaults]
133RUNTIME=20
134
135[sec1]
136runtime={RUNTIME}
137"""
138
139 @test("test_compile_defaults")
140 def test_compile_defaults(self):
141 sections = P(self.code_test_params_in_defaults, {})
142 sections = list(sections)
143
144 ok(len(sections)) == 1
145 sec1 = sections[0]
146 ok(sec1.name) == "sec1"
147 vals = sec1.vals
148 ok(vals['wait_for_previous']).is_(None)
149 ok(vals['iodepth']) == 1
150 ok(vals['runtime']) == 20
151
152 @test("test_defaults")
153 def test_defaults(self):
154 sections = P(code_test_defaults, {})
155 sections = list(sections)
156
157 ok(len(sections)) == 2
158 sec1, sec2 = sections
159
160 ok(sec1.name) == "sec1"
161 ok(sec2.name) == "sec2"
162
163 ok(sec1.vals['wait_for_previous']).is_(None)
164 ok(sec2.vals['wait_for_previous']).is_(None)
165
166 ok(sec1.vals['iodepth']) == 2
167 ok(sec2.vals['iodepth']) == 1
168
169 ok(sec1.vals['buffered']) == 0
170 ok(sec2.vals['buffered']) == 0
171
172 code_test_ext_params = defaults + """
173[sec1]
174runtime={RUNTIME}
175"""
176
177 @test("test_external_params")
178 def test_external_params(self):
179 with self.assertRaises(KeyError):
180 sections = P(self.code_test_ext_params, {})
181 list(sections)
182
183 sections = P(self.code_test_ext_params,
184 {'RUNTIME': 20})
185 sections = list(sections)
186
187 code_test_cycle = defaults + """
188[sec1]
189runtime={RUNTIME}
190ramp_time={% 20, 40 %}
191"""
192
193 @test("test_cycle")
194 def test_cycle(self):
195 sections = P(self.code_test_cycle,
196 {'RUNTIME': 20})
197 sections = list(sections)
198 ok(len(sections)) == 2
199 ok(sections[0].vals['ramp_time']) == 20
200 ok(sections[1].vals['ramp_time']) == 40
201
202 code_test_cycles = defaults + """
203[sec1]
204ramp_time={% 20, 40 %}
205runtime={RUNTIME}
206blocksize={% 4k, 4m %}
207"""
208
209 @test("test_cycles")
210 def test_cycles(self):
211 sections = P(self.code_test_cycles,
212 {'RUNTIME': 20})
213 sections = list(sections)
214 ok(len(sections)) == 4
215
216 combinations = [
217 (section.vals['ramp_time'], section.vals['blocksize'])
218 for section in sections
219 ]
220
221 combinations.sort()
222
223 ok(combinations) == [(20, '4k'), (20, '4m'), (40, '4k'), (40, '4m')]
224
225 @test("test_time_estimate")
226 def test_time_estimate(self):
227 sections = P(self.code_test_cycles,
228 {'RUNTIME': 20})
229 sections = list(sections)
230 etime = agent.calculate_execution_time(sections)
231
232 ok(etime) == 20 * 4 + 20 * 2 + 40 * 2
233 ok(agent.sec_to_str(etime)) == "0:03:20"
234
235 code_test_cycles2 = defaults + """
236[sec1 * 7]
237ramp_time={% 20, 40 %}
238runtime={RUNTIME}
239blocksize={% 4k, 4m %}
240"""
241
242 @test("test_time_estimate")
243 def test_time_estimate_large(self):
244 sections = P(self.code_test_cycles2,
245 {'RUNTIME': 30})
246 sections = list(sections)
247
248 ok(sections[0].name) == 'sec1'
249 ok(len(sections)) == 7 * 4
250
251 etime = agent.calculate_execution_time(sections)
252 # ramptime optimization
253 expected_time = (20 + 30 + 30 * 6) * 2
254 expected_time += (40 + 30 + 30 * 6) * 2
255 ok(etime) == expected_time
256
257 code_test_cycles3 = defaults + """
258[sec1 * 7]
259ramp_time={% 20, 40 %}
260runtime={RUNTIME}
261blocksize={% 4k, 4m %}
262
263[sec2 * 7]
264ramp_time={% 20, 40 %}
265runtime={RUNTIME}
266blocksize={% 4k, 4m %}
267"""
268
269 @test("test_time_estimate2")
270 def test_time_estimate_large2(self):
271 sections = P(self.code_test_cycles3, {'RUNTIME': 30})
272 sections = list(sections)
273
274 ok(sections[0].name) == 'sec1'
275 ok(sections[1].name) == 'sec1'
276 ok(len(sections)) == 7 * 4 * 2
277
278 etime = agent.calculate_execution_time(sections)
279 # ramptime optimization
280 expected_time = (20 + 30 + 30 * 6) * 2
281 expected_time += (40 + 30 + 30 * 6) * 2
282 ok(etime) == expected_time * 2
283
284 code_test_repeats = defaults + """
285[defaults]
286REPCOUNT=2
287[sec1 * 3]
288[sec2 * {REPCOUNT}]
289"""
290
291 @test("test_repeat")
292 def test_repeat(self):
293 sections = P(self.code_test_repeats, {})
294 sections = list(sections)
295 ok(len(sections)) == 2 + 3
296 ok(sections[0].name) == 'sec1'
297 ok(sections[1].name) == 'sec1'
298 ok(sections[2].name) == 'sec1'
299 ok(sections[3].name) == 'sec2'
300 ok(sections[4].name) == 'sec2'
301
302 @test("test_real_tasks")
303 def test_real_tasks(self):
304 tasks_dir = os.path.dirname(agent.__file__)
305 fname = os.path.join(tasks_dir, 'io_scenario_ceph.cfg')
306 fc = open(fname).read()
307
308 sections = P(fc, {'FILENAME': '/dev/null'})
309 sections = list(sections)
310
311 ok(len(sections)) == 7 * 9 * 4 + 7
312
313 etime = agent.calculate_execution_time(sections)
314 # ramptime optimization
315 expected_time = (60 * 7 + 30) * 9 * 4 + (60 * 7 + 30)
316 ok(etime) == expected_time
317
318if __name__ == '__main__':
319 main()
320
321# def do_run_fio_fake(bconf):
322# def estimate_iops(sz, bw, lat):
323# return 1 / (lat + float(sz) / bw)
324# global count
325# count += 1
326# parsed_out = []
327
328# BW = 120.0 * (1024 ** 2)
329# LAT = 0.003
330
331# for name, cfg in bconf:
332# sz = to_bytes(cfg['blocksize'])
333# curr_lat = LAT * ((random.random() - 0.5) * 0.1 + 1)
334# curr_ulat = curr_lat * 1000000
335# curr_bw = BW * ((random.random() - 0.5) * 0.1 + 1)
336# iops = estimate_iops(sz, curr_bw, curr_lat)
337# bw = iops * sz
338
339# res = {'ctx': 10683,
340# 'error': 0,
341# 'groupid': 0,
342# 'jobname': name,
343# 'majf': 0,
344# 'minf': 30,
345# 'read': {'bw': 0,
346# 'bw_agg': 0.0,
347# 'bw_dev': 0.0,
348# 'bw_max': 0,
349# 'bw_mean': 0.0,
350# 'bw_min': 0,
351# 'clat': {'max': 0,
352# 'mean': 0.0,
353# 'min': 0,
354# 'stddev': 0.0},
355# 'io_bytes': 0,
356# 'iops': 0,
357# 'lat': {'max': 0, 'mean': 0.0,
358# 'min': 0, 'stddev': 0.0},
359# 'runtime': 0,
360# 'slat': {'max': 0, 'mean': 0.0,
361# 'min': 0, 'stddev': 0.0}
362# },
363# 'sys_cpu': 0.64,
364# 'trim': {'bw': 0,
365# 'bw_agg': 0.0,
366# 'bw_dev': 0.0,
367# 'bw_max': 0,
368# 'bw_mean': 0.0,
369# 'bw_min': 0,
370# 'clat': {'max': 0,
371# 'mean': 0.0,
372# 'min': 0,
373# 'stddev': 0.0},
374# 'io_bytes': 0,
375# 'iops': 0,
376# 'lat': {'max': 0, 'mean': 0.0,
377# 'min': 0, 'stddev': 0.0},
378# 'runtime': 0,
379# 'slat': {'max': 0, 'mean': 0.0,
380# 'min': 0, 'stddev': 0.0}
381# },
382# 'usr_cpu': 0.23,
383# 'write': {'bw': 0,
384# 'bw_agg': 0,
385# 'bw_dev': 0,
386# 'bw_max': 0,
387# 'bw_mean': 0,
388# 'bw_min': 0,
389# 'clat': {'max': 0, 'mean': 0,
390# 'min': 0, 'stddev': 0},
391# 'io_bytes': 0,
392# 'iops': 0,
393# 'lat': {'max': 0, 'mean': 0,
394# 'min': 0, 'stddev': 0},
395# 'runtime': 0,
396# 'slat': {'max': 0, 'mean': 0.0,
397# 'min': 0, 'stddev': 0.0}
398# }
399# }
400
401# if cfg['rw'] in ('read', 'randread'):
402# key = 'read'
403# elif cfg['rw'] in ('write', 'randwrite'):
404# key = 'write'
405# else:
406# raise ValueError("Uknown op type {0}".format(key))
407
408# res[key]['bw'] = bw
409# res[key]['iops'] = iops
410# res[key]['runtime'] = 30
411# res[key]['io_bytes'] = res[key]['runtime'] * bw
412# res[key]['bw_agg'] = bw
413# res[key]['bw_dev'] = bw / 30
414# res[key]['bw_max'] = bw * 1.5
415# res[key]['bw_min'] = bw / 1.5
416# res[key]['bw_mean'] = bw
417# res[key]['clat'] = {'max': curr_ulat * 10, 'mean': curr_ulat,
418# 'min': curr_ulat / 2, 'stddev': curr_ulat}
419# res[key]['lat'] = res[key]['clat'].copy()
420# res[key]['slat'] = res[key]['clat'].copy()
421
422# parsed_out.append(res)
423
424# return zip(parsed_out, bconf)