From f55b22e195ff0dfaf117aaef2a0fcc51fe0058c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Sat, 29 Feb 2020 18:45:47 +0100 Subject: add assertResources sanitizer to cli/js/ unit tests (#4161) --- cli/js/test_util.ts | 57 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 13 deletions(-) (limited to 'cli/js/test_util.ts') diff --git a/cli/js/test_util.ts b/cli/js/test_util.ts index b8ae3ca93..6f52c01df 100644 --- a/cli/js/test_util.ts +++ b/cli/js/test_util.ts @@ -106,6 +106,22 @@ function normalizeTestPermissions(perms: TestPermissions): Permissions { }; } +// Wrap `TestFunction` in additional assertion that makes sure +// the test case does not "leak" resources - ie. resource table after +// the test has exactly the same contents as before the test. +function assertResources(fn: Deno.TestFunction): Deno.TestFunction { + return async function(): Promise { + const preResources = Deno.resources(); + await fn(); + const postResources = Deno.resources(); + const msg = `Test case is leaking resources. +Before: ${JSON.stringify(preResources, null, 2)} +After: ${JSON.stringify(postResources, null, 2)}`; + + assertEquals(preResources, postResources, msg); + }; +} + export function testPerm(perms: TestPermissions, fn: Deno.TestFunction): void { const normalizedPerms = normalizeTestPermissions(perms); @@ -115,7 +131,7 @@ export function testPerm(perms: TestPermissions, fn: Deno.TestFunction): void { return; } - Deno.test(fn); + Deno.test(fn.name, assertResources(fn)); } export function test(fn: Deno.TestFunction): void { @@ -171,6 +187,24 @@ export async function parseUnitTestOutput( return { actual, expected, resultOutput: result }; } +export interface ResolvableMethods { + resolve: (value?: T | PromiseLike) => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + reject: (reason?: any) => void; +} + +export type Resolvable = Promise & ResolvableMethods; + +export function createResolvable(): Resolvable { + let methods: ResolvableMethods; + const promise = new Promise((resolve, reject): void => { + methods = { resolve, reject }; + }); + // TypeScript doesn't know that the Promise callback occurs synchronously + // therefore use of not null assertion (`!`) + return Object.assign(promise, methods!) as Resolvable; +} + test(function permissionsMatches(): void { assert( permissionsMatch( @@ -265,28 +299,25 @@ testPerm({ read: true }, async function parsingUnitTestOutput(): Promise { let result; // This is an example of a successful unit test output. - result = await parseUnitTestOutput( - await Deno.open(`${testDataPath}/unit_test_output1.txt`), - false - ); + const f1 = await Deno.open(`${testDataPath}/unit_test_output1.txt`); + result = await parseUnitTestOutput(f1, false); assertEquals(result.actual, 96); assertEquals(result.expected, 96); + f1.close(); // This is an example of a silently dying unit test. - result = await parseUnitTestOutput( - await Deno.open(`${testDataPath}/unit_test_output2.txt`), - false - ); + const f2 = await Deno.open(`${testDataPath}/unit_test_output2.txt`); + result = await parseUnitTestOutput(f2, false); assertEquals(result.actual, undefined); assertEquals(result.expected, 96); + f2.close(); // This is an example of compiling before successful unit tests. - result = await parseUnitTestOutput( - await Deno.open(`${testDataPath}/unit_test_output3.txt`), - false - ); + const f3 = await Deno.open(`${testDataPath}/unit_test_output3.txt`); + result = await parseUnitTestOutput(f3, false); assertEquals(result.actual, 96); assertEquals(result.expected, 96); + f3.close(); // Check what happens on empty output. const f = new Deno.Buffer(new TextEncoder().encode("\n\n\n")); -- cgit v1.2.3