blob: fa23cb788cba9623a75389b69d65740237bbaf19 [file] [log] [blame]
mbligh5bba5ca2008-06-10 16:27:26 +00001#!/usr/bin/python
2
jadmanski6ca37b62008-06-30 21:17:07 +00003import os, unittest, pickle, shutil, sys, time
mbligh5bba5ca2008-06-10 16:27:26 +00004import common
jadmanski6f731362008-06-17 16:47:06 +00005
mbligh5bba5ca2008-06-10 16:27:26 +00006from autotest_lib.client.bin import job, boottool, config, sysinfo, harness
jadmanski6ca37b62008-06-30 21:17:07 +00007from autotest_lib.client.bin import test, xen, kernel, autotest_utils, cpuset
8from autotest_lib.client.common_lib import utils, error, logging
mbligh5bba5ca2008-06-10 16:27:26 +00009from autotest_lib.client.common_lib.test_utils import mock
10
11
jadmanski6f731362008-06-17 16:47:06 +000012class first_line_comparator(mock.argument_comparator):
13 def __init__(self, first_line):
14 self.first_line = first_line
15
16
17 def is_satisfied_by(self, parameter):
18 return self.first_line == parameter.splitlines()[0]
19
20
mbligh5bba5ca2008-06-10 16:27:26 +000021class TestBaseJob(unittest.TestCase):
22 def setUp(self):
23 # make god
24 self.god = mock.mock_god()
25
26 # need to set some environ variables
27 self.autodir = "autodir"
28 os.environ['AUTODIR'] = self.autodir
29
30 # set up some variables
31 self.control = "control"
32 self.jobtag = "jobtag"
33
34 # stub out some stuff
35 self.god.stub_function(os.path, 'exists')
mblighc1f8ced2008-06-13 21:43:28 +000036 self.god.stub_function(os.path, 'isdir')
mbligh5bba5ca2008-06-10 16:27:26 +000037 self.god.stub_function(os, 'mkdir')
38 self.god.stub_function(shutil, 'copyfile')
39 self.god.stub_function(job, 'open')
40 self.god.stub_function(utils, 'system')
41 self.god.stub_function(harness, 'select')
42 self.god.stub_function(sysinfo, 'log_per_reboot_data')
43 self.god.stub_function(pickle, 'load')
44 self.god.stub_function(sysinfo, 'log_per_reboot_data')
45
46 self.god.stub_class(config, 'config')
47 self.god.stub_class(boottool, 'boottool')
48
49
50 def tearDown(self):
51 self.god.unstub_all()
52
53
54 def construct_job(self, cont):
55 # will construct class instance using __new__
56 self.job = job.base_job.__new__(job.base_job)
57
58 # now some specific stubs
59 self.god.stub_function(self.job, '_load_state')
60 self.god.stub_function(self.job, '_init_group_level')
61 self.god.stub_function(self.job, 'config_get')
62 self.god.stub_function(self.job, 'record')
63 self.god.stub_function(self.job, '_increment_group_level')
jadmanski6f731362008-06-17 16:47:06 +000064 self.god.stub_function(self.job, '_decrement_group_level')
mbligh5bba5ca2008-06-10 16:27:26 +000065 self.god.stub_function(self.job, 'get_state')
66
67 # other setup
68 tmpdir = os.path.join(self.autodir, 'tmp')
69 results = os.path.join(self.autodir, 'results')
70 download = os.path.join(self.autodir, 'tests', 'download')
71 resultdir = os.path.join(self.autodir, 'results', self.jobtag)
72 sysinfodir = os.path.join(resultdir, 'sysinfo')
73
74 # record
75 self.job._load_state.expect_call()
76 if not cont:
77 os.path.exists.expect_call(tmpdir).and_return(False)
78 os.mkdir.expect_call(tmpdir)
79 os.path.exists.expect_call(results).and_return(False)
80 os.mkdir.expect_call(results)
81 os.path.exists.expect_call(download).and_return(False)
82 os.mkdir.expect_call(download)
83 os.path.exists.expect_call(resultdir).and_return(True)
84 utils.system.expect_call('rm -rf ' + resultdir)
85 os.mkdir.expect_call(resultdir)
86 os.mkdir.expect_call(sysinfodir)
87 os.mkdir.expect_call(os.path.join(resultdir, 'debug'))
88 os.mkdir.expect_call(os.path.join(resultdir,
89 'analysis'))
90 shutil.copyfile.expect_call(mock.is_string_comparator(),
91 os.path.join(resultdir, 'control'))
92
93 self.job._init_group_level.expect_call()
94 self.config = config.config.expect_new(self.job)
95 my_harness = self.god.create_mock_class(harness.harness,
96 'my_harness')
97 harness.select.expect_call(None,
98 self.job).and_return(my_harness)
99 self.job.config_get.expect_call(
100 'boottool.executable').and_return(None)
101 bootloader = boottool.boottool.expect_new(None)
102 sysinfo.log_per_reboot_data.expect_call(sysinfodir)
103 if not cont:
104 self.job.record.expect_call('START', None, None)
105 self.job._increment_group_level.expect_call()
106
107 my_harness.run_start.expect_call()
108 self.job.get_state.expect_call('__monitor_disk',
109 default=0.0).and_return(0.0)
110
111 # finish constructor
112 self.job.__init__(self.control, self.jobtag, cont)
113
114 # check
115 self.god.check_playback()
116
mblighc1f8ced2008-06-13 21:43:28 +0000117
mbligh5bba5ca2008-06-10 16:27:26 +0000118 def test_constructor(self):
119 self.construct_job(False)
120
121
122 def test_monitor_disk_usage(self):
123 self.construct_job(True)
124
125 # setup
126 self.god.stub_function(self.job, 'set_state')
127
128 # record
129 max_rate = 10.0
130 self.job.set_state.expect_call('__monitor_disk', max_rate)
131
132 # test
133 self.job.monitor_disk_usage(max_rate)
134 self.god.check_playback()
135
136
jadmanski6ca37b62008-06-30 21:17:07 +0000137 def test_relative_path(self):
mblighc1f8ced2008-06-13 21:43:28 +0000138 self.construct_job(True)
139 dummy = "asdf"
140 ret = self.job.relative_path(os.path.join(self.job.resultdir, dummy))
141 self.assertEquals(ret, dummy)
142
143
144 def test_control_functions(self):
145 self.construct_job(True)
146 control_file = "blah"
147 self.job.control_set(control_file)
148 self.assertEquals(self.job.control_get(), os.path.abspath(control_file))
149
150
mbligh5bba5ca2008-06-10 16:27:26 +0000151 def test_harness_select(self):
152 self.construct_job(True)
153
154 # record
155 which = "which"
156 harness.select.expect_call(which, self.job).and_return(None)
157
158 # run and test
159 self.job.harness_select(which)
160 self.god.check_playback()
161
162
163 def test_config_set(self):
164 self.construct_job(True)
165
166 # record
167 name = "foo"
168 val = 10
169 self.config.set.expect_call(name, val)
170
171 # run and test
172 self.job.config_set(name, val)
173 self.god.check_playback()
174
175
176 def test_config_get(self):
177 self.construct_job(True)
178
179 # unstub config_get
180 self.god.unstub(self.job, 'config_get')
181 # record
182 name = "foo"
183 val = 10
184 self.config.get.expect_call(name).and_return(val)
185
186 # run and test
187 self.job.config_get(name)
188 self.god.check_playback()
189
190
mblighc1f8ced2008-06-13 21:43:28 +0000191 def test_setup_dirs_raise(self):
192 self.construct_job(True)
193
194 # setup
195 results_dir = 'foo'
196 tmp_dir = 'bar'
197
198 # record
199 os.path.exists.expect_call(tmp_dir).and_return(True)
200 os.path.isdir.expect_call(tmp_dir).and_return(False)
201
202 # test
203 self.assertRaises(ValueError, self.job.setup_dirs, results_dir, tmp_dir)
204 self.god.check_playback()
205
206
207 def test_setup_dirs(self):
208 self.construct_job(True)
209
210 # setup
211 results_dir1 = os.path.join(self.job.resultdir, 'build')
212 results_dir2 = os.path.join(self.job.resultdir, 'build.2')
213 results_dir3 = os.path.join(self.job.resultdir, 'build.3')
214 tmp_dir = 'bar'
215
216 # record
217 os.path.exists.expect_call(tmp_dir).and_return(False)
218 os.mkdir.expect_call(tmp_dir)
219 os.path.isdir.expect_call(tmp_dir).and_return(True)
220 os.path.exists.expect_call(results_dir1).and_return(True)
221 os.path.exists.expect_call(results_dir2).and_return(True)
222 os.path.exists.expect_call(results_dir3).and_return(False)
223 os.path.exists.expect_call(results_dir3).and_return(False)
224 os.mkdir.expect_call(results_dir3)
225
226 # test
227 self.assertEqual(self.job.setup_dirs(None, tmp_dir),
228 (results_dir3, tmp_dir))
229 self.god.check_playback()
230
231
jadmanski6ca37b62008-06-30 21:17:07 +0000232 def test_xen(self):
233 self.construct_job(True)
234
235 # setup
236 self.god.stub_function(self.job, "setup_dirs")
237 self.god.stub_class(xen, "xen")
238 results = 'results_dir'
239 tmp = 'tmp'
240 build = 'xen'
241 base_tree = object()
242
243 # record
244 self.job.setup_dirs.expect_call(results,
245 tmp).and_return((results, tmp))
246 myxen = xen.xen.expect_new(self.job, base_tree, results, tmp, build,
247 False, None)
248
249 # run job and check
250 axen = self.job.xen(base_tree, results, tmp)
251 self.god.check_playback()
252 self.assertEquals(myxen, axen)
253
254
255 def test_kernel_rpm(self):
256 self.construct_job(True)
257
258 # setup
259 self.god.stub_function(self.job, "setup_dirs")
260 self.god.stub_class(kernel, "rpm_kernel")
261 self.god.stub_function(kernel, "preprocess_path")
262 results = 'results_dir'
263 tmp = 'tmp'
264 build = 'xen'
265 path = "somepath.rpm"
266
267 # record
268 self.job.setup_dirs.expect_call(results,
269 tmp).and_return((results, tmp))
270 kernel.preprocess_path.expect_call(path).and_return(path)
271 mykernel = kernel.rpm_kernel.expect_new(self.job, path, results)
272
273 # check
274 akernel = self.job.kernel(path, results, tmp)
275 self.god.check_playback()
276 self.assertEquals(mykernel, akernel)
277
278
279 def test_kernel(self):
280 self.construct_job(True)
281
282 # setup
283 self.god.stub_function(self.job, "setup_dirs")
284 self.god.stub_class(kernel, "kernel")
285 self.god.stub_function(kernel, "preprocess_path")
286 results = 'results_dir'
287 tmp = 'tmp'
288 build = 'linux'
289 path = "somepath.deb"
290
291 # record
292 self.job.setup_dirs.expect_call(results,
293 tmp).and_return((results, tmp))
294 kernel.preprocess_path.expect_call(path).and_return(path)
295 mykernel = kernel.kernel.expect_new(self.job, path, results, tmp,
296 build, False)
297
298 # check
299 akernel = self.job.kernel(path, results, tmp)
300 self.god.check_playback()
301 self.assertEquals(mykernel, akernel)
302
303
jadmanski6f731362008-06-17 16:47:06 +0000304 def test_run_test_logs_test_error_from_unhandled_error(self):
305 self.construct_job(True)
306
307 # set up stubs
308 self.god.stub_function(test, "testname")
309 self.god.stub_function(self.job, "_runtest")
310
311 # create an unhandled error object
312 class MyError(error.TestError):
313 pass
314 real_error = MyError("this is the real error message")
315 unhandled_error = error.UnhandledError(real_error)
316
317 # set up the recording
318 testname = "error_test"
319 outputdir = os.path.join(self.job.resultdir, testname)
320 test.testname.expect_call(testname).and_return(("", testname))
321 os.path.exists.expect_call(outputdir).and_return(False)
322 os.mkdir.expect_call(outputdir)
323 self.job.record.expect_call("START", testname, testname)
324 self.job._increment_group_level.expect_call()
325 self.job._runtest.expect_call(testname, "", (), {}).and_raises(
326 unhandled_error)
327 self.job.record.expect_call("FAIL", testname, testname,
328 first_line_comparator(str(real_error)))
329 self.job._decrement_group_level.expect_call()
330 self.job.record.expect_call("END FAIL", testname, testname,
331 first_line_comparator(str(real_error)))
332
333 # run and check
334 self.job.run_test(testname)
335 self.god.check_playback()
336
337
338 def test_run_test_logs_non_test_error_from_unhandled_error(self):
339 self.construct_job(True)
340
341 # set up stubs
342 self.god.stub_function(test, "testname")
343 self.god.stub_function(self.job, "_runtest")
344
345 # create an unhandled error object
346 class MyError(Exception):
347 pass
348 real_error = MyError("this is the real error message")
349 unhandled_error = error.UnhandledError(real_error)
350 reason = first_line_comparator("Unhandled MyError: %s" % real_error)
351
352 # set up the recording
353 testname = "error_test"
354 outputdir = os.path.join(self.job.resultdir, testname)
355 test.testname.expect_call(testname).and_return(("", testname))
356 os.path.exists.expect_call(outputdir).and_return(False)
357 os.mkdir.expect_call(outputdir)
358 self.job.record.expect_call("START", testname, testname)
359 self.job._increment_group_level.expect_call()
360 self.job._runtest.expect_call(testname, "", (), {}).and_raises(
361 unhandled_error)
362 self.job.record.expect_call("FAIL", testname, testname, reason)
363 self.job._decrement_group_level.expect_call()
364 self.job.record.expect_call("END FAIL", testname, testname, reason)
365
366 # run and check
367 self.job.run_test(testname)
368 self.god.check_playback()
369
jadmanski6ca37b62008-06-30 21:17:07 +0000370
371 def new_container(self):
372 self.construct_job(True)
373
374 # set up stubs
375 self.god.stub_function(autotest_utils, "grep")
376 self.god.stub_function(os, "getpid")
377 self.god.stub_class(cpuset, "cpuset")
378 pid = 100
379 name = 'test%d' % pid
380
381 # record
382 autotest_utils.grep.expect_call('cpuset',
383 '/proc/filesystems').and_return(True)
384 os.getpid.expect_call().and_return(pid)
385
386 container = cpuset.cpuset.expect_new(name, job_size=None, job_pid=pid,
mbligha9a87a62008-07-09 21:54:30 +0000387 cpus=None, root=None, disk=None,
jadmanski9e722982008-07-01 14:19:23 +0000388 network=None)
jadmanski6ca37b62008-06-30 21:17:07 +0000389
390 # run test
391 self.job.new_container()
mbligha9a87a62008-07-09 21:54:30 +0000392
jadmanski6ca37b62008-06-30 21:17:07 +0000393 self.god.check_playback()
394 return container
395
396
397 def test_new_container(self):
398 container = self.new_container()
399 self.assertEquals(self.job.container, container)
400
401
402 def test_release_container(self):
403 self.new_container()
404
405 # record
406 self.job.container.release.expect_call()
407
408 # run
409 self.job.release_container()
410 self.god.check_playback()
411 self.assertEquals(self.job.container, None)
412
413
414 def test_record(self):
415 self.construct_job(True)
416
417 # steup
418 self.job.group_level = 1
419 status = ''
420 status_code = "PASS"
421 subdir = "subdir"
422 operation = "super_fun"
423 mytime = "1234"
424 msg_tag = ""
425 if "." in self.job.log_filename:
426 msg_tag = self.job.log_filename.split(".", 1)[1]
427 epoch_time = int(mytime)
428 local_time = time.localtime(epoch_time)
429 optional_fields = {}
430 optional_fields["timestamp"] = str(epoch_time)
431 optional_fields["localtime"] = time.strftime("%b %d %H:%M:%S",
432 local_time)
433 fields = [status_code, subdir, operation]
434 fields += ["%s=%s" % x for x in optional_fields.iteritems()]
435 fields.append(status)
436 msg = '\t'.join(str(x) for x in fields)
437 msg = '\t' * self.job.group_level + msg
438
439 self.god.stub_function(logging, "is_valid_status")
440 self.god.stub_function(time, "time")
441 self.god.stub_function(self.job, "open")
442
443
444 # record
445 logging.is_valid_status.expect_call(status_code).and_return(True)
446 time.time.expect_call().and_return(mytime)
447 self.job.harness.test_status_detail.expect_call(status_code, subdir,
448 operation, '', msg_tag)
449 self.job.harness.test_status.expect_call(msg, msg_tag)
450 myfile = self.god.create_mock_class(file, "file")
451 status_file = os.path.join(self.job.resultdir, self.job.log_filename)
452 self.job.open.expect_call(status_file, "a").and_return(myfile)
453 myfile.write.expect_call(msg + "\n")
454
455 dir = os.path.join(self.job.resultdir, subdir)
456 status_file = os.path.join(dir, self.job.DEFAULT_LOG_FILENAME)
457 self.job.open.expect_call(status_file, "a").and_return(myfile)
458 myfile.write.expect_call(msg + "\n")
459
460
461 # run test
462 self.god.unstub(self.job, "record")
463 self.job.record(status_code, subdir, operation)
464 self.god.check_playback()
465
466
mbligh5bba5ca2008-06-10 16:27:26 +0000467if __name__ == "__main__":
468 unittest.main()