1#!/usr/bin/python
2#pylint: disable-msg=C0111
3__author__ = "raphtee@google.com (Travis Miller)"
4
5import unittest, os, tempfile, logging
6
7import common
8from autotest_lib.server import autotest, utils, hosts, server_job, profilers
9from autotest_lib.client.bin import sysinfo
10from autotest_lib.client.common_lib import packages
11from autotest_lib.client.common_lib import error
12from autotest_lib.client.common_lib.test_utils import mock
13
14
15class TestBaseAutotest(unittest.TestCase):
16    def setUp(self):
17        # create god
18        self.god = mock.mock_god()
19
20        # create mock host object
21        self.host = self.god.create_mock_class(hosts.RemoteHost, "host")
22        self.host.hostname = "hostname"
23        self.host.job = self.god.create_mock_class(server_job.server_job,
24                                                   "job")
25        self.host.job.run_test_cleanup = True
26        self.host.job.last_boot_tag = 'Autotest'
27        self.host.job.sysinfo = self.god.create_mock_class(
28            sysinfo.sysinfo, "sysinfo")
29        self.host.job.profilers = self.god.create_mock_class(
30            profilers.profilers, "profilers")
31        self.host.job.profilers.add_log = {}
32        self.host.job.tmpdir = "/job/tmp"
33        self.host.job.default_profile_only = False
34        self.host.job.args = []
35        self.host.job.record = lambda *args: None
36
37        # stubs
38        self.god.stub_function(utils, "get_server_dir")
39        self.god.stub_function(utils, "run")
40        self.god.stub_function(utils, "get")
41        self.god.stub_function(utils, "read_keyval")
42        self.god.stub_function(utils, "write_keyval")
43        self.god.stub_function(utils, "system")
44        self.god.stub_function(tempfile, "mkstemp")
45        self.god.stub_function(tempfile, "mktemp")
46        self.god.stub_function(os, "getcwd")
47        self.god.stub_function(os, "system")
48        self.god.stub_function(os, "chdir")
49        self.god.stub_function(os, "makedirs")
50        self.god.stub_function(os, "remove")
51        self.god.stub_function(os, "fdopen")
52        self.god.stub_function(os.path, "exists")
53        self.god.stub_function(autotest, "open")
54        self.god.stub_function(autotest.global_config.global_config,
55                               "get_config_value")
56        self.god.stub_function(logging, "exception")
57        self.god.stub_class(autotest, "_Run")
58        self.god.stub_class(autotest, "log_collector")
59
60
61    def tearDown(self):
62        self.god.unstub_all()
63
64
65    def construct(self):
66        # setup
67        self.serverdir = "serverdir"
68
69        # record
70        utils.get_server_dir.expect_call().and_return(self.serverdir)
71
72        # create the autotest object
73        self.base_autotest = autotest.BaseAutotest(self.host)
74        self.base_autotest.job = self.host.job
75        self.god.stub_function(self.base_autotest, "_install_using_send_file")
76
77        # stub out abspath
78        self.god.stub_function(os.path, "abspath")
79
80        # check
81        self.god.check_playback()
82
83
84    def record_install_prologue(self):
85        self.construct()
86
87        # setup
88        self.god.stub_class(packages, "PackageManager")
89        self.base_autotest.got = False
90        location = os.path.join(self.serverdir, '../client')
91        location = os.path.abspath.expect_call(location).and_return(location)
92
93        # record
94        os.getcwd.expect_call().and_return('cwd')
95        os.chdir.expect_call(os.path.join(self.serverdir, '../client'))
96        utils.system.expect_call('tools/make_clean', ignore_status=True)
97        os.chdir.expect_call('cwd')
98        utils.get.expect_call(os.path.join(self.serverdir,
99            '../client')).and_return('source_material')
100
101        self.host.wait_up.expect_call(timeout=30)
102        self.host.setup.expect_call()
103        self.host.get_autodir.expect_call().and_return("autodir")
104        self.host.set_autodir.expect_call("autodir")
105        self.host.run.expect_call('mkdir -p autodir')
106        self.host.run.expect_call('rm -rf autodir/results/*',
107                                  ignore_status=True)
108
109
110    def test_constructor(self):
111        self.construct()
112
113        # we should check the calls
114        self.god.check_playback()
115
116
117    def test_full_client_install(self):
118        self.record_install_prologue()
119
120        self.host.run.expect_call('rm -f "autodir/packages.checksum"')
121        c = autotest.global_config.global_config
122        c.get_config_value.expect_call('PACKAGES',
123                                       'serve_packages_from_autoserv',
124                                       type=bool).and_return(False)
125        self.host.send_file.expect_call('source_material', 'autodir',
126                                        delete_dest=True)
127
128        # run and check
129        self.base_autotest.install_full_client()
130        self.god.check_playback()
131
132
133    def test_autoserv_install(self):
134        self.record_install_prologue()
135
136        c = autotest.global_config.global_config
137        c.get_config_value.expect_call('PACKAGES',
138            'fetch_location', type=list, default=[]).and_return([])
139
140        c.get_config_value.expect_call('PACKAGES',
141                                       'serve_packages_from_autoserv',
142                                       type=bool).and_return(True)
143        self.base_autotest._install_using_send_file.expect_call(self.host,
144                                                                'autodir')
145        # run and check
146        self.base_autotest.install()
147        self.god.check_playback()
148
149
150    def test_packaging_install(self):
151        self.record_install_prologue()
152
153        c = autotest.global_config.global_config
154        c.get_config_value.expect_call('PACKAGES',
155            'fetch_location', type=list, default=[]).and_return(['repo'])
156        pkgmgr = packages.PackageManager.expect_new('autodir',
157            repo_urls=['repo'], hostname='hostname', do_locking=False,
158            run_function=self.host.run, run_function_dargs=dict(timeout=600))
159        pkg_dir = os.path.join('autodir', 'packages')
160        cmd = ('cd autodir && ls | grep -v "^packages$"'
161               ' | xargs rm -rf && rm -rf .[!.]*')
162        self.host.run.expect_call(cmd)
163        pkgmgr.install_pkg.expect_call('autotest', 'client', pkg_dir,
164                                       'autodir', preserve_install_dir=True)
165
166        # run and check
167        self.base_autotest.install()
168        self.god.check_playback()
169
170
171    def test_run(self):
172        self.construct()
173
174        # setup
175        control = "control"
176
177        # stub out install
178        self.god.stub_function(self.base_autotest, "install")
179
180        # record
181        self.base_autotest.install.expect_call(self.host, use_packaging=True)
182        self.host.wait_up.expect_call(timeout=30)
183        os.path.abspath.expect_call('.').and_return('.')
184        run_obj = autotest._Run.expect_new(self.host, '.', None, False, False)
185        tag = None
186        run_obj.manual_control_file = os.path.join('autodir',
187                                                   'control.%s' % tag)
188        run_obj.remote_control_file = os.path.join('autodir',
189                                                   'control.%s.autoserv' % tag)
190        run_obj.tag = tag
191        run_obj.autodir = 'autodir'
192        run_obj.verify_machine.expect_call()
193        run_obj.background = False
194        debug = os.path.join('.', 'debug')
195        os.makedirs.expect_call(debug)
196        delete_file_list = [run_obj.remote_control_file,
197                            run_obj.remote_control_file + '.state',
198                            run_obj.manual_control_file,
199                            run_obj.manual_control_file + '.state']
200        cmd = ';'.join('rm -f ' + control for control in delete_file_list)
201        self.host.run.expect_call(cmd, ignore_status=True)
202
203        utils.get.expect_call(control, local_copy=True).and_return("temp")
204
205        c = autotest.global_config.global_config
206        c.get_config_value.expect_call("PACKAGES",
207            'fetch_location', type=list, default=[]).and_return(['repo'])
208
209        cfile = self.god.create_mock_class(file, "file")
210        cfile_orig = "original control file"
211        cfile_new = "args = []\njob.add_repository(['repo'])\n"
212        cfile_new += cfile_orig
213
214        autotest.open.expect_call("temp").and_return(cfile)
215        cfile.read.expect_call().and_return(cfile_orig)
216        autotest.open.expect_call("temp", 'w').and_return(cfile)
217        cfile.write.expect_call(cfile_new)
218
219        self.host.job.preprocess_client_state.expect_call().and_return(
220            '/job/tmp/file1')
221        self.host.send_file.expect_call(
222            "/job/tmp/file1", "autodir/control.None.autoserv.init.state")
223        os.remove.expect_call("/job/tmp/file1")
224
225        self.host.send_file.expect_call("temp", run_obj.remote_control_file)
226        os.path.abspath.expect_call('temp').and_return('control_file')
227        os.path.abspath.expect_call('control').and_return('control')
228        os.remove.expect_call("temp")
229
230        run_obj.execute_control.expect_call(timeout=30,
231                                            client_disconnect_timeout=240)
232
233        # run and check output
234        self.base_autotest.run(control, timeout=30)
235        self.god.check_playback()
236
237
238    def _stub_get_client_autodir_paths(self):
239        def mock_get_client_autodir_paths(cls, host):
240            return ['/some/path', '/another/path']
241        self.god.stub_with(autotest.Autotest, 'get_client_autodir_paths',
242                           classmethod(mock_get_client_autodir_paths))
243
244
245    def _expect_failed_run(self, command):
246        (self.host.run.expect_call(command)
247         .and_raises(error.AutoservRunError('dummy', object())))
248
249
250    def test_get_installed_autodir(self):
251        self._stub_get_client_autodir_paths()
252        self.host.get_autodir.expect_call().and_return(None)
253        self._expect_failed_run('test -x /some/path/bin/autotest')
254        self.host.run.expect_call('test -x /another/path/bin/autotest')
255        self.host.run.expect_call('test -w /another/path')
256
257        autodir = autotest.Autotest.get_installed_autodir(self.host)
258        self.assertEquals(autodir, '/another/path')
259
260
261    def test_get_install_dir(self):
262        self._stub_get_client_autodir_paths()
263        self.host.get_autodir.expect_call().and_return(None)
264        self._expect_failed_run('test -x /some/path/bin/autotest')
265        self._expect_failed_run('test -x /another/path/bin/autotest')
266        self._expect_failed_run('mkdir -p /some/path')
267        self.host.run.expect_call('mkdir -p /another/path')
268        self.host.run.expect_call('test -w /another/path')
269
270        install_dir = autotest.Autotest.get_install_dir(self.host)
271        self.assertEquals(install_dir, '/another/path')
272
273
274    def test_client_logger_process_line_log_copy_collection_failure(self):
275        collector = autotest.log_collector.expect_new(self.host, '', '')
276        logger = autotest.client_logger(self.host, '', '')
277        collector.collect_client_job_results.expect_call().and_raises(
278                Exception('log copy failure'))
279        logging.exception.expect_call(mock.is_string_comparator())
280        logger._process_line('AUTOTEST_TEST_COMPLETE:/autotest/fifo1')
281
282
283    def test_client_logger_process_line_log_copy_fifo_failure(self):
284        collector = autotest.log_collector.expect_new(self.host, '', '')
285        logger = autotest.client_logger(self.host, '', '')
286        collector.collect_client_job_results.expect_call()
287        self.host.run.expect_call('echo A > /autotest/fifo2').and_raises(
288                Exception('fifo failure'))
289        logging.exception.expect_call(mock.is_string_comparator())
290        logger._process_line('AUTOTEST_TEST_COMPLETE:/autotest/fifo2')
291
292
293    def test_client_logger_process_line_package_install_fifo_failure(self):
294        collector = autotest.log_collector.expect_new(self.host, '', '')
295        logger = autotest.client_logger(self.host, '', '')
296        self.god.stub_function(logger, '_send_tarball')
297
298        c = autotest.global_config.global_config
299        c.get_config_value.expect_call('PACKAGES',
300                                       'serve_packages_from_autoserv',
301                                       type=bool).and_return(True)
302        c.get_config_value.expect_call('PACKAGES',
303                                       'serve_packages_from_autoserv',
304                                       type=bool).and_return(True)
305        logger._send_tarball.expect_call('pkgname.tar.bz2', '/autotest/dest/')
306
307        self.host.run.expect_call('echo B > /autotest/fifo3').and_raises(
308                Exception('fifo failure'))
309        logging.exception.expect_call(mock.is_string_comparator())
310        logger._process_line('AUTOTEST_FETCH_PACKAGE:pkgname.tar.bz2:'
311                             '/autotest/dest/:/autotest/fifo3')
312
313
314if __name__ == "__main__":
315    unittest.main()
316