blob: 948564af6feeaf76180973ff9daab9233545407f [file] [log] [blame]
showarde39ebe92009-06-18 23:14:48 +00001#!/usr/bin/python
2
showard42d44982009-10-12 20:34:03 +00003import os, unittest
showarde39ebe92009-06-18 23:14:48 +00004import common
showardac5b0002009-10-19 18:34:00 +00005from autotest_lib.client.common_lib import global_config
showard42d44982009-10-12 20:34:03 +00006from autotest_lib.client.common_lib.test_utils import mock
showard2aafd902009-10-14 16:20:14 +00007from autotest_lib.scheduler import drone_manager, drone_utility, drones
showardac5b0002009-10-19 18:34:00 +00008from autotest_lib.scheduler import scheduler_config
showarde39ebe92009-06-18 23:14:48 +00009
10class MockDrone(drones._AbstractDrone):
showard202343e2009-10-14 16:20:24 +000011 def __init__(self, name, active_processes=0, max_processes=10):
showarde39ebe92009-06-18 23:14:48 +000012 super(MockDrone, self).__init__()
13 self.name = name
14 self.active_processes = active_processes
15 self.max_processes = max_processes
showard42d44982009-10-12 20:34:03 +000016 # maps method names list of tuples containing method arguments
17 self._recorded_calls = {'queue_call': [],
18 'send_file_to': []}
19
20
21 def queue_call(self, method, *args, **kwargs):
22 self._recorded_calls['queue_call'].append((method, args, kwargs))
23
24
showard2aafd902009-10-14 16:20:14 +000025 def call(self, method, *args, **kwargs):
26 # don't bother differentiating between call() and queue_call()
27 return self.queue_call(method, *args, **kwargs)
28
29
showard42d44982009-10-12 20:34:03 +000030 def send_file_to(self, drone, source_path, destination_path,
31 can_fail=False):
32 self._recorded_calls['send_file_to'].append(
33 (drone, source_path, destination_path))
34
35
36 # method for use by tests
37 def _check_for_recorded_call(self, method_name, arguments):
38 recorded_arg_list = self._recorded_calls[method_name]
39 was_called = arguments in recorded_arg_list
40 if not was_called:
41 print 'Recorded args:', recorded_arg_list
42 print 'Expected:', arguments
43 return was_called
44
45
46 def was_call_queued(self, method, *args, **kwargs):
47 return self._check_for_recorded_call('queue_call',
48 (method, args, kwargs))
49
50
51 def was_file_sent(self, drone, source_path, destination_path):
52 return self._check_for_recorded_call('send_file_to',
53 (drone, source_path,
54 destination_path))
showarde39ebe92009-06-18 23:14:48 +000055
56
57class DroneManager(unittest.TestCase):
showard42d44982009-10-12 20:34:03 +000058 _DRONE_INSTALL_DIR = '/drone/install/dir'
showardc75fded2009-10-14 16:20:02 +000059 _DRONE_RESULTS_DIR = os.path.join(_DRONE_INSTALL_DIR, 'results')
showard42d44982009-10-12 20:34:03 +000060 _RESULTS_DIR = '/results/dir'
61 _SOURCE_PATH = 'source/path'
62 _DESTINATION_PATH = 'destination/path'
showard2aafd902009-10-14 16:20:14 +000063 _WORKING_DIRECTORY = 'working/directory'
showard42d44982009-10-12 20:34:03 +000064
showarde39ebe92009-06-18 23:14:48 +000065 def setUp(self):
showard42d44982009-10-12 20:34:03 +000066 self.god = mock.mock_god()
67 self.god.stub_with(drones, 'AUTOTEST_INSTALL_DIR',
68 self._DRONE_INSTALL_DIR)
showarde39ebe92009-06-18 23:14:48 +000069 self.manager = drone_manager.DroneManager()
showard42d44982009-10-12 20:34:03 +000070 self.god.stub_with(self.manager, '_results_dir', self._RESULTS_DIR)
71
showard2aafd902009-10-14 16:20:14 +000072 # we don't want this to ever actually get called
73 self.god.stub_function(drones, 'get_drone')
showardac5b0002009-10-19 18:34:00 +000074 # we don't want the DroneManager to go messing with global config
75 def do_nothing():
76 pass
77 self.god.stub_with(self.manager, 'refresh_drone_configs', do_nothing)
showard2aafd902009-10-14 16:20:14 +000078
showard42d44982009-10-12 20:34:03 +000079 # set up some dummy drones
showard202343e2009-10-14 16:20:24 +000080 self.mock_drone = MockDrone('mock_drone')
showard42d44982009-10-12 20:34:03 +000081 self.manager._drones[self.mock_drone.name] = self.mock_drone
82 self.results_drone = MockDrone('results_drone', 0, 10)
83 self.manager._results_drone = self.results_drone
84
85 self.mock_drone_process = drone_manager.Process(self.mock_drone.name, 0)
86
87
88 def tearDown(self):
89 self.god.unstub_all()
showarde39ebe92009-06-18 23:14:48 +000090
91
92 def _test_choose_drone_for_execution_helper(self, processes_info_list,
93 requested_processes):
94 for index, process_info in enumerate(processes_info_list):
95 active_processes, max_processes = process_info
96 self.manager._enqueue_drone(MockDrone(index, active_processes,
97 max_processes))
98
99 return self.manager._choose_drone_for_execution(requested_processes)
100
101
102 def test_choose_drone_for_execution(self):
103 drone = self._test_choose_drone_for_execution_helper([(1, 2), (0, 2)],
104 1)
105 self.assertEquals(drone.name, 1)
106
107
108 def test_choose_drone_for_execution_some_full(self):
109 drone = self._test_choose_drone_for_execution_helper([(0, 1), (1, 3)],
110 2)
111 self.assertEquals(drone.name, 1)
112
113
114 def test_choose_drone_for_execution_all_full(self):
115 drone = self._test_choose_drone_for_execution_helper([(2, 1), (3, 2)],
116 1)
117 self.assertEquals(drone.name, 1)
118
119
showard2aafd902009-10-14 16:20:14 +0000120 def test_initialize(self):
showard2aafd902009-10-14 16:20:14 +0000121 results_hostname = 'results_repo'
showardac5b0002009-10-19 18:34:00 +0000122 results_install_dir = '/results/install'
123 global_config.global_config.override_config_value(
124 scheduler_config.CONFIG_SECTION,
125 'results_host_installation_directory', results_install_dir)
showard2aafd902009-10-14 16:20:14 +0000126
showard2aafd902009-10-14 16:20:14 +0000127 (drones.get_drone.expect_call(self.mock_drone.name)
128 .and_return(self.mock_drone))
showard202343e2009-10-14 16:20:24 +0000129
130 results_drone = MockDrone('results_drone')
131 self.god.stub_function(results_drone, 'set_autotest_install_dir')
132 drones.get_drone.expect_call(results_hostname).and_return(results_drone)
showardac5b0002009-10-19 18:34:00 +0000133 results_drone.set_autotest_install_dir.expect_call(results_install_dir)
showard2aafd902009-10-14 16:20:14 +0000134
135 self.manager.initialize(base_results_dir=self._RESULTS_DIR,
136 drone_hostnames=[self.mock_drone.name],
137 results_repository_hostname=results_hostname)
138
139 self.assert_(self.mock_drone.was_call_queued(
140 'initialize', self._DRONE_RESULTS_DIR + '/'))
showardac5b0002009-10-19 18:34:00 +0000141 self.god.check_playback()
showard2aafd902009-10-14 16:20:14 +0000142
143
showard42d44982009-10-12 20:34:03 +0000144 def test_execute_command(self):
145 self.manager._enqueue_drone(self.mock_drone)
146
showard42d44982009-10-12 20:34:03 +0000147 pidfile_name = 'my_pidfile'
148 log_file = 'log_file'
149
150 pidfile_id = self.manager.execute_command(
151 command=['test', drone_manager.WORKING_DIRECTORY],
showard2aafd902009-10-14 16:20:14 +0000152 working_directory=self._WORKING_DIRECTORY,
showard42d44982009-10-12 20:34:03 +0000153 pidfile_name=pidfile_name,
154 log_file=log_file)
155
showardc75fded2009-10-14 16:20:02 +0000156 full_working_directory = os.path.join(self._DRONE_RESULTS_DIR,
showard2aafd902009-10-14 16:20:14 +0000157 self._WORKING_DIRECTORY)
showard42d44982009-10-12 20:34:03 +0000158 self.assertEquals(pidfile_id.path,
159 os.path.join(full_working_directory, pidfile_name))
160 self.assert_(self.mock_drone.was_call_queued(
161 'execute_command', ['test', full_working_directory],
162 full_working_directory,
showardc75fded2009-10-14 16:20:02 +0000163 os.path.join(self._DRONE_RESULTS_DIR, log_file), pidfile_name))
showard42d44982009-10-12 20:34:03 +0000164
165
showard2aafd902009-10-14 16:20:14 +0000166 def test_attach_file_to_execution(self):
167 self.manager._enqueue_drone(self.mock_drone)
168
169 contents = 'my\ncontents'
170 attached_path = self.manager.attach_file_to_execution(
171 self._WORKING_DIRECTORY, contents)
172 self.manager.execute_command(command=['test'],
173 working_directory=self._WORKING_DIRECTORY,
174 pidfile_name='mypidfile')
175
176 self.assert_(self.mock_drone.was_call_queued(
177 'write_to_file',
178 os.path.join(self._DRONE_RESULTS_DIR, attached_path),
179 contents))
180
181
showard42d44982009-10-12 20:34:03 +0000182 def test_copy_results_on_drone(self):
183 self.manager.copy_results_on_drone(self.mock_drone_process,
184 self._SOURCE_PATH,
185 self._DESTINATION_PATH)
186 self.assert_(self.mock_drone.was_call_queued(
187 'copy_file_or_directory',
showardc75fded2009-10-14 16:20:02 +0000188 os.path.join(self._DRONE_RESULTS_DIR, self._SOURCE_PATH),
189 os.path.join(self._DRONE_RESULTS_DIR, self._DESTINATION_PATH)))
showard42d44982009-10-12 20:34:03 +0000190
191
192 def test_copy_to_results_repository(self):
193 self.manager.copy_to_results_repository(self.mock_drone_process,
194 self._SOURCE_PATH)
195 self.assert_(self.mock_drone.was_file_sent(
196 self.results_drone,
showardc75fded2009-10-14 16:20:02 +0000197 os.path.join(self._DRONE_RESULTS_DIR, self._SOURCE_PATH),
showard42d44982009-10-12 20:34:03 +0000198 os.path.join(self._RESULTS_DIR, self._SOURCE_PATH)))
199
200
201 def test_write_lines_to_file(self):
202 file_path = 'file/path'
203 lines = ['line1', 'line2']
204 written_data = 'line1\nline2\n'
205
206 # write to results repository
207 self.manager.write_lines_to_file(file_path, lines)
208 self.assert_(self.results_drone.was_call_queued(
209 'write_to_file', os.path.join(self._RESULTS_DIR, file_path),
210 written_data))
211
212 # write to a drone
213 self.manager.write_lines_to_file(
214 file_path, lines, paired_with_process=self.mock_drone_process)
215 self.assert_(self.mock_drone.was_call_queued(
216 'write_to_file',
showardc75fded2009-10-14 16:20:02 +0000217 os.path.join(self._DRONE_RESULTS_DIR, file_path), written_data))
showard42d44982009-10-12 20:34:03 +0000218
219
showarde39ebe92009-06-18 23:14:48 +0000220if __name__ == '__main__':
221 unittest.main()