as-test 0.4.4 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/README.md +196 -82
- package/as-test.config.schema.json +137 -0
- package/assembly/coverage.ts +19 -0
- package/assembly/index.ts +172 -85
- package/assembly/src/expectation.ts +263 -199
- package/assembly/src/log.ts +1 -9
- package/assembly/src/suite.ts +61 -25
- package/assembly/src/tests.ts +2 -0
- package/assembly/util/wipc.ts +286 -0
- package/bin/build.js +86 -41
- package/bin/index.js +337 -68
- package/bin/init.js +441 -183
- package/bin/reporter.js +1 -1
- package/bin/reporters/default.js +379 -0
- package/bin/reporters/types.js +1 -0
- package/bin/run.js +882 -194
- package/bin/types.js +14 -7
- package/bin/util.js +54 -3
- package/package.json +34 -16
- package/transform/lib/builder.js +169 -169
- package/transform/lib/builder.js.map +1 -1
- package/transform/lib/coverage.js +47 -1
- package/transform/lib/coverage.js.map +1 -1
- package/transform/lib/index.js +70 -0
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/location.js +20 -0
- package/transform/lib/location.js.map +1 -0
- package/transform/lib/log.js +118 -0
- package/transform/lib/log.js.map +1 -0
- package/transform/lib/mock.js +2 -2
- package/transform/lib/mock.js.map +1 -1
- package/transform/lib/util.js +3 -3
- package/transform/lib/util.js.map +1 -1
- package/.github/workflows/as-test.yml +0 -26
- package/.prettierrc +0 -3
- package/as-test.config.json +0 -19
- package/assembly/__tests__/array.spec.ts +0 -25
- package/assembly/__tests__/math.spec.ts +0 -16
- package/assembly/__tests__/mock.spec.ts +0 -22
- package/assembly/__tests__/mock.ts +0 -7
- package/assembly/__tests__/sleep.spec.ts +0 -28
- package/assembly/tsconfig.json +0 -97
- package/assets/img/screenshot.png +0 -0
- package/cli/build.ts +0 -117
- package/cli/index.ts +0 -190
- package/cli/init.ts +0 -247
- package/cli/reporter.ts +0 -1
- package/cli/run.ts +0 -286
- package/cli/tsconfig.json +0 -9
- package/cli/types.ts +0 -29
- package/cli/util.ts +0 -65
- package/run/package.json +0 -27
- package/tests/array.run.js +0 -7
- package/tests/math.run.js +0 -7
- package/tests/mock.run.js +0 -14
- package/tests/sleep.run.js +0 -7
- package/transform/src/builder.ts +0 -1474
- package/transform/src/coverage.ts +0 -580
- package/transform/src/index.ts +0 -73
- package/transform/src/linker.ts +0 -41
- package/transform/src/mock.ts +0 -163
- package/transform/src/range.ts +0 -12
- package/transform/src/types.ts +0 -35
- package/transform/src/util.ts +0 -81
- package/transform/src/visitor.ts +0 -744
- package/transform/tsconfig.json +0 -10
package/cli/run.ts
DELETED
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk";
|
|
2
|
-
import { exec } from "child_process";
|
|
3
|
-
import { glob } from "glob";
|
|
4
|
-
import { formatTime, getExec, loadConfig } from "./util.js";
|
|
5
|
-
import * as path from "path";
|
|
6
|
-
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
7
|
-
import { diff } from "typer-diff";
|
|
8
|
-
import gradient from "gradient-string";
|
|
9
|
-
|
|
10
|
-
const CONFIG_PATH = path.join(process.cwd(), "./as-test.config.json");
|
|
11
|
-
const version = "0.4.0";
|
|
12
|
-
export async function run() {
|
|
13
|
-
const reports: any[] = [];
|
|
14
|
-
const config = loadConfig(CONFIG_PATH);
|
|
15
|
-
const inputFiles = await glob(config.input);
|
|
16
|
-
console.log(
|
|
17
|
-
chalk.dim("Running tests using " + config.runOptions.runtime.name + ""),
|
|
18
|
-
);
|
|
19
|
-
|
|
20
|
-
const command = config.runOptions.runtime.run.split(" ")[0];
|
|
21
|
-
let execPath = getExec(command);
|
|
22
|
-
|
|
23
|
-
if (!execPath) {
|
|
24
|
-
console.log(
|
|
25
|
-
`${chalk.bgRed(" ERROR ")}${chalk.dim(":")} could not locate ${command} in PATH variable!`,
|
|
26
|
-
);
|
|
27
|
-
process.exit(0);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (inputFiles.length) {
|
|
31
|
-
console.log(
|
|
32
|
-
"\n" +
|
|
33
|
-
gradient(["#87afff", "#3a5fcd"])
|
|
34
|
-
.multiline(` █████ ███████ ████████ ███████ ███████ ████████
|
|
35
|
-
██ ██ ██ ██ ██ ██ ██
|
|
36
|
-
███████ ███████ █████ ██ █████ ███████ ██
|
|
37
|
-
██ ██ ██ ██ ██ ██ ██
|
|
38
|
-
██ ██ ███████ ██ ███████ ███████ ██ `),
|
|
39
|
-
);
|
|
40
|
-
console.log(
|
|
41
|
-
chalk.dim(
|
|
42
|
-
`\n----------------------- v${version} -----------------------\n`,
|
|
43
|
-
),
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
for (const plugin of Object.keys(config.plugins)) {
|
|
48
|
-
if (!config.plugins[plugin]) continue;
|
|
49
|
-
console.log(
|
|
50
|
-
chalk.bgBlueBright(" PLUGIN ") +
|
|
51
|
-
" " +
|
|
52
|
-
chalk.dim(
|
|
53
|
-
"Using " + plugin.slice(0, 1).toUpperCase() + plugin.slice(1),
|
|
54
|
-
) +
|
|
55
|
-
"\n",
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
for (let i = 0; i < inputFiles.length; i++) {
|
|
60
|
-
const file = inputFiles[i];
|
|
61
|
-
const outFile = path.join(
|
|
62
|
-
config.outDir,
|
|
63
|
-
file.slice(file.lastIndexOf("/") + 1).replace(".ts", ".wasm"),
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
let cmd = config.runOptions.runtime.run.replace(command, execPath);
|
|
67
|
-
if (config.buildOptions.target == "bindings") {
|
|
68
|
-
cmd = config.runOptions.runtime.run.replace(command, execPath);
|
|
69
|
-
|
|
70
|
-
if (cmd.includes("<name>")) {
|
|
71
|
-
cmd = cmd.replace(
|
|
72
|
-
"<name>",
|
|
73
|
-
file
|
|
74
|
-
.slice(file.lastIndexOf("/") + 1)
|
|
75
|
-
.replace(".ts", "")
|
|
76
|
-
.replace(".spec", ""),
|
|
77
|
-
);
|
|
78
|
-
} else {
|
|
79
|
-
cmd = cmd.replace(
|
|
80
|
-
"<file>",
|
|
81
|
-
outFile
|
|
82
|
-
.replace("build", "tests")
|
|
83
|
-
.replace(".spec", "")
|
|
84
|
-
.replace(".wasm", ".run.js"),
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
} else {
|
|
88
|
-
cmd = cmd.replace("<file>", outFile);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const report = JSON.parse(
|
|
92
|
-
await (() => {
|
|
93
|
-
return new Promise<string>((res, _) => {
|
|
94
|
-
let stdout = "";
|
|
95
|
-
const io = exec(cmd);
|
|
96
|
-
io.stdout.pipe(process.stdout);
|
|
97
|
-
io.stderr.pipe(process.stderr);
|
|
98
|
-
io.stdout.on("data", (data: string) => {
|
|
99
|
-
stdout += readData(data);
|
|
100
|
-
});
|
|
101
|
-
io.stdout.on("close", () => {
|
|
102
|
-
res(stdout);
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
})(),
|
|
106
|
-
);
|
|
107
|
-
reports.push(report);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (config.logs && config.logs != "none") {
|
|
111
|
-
if (!existsSync(path.join(process.cwd(), config.logs))) {
|
|
112
|
-
mkdirSync(path.join(process.cwd(), config.logs));
|
|
113
|
-
}
|
|
114
|
-
writeFileSync(
|
|
115
|
-
path.join(process.cwd(), config.logs, "test.log.json"),
|
|
116
|
-
JSON.stringify(reports, null, 2),
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
const reporter = new Reporter(reports);
|
|
120
|
-
|
|
121
|
-
if (reporter.failed.length) {
|
|
122
|
-
console.log(chalk.dim("----------------- [FAILED] -------------------\n"));
|
|
123
|
-
for (const failed of reporter.failed) {
|
|
124
|
-
console.log(
|
|
125
|
-
`${chalk.bgRed(" FAIL ")} ${chalk.dim(failed.description)}\n`,
|
|
126
|
-
);
|
|
127
|
-
for (const test of failed.tests) {
|
|
128
|
-
const diffResult = diff(
|
|
129
|
-
JSON.stringify(test.left),
|
|
130
|
-
JSON.stringify(test.right),
|
|
131
|
-
);
|
|
132
|
-
let expected = "";
|
|
133
|
-
let received = chalk.dim(JSON.stringify(test.left));
|
|
134
|
-
for (const res of diffResult.diff) {
|
|
135
|
-
switch (res.type) {
|
|
136
|
-
case "correct": {
|
|
137
|
-
expected += chalk.dim(res.value);
|
|
138
|
-
continue;
|
|
139
|
-
}
|
|
140
|
-
case "extra": {
|
|
141
|
-
expected += chalk.red.strikethrough(res.value);
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
case "missing": {
|
|
145
|
-
expected += chalk.bgBlack(res.value);
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
case "wrong": {
|
|
149
|
-
expected += chalk.bgRed(res.value);
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
case "untouched": {
|
|
153
|
-
//received += chalk.bgBlackBright(res.value);
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
case "spacer": {
|
|
157
|
-
//received += chalk.bgBlackBright(res.value);
|
|
158
|
-
continue;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
if (test.verdict == "fail") {
|
|
163
|
-
console.log(`${chalk.dim("(expected) ->")} ${expected}`);
|
|
164
|
-
console.log(`${chalk.dim("(received) ->")} ${received}\n`);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
console.log(chalk.dim("----------------- [RESULTS] ------------------\n"));
|
|
171
|
-
|
|
172
|
-
process.stdout.write(chalk.bold("Files: "));
|
|
173
|
-
if (reporter.failedFiles) {
|
|
174
|
-
process.stdout.write(chalk.bold.red(reporter.failedFiles + " failed"));
|
|
175
|
-
} else {
|
|
176
|
-
process.stdout.write(chalk.bold.greenBright("0 failed"));
|
|
177
|
-
}
|
|
178
|
-
process.stdout.write(
|
|
179
|
-
", " + (reporter.failedFiles + reporter.passedFiles) + " total\n",
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
process.stdout.write(chalk.bold("Suites: "));
|
|
183
|
-
if (reporter.failedSuites) {
|
|
184
|
-
process.stdout.write(chalk.bold.red(reporter.failedSuites + " failed"));
|
|
185
|
-
} else {
|
|
186
|
-
process.stdout.write(chalk.bold.greenBright("0 failed"));
|
|
187
|
-
}
|
|
188
|
-
process.stdout.write(
|
|
189
|
-
", " + (reporter.failedSuites + reporter.passedSuites) + " total\n",
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
process.stdout.write(chalk.bold("Tests: "));
|
|
193
|
-
if (reporter.failedTests) {
|
|
194
|
-
process.stdout.write(chalk.bold.red(reporter.failedTests + " failed"));
|
|
195
|
-
} else {
|
|
196
|
-
process.stdout.write(chalk.bold.greenBright("0 failed"));
|
|
197
|
-
}
|
|
198
|
-
process.stdout.write(
|
|
199
|
-
", " + (reporter.failedTests + reporter.passedTests) + " total\n",
|
|
200
|
-
);
|
|
201
|
-
|
|
202
|
-
process.stdout.write(
|
|
203
|
-
chalk.bold("Time: ") + formatTime(reporter.time) + "\n",
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
if (reporter.failedFiles) process.exit(1);
|
|
207
|
-
process.exit(0);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
class Reporter {
|
|
211
|
-
public passedFiles = 0;
|
|
212
|
-
public failedFiles = 0;
|
|
213
|
-
|
|
214
|
-
public passedSuites = 0;
|
|
215
|
-
public failedSuites = 0;
|
|
216
|
-
|
|
217
|
-
public passedTests = 0;
|
|
218
|
-
public failedTests = 0;
|
|
219
|
-
|
|
220
|
-
public failed: any[] = [];
|
|
221
|
-
|
|
222
|
-
public time = 0.0;
|
|
223
|
-
constructor(reports: any[]) {
|
|
224
|
-
this.readReports(reports);
|
|
225
|
-
}
|
|
226
|
-
readReports(reports: any[]) {
|
|
227
|
-
for (const file of reports) {
|
|
228
|
-
this.readFile(file);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
readFile(file: any) {
|
|
232
|
-
let failed = false;
|
|
233
|
-
for (const suite of file) {
|
|
234
|
-
if (suite.verdict == "fail") {
|
|
235
|
-
failed = true;
|
|
236
|
-
this.failedSuites++;
|
|
237
|
-
} else {
|
|
238
|
-
this.passedSuites++;
|
|
239
|
-
}
|
|
240
|
-
this.time += suite.time.end - suite.time.start;
|
|
241
|
-
for (const subSuite of suite.suites) {
|
|
242
|
-
this.readSuite(subSuite);
|
|
243
|
-
}
|
|
244
|
-
for (const test of suite.tests) {
|
|
245
|
-
if (test.verdict == "fail") this.failed.push(suite);
|
|
246
|
-
this.readTest(test);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
if (failed) this.failedFiles++;
|
|
250
|
-
else this.passedFiles++;
|
|
251
|
-
}
|
|
252
|
-
readSuite(suite: any) {
|
|
253
|
-
if (suite.verdict == "fail") {
|
|
254
|
-
this.failedSuites++;
|
|
255
|
-
} else {
|
|
256
|
-
this.passedSuites++;
|
|
257
|
-
}
|
|
258
|
-
this.time += suite.time.end - suite.time.start;
|
|
259
|
-
for (const subSuite of suite.suites) {
|
|
260
|
-
this.readSuite(subSuite);
|
|
261
|
-
}
|
|
262
|
-
for (const test of suite.tests) {
|
|
263
|
-
if (test.verdict == "fail") this.failed.push(suite);
|
|
264
|
-
this.readTest(test);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
readTest(test: any) {
|
|
268
|
-
if (test.verdict == "fail") {
|
|
269
|
-
this.failedTests++;
|
|
270
|
-
} else {
|
|
271
|
-
this.passedTests++;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
function readData(data: string): string {
|
|
277
|
-
let out = "";
|
|
278
|
-
const start = data.indexOf("READ_LINE");
|
|
279
|
-
if (start >= 0) {
|
|
280
|
-
const slice = data.slice(start + 9);
|
|
281
|
-
const end = slice.indexOf("END_LINE");
|
|
282
|
-
out += slice.slice(0, end);
|
|
283
|
-
out += readData(slice);
|
|
284
|
-
}
|
|
285
|
-
return out;
|
|
286
|
-
}
|
package/cli/tsconfig.json
DELETED
package/cli/types.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export class Config {
|
|
2
|
-
input: string[] = ["./assembly/__tests__/*.spec.ts"];
|
|
3
|
-
outDir: string = "./build";
|
|
4
|
-
logs: string = "./logs";
|
|
5
|
-
config: string = "none";
|
|
6
|
-
plugins: {} = {
|
|
7
|
-
coverage: true,
|
|
8
|
-
};
|
|
9
|
-
buildOptions: BuildOptions = new BuildOptions();
|
|
10
|
-
runOptions: RunOptions = new RunOptions();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class Suite {
|
|
14
|
-
name: string = "";
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export class BuildOptions {
|
|
18
|
-
args: string[] = [];
|
|
19
|
-
target: string = "wasi";
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export class RunOptions {
|
|
23
|
-
runtime: Runtime = new Runtime();
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export class Runtime {
|
|
27
|
-
name: string = "wasmtime";
|
|
28
|
-
run: string = "wasmtime <file>";
|
|
29
|
-
}
|
package/cli/util.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "fs";
|
|
2
|
-
import { Config } from "./types.js";
|
|
3
|
-
import chalk from "chalk";
|
|
4
|
-
import { delimiter, join } from "path";
|
|
5
|
-
|
|
6
|
-
export function formatTime(ms: number): string {
|
|
7
|
-
if (ms < 0) {
|
|
8
|
-
throw new Error("Time should be a non-negative number.");
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// Convert milliseconds to microseconds
|
|
12
|
-
const us = ms * 1000;
|
|
13
|
-
|
|
14
|
-
const units: {
|
|
15
|
-
name: string;
|
|
16
|
-
divisor: number;
|
|
17
|
-
}[] = [
|
|
18
|
-
{ name: "μs", divisor: 1 },
|
|
19
|
-
{ name: "ms", divisor: 1000 },
|
|
20
|
-
{ name: "s", divisor: 1000 * 1000 },
|
|
21
|
-
{ name: "m", divisor: 60 * 1000 * 1000 },
|
|
22
|
-
{ name: "h", divisor: 60 * 60 * 1000 * 1000 },
|
|
23
|
-
{ name: "d", divisor: 24 * 60 * 60 * 1000 * 1000 },
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
for (let i = units.length - 1; i >= 0; i--) {
|
|
27
|
-
const unit = units[i]!;
|
|
28
|
-
if (us >= unit.divisor) {
|
|
29
|
-
const value = Math.round((us / unit.divisor) * 1000) / 1000;
|
|
30
|
-
return `${value}${unit.name}`;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return `${us}us`;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function loadConfig(CONFIG_PATH: string, warn: boolean = false): Config {
|
|
38
|
-
if (!existsSync(CONFIG_PATH)) {
|
|
39
|
-
if (warn)
|
|
40
|
-
console.log(
|
|
41
|
-
`${chalk.bgMagentaBright(" WARN ")}${chalk.dim(":")} Could not locate config file in the current directory! Continuing with default config.`,
|
|
42
|
-
);
|
|
43
|
-
return new Config();
|
|
44
|
-
} else {
|
|
45
|
-
return Object.assign(
|
|
46
|
-
new Config(),
|
|
47
|
-
JSON.parse(readFileSync(CONFIG_PATH).toString()),
|
|
48
|
-
) as Config;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function getExec(exec: string): string | null {
|
|
53
|
-
const PATH = process.env.PATH.split(delimiter);
|
|
54
|
-
|
|
55
|
-
for (const pathDir of PATH) {
|
|
56
|
-
const fullPath = join(
|
|
57
|
-
pathDir,
|
|
58
|
-
exec + (process.platform === "win32" ? ".exe" : ""),
|
|
59
|
-
);
|
|
60
|
-
if (existsSync(fullPath)) {
|
|
61
|
-
return fullPath;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return null;
|
|
65
|
-
}
|
package/run/package.json
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@as-test/run",
|
|
3
|
-
"version": "0.3.5",
|
|
4
|
-
"description": "Testing framework for AssemblyScript. Compatible with WASI or Bindings ",
|
|
5
|
-
"main": "./lib/index.js",
|
|
6
|
-
"author": "Jairus Tanaka",
|
|
7
|
-
"contributors": [],
|
|
8
|
-
"license": "MIT",
|
|
9
|
-
"scripts": {},
|
|
10
|
-
"devDependencies": {
|
|
11
|
-
"typescript": "^5.5.3"
|
|
12
|
-
},
|
|
13
|
-
"dependencies": {},
|
|
14
|
-
"repository": {
|
|
15
|
-
"type": "git",
|
|
16
|
-
"url": "git+https://github.com/JairusSW/as-test.git"
|
|
17
|
-
},
|
|
18
|
-
"keywords": [],
|
|
19
|
-
"bugs": {
|
|
20
|
-
"url": "https://github.com/JairusSW/as-test/issues"
|
|
21
|
-
},
|
|
22
|
-
"homepage": "https://github.com/JairusSW/as-test#readme",
|
|
23
|
-
"type": "module",
|
|
24
|
-
"publishConfig": {
|
|
25
|
-
"@JairusSW:registry": "https://npm.pkg.github.com"
|
|
26
|
-
}
|
|
27
|
-
}
|
package/tests/array.run.js
DELETED
package/tests/math.run.js
DELETED
package/tests/mock.run.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "fs";
|
|
2
|
-
import { instantiate } from "../build/mock.spec.js";
|
|
3
|
-
|
|
4
|
-
const binary = readFileSync("./build/mock.spec.wasm");
|
|
5
|
-
const module = new WebAssembly.Module(binary);
|
|
6
|
-
|
|
7
|
-
const exports = instantiate(module, {
|
|
8
|
-
"mock.spec": {},
|
|
9
|
-
mock: {
|
|
10
|
-
foo: () => {
|
|
11
|
-
return "buz";
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
});
|
package/tests/sleep.run.js
DELETED