specific function timing tests, jest coverage ignores

This commit is contained in:
Michael Peters 2022-10-03 23:58:12 -07:00
parent e1364b49e8
commit 0d5716ccc9
2 changed files with 43 additions and 15 deletions

View File

@ -150,7 +150,7 @@ describe('fetchAndVerifyIfNeeded tests', () => {
primaryFunc: jest.Mock<Promise<BasicWE | null>, []>,
trustedFunc: jest.Mock<Promise<BasicWE | null>, []>,
ensureTrustedFuncReadyFunc: jest.Mock<Promise<void>, []>,
verifyFunc: jest.Mock<Promise<boolean>, []>,
verifyFunc: jest.Mock<Promise<boolean>, [primaryResult: BasicWE | null, trustedResult: BasicWE | null]>,
} {
const manuals: {
primary: ManualPromise<BasicWE | null>[],
@ -190,7 +190,7 @@ describe('fetchAndVerifyIfNeeded tests', () => {
primaryFunc: jest.fn(() => manuals.primary[calls.primary++]!.promise),
trustedFunc: jest.fn(() => manuals.trusted[calls.trusted++]!.promise),
ensureTrustedFuncReadyFunc: jest.fn(() => manuals.ensureTrustedFuncReady[calls.ensureTrustedFuncReady++]!.promise),
verifyFunc: jest.fn(() => manuals.verify[calls.verify++]!.promise),
verifyFunc: jest.fn((_primaryResult: BasicWE | null, _trustedResult: BasicWE | null) => manuals.verify[calls.verify++]!.promise),
}
}
function getGeneralMocks(): {
@ -221,8 +221,12 @@ describe('fetchAndVerifyIfNeeded tests', () => {
async function disjoint() {
await Util.sleep(0);
}
/* test('nothing before, primary null, then trusted with value', async () => { */
/* expect(false).toBe(true); */
/* }); */
test('nothing before, primary with value, then trusted with value', async () => {
// TODO: Make xxxFunc mock functions that can be tested for if they were called
const {
nextPrimary, nextTrusted, nextEnsureTrustedFuncReady, nextVerify,
primaryFunc, trustedFunc, ensureTrustedFuncReadyFunc, verifyFunc
@ -240,23 +244,27 @@ describe('fetchAndVerifyIfNeeded tests', () => {
expect(av.trustedPromise).toBe(trusted.promise);
expect(av.trustedStatus).toBe('fetching');
expect(primaryFunc).toHaveBeenCalled();
expect(trustedFunc).toHaveBeenCalled();
expect(ensureTrustedFuncReadyFunc).toHaveBeenCalledTimes(0);
primary.resolve(new BasicWE(2));
await disjoint();
expect(primaryFunc).toHaveBeenCalled();
expect(result).resolves.toEqual(new BasicWE(2));
expect(av.primaryPromise).toBe(null);
expect(av.trustedPromise).toBe(trusted.promise);
expect(av.trustedStatus).toBe('verifying');
expect(ensureTrustedFuncReadyFunc).toHaveBeenCalled();
ensureTrustedFuncReady.resolve();
await disjoint();
expect(ensureTrustedFuncReadyFunc).toHaveBeenCalled();
expect(av.primaryPromise).toBe(null);
expect(av.trustedPromise).toBe(trusted.promise);
expect(av.trustedStatus).toBe('verifying');
expect(trustedFunc).toHaveBeenCalled();
expect(verifyFunc).toHaveBeenCalledTimes(0);
trusted.resolve(new BasicWE(2));
await disjoint();
@ -265,10 +273,11 @@ describe('fetchAndVerifyIfNeeded tests', () => {
expect(av.trustedPromise).toBe(trusted.promise);
expect(av.trustedStatus).toBe('verifying');
expect(verifyFunc).toHaveBeenCalled();
verify.resolve(true);
await disjoint();
expect(verifyFunc).toHaveBeenCalled();
expect(verifyFunc).toHaveBeenCalledWith(new BasicWE(2), new BasicWE(2));
expect(av.primaryPromise).toBe(null);
expect(av.trustedPromise).toBe(trusted.promise);
expect(av.trustedStatus).toBe('verified');
@ -278,5 +287,9 @@ describe('fetchAndVerifyIfNeeded tests', () => {
expect(ensureTrustedFuncReadyFunc).toHaveBeenCalledTimes(1);
expect(verifyFunc).toHaveBeenCalledTimes(1);
});
/* test('nothing before, primary with value, then trusted with null', async () => { */
/* expect(false).toBe(true); */
/* }); */
// Make sure to do try/catch errors
});

View File

@ -187,9 +187,11 @@ export class AutoVerifier<T> {
// eslint-disable-next-line no-async-promise-executor
async (resolve: (result: T | null) => void, reject: (error: Error) => void) => {
let resolved = false;
/* istanbul ignore next */
const fetchId = debug && `v#${this.verifierId} f#${uuid.v4().slice(undefined, 4)}`;
try {
if (this.primaryPromise === null) {
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': created primary promise');
this.primaryPromise = this.primaryFunc();
}
@ -197,6 +199,7 @@ export class AutoVerifier<T> {
// pre-fetch the trusted result while we fetch the primary result
if (!lazyVerify && this.trustedStatus === 'none') {
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ": created trusted promise, set to 'fetching'");
this.trustedStatus = 'fetching';
this.trustedPromise = this.trustedFunc();
@ -205,15 +208,18 @@ export class AutoVerifier<T> {
const primaryResult = await this.primaryPromise;
if (this.primaryPromise === origPrimaryPromise) {
// reset the primary promise so we create a new one next time
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': reset the primary promise for next time');
this.primaryPromise = null;
}
if (primaryResult) {
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': resolving with primary result');
resolve(primaryResult);
resolved = true;
if (lazyVerify || this.trustedStatus === 'verified') {
/* istanbul ignore next */
if (debug)
LOG.debug(fetchId + ': not waiting on trusted promise', {
lazyVerify,
@ -227,6 +233,7 @@ export class AutoVerifier<T> {
if (this.trustedStatus === 'none') {
// try to re-fetch the trusted result
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ": creating trusted result (since status is 'none'");
this.trustedStatus = 'fetching';
this.trustedPromise = this.trustedFunc();
@ -240,6 +247,7 @@ export class AutoVerifier<T> {
// no one has started verifying the trusted yet
this.trustedStatus = 'verifying';
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': verifying... (awaiting trustedPromise)');
await this.ensureTrustedFuncReady();
// if (debug) LOG.debug(fetchId + ': verifying...');
@ -251,11 +259,10 @@ export class AutoVerifier<T> {
if (this.trustedPromise !== origTrustedPromise) {
// we've been invalidated while we were waiting for the trusted result!
// TODO: This happens when a socket fetch is sent before the socket is connected to.
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': unverified during fetch!', new Error());
if (debug)
LOG.debug(fetchId + ': trustedPromise now: ', {
trustedPromise: this.trustedPromise,
});
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': trustedPromise now: ', { trustedPromise: this.trustedPromise });
console.warn(
'RARE ALERT: we got unverified while trying to fetch a trusted promise for verification!',
new Error(),
@ -277,10 +284,12 @@ export class AutoVerifier<T> {
if (trustedResult !== null && primaryUpToDate) {
// we got a good trusted result and the primary data has been updated
// to reflect the trusted data (or already reflects it).
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': verified successfully.');
this.trustedStatus = 'verified';
} else {
// we have to re-fetch the trusted promise again next fetch
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': needs trusted promise re-fetched next time');
this.trustedStatus = 'none';
}
@ -293,6 +302,7 @@ export class AutoVerifier<T> {
if (!resolved) {
// removed 01/09/2021 pretty sure should not be here... && trustedResult
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': resolving with trusted result');
resolve(trustedResult);
resolved = true;
@ -302,6 +312,7 @@ export class AutoVerifier<T> {
// await the same trusted promise and return its result if we didn't get a result
// from the primary source.
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': waiting on result of a different verifier...');
// note: Promises that have already resolved will return the same value when awaited again :)
@ -310,22 +321,23 @@ export class AutoVerifier<T> {
if (this.trustedPromise !== origTrustedPromise) {
// we've been invalidated while we were waiting for the trusted result!
/* istanbul ignore next */
if (debug)
LOG.debug(
fetchId +
': got unverified while waiting on the result of a different verifier!',
new Error(),
);
console.warn(
'ULTRA RARE ALERT: we got unverified while awaiting a trusted promise another path was verifying!',
);
console.warn(
'ULTRA RARE ALERT: we got unverified while awaiting a trusted promise another path was verifying!',
);
await tryResolveTrustedPromise();
return;
}
if (!resolved) {
if (debug)
LOG.debug(fetchId + ': resolving with trusted result of different verifier');
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': resolving with trusted result of different verifier');
resolve(trustedResult);
resolved = true;
}
@ -333,6 +345,7 @@ export class AutoVerifier<T> {
} else {
// we are all up to date, make sure to resolve if primaryResult is null
if (!resolved) {
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': no trusted promise, resolving with null');
resolve(null);
resolved = true;
@ -343,11 +356,13 @@ export class AutoVerifier<T> {
} catch (e: unknown) {
this.unverify();
if (!resolved) {
/* istanbul ignore next */
if (debug) LOG.debug(fetchId + ': error during fetch', e);
// eslint-disable-next-line prefer-promise-reject-errors
reject(e as Error);
resolved = true;
} else {
/* istanbul ignore next */
if (debug)
LOG.debug(
fetchId +