ic-mops 0.30.0 → 0.31.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/commands/add.ts +12 -3
- package/commands/install.ts +2 -2
- package/commands/update.ts +30 -2
- package/dist/commands/add.js +11 -3
- package/dist/commands/install.js +2 -2
- package/dist/commands/update.js +27 -2
- package/dist/mops.d.ts +4 -2
- package/dist/mops.js +18 -4
- package/dist/package.json +1 -1
- package/dist/vessel.js +10 -10
- package/mops.ts +19 -5
- package/package.json +1 -1
- package/vessel.ts +10 -10
- package/dist/bench/$USER_BENCH_FILE.mo +0 -45
- package/dist/bench/bench-canister.mo +0 -57
- package/dist/commands/bench/$USER_BENCH_FILE.mo +0 -45
- package/dist/commands/bench/bench/$USER_BENCH_FILE.mo +0 -45
- package/dist/commands/bench/bench/bench-canister.mo +0 -57
- package/dist/commands/bench/bench-canister.mo +0 -85
- package/dist/commands/bench/declarations/bench/bench.did.d.ts +0 -6
- package/dist/commands/bench/declarations/bench/bench.did.js +0 -22
- package/dist/commands/bench/declarations/bench/index.d.ts +0 -2
- package/dist/commands/bench/declarations/bench/index.js +0 -30
- package/dist/commands/bench/declarations/main/index.d.ts +0 -2
- package/dist/commands/bench/declarations/main/index.js +0 -30
- package/dist/commands/bench/declarations/main/main.did.d.ts +0 -6
- package/dist/commands/bench/declarations/main/main.did.js +0 -242
- package/dist/commands/bench/declarations/storage/index.d.ts +0 -4
- package/dist/commands/bench/declarations/storage/index.js +0 -26
- package/dist/commands/bench/declarations/storage/storage.did.d.ts +0 -6
- package/dist/commands/bench/declarations/storage/storage.did.js +0 -34
- package/dist/commands/bench/user-bench.mo +0 -14
- package/dist/commands/bench.d.ts +0 -10
- package/dist/commands/bench.js +0 -214
- package/dist/commands/mmf1.d.ts +0 -21
- package/dist/commands/mmf1.js +0 -93
- package/dist/commands/test/reporter-files.d.ts +0 -10
- package/dist/commands/test/reporter-files.js +0 -48
- package/dist/commands/test/reporter-verbose.d.ts +0 -10
- package/dist/commands/test/reporter-verbose.js +0 -56
- package/dist/commands/test.d.ts +0 -4
- package/dist/commands/test.js +0 -186
- package/dist/declarations/bench/bench.did +0 -24
- package/dist/declarations/bench/bench.did.d.ts +0 -24
- package/dist/declarations/bench/bench.did.js +0 -24
- package/dist/declarations/bench/index.d.ts +0 -50
- package/dist/declarations/bench/index.js +0 -41
- package/dist/helpers/get-dfx-version.d.ts +0 -1
- package/dist/helpers/get-dfx-version.js +0 -9
- package/dist/helpers/get-moc-path.d.ts +0 -1
- package/dist/helpers/get-moc-path.js +0 -11
- package/dist/helpers/get-moc-version.d.ts +0 -1
- package/dist/helpers/get-moc-version.js +0 -7
- package/dist/out/cli.d.ts +0 -2
- package/dist/out/cli.js +0 -114581
- package/dist/parse-changelog.d.ts +0 -1
- package/dist/parse-changelog.js +0 -1435
- package/dist/test.d.ts +0 -1
- package/dist/test.js +0 -1411
package/dist/commands/bench.js
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import fs from 'node:fs';
|
|
4
|
-
// import os from 'node:os';
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
import { globSync } from 'glob';
|
|
7
|
-
import { markdownTable } from 'markdown-table';
|
|
8
|
-
import logUpdate from 'log-update';
|
|
9
|
-
import { getRootDir } from '../mops.js';
|
|
10
|
-
import { parallel } from '../parallel.js';
|
|
11
|
-
import { createActor } from '../declarations/bench/index.js';
|
|
12
|
-
import { absToRel } from './test/utils.js';
|
|
13
|
-
import { getMocVersion } from '../helpers/get-moc-version.js';
|
|
14
|
-
import { getDfxVersion } from '../helpers/get-dfx-version.js';
|
|
15
|
-
let ignore = [
|
|
16
|
-
'**/node_modules/**',
|
|
17
|
-
'**/.mops/**',
|
|
18
|
-
'**/.vessel/**',
|
|
19
|
-
'**/.git/**',
|
|
20
|
-
];
|
|
21
|
-
let globConfig = {
|
|
22
|
-
nocase: true,
|
|
23
|
-
ignore: ignore,
|
|
24
|
-
};
|
|
25
|
-
export async function bench(filter = '', options = {}) {
|
|
26
|
-
let rootDir = getRootDir();
|
|
27
|
-
let globStr = '**/bench?(mark)/**/*.bench.mo';
|
|
28
|
-
if (filter) {
|
|
29
|
-
globStr = `**/bench?(mark)/**/*${filter}*.mo`;
|
|
30
|
-
}
|
|
31
|
-
let files = globSync(path.join(rootDir, globStr), globConfig);
|
|
32
|
-
if (!files.length) {
|
|
33
|
-
if (filter) {
|
|
34
|
-
console.log(`No benchmark files found for filter '${filter}'`);
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
console.log('No *.bench.mo files found');
|
|
38
|
-
console.log('Put your benchmark files in \'bench\' directory in *.bench.mo files');
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
files.sort();
|
|
42
|
-
let benchDir = `${getRootDir()}/.mops/.bench/`;
|
|
43
|
-
fs.rmSync(benchDir, { recursive: true, force: true });
|
|
44
|
-
fs.mkdirSync(benchDir, { recursive: true });
|
|
45
|
-
console.log('Benchmark files:');
|
|
46
|
-
for (let file of files) {
|
|
47
|
-
console.log(chalk.gray(`• ${absToRel(file)}`));
|
|
48
|
-
}
|
|
49
|
-
console.log('');
|
|
50
|
-
console.log('='.repeat(50));
|
|
51
|
-
console.log('Starting dfx replica...');
|
|
52
|
-
startDfx(options.verbose);
|
|
53
|
-
let resultsByName = new Map();
|
|
54
|
-
// await parallel(os.cpus().length, files, async (file: string) => {
|
|
55
|
-
await parallel(1, files, async (file) => {
|
|
56
|
-
console.log('\n' + '—'.repeat(50));
|
|
57
|
-
console.log(`\nRunning ${chalk.gray(absToRel(file))}...`);
|
|
58
|
-
console.log('');
|
|
59
|
-
try {
|
|
60
|
-
let { schema, results } = await runBenchFile(file, options);
|
|
61
|
-
resultsByName.set(schema.name || absToRel(file), results);
|
|
62
|
-
}
|
|
63
|
-
catch (err) {
|
|
64
|
-
console.error('Unexpected error. Stopping dfx replica...');
|
|
65
|
-
stopDfx(options.verbose);
|
|
66
|
-
throw err;
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
if (options.save) {
|
|
70
|
-
console.log('Saving results to mops.bench.json...');
|
|
71
|
-
let json = {
|
|
72
|
-
version: 1,
|
|
73
|
-
moc: options.moc || getMocVersion(),
|
|
74
|
-
dfx: options.dfx || getDfxVersion(),
|
|
75
|
-
gc: options.gc || 'incremental',
|
|
76
|
-
results: {},
|
|
77
|
-
};
|
|
78
|
-
resultsByName.forEach((results, name) => {
|
|
79
|
-
json.results[name] = Array.from(results.entries());
|
|
80
|
-
});
|
|
81
|
-
fs.writeFileSync(path.join(rootDir, 'mops.bench.json'), JSON.stringify(json, (_, val) => {
|
|
82
|
-
if (typeof val === 'bigint') {
|
|
83
|
-
return Number(val);
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
return val;
|
|
87
|
-
}
|
|
88
|
-
}, 2));
|
|
89
|
-
}
|
|
90
|
-
console.log('Stopping dfx replica...');
|
|
91
|
-
stopDfx(options.verbose);
|
|
92
|
-
fs.rmSync(benchDir, { recursive: true, force: true });
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
function dfxJson(canisterName) {
|
|
96
|
-
return {
|
|
97
|
-
version: 1,
|
|
98
|
-
canisters: {
|
|
99
|
-
[canisterName]: {
|
|
100
|
-
type: 'motoko',
|
|
101
|
-
main: 'canister.mo',
|
|
102
|
-
args: '--force-gc --incremental-gc',
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
defaults: {
|
|
106
|
-
build: {
|
|
107
|
-
packtool: 'mops sources',
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
networks: {
|
|
111
|
-
local: {
|
|
112
|
-
type: 'ephemeral',
|
|
113
|
-
bind: '127.0.0.1:4947',
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
function startDfx(verbose = false) {
|
|
119
|
-
stopDfx(verbose);
|
|
120
|
-
let dir = path.join(getRootDir(), '.mops/.bench');
|
|
121
|
-
fs.writeFileSync(path.join(dir, 'dfx.json'), JSON.stringify(dfxJson(''), null, 2));
|
|
122
|
-
execSync('dfx start --background --clean', { cwd: dir, stdio: ['inherit', verbose ? 'inherit' : 'ignore', 'inherit'] });
|
|
123
|
-
}
|
|
124
|
-
function stopDfx(verbose = false) {
|
|
125
|
-
let dir = path.join(getRootDir(), '.mops/.bench');
|
|
126
|
-
execSync('dfx stop', { cwd: dir, stdio: ['pipe', verbose ? 'inherit' : 'ignore', 'pipe'] });
|
|
127
|
-
}
|
|
128
|
-
async function runBenchFile(file, options = {}) {
|
|
129
|
-
let rootDir = getRootDir();
|
|
130
|
-
let tempDir = path.join(rootDir, '.mops/.bench/', path.parse(file).name);
|
|
131
|
-
fs.mkdirSync(tempDir, { recursive: true });
|
|
132
|
-
let canisterName = Date.now().toString(36);
|
|
133
|
-
// prepare temp files
|
|
134
|
-
fs.writeFileSync(path.join(tempDir, 'dfx.json'), JSON.stringify(dfxJson(canisterName), null, 2));
|
|
135
|
-
fs.cpSync(new URL('./bench/bench-canister.mo', import.meta.url), path.join(tempDir, 'canister.mo'));
|
|
136
|
-
fs.cpSync(file, path.join(tempDir, 'user-bench.mo'));
|
|
137
|
-
// deploy canister
|
|
138
|
-
execSync(`dfx deploy ${canisterName} --mode reinstall --yes --identity anonymous`, { cwd: tempDir, stdio: options.verbose ? 'pipe' : ['pipe', 'ignore', 'pipe'] });
|
|
139
|
-
let canisterId = execSync(`dfx canister id ${canisterName}`, { cwd: tempDir }).toString().trim();
|
|
140
|
-
let actor = await createActor(canisterId, {
|
|
141
|
-
agentOptions: {
|
|
142
|
-
host: 'http://127.0.0.1:4947',
|
|
143
|
-
},
|
|
144
|
-
});
|
|
145
|
-
let schema = await actor.init();
|
|
146
|
-
// load previous results
|
|
147
|
-
let prevResults;
|
|
148
|
-
if (options.compare) {
|
|
149
|
-
let prevResultsJson = JSON.parse(fs.readFileSync(path.join(rootDir, 'mops.bench.json')).toString());
|
|
150
|
-
if (prevResultsJson.results[schema.name]) {
|
|
151
|
-
prevResults = new Map(prevResultsJson.results[schema.name]);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
console.log(chalk.yellow(`No previous results found for benchmark with name "${schema.name}"`));
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
let results = new Map();
|
|
158
|
-
let formatNumber = (n) => {
|
|
159
|
-
return n.toLocaleString('en-US').replaceAll(',', '_');
|
|
160
|
-
};
|
|
161
|
-
let getTable = (prop) => {
|
|
162
|
-
let resArr = [['', ...schema.cols]];
|
|
163
|
-
for (let [_rowIndex, row] of schema.rows.entries()) {
|
|
164
|
-
let curRow = [row];
|
|
165
|
-
for (let [_colIndex, col] of schema.cols.entries()) {
|
|
166
|
-
let res = results.get(`${row}:${col}`);
|
|
167
|
-
if (res) {
|
|
168
|
-
// compare with previous results
|
|
169
|
-
let diff = '';
|
|
170
|
-
if (options.compare && prevResults) {
|
|
171
|
-
let prevRes = prevResults.get(`${row}:${col}`);
|
|
172
|
-
if (prevRes) {
|
|
173
|
-
let percent = (Number(res[prop]) - Number(prevRes[prop])) / Number(prevRes[prop]) * 100;
|
|
174
|
-
let sign = percent > 0 ? '+' : '';
|
|
175
|
-
let percentText = percent == 0 ? '0%' : sign + percent.toFixed(2) + '%';
|
|
176
|
-
// diff = ' (' + (percent > 0 ? chalk.red(percentText) : chalk.green(percentText)) + ')'; // alignment is broken
|
|
177
|
-
diff = ' (' + percentText + ')';
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
diff = chalk.yellow(' (no previous results)');
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
// add to table
|
|
184
|
-
curRow.push(formatNumber(res[prop]) + diff);
|
|
185
|
-
}
|
|
186
|
-
else {
|
|
187
|
-
curRow.push('');
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
resArr.push(curRow);
|
|
191
|
-
}
|
|
192
|
-
return markdownTable(resArr, { align: ['l', ...'r'.repeat(schema.cols.length)] });
|
|
193
|
-
};
|
|
194
|
-
let printResults = () => {
|
|
195
|
-
logUpdate(`
|
|
196
|
-
\n${chalk.bold(schema.name)}
|
|
197
|
-
${schema.description ? '\n' + chalk.gray(schema.description) : ''}
|
|
198
|
-
\n\n${chalk.blue('Instructions')}\n\n${getTable('instructions')}
|
|
199
|
-
\n\n${chalk.blue('Heap')}\n\n${getTable('rts_heap_size')}
|
|
200
|
-
`);
|
|
201
|
-
};
|
|
202
|
-
printResults();
|
|
203
|
-
// run all cells
|
|
204
|
-
for (let [rowIndex, row] of schema.rows.entries()) {
|
|
205
|
-
for (let [colIndex, col] of schema.cols.entries()) {
|
|
206
|
-
// let res = await actor.runCellQuery(BigInt(rowIndex), BigInt(colIndex));
|
|
207
|
-
let res = await actor.runCellUpdate(BigInt(rowIndex), BigInt(colIndex));
|
|
208
|
-
results.set(`${row}:${col}`, res);
|
|
209
|
-
printResults();
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
logUpdate.done();
|
|
213
|
-
return { schema, results };
|
|
214
|
-
}
|
package/dist/commands/mmf1.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
type Strategy = 'store' | 'print';
|
|
2
|
-
export declare class MMF1 {
|
|
3
|
-
stack: string[];
|
|
4
|
-
currSuite: string;
|
|
5
|
-
failed: number;
|
|
6
|
-
passed: number;
|
|
7
|
-
skipped: number;
|
|
8
|
-
srategy: Strategy;
|
|
9
|
-
output: string[];
|
|
10
|
-
constructor(srategy: Strategy);
|
|
11
|
-
_log(...args: string[]): void;
|
|
12
|
-
flush(): void;
|
|
13
|
-
parseLine(line: string): void;
|
|
14
|
-
_testStart(name: string): void;
|
|
15
|
-
_testEnd(name: string): void;
|
|
16
|
-
_testSkip(name: string): void;
|
|
17
|
-
_status(name: string, status: string): void;
|
|
18
|
-
fail(stderr: string): void;
|
|
19
|
-
pass(): void;
|
|
20
|
-
}
|
|
21
|
-
export {};
|
package/dist/commands/mmf1.js
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
// mops message format v1
|
|
2
|
-
// mops:1:start
|
|
3
|
-
// mops:1:end
|
|
4
|
-
// mops:1:skip
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
export class MMF1 {
|
|
7
|
-
constructor(srategy) {
|
|
8
|
-
this.stack = [];
|
|
9
|
-
this.currSuite = '';
|
|
10
|
-
this.failed = 0;
|
|
11
|
-
this.passed = 0;
|
|
12
|
-
this.skipped = 0;
|
|
13
|
-
this.output = [];
|
|
14
|
-
this.srategy = srategy;
|
|
15
|
-
}
|
|
16
|
-
_log(...args) {
|
|
17
|
-
if (this.srategy === 'store') {
|
|
18
|
-
this.output.push(args.join(' '));
|
|
19
|
-
}
|
|
20
|
-
else if (this.srategy === 'print') {
|
|
21
|
-
console.log(...args);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
flush() {
|
|
25
|
-
for (let out of this.output) {
|
|
26
|
-
console.log(out);
|
|
27
|
-
}
|
|
28
|
-
this.output = [];
|
|
29
|
-
}
|
|
30
|
-
parseLine(line) {
|
|
31
|
-
if (line.startsWith('mops:1:start ')) {
|
|
32
|
-
this._testStart(line.split('mops:1:start ')[1] || '');
|
|
33
|
-
}
|
|
34
|
-
else if (line.startsWith('mops:1:end ')) {
|
|
35
|
-
this._testEnd(line.split('mops:1:end ')[1] || '');
|
|
36
|
-
}
|
|
37
|
-
else if (line.startsWith('mops:1:skip ')) {
|
|
38
|
-
this._testSkip(line.split('mops:1:skip ')[1] || '');
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
this._log(' '.repeat(this.stack.length * 2), chalk.gray('stdout'), line);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
_testStart(name) {
|
|
45
|
-
let suite = this.stack[this.stack.length - 1];
|
|
46
|
-
if (suite) {
|
|
47
|
-
if (this.currSuite !== suite) {
|
|
48
|
-
this.currSuite = suite;
|
|
49
|
-
this._log(' '.repeat((this.stack.length - 1) * 2), (chalk.gray('•')) + '', suite);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
this.stack.push(name);
|
|
53
|
-
}
|
|
54
|
-
_testEnd(name) {
|
|
55
|
-
if (name !== this.stack.pop()) {
|
|
56
|
-
throw 'mmf1._testEnd: start and end test mismatch';
|
|
57
|
-
}
|
|
58
|
-
this._status(name, 'pass');
|
|
59
|
-
}
|
|
60
|
-
_testSkip(name) {
|
|
61
|
-
this._status(name, 'skip');
|
|
62
|
-
}
|
|
63
|
-
_status(name, status) {
|
|
64
|
-
if (status === 'pass') {
|
|
65
|
-
// do not print suite at the end
|
|
66
|
-
if (name === this.currSuite) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
this.passed++;
|
|
70
|
-
this._log(' '.repeat(this.stack.length * 2), chalk.green('✓'), name);
|
|
71
|
-
}
|
|
72
|
-
else if (status === 'fail') {
|
|
73
|
-
this.failed++;
|
|
74
|
-
this._log(' '.repeat(this.stack.length * 2), chalk.red('✖'), name);
|
|
75
|
-
}
|
|
76
|
-
else if (status === 'skip') {
|
|
77
|
-
this.skipped++;
|
|
78
|
-
this._log(' '.repeat(this.stack.length * 2), chalk.yellow('−'), name);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
fail(stderr) {
|
|
82
|
-
let name = this.stack.pop() || '';
|
|
83
|
-
this._status(name, 'fail');
|
|
84
|
-
this._log(' '.repeat(this.stack.length * 2), chalk.red('FAIL'), stderr);
|
|
85
|
-
}
|
|
86
|
-
pass() {
|
|
87
|
-
let name = this.stack.pop();
|
|
88
|
-
if (name) {
|
|
89
|
-
this._status(name, 'pass');
|
|
90
|
-
}
|
|
91
|
-
this._log(' '.repeat(this.stack.length * 2), chalk.green('PASS'));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { MMF1 } from './mmf1.js';
|
|
2
|
-
export declare class FilesReporter {
|
|
3
|
-
#private;
|
|
4
|
-
passed: number;
|
|
5
|
-
failed: number;
|
|
6
|
-
skipped: number;
|
|
7
|
-
addFiles(files: string[]): void;
|
|
8
|
-
addRun(file: string, mmf: MMF1, state: Promise<void>, wasiMode: boolean): void;
|
|
9
|
-
done(): boolean;
|
|
10
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
-
};
|
|
6
|
-
var _FilesReporter_startTime;
|
|
7
|
-
import chalk from 'chalk';
|
|
8
|
-
import { absToRel } from './utils.js';
|
|
9
|
-
export class FilesReporter {
|
|
10
|
-
constructor() {
|
|
11
|
-
this.passed = 0;
|
|
12
|
-
this.failed = 0;
|
|
13
|
-
this.skipped = 0;
|
|
14
|
-
_FilesReporter_startTime.set(this, Date.now());
|
|
15
|
-
}
|
|
16
|
-
addFiles(files) {
|
|
17
|
-
console.log(`Test files: ${files.length}`);
|
|
18
|
-
console.log('='.repeat(50));
|
|
19
|
-
}
|
|
20
|
-
addRun(file, mmf, state, wasiMode) {
|
|
21
|
-
state.then(() => {
|
|
22
|
-
this.passed += mmf.passed;
|
|
23
|
-
this.failed += mmf.failed;
|
|
24
|
-
this.skipped += mmf.skipped;
|
|
25
|
-
if (this.failed) {
|
|
26
|
-
mmf.flush();
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
console.log(`${chalk.green('✓')} ${absToRel(file)} ${wasiMode ? chalk.gray('(wasi)') : ''}`);
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
done() {
|
|
34
|
-
console.log('='.repeat(50));
|
|
35
|
-
if (this.failed) {
|
|
36
|
-
console.log(chalk.redBright('Tests failed'));
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
console.log(chalk.greenBright('Tests passed'));
|
|
40
|
-
}
|
|
41
|
-
console.log(`Done in ${chalk.gray(((Date.now() - __classPrivateFieldGet(this, _FilesReporter_startTime, "f")) / 1000).toFixed(2) + 's')}`
|
|
42
|
-
+ `, passed ${chalk.greenBright(this.passed)}`
|
|
43
|
-
+ (this.skipped ? `, skipped ${chalk[this.skipped ? 'yellowBright' : 'gray'](this.skipped)}` : '')
|
|
44
|
-
+ (this.failed ? `, failed ${chalk[this.failed ? 'redBright' : 'gray'](this.failed)}` : ''));
|
|
45
|
-
return this.failed === 0;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
_FilesReporter_startTime = new WeakMap();
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { MMF1 } from './mmf1.js';
|
|
2
|
-
export declare class VerboseReporter {
|
|
3
|
-
#private;
|
|
4
|
-
passed: number;
|
|
5
|
-
failed: number;
|
|
6
|
-
skipped: number;
|
|
7
|
-
addFiles(files: string[]): void;
|
|
8
|
-
addRun(file: string, mmf: MMF1, state: Promise<void>, wasiMode: boolean): void;
|
|
9
|
-
done(): boolean;
|
|
10
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
-
};
|
|
6
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
7
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
|
-
};
|
|
12
|
-
var _VerboseReporter_startTime, _VerboseReporter_curFileIndex;
|
|
13
|
-
import chalk from 'chalk';
|
|
14
|
-
import { absToRel } from './utils.js';
|
|
15
|
-
export class VerboseReporter {
|
|
16
|
-
constructor() {
|
|
17
|
-
this.passed = 0;
|
|
18
|
-
this.failed = 0;
|
|
19
|
-
this.skipped = 0;
|
|
20
|
-
_VerboseReporter_startTime.set(this, Date.now());
|
|
21
|
-
_VerboseReporter_curFileIndex.set(this, 0);
|
|
22
|
-
}
|
|
23
|
-
addFiles(files) {
|
|
24
|
-
console.log('Test files:');
|
|
25
|
-
for (let file of files) {
|
|
26
|
-
console.log(chalk.gray(`• ${absToRel(file)}`));
|
|
27
|
-
}
|
|
28
|
-
console.log('='.repeat(50));
|
|
29
|
-
}
|
|
30
|
-
addRun(file, mmf, state, wasiMode) {
|
|
31
|
-
state.then(() => {
|
|
32
|
-
var _a, _b;
|
|
33
|
-
this.passed += mmf.passed;
|
|
34
|
-
this.failed += mmf.failed;
|
|
35
|
-
this.skipped += mmf.skipped;
|
|
36
|
-
(__classPrivateFieldSet(this, _VerboseReporter_curFileIndex, (_b = __classPrivateFieldGet(this, _VerboseReporter_curFileIndex, "f"), _a = _b++, _b), "f"), _a) && console.log('-'.repeat(50));
|
|
37
|
-
console.log(`Running ${chalk.gray(absToRel(file))} ${wasiMode ? chalk.gray('(wasi)') : ''}`);
|
|
38
|
-
mmf.flush();
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
done() {
|
|
42
|
-
console.log('='.repeat(50));
|
|
43
|
-
if (this.failed) {
|
|
44
|
-
console.log(chalk.redBright('Tests failed'));
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
console.log(chalk.greenBright('Tests passed'));
|
|
48
|
-
}
|
|
49
|
-
console.log(`Done in ${chalk.gray(((Date.now() - __classPrivateFieldGet(this, _VerboseReporter_startTime, "f")) / 1000).toFixed(2) + 's')}`
|
|
50
|
-
+ `, passed ${chalk.greenBright(this.passed)}`
|
|
51
|
-
+ (this.skipped ? `, skipped ${chalk[this.skipped ? 'yellowBright' : 'gray'](this.skipped)}` : '')
|
|
52
|
-
+ (this.failed ? `, failed ${chalk[this.failed ? 'redBright' : 'gray'](this.failed)}` : ''));
|
|
53
|
-
return this.failed === 0;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
_VerboseReporter_startTime = new WeakMap(), _VerboseReporter_curFileIndex = new WeakMap();
|
package/dist/commands/test.d.ts
DELETED
package/dist/commands/test.js
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import { spawn, execSync } from 'node:child_process';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import fs from 'node:fs';
|
|
4
|
-
import os from 'node:os';
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
import { globSync } from 'glob';
|
|
7
|
-
import chokidar from 'chokidar';
|
|
8
|
-
import debounce from 'debounce';
|
|
9
|
-
import { MMF1 } from './mmf1.js';
|
|
10
|
-
import { sources } from './sources.js';
|
|
11
|
-
import { getRootDir } from '../mops.js';
|
|
12
|
-
import { parallel } from '../parallel.js';
|
|
13
|
-
import { absToRel } from './test/utils.js';
|
|
14
|
-
import { VerboseReporter } from './test/reporter-verbose.js';
|
|
15
|
-
let ignore = [
|
|
16
|
-
'**/node_modules/**',
|
|
17
|
-
'**/.mops/**',
|
|
18
|
-
'**/.vessel/**',
|
|
19
|
-
'**/.git/**',
|
|
20
|
-
];
|
|
21
|
-
let globConfig = {
|
|
22
|
-
nocase: true,
|
|
23
|
-
ignore: ignore,
|
|
24
|
-
};
|
|
25
|
-
export async function test(filter = '', { watch = false } = {}) {
|
|
26
|
-
let rootDir = getRootDir();
|
|
27
|
-
if (watch) {
|
|
28
|
-
// todo: run only changed for *.test.mo?
|
|
29
|
-
// todo: run all for *.mo?
|
|
30
|
-
let run = debounce(async () => {
|
|
31
|
-
console.clear();
|
|
32
|
-
process.stdout.write('\x1Bc');
|
|
33
|
-
await runAll(filter);
|
|
34
|
-
console.log('-'.repeat(50));
|
|
35
|
-
console.log('Waiting for file changes...');
|
|
36
|
-
console.log(chalk.gray((`Press ${chalk.gray('Ctrl+C')} to exit.`)));
|
|
37
|
-
}, 200);
|
|
38
|
-
let watcher = chokidar.watch([
|
|
39
|
-
path.join(rootDir, '**/*.mo'),
|
|
40
|
-
path.join(rootDir, 'mops.toml'),
|
|
41
|
-
], {
|
|
42
|
-
ignored: ignore,
|
|
43
|
-
ignoreInitial: true,
|
|
44
|
-
});
|
|
45
|
-
watcher.on('all', () => {
|
|
46
|
-
run();
|
|
47
|
-
});
|
|
48
|
-
run();
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
let passed = await runAll(filter);
|
|
52
|
-
if (!passed) {
|
|
53
|
-
process.exit(1);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
let mocPath = process.env.DFX_MOC_PATH;
|
|
58
|
-
export async function runAll(filter = '') {
|
|
59
|
-
let reporter = new VerboseReporter;
|
|
60
|
-
let rootDir = getRootDir();
|
|
61
|
-
let files = [];
|
|
62
|
-
let libFiles = globSync('**/test?(s)/lib.mo', globConfig);
|
|
63
|
-
if (libFiles[0]) {
|
|
64
|
-
files = [libFiles[0]];
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
let globStr = '**/test?(s)/**/*.test.mo';
|
|
68
|
-
if (filter) {
|
|
69
|
-
globStr = `**/test?(s)/**/*${filter}*.mo`;
|
|
70
|
-
}
|
|
71
|
-
files = globSync(path.join(rootDir, globStr), globConfig);
|
|
72
|
-
}
|
|
73
|
-
if (!files.length) {
|
|
74
|
-
if (filter) {
|
|
75
|
-
console.log(`No test files found for filter '${filter}'`);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
console.log('No test files found');
|
|
79
|
-
console.log('Put your tests in \'test\' directory in *.test.mo files');
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
reporter.addFiles(files);
|
|
83
|
-
// console.log('Test files:');
|
|
84
|
-
// for (let file of files) {
|
|
85
|
-
// console.log(chalk.gray(`• ${absToRel(file)}`));
|
|
86
|
-
// }
|
|
87
|
-
// console.log('='.repeat(50));
|
|
88
|
-
// let failed = 0;
|
|
89
|
-
// let passed = 0;
|
|
90
|
-
// let skipped = 0;
|
|
91
|
-
let sourcesArr = await sources();
|
|
92
|
-
if (!mocPath) {
|
|
93
|
-
mocPath = execSync('dfx cache show').toString().trim() + '/moc';
|
|
94
|
-
}
|
|
95
|
-
let wasmDir = `${getRootDir()}/.mops/.test/`;
|
|
96
|
-
fs.mkdirSync(wasmDir, { recursive: true });
|
|
97
|
-
await parallel(os.cpus().length, files, async (file) => {
|
|
98
|
-
let mmf = new MMF1('store');
|
|
99
|
-
let wasiMode = fs.readFileSync(file, 'utf8').startsWith('// @testmode wasi');
|
|
100
|
-
let promise = new Promise((resolve) => {
|
|
101
|
-
if (!mocPath) {
|
|
102
|
-
mocPath = 'moc';
|
|
103
|
-
}
|
|
104
|
-
let mocArgs = ['--hide-warnings', '--error-detail=2', ...sourcesArr.join(' ').split(' '), file].filter(x => x);
|
|
105
|
-
// build and run wasm
|
|
106
|
-
if (wasiMode) {
|
|
107
|
-
let wasmFile = `${path.join(wasmDir, path.parse(file).name)}.wasm`;
|
|
108
|
-
// build
|
|
109
|
-
let buildProc = spawn(mocPath, [`-o=${wasmFile}`, '-wasi-system-api', ...mocArgs]);
|
|
110
|
-
pipeMMF(buildProc, mmf).then(async () => {
|
|
111
|
-
if (mmf.failed > 0) {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
// run
|
|
115
|
-
let proc = spawn('wasmtime', [wasmFile]);
|
|
116
|
-
await pipeMMF(proc, mmf);
|
|
117
|
-
}).finally(() => {
|
|
118
|
-
fs.rmSync(wasmFile, { force: true });
|
|
119
|
-
}).then(resolve);
|
|
120
|
-
}
|
|
121
|
-
// interpret
|
|
122
|
-
else {
|
|
123
|
-
let proc = spawn(mocPath, ['-r', '-ref-system-api', ...mocArgs]);
|
|
124
|
-
pipeMMF(proc, mmf).then(resolve);
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
reporter.addRun(file, mmf, promise, wasiMode);
|
|
128
|
-
await promise;
|
|
129
|
-
});
|
|
130
|
-
fs.rmSync(wasmDir, { recursive: true, force: true });
|
|
131
|
-
return reporter.done();
|
|
132
|
-
}
|
|
133
|
-
function pipeMMF(proc, mmf) {
|
|
134
|
-
return new Promise((resolve) => {
|
|
135
|
-
// stdout
|
|
136
|
-
proc.stdout.on('data', (data) => {
|
|
137
|
-
for (let line of data.toString().split('\n')) {
|
|
138
|
-
line = line.trim();
|
|
139
|
-
if (line) {
|
|
140
|
-
mmf.parseLine(line);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
// stderr
|
|
145
|
-
proc.stderr.on('data', (data) => {
|
|
146
|
-
let text = data.toString().trim();
|
|
147
|
-
let failedLine = '';
|
|
148
|
-
text = text.replace(/([\w+._/-]+):(\d+).(\d+)(-\d+.\d+)/g, (_m0, m1, m2, m3) => {
|
|
149
|
-
// change absolute file path to relative
|
|
150
|
-
// change :line:col-line:col to :line:col to work in vscode
|
|
151
|
-
let res = `${absToRel(m1)}:${m2}:${m3}`;
|
|
152
|
-
if (!fs.existsSync(m1)) {
|
|
153
|
-
return res;
|
|
154
|
-
}
|
|
155
|
-
// show failed line
|
|
156
|
-
let content = fs.readFileSync(m1);
|
|
157
|
-
let lines = content.toString().split('\n') || [];
|
|
158
|
-
failedLine += chalk.dim `\n ...`;
|
|
159
|
-
let lineBefore = lines[+m2 - 2];
|
|
160
|
-
if (lineBefore) {
|
|
161
|
-
failedLine += chalk.dim `\n ${+m2 - 1}\t| ${lineBefore.replaceAll('\t', ' ')}`;
|
|
162
|
-
}
|
|
163
|
-
failedLine += `\n${chalk.redBright `->`} ${m2}\t| ${lines[+m2 - 1]?.replaceAll('\t', ' ')}`;
|
|
164
|
-
if (lines.length > +m2) {
|
|
165
|
-
failedLine += chalk.dim `\n ${+m2 + 1}\t| ${lines[+m2]?.replaceAll('\t', ' ')}`;
|
|
166
|
-
}
|
|
167
|
-
failedLine += chalk.dim `\n ...`;
|
|
168
|
-
return res;
|
|
169
|
-
});
|
|
170
|
-
if (failedLine) {
|
|
171
|
-
text += failedLine;
|
|
172
|
-
}
|
|
173
|
-
mmf.fail(text);
|
|
174
|
-
});
|
|
175
|
-
// exit
|
|
176
|
-
proc.on('close', (code) => {
|
|
177
|
-
if (code === 0) {
|
|
178
|
-
mmf.pass();
|
|
179
|
-
}
|
|
180
|
-
else if (code !== 1) {
|
|
181
|
-
mmf.fail(`unknown exit code: ${code}`);
|
|
182
|
-
}
|
|
183
|
-
resolve();
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
type anon_class_10_1 =
|
|
2
|
-
service {
|
|
3
|
-
getStats: () -> (BenchResult) query;
|
|
4
|
-
init: () -> (BenchSchema);
|
|
5
|
-
runCellQuery: (nat, nat) -> (BenchResult) query;
|
|
6
|
-
runCellUpdate: (nat, nat) -> (BenchResult);
|
|
7
|
-
};
|
|
8
|
-
type BenchSchema =
|
|
9
|
-
record {
|
|
10
|
-
cols: vec text;
|
|
11
|
-
description: text;
|
|
12
|
-
name: text;
|
|
13
|
-
rows: vec text;
|
|
14
|
-
};
|
|
15
|
-
type BenchResult =
|
|
16
|
-
record {
|
|
17
|
-
instructions: int;
|
|
18
|
-
rts_collector_instructions: int;
|
|
19
|
-
rts_heap_size: int;
|
|
20
|
-
rts_memory_size: int;
|
|
21
|
-
rts_mutator_instructions: int;
|
|
22
|
-
rts_total_allocation: int;
|
|
23
|
-
};
|
|
24
|
-
service : () -> anon_class_10_1
|