... |
... |
@@ -36,6 +36,12 @@ from buildgrid.server.worker import bots_interface, bots_service |
36
|
36
|
def context():
|
37
|
37
|
yield mock.MagicMock(spec = _Context)
|
38
|
38
|
|
|
39
|
+@pytest.fixture
|
|
40
|
+def action_job():
|
|
41
|
+ action_digest = remote_execution_pb2.Digest()
|
|
42
|
+ j = job.Job(action_digest, None)
|
|
43
|
+ yield j
|
|
44
|
+
|
39
|
45
|
@pytest.fixture
|
40
|
46
|
def bot_session():
|
41
|
47
|
bot = bots_pb2.BotSession()
|
... |
... |
@@ -101,7 +107,6 @@ def test_update_bot_session_zombie(bot_session, context, instance): |
101
|
107
|
|
102
|
108
|
response = instance.UpdateBotSession(request, context)
|
103
|
109
|
|
104
|
|
- assert isinstance(response, bots_pb2.BotSession)
|
105
|
110
|
context.set_code.assert_called_once_with(grpc.StatusCode.INVALID_ARGUMENT)
|
106
|
111
|
|
107
|
112
|
def test_update_bot_session_bot_id_fail(bot_session, context, instance):
|
... |
... |
@@ -113,35 +118,33 @@ def test_update_bot_session_bot_id_fail(bot_session, context, instance): |
113
|
118
|
|
114
|
119
|
context.set_code.assert_called_once_with(grpc.StatusCode.INVALID_ARGUMENT)
|
115
|
120
|
|
116
|
|
-@pytest.mark.parametrize("number_of_leases", [1, 3, 500])
|
117
|
|
-def test_update_leases(number_of_leases, bot_session, context, instance):
|
118
|
|
- leases = [bots_pb2.Lease() for x in range(number_of_leases)]
|
119
|
|
- bot_session.leases.extend(leases)
|
|
121
|
+@pytest.mark.parametrize("number_of_jobs", [0, 1, 3, 500])
|
|
122
|
+def test_number_of_leases(number_of_jobs, bot_session, context, instance):
|
120
|
123
|
request = bots_pb2.CreateBotSessionRequest(parent='',
|
121
|
124
|
bot_session=bot_session)
|
|
125
|
+ # Inject work
|
|
126
|
+ for n in range(0, number_of_jobs):
|
|
127
|
+ action_digest = remote_execution_pb2.Digest()
|
|
128
|
+ instance._instance._scheduler.append_job(job.Job(action_digest))
|
122
|
129
|
# Simulated the severed binding between client and server
|
123
|
130
|
bot = copy.deepcopy(instance.CreateBotSession(request, context))
|
124
|
131
|
|
|
132
|
+ # Creation of bot session should not create leases
|
|
133
|
+ assert len(bot.leases) == 0
|
|
134
|
+
|
125
|
135
|
request = bots_pb2.UpdateBotSessionRequest(name=bot.name,
|
126
|
136
|
bot_session=bot)
|
127
|
137
|
|
128
|
138
|
response = instance.UpdateBotSession(request, context)
|
129
|
139
|
|
130
|
|
- assert isinstance(response, bots_pb2.BotSession)
|
131
|
|
- assert len(response.leases) == len(bot.leases)
|
132
|
|
- assert bot == response
|
|
140
|
+ assert len(response.leases) == number_of_jobs
|
133
|
141
|
|
134
|
142
|
def test_update_leases_with_work(bot_session, context, instance):
|
135
|
|
- leases = [bots_pb2.Lease() for x in range(2)]
|
136
|
|
- bot_session.leases.extend(leases)
|
137
|
|
-
|
138
|
|
- # Inject some work to be done
|
139
|
|
- action = remote_execution_pb2.Action()
|
140
|
|
- action.command_digest.hash = 'rick'
|
141
|
|
- instance._instance._scheduler.append_job(job.Job(action))
|
142
|
|
-
|
143
|
143
|
request = bots_pb2.CreateBotSessionRequest(parent='',
|
144
|
144
|
bot_session=bot_session)
|
|
145
|
+ # Inject work
|
|
146
|
+ action_digest = remote_execution_pb2.Digest(hash = 'gaff')
|
|
147
|
+ instance._instance._scheduler.append_job(job.Job(action_digest))
|
145
|
148
|
# Simulated the severed binding between client and server
|
146
|
149
|
bot = copy.deepcopy(instance.CreateBotSession(request, context))
|
147
|
150
|
|
... |
... |
@@ -149,26 +152,50 @@ def test_update_leases_with_work(bot_session, context, instance): |
149
|
152
|
bot_session=bot)
|
150
|
153
|
|
151
|
154
|
response = instance.UpdateBotSession(request, context)
|
152
|
|
- response_action = remote_execution_pb2.Action()
|
153
|
|
- _unpack_any(response.leases[0].payload, response_action)
|
154
|
155
|
|
|
156
|
+ response_action = remote_execution_pb2.Digest()
|
|
157
|
+ response.leases[0].payload.Unpack(response_action)
|
155
|
158
|
assert isinstance(response, bots_pb2.BotSession)
|
156
|
159
|
assert response.leases[0].state == LeaseState.PENDING.value
|
157
|
|
- assert response.leases[1].state == LeaseState.LEASE_STATE_UNSPECIFIED.value
|
158
|
160
|
assert uuid.UUID(response.leases[0].id, version=4)
|
159
|
|
- assert response_action == action
|
|
161
|
+ assert response_action == action_digest
|
160
|
162
|
|
161
|
163
|
def test_update_leases_work_complete(bot_session, context, instance):
|
162
|
|
- leases = [bots_pb2.Lease() for x in range(2)]
|
163
|
|
- bot_session.leases.extend(leases)
|
|
164
|
+ request = bots_pb2.CreateBotSessionRequest(parent='',
|
|
165
|
+ bot_session=bot_session)
|
|
166
|
+ # Inject work
|
|
167
|
+ action_digest = remote_execution_pb2.Digest(hash = 'gaff')
|
|
168
|
+ instance._instance._scheduler.append_job(job.Job(action_digest))
|
|
169
|
+ # Simulated the severed binding between client and server
|
|
170
|
+ bot = copy.deepcopy(instance.CreateBotSession(request, context))
|
|
171
|
+
|
|
172
|
+ request = bots_pb2.UpdateBotSessionRequest(name=bot.name,
|
|
173
|
+ bot_session=bot)
|
|
174
|
+
|
|
175
|
+ response = copy.deepcopy(instance.UpdateBotSession(request, context))
|
|
176
|
+
|
|
177
|
+ response.leases[0].state = LeaseState.ACTIVE.value
|
|
178
|
+
|
|
179
|
+ request = bots_pb2.UpdateBotSessionRequest(name=response.name,
|
|
180
|
+ bot_session=response)
|
|
181
|
+
|
|
182
|
+ response = copy.deepcopy(instance.UpdateBotSession(request, context))
|
|
183
|
+
|
|
184
|
+ response.leases[0].state = LeaseState.COMPLETED.value
|
|
185
|
+
|
|
186
|
+ request = bots_pb2.UpdateBotSessionRequest(name=response.name,
|
|
187
|
+ bot_session=response)
|
164
|
188
|
|
165
|
|
- # Inject some work to be done
|
166
|
|
- action = remote_execution_pb2.Action()
|
167
|
|
- action.command_digest.hash = 'rick'
|
168
|
|
- instance._instance._scheduler.append_job(job.Job(action))
|
|
189
|
+ response = copy.deepcopy(instance.UpdateBotSession(request, context))
|
|
190
|
+
|
|
191
|
+ assert len(response.leases) == 0
|
169
|
192
|
|
|
193
|
+def test_work_rejected_by_bot(bot_session, context, instance):
|
170
|
194
|
request = bots_pb2.CreateBotSessionRequest(parent='',
|
171
|
195
|
bot_session=bot_session)
|
|
196
|
+ # Inject work
|
|
197
|
+ action_digest = remote_execution_pb2.Digest(hash = 'gaff')
|
|
198
|
+ instance._instance._scheduler.append_job(job.Job(action_digest))
|
172
|
199
|
# Simulated the severed binding between client and server
|
173
|
200
|
bot = copy.deepcopy(instance.CreateBotSession(request, context))
|
174
|
201
|
|
... |
... |
@@ -177,26 +204,125 @@ def test_update_leases_work_complete(bot_session, context, instance): |
177
|
204
|
|
178
|
205
|
response = copy.deepcopy(instance.UpdateBotSession(request, context))
|
179
|
206
|
|
180
|
|
- operation_name = response.leases[0].id
|
|
207
|
+ response.leases[0].state = LeaseState.COMPLETED.value
|
|
208
|
+
|
|
209
|
+ request = bots_pb2.UpdateBotSessionRequest(name=response.name,
|
|
210
|
+ bot_session=response)
|
|
211
|
+
|
|
212
|
+ response = instance.UpdateBotSession(request, context)
|
|
213
|
+
|
|
214
|
+ context.set_code.assert_called_once_with(grpc.StatusCode.UNIMPLEMENTED)
|
|
215
|
+
|
|
216
|
+def test_work_rejected_by_bot(bot_session, context, instance):
|
|
217
|
+ request = bots_pb2.CreateBotSessionRequest(parent='',
|
|
218
|
+ bot_session=bot_session)
|
|
219
|
+ # Inject work
|
|
220
|
+ action_digest = remote_execution_pb2.Digest(hash = 'gaff')
|
|
221
|
+ instance._instance._scheduler.append_job(job.Job(action_digest))
|
|
222
|
+ # Simulated the severed binding between client and server
|
|
223
|
+ bot = copy.deepcopy(instance.CreateBotSession(request, context))
|
|
224
|
+
|
|
225
|
+ request = bots_pb2.UpdateBotSessionRequest(name=bot.name,
|
|
226
|
+ bot_session=bot)
|
|
227
|
+
|
|
228
|
+ response = copy.deepcopy(instance.UpdateBotSession(request, context))
|
181
|
229
|
|
182
|
|
- assert response.leases[0].state == LeaseState.PENDING.value
|
183
|
230
|
response.leases[0].state = LeaseState.COMPLETED.value
|
184
|
231
|
|
185
|
232
|
request = bots_pb2.UpdateBotSessionRequest(name=response.name,
|
186
|
233
|
bot_session=response)
|
|
234
|
+
|
|
235
|
+ response = instance.UpdateBotSession(request, context)
|
|
236
|
+
|
|
237
|
+ context.set_code.assert_called_once_with(grpc.StatusCode.UNIMPLEMENTED)
|
|
238
|
+
|
|
239
|
+@pytest.mark.parametrize("state", [ LeaseState.LEASE_STATE_UNSPECIFIED, LeaseState.PENDING])
|
|
240
|
+def test_work_out_of_sync_from_pending(state, bot_session, context, instance):
|
|
241
|
+ request = bots_pb2.CreateBotSessionRequest(parent='',
|
|
242
|
+ bot_session=bot_session)
|
|
243
|
+ # Inject work
|
|
244
|
+ action_digest = remote_execution_pb2.Digest(hash = 'gaff')
|
|
245
|
+ instance._instance._scheduler.append_job(job.Job(action_digest))
|
|
246
|
+ # Simulated the severed binding between client and server
|
|
247
|
+ bot = copy.deepcopy(instance.CreateBotSession(request, context))
|
|
248
|
+
|
|
249
|
+ request = bots_pb2.UpdateBotSessionRequest(name=bot.name,
|
|
250
|
+ bot_session=bot)
|
|
251
|
+
|
|
252
|
+ response = copy.deepcopy(instance.UpdateBotSession(request, context))
|
|
253
|
+
|
|
254
|
+ response.leases[0].state = state.value
|
|
255
|
+
|
|
256
|
+ request = bots_pb2.UpdateBotSessionRequest(name=response.name,
|
|
257
|
+ bot_session=response)
|
|
258
|
+
|
|
259
|
+ response = instance.UpdateBotSession(request, context)
|
|
260
|
+
|
|
261
|
+ context.set_code.assert_called_once_with(grpc.StatusCode.DATA_LOSS)
|
|
262
|
+
|
|
263
|
+@pytest.mark.parametrize("state", [ LeaseState.LEASE_STATE_UNSPECIFIED, LeaseState.PENDING])
|
|
264
|
+def test_work_out_of_sync_from_active(state, bot_session, context, instance):
|
|
265
|
+ request = bots_pb2.CreateBotSessionRequest(parent='',
|
|
266
|
+ bot_session=bot_session)
|
|
267
|
+ # Inject work
|
|
268
|
+ action_digest = remote_execution_pb2.Digest(hash = 'gaff')
|
|
269
|
+ instance._instance._scheduler.append_job(job.Job(action_digest))
|
187
|
270
|
# Simulated the severed binding between client and server
|
|
271
|
+ bot = copy.deepcopy(instance.CreateBotSession(request, context))
|
|
272
|
+
|
|
273
|
+ request = bots_pb2.UpdateBotSessionRequest(name=bot.name,
|
|
274
|
+ bot_session=bot)
|
|
275
|
+
|
188
|
276
|
response = copy.deepcopy(instance.UpdateBotSession(request, context))
|
189
|
|
- assert isinstance(response, bots_pb2.BotSession)
|
190
|
|
- assert instance._instance._scheduler.jobs[operation_name]._execute_stage == ExecuteStage.COMPLETED
|
|
277
|
+
|
|
278
|
+ response.leases[0].state = LeaseState.ACTIVE.value
|
|
279
|
+
|
|
280
|
+ request = copy.deepcopy(bots_pb2.UpdateBotSessionRequest(name=response.name,
|
|
281
|
+ bot_session=response))
|
|
282
|
+
|
|
283
|
+ response = instance.UpdateBotSession(request, context)
|
|
284
|
+
|
|
285
|
+ response.leases[0].state = state.value
|
|
286
|
+
|
|
287
|
+ request = bots_pb2.UpdateBotSessionRequest(name=response.name,
|
|
288
|
+ bot_session=response)
|
|
289
|
+
|
|
290
|
+ response = instance.UpdateBotSession(request, context)
|
|
291
|
+
|
|
292
|
+ context.set_code.assert_called_once_with(grpc.StatusCode.DATA_LOSS)
|
|
293
|
+
|
|
294
|
+def test_work_active_to_active(bot_session, context, instance):
|
|
295
|
+ request = bots_pb2.CreateBotSessionRequest(parent='',
|
|
296
|
+ bot_session=bot_session)
|
|
297
|
+ # Inject work
|
|
298
|
+ action_digest = remote_execution_pb2.Digest(hash = 'gaff')
|
|
299
|
+ instance._instance._scheduler.append_job(job.Job(action_digest))
|
|
300
|
+ # Simulated the severed binding between client and server
|
|
301
|
+ bot = copy.deepcopy(instance.CreateBotSession(request, context))
|
|
302
|
+
|
|
303
|
+ request = bots_pb2.UpdateBotSessionRequest(name=bot.name,
|
|
304
|
+ bot_session=bot)
|
|
305
|
+
|
|
306
|
+ response = copy.deepcopy(instance.UpdateBotSession(request, context))
|
|
307
|
+
|
|
308
|
+ response.leases[0].state = LeaseState.ACTIVE.value
|
|
309
|
+
|
|
310
|
+ request = copy.deepcopy(bots_pb2.UpdateBotSessionRequest(name=response.name,
|
|
311
|
+ bot_session=response))
|
|
312
|
+
|
|
313
|
+ response = instance.UpdateBotSession(request, context)
|
|
314
|
+
|
|
315
|
+ response.leases[0].state = LeaseState.ACTIVE.value
|
|
316
|
+
|
|
317
|
+ request = bots_pb2.UpdateBotSessionRequest(name=response.name,
|
|
318
|
+ bot_session=response)
|
|
319
|
+
|
|
320
|
+ response = instance.UpdateBotSession(request, context)
|
|
321
|
+
|
|
322
|
+ assert response.leases[0].state == LeaseState.ACTIVE.value
|
191
|
323
|
|
192
|
324
|
def test_post_bot_event_temp(context, instance):
|
193
|
325
|
request = bots_pb2.PostBotEventTempRequest()
|
194
|
326
|
instance.PostBotEventTemp(request, context)
|
195
|
327
|
|
196
|
328
|
context.set_code.assert_called_once_with(grpc.StatusCode.UNIMPLEMENTED)
|
197
|
|
-
|
198
|
|
-def _unpack_any(unpack_from, to):
|
199
|
|
- any = any_pb2.Any()
|
200
|
|
- any.CopyFrom(unpack_from)
|
201
|
|
- any.Unpack(to)
|
202
|
|
- return to
|