Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: test runner #516

Merged
merged 20 commits into from
Aug 15, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions testing/runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env deno -A
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { parse } from "../flags/mod.ts";
import { glob, walk } from "../fs/mod.ts";
import { runTests } from "./mod.ts";
const { args, cwd } = Deno;

// TODO: settle on list of default globs
bartlomieju marked this conversation as resolved.
Show resolved Hide resolved
const DEFAULT_GLOBS = ["**/*_test.ts", "**/*_test.js"];

// TODO: upgrade it
/* eslint-disable max-len */
function showHelp(): void {
console.log(`deno test-runner
Test runner

USAGE:
deno -A https://deno.land/std/testing/runner.ts [OPTIONS]

OPTIONS:
-q, --quiet Don't show output from test cases
-f, --failfast Stop test suite on first error
-g, --glob <PATH...> List of globs for test files, defaults to: **/*_test.ts,**/*_test.js
`);
}
/* eslint-enable max-len */

async function main(): Promise<void> {
const parsedArgs = parse(args.slice(1), {
boolean: ["quiet", "failfast", "help"],
string: ["glob"],
alias: {
help: ["h"],
quiet: ["q"],
failfast: ["f"],
glob: ["g"]
}
});

if (parsedArgs.help) {
return showHelp();
}

let fileGlobs;
if (parsedArgs.glob) {
fileGlobs = (parsedArgs.glob as string).split(",");
} else {
fileGlobs = DEFAULT_GLOBS;
}

const filesIterator = walk(cwd(), {
bartlomieju marked this conversation as resolved.
Show resolved Hide resolved
match: fileGlobs.map(glob)
});

const foundTestFiles: string[] = [];
for await (const { filename } of filesIterator) {
foundTestFiles.push(filename);
}

console.log(`Found ${foundTestFiles.length} matching files.`);

for (const filename of foundTestFiles) {
await import(filename);
}

await runTests({
exitOnFail: !!parsedArgs.failfast,
disableLog: !!parsedArgs.quiet
});
bartlomieju marked this conversation as resolved.
Show resolved Hide resolved
}

main();
ry marked this conversation as resolved.
Show resolved Hide resolved
77 changes: 77 additions & 0 deletions testing/runner_util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
async function writeAll(buffer: Deno.Buffer, arr: Uint8Array): Promise<void> {
let bytesWritten = 0;
while (bytesWritten < arr.length) {
try {
const nwritten = await buffer.write(arr.subarray(bytesWritten));
bytesWritten += nwritten;
} catch {
return;
}
}
}

// TODO(bartlomieju): Copied from //deno/js/xeval.ts
// this module one supposed to be moved to std lib anyway
// Read from reader until EOF and emit string chunks separated
// by the given delimiter.
export async function* chunks(
reader: Deno.Reader,
delim: string
): AsyncIterableIterator<string> {
const inputBuffer = new Deno.Buffer();
const inspectArr = new Uint8Array(1024);
const encoder = new TextEncoder();
const decoder = new TextDecoder();
// Avoid unicode problems
const delimArr = encoder.encode(delim);

// Record how far we have gone with delimiter matching.
let nextMatchIndex = 0;
while (true) {
const rr = await reader.read(inspectArr);
if (rr.nread < 0) {
// Silently fail.
break;
}
const sliceRead = inspectArr.subarray(0, rr.nread);
// Remember how far we have scanned through inspectArr.
let nextSliceStartIndex = 0;
for (let i = 0; i < sliceRead.length; i++) {
if (sliceRead[i] == delimArr[nextMatchIndex]) {
// One byte matches with delimiter, move 1 step forward.
nextMatchIndex++;
} else {
// Match delimiter failed. Start from beginning.
nextMatchIndex = 0;
}
// A complete match is found.
if (nextMatchIndex === delimArr.length) {
nextMatchIndex = 0; // Reset delim match index.
const sliceToJoin = sliceRead.subarray(nextSliceStartIndex, i + 1);
// Record where to start next chunk when a subsequent match is found.
nextSliceStartIndex = i + 1;
// Write slice to buffer before processing, since potentially
// part of the delimiter is stored in the buffer.
await writeAll(inputBuffer, sliceToJoin);

let readyBytes = inputBuffer.bytes();
inputBuffer.reset();
// Remove delimiter from buffer bytes.
readyBytes = readyBytes.subarray(
0,
readyBytes.length - delimArr.length
);
let readyChunk = decoder.decode(readyBytes);
yield readyChunk;
}
}
// Write all unprocessed chunk to buffer for future inspection.
await writeAll(inputBuffer, sliceRead.subarray(nextSliceStartIndex));
if (rr.eof) {
// Flush the remainder unprocessed chunk.
const lastChunk = inputBuffer.toString();
yield lastChunk;
break;
}
}
}