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

Implement expandGlob() #617

Merged
merged 20 commits into from
Oct 2, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Prev Previous commit
Next Next commit
testing: Refactor to resemble prettier
Should help later when extracting common functionality to expandGlob(),
like exclusion. Makes findTestModules() an async generator.
  • Loading branch information
nayeemrmn committed Sep 28, 2019
commit 47291070e0c1dc34dbe7d658bbde5fba16ce6c13
74 changes: 37 additions & 37 deletions testing/runner.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
#!/usr/bin/env -S deno -A
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { parse } from "../flags/mod.ts";
import {
WalkInfo,
expandGlobSync,
glob,
ExpandGlobOptions
} from "../fs/mod.ts";
import { WalkInfo, expandGlob, glob, ExpandGlobOptions } from "../fs/mod.ts";
import { isWindows } from "../fs/path/constants.ts";
import { isAbsolute, join } from "../fs/path/mod.ts";
import { RunTestsOptions, runTests } from "./mod.ts";
Expand Down Expand Up @@ -64,26 +59,20 @@ function filePathToUrl(path: string): string {
return `file:https://${isWindows ? "/" : ""}${path.replace(/\\/g, "/")}`;
}

function expandDirectory(dir: string, options: ExpandGlobOptions): WalkInfo[] {
return DIR_GLOBS.flatMap((s: string): WalkInfo[] => [
...expandGlobSync(s, { ...options, root: dir })
]);
}

