verifyFunc rejection tests

This commit is contained in:
Michael Peters 2022-10-19 22:32:10 -07:00
parent 46e0d4c1a7
commit d688508e5d

View File

@ -186,6 +186,10 @@ describe('fetchAndVerifyIfNeeded tests', () => {
}
}
// this function makes it easier to do concurrent request
// although its naming can make stuff a bit confusing depending on the situation
// a means the 1st function call for each func AND the promise of the 1st fetchAndVerifyIfNeeded
// b means the 2nd function call for each func AND the promise of the 2nd fetchAndVerifyIfNeeded
function fetchAndVerifyIfNeededManually<T>(
av: AutoVerifier<T>,
nextPrimary: () => ManualPromise<T | null>,
@ -209,8 +213,9 @@ describe('fetchAndVerifyIfNeeded tests', () => {
resultPromise: av.fetchAndVerifyIfNeeded(lazyVerify),
}
state.resultPromise.then((value: T | null) => { state.result = value; });
state.resultPromise.catch((value: Error) => { console.log('caught', value); state.rejection = value; });
state.resultPromise
.then((value: T | null) => { state.result = value; })
.catch((value: Error) => { state.rejection = value; });
return state;
}
@ -727,6 +732,64 @@ describe('fetchAndVerifyIfNeeded tests', () => {
expect(verifyFunc).toHaveBeenCalledTimes(0);
});
test('primary null, then trusted with value, verifyFunc rejects - cache miss, return from server, verify failed', async () => {
const {
nextPrimary, nextTrusted, nextVerify,
primaryFunc, trustedFunc, verifyFunc
} = getManualsAndMocks();
const primary = nextPrimary();
const trusted = nextTrusted();
const verify = nextVerify();
const av = new AutoVerifier(primaryFunc, trustedFunc, verifyFunc);
const resultPromise = av.fetchAndVerifyIfNeeded();
let result: BasicWE | null | undefined = undefined;
let rejection: unknown | undefined = undefined;
resultPromise
.then(value => { result = value; })
.catch(value => { rejection = value; });
expect(av.primaryPromise).toBe(primary.promise);
expect(av.trustedPromise).toBe(trusted.promise);
expect(av.trustedStatus).toBe('fetching');
expect(primaryFunc).toHaveBeenCalled();
expect(trustedFunc).toHaveBeenCalled();
primary.resolve(null);
await disjoint();
expect(av.primaryPromise).toBe(null);
expect(av.trustedPromise).toBe(trusted.promise);
expect(av.trustedStatus).toBe('verifying');
expect(verifyFunc).toHaveBeenCalledTimes(0);
trusted.resolve(new BasicWE(2));
await disjoint();
expect(verifyFunc).toHaveBeenCalledWith(null, new BasicWE(2));
expect(av.primaryPromise).toBe(null);
expect(av.trustedPromise).toBe(trusted.promise);
expect(av.trustedStatus).toBe('verifying');
expect(result).toBeUndefined();
expect(rejection).toBeUndefined();
verify.reject(new Error('rejection'))
await disjoint();
expect(result).toBeUndefined();
expect(rejection).toBeDefined();
expect(av.primaryPromise).toBe(null);
expect(av.trustedPromise).toBe(null);
expect(av.trustedStatus).toBe('none');
await disjoint(); // sanity check
expect(primaryFunc).toHaveBeenCalledTimes(1);
expect(trustedFunc).toHaveBeenCalledTimes(1);
expect(verifyFunc).toHaveBeenCalledTimes(1);
});
test('ab, a: primary with value, b: primary dedup, ab: trusted dedup with value', async () => {
const {
nextPrimary, nextTrusted, nextVerify,
@ -946,7 +1009,6 @@ describe('fetchAndVerifyIfNeeded tests', () => {
await disjoint(); // sanity check
// Even though there were two fetchAnd... calls, they were deduped such that each func was only called once
expect(primaryFunc).toHaveBeenCalledTimes(1);
expect(trustedFunc).toHaveBeenCalledTimes(1);
expect(verifyFunc).toHaveBeenCalledTimes(1);
@ -1169,7 +1231,7 @@ describe('fetchAndVerifyIfNeeded tests', () => {
expect(av.trustedPromise).toBe(a.trusted.promise);
expect(av.trustedStatus).toBe('verifying');
a.trusted.reject(new Error('rejected'));
a.trusted.reject(new Error('rejection'));
av.unverify()
expect(av.primaryPromise).toBe(null);
@ -1392,6 +1454,67 @@ describe('fetchAndVerifyIfNeeded tests', () => {
expect(trustedFunc).toHaveBeenCalledTimes(1);
expect(verifyFunc).toHaveBeenCalledTimes(1);
});
test('ab: a: primary with null, b: primary dedup, ab: verifyFunc false, ab: resolve with trusted', async () => {
const {
nextPrimary, nextTrusted, nextVerify,
primaryFunc, trustedFunc, verifyFunc
} = getManualsAndMocks();
const av = new AutoVerifier(primaryFunc, trustedFunc, verifyFunc);
const a = fetchAndVerifyIfNeededManually(av, nextPrimary, nextTrusted, nextVerify);
expect(av.primaryPromise).toBe(a.primary.promise);
expect(av.trustedPromise).toBe(a.trusted.promise);
expect(av.trustedStatus).toBe('fetching');
expect(primaryFunc).toHaveBeenCalled();
expect(trustedFunc).toHaveBeenCalled();
const b = fetchAndVerifyIfNeededManually(av, nextPrimary, nextTrusted, nextVerify);
expect(av.primaryPromise).toBe(a.primary.promise); // doesn't change from a
expect(av.trustedPromise).toBe(a.trusted.promise); // doesn't change from a
expect(av.trustedStatus).toBe('fetching');
a.primary.resolve(null);
await disjoint();
expect(av.primaryPromise).toBe(null);
expect(av.trustedPromise).toBe(a.trusted.promise);
expect(av.trustedStatus).toBe('verifying');
expect(verifyFunc).toHaveBeenCalledTimes(0);
a.trusted.resolve(new BasicWE(2));
await disjoint();
expect(verifyFunc).toHaveBeenCalledWith(null, new BasicWE(2));
expect(av.primaryPromise).toBe(null);
expect(av.trustedPromise).toBe(a.trusted.promise);
expect(av.trustedStatus).toBe('verifying');
expect(a.result).toBeUndefined();
expect(b.result).toBeUndefined();
a.verify.reject(new Error('rejection'))
await disjoint();
expect(a.result).toBeUndefined();
expect(b.result).toBeUndefined();
expect(a.rejection).toBeDefined();
expect(b.rejection).toBeDefined();
expect(av.primaryPromise).toBe(null);
expect(av.trustedPromise).toBe(null);
expect(av.trustedStatus).toBe('none');
await disjoint(); // sanity check
// Even though there were two fetchAnd... calls, they were deduped such that each func was only called once
expect(primaryFunc).toHaveBeenCalledTimes(1);
expect(trustedFunc).toHaveBeenCalledTimes(1);
expect(verifyFunc).toHaveBeenCalledTimes(1);
});
// TODO: Why not have fetcher and a simple dedup wrapper to remove some complexity from this function?
// This would likely make it possible to get rid of the "else" block in tryResolveTrustedPromise
// Make sure it would work properly for retry functionality
@ -1400,7 +1523,6 @@ describe('fetchAndVerifyIfNeeded tests', () => {
// Make sure to do try/catch errors/rejections, verification failures, unverifies in the middle
// Fetching after verified doesn't re-fetch trusted
// Unverify during verify w/ dedups
// verifyFunc returns false
// verifyFunc rejects
// not possible (and therefore not tested) list