ic-mops 0.45.3 → 1.0.0-pre.0
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/.eslintrc.json +0 -0
- package/.gitignore +0 -0
- package/CHANGELOG.md +15 -0
- package/README.md +1 -1
- package/api/actors.ts +25 -17
- package/api/downloadPackageFiles.ts +0 -0
- package/api/getHighestVersion.ts +0 -0
- package/api/index.ts +0 -0
- package/api/network.ts +0 -0
- package/api/resolveVersion.ts +0 -0
- package/cache.ts +20 -8
- package/cli.ts +28 -27
- package/commands/add.ts +4 -0
- package/commands/bench/bench-canister.mo +34 -8
- package/commands/bench/user-bench.mo +0 -0
- package/commands/bench-replica.ts +11 -6
- package/commands/bench.ts +31 -5
- package/commands/bump.ts +0 -0
- package/commands/docs.ts +0 -0
- package/commands/outdated.ts +0 -0
- package/commands/publish.ts +1 -1
- package/commands/replica.ts +237 -0
- package/commands/search.ts +0 -0
- package/commands/sources.ts +2 -3
- package/commands/sync.ts +0 -0
- package/commands/template.ts +0 -0
- package/commands/test/mmf1.ts +5 -5
- package/commands/test/reporters/compact-reporter.ts +2 -1
- package/commands/test/reporters/files-reporter.ts +3 -2
- package/commands/test/reporters/reporter.ts +2 -1
- package/commands/test/reporters/silent-reporter.ts +2 -1
- package/commands/test/reporters/verbose-reporter.ts +14 -4
- package/commands/test/test.ts +213 -74
- package/commands/test/utils.ts +0 -0
- package/commands/toolchain/moc.ts +0 -0
- package/commands/toolchain/pocket-ic.ts +0 -0
- package/commands/toolchain/toolchain-utils.ts +0 -0
- package/commands/toolchain/wasmtime.ts +0 -0
- package/commands/transfer-ownership.ts +0 -0
- package/commands/update.ts +0 -0
- package/commands/user.ts +71 -1
- package/declarations/bench/bench.did +8 -4
- package/declarations/bench/bench.did.d.ts +4 -0
- package/declarations/bench/bench.did.js +4 -0
- package/declarations/storage/index.d.ts +0 -0
- package/declarations/storage/index.js +0 -0
- package/declarations/storage/storage.did +0 -0
- package/declarations/storage/storage.did.d.ts +0 -0
- package/declarations/storage/storage.did.js +0 -0
- package/dist/api/actors.js +19 -13
- package/dist/cache.js +17 -8
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +24 -27
- package/dist/commands/add.js +3 -0
- package/dist/commands/bench/bench-canister.mo +34 -8
- package/dist/commands/bench/user-bench.mo +0 -0
- package/dist/commands/bench-replica.d.ts +2 -1
- package/dist/commands/bench-replica.js +10 -6
- package/dist/commands/bench.js +29 -5
- package/dist/commands/publish.js +1 -1
- package/dist/commands/replica.d.ts +59 -0
- package/dist/commands/replica.js +193 -0
- package/dist/commands/sources.d.ts +2 -2
- package/dist/commands/sources.js +2 -3
- package/dist/commands/test/mmf1.d.ts +2 -2
- package/dist/commands/test/mmf1.js +4 -4
- package/dist/commands/test/reporters/compact-reporter.d.ts +2 -1
- package/dist/commands/test/reporters/compact-reporter.js +1 -1
- package/dist/commands/test/reporters/files-reporter.d.ts +2 -1
- package/dist/commands/test/reporters/files-reporter.js +2 -2
- package/dist/commands/test/reporters/reporter.d.ts +2 -1
- package/dist/commands/test/reporters/silent-reporter.d.ts +2 -1
- package/dist/commands/test/reporters/silent-reporter.js +1 -1
- package/dist/commands/test/reporters/verbose-reporter.d.ts +3 -1
- package/dist/commands/test/reporters/verbose-reporter.js +12 -4
- package/dist/commands/test/test.d.ts +10 -8
- package/dist/commands/test/test.js +170 -71
- package/dist/commands/user.d.ts +6 -0
- package/dist/commands/user.js +59 -1
- package/dist/declarations/bench/bench.did +8 -4
- package/dist/declarations/bench/bench.did.d.ts +4 -0
- package/dist/declarations/bench/bench.did.js +4 -0
- package/dist/declarations/storage/index.d.ts +0 -0
- package/dist/declarations/storage/index.js +0 -0
- package/dist/declarations/storage/storage.did +0 -0
- package/dist/declarations/storage/storage.did.d.ts +0 -0
- package/dist/declarations/storage/storage.did.js +0 -0
- package/dist/mops.d.ts +1 -1
- package/dist/mops.js +4 -28
- package/dist/package.json +4 -3
- package/dist/resolve-packages.d.ts +2 -2
- package/dist/resolve-packages.js +29 -7
- package/dist/templates/README.md +0 -0
- package/dist/templates/licenses/Apache-2.0 +0 -0
- package/dist/templates/licenses/Apache-2.0-NOTICE +0 -0
- package/dist/templates/licenses/MIT +0 -0
- package/dist/templates/mops-publish.yml +0 -0
- package/dist/templates/mops-test.yml +0 -0
- package/dist/templates/src/lib.mo +0 -0
- package/dist/templates/test/lib.test.mo +0 -0
- package/dist/types.d.ts +1 -0
- package/global.d.ts +0 -0
- package/helpers/get-dfx-version.ts +0 -0
- package/helpers/get-moc-path.ts +0 -0
- package/helpers/get-moc-version.ts +0 -0
- package/mops.ts +4 -31
- package/package.json +4 -3
- package/parallel.ts +0 -0
- package/resolve-packages.ts +39 -8
- package/templates/README.md +0 -0
- package/templates/licenses/Apache-2.0 +0 -0
- package/templates/licenses/Apache-2.0-NOTICE +0 -0
- package/templates/licenses/MIT +0 -0
- package/templates/mops-publish.yml +0 -0
- package/templates/mops-test.yml +0 -0
- package/templates/src/lib.mo +0 -0
- package/templates/test/lib.test.mo +0 -0
- package/types.ts +3 -1
- package/.DS_Store +0 -0
- package/bundle/bench/bench-canister.mo +0 -87
- package/bundle/bench/user-bench.mo +0 -14
- package/bundle/bin/moc-wrapper.sh +0 -40
- package/bundle/bin/mops.js +0 -3
- package/bundle/cli.js +0 -163
- package/bundle/cli.tgz +0 -0
- package/bundle/declarations/bench/bench.did +0 -26
- package/bundle/declarations/bench/bench.did.d.ts +0 -29
- package/bundle/declarations/bench/bench.did.js +0 -26
- package/bundle/declarations/bench/index.d.ts +0 -50
- package/bundle/declarations/bench/index.js +0 -40
- package/bundle/declarations/main/index.d.ts +0 -50
- package/bundle/declarations/main/index.js +0 -40
- package/bundle/declarations/main/main.did +0 -438
- package/bundle/declarations/main/main.did.d.ts +0 -360
- package/bundle/declarations/main/main.did.js +0 -412
- package/bundle/declarations/storage/index.d.ts +0 -50
- package/bundle/declarations/storage/index.js +0 -30
- package/bundle/declarations/storage/storage.did +0 -46
- package/bundle/declarations/storage/storage.did.d.ts +0 -40
- package/bundle/declarations/storage/storage.did.js +0 -38
- package/bundle/package.json +0 -31
- package/bundle/templates/README.md +0 -13
- package/bundle/templates/licenses/Apache-2.0 +0 -202
- package/bundle/templates/licenses/Apache-2.0-NOTICE +0 -13
- package/bundle/templates/licenses/MIT +0 -21
- package/bundle/templates/mops-publish.yml +0 -17
- package/bundle/templates/mops-test.yml +0 -22
- package/bundle/templates/src/lib.mo +0 -15
- package/bundle/templates/test/lib.test.mo +0 -4
- package/commands/import-identity.ts +0 -62
- package/commands/whoami.ts +0 -12
package/commands/test/test.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {spawn, ChildProcessWithoutNullStreams} from 'node:child_process';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import os from 'node:os';
|
|
6
|
+
|
|
6
7
|
import chalk from 'chalk';
|
|
7
8
|
import {globSync} from 'glob';
|
|
8
9
|
import chokidar from 'chokidar';
|
|
@@ -20,6 +21,10 @@ import {FilesReporter} from './reporters/files-reporter.js';
|
|
|
20
21
|
import {CompactReporter} from './reporters/compact-reporter.js';
|
|
21
22
|
import {SilentReporter} from './reporters/silent-reporter.js';
|
|
22
23
|
import {toolchain} from '../toolchain/index.js';
|
|
24
|
+
import {Replica} from '../replica.js';
|
|
25
|
+
import {ActorMethod} from '@dfinity/agent';
|
|
26
|
+
import {PassThrough, Readable} from 'node:stream';
|
|
27
|
+
import {TestMode} from '../../types.js';
|
|
23
28
|
|
|
24
29
|
let ignore = [
|
|
25
30
|
'**/node_modules/**',
|
|
@@ -34,18 +39,60 @@ let globConfig = {
|
|
|
34
39
|
};
|
|
35
40
|
|
|
36
41
|
type ReporterName = 'verbose' | 'files' | 'compact' | 'silent';
|
|
37
|
-
type
|
|
42
|
+
type ReplicaName = 'dfx' | 'pocket-ic';
|
|
43
|
+
|
|
44
|
+
type TestOptions = {
|
|
45
|
+
watch : boolean;
|
|
46
|
+
reporter : ReporterName;
|
|
47
|
+
mode : TestMode;
|
|
48
|
+
replica : ReplicaName;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
let replica = new Replica();
|
|
53
|
+
let replicaStartPromise : Promise<void> | undefined;
|
|
54
|
+
|
|
55
|
+
async function startReplicaOnce(replica : Replica, type : ReplicaName) {
|
|
56
|
+
if (!replicaStartPromise) {
|
|
57
|
+
replicaStartPromise = new Promise((resolve) => {
|
|
58
|
+
replica.start({type, silent: true}).then(resolve);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return replicaStartPromise;
|
|
62
|
+
}
|
|
38
63
|
|
|
39
|
-
export async function test(filter = '',
|
|
64
|
+
export async function test(filter = '', options : Partial<TestOptions> = {}) {
|
|
65
|
+
let config = readConfig();
|
|
40
66
|
let rootDir = getRootDir();
|
|
41
67
|
|
|
42
|
-
|
|
68
|
+
let replicaType = options.replica ?? (config.toolchain?.['pocket-ic'] ? 'pocket-ic' : 'dfx' as ReplicaName);
|
|
69
|
+
replica.type = replicaType;
|
|
70
|
+
|
|
71
|
+
if (options.watch) {
|
|
72
|
+
replica.ttl = 60 * 15; // 15 minutes
|
|
73
|
+
|
|
74
|
+
let sigint = false;
|
|
75
|
+
process.on('SIGINT', () => {
|
|
76
|
+
if (sigint) {
|
|
77
|
+
console.log('Force exit');
|
|
78
|
+
process.exit(0);
|
|
79
|
+
}
|
|
80
|
+
sigint = true;
|
|
81
|
+
|
|
82
|
+
if (replicaStartPromise) {
|
|
83
|
+
console.log('Stopping replica...');
|
|
84
|
+
replica.stop(true).then(() => {
|
|
85
|
+
process.exit(0);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
43
90
|
// todo: run only changed for *.test.mo?
|
|
44
91
|
// todo: run all for *.mo?
|
|
45
92
|
let run = debounce(async () => {
|
|
46
93
|
console.clear();
|
|
47
94
|
process.stdout.write('\x1Bc');
|
|
48
|
-
await runAll(reporter, filter, mode);
|
|
95
|
+
await runAll(options.reporter, filter, options.mode, replicaType, true);
|
|
49
96
|
console.log('-'.repeat(50));
|
|
50
97
|
console.log('Waiting for file changes...');
|
|
51
98
|
console.log(chalk.gray((`Press ${chalk.gray('Ctrl+C')} to exit.`)));
|
|
@@ -65,7 +112,7 @@ export async function test(filter = '', {watch = false, reporter = 'verbose' as
|
|
|
65
112
|
run();
|
|
66
113
|
}
|
|
67
114
|
else {
|
|
68
|
-
let passed = await runAll(reporter, filter, mode);
|
|
115
|
+
let passed = await runAll(options.reporter, filter, options.mode, replicaType);
|
|
69
116
|
if (!passed) {
|
|
70
117
|
process.exit(1);
|
|
71
118
|
}
|
|
@@ -75,25 +122,12 @@ export async function test(filter = '', {watch = false, reporter = 'verbose' as
|
|
|
75
122
|
let mocPath = '';
|
|
76
123
|
let wasmtimePath = '';
|
|
77
124
|
|
|
78
|
-
|
|
79
|
-
let
|
|
80
|
-
if (reporterName == 'compact') {
|
|
81
|
-
reporter = new CompactReporter;
|
|
82
|
-
}
|
|
83
|
-
else if (reporterName == 'files') {
|
|
84
|
-
reporter = new FilesReporter;
|
|
85
|
-
}
|
|
86
|
-
else if (reporterName == 'silent') {
|
|
87
|
-
reporter = new SilentReporter;
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
reporter = new VerboseReporter;
|
|
91
|
-
}
|
|
92
|
-
let done = await testWithReporter(reporter, filter, mode);
|
|
125
|
+
async function runAll(reporterName : ReporterName | undefined, filter = '', mode : TestMode = 'interpreter', replicaType : ReplicaName, watch = false) : Promise<boolean> {
|
|
126
|
+
let done = await testWithReporter(reporterName, filter, mode, replicaType, watch);
|
|
93
127
|
return done;
|
|
94
128
|
}
|
|
95
129
|
|
|
96
|
-
export async function testWithReporter(
|
|
130
|
+
export async function testWithReporter(reporterName : ReporterName | Reporter | undefined, filter = '', defaultMode : TestMode = 'interpreter', replicaType : ReplicaName, watch = false) : Promise<boolean> {
|
|
97
131
|
let rootDir = getRootDir();
|
|
98
132
|
let files : string[] = [];
|
|
99
133
|
let libFiles = globSync('**/test?(s)/lib.mo', globConfig);
|
|
@@ -117,6 +151,31 @@ export async function testWithReporter(reporter : Reporter, filter = '', mode :
|
|
|
117
151
|
return false;
|
|
118
152
|
}
|
|
119
153
|
|
|
154
|
+
|
|
155
|
+
let reporter : Reporter;
|
|
156
|
+
|
|
157
|
+
if (!reporterName || typeof reporterName === 'string') {
|
|
158
|
+
if (!reporterName) {
|
|
159
|
+
reporterName = files.length > 1 ? 'files' : 'verbose';
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (reporterName == 'compact') {
|
|
163
|
+
reporter = new CompactReporter;
|
|
164
|
+
}
|
|
165
|
+
else if (reporterName == 'files') {
|
|
166
|
+
reporter = new FilesReporter;
|
|
167
|
+
}
|
|
168
|
+
else if (reporterName == 'silent') {
|
|
169
|
+
reporter = new SilentReporter;
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
reporter = new VerboseReporter;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
reporter = reporterName;
|
|
177
|
+
}
|
|
178
|
+
|
|
120
179
|
reporter.addFiles(files);
|
|
121
180
|
|
|
122
181
|
let config = readConfig();
|
|
@@ -126,14 +185,25 @@ export async function testWithReporter(reporter : Reporter, filter = '', mode :
|
|
|
126
185
|
mocPath = await toolchain.bin('moc', {fallback: true});
|
|
127
186
|
}
|
|
128
187
|
|
|
129
|
-
let
|
|
130
|
-
|
|
188
|
+
let testTempDir = path.join(getRootDir(), '.mops/.test/');
|
|
189
|
+
replica.dir = testTempDir;
|
|
190
|
+
|
|
191
|
+
fs.mkdirSync(testTempDir, {recursive: true});
|
|
131
192
|
|
|
132
193
|
await parallel(os.cpus().length, files, async (file : string) => {
|
|
133
194
|
let mmf = new MMF1('store', absToRel(file));
|
|
134
|
-
let wasiMode = mode === 'wasi' || fs.readFileSync(file, 'utf8').startsWith('// @testmode wasi');
|
|
135
195
|
|
|
136
|
-
|
|
196
|
+
// mode overrides
|
|
197
|
+
let lines = fs.readFileSync(file, 'utf8').split('\n');
|
|
198
|
+
let mode = defaultMode;
|
|
199
|
+
if (lines.includes('// @testmode wasi')) {
|
|
200
|
+
mode = 'wasi';
|
|
201
|
+
}
|
|
202
|
+
else if (lines.includes('actor {') || lines.includes('// @testmode replica')) {
|
|
203
|
+
mode = 'replica';
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (mode === 'wasi' && !wasmtimePath) {
|
|
137
207
|
// ensure wasmtime is installed or specified in config
|
|
138
208
|
if (config.toolchain?.wasmtime) {
|
|
139
209
|
wasmtimePath = await toolchain.bin('wasmtime');
|
|
@@ -149,9 +219,14 @@ export async function testWithReporter(reporter : Reporter, filter = '', mode :
|
|
|
149
219
|
let promise = new Promise<void>((resolve) => {
|
|
150
220
|
let mocArgs = ['--hide-warnings', '--error-detail=2', ...sourcesArr.join(' ').split(' '), file].filter(x => x);
|
|
151
221
|
|
|
222
|
+
// interpret
|
|
223
|
+
if (mode === 'interpreter') {
|
|
224
|
+
let proc = spawn(mocPath, ['-r', '-ref-system-api', ...mocArgs]);
|
|
225
|
+
pipeMMF(proc, mmf).then(resolve);
|
|
226
|
+
}
|
|
152
227
|
// build and run wasm
|
|
153
|
-
if (
|
|
154
|
-
let wasmFile = `${path.join(
|
|
228
|
+
else if (mode === 'wasi') {
|
|
229
|
+
let wasmFile = `${path.join(testTempDir, path.parse(file).name)}.wasm`;
|
|
155
230
|
|
|
156
231
|
// build
|
|
157
232
|
let buildProc = spawn(mocPath, [`-o=${wasmFile}`, '-wasi-system-api', ...mocArgs]);
|
|
@@ -172,6 +247,7 @@ export async function testWithReporter(reporter : Reporter, filter = '', mode :
|
|
|
172
247
|
wasmFile,
|
|
173
248
|
];
|
|
174
249
|
}
|
|
250
|
+
// backcompat
|
|
175
251
|
else {
|
|
176
252
|
wasmtimeArgs = [
|
|
177
253
|
'--max-wasm-stack=4000000',
|
|
@@ -188,72 +264,135 @@ export async function testWithReporter(reporter : Reporter, filter = '', mode :
|
|
|
188
264
|
fs.rmSync(wasmFile, {force: true});
|
|
189
265
|
}).then(resolve);
|
|
190
266
|
}
|
|
191
|
-
//
|
|
192
|
-
else {
|
|
193
|
-
|
|
194
|
-
|
|
267
|
+
// build and execute in replica
|
|
268
|
+
else if (mode === 'replica') {
|
|
269
|
+
// mmf.strategy = 'print'; // because we run replica tests one-by-one
|
|
270
|
+
|
|
271
|
+
let wasmFile = `${path.join(testTempDir, path.parse(file).name)}.wasm`;
|
|
272
|
+
|
|
273
|
+
// build
|
|
274
|
+
let buildProc = spawn(mocPath, [`-o=${wasmFile}`, ...mocArgs]);
|
|
275
|
+
|
|
276
|
+
pipeMMF(buildProc, mmf).then(async () => {
|
|
277
|
+
if (mmf.failed > 0) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
await startReplicaOnce(replica, replicaType);
|
|
282
|
+
|
|
283
|
+
let canisterName = path.parse(file).name;
|
|
284
|
+
let idlFactory = ({IDL} : any) => {
|
|
285
|
+
return IDL.Service({'runTests': IDL.Func([], [], [])});
|
|
286
|
+
};
|
|
287
|
+
interface _SERVICE {'runTests' : ActorMethod<[], undefined>;}
|
|
288
|
+
|
|
289
|
+
let {stream} = await replica.deploy(canisterName, wasmFile, idlFactory);
|
|
290
|
+
|
|
291
|
+
pipeStdoutToMMF(stream, mmf);
|
|
292
|
+
|
|
293
|
+
let actor = await replica.getActor(canisterName) as _SERVICE;
|
|
294
|
+
|
|
295
|
+
try {
|
|
296
|
+
if (globalThis.mopsReplicaTestRunning) {
|
|
297
|
+
await new Promise<void>((resolve) => {
|
|
298
|
+
let timerId = setInterval(() => {
|
|
299
|
+
if (!globalThis.mopsReplicaTestRunning) {
|
|
300
|
+
resolve();
|
|
301
|
+
clearInterval(timerId);
|
|
302
|
+
}
|
|
303
|
+
}, Math.random() * 1000 |0);
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
globalThis.mopsReplicaTestRunning = true;
|
|
308
|
+
await actor.runTests();
|
|
309
|
+
globalThis.mopsReplicaTestRunning = false;
|
|
310
|
+
|
|
311
|
+
mmf.pass();
|
|
312
|
+
}
|
|
313
|
+
catch (e : any) {
|
|
314
|
+
let stderrStream = new PassThrough();
|
|
315
|
+
pipeStderrToMMF(stderrStream, mmf, path.dirname(file));
|
|
316
|
+
stderrStream.write(e.message);
|
|
317
|
+
}
|
|
318
|
+
}).finally(async () => {
|
|
319
|
+
fs.rmSync(wasmFile, {force: true});
|
|
320
|
+
}).then(resolve);
|
|
195
321
|
}
|
|
196
322
|
});
|
|
197
323
|
|
|
198
|
-
reporter.addRun(file, mmf, promise,
|
|
324
|
+
reporter.addRun(file, mmf, promise, mode);
|
|
199
325
|
|
|
200
326
|
await promise;
|
|
201
327
|
});
|
|
202
328
|
|
|
203
|
-
|
|
329
|
+
if (replicaStartPromise && !watch) {
|
|
330
|
+
await replica.stop();
|
|
331
|
+
fs.rmSync(testTempDir, {recursive: true, force: true});
|
|
332
|
+
}
|
|
333
|
+
|
|
204
334
|
return reporter.done();
|
|
205
335
|
}
|
|
206
336
|
|
|
207
|
-
function
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (line) {
|
|
214
|
-
mmf.parseLine(line);
|
|
215
|
-
}
|
|
337
|
+
function pipeStdoutToMMF(stdout : Readable, mmf : MMF1) {
|
|
338
|
+
stdout.on('data', (data) => {
|
|
339
|
+
for (let line of data.toString().split('\n')) {
|
|
340
|
+
line = line.trim();
|
|
341
|
+
if (line) {
|
|
342
|
+
mmf.parseLine(line);
|
|
216
343
|
}
|
|
217
|
-
}
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function pipeStderrToMMF(stderr : Readable, mmf : MMF1, dir = '') {
|
|
349
|
+
stderr.on('data', (data) => {
|
|
350
|
+
let text : string = data.toString().trim();
|
|
351
|
+
let failedLine = '';
|
|
352
|
+
|
|
353
|
+
text = text.replace(/([\w+._/-]+):(\d+).(\d+)(-\d+.\d+)/g, (_m0, m1 : string, m2 : string, m3 : string) => {
|
|
354
|
+
// change absolute file path to relative
|
|
355
|
+
// change :line:col-line:col to :line:col to work in vscode
|
|
356
|
+
let res = `${absToRel(m1)}:${m2}:${m3}`;
|
|
357
|
+
let file = path.join(dir, m1);
|
|
218
358
|
|
|
219
|
-
|
|
220
|
-
proc.stderr.on('data', (data) => {
|
|
221
|
-
let text : string = data.toString().trim();
|
|
222
|
-
let failedLine = '';
|
|
223
|
-
text = text.replace(/([\w+._/-]+):(\d+).(\d+)(-\d+.\d+)/g, (_m0, m1 : string, m2 : string, m3 : string) => {
|
|
224
|
-
// change absolute file path to relative
|
|
225
|
-
// change :line:col-line:col to :line:col to work in vscode
|
|
226
|
-
let res = `${absToRel(m1)}:${m2}:${m3}`;
|
|
227
|
-
|
|
228
|
-
if (!fs.existsSync(m1)) {
|
|
229
|
-
return res;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// show failed line
|
|
233
|
-
let content = fs.readFileSync(m1);
|
|
234
|
-
let lines = content.toString().split('\n') || [];
|
|
235
|
-
failedLine += chalk.dim('\n ...');
|
|
236
|
-
let lineBefore = lines[+m2 - 2];
|
|
237
|
-
if (lineBefore) {
|
|
238
|
-
failedLine += chalk.dim(`\n ${+m2 - 1}\t| ${lineBefore.replaceAll('\t', ' ')}`);
|
|
239
|
-
}
|
|
240
|
-
failedLine += `\n${chalk.redBright`->`} ${m2}\t| ${lines[+m2 - 1]?.replaceAll('\t', ' ')}`;
|
|
241
|
-
if (lines.length > +m2) {
|
|
242
|
-
failedLine += chalk.dim(`\n ${+m2 + 1}\t| ${lines[+m2]?.replaceAll('\t', ' ')}`);
|
|
243
|
-
}
|
|
244
|
-
failedLine += chalk.dim('\n ...');
|
|
359
|
+
if (!fs.existsSync(file)) {
|
|
245
360
|
return res;
|
|
246
|
-
});
|
|
247
|
-
if (failedLine) {
|
|
248
|
-
text += failedLine;
|
|
249
361
|
}
|
|
250
|
-
|
|
362
|
+
|
|
363
|
+
// show failed line
|
|
364
|
+
let content = fs.readFileSync(file);
|
|
365
|
+
let lines = content.toString().split('\n') || [];
|
|
366
|
+
|
|
367
|
+
failedLine += chalk.dim('\n ...');
|
|
368
|
+
|
|
369
|
+
let lineBefore = lines[+m2 - 2];
|
|
370
|
+
if (lineBefore) {
|
|
371
|
+
failedLine += chalk.dim(`\n ${+m2 - 1}\t| ${lineBefore.replaceAll('\t', ' ')}`);
|
|
372
|
+
}
|
|
373
|
+
failedLine += `\n${chalk.redBright`->`} ${m2}\t| ${lines[+m2 - 1]?.replaceAll('\t', ' ')}`;
|
|
374
|
+
if (lines.length > +m2) {
|
|
375
|
+
failedLine += chalk.dim(`\n ${+m2 + 1}\t| ${lines[+m2]?.replaceAll('\t', ' ')}`);
|
|
376
|
+
}
|
|
377
|
+
failedLine += chalk.dim('\n ...');
|
|
378
|
+
return res;
|
|
251
379
|
});
|
|
380
|
+
if (failedLine) {
|
|
381
|
+
text += failedLine;
|
|
382
|
+
}
|
|
383
|
+
mmf.fail(text);
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function pipeMMF(proc : ChildProcessWithoutNullStreams, mmf : MMF1) {
|
|
388
|
+
return new Promise<void>((resolve) => {
|
|
389
|
+
pipeStdoutToMMF(proc.stdout, mmf);
|
|
390
|
+
pipeStderrToMMF(proc.stderr, mmf);
|
|
252
391
|
|
|
253
392
|
// exit
|
|
254
393
|
proc.on('close', (code) => {
|
|
255
394
|
if (code === 0) {
|
|
256
|
-
mmf.pass();
|
|
395
|
+
mmf.strategy !== 'print' && mmf.pass();
|
|
257
396
|
}
|
|
258
397
|
else if (code !== 1) {
|
|
259
398
|
mmf.fail(`unknown exit code: ${code}`);
|
package/commands/test/utils.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/commands/update.ts
CHANGED
|
File without changes
|
package/commands/user.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import process from 'node:process';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import {Buffer} from 'node:buffer';
|
|
6
|
+
import prompts from 'prompts';
|
|
7
|
+
import {deleteSync} from 'del';
|
|
4
8
|
import {mainActor} from '../api/actors.js';
|
|
9
|
+
import {getIdentity, globalConfigDir} from '../mops.js';
|
|
10
|
+
import {encrypt} from '../pem.js';
|
|
5
11
|
|
|
6
12
|
export async function getUserProp(prop : string) {
|
|
7
13
|
let actor = await mainActor();
|
|
@@ -26,4 +32,68 @@ export async function setUserProp(prop : string, value : string) {
|
|
|
26
32
|
else {
|
|
27
33
|
console.log(chalk.red('Error: ') + res.err);
|
|
28
34
|
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function getPrincipal() {
|
|
38
|
+
let identity = await getIdentity();
|
|
39
|
+
if (identity) {
|
|
40
|
+
console.log(identity.getPrincipal().toText());
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.log(chalk.red('Error: ') + 'identity not found. Run ' + chalk.greenBright('mops user import') + ' command.');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type ImportIdentityOptions = {
|
|
48
|
+
encrypt : boolean;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export async function importPem(data : string, options : ImportIdentityOptions = {encrypt: true}) {
|
|
52
|
+
try {
|
|
53
|
+
if (!fs.existsSync(globalConfigDir)) {
|
|
54
|
+
fs.mkdirSync(globalConfigDir);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let password = '';
|
|
58
|
+
|
|
59
|
+
if (options.encrypt) {
|
|
60
|
+
let res = await prompts({
|
|
61
|
+
type: 'invisible',
|
|
62
|
+
name: 'password',
|
|
63
|
+
message: 'Enter password to encrypt identity.pem',
|
|
64
|
+
});
|
|
65
|
+
password = res.password;
|
|
66
|
+
|
|
67
|
+
if (!password) {
|
|
68
|
+
let res = await prompts({
|
|
69
|
+
type: 'confirm',
|
|
70
|
+
name: 'ok',
|
|
71
|
+
message: 'Are you sure you don\'t want to protect your identity.pem with a password?',
|
|
72
|
+
});
|
|
73
|
+
if (!res.ok) {
|
|
74
|
+
console.log('aborted');
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let identityPem = path.resolve(globalConfigDir, 'identity.pem');
|
|
81
|
+
let identityPemEncrypted = path.resolve(globalConfigDir, 'identity.pem.encrypted');
|
|
82
|
+
|
|
83
|
+
deleteSync([identityPem, identityPemEncrypted], {force: true});
|
|
84
|
+
|
|
85
|
+
// encrypted
|
|
86
|
+
if (password) {
|
|
87
|
+
let encrypted = await encrypt(Buffer.from(data), password);
|
|
88
|
+
fs.writeFileSync(identityPemEncrypted, encrypted);
|
|
89
|
+
}
|
|
90
|
+
// unencrypted
|
|
91
|
+
else {
|
|
92
|
+
fs.writeFileSync(identityPem, data);
|
|
93
|
+
}
|
|
94
|
+
console.log(chalk.green('Success'));
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
console.log(chalk.red('Error: ') + err);
|
|
98
|
+
}
|
|
29
99
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type _anon_class_10_1 =
|
|
1
|
+
type _anon_class_10_1 =
|
|
2
2
|
service {
|
|
3
3
|
getSchema: () -> (BenchSchema) query;
|
|
4
4
|
getStats: () -> (BenchResult) query;
|
|
@@ -7,20 +7,24 @@ type _anon_class_10_1 =
|
|
|
7
7
|
runCellUpdate: (nat, nat) -> (BenchResult);
|
|
8
8
|
runCellUpdateAwait: (nat, nat) -> (BenchResult);
|
|
9
9
|
};
|
|
10
|
-
type BenchSchema =
|
|
10
|
+
type BenchSchema =
|
|
11
11
|
record {
|
|
12
12
|
cols: vec text;
|
|
13
13
|
description: text;
|
|
14
14
|
name: text;
|
|
15
15
|
rows: vec text;
|
|
16
16
|
};
|
|
17
|
-
type BenchResult =
|
|
17
|
+
type BenchResult =
|
|
18
18
|
record {
|
|
19
19
|
instructions: int;
|
|
20
|
-
rts_collector_instructions: int;
|
|
21
20
|
rts_heap_size: int;
|
|
21
|
+
stable_memory_size: int;
|
|
22
|
+
rts_stable_memory_size: int;
|
|
23
|
+
rts_collector_instructions: int;
|
|
22
24
|
rts_memory_size: int;
|
|
23
25
|
rts_mutator_instructions: int;
|
|
24
26
|
rts_total_allocation: int;
|
|
27
|
+
rts_logical_stable_memory_size: int;
|
|
28
|
+
rts_reclaimed: int;
|
|
25
29
|
};
|
|
26
30
|
service : () -> _anon_class_10_1
|
|
@@ -5,10 +5,14 @@ import type { IDL } from '@dfinity/candid';
|
|
|
5
5
|
export interface BenchResult {
|
|
6
6
|
'instructions' : bigint,
|
|
7
7
|
'rts_memory_size' : bigint,
|
|
8
|
+
'stable_memory_size' : bigint,
|
|
9
|
+
'rts_stable_memory_size' : bigint,
|
|
10
|
+
'rts_logical_stable_memory_size' : bigint,
|
|
8
11
|
'rts_total_allocation' : bigint,
|
|
9
12
|
'rts_collector_instructions' : bigint,
|
|
10
13
|
'rts_mutator_instructions' : bigint,
|
|
11
14
|
'rts_heap_size' : bigint,
|
|
15
|
+
'rts_reclaimed' : bigint,
|
|
12
16
|
}
|
|
13
17
|
export interface BenchSchema {
|
|
14
18
|
'cols' : Array<string>,
|
|
@@ -7,11 +7,15 @@ export const idlFactory = ({ IDL }) => {
|
|
|
7
7
|
});
|
|
8
8
|
const BenchResult = IDL.Record({
|
|
9
9
|
'instructions' : IDL.Int,
|
|
10
|
+
'stable_memory_size' : IDL.Int,
|
|
11
|
+
'rts_stable_memory_size' : IDL.Int,
|
|
12
|
+
'rts_logical_stable_memory_size' : IDL.Int,
|
|
10
13
|
'rts_memory_size' : IDL.Int,
|
|
11
14
|
'rts_total_allocation' : IDL.Int,
|
|
12
15
|
'rts_collector_instructions' : IDL.Int,
|
|
13
16
|
'rts_mutator_instructions' : IDL.Int,
|
|
14
17
|
'rts_heap_size' : IDL.Int,
|
|
18
|
+
'rts_reclaimed' : IDL.Int,
|
|
15
19
|
});
|
|
16
20
|
const _anon_class_10_1 = IDL.Service({
|
|
17
21
|
'getSchema' : IDL.Func([], [BenchSchema], ['query']),
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/api/actors.js
CHANGED
|
@@ -3,28 +3,34 @@ import { idlFactory } from '../declarations/main/main.did.js';
|
|
|
3
3
|
import { idlFactory as storageIdlFactory } from '../declarations/storage/storage.did.js';
|
|
4
4
|
import { getEndpoint } from './network.js';
|
|
5
5
|
import { getNetwork } from './network.js';
|
|
6
|
+
let agentPromiseByPrincipal = new Map();
|
|
7
|
+
let getAgent = async (identity) => {
|
|
8
|
+
let principal = identity ? identity?.getPrincipal().toText() : '';
|
|
9
|
+
let agentPromise = agentPromiseByPrincipal.get(principal);
|
|
10
|
+
if (!agentPromise) {
|
|
11
|
+
let network = getNetwork();
|
|
12
|
+
let host = getEndpoint(network).host;
|
|
13
|
+
agentPromise = HttpAgent.create({
|
|
14
|
+
host,
|
|
15
|
+
identity,
|
|
16
|
+
shouldFetchRootKey: network === 'local',
|
|
17
|
+
verifyQuerySignatures: process.env.MOPS_VERIFY_QUERY_SIGNATURES !== 'false',
|
|
18
|
+
});
|
|
19
|
+
agentPromiseByPrincipal.set(principal, agentPromise);
|
|
20
|
+
}
|
|
21
|
+
return agentPromise;
|
|
22
|
+
};
|
|
6
23
|
export let mainActor = async (identity) => {
|
|
24
|
+
let agent = await getAgent(identity);
|
|
7
25
|
let network = getNetwork();
|
|
8
|
-
let host = getEndpoint(network).host;
|
|
9
26
|
let canisterId = getEndpoint(network).canisterId;
|
|
10
|
-
// @ts-ignore exactOptionalPropertyTypes
|
|
11
|
-
let agent = new HttpAgent({ host, identity });
|
|
12
|
-
if (network === 'local') {
|
|
13
|
-
await agent.fetchRootKey();
|
|
14
|
-
}
|
|
15
27
|
return Actor.createActor(idlFactory, {
|
|
16
28
|
agent,
|
|
17
29
|
canisterId,
|
|
18
30
|
});
|
|
19
31
|
};
|
|
20
32
|
export let storageActor = async (storageId, identity) => {
|
|
21
|
-
let
|
|
22
|
-
let host = getEndpoint(network).host;
|
|
23
|
-
// @ts-ignore exactOptionalPropertyTypes
|
|
24
|
-
let agent = new HttpAgent({ host, identity });
|
|
25
|
-
if (network === 'local') {
|
|
26
|
-
await agent.fetchRootKey();
|
|
27
|
-
}
|
|
33
|
+
let agent = await getAgent(identity);
|
|
28
34
|
return Actor.createActor(storageIdlFactory, {
|
|
29
35
|
agent,
|
|
30
36
|
canisterId: storageId,
|
package/dist/cache.js
CHANGED
|
@@ -2,13 +2,17 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import ncp from 'ncp';
|
|
4
4
|
import getFolderSize from 'get-folder-size';
|
|
5
|
-
import { getDependencyType, globalCacheDir, parseGithubURL } from './mops.js';
|
|
5
|
+
import { getDependencyType, getNetwork, getRootDir, globalCacheDir, parseGithubURL } from './mops.js';
|
|
6
6
|
import { getPackageId } from './helpers/get-package-id.js';
|
|
7
|
+
let getGlobalCacheDir = () => {
|
|
8
|
+
let network = getNetwork();
|
|
9
|
+
return path.join(globalCacheDir, network === 'ic' ? '' : network);
|
|
10
|
+
};
|
|
7
11
|
export let show = () => {
|
|
8
|
-
return
|
|
12
|
+
return getGlobalCacheDir();
|
|
9
13
|
};
|
|
10
14
|
export let getDepCacheDir = (cacheName) => {
|
|
11
|
-
return path.join(
|
|
15
|
+
return path.join(getGlobalCacheDir(), 'packages', cacheName);
|
|
12
16
|
};
|
|
13
17
|
export let isDepCached = (cacheName) => {
|
|
14
18
|
let dir = getDepCacheDir(cacheName);
|
|
@@ -26,7 +30,7 @@ export function getGithubDepCacheName(name, repo) {
|
|
|
26
30
|
return `_github/${name}#${branch}` + (commitHash ? `@${commitHash}` : '');
|
|
27
31
|
}
|
|
28
32
|
export let addCache = (cacheName, source) => {
|
|
29
|
-
let dest = path.join(
|
|
33
|
+
let dest = path.join(getGlobalCacheDir(), 'packages', cacheName);
|
|
30
34
|
fs.mkdirSync(dest, { recursive: true });
|
|
31
35
|
return new Promise((resolve, reject) => {
|
|
32
36
|
ncp.ncp(source, dest, { stopOnErr: true }, (err) => {
|
|
@@ -38,7 +42,7 @@ export let addCache = (cacheName, source) => {
|
|
|
38
42
|
});
|
|
39
43
|
};
|
|
40
44
|
export let copyCache = (cacheName, dest) => {
|
|
41
|
-
let source = path.join(
|
|
45
|
+
let source = path.join(getGlobalCacheDir(), 'packages', cacheName);
|
|
42
46
|
fs.mkdirSync(dest, { recursive: true });
|
|
43
47
|
return new Promise((resolve, reject) => {
|
|
44
48
|
ncp.ncp(source, dest, { stopOnErr: true }, (err) => {
|
|
@@ -50,7 +54,7 @@ export let copyCache = (cacheName, dest) => {
|
|
|
50
54
|
});
|
|
51
55
|
};
|
|
52
56
|
export let cacheSize = async () => {
|
|
53
|
-
let dir = path.join(
|
|
57
|
+
let dir = path.join(getGlobalCacheDir());
|
|
54
58
|
fs.mkdirSync(dir, { recursive: true });
|
|
55
59
|
let size = await getFolderSize.strict(dir);
|
|
56
60
|
if (size < 1024 * 1024) {
|
|
@@ -59,6 +63,11 @@ export let cacheSize = async () => {
|
|
|
59
63
|
return (size / 1024 / 1024).toFixed(2) + ' MB';
|
|
60
64
|
};
|
|
61
65
|
export let cleanCache = async () => {
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
if (!getGlobalCacheDir().endsWith('mops/cache') && !getGlobalCacheDir().endsWith('/mops') && !getGlobalCacheDir().endsWith('/mops/' + getNetwork())) {
|
|
67
|
+
throw new Error('Invalid cache directory: ' + getGlobalCacheDir());
|
|
68
|
+
}
|
|
69
|
+
// local cache
|
|
70
|
+
fs.rmSync(path.join(getRootDir(), '.mops'), { recursive: true, force: true });
|
|
71
|
+
// global cache
|
|
72
|
+
fs.rmSync(getGlobalCacheDir(), { recursive: true, force: true });
|
|
64
73
|
};
|