/**
* Given a list of globs or URLs to include and exclude and a root directory
* from which to expand relative globs, return a list of URLs
* from which to expand relative globs, yield a list of URLs
* (file: or remote) that should be imported for the test runner.
*/
export async function findTestModules(
export async function* findTestModules(
includeModules: string[],
excludeModules: string[],
root: string = cwd()
): Promise<string[]> {
): AsyncIterableIterator<string> {
const [includePaths, includeUrls] = partition(includeModules, isRemoteUrl);
const [excludePaths, excludeUrls] = partition(excludeModules, isRemoteUrl);

const expandGlobOpts = {
const expandGlobOpts: ExpandGlobOptions = {
root,
extended: true,
globstar: true,
Expand All @@ -99,25 +88,36 @@ export async function findTestModules(
const excludeUrlPatterns = excludeUrls.map(
(url: string): RegExp => RegExp(url)
);
const notExcludedPath = ({ filename }: WalkInfo): boolean =>
const shouldIncludePath = ({ filename }: WalkInfo): boolean =>
!excludePathPatterns.some((p: RegExp): boolean => !!filename.match(p));
const notExcludedUrl = (url: string): boolean =>
const shouldIncludeUrl = (url: string): boolean =>
!excludeUrlPatterns.some((p: RegExp): boolean => !!url.match(p));

const matchedPaths = includePaths
.flatMap((s: string): WalkInfo[] => [...expandGlobSync(s, expandGlobOpts)])
.filter(notExcludedPath)
.flatMap(({ filename, info }): string[] =>
info.isDirectory()
? expandDirectory(filename, { ...expandGlobOpts, includeDirs: false })
.filter(notExcludedPath)
.map(({ filename }): string => filename)
: [filename]
);
async function* expandDirectory(d: string): AsyncIterableIterator<string> {
for (const dirGlob of DIR_GLOBS) {
for await (const walkInfo of expandGlob(dirGlob, {
...expandGlobOpts,
root: d,
includeDirs: false
})) {
if (shouldIncludePath(walkInfo)) {
yield filePathToUrl(walkInfo.filename);
}
}
}
}

const matchedUrls = includeUrls.filter(notExcludedUrl);
for (const globString of includePaths) {
for await (const walkInfo of expandGlob(globString, expandGlobOpts)) {
if (walkInfo.info.isDirectory()) {
yield* expandDirectory(walkInfo.filename);
} else if (shouldIncludePath(walkInfo)) {
yield filePathToUrl(walkInfo.filename);
}
}
}

return [...matchedPaths.map(filePathToUrl), ...matchedUrls];
yield* includeUrls.filter(shouldIncludeUrl);
}

export interface RunTestModulesOptions extends RunTestsOptions {
Expand Down Expand Up @@ -162,9 +162,13 @@ export async function runTestModules({
skip = /^\s*$/,
disableLog = false
}: RunTestModulesOptions = {}): Promise<void> {
const testModuleUrls = await findTestModules(include, exclude);
let moduleCount = 0;
for await (const testModule of findTestModules(include, exclude)) {
await import(testModule);
moduleCount++;
}

if (testModuleUrls.length == 0) {
if (moduleCount == 0) {
const noneFoundMessage = "No matching test modules found.";
if (!allowNone) {
throw new DenoError(ErrorKind.NotFound, noneFoundMessage);
Expand All @@ -175,11 +179,7 @@ export async function runTestModules({
}

if (!disableLog) {
console.log(`Found ${testModuleUrls.length} matching test modules.`);
}

for (const url of testModuleUrls) {
await import(url);
console.log(`Found ${moduleCount} matching test modules.`);
}

await runTests({
Expand Down
29 changes: 23 additions & 6 deletions testing/runner_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,30 @@ import { test } from "./mod.ts";
import { findTestModules } from "./runner.ts";
import { isWindows } from "../fs/path/constants.ts";
import { assertEquals } from "../testing/asserts.ts";
const { cwd } = Deno;

function urlToFilePath(url: URL): string {
// Since `new URL('file:https:///C:/a').pathname` is `/C:/a`, remove leading slash.
return url.pathname.slice(url.protocol == "file:" && isWindows ? 1 : 0);
}

async function findTestModulesArray(
include: string[],
exclude: string[],
root: string = cwd()
): Promise<string[]> {
const result = [];
for await (const testModule of findTestModules(include, exclude, root)) {
result.push(testModule);
}
return result;
}

const TEST_DATA_URL = new URL("testdata", import.meta.url);
const TEST_DATA_PATH = urlToFilePath(TEST_DATA_URL);

test(async function findTestModulesDir1(): Promise<void> {
const urls = await findTestModules(["."], [], TEST_DATA_PATH);
const urls = await findTestModulesArray(["."], [], TEST_DATA_PATH);
assertEquals(urls.sort(), [
`${TEST_DATA_URL}/bar_test.js`,
`${TEST_DATA_URL}/foo_test.ts`,
Expand All @@ -27,7 +40,7 @@ test(async function findTestModulesDir1(): Promise<void> {
});

test(async function findTestModulesDir2(): Promise<void> {
const urls = await findTestModules(["subdir"], [], TEST_DATA_PATH);
const urls = await findTestModulesArray(["subdir"], [], TEST_DATA_PATH);
assertEquals(urls.sort(), [
`${TEST_DATA_URL}/subdir/bar_test.js`,
`${TEST_DATA_URL}/subdir/foo_test.ts`,
Expand All @@ -37,7 +50,11 @@ test(async function findTestModulesDir2(): Promise<void> {
});

test(async function findTestModulesGlob(): Promise<void> {
const urls = await findTestModules(["**/*_test.{js,ts}"], [], TEST_DATA_PATH);
const urls = await findTestModulesArray(
["**/*_test.{js,ts}"],
[],
TEST_DATA_PATH
);
assertEquals(urls.sort(), [
`${TEST_DATA_URL}/bar_test.js`,
`${TEST_DATA_URL}/foo_test.ts`,
Expand All @@ -47,7 +64,7 @@ test(async function findTestModulesGlob(): Promise<void> {
});

test(async function findTestModulesExcludeDir(): Promise<void> {
const urls = await findTestModules(["."], ["subdir"], TEST_DATA_PATH);
const urls = await findTestModulesArray(["."], ["subdir"], TEST_DATA_PATH);
assertEquals(urls.sort(), [
`${TEST_DATA_URL}/bar_test.js`,
`${TEST_DATA_URL}/foo_test.ts`,
Expand All @@ -57,7 +74,7 @@ test(async function findTestModulesExcludeDir(): Promise<void> {
});

test(async function findTestModulesExcludeGlob(): Promise<void> {
const urls = await findTestModules(["."], ["**/foo*"], TEST_DATA_PATH);
const urls = await findTestModulesArray(["."], ["**/foo*"], TEST_DATA_PATH);
assertEquals(urls.sort(), [
`${TEST_DATA_URL}/bar_test.js`,
`${TEST_DATA_URL}/subdir/bar_test.js`,
Expand All @@ -73,6 +90,6 @@ test(async function findTestModulesRemote(): Promise<void> {
"https://example.com/colors_test.ts",
"http:https://example.com/printf_test.ts"
];
const matches = await findTestModules(urls, []);
const matches = await findTestModulesArray(urls, []);
assertEquals(matches, urls);
});