1#!/usr/bin/python
2
3import unittest, os, time, re, glob, logging
4import common
5from autotest_lib.client.common_lib.test_utils import mock
6from autotest_lib.client.bin import kernel, job, utils, kernelexpand
7from autotest_lib.client.bin import kernel_config, boottool, os_dep
8
9
10class TestAddKernelToBootLoader(unittest.TestCase):
11
12    def add_to_bootloader(self, base_args, args, bootloader_args,
13                          bootloader_root, tag='image', image='image',
14                          initrd='initrd'):
15        god = mock.mock_god()
16        bootloader = god.create_mock_class(boottool.boottool, "boottool")
17
18        # record
19        bootloader.remove_kernel.expect_call(tag)
20        bootloader.add_kernel.expect_call(image, tag, initrd=initrd,
21                                          args='_dummy_', root=bootloader_root)
22
23        for a in bootloader_args.split():
24            bootloader.add_args.expect_call(kernel=tag, args=a)
25        bootloader.remove_args.expect_call(kernel=tag, args='_dummy_')
26
27        # run and check
28        kernel._add_kernel_to_bootloader(bootloader, base_args, tag, args,
29                                         image, initrd)
30        god.check_playback()
31
32
33    def test_add_kernel_to_bootloader(self):
34        self.add_to_bootloader(base_args='baseargs', args='',
35                               bootloader_args='baseargs', bootloader_root=None)
36        self.add_to_bootloader(base_args='arg1 root=/dev/oldroot arg2',
37                               args='root=/dev/newroot arg3',
38                               bootloader_args='arg1 arg2 arg3',
39                               bootloader_root='/dev/newroot')
40
41
42class TestBootableKernel(unittest.TestCase):
43
44    def setUp(self):
45        self.god = mock.mock_god()
46        self.god.stub_function(time, "time")
47        self.god.stub_function(utils, "system")
48        self.god.stub_function(kernel, "_add_kernel_to_bootloader")
49        job_ = self.god.create_mock_class(job.job, "job")
50        self.kernel = kernel.BootableKernel(job_)
51        self.kernel.job.bootloader = self.god.create_mock_class(
52                              boottool.boottool, "boottool")
53
54
55    def tearDown(self):
56        # note: time.time() can only be unstubbed via tearDown()
57        self.god.unstub_all()
58
59
60    def boot_kernel(self, ident_check):
61        notes = "applied_patches"
62        when = 1
63        args = ''
64        base_args = 'base_args'
65        tag = 'ident'
66        subdir = 'subdir'
67        self.kernel.image = 'image'
68        self.kernel.initrd = 'initrd'
69        self.kernel.installed_as = tag
70
71        # record
72        args_ = args
73        if ident_check:
74            time.time.expect_call().and_return(when)
75            args_ += " IDENT=%d" % when
76            status = ["job.end_reboot_and_verify", when, tag, subdir, notes]
77        else:
78            status = ["job.end_reboot", subdir, tag, notes]
79        self.kernel.job.next_step_prepend.expect_call(status)
80        self.kernel.job.config_get.expect_call(
81                'boot.default_args').and_return(base_args)
82        kernel._add_kernel_to_bootloader.expect_call(
83                self.kernel.job.bootloader, base_args, tag,
84                args_, self.kernel.image, self.kernel.initrd)
85        utils.system.expect_call('touch /fastboot')
86        self.kernel.job.start_reboot.expect_call()
87        self.kernel.job.reboot.expect_call(tag=tag)
88
89        # run and check
90        self.kernel._boot_kernel(args=args, ident_check=ident_check,
91                                 expected_ident=tag, subdir=subdir, notes=notes)
92        self.god.check_playback()
93
94
95    def test_boot_kernel(self):
96        self.boot_kernel(ident_check=False)
97        self.boot_kernel(ident_check=True)
98
99
100class TestKernel(unittest.TestCase):
101    def setUp(self):
102        self.god = mock.mock_god()
103
104        logging.disable(logging.CRITICAL)
105
106        self.god.stub_function(time, "time")
107        self.god.stub_function(os, "mkdir")
108        self.god.stub_function(os, "chdir")
109        self.god.stub_function(os, "symlink")
110        self.god.stub_function(os, "remove")
111        self.god.stub_function(os.path, "isdir")
112        self.god.stub_function(os.path, "exists")
113        self.god.stub_function(os.path, "isfile")
114        self.god.stub_function(os_dep, "commands")
115        self.god.stub_function(kernel, "open")
116        self.god.stub_function(utils, "system")
117        self.god.stub_function(utils, "system_output")
118        self.god.stub_function(utils, "get_file")
119        self.god.stub_function(utils, "get_current_kernel_arch")
120        self.god.stub_function(utils, "cat_file_to_cmd")
121        self.god.stub_function(utils, "force_copy")
122        self.god.stub_function(utils, "extract_tarball_to_dir")
123        self.god.stub_function(utils, "count_cpus")
124        self.god.stub_function(utils, "get_os_vendor")
125        self.god.stub_function(kernelexpand, "expand_classic")
126        self.god.stub_function(kernel_config, "modules_needed")
127        self.god.stub_function(glob, "glob")
128        def dummy_mark(filename, msg):
129            pass
130        self.god.stub_with(kernel, '_mark', dummy_mark)
131
132        self.job = self.god.create_mock_class(job.job, "job")
133        self.job.bootloader = self.god.create_mock_class(boottool.boottool,
134                                                         "boottool")
135
136        class DummyLoggingManager(object):
137            def tee_redirect_debug_dir(self, *args, **kwargs):
138                pass
139
140
141            def restore(self, *args, **kwargs):
142                pass
143
144        self.job.logging = DummyLoggingManager()
145
146        self.job.autodir = "autodir"
147        self.base_tree = "2.6.24"
148        self.tmp_dir = "tmpdir"
149        self.subdir = "subdir"
150
151
152    def tearDown(self):
153        self.god.unstub_all()
154
155
156    def construct_kernel(self):
157        self.kernel = kernel.kernel.__new__(kernel.kernel)
158        self.god.stub_function(self.kernel, "extract")
159
160        # setup
161        self.src_dir    = os.path.join(self.tmp_dir, 'src')
162        self.build_dir  = os.path.join(self.tmp_dir, "build_dir")
163        self.config_dir = os.path.join(self.subdir, 'config')
164        self.log_dir    = os.path.join(self.subdir, 'debug')
165        self.results_dir = os.path.join(self.subdir, 'results')
166
167        # record
168        os.path.isdir.expect_call(self.src_dir).and_return(True)
169        utils.system.expect_call('rm -rf ' + self.src_dir)
170        os.path.isdir.expect_call(self.build_dir).and_return(True)
171        utils.system.expect_call('rm -rf ' + self.build_dir)
172        os.path.exists.expect_call(self.src_dir).and_return(False)
173        os.mkdir.expect_call(self.src_dir)
174        for path in [self.config_dir, self.log_dir, self.results_dir]:
175            os.path.exists.expect_call(path).and_return(True)
176            utils.system.expect_call('rm -rf ' + path)
177            os.mkdir.expect_call(path)
178
179        logpath = os.path.join(self.log_dir, 'build_log')
180        self.logfile = self.god.create_mock_class(file, "file")
181        kernel.open.expect_call(logpath, 'w+').and_return(self.logfile)
182        utils.get_current_kernel_arch.expect_call().and_return('ia64')
183        self.logfile.write.expect_call('BASE: %s\n' % self.base_tree)
184        self.kernel.extract.expect_call(self.base_tree)
185
186        # finish creation of kernel object and test (and unstub extract)
187        self.kernel.__init__(self.job, self.base_tree, self.subdir,
188                             self.tmp_dir, "build_dir")
189        self.god.check_playback()
190        self.god.unstub(self.kernel, "extract")
191
192
193    def test_constructor(self):
194        self.construct_kernel()
195
196
197    def test_kernelexpand1(self):
198        self.construct_kernel()
199
200        ret_val = self.kernel.kernelexpand("/path/to/kernel")
201        self.assertEquals(ret_val, ["/path/to/kernel"])
202        self.god.check_playback()
203
204
205    def test_kernel_expand2(self):
206        self.construct_kernel()
207        kernel = "kernel.tar.gz"
208
209        # record
210        self.job.config_get.expect_call('mirror.mirrors').and_return('mirror')
211        kernelexpand.expand_classic.expect_call(kernel,
212            'mirror').and_return('patches')
213
214        # run
215        self.assertEquals(self.kernel.kernelexpand(kernel), 'patches')
216        self.god.check_playback()
217
218
219    def test_kernel_expand3(self):
220        self.construct_kernel()
221        kernel = "kernel.tar.gz"
222
223        # record
224        self.job.config_get.expect_call('mirror.mirrors')
225        self.job.config_get.expect_call(
226            'mirror.ftp_kernel_org').and_return('mirror')
227        korg = 'http://www.kernel.org/pub/linux/kernel'
228        mirrors = [
229                   [ korg + '/v2.6', 'mirror' + '/v2.6' ],
230                   [ korg + '/people/akpm/patches/2.6', 'mirror' + '/akpm' ],
231                   [ korg + '/people/mbligh', 'mirror' + '/mbligh' ],
232                  ]
233        kernelexpand.expand_classic.expect_call(kernel,
234            mirrors).and_return('patches')
235
236        # run
237        self.assertEquals(self.kernel.kernelexpand(kernel), 'patches')
238        self.god.check_playback()
239
240
241    def test_extract1(self):
242        self.construct_kernel()
243
244        # setup
245        self.god.stub_function(self.kernel, "get_kernel_tree")
246
247        # record
248        os.path.exists.expect_call(self.base_tree).and_return(True)
249        self.kernel.get_kernel_tree.expect_call(self.base_tree)
250        self.job.record.expect_call('GOOD', self.subdir, 'kernel.extract')
251
252        # run
253        self.kernel.extract(self.base_tree)
254        self.god.check_playback()
255        self.god.unstub(self.kernel, "get_kernel_tree")
256
257
258    def test_extract2(self):
259        self.construct_kernel()
260
261        # setup
262        self.god.stub_function(self.kernel, "kernelexpand")
263        self.god.stub_function(self.kernel, "get_kernel_tree")
264        self.god.stub_function(self.kernel, "patch")
265
266        # record
267        os.path.exists.expect_call(self.base_tree).and_return(False)
268        components = ["component0", "component1"]
269        self.kernel.kernelexpand.expect_call(self.base_tree).and_return(
270            components)
271        self.kernel.get_kernel_tree.expect_call(components[0])
272        self.kernel.patch.expect_call(components[1])
273        self.job.record.expect_call('GOOD', self.subdir, 'kernel.extract')
274
275        # run
276        self.kernel.extract(self.base_tree)
277        self.god.check_playback()
278        self.god.unstub(self.kernel, "kernelexpand")
279        self.god.unstub(self.kernel, "get_kernel_tree")
280        self.god.unstub(self.kernel, "patch")
281
282
283    def test_patch1(self):
284        self.construct_kernel()
285        patches = ('patch1', 'patch2')
286        self.god.stub_function(self.kernel, "apply_patches")
287        self.god.stub_function(self.kernel, "get_patches")
288
289        #record
290        self.kernel.get_patches.expect_call(patches).and_return(patches)
291        self.kernel.apply_patches.expect_call(patches)
292        self.job.record.expect_call('GOOD', self.subdir, 'kernel.patch')
293
294        #run
295        self.kernel.patch(*patches)
296        self.god.check_playback()
297        self.god.unstub(self.kernel, "apply_patches")
298        self.god.unstub(self.kernel, "get_patches")
299
300
301    def test_patch2(self):
302        self.construct_kernel()
303        patches = []
304
305        # record
306        self.job.record.expect_call('GOOD', self.subdir, 'kernel.patch')
307
308        # run
309        self.kernel.patch(*patches)
310        self.god.check_playback()
311
312
313    def test_config(self):
314        self.construct_kernel()
315
316        # setup
317        self.god.stub_function(self.kernel, "set_cross_cc")
318        self.god.stub_class(kernel_config, "kernel_config")
319
320        # record
321        self.kernel.set_cross_cc.expect_call()
322        kernel_config.kernel_config.expect_new(self.job, self.build_dir,
323                                               self.config_dir, '', None,
324                                               False, self.base_tree, None)
325        self.job.record.expect_call('GOOD', self.subdir, 'kernel.config')
326
327        # run
328        self.kernel.config()
329        self.god.check_playback()
330        self.god.unstub(self.kernel, "set_cross_cc")
331
332
333    def test_get_patches(self):
334        self.construct_kernel()
335
336        # setup
337        patches = ['patch1', 'patch2', 'patch3']
338        local_patches = []
339
340        # record
341        for patch in patches:
342            dest = os.path.join(self.src_dir, os.path.basename(patch))
343            utils.get_file.expect_call(patch, dest)
344            utils.system_output.expect_call(
345                'md5sum ' + dest).and_return('md5sum')
346            local_patches.append((patch, dest, 'md5sum'))
347
348        # run and check
349        self.assertEquals(self.kernel.get_patches(patches), local_patches)
350        self.god.check_playback()
351
352
353    def test_apply_patches(self):
354        self.construct_kernel()
355
356        # setup
357        patches = []
358        patches.append(('patch1', 'patch1.gz', 'md5sum1'))
359        patches.append(('patch2', 'patch2.bz2', 'md5sum2'))
360        patches.append(('patch3', 'patch3', 'md5sum3'))
361        applied_patches = []
362
363        # record
364        os.chdir.expect_call(self.build_dir)
365
366        patch_id = "%s %s %s" % ('patch1', 'patch1', 'md5sum1')
367        log = "PATCH: " + patch_id + "\n"
368        utils.cat_file_to_cmd.expect_call('patch1.gz',
369            'patch -p1 > /dev/null')
370        self.logfile.write.expect_call(log)
371        applied_patches.append(patch_id)
372
373        patch_id = "%s %s %s" % ('patch2', 'patch2', 'md5sum2')
374        log = "PATCH: " + patch_id + "\n"
375        utils.cat_file_to_cmd.expect_call('patch2.bz2',
376            'patch -p1 > /dev/null')
377        self.logfile.write.expect_call(log)
378        applied_patches.append(patch_id)
379
380        utils.force_copy.expect_call('patch3',
381            self.results_dir).and_return('local_patch3')
382        self.job.relative_path.expect_call('local_patch3').and_return(
383            'rel_local_patch3')
384        patch_id = "%s %s %s" % ('patch3', 'rel_local_patch3', 'md5sum3')
385        log = "PATCH: " + patch_id + "\n"
386        utils.cat_file_to_cmd.expect_call('patch3',
387            'patch -p1 > /dev/null')
388        self.logfile.write.expect_call(log)
389        applied_patches.append(patch_id)
390
391        # run and test
392        self.kernel.apply_patches(patches)
393        self.assertEquals(self.kernel.applied_patches, applied_patches)
394        self.god.check_playback()
395
396
397    def test_get_kernel_tree1(self):
398        self.construct_kernel()
399
400        # record
401        os.path.isdir.expect_call(self.base_tree).and_return(True)
402        os.symlink.expect_call(self.base_tree, self.build_dir)
403
404        # run and check
405        self.kernel.get_kernel_tree(self.base_tree)
406        self.god.check_playback()
407
408
409    def test_get_kernel_tree2(self):
410        self.construct_kernel()
411
412        # record
413        os.path.isdir.expect_call(self.base_tree).and_return(False)
414        os.chdir.expect_call(os.path.dirname(self.src_dir))
415        tarball = os.path.join(self.src_dir, os.path.basename(self.base_tree))
416        utils.get_file.expect_call(self.base_tree, tarball)
417        utils.extract_tarball_to_dir.expect_call(tarball,
418                                                          self.build_dir)
419
420        # run and check
421        self.kernel.get_kernel_tree(self.base_tree)
422        self.god.check_playback()
423
424
425    def test_extraversion(self):
426        self.construct_kernel()
427        tag = "tag"
428        # setup
429        self.god.stub_function(self.kernel, "config")
430
431        # record
432        os.chdir.expect_call(self.build_dir)
433        extraversion_sub = r's/^CONFIG_LOCALVERSION=\s*"\(.*\)"/CONFIG_LOCALVERSION='
434        cfg = self.build_dir + '/.config'
435        p = extraversion_sub + '"\\1-%s"/' % tag
436        utils.system.expect_call('mv %s %s.old' % (cfg, cfg))
437        utils.system.expect_call("sed '%s' < %s.old > %s" % (p, cfg, cfg))
438        self.kernel.config.expect_call(make='oldconfig')
439
440        # run and check
441        self.kernel.extraversion(tag)
442        self.god.check_playback()
443
444
445    def test_build(self):
446        self.construct_kernel()
447        self.god.stub_function(self.kernel, "extraversion")
448        self.god.stub_function(self.kernel, "set_cross_cc")
449        self.god.stub_function(self.kernel, "get_kernel_build_ver")
450        self.kernel.build_target = 'build_target'
451
452        # record
453        os_dep.commands.expect_call('gcc', 'make')
454        logfile = os.path.join(self.log_dir, 'kernel_build')
455        os.chdir.expect_call(self.build_dir)
456        self.kernel.extraversion.expect_call('autotest')
457        self.kernel.set_cross_cc.expect_call()
458        utils.system.expect_call('make dep', ignore_status=True)
459        utils.count_cpus.expect_call().and_return(4)
460        threads = 2 * 4
461        build_string = 'make -j %d %s %s' % (threads, '', 'build_target')
462        utils.system.expect_call(build_string)
463        kernel_config.modules_needed.expect_call('.config').and_return(True)
464        utils.system.expect_call('make -j %d modules' % (threads))
465        self.kernel.get_kernel_build_ver.expect_call().and_return('2.6.24')
466        kernel_version = re.sub('-autotest', '', '2.6.24')
467        self.logfile.write.expect_call('BUILD VERSION: %s\n' % kernel_version)
468        utils.force_copy.expect_call(self.build_dir+'/System.map',
469                                              self.results_dir)
470        self.job.record.expect_call('GOOD', self.subdir, 'kernel.build')
471
472        # run and check
473        self.kernel.build()
474        self.god.check_playback()
475
476
477    def test_build_timed(self):
478        self.construct_kernel()
479        self.god.stub_function(self.kernel, "set_cross_cc")
480        self.god.stub_function(self.kernel, "clean")
481
482        # record
483        os.chdir.expect_call(self.build_dir)
484        self.kernel.set_cross_cc.expect_call()
485        self.kernel.clean.expect_call()
486        build_string = "/usr/bin/time -o /dev/null make  -j 8 vmlinux"
487        build_string += ' > /dev/null 2>&1'
488        utils.system.expect_call(build_string)
489        os.path.isfile.expect_call('vmlinux').and_return(True)
490
491        # run and check
492        self.kernel.build_timed(threads=8)
493        self.god.check_playback()
494
495
496    def test_clean(self):
497        self.construct_kernel()
498
499        # record
500        os.chdir.expect_call(self.build_dir)
501        utils.system.expect_call('make clean > /dev/null 2> /dev/null')
502        self.job.record.expect_call('GOOD', self.subdir, 'kernel.clean')
503
504        # run and check
505        self.kernel.clean()
506        self.god.check_playback()
507
508
509    def test_mkinitrd(self):
510        self.construct_kernel()
511
512        # record
513        utils.get_os_vendor.expect_call().and_return('Ubuntu')
514        os.path.isfile.expect_call('initrd').and_return(True)
515        os.remove.expect_call('initrd')
516        self.job.config_get.expect_call(
517            'kernel.mkinitrd_extra_args').and_return(None)
518        args = ''
519        glob.glob.expect_call('/lib/modules/2.6.24*').and_return(['2.6.24'])
520        os.path.isfile.expect_call('/usr/sbin/mkinitrd').and_return(True)
521        cmd = '/usr/sbin/mkinitrd'
522        utils.system.expect_call('%s %s -o initrd 2.6.24' % (cmd, args))
523        self.job.record.expect_call('GOOD', self.subdir, 'kernel.mkinitrd')
524
525        # run and check
526        self.kernel.mkinitrd(version="2.6.24", image="image",
527                             system_map="system_map", initrd="initrd")
528        self.god.check_playback()
529
530
531    def test_install(self):
532        self.construct_kernel()
533        tag = 'autotest'
534        prefix = '/'
535        self.kernel.build_image = None
536        self.kernel.build_target = 'build_target'
537        self.god.stub_function(self.kernel, "get_kernel_build_ver")
538        self.god.stub_function(self.kernel, "mkinitrd")
539
540        # record
541        os.chdir.expect_call(self.build_dir)
542        os.path.isdir.expect_call(prefix).and_return(False)
543        os.mkdir.expect_call(prefix)
544        boot_dir = os.path.join(prefix, 'boot')
545        os.path.isdir.expect_call(boot_dir).and_return(False)
546        os.mkdir.expect_call(boot_dir)
547        glob.glob.expect_call(
548            'arch/*/boot/' + 'build_target').and_return('')
549        build_image = self.kernel.build_target
550        utils.force_copy.expect_call('vmlinux',
551            '/boot/vmlinux-autotest')
552        utils.force_copy.expect_call('build_target',
553            '/boot/vmlinuz-autotest')
554        utils.force_copy.expect_call('System.map',
555            '/boot/System.map-autotest')
556        utils.force_copy.expect_call('.config',
557            '/boot/config-autotest')
558        kernel_config.modules_needed.expect_call('.config').and_return(True)
559        utils.system.expect_call('make modules_install INSTALL_MOD_PATH=%s'
560                                 % prefix)
561        initrd = boot_dir + '/initrd-' + tag
562        self.kernel.get_kernel_build_ver.expect_call().and_return('2.6.24')
563        self.kernel.mkinitrd.expect_call('2.6.24', '/boot/vmlinuz-autotest',
564            '/boot/System.map-autotest', '/boot/initrd-autotest')
565        self.job.record.expect_call('GOOD', self.subdir, 'kernel.install')
566
567        # run and check
568        self.kernel.install()
569        self.god.check_playback()
570
571
572    def test_get_kernel_build_arch1(self):
573        self.construct_kernel()
574
575        # record
576        utils.get_current_kernel_arch.expect_call().and_return("i386")
577
578        # run and check
579        self.assertEquals(self.kernel.get_kernel_build_arch(), "i386")
580        self.god.check_playback()
581
582
583    def test_get_kernel_build_arch2(self):
584        self.construct_kernel()
585
586        # run and check
587        self.assertEquals(self.kernel.get_kernel_build_arch('i586'), "i386")
588        self.god.check_playback()
589
590
591    def test_get_kernel_build_release(self):
592        self.construct_kernel()
593        mock_file = self.god.create_mock_class(file, "file")
594
595        # record
596        for f in [self.build_dir + "/include/linux/version.h",
597                  self.build_dir + "/include/linux/utsrelease.h"]:
598            os.path.exists.expect_call(f).and_return(True)
599            kernel.open.expect_call(f, 'r').and_return(mock_file)
600            mock_file.readlines.expect_call().and_return("Some lines")
601            mock_file.close.expect_call()
602
603        for f in [self.build_dir + "/include/linux/compile.h",
604                  self.build_dir + "/include/generated/utsrelease.h",
605                  self.build_dir + "/include/generated/compile.h"]:
606            os.path.exists.expect_call(f).and_return(False)
607
608        # run and test
609        self.kernel.get_kernel_build_release()
610        self.god.check_playback()
611
612
613    def test_get_kernel_build_ident(self):
614        self.construct_kernel()
615        self.god.stub_function(self.kernel, "get_kernel_build_release")
616
617        # record
618        self.kernel.get_kernel_build_release.expect_call().and_return(
619            ("AwesomeRelease", "1.0"))
620
621        # run and check
622        self.assertEquals(self.kernel.get_kernel_build_ident(),
623            "AwesomeRelease::1.0")
624        self.god.check_playback()
625
626
627    def test_boot(self):
628        self.construct_kernel()
629        self.god.stub_function(self.kernel, "get_kernel_build_ident")
630        self.god.stub_function(self.kernel, "install")
631        self.god.stub_function(self.kernel, "_boot_kernel")
632        self.kernel.applied_patches = "applied_patches"
633        self.kernel.installed_as = None
634        args = ''
635        expected_ident = 'ident'
636        ident = True
637
638        # record
639        self.kernel.install.expect_call()
640        self.kernel.get_kernel_build_ident.expect_call(
641                ).and_return(expected_ident)
642        self.kernel._boot_kernel.expect_call(
643                args, ident, expected_ident,
644                self.subdir, self.kernel.applied_patches)
645
646        # run and check
647        self.kernel.boot(args=args, ident=ident)
648        self.god.check_playback()
649
650
651if __name__ == "__main__":
652    unittest.main()
653