[Alerting][Event Log] ensures we wait for the right number of events in test (#84189)

Keeps the exact same assertions, but ensures the retry loop waits for them to complete so we don't assert too soon.
This commit is contained in:
Gidi Meir Morris 2020-12-03 15:13:59 +00:00 committed by GitHub
parent 7393c230a4
commit eb0569b1ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 58 additions and 37 deletions

View file

@ -8,13 +8,26 @@ import { IValidatedEvent } from '../../../../plugins/event_log/server';
import { getUrlPrefix } from '.'; import { getUrlPrefix } from '.';
import { FtrProviderContext } from '../ftr_provider_context'; import { FtrProviderContext } from '../ftr_provider_context';
interface GreaterThanEqualCondition {
gte: number;
}
interface EqualCondition {
equal: number;
}
function isEqualConsition(
condition: GreaterThanEqualCondition | EqualCondition
): condition is EqualCondition {
return Number.isInteger((condition as EqualCondition).equal);
}
interface GetEventLogParams { interface GetEventLogParams {
getService: FtrProviderContext['getService']; getService: FtrProviderContext['getService'];
spaceId: string; spaceId: string;
type: string; type: string;
id: string; id: string;
provider: string; provider: string;
actions: string[]; actions: Map<string, { gte: number } | { equal: number }>;
} }
// Return event log entries given the specified parameters; for the `actions` // Return event log entries given the specified parameters; for the `actions`
@ -22,7 +35,6 @@ interface GetEventLogParams {
export async function getEventLog(params: GetEventLogParams): Promise<IValidatedEvent[]> { export async function getEventLog(params: GetEventLogParams): Promise<IValidatedEvent[]> {
const { getService, spaceId, type, id, provider, actions } = params; const { getService, spaceId, type, id, provider, actions } = params;
const supertest = getService('supertest'); const supertest = getService('supertest');
const actionsSet = new Set(actions);
const spacePrefix = getUrlPrefix(spaceId); const spacePrefix = getUrlPrefix(spaceId);
const url = `${spacePrefix}/api/event_log/${type}/${id}/_find?per_page=5000`; const url = `${spacePrefix}/api/event_log/${type}/${id}/_find?per_page=5000`;
@ -36,14 +48,35 @@ export async function getEventLog(params: GetEventLogParams): Promise<IValidated
const events: IValidatedEvent[] = (result.data as IValidatedEvent[]) const events: IValidatedEvent[] = (result.data as IValidatedEvent[])
.filter((event) => event?.event?.provider === provider) .filter((event) => event?.event?.provider === provider)
.filter((event) => event?.event?.action) .filter((event) => event?.event?.action)
.filter((event) => actionsSet.has(event?.event?.action!)); .filter((event) => actions.has(event?.event?.action!));
const foundActions = new Set(
events.map((event) => event?.event?.action).filter((action) => !!action)
);
for (const action of actions) { const foundActions = events
if (!foundActions.has(action)) { .map((event) => event?.event?.action)
throw new Error(`no event found with action "${action}"`); .reduce((actionsSum, action) => {
if (action) {
actionsSum.set(action, 1 + (actionsSum.get(action) ?? 0));
}
return actionsSum;
}, new Map<string, number>());
for (const [action, condition] of actions.entries()) {
if (
!(
foundActions.has(action) &&
(isEqualConsition(condition)
? foundActions.get(action)! === condition.equal
: foundActions.get(action)! >= condition.gte)
)
) {
throw new Error(
`insufficient events found with action "${action}" (${
foundActions.get(action) ?? 0
} must be ${
isEqualConsition(condition)
? `equal to ${condition.equal}`
: `greater than or equal to ${condition.gte}`
})`
);
} }
} }

View file

@ -518,12 +518,10 @@ export default function ({ getService }: FtrProviderContext) {
type: 'action', type: 'action',
id: actionId, id: actionId,
provider: 'actions', provider: 'actions',
actions: ['execute'], actions: new Map([['execute', { equal: 1 }]]),
}); });
}); });
expect(events.length).to.equal(1);
const event = events[0]; const event = events[0];
const duration = event?.event?.duration; const duration = event?.event?.duration;

View file

@ -1096,12 +1096,10 @@ instanceStateValue: true
type: 'alert', type: 'alert',
id: alertId, id: alertId,
provider: 'alerting', provider: 'alerting',
actions: ['execute'], actions: new Map([['execute', { gte: 1 }]]),
}); });
}); });
expect(events.length).to.be.greaterThan(0);
const event = events[0]; const event = events[0];
const duration = event?.event?.duration; const duration = event?.event?.duration;

