-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix flaky bucket eviction tests by splitting/isolating them (#5876)
* fix flaky bucket eviction tests by splitting/isolating them * fix imports
- Loading branch information
1 parent
7690ab5
commit 102b4b0
Showing
8 changed files
with
173 additions
and
102 deletions.
There are no files selected for viewing
49 changes: 49 additions & 0 deletions
49
frontend/javascripts/test/sagas/volumetracing/bucket_eviction_expect_failure.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// @flow | ||
import test from "ava"; | ||
import mockRequire from "mock-require"; | ||
import { waitForCondition } from "libs/utils"; | ||
|
||
import "test/sagas/saga_integration.mock"; | ||
import { __setupOxalis, createBucketResponseFunction } from "test/helpers/apiHelpers"; | ||
import { restartSagaAction, wkReadyAction } from "oxalis/model/actions/actions"; | ||
import Store from "oxalis/store"; | ||
import { hasRootSagaCrashed } from "oxalis/model/sagas/root_saga"; | ||
|
||
import { testLabelingManyBuckets } from "./bucket_eviction_helper"; | ||
|
||
const { discardSaveQueuesAction } = mockRequire.reRequire("oxalis/model/actions/save_actions"); | ||
|
||
test.beforeEach(async t => { | ||
// Setup oxalis, this will execute model.fetch(...) and initialize the store with the tracing, etc. | ||
Store.dispatch(restartSagaAction()); | ||
Store.dispatch(discardSaveQueuesAction()); | ||
|
||
await __setupOxalis(t, "volume"); | ||
|
||
// Dispatch the wkReadyAction, so the sagas are started | ||
Store.dispatch(wkReadyAction()); | ||
}); | ||
|
||
test.serial( | ||
"Brushing/Tracing should crash when too many buckets are labeled at once without saving inbetween", | ||
async t => { | ||
await t.context.api.tracing.save(); | ||
|
||
t.context.mocks.Request.sendJSONReceiveArraybufferWithHeaders = createBucketResponseFunction( | ||
Uint16Array, | ||
0, | ||
0, | ||
); | ||
// webKnossos will start to evict buckets forcefully if too many are dirty at the same time. | ||
// This is not ideal, but usually handled by the fact that buckets are regularly saved to the | ||
// backend and then marked as not dirty. | ||
// This test provokes that webKnossos crashes (a hard crash is only done during testing; in dev/prod | ||
// a soft warning is emitted via the devtools). | ||
// The corresponding sibling test checks that saving inbetween does not make webKnossos crash. | ||
t.plan(2); | ||
t.false(hasRootSagaCrashed()); | ||
const failedSagaPromise = waitForCondition(hasRootSagaCrashed, 500); | ||
await Promise.race([testLabelingManyBuckets(t, false), failedSagaPromise]); | ||
t.true(hasRootSagaCrashed()); | ||
}, | ||
); |
43 changes: 43 additions & 0 deletions
43
frontend/javascripts/test/sagas/volumetracing/bucket_eviction_expect_success.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// @flow | ||
import test from "ava"; | ||
import mockRequire from "mock-require"; | ||
import { waitForCondition } from "libs/utils"; | ||
|
||
import "test/sagas/saga_integration.mock"; | ||
import { __setupOxalis, createBucketResponseFunction } from "test/helpers/apiHelpers"; | ||
import { restartSagaAction, wkReadyAction } from "oxalis/model/actions/actions"; | ||
import Store from "oxalis/store"; | ||
import { hasRootSagaCrashed } from "oxalis/model/sagas/root_saga"; | ||
|
||
import { testLabelingManyBuckets } from "./bucket_eviction_helper"; | ||
|
||
const { discardSaveQueuesAction } = mockRequire.reRequire("oxalis/model/actions/save_actions"); | ||
|
||
test.beforeEach(async t => { | ||
// Setup oxalis, this will execute model.fetch(...) and initialize the store with the tracing, etc. | ||
Store.dispatch(restartSagaAction()); | ||
Store.dispatch(discardSaveQueuesAction()); | ||
|
||
await __setupOxalis(t, "volume"); | ||
|
||
// Dispatch the wkReadyAction, so the sagas are started | ||
Store.dispatch(wkReadyAction()); | ||
}); | ||
|
||
test.serial( | ||
"Brushing/Tracing should not crash when too many buckets are labeled at once with saving inbetween", | ||
async t => { | ||
await t.context.api.tracing.save(); | ||
|
||
t.context.mocks.Request.sendJSONReceiveArraybufferWithHeaders = createBucketResponseFunction( | ||
Uint16Array, | ||
0, | ||
0, | ||
); | ||
t.plan(2); | ||
t.false(hasRootSagaCrashed()); | ||
const failedSagaPromise = waitForCondition(hasRootSagaCrashed, 500); | ||
await Promise.race([testLabelingManyBuckets(t, true), failedSagaPromise]); | ||
t.false(hasRootSagaCrashed()); | ||
}, | ||
); |
76 changes: 76 additions & 0 deletions
76
frontend/javascripts/test/sagas/volumetracing/bucket_eviction_helper.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// @flow | ||
import _ from "lodash"; | ||
import mockRequire from "mock-require"; | ||
|
||
import "test/sagas/saga_integration.mock"; | ||
import { createBucketResponseFunction } from "test/helpers/apiHelpers"; | ||
import Store from "oxalis/store"; | ||
|
||
import { OrthoViews, AnnotationToolEnum } from "oxalis/constants"; | ||
import { updateUserSettingAction } from "oxalis/model/actions/settings_actions"; | ||
|
||
const { setToolAction } = mockRequire.reRequire("oxalis/model/actions/ui_actions"); | ||
const { setPositionAction } = mockRequire.reRequire("oxalis/model/actions/flycam_actions"); | ||
|
||
const { | ||
setActiveCellAction, | ||
addToLayerAction, | ||
startEditingAction, | ||
finishEditingAction, | ||
} = mockRequire.reRequire("oxalis/model/actions/volumetracing_actions"); | ||
|
||
export async function testLabelingManyBuckets(t: any, saveInbetween: boolean) { | ||
// We set MAXIMUM_BUCKET_COUNT to 150 and then label 199 = 75 (mag1) + 124 (downsampled) buckets in total. | ||
// In between, we will save the data which allows the buckets of the first batch to be GC'ed. | ||
// Therefore, saving the buckets of the second batch should not cause any problems. | ||
t.context.model.getCubeByLayerName("segmentation").MAXIMUM_BUCKET_COUNT = 150; | ||
|
||
const oldCellId = 11; | ||
const brushSize = 10; | ||
const newCellId = 2; | ||
|
||
t.context.mocks.Request.sendJSONReceiveArraybufferWithHeaders = createBucketResponseFunction( | ||
Uint16Array, | ||
oldCellId, | ||
500, | ||
); | ||
// Reload buckets which might have already been loaded before swapping the sendJSONReceiveArraybufferWithHeaders | ||
// function. | ||
await t.context.api.data.reloadAllBuckets(); | ||
|
||
// Prepare to paint into the center of 50 buckets. | ||
const paintPositions1 = _.range(0, 50).map(idx => [32 * idx + 16, 32 * idx + 16, 32 * idx + 16]); | ||
// Prepare to paint into the center of 50 other buckets. | ||
const paintPositions2 = _.range(50, 100).map(idx => [ | ||
32 * idx + 16, | ||
32 * idx + 16, | ||
32 * idx + 16, | ||
]); | ||
|
||
Store.dispatch(updateUserSettingAction("brushSize", brushSize)); | ||
Store.dispatch(setToolAction(AnnotationToolEnum.BRUSH)); | ||
Store.dispatch(setActiveCellAction(newCellId)); | ||
|
||
for (const paintPosition of paintPositions1) { | ||
Store.dispatch(setPositionAction(paintPosition)); | ||
Store.dispatch(startEditingAction(paintPosition, OrthoViews.PLANE_XY)); | ||
Store.dispatch(addToLayerAction(paintPosition)); | ||
Store.dispatch(finishEditingAction()); | ||
} | ||
|
||
console.log("saveInbetween", saveInbetween); | ||
if (saveInbetween) { | ||
await t.context.api.tracing.save(); | ||
} | ||
|
||
for (const paintPosition of paintPositions2) { | ||
Store.dispatch(setPositionAction(paintPosition)); | ||
Store.dispatch(startEditingAction(paintPosition, OrthoViews.PLANE_XY)); | ||
Store.dispatch(addToLayerAction(paintPosition)); | ||
Store.dispatch(finishEditingAction()); | ||
} | ||
|
||
await t.context.api.tracing.save(); | ||
} | ||
|
||
export default {}; |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...volumetracing_saga_integration.spec.js.md → ...volumetracing_saga_integration.spec.js.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.