blob: a65978f2a947f3e2eb9b6071a0eee6e6f53a7a98 [file] [log] [blame]
jamesrendbeebf82010-04-08 22:58:26 +00001#!/usr/bin/python
2
3import unittest
4import common
5from autotest_lib.frontend import setup_django_environment
6from autotest_lib.client.common_lib.test_utils import mock
7from autotest_lib.frontend.afe import frontend_test_utils, models as afe_models
8from autotest_lib.frontend.afe import model_attributes as afe_model_attributes
9from autotest_lib.frontend.shared import rest_client
10from autotest_lib.frontend.planner import models, execution_engine, support
11from autotest_lib.frontend.planner import model_attributes
12
13
14class MockObject(object):
15 """
16 Empty mock object class, so that setattr() works on all names
17 """
18 pass
19
20
21class MockAfeRest(object):
22 jobs = MockObject()
23 execution_info = MockObject()
24 queue_entries_request = MockObject()
25
26
27class MockRestJobs(object):
28 def __init__(self, total_results):
29 self.total_results = total_results
30
31
32class MockExecutionInfo(object):
33 execution_info = {}
34
35
36class MockQueueEntriesRequest(object):
37 queue_entries = object()
38
39
40class MockExecutionEngine(execution_engine.ExecutionEngine):
41 _planner_rpc = MockObject()
42 _tko_rpc = object()
43 _plan_id = object()
44 _server = object()
45 _afe_rest = MockAfeRest()
46 _label_name = object()
jamesrene38a0a72010-04-19 18:05:31 +000047 _owner = object()
jamesrendbeebf82010-04-08 22:58:26 +000048
49
50 def __init__(self, *args, **kwargs):
51 pass
52
53
54class MockTestPlanController(support.TestPlanController):
55 def __init__(self, *args, **kwargs):
56 super(MockTestPlanController, self).__init__(machine=None,
57 test_alias=None)
58
59
60class ExecutionEngineTest(unittest.TestCase,
61 frontend_test_utils.FrontendTestMixin):
62 def setUp(self):
63 self._frontend_common_setup()
64 self.engine = MockExecutionEngine()
65
66
67 def tearDown(self):
68 self._frontend_common_teardown()
69
70
71 def _setup_test_initialize_plan(self):
72 self.god.stub_function(self.engine._planner_rpc, 'run')
73 self.god.stub_function(self.engine._afe_rest.jobs, 'get')
74 self.god.stub_function(self.engine, '_wait_for_initialization')
75
76
77 def test_initialize_plan_new_plan(self):
78 self._setup_test_initialize_plan()
79 self.god.stub_function(self.engine, '_launch_set_atomic_group_job')
80
81 self.engine._planner_rpc.run.expect_call(
82 'get_plan', id=self.engine._plan_id).and_return(
83 {'name': 'plan'})
84 self.engine._afe_rest.jobs.get.expect_call(
85 name='plan_set_atomic_group').and_return(MockRestJobs(None))
86 self.engine._launch_set_atomic_group_job.expect_call(
87 'plan_set_atomic_group')
88 self.engine._wait_for_initialization.expect_call()
89
90 self.engine._initialize_plan()
91 self.god.check_playback
92
93
94 def test_initialize_plan_existing(self):
95 self._setup_test_initialize_plan()
96
97 self.engine._planner_rpc.run.expect_call(
98 'get_plan', id=self.engine._plan_id).and_return(
99 {'name': 'plan'})
100 self.engine._afe_rest.jobs.get.expect_call(
101 name='plan_set_atomic_group').and_return(MockRestJobs(object()))
102 self.engine._wait_for_initialization.expect_call()
103
104 self.engine._initialize_plan()
105 self.god.check_playback
106
107
108 def _setup_test_launch_atomic_group_job(self, name):
jamesrendaa81282010-05-06 19:38:51 +0000109 DUMMY_CONTROL = '%(server)r %(label_name)r %(plan_id)r'
jamesrendbeebf82010-04-08 22:58:26 +0000110 DUMMY_EXECUTION_INFO = MockExecutionInfo()
111 DUMMY_QUEUE_ENTRIES_REQUEST = MockQueueEntriesRequest()
112
113 self.god.stub_function(self.engine._planner_rpc, 'run')
114 self.god.stub_function(self.engine._afe_rest.execution_info, 'get')
115 self.god.stub_function(
116 self.engine._afe_rest.queue_entries_request, 'get')
117
118 self.engine._planner_rpc.run.expect_call(
119 'get_hosts', plan_id=self.engine._plan_id).and_return(
120 self.hosts)
121 self.engine._planner_rpc.run.expect_call(
122 'get_atomic_group_control_file').and_return(DUMMY_CONTROL)
123 self.engine._afe_rest.execution_info.get.expect_call().and_return(
124 DUMMY_EXECUTION_INFO)
125 self.engine._afe_rest.queue_entries_request.get.expect_call(
126 hosts=self.hosts).and_return(DUMMY_QUEUE_ENTRIES_REQUEST)
127
jamesrendaa81282010-05-06 19:38:51 +0000128 control_file = DUMMY_CONTROL % dict(server=self.engine._server,
129 label_name=self.engine._label_name,
130 plan_id=self.engine._plan_id)
jamesrendbeebf82010-04-08 22:58:26 +0000131 DUMMY_EXECUTION_INFO.execution_info = {
jamesrendaa81282010-05-06 19:38:51 +0000132 'control_file': control_file,
jamesrendbeebf82010-04-08 22:58:26 +0000133 'cleanup_before_job': afe_model_attributes.RebootBefore.NEVER,
134 'cleanup_after_job': afe_model_attributes.RebootAfter.NEVER,
135 'run_verify': False,
136 'machines_per_execution': len(self.hosts)}
137
jamesrendbeebf82010-04-08 22:58:26 +0000138 job_req = {'name': name,
jamesrene38a0a72010-04-19 18:05:31 +0000139 'owner': self.engine._owner,
jamesrendbeebf82010-04-08 22:58:26 +0000140 'execution_info': DUMMY_EXECUTION_INFO.execution_info,
jamesrendaa81282010-05-06 19:38:51 +0000141 'queue_entries': DUMMY_QUEUE_ENTRIES_REQUEST.queue_entries}
jamesrendbeebf82010-04-08 22:58:26 +0000142
143 return job_req
144
145
146 def test_launch_atomic_group_job(self):
147 job_req = self._setup_test_launch_atomic_group_job('atomic_group_job')
148 self.god.stub_function(self.engine._afe_rest.jobs, 'post')
149
150 self.engine._afe_rest.jobs.post.expect_call(job_req)
151
152 self.engine._launch_set_atomic_group_job('atomic_group_job')
153 self.god.check_playback()
154
155
156 def _setup_mock_controller(self, controller_options):
157 mock_controller = MockTestPlanController()
158 for key, value in controller_options.iteritems():
159 setattr(mock_controller, key, value)
160 self.god.stub_with(support, 'TestPlanController',
161 lambda *args, **kwargs : mock_controller)
162 return mock_controller
163
164
165 def _test_process_finished_runs_helper(self, status, should_block=False,
166 controller_options={}):
167 Status = model_attributes.TestRunStatus
168 TEST_RUN_ID = object()
169 TKO_TEST_ID = object()
170 HOST_ID = object()
171
172 mock_controller = self._setup_mock_controller(controller_options)
173
174 self.god.stub_function(self.engine._planner_rpc, 'run')
175 self.god.stub_function(self.engine, '_run_execute_after')
176
177 test_run = {'id': TEST_RUN_ID,
178 'host': {'host': self.hosts[0].hostname,
179 'id': HOST_ID},
180 'test_job': {'test_config': {'alias': 'test_alias'}},
181 'tko_test': TKO_TEST_ID,
182 'status': status}
183
184 self.engine._planner_rpc.run.expect_call(
185 'get_test_runs',
186 plan__id=self.engine._plan_id,
187 status__in=(Status.PASSED, Status.FAILED),
188 finalized=False).and_return([test_run])
189 self.engine._run_execute_after.expect_call(
190 mock_controller, tko_test_id=TKO_TEST_ID,
191 success=(status == Status.PASSED))
192 if should_block:
193 self.engine._planner_rpc.run.expect_call('modify_host', id=HOST_ID,
194 blocked=True)
195 self.engine._planner_rpc.run.expect_call('modify_test_run',
196 id=TEST_RUN_ID, finalized=True)
197
198 self.engine._process_finished_runs()
199
200 self.god.check_playback()
201
202
203 def test_process_finished_runs_pass(self):
204 self._test_process_finished_runs_helper(
205 model_attributes.TestRunStatus.PASSED)
206
207
208 def test_process_finished_runs_fail(self):
209 self._test_process_finished_runs_helper(
210 model_attributes.TestRunStatus.FAILED, should_block=True)
211
212
213 def test_process_finished_runs_fail_unblock(self):
214 self._test_process_finished_runs_helper(
215 model_attributes.TestRunStatus.FAILED, should_block=False,
216 controller_options={'_unblock': True})
217
218
219 def _test_schedule_new_runs_helper(self, complete=False, should_skip=False,
220 controller_options={}):
221 TEST_CONFIG_ID = object()
222
223 self.god.stub_function(self.engine._planner_rpc, 'run')
224 self.god.stub_function(self.engine, '_run_execute_before')
225
226 result = {'complete': complete,
227 'next_configs': [{'next_test_config_id': TEST_CONFIG_ID,
228 'host': self.hosts[0].hostname,
229 'next_test_config_alias': object()}]}
230
231 mock_controller = self._setup_mock_controller(controller_options)
232
233 self.engine._planner_rpc.run.expect_call(
234 'get_next_test_configs',
235 plan_id=self.engine._plan_id).and_return(result)
236
237 if not complete:
238 self.engine._run_execute_before.expect_call(mock_controller)
239
240 if should_skip:
241 self.engine._planner_rpc.run.expect_call(
242 'skip_test', test_config_id=TEST_CONFIG_ID,
243 hostname=self.hosts[0].hostname)
244 else:
245 self.god.stub_function(self.engine, '_run_job')
246 self.engine._run_job.expect_call(
247 hostname=self.hosts[0].hostname,
248 test_config_id=TEST_CONFIG_ID,
249 cleanup_before_job=mock_controller._reboot_before,
250 cleanup_after_job=mock_controller._reboot_after,
251 run_verify=mock_controller._run_verify)
252
253 self.engine._schedule_new_runs()
254
255 self.god.check_playback()
256
257
258 def test_schedule_new_runs(self):
259 self._test_schedule_new_runs_helper()
260
261
262 def test_schedule_new_runs_complete(self):
263 self._test_schedule_new_runs_helper(complete=True)
264
265
266 def test_schedule_new_runs_skip(self):
267 self._test_schedule_new_runs_helper(should_skip=True,
268 controller_options={'_skip': True})
269
270
271 def test_run_global_support(self):
272 self._ran_global_support = False
273 support = """
274def test_global_support(controller):
275 controller._ran_global_support = True
276"""
277
278 DUMMY_PLAN = {'support': support}
279
280 self.god.stub_function(self.engine._planner_rpc, 'run')
281
282 self.engine._planner_rpc.run.expect_call(
283 'get_plan', id=self.engine._plan_id).and_return(DUMMY_PLAN)
284
285 self.engine._run_global_support(controller=self,
286 function_name='test_global_support')
287
288 self.assertTrue(self._ran_global_support)
289 self.god.check_playback()
290
291
292if __name__ == '__main__':
293 unittest.main()