View file

@ -56,7 +56,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
type: 'alert', type: 'alert',
id: alertId, id: alertId,
provider: 'alerting', provider: 'alerting',
actions: ['execute'], actions: new Map([['execute', { gte: 1 }]]),
}); });
const errorEvents = someEvents.filter( const errorEvents = someEvents.filter(
(event) => event?.kibana?.alerting?.status === 'error' (event) => event?.kibana?.alerting?.status === 'error'

View file

@ -270,12 +270,10 @@ export default function ({ getService }: FtrProviderContext) {
type: 'action', type: 'action',
id: actionId, id: actionId,
provider: 'actions', provider: 'actions',
actions: ['execute'], actions: new Map([['execute', { equal: 1 }]]),
}); });
}); });
expect(events.length).to.equal(1);
const event = events[0]; const event = events[0];
const duration = event?.event?.duration; const duration = event?.event?.duration;

View file

@ -17,8 +17,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
const supertest = getService('supertest'); const supertest = getService('supertest');
const retry = getService('retry'); const retry = getService('retry');
// FLAKY: https://github.com/elastic/kibana/issues/81668 describe('eventLog', () => {
describe.skip('eventLog', () => {
const objectRemover = new ObjectRemover(supertest); const objectRemover = new ObjectRemover(supertest);
after(() => objectRemover.removeAll()); after(() => objectRemover.removeAll());
@ -73,27 +72,22 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
type: 'alert', type: 'alert',
id: alertId, id: alertId,
provider: 'alerting', provider: 'alerting',
actions: [ actions: new Map([
'execute', // make sure the counts of the # of events per type are as expected
'execute-action', ['execute', { gte: 4 }],
'new-instance', ['execute-action', { equal: 2 }],
'active-instance', ['new-instance', { equal: 1 }],
'recovered-instance', ['active-instance', { gte: 1 }],
], ['recovered-instance', { equal: 1 }],
]),
}); });
}); });
// make sure the counts of the # of events per type are as expected
const executeEvents = getEventsByAction(events, 'execute'); const executeEvents = getEventsByAction(events, 'execute');
const executeActionEvents = getEventsByAction(events, 'execute-action'); const executeActionEvents = getEventsByAction(events, 'execute-action');
const newInstanceEvents = getEventsByAction(events, 'new-instance'); const newInstanceEvents = getEventsByAction(events, 'new-instance');
const recoveredInstanceEvents = getEventsByAction(events, 'recovered-instance'); const recoveredInstanceEvents = getEventsByAction(events, 'recovered-instance');
expect(executeEvents.length >= 4).to.be(true);
expect(executeActionEvents.length).to.be(2);
expect(newInstanceEvents.length).to.be(1);
expect(recoveredInstanceEvents.length).to.be(1);
// make sure the events are in the right temporal order // make sure the events are in the right temporal order
const executeTimes = getTimestamps(executeEvents); const executeTimes = getTimestamps(executeEvents);
const executeActionTimes = getTimestamps(executeActionEvents); const executeActionTimes = getTimestamps(executeActionEvents);
@ -137,7 +131,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
validateInstanceEvent(event, `created new instance: 'instance'`); validateInstanceEvent(event, `created new instance: 'instance'`);
break; break;
case 'recovered-instance': case 'recovered-instance':
validateInstanceEvent(event, `recovered instance: 'instance'`); validateInstanceEvent(event, `instance 'instance' has recovered`);
break; break;
case 'active-instance': case 'active-instance':
validateInstanceEvent(event, `active instance: 'instance' in actionGroup: 'default'`); validateInstanceEvent(event, `active instance: 'instance' in actionGroup: 'default'`);
@ -182,7 +176,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) {
type: 'alert', type: 'alert',
id: alertId, id: alertId,
provider: 'alerting', provider: 'alerting',
actions: ['execute'], actions: new Map([['execute', { gte: 1 }]]),
}); });
}); });

View file

@ -256,7 +256,7 @@ export default function createGetAlertInstanceSummaryTests({ getService }: FtrPr
type: 'alert', type: 'alert',
id, id,
provider: 'alerting', provider: 'alerting',
actions, actions: new Map(actions.map((action) => [action, { gte: 1 }])),
}); });
}); });
} }