Attempt to stabilize cloneIndex integration tests (#86123)

* Attempt to stabilize cloneIndex integration tests

* Unskip test

* return resolves/rejects and add assertions counts to each test

* Await don't return expect promises

* Await don't return expect promises for other tests too
This commit is contained in:
Rudolf Meijering 2020-12-18 14:30:14 +01:00 committed by GitHub
parent d5d19f0652
commit 3c284fbff3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 114 additions and 69 deletions

View file

@ -22,14 +22,14 @@ import { elasticsearchClientMock } from '../../../elasticsearch/client/mocks';
import { catchRetryableEsClientErrors } from './catch_retryable_es_client_errors';
describe('catchRetryableEsClientErrors', () => {
it('rejects non-retryable response errors', () => {
it('rejects non-retryable response errors', async () => {
const error = new esErrors.ResponseError(
elasticsearchClientMock.createApiResponse({
body: { error: { type: 'cluster_block_exception' } },
statusCode: 400,
})
);
return expect(Promise.reject(error).catch(catchRetryableEsClientErrors)).rejects.toBe(error);
await expect(Promise.reject(error).catch(catchRetryableEsClientErrors)).rejects.toBe(error);
});
describe('returns left retryable_es_client_error for', () => {
it('NoLivingConnectionsError', async () => {

View file

@ -100,8 +100,9 @@ describe('migration actions', () => {
describe('fetchIndices', () => {
it('resolves right empty record if no indices were found', async () => {
expect.assertions(1);
const task = fetchIndices(client, ['no_such_index']);
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Right",
"right": Object {},
@ -109,12 +110,13 @@ describe('migration actions', () => {
`);
});
it('resolves right record with found indices', async () => {
expect.assertions(1);
const res = (await fetchIndices(client, [
'no_such_index',
'existing_index_with_docs',
])()) as Either.Right<unknown>;
return expect(res.right).toEqual(
expect(res.right).toEqual(
expect.objectContaining({
existing_index_with_docs: {
aliases: {},
@ -131,17 +133,19 @@ describe('migration actions', () => {
await createIndex(client, 'new_index_without_write_block', { properties: {} })();
});
it('resolves right when setting the write block succeeds', async () => {
expect.assertions(1);
const task = setWriteBlock(client, 'new_index_without_write_block');
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Right",
"right": "set_write_block_succeeded",
}
`);
});
it('resolves right when setting a write block on an index that already has one', () => {
it('resolves right when setting a write block on an index that already has one', async () => {
expect.assertions(1);
const task = setWriteBlock(client, 'existing_index_with_write_block');
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Right",
"right": "set_write_block_succeeded",
@ -149,6 +153,7 @@ describe('migration actions', () => {
`);
});
it('once resolved, prevents further writes to the index', async () => {
expect.assertions(1);
const task = setWriteBlock(client, 'new_index_without_write_block');
await task();
const sourceDocs = ([
@ -157,13 +162,14 @@ describe('migration actions', () => {
{ _source: { title: 'doc 3' } },
{ _source: { title: 'doc 4' } },
] as unknown) as SavedObjectsRawDoc[];
return expect(
await expect(
bulkOverwriteTransformedDocuments(client, 'new_index_without_write_block', sourceDocs)()
).rejects.toMatchObject(expect.anything());
});
it('resolves left index_not_found_exception when the index does not exist', () => {
it('resolves left index_not_found_exception when the index does not exist', async () => {
expect.assertions(1);
const task = setWriteBlock(client, 'no_such_index');
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Left",
"left": Object {
@ -180,43 +186,51 @@ describe('migration actions', () => {
await createIndex(client, 'existing_index_with_write_block_2', { properties: {} })();
await setWriteBlock(client, 'existing_index_with_write_block_2')();
});
it('resolves right if successful when an index already has a write block', () => {
it('resolves right if successful when an index already has a write block', async () => {
expect.assertions(1);
const task = removeWriteBlock(client, 'existing_index_with_write_block_2');
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Right",
"right": "remove_write_block_succeeded",
}
`);
});
it('resolves right if successful when an index does not have a write block', () => {
it('resolves right if successful when an index does not have a write block', async () => {
expect.assertions(1);
const task = removeWriteBlock(client, 'existing_index_without_write_block_2');
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Right",
"right": "remove_write_block_succeeded",
}
`);
});
it('rejects if there is a non-retryable error', () => {
it('rejects if there is a non-retryable error', async () => {
expect.assertions(1);
const task = removeWriteBlock(client, 'no_such_index');
return expect(task()).rejects.toMatchInlineSnapshot(
await expect(task()).rejects.toMatchInlineSnapshot(
`[ResponseError: index_not_found_exception]`
);
});
});
describe('cloneIndex', () => {
afterEach(async () => {
afterAll(async () => {
try {
await client.indices.delete({ index: 'yellow_then_green_index' });
await client.indices.delete({ index: 'clone_*' });
} catch (e) {
/** ignore */
}
});
it('resolves right if cloning into a new target index', () => {
const task = cloneIndex(client, 'existing_index_with_write_block', 'yellow_then_green_index');
expect(task()).resolves.toMatchInlineSnapshot(`
it('resolves right if cloning into a new target index', async () => {
expect.assertions(1);
const task = cloneIndex(
client,
'existing_index_with_write_block',
'clone_yellow_then_green_index_1'
);
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Right",
"right": Object {
@ -226,10 +240,11 @@ describe('migration actions', () => {
}
`);
});
it.skip('resolves right after waiting for index status to be green if clone target already existed', async () => {
it('resolves right after waiting for index status to be green if clone target already existed', async () => {
expect.assertions(2);
// Create a yellow index
await client.indices.create({
index: 'yellow_then_green_index',
index: 'clone_yellow_then_green_index_2',
body: {
mappings: { properties: {} },
settings: {
@ -243,7 +258,7 @@ describe('migration actions', () => {
const cloneIndexPromise = cloneIndex(
client,
'existing_index_with_write_block',
'yellow_then_green_index'
'clone_yellow_then_green_index_2'
)();
let indexGreen = false;
@ -258,7 +273,7 @@ describe('migration actions', () => {
indexGreen = true;
}, 10);
return cloneIndexPromise.then((res) => {
await cloneIndexPromise.then((res) => {
// Assert that the promise didn't resolve before the index became green
expect(indexGreen).toBe(true);
expect(res).toMatchInlineSnapshot(`
@ -272,9 +287,10 @@ describe('migration actions', () => {
`);
});
});
it('resolves left index_not_found_exception if the source index does not exist', () => {
const task = cloneIndex(client, 'no_such_index', 'yellow_then_green_index');
expect(task()).resolves.toMatchInlineSnapshot(`
it('resolves left index_not_found_exception if the source index does not exist', async () => {
expect.assertions(1);
const task = cloneIndex(client, 'no_such_index', 'clone_yellow_then_green_index_3');
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Left",
"left": Object {
@ -289,6 +305,7 @@ describe('migration actions', () => {
// Reindex doesn't return any errors on it's own, so we have to test
// together with waitForReindexTask
describe('reindex & waitForReindexTask', () => {
expect.assertions(2);
it('resolves right when reindex succeeds without reindex script', async () => {
const res = (await reindex(
client,
@ -320,6 +337,7 @@ describe('migration actions', () => {
`);
});
it('resolves right when reindex succeeds with reindex script', async () => {
expect.assertions(2);
const res = (await reindex(
client,
'existing_index_with_docs',
@ -349,6 +367,7 @@ describe('migration actions', () => {
`);
});
it('resolves right, ignores version conflicts and does not update existing docs when reindex multiple times', async () => {
expect.assertions(3);
// Reindex with a script
let res = (await reindex(
client,
@ -397,6 +416,7 @@ describe('migration actions', () => {
`);
});
it('resolves right and proceeds to add missing documents if there are some existing docs conflicts', async () => {
expect.assertions(2);
// Simulate a reindex that only adds some of the documents from the
// source index into the target index
await createIndex(client, 'reindex_target_4', { properties: {} })();
@ -444,6 +464,7 @@ describe('migration actions', () => {
`);
});
it('resolves left incompatible_mapping_exception if all reindex failures are due to a strict_dynamic_mapping_exception', async () => {
expect.assertions(1);
// Simulates one instance having completed the UPDATE_TARGET_MAPPINGS
// step which makes the mappings incompatible with outdated documents.
// If another instance then tries a reindex it will get a
@ -479,6 +500,7 @@ describe('migration actions', () => {
`);
});
it('resolves left incompatible_mapping_exception if all reindex failures are due to a mapper_parsing_exception', async () => {
expect.assertions(1);
// Simulates one instance having completed the UPDATE_TARGET_MAPPINGS
// step which makes the mappings incompatible with outdated documents.
// If another instance then tries a reindex it will get a
@ -512,6 +534,7 @@ describe('migration actions', () => {
`);
});
it('resolves left index_not_found_exception if source index does not exist', async () => {
expect.assertions(1);
const res = (await reindex(
client,
'no_such_index',
@ -520,7 +543,7 @@ describe('migration actions', () => {
false
)()) as Either.Right<ReindexResponse>;
const task = waitForReindexTask(client, res.right.taskId, '10s');
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Left",
"left": Object {
@ -531,6 +554,7 @@ describe('migration actions', () => {
`);
});
it('resolves left target_index_had_write_block if all failures are due to a write block', async () => {
expect.assertions(1);
const res = (await reindex(
client,
'existing_index_with_docs',
@ -541,7 +565,7 @@ describe('migration actions', () => {
const task = waitForReindexTask(client, res.right.taskId, '10s');
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Left",
"left": Object {
@ -551,6 +575,7 @@ describe('migration actions', () => {
`);
});
it('resolves left if requireAlias=true and the target is not an alias', async () => {
expect.assertions(1);
const res = (await reindex(
client,
'existing_index_with_docs',
@ -561,7 +586,7 @@ describe('migration actions', () => {
const task = waitForReindexTask(client, res.right.taskId, '10s');
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Left",
"left": Object {
@ -575,6 +600,7 @@ describe('migration actions', () => {
describe('verifyReindex', () => {
it('resolves right if source and target indices have the same amount of documents', async () => {
expect.assertions(1);
const res = (await reindex(
client,
'existing_index_with_docs',
@ -592,9 +618,10 @@ describe('migration actions', () => {
}
`);
});
it('resolves left if source and target indices have different amount of documents', () => {
it('resolves left if source and target indices have different amount of documents', async () => {
expect.assertions(1);
const task = verifyReindex(client, 'existing_index_with_docs', 'existing_index_2');
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Left",
"left": Object {
@ -604,6 +631,7 @@ describe('migration actions', () => {
`);
});
it('rejects if source or target index does not exist', async () => {
expect.assertions(2);
let task = verifyReindex(client, 'no_such_index', 'existing_index_2');
await expect(task()).rejects.toMatchInlineSnapshot(
`[ResponseError: index_not_found_exception]`
@ -618,6 +646,7 @@ describe('migration actions', () => {
describe('searchForOutdatedDocuments', () => {
it('only returns documents that match the outdatedDocumentsQuery', async () => {
expect.assertions(2);
const resultsWithQuery = ((await searchForOutdatedDocuments(
client,
'existing_index_with_docs',
@ -635,6 +664,7 @@ describe('migration actions', () => {
expect(resultsWithoutQuery.length).toBe(4);
});
it('resolves with _id, _source, _seq_no and _primary_term', async () => {
expect.assertions(1);
const results = ((await searchForOutdatedDocuments(client, 'existing_index_with_docs', {
match: { title: { query: 'doc' } },
})()) as Either.Right<SearchResponse>).right.outdatedDocuments;
@ -655,6 +685,7 @@ describe('migration actions', () => {
describe('waitForPickupUpdatedMappingsTask', () => {
it('rejects if there are failures', async () => {
expect.assertions(1);
const res = (await pickupUpdatedMappings(
client,
'existing_index_with_write_block'
@ -664,11 +695,12 @@ describe('migration actions', () => {
// We can't do a snapshot match because the response includes an index
// id which ES assigns dynamically
return expect(task()).rejects.toMatchObject({
await expect(task()).rejects.toMatchObject({
message: /pickupUpdatedMappings task failed with the following failures:\n\[\{\"index\":\"existing_index_with_write_block\"/,
});
});
it('rejects if there is an error', async () => {
expect.assertions(1);
const res = (await pickupUpdatedMappings(
client,
'no_such_index'
@ -676,12 +708,13 @@ describe('migration actions', () => {
const task = waitForPickupUpdatedMappingsTask(client, res.right.taskId, '10s');
return expect(task()).rejects.toMatchInlineSnapshot(`
await expect(task()).rejects.toMatchInlineSnapshot(`
[Error: pickupUpdatedMappings task failed with the following error:
{"type":"index_not_found_exception","reason":"no such index [no_such_index]","resource.type":"index_or_alias","resource.id":"no_such_index","index_uuid":"_na_","index":"no_such_index"}]
`);
});
it('resolves right when successful', async () => {
expect.assertions(1);
const res = (await pickupUpdatedMappings(
client,
'existing_index_with_docs'
@ -689,7 +722,7 @@ describe('migration actions', () => {
const task = waitForPickupUpdatedMappingsTask(client, res.right.taskId, '10s');
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Right",
"right": "pickup_updated_mappings_succeeded",
@ -700,6 +733,7 @@ describe('migration actions', () => {
describe('updateAndPickupMappings', () => {
it('resolves right when mappings were updated and picked up', async () => {
expect.assertions(3);
// Create an index without any mappings and insert documents into it
await createIndex(client, 'existing_index_without_mappings', {
dynamic: false as any,
@ -741,13 +775,14 @@ describe('migration actions', () => {
'existing_index_without_mappings',
{ match: { title: { query: 'doc' } } }
)()) as Either.Right<SearchResponse>).right.outdatedDocuments;
return expect(pickedUpSearchResults.length).toBe(4);
expect(pickedUpSearchResults.length).toBe(4);
});
});
describe('updateAliases', () => {
describe('remove', () => {
it('resolves left index_not_found_exception when the index does not exist', () => {
it('resolves left index_not_found_exception when the index does not exist', async () => {
expect.assertions(1);
const task = updateAliases(client, [
{
remove: {
@ -757,7 +792,7 @@ describe('migration actions', () => {
},
},
]);
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Left",
"left": Object {
@ -769,6 +804,7 @@ describe('migration actions', () => {
});
describe('with must_exist=false', () => {
it('resolves left alias_not_found_exception when alias does not exist', async () => {
expect.assertions(1);
const task = updateAliases(client, [
{
remove: {
@ -778,7 +814,7 @@ describe('migration actions', () => {
},
},
]);
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Left",
"left": Object {
@ -790,6 +826,7 @@ describe('migration actions', () => {
});
describe('with must_exist=true', () => {
it('resolves left alias_not_found_exception when alias does not exist on specified index', async () => {
expect.assertions(1);
const task = updateAliases(client, [
{
remove: {
@ -799,7 +836,7 @@ describe('migration actions', () => {
},
},
]);
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Left",
"left": Object {
@ -809,6 +846,7 @@ describe('migration actions', () => {
`);
});
it('resolves left alias_not_found_exception when alias does not exist', async () => {
expect.assertions(1);
const task = updateAliases(client, [
{
remove: {
@ -818,7 +856,7 @@ describe('migration actions', () => {
},
},
]);
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Left",
"left": Object {
@ -830,7 +868,8 @@ describe('migration actions', () => {
});
});
describe('remove_index', () => {
it('left index_not_found_exception if index does not exist', () => {
it('left index_not_found_exception if index does not exist', async () => {
expect.assertions(1);
const task = updateAliases(client, [
{
remove_index: {
@ -838,7 +877,7 @@ describe('migration actions', () => {
},
},
]);
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Left",
"left": Object {
@ -848,7 +887,8 @@ describe('migration actions', () => {
}
`);
});
it('left remove_index_not_a_concrete_index when remove_index targets an alias', () => {
it('left remove_index_not_a_concrete_index when remove_index targets an alias', async () => {
expect.assertions(1);
const task = updateAliases(client, [
{
remove_index: {
@ -856,7 +896,7 @@ describe('migration actions', () => {
},
},
]);
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Left",
"left": Object {
@ -872,7 +912,8 @@ describe('migration actions', () => {
afterAll(async () => {
await client.indices.delete({ index: 'yellow_then_green_index' });
});
it.skip('resolves right after waiting for an index status to be green if the index already existed', async () => {
it('resolves right after waiting for an index status to be green if the index already existed', async () => {
expect.assertions(2);
// Create a yellow index
await client.indices.create(
{
@ -903,7 +944,7 @@ describe('migration actions', () => {
indexGreen = true;
}, 10);
return createIndexPromise.then((res) => {
await createIndexPromise.then((res) => {
// Assert that the promise didn't resolve before the index became green
expect(indexGreen).toBe(true);
expect(res).toMatchInlineSnapshot(`
@ -914,24 +955,26 @@ describe('migration actions', () => {
`);
});
});
it('rejects when there is an unexpected error creating the index', () => {
it('rejects when there is an unexpected error creating the index', async () => {
expect.assertions(1);
// Creating an index with the same name as an existing alias to induce
// failure
expect(
await expect(
createIndex(client, 'existing_index_2_alias', undefined as any)()
).rejects.toMatchInlineSnapshot(`[ResponseError: invalid_index_name_exception]`);
});
});
describe('bulkOverwriteTransformedDocuments', () => {
it('resolves right when documents do not yet exist in the index', () => {
it('resolves right when documents do not yet exist in the index', async () => {
expect.assertions(1);
const newDocs = ([
{ _source: { title: 'doc 5' } },
{ _source: { title: 'doc 6' } },
{ _source: { title: 'doc 7' } },
] as unknown) as SavedObjectsRawDoc[];
const task = bulkOverwriteTransformedDocuments(client, 'existing_index_with_docs', newDocs);
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Right",
"right": "bulk_index_succeeded",
@ -939,6 +982,7 @@ describe('migration actions', () => {
`);
});
it('resolves right even if there were some version_conflict_engine_exception', async () => {
expect.assertions(1);
const existingDocs = ((await searchForOutdatedDocuments(
client,
'existing_index_with_docs',
@ -949,20 +993,21 @@ describe('migration actions', () => {
...existingDocs,
({ _source: { title: 'doc 8' } } as unknown) as SavedObjectsRawDoc,
]);
return expect(task()).resolves.toMatchInlineSnapshot(`
await expect(task()).resolves.toMatchInlineSnapshot(`
Object {
"_tag": "Right",
"right": "bulk_index_succeeded",
}
`);
});
it('rejects if there are errors', () => {
it('rejects if there are errors', async () => {
expect.assertions(1);
const newDocs = ([
{ _source: { title: 'doc 5' } },
{ _source: { title: 'doc 6' } },
{ _source: { title: 'doc 7' } },
] as unknown) as SavedObjectsRawDoc[];
return expect(
await expect(
bulkOverwriteTransformedDocuments(client, 'existing_index_with_write_block', newDocs)()
).rejects.toMatchObject(expect.anything());
});

View file

@ -142,8 +142,8 @@ describe('migrationsStateActionMachine', () => {
}
`);
});
it('resolves when reaching the DONE state', () => {
return expect(
it('resolves when reaching the DONE state', async () => {
await expect(
migrationStateActionMachine({
initialState,
logger: mockLogger.get(),
@ -152,8 +152,8 @@ describe('migrationsStateActionMachine', () => {
})
).resolves.toEqual(expect.anything());
});
it('resolves with migrated status if some sourceIndex in the DONE state', () => {
return expect(
it('resolves with migrated status if some sourceIndex in the DONE state', async () => {
await expect(
migrationStateActionMachine({
initialState: { ...initialState, ...{ sourceIndex: Option.some('source-index') } },
logger: mockLogger.get(),
@ -162,8 +162,8 @@ describe('migrationsStateActionMachine', () => {
})
).resolves.toEqual(expect.objectContaining({ status: 'migrated' }));
});
it('resolves with patched status if none sourceIndex in the DONE state', () => {
return expect(
it('resolves with patched status if none sourceIndex in the DONE state', async () => {
await expect(
migrationStateActionMachine({
initialState: { ...initialState, ...{ sourceIndex: Option.none } },
logger: mockLogger.get(),
@ -172,8 +172,8 @@ describe('migrationsStateActionMachine', () => {
})
).resolves.toEqual(expect.objectContaining({ status: 'patched' }));
});
it('rejects with error message when reaching the FATAL state', () => {
return expect(
it('rejects with error message when reaching the FATAL state', async () => {
await expect(
migrationStateActionMachine({
initialState: { ...initialState, reason: 'the fatal reason' } as State,
logger: mockLogger.get(),

View file

@ -86,14 +86,14 @@ describe('state action machine', () => {
});
});
test('rejects if an exception is throw from inside an action', () => {
return expect(
test('rejects if an exception is throw from inside an action', async () => {
await expect(
stateActionMachine({ ...state, controlState: 'THROW' }, next, countUntilThree)
).rejects.toThrowErrorMatchingInlineSnapshot(`"Invalid control state"`);
});
test('resolve with the final state once all steps are completed', () => {
return expect(finalStateP).resolves.toMatchInlineSnapshot(`
test('resolve with the final state once all steps are completed', async () => {
await expect(finalStateP).resolves.toMatchInlineSnapshot(`
Object {
"controlState": "DONE",
"count": 3,
@ -101,8 +101,8 @@ describe('state action machine', () => {
`);
});
test("rejects if control state doesn't change after 50 steps", () => {
return expect(
test("rejects if control state doesn't change after 50 steps", async () => {
await expect(
stateActionMachine(state, next, countUntilModel(51))
).rejects.toThrowErrorMatchingInlineSnapshot(
`"Control state didn't change after 50 steps aborting."`