blob: d388a823abeb5ef66a7a0334929e84752bf90ce9 [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
showard42d44982009-10-12 20:34:03 +00005from autotest_lib.client.common_lib.test_utils import mock
showard2aafd902009-10-14 16:20:14 +00006from autotest_lib.scheduler import drone_manager, drone_utility, drones
showarde39ebe92009-06-18 23:14:48 +00007
8class MockDrone(drones._AbstractDrone):
9 def __init__(self, name, active_processes, max_processes):
10 super(MockDrone, self).__init__()
11 self.name = name
12 self.active_processes = active_processes
13 self.max_processes = max_processes
showard42d44982009-10-12 20:34:03 +000014 # maps method names list of tuples containing method arguments
15 self._recorded_calls = {'queue_call': [],
16 'send_file_to': []}
17
18
19 def queue_call(self, method, *args, **kwargs):
20 self._recorded_calls['queue_call'].append((method, args, kwargs))
21
22
showard2aafd902009-10-14 16:20:14 +000023 def call(self, method, *args, **kwargs):
24 # don't bother differentiating between call() and queue_call()
25 return self.queue_call(method, *args, **kwargs)
26
27
showard42d44982009-10-12 20:34:03 +000028 def send_file_to(self, drone, source_path, destination_path,
29 can_fail=False):
30 self._recorded_calls['send_file_to'].append(
31 (drone, source_path, destination_path))
32
33
34 # method for use by tests
35 def _check_for_recorded_call(self, method_name, arguments):
36 recorded_arg_list = self._recorded_calls[method_name]
37 was_called = arguments in recorded_arg_list
38 if not was_called:
39 print 'Recorded args:', recorded_arg_list
40 print 'Expected:', arguments
41 return was_called
42
43
44 def was_call_queued(self, method, *args, **kwargs):
45 return self._check_for_recorded_call('queue_call',
46 (method, args, kwargs))
47
48
49 def was_file_sent(self, drone, source_path, destination_path):
50 return self._check_for_recorded_call('send_file_to',
51 (drone, source_path,
52 destination_path))
showarde39ebe92009-06-18 23:14:48 +000053
54
55class DroneManager(unittest.TestCase):
showard42d44982009-10-12 20:34:03 +000056 _DRONE_INSTALL_DIR = '/drone/install/dir'
showardc75fded2009-10-14 16:20:02 +000057 _DRONE_RESULTS_DIR = os.path.join(_DRONE_INSTALL_DIR, 'results')
showard42d44982009-10-12 20:34:03 +000058 _RESULTS_DIR = '/results/dir'
59 _SOURCE_PATH = 'source/path'
60 _DESTINATION_PATH = 'destination/path'
showard2aafd902009-10-14 16:20:14 +000061 _WORKING_DIRECTORY = 'working/directory'
showard42d44982009-10-12 20:34:03 +000062
showarde39ebe92009-06-18 23:14:48 +000063 def setUp(self):
showard42d44982009-10-12 20:34:03 +000064 self.god = mock.mock_god()
65 self.god.stub_with(drones, 'AUTOTEST_INSTALL_DIR',
66 self._DRONE_INSTALL_DIR)
showarde39ebe92009-06-18 23:14:48 +000067 self.manager = drone_manager.DroneManager()
showard42d44982009-10-12 20:34:03 +000068 self.god.stub_with(self.manager, '_results_dir', self._RESULTS_DIR)
69
showard2aafd902009-10-14 16:20:14 +000070 # we don't want this to ever actually get called
71 self.god.stub_function(drones, 'get_drone')
72
showard42d44982009-10-12 20:34:03 +000073 # set up some dummy drones
74 self.mock_drone = MockDrone('mock_drone', 0, 10)
75 self.manager._drones[self.mock_drone.name] = self.mock_drone
76 self.results_drone = MockDrone('results_drone', 0, 10)
77 self.manager._results_drone = self.results_drone
78
79 self.mock_drone_process = drone_manager.Process(self.mock_drone.name, 0)
80
81
82 def tearDown(self):
83 self.god.unstub_all()
showarde39ebe92009-06-18 23:14:48 +000084
85
86 def _test_choose_drone_for_execution_helper(self, processes_info_list,
87 requested_processes):
88 for index, process_info in enumerate(processes_info_list):
89 active_processes, max_processes = process_info
90 self.manager._enqueue_drone(MockDrone(index, active_processes,
91 max_processes))
92
93 return self.manager._choose_drone_for_execution(requested_processes)
94
95
96 def test_choose_drone_for_execution(self):
97 drone = self._test_choose_drone_for_execution_helper([(1, 2), (0, 2)],
98 1)
99 self.assertEquals(drone.name, 1)
100
101
102 def test_choose_drone_for_execution_some_full(self):
103 drone = self._test_choose_drone_for_execution_helper([(0, 1), (1, 3)],
104 2)
105 self.assertEquals(drone.name, 1)
106
107
108 def test_choose_drone_for_execution_all_full(self):
109 drone = self._test_choose_drone_for_execution_helper([(2, 1), (3, 2)],
110 1)
111 self.assertEquals(drone.name, 1)
112
113
showard2aafd902009-10-14 16:20:14 +0000114 def test_initialize(self):
115 self.god.stub_function(drones, 'set_temporary_directory')
116 results_hostname = 'results_repo'
117
118 drones.set_temporary_directory.expect_call(
119 os.path.join(self._DRONE_RESULTS_DIR,
120 drone_utility._TEMPORARY_DIRECTORY))
121 (drones.get_drone.expect_call(self.mock_drone.name)
122 .and_return(self.mock_drone))
123 drones.get_drone.expect_call(results_hostname).and_return(object())
124
125 self.manager.initialize(base_results_dir=self._RESULTS_DIR,
126 drone_hostnames=[self.mock_drone.name],
127 results_repository_hostname=results_hostname)
128
129 self.assert_(self.mock_drone.was_call_queued(
130 'initialize', self._DRONE_RESULTS_DIR + '/'))
131
132
showard42d44982009-10-12 20:34:03 +0000133 def test_execute_command(self):
134 self.manager._enqueue_drone(self.mock_drone)
135
showard42d44982009-10-12 20:34:03 +0000136 pidfile_name = 'my_pidfile'
137 log_file = 'log_file'
138
139 pidfile_id = self.manager.execute_command(
140 command=['test', drone_manager.WORKING_DIRECTORY],
showard2aafd902009-10-14 16:20:14 +0000141 working_directory=self._WORKING_DIRECTORY,
showard42d44982009-10-12 20:34:03 +0000142 pidfile_name=pidfile_name,
143 log_file=log_file)
144
showardc75fded2009-10-14 16:20:02 +0000145 full_working_directory = os.path.join(self._DRONE_RESULTS_DIR,
showard2aafd902009-10-14 16:20:14 +0000146 self._WORKING_DIRECTORY)
showard42d44982009-10-12 20:34:03 +0000147 self.assertEquals(pidfile_id.path,
148 os.path.join(full_working_directory, pidfile_name))
149 self.assert_(self.mock_drone.was_call_queued(
150 'execute_command', ['test', full_working_directory],
151 full_working_directory,
showardc75fded2009-10-14 16:20:02 +0000152 os.path.join(self._DRONE_RESULTS_DIR, log_file), pidfile_name))
showard42d44982009-10-12 20:34:03 +0000153
154
showard2aafd902009-10-14 16:20:14 +0000155 def test_attach_file_to_execution(self):
156 self.manager._enqueue_drone(self.mock_drone)
157
158 contents = 'my\ncontents'
159 attached_path = self.manager.attach_file_to_execution(
160 self._WORKING_DIRECTORY, contents)
161 self.manager.execute_command(command=['test'],
162 working_directory=self._WORKING_DIRECTORY,
163 pidfile_name='mypidfile')
164
165 self.assert_(self.mock_drone.was_call_queued(
166 'write_to_file',
167 os.path.join(self._DRONE_RESULTS_DIR, attached_path),
168 contents))
169
170
showard42d44982009-10-12 20:34:03 +0000171 def test_copy_results_on_drone(self):
172 self.manager.copy_results_on_drone(self.mock_drone_process,
173 self._SOURCE_PATH,
174 self._DESTINATION_PATH)
175 self.assert_(self.mock_drone.was_call_queued(
176 'copy_file_or_directory',
showardc75fded2009-10-14 16:20:02 +0000177 os.path.join(self._DRONE_RESULTS_DIR, self._SOURCE_PATH),
178 os.path.join(self._DRONE_RESULTS_DIR, self._DESTINATION_PATH)))
showard42d44982009-10-12 20:34:03 +0000179
180
181 def test_copy_to_results_repository(self):
182 self.manager.copy_to_results_repository(self.mock_drone_process,
183 self._SOURCE_PATH)
184 self.assert_(self.mock_drone.was_file_sent(
185 self.results_drone,
showardc75fded2009-10-14 16:20:02 +0000186 os.path.join(self._DRONE_RESULTS_DIR, self._SOURCE_PATH),
showard42d44982009-10-12 20:34:03 +0000187 os.path.join(self._RESULTS_DIR, self._SOURCE_PATH)))
188
189
190 def test_write_lines_to_file(self):
191 file_path = 'file/path'
192 lines = ['line1', 'line2']
193 written_data = 'line1\nline2\n'
194
195 # write to results repository
196 self.manager.write_lines_to_file(file_path, lines)
197 self.assert_(self.results_drone.was_call_queued(
198 'write_to_file', os.path.join(self._RESULTS_DIR, file_path),
199 written_data))
200
201 # write to a drone
202 self.manager.write_lines_to_file(
203 file_path, lines, paired_with_process=self.mock_drone_process)
204 self.assert_(self.mock_drone.was_call_queued(
205 'write_to_file',
showardc75fded2009-10-14 16:20:02 +0000206 os.path.join(self._DRONE_RESULTS_DIR, file_path), written_data))
showard42d44982009-10-12 20:34:03 +0000207
208
showarde39ebe92009-06-18 23:14:48 +0000209if __name__ == '__main__':
210 unittest.main()