@@ -381,19 +381,15 @@ class OperationRepoTests : FunSpec({
381
381
val enqueueAndWaitMaxTime = mocks.configModelStore.model.opRepoExecutionInterval / 2
382
382
val opRepo = mocks.operationRepo
383
383
384
- val executeOperationsCall = Waiter ()
385
- coEvery { opRepo.executeOperations(any()) } coAnswers {
386
- executeOperationsCall.wake()
387
- delay(10)
388
- }
384
+ val executeOperationsCall = mockExecuteOperations(opRepo)
389
385
390
386
// When
391
387
opRepo.start()
392
- opRepo.enqueue(mockOperation(groupComparisonType = GroupComparisonType . NONE ))
388
+ opRepo.enqueue(mockOperationNonGroupable( ))
393
389
executeOperationsCall.waitForWake()
394
390
val secondEnqueueResult =
395
391
withTimeoutOrNull(enqueueAndWaitMaxTime) {
396
- opRepo.enqueueAndWait(mockOperation(groupComparisonType = GroupComparisonType . NONE ))
392
+ opRepo.enqueueAndWait(mockOperationNonGroupable( ))
397
393
}
398
394
399
395
// Then
@@ -402,6 +398,34 @@ class OperationRepoTests : FunSpec({
402
398
opRepo.executeOperations(any())
403
399
}
404
400
}
401
+
402
+ // This ensures there are no off-by-one errors with the same scenario as above, but on a 2nd
403
+ // pass of OperationRepo
404
+ test("operations enqueued while repo is executing should be executed only after the next opRepoExecutionInterval, 2nd pass") {
405
+ // Given
406
+ val mocks = Mocks ()
407
+ mocks.configModelStore.model.opRepoExecutionInterval = 100
408
+ val enqueueAndWaitMaxTime = mocks.configModelStore.model.opRepoExecutionInterval / 2
409
+ val opRepo = mocks.operationRepo
410
+
411
+ val executeOperationsCall = mockExecuteOperations(opRepo)
412
+
413
+ // When
414
+ opRepo.start()
415
+ opRepo.enqueue(mockOperationNonGroupable())
416
+ executeOperationsCall.waitForWake()
417
+ opRepo.enqueueAndWait(mockOperationNonGroupable())
418
+ val thirdEnqueueResult =
419
+ withTimeoutOrNull(enqueueAndWaitMaxTime) {
420
+ opRepo.enqueueAndWait(mockOperationNonGroupable())
421
+ }
422
+
423
+ // Then
424
+ thirdEnqueueResult shouldBe null
425
+ coVerify(exactly = 2) {
426
+ opRepo.executeOperations(any())
427
+ }
428
+ }
405
429
}) {
406
430
companion object {
407
431
private fun mockOperation (
@@ -427,5 +451,17 @@ class OperationRepoTests : FunSpec({
427
451
428
452
return operation
429
453
}
454
+
455
+ private fun mockOperationNonGroupable () = mockOperation(groupComparisonType = GroupComparisonType .NONE )
456
+
457
+ private fun mockExecuteOperations (opRepo : OperationRepo ): Waiter {
458
+ val executeWaiter = Waiter ()
459
+ coEvery { opRepo.executeOperations(any()) } coAnswers {
460
+ executeWaiter.wake()
461
+ delay(10 )
462
+ firstArg<List <OperationRepo .OperationQueueItem >>().forEach { it.waiter?.wake(true ) }
463
+ }
464
+ return executeWaiter
465
+ }
430
466
}
431
467
}
0 commit comments