ic-mops 1.12.0 → 2.0.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.
Files changed (322) hide show
  1. package/.DS_Store +0 -0
  2. package/.eslintrc.json +7 -7
  3. package/CHANGELOG.md +6 -0
  4. package/api/actors.ts +41 -37
  5. package/api/downloadPackageFiles.ts +75 -61
  6. package/api/getHighestVersion.ts +5 -5
  7. package/api/index.ts +4 -4
  8. package/api/network.ts +19 -21
  9. package/api/resolveVersion.ts +14 -11
  10. package/bin/mops.js +1 -1
  11. package/bundle/bench/bench-canister.mo +109 -101
  12. package/bundle/bench/user-bench.mo +6 -6
  13. package/bundle/bin/mops.js +1 -1
  14. package/bundle/cli.js +797 -792
  15. package/bundle/cli.tgz +0 -0
  16. package/bundle/package.json +6 -5
  17. package/bundle/templates/mops-publish.yml +3 -3
  18. package/bundle/templates/mops-test.yml +3 -3
  19. package/bundle/templates/src/lib.mo +13 -13
  20. package/bundle/templates/test/lib.test.mo +2 -2
  21. package/bundle-package-json.ts +8 -8
  22. package/cache.ts +80 -65
  23. package/check-requirements.ts +49 -45
  24. package/cli.ts +577 -376
  25. package/commands/add.ts +142 -129
  26. package/commands/available-updates.ts +55 -41
  27. package/commands/bench/bench-canister.mo +114 -108
  28. package/commands/bench/user-bench.mo +6 -6
  29. package/commands/bench-replica.ts +146 -118
  30. package/commands/bench.ts +563 -497
  31. package/commands/build.ts +177 -0
  32. package/commands/bump.ts +68 -57
  33. package/commands/check-candid.ts +24 -0
  34. package/commands/docs-coverage.ts +124 -102
  35. package/commands/docs.ts +118 -108
  36. package/commands/format.ts +171 -155
  37. package/commands/init.ts +301 -275
  38. package/commands/install/install-all.ts +75 -62
  39. package/commands/install/install-dep.ts +43 -28
  40. package/commands/install/install-deps.ts +23 -15
  41. package/commands/install/install-local-dep.ts +42 -34
  42. package/commands/install/install-mops-dep.ts +154 -123
  43. package/commands/install/sync-local-cache.ts +39 -35
  44. package/commands/maintainer.ts +109 -99
  45. package/commands/outdated.ts +30 -24
  46. package/commands/owner.ts +107 -99
  47. package/commands/publish.ts +534 -443
  48. package/commands/remove.ts +119 -89
  49. package/commands/replica.ts +391 -316
  50. package/commands/search.ts +42 -36
  51. package/commands/self.ts +63 -56
  52. package/commands/sources.ts +66 -49
  53. package/commands/sync.ts +92 -75
  54. package/commands/template.ts +145 -102
  55. package/commands/test/mmf1.ts +146 -119
  56. package/commands/test/reporters/compact-reporter.ts +87 -84
  57. package/commands/test/reporters/files-reporter.ts +56 -51
  58. package/commands/test/reporters/reporter.ts +12 -6
  59. package/commands/test/reporters/silent-reporter.ts +58 -59
  60. package/commands/test/reporters/verbose-reporter.ts +66 -54
  61. package/commands/test/test.ts +498 -401
  62. package/commands/test/utils.ts +72 -67
  63. package/commands/toolchain/index.ts +363 -322
  64. package/commands/toolchain/moc.ts +78 -50
  65. package/commands/toolchain/pocket-ic.ts +41 -34
  66. package/commands/toolchain/toolchain-utils.ts +92 -72
  67. package/commands/toolchain/wasmtime.ts +37 -34
  68. package/commands/update.ts +82 -64
  69. package/commands/user.ts +90 -81
  70. package/commands/watch/deployer.ts +188 -152
  71. package/commands/watch/error-checker.ts +90 -80
  72. package/commands/watch/formatter.ts +72 -60
  73. package/commands/watch/generator.ts +116 -96
  74. package/commands/watch/globMoFiles.ts +13 -13
  75. package/commands/watch/parseDfxJson.ts +63 -57
  76. package/commands/watch/tester.ts +83 -65
  77. package/commands/watch/warning-checker.ts +149 -136
  78. package/commands/watch/watch.ts +123 -95
  79. package/dist/api/actors.d.ts +4 -4
  80. package/dist/api/actors.js +8 -8
  81. package/dist/api/downloadPackageFiles.d.ts +2 -2
  82. package/dist/api/downloadPackageFiles.js +10 -10
  83. package/dist/api/getHighestVersion.js +1 -1
  84. package/dist/api/index.d.ts +4 -4
  85. package/dist/api/index.js +4 -4
  86. package/dist/api/network.js +9 -9
  87. package/dist/api/resolveVersion.js +3 -3
  88. package/dist/bin/mops.js +1 -1
  89. package/dist/bundle-package-json.js +8 -8
  90. package/dist/cache.js +22 -17
  91. package/dist/check-requirements.js +11 -11
  92. package/dist/cli.js +283 -186
  93. package/dist/commands/add.d.ts +1 -1
  94. package/dist/commands/add.js +40 -37
  95. package/dist/commands/available-updates.d.ts +1 -1
  96. package/dist/commands/available-updates.js +18 -12
  97. package/dist/commands/bench/bench-canister.mo +114 -108
  98. package/dist/commands/bench/user-bench.mo +6 -6
  99. package/dist/commands/bench-replica.d.ts +4 -4
  100. package/dist/commands/bench-replica.js +45 -34
  101. package/dist/commands/bench.d.ts +5 -5
  102. package/dist/commands/bench.js +134 -118
  103. package/dist/commands/build.d.ts +7 -0
  104. package/dist/commands/build.js +121 -0
  105. package/dist/commands/bump.js +27 -18
  106. package/dist/commands/check-candid.d.ts +4 -0
  107. package/dist/commands/check-candid.js +15 -0
  108. package/dist/commands/docs-coverage.d.ts +1 -1
  109. package/dist/commands/docs-coverage.js +45 -31
  110. package/dist/commands/docs.d.ts +1 -1
  111. package/dist/commands/docs.js +39 -38
  112. package/dist/commands/format.js +31 -27
  113. package/dist/commands/init.js +102 -92
  114. package/dist/commands/install/install-all.d.ts +2 -2
  115. package/dist/commands/install/install-all.js +23 -21
  116. package/dist/commands/install/install-dep.d.ts +1 -1
  117. package/dist/commands/install/install-dep.js +21 -8
  118. package/dist/commands/install/install-deps.d.ts +1 -1
  119. package/dist/commands/install/install-deps.js +1 -1
  120. package/dist/commands/install/install-local-dep.js +11 -9
  121. package/dist/commands/install/install-mops-dep.d.ts +1 -1
  122. package/dist/commands/install/install-mops-dep.js +32 -27
  123. package/dist/commands/install/sync-local-cache.js +10 -10
  124. package/dist/commands/maintainer.js +21 -21
  125. package/dist/commands/outdated.js +12 -8
  126. package/dist/commands/owner.js +21 -21
  127. package/dist/commands/publish.js +148 -128
  128. package/dist/commands/remove.d.ts +1 -1
  129. package/dist/commands/remove.js +42 -30
  130. package/dist/commands/replica.d.ts +7 -7
  131. package/dist/commands/replica.js +85 -57
  132. package/dist/commands/search.js +15 -13
  133. package/dist/commands/self.js +31 -28
  134. package/dist/commands/sources.d.ts +5 -1
  135. package/dist/commands/sources.js +23 -17
  136. package/dist/commands/sync.d.ts +1 -1
  137. package/dist/commands/sync.js +38 -25
  138. package/dist/commands/template.js +66 -56
  139. package/dist/commands/test/mmf1.d.ts +3 -3
  140. package/dist/commands/test/mmf1.js +33 -31
  141. package/dist/commands/test/reporters/compact-reporter.d.ts +3 -3
  142. package/dist/commands/test/reporters/compact-reporter.js +19 -15
  143. package/dist/commands/test/reporters/files-reporter.d.ts +3 -3
  144. package/dist/commands/test/reporters/files-reporter.js +18 -14
  145. package/dist/commands/test/reporters/reporter.d.ts +2 -2
  146. package/dist/commands/test/reporters/silent-reporter.d.ts +3 -3
  147. package/dist/commands/test/reporters/silent-reporter.js +4 -4
  148. package/dist/commands/test/reporters/verbose-reporter.d.ts +3 -3
  149. package/dist/commands/test/reporters/verbose-reporter.js +17 -13
  150. package/dist/commands/test/test.d.ts +4 -4
  151. package/dist/commands/test/test.js +134 -112
  152. package/dist/commands/test/utils.d.ts +3 -3
  153. package/dist/commands/test/utils.js +17 -17
  154. package/dist/commands/toolchain/index.d.ts +1 -1
  155. package/dist/commands/toolchain/index.js +81 -69
  156. package/dist/commands/toolchain/moc.d.ts +1 -1
  157. package/dist/commands/toolchain/moc.js +48 -24
  158. package/dist/commands/toolchain/pocket-ic.js +12 -12
  159. package/dist/commands/toolchain/toolchain-utils.d.ts +2 -0
  160. package/dist/commands/toolchain/toolchain-utils.js +32 -23
  161. package/dist/commands/toolchain/wasmtime.js +11 -11
  162. package/dist/commands/update.d.ts +1 -1
  163. package/dist/commands/update.js +18 -14
  164. package/dist/commands/user.js +31 -28
  165. package/dist/commands/watch/deployer.d.ts +4 -4
  166. package/dist/commands/watch/deployer.js +45 -36
  167. package/dist/commands/watch/error-checker.d.ts +2 -2
  168. package/dist/commands/watch/error-checker.js +27 -27
  169. package/dist/commands/watch/formatter.d.ts +4 -4
  170. package/dist/commands/watch/formatter.js +17 -17
  171. package/dist/commands/watch/generator.d.ts +3 -3
  172. package/dist/commands/watch/generator.js +28 -23
  173. package/dist/commands/watch/globMoFiles.js +8 -8
  174. package/dist/commands/watch/parseDfxJson.d.ts +2 -2
  175. package/dist/commands/watch/parseDfxJson.js +9 -9
  176. package/dist/commands/watch/tester.d.ts +4 -4
  177. package/dist/commands/watch/tester.js +23 -21
  178. package/dist/commands/watch/warning-checker.d.ts +3 -3
  179. package/dist/commands/watch/warning-checker.js +36 -36
  180. package/dist/commands/watch/watch.js +45 -32
  181. package/dist/environments/nodejs/cli.d.ts +1 -0
  182. package/dist/environments/nodejs/cli.js +4 -0
  183. package/dist/environments/web/cli.d.ts +1 -0
  184. package/dist/environments/web/cli.js +4 -0
  185. package/dist/error.d.ts +1 -0
  186. package/dist/error.js +5 -0
  187. package/dist/fix-dist.js +5 -5
  188. package/dist/helpers/find-changelog-entry.js +8 -5
  189. package/dist/helpers/get-dep-name.js +2 -2
  190. package/dist/helpers/get-dfx-version.js +4 -4
  191. package/dist/helpers/get-moc-path.js +8 -7
  192. package/dist/helpers/get-moc-version.js +10 -7
  193. package/dist/helpers/get-package-id.js +2 -2
  194. package/dist/helpers/is-candid-compatible.d.ts +1 -0
  195. package/dist/helpers/is-candid-compatible.js +20 -0
  196. package/dist/integrity.d.ts +1 -1
  197. package/dist/integrity.js +47 -38
  198. package/dist/jest.config.d.ts +11 -0
  199. package/dist/jest.config.js +14 -0
  200. package/dist/mops.d.ts +6 -6
  201. package/dist/mops.js +87 -80
  202. package/dist/notify-installs.js +4 -4
  203. package/dist/package.json +9 -5
  204. package/dist/pem.d.ts +3 -3
  205. package/dist/pem.js +20 -12
  206. package/dist/release-cli.js +20 -20
  207. package/dist/resolve-packages.d.ts +1 -1
  208. package/dist/resolve-packages.js +52 -36
  209. package/dist/templates/mops-publish.yml +3 -3
  210. package/dist/templates/mops-test.yml +3 -3
  211. package/dist/templates/src/lib.mo +13 -13
  212. package/dist/templates/test/lib.test.mo +2 -2
  213. package/dist/templates.js +1 -1
  214. package/dist/tests/cli.test.d.ts +1 -0
  215. package/dist/tests/cli.test.js +63 -0
  216. package/dist/types.d.ts +14 -4
  217. package/dist/vessel.d.ts +2 -2
  218. package/dist/vessel.js +41 -34
  219. package/dist/wasm/pkg/bundler/package.json +20 -0
  220. package/dist/wasm/pkg/bundler/wasm.d.ts +3 -0
  221. package/dist/wasm/pkg/bundler/wasm.js +5 -0
  222. package/dist/wasm/pkg/bundler/wasm_bg.js +93 -0
  223. package/dist/wasm/pkg/bundler/wasm_bg.wasm +0 -0
  224. package/dist/wasm/pkg/bundler/wasm_bg.wasm.d.ts +8 -0
  225. package/dist/wasm/pkg/nodejs/package.json +14 -0
  226. package/dist/wasm/pkg/nodejs/wasm.d.ts +3 -0
  227. package/dist/wasm/pkg/nodejs/wasm.js +98 -0
  228. package/dist/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
  229. package/dist/wasm/pkg/nodejs/wasm_bg.wasm.d.ts +8 -0
  230. package/dist/wasm/pkg/web/package.json +18 -0
  231. package/dist/wasm/pkg/web/wasm.d.ts +35 -0
  232. package/dist/wasm/pkg/web/wasm.js +191 -0
  233. package/dist/wasm/pkg/web/wasm_bg.wasm +0 -0
  234. package/dist/wasm/pkg/web/wasm_bg.wasm.d.ts +8 -0
  235. package/dist/wasm.d.ts +5 -0
  236. package/dist/wasm.js +10 -0
  237. package/environments/nodejs/cli.ts +6 -0
  238. package/environments/web/cli.ts +6 -0
  239. package/error.ts +6 -0
  240. package/fix-dist.ts +5 -5
  241. package/global.d.ts +3 -3
  242. package/helpers/find-changelog-entry.ts +26 -23
  243. package/helpers/get-dep-name.ts +5 -5
  244. package/helpers/get-dfx-version.ts +8 -9
  245. package/helpers/get-moc-path.ts +25 -26
  246. package/helpers/get-moc-version.ts +21 -19
  247. package/helpers/get-package-id.ts +4 -4
  248. package/helpers/is-candid-compatible.ts +22 -0
  249. package/integrity.ts +270 -236
  250. package/jest.config.js +14 -0
  251. package/mops.ts +238 -215
  252. package/notify-installs.ts +16 -17
  253. package/package.json +19 -10
  254. package/parallel.ts +28 -24
  255. package/pem.ts +55 -47
  256. package/release-cli.ts +73 -39
  257. package/resolve-packages.ts +231 -189
  258. package/templates/mops-publish.yml +3 -3
  259. package/templates/mops-test.yml +3 -3
  260. package/templates/src/lib.mo +13 -13
  261. package/templates/test/lib.test.mo +2 -2
  262. package/templates.ts +4 -4
  263. package/tests/__snapshots__/cli.test.ts.snap +202 -0
  264. package/tests/build/error/candid/bar.did +3 -0
  265. package/tests/build/error/dfx.json +12 -0
  266. package/tests/build/error/mops.toml +9 -0
  267. package/tests/build/error/src/Bar.mo +5 -0
  268. package/tests/build/error/src/Foo.mo +5 -0
  269. package/tests/build/success/.dfx/local/canister_ids.json +17 -0
  270. package/tests/build/success/.dfx/local/canisters/bar/bar.did +3 -0
  271. package/tests/build/success/.dfx/local/canisters/bar/bar.most +4 -0
  272. package/tests/build/success/.dfx/local/canisters/bar/bar.wasm +0 -0
  273. package/tests/build/success/.dfx/local/canisters/bar/constructor.did +3 -0
  274. package/tests/build/success/.dfx/local/canisters/bar/index.js +42 -0
  275. package/tests/build/success/.dfx/local/canisters/bar/init_args.txt +1 -0
  276. package/tests/build/success/.dfx/local/canisters/bar/service.did +3 -0
  277. package/tests/build/success/.dfx/local/canisters/bar/service.did.d.ts +7 -0
  278. package/tests/build/success/.dfx/local/canisters/bar/service.did.js +4 -0
  279. package/tests/build/success/.dfx/local/canisters/foo/constructor.did +3 -0
  280. package/tests/build/success/.dfx/local/canisters/foo/foo.did +3 -0
  281. package/tests/build/success/.dfx/local/canisters/foo/foo.most +4 -0
  282. package/tests/build/success/.dfx/local/canisters/foo/foo.wasm +0 -0
  283. package/tests/build/success/.dfx/local/canisters/foo/index.js +42 -0
  284. package/tests/build/success/.dfx/local/canisters/foo/init_args.txt +1 -0
  285. package/tests/build/success/.dfx/local/canisters/foo/service.did +3 -0
  286. package/tests/build/success/.dfx/local/canisters/foo/service.did.d.ts +7 -0
  287. package/tests/build/success/.dfx/local/canisters/foo/service.did.js +4 -0
  288. package/tests/build/success/.dfx/local/lsp/ucwa4-rx777-77774-qaada-cai.did +3 -0
  289. package/tests/build/success/.dfx/local/lsp/ulvla-h7777-77774-qaacq-cai.did +3 -0
  290. package/tests/build/success/.dfx/local/network-id +4 -0
  291. package/tests/build/success/candid/bar.did +3 -0
  292. package/tests/build/success/dfx.json +12 -0
  293. package/tests/build/success/mops.toml +9 -0
  294. package/tests/build/success/src/Bar.mo +5 -0
  295. package/tests/build/success/src/Foo.mo +5 -0
  296. package/tests/check-candid/a.did +3 -0
  297. package/tests/check-candid/b.did +5 -0
  298. package/tests/check-candid/c.did +3 -0
  299. package/tests/cli.test.ts +82 -0
  300. package/tsconfig.json +26 -19
  301. package/types.ts +41 -31
  302. package/vessel.ts +219 -187
  303. package/wasm/Cargo.lock +1475 -0
  304. package/wasm/Cargo.toml +28 -0
  305. package/wasm/pkg/bundler/package.json +20 -0
  306. package/wasm/pkg/bundler/wasm.d.ts +3 -0
  307. package/wasm/pkg/bundler/wasm.js +5 -0
  308. package/wasm/pkg/bundler/wasm_bg.js +93 -0
  309. package/wasm/pkg/bundler/wasm_bg.wasm +0 -0
  310. package/wasm/pkg/bundler/wasm_bg.wasm.d.ts +8 -0
  311. package/wasm/pkg/nodejs/package.json +14 -0
  312. package/wasm/pkg/nodejs/wasm.d.ts +3 -0
  313. package/wasm/pkg/nodejs/wasm.js +98 -0
  314. package/wasm/pkg/nodejs/wasm_bg.wasm +0 -0
  315. package/wasm/pkg/nodejs/wasm_bg.wasm.d.ts +8 -0
  316. package/wasm/pkg/web/package.json +18 -0
  317. package/wasm/pkg/web/wasm.d.ts +35 -0
  318. package/wasm/pkg/web/wasm.js +191 -0
  319. package/wasm/pkg/web/wasm_bg.wasm +0 -0
  320. package/wasm/pkg/web/wasm_bg.wasm.d.ts +8 -0
  321. package/wasm/src/lib.rs +17 -0
  322. package/wasm.ts +16 -0
@@ -1,419 +1,516 @@
1
- import process from 'node:process';
2
- import {spawn} from 'node:child_process';
3
- import path from 'node:path';
4
- import fs from 'node:fs';
5
- import os from 'node:os';
6
- import {PassThrough} from 'node:stream';
7
-
8
- import chalk from 'chalk';
9
- import {globSync} from 'glob';
10
- import chokidar from 'chokidar';
11
- import debounce from 'debounce';
12
- import {SemVer} from 'semver';
13
- import {ActorMethod} from '@icp-sdk/core/agent';
14
-
15
- import {sources} from '../sources.js';
16
- import {getRootDir, readConfig} from '../../mops.js';
17
- import {parallel} from '../../parallel.js';
18
-
19
- import {MMF1} from './mmf1.js';
20
- import {absToRel, pipeMMF, pipeStderrToMMF, pipeStdoutToMMF} from './utils.js';
21
- import {Reporter} from './reporters/reporter.js';
22
- import {VerboseReporter} from './reporters/verbose-reporter.js';
23
- import {FilesReporter} from './reporters/files-reporter.js';
24
- import {CompactReporter} from './reporters/compact-reporter.js';
25
- import {SilentReporter} from './reporters/silent-reporter.js';
26
- import {toolchain} from '../toolchain/index.js';
27
- import {Replica} from '../replica.js';
28
- import {TestMode} from '../../types.js';
29
- import {getDfxVersion} from '../../helpers/get-dfx-version.js';
1
+ import process from "node:process";
2
+ import { spawn } from "node:child_process";
3
+ import path from "node:path";
4
+ import fs from "node:fs";
5
+ import os from "node:os";
6
+ import { PassThrough } from "node:stream";
7
+
8
+ import chalk from "chalk";
9
+ import { globSync } from "glob";
10
+ import chokidar from "chokidar";
11
+ import debounce from "debounce";
12
+ import { SemVer } from "semver";
13
+ import { ActorMethod } from "@icp-sdk/core/agent";
14
+
15
+ import { sources } from "../sources.js";
16
+ import { getRootDir, readConfig } from "../../mops.js";
17
+ import { parallel } from "../../parallel.js";
18
+
19
+ import { MMF1 } from "./mmf1.js";
20
+ import {
21
+ absToRel,
22
+ pipeMMF,
23
+ pipeStderrToMMF,
24
+ pipeStdoutToMMF,
25
+ } from "./utils.js";
26
+ import { Reporter } from "./reporters/reporter.js";
27
+ import { VerboseReporter } from "./reporters/verbose-reporter.js";
28
+ import { FilesReporter } from "./reporters/files-reporter.js";
29
+ import { CompactReporter } from "./reporters/compact-reporter.js";
30
+ import { SilentReporter } from "./reporters/silent-reporter.js";
31
+ import { toolchain } from "../toolchain/index.js";
32
+ import { Replica } from "../replica.js";
33
+ import { TestMode } from "../../types.js";
34
+ import { getDfxVersion } from "../../helpers/get-dfx-version.js";
30
35
 
31
36
  let ignore = [
32
- '**/node_modules/**',
33
- '**/.mops/**',
34
- '**/.vessel/**',
35
- '**/.git/**',
37
+ "**/node_modules/**",
38
+ "**/.mops/**",
39
+ "**/.vessel/**",
40
+ "**/.git/**",
36
41
  ];
37
42
 
38
43
  let globConfig = {
39
- nocase: true,
40
- ignore: ignore,
44
+ nocase: true,
45
+ ignore: ignore,
41
46
  };
42
47
 
43
- type ReporterName = 'verbose' | 'files' | 'compact' | 'silent';
44
- type ReplicaName = 'dfx' | 'pocket-ic' | 'dfx-pocket-ic';
48
+ type ReporterName = "verbose" | "files" | "compact" | "silent";
49
+ type ReplicaName = "dfx" | "pocket-ic" | "dfx-pocket-ic";
45
50
 
46
51
  type TestOptions = {
47
- watch : boolean;
48
- reporter : ReporterName;
49
- mode : TestMode;
50
- replica : ReplicaName;
51
- verbose : boolean;
52
+ watch: boolean;
53
+ reporter: ReporterName;
54
+ mode: TestMode;
55
+ replica: ReplicaName;
56
+ verbose: boolean;
52
57
  };
53
58
 
54
-
55
59
  let replica = new Replica();
56
- let replicaStartPromise : Promise<void> | undefined;
57
-
58
- async function startReplicaOnce(replica : Replica, type : ReplicaName) {
59
- if (!replicaStartPromise) {
60
- replicaStartPromise = new Promise((resolve) => {
61
- replica.start({type, silent: true}).then(resolve);
62
- });
63
- }
64
- return replicaStartPromise;
60
+ let replicaStartPromise: Promise<void> | undefined;
61
+
62
+ async function startReplicaOnce(replica: Replica, type: ReplicaName) {
63
+ if (!replicaStartPromise) {
64
+ replicaStartPromise = new Promise((resolve) => {
65
+ replica.start({ type, silent: true }).then(resolve);
66
+ });
67
+ }
68
+ return replicaStartPromise;
65
69
  }
66
70
 
67
- export async function test(filter = '', options : Partial<TestOptions> = {}) {
68
- let config = readConfig();
69
- let rootDir = getRootDir();
70
-
71
- let replicaType = options.replica ?? (config.toolchain?.['pocket-ic'] ? 'pocket-ic' : 'dfx' as ReplicaName);
72
-
73
- if (replicaType === 'pocket-ic' && !config.toolchain?.['pocket-ic']) {
74
- let dfxVersion = getDfxVersion();
75
- if (!dfxVersion || new SemVer(dfxVersion).compare('0.24.1') < 0) {
76
- console.log(chalk.red('Please update dfx to the version >=0.24.1 or specify pocket-ic version in mops.toml'));
77
- process.exit(1);
78
- }
79
- else {
80
- replicaType = 'dfx-pocket-ic';
81
- }
82
- }
83
-
84
- replica.type = replicaType;
85
- replica.verbose = !!options.verbose;
86
-
87
- if (options.watch) {
88
- replica.ttl = 60 * 15; // 15 minutes
89
-
90
- let sigint = false;
91
- process.on('SIGINT', () => {
92
- if (sigint) {
93
- console.log('Force exit');
94
- process.exit(0);
95
- }
96
- sigint = true;
97
-
98
- if (replicaStartPromise) {
99
- console.log('Stopping replica...');
100
- replica.stop(true).then(() => {
101
- process.exit(0);
102
- });
103
- }
104
- else {
105
- process.exit(0);
106
- }
107
- });
108
-
109
- // todo: run only changed for *.test.mo?
110
- // todo: run all for *.mo?
111
-
112
- let curRun = Promise.resolve(true);
113
- let controller = new AbortController();
114
-
115
- let run = debounce(async () => {
116
- controller.abort();
117
- await curRun;
118
-
119
- console.clear();
120
- process.stdout.write('\x1Bc');
121
-
122
- controller = new AbortController();
123
- curRun = runAll(options.reporter, filter, options.mode, replicaType, true, controller.signal);
124
- await curRun;
125
-
126
- console.log('-'.repeat(50));
127
- console.log('Waiting for file changes...');
128
- console.log(chalk.gray((`Press ${chalk.gray('Ctrl+C')} to exit.`)));
129
- }, 200);
130
-
131
- let watcher = chokidar.watch([
132
- path.join(rootDir, '**/*.mo'),
133
- path.join(rootDir, 'mops.toml'),
134
- ], {
135
- ignored: ignore,
136
- ignoreInitial: true,
137
- });
138
-
139
- watcher.on('all', () => {
140
- run();
141
- });
142
- run();
143
- }
144
- else {
145
- let passed = await runAll(options.reporter, filter, options.mode, replicaType);
146
- if (!passed) {
147
- process.exit(1);
148
- }
149
- }
71
+ export async function test(filter = "", options: Partial<TestOptions> = {}) {
72
+ let config = readConfig();
73
+ let rootDir = getRootDir();
74
+
75
+ let replicaType =
76
+ options.replica ??
77
+ (config.toolchain?.["pocket-ic"] ? "pocket-ic" : ("dfx" as ReplicaName));
78
+
79
+ if (replicaType === "pocket-ic" && !config.toolchain?.["pocket-ic"]) {
80
+ let dfxVersion = getDfxVersion();
81
+ if (!dfxVersion || new SemVer(dfxVersion).compare("0.24.1") < 0) {
82
+ console.log(
83
+ chalk.red(
84
+ "Please update dfx to the version >=0.24.1 or specify pocket-ic version in mops.toml",
85
+ ),
86
+ );
87
+ process.exit(1);
88
+ } else {
89
+ replicaType = "dfx-pocket-ic";
90
+ }
91
+ }
92
+
93
+ replica.type = replicaType;
94
+ replica.verbose = !!options.verbose;
95
+
96
+ if (options.watch) {
97
+ replica.ttl = 60 * 15; // 15 minutes
98
+
99
+ let sigint = false;
100
+ process.on("SIGINT", () => {
101
+ if (sigint) {
102
+ console.log("Force exit");
103
+ process.exit(0);
104
+ }
105
+ sigint = true;
106
+
107
+ if (replicaStartPromise) {
108
+ console.log("Stopping replica...");
109
+ replica.stop(true).then(() => {
110
+ process.exit(0);
111
+ });
112
+ } else {
113
+ process.exit(0);
114
+ }
115
+ });
116
+
117
+ // todo: run only changed for *.test.mo?
118
+ // todo: run all for *.mo?
119
+
120
+ let curRun = Promise.resolve(true);
121
+ let controller = new AbortController();
122
+
123
+ let run = debounce(async () => {
124
+ controller.abort();
125
+ await curRun;
126
+
127
+ console.clear();
128
+ process.stdout.write("\x1Bc");
129
+
130
+ controller = new AbortController();
131
+ curRun = runAll(
132
+ options.reporter,
133
+ filter,
134
+ options.mode,
135
+ replicaType,
136
+ true,
137
+ controller.signal,
138
+ );
139
+ await curRun;
140
+
141
+ console.log("-".repeat(50));
142
+ console.log("Waiting for file changes...");
143
+ console.log(chalk.gray(`Press ${chalk.gray("Ctrl+C")} to exit.`));
144
+ }, 200);
145
+
146
+ let watcher = chokidar.watch(
147
+ [path.join(rootDir, "**/*.mo"), path.join(rootDir, "mops.toml")],
148
+ {
149
+ ignored: ignore,
150
+ ignoreInitial: true,
151
+ },
152
+ );
153
+
154
+ watcher.on("all", () => {
155
+ run();
156
+ });
157
+ run();
158
+ } else {
159
+ let passed = await runAll(
160
+ options.reporter,
161
+ filter,
162
+ options.mode,
163
+ replicaType,
164
+ );
165
+ if (!passed) {
166
+ process.exit(1);
167
+ }
168
+ }
150
169
  }
151
170
 
152
- let mocPath = '';
153
- let wasmtimePath = '';
154
-
155
- async function runAll(reporterName : ReporterName | undefined, filter = '', mode : TestMode = 'interpreter', replicaType : ReplicaName, watch = false, signal ?: AbortSignal) : Promise<boolean> {
156
- let done = await testWithReporter(reporterName, filter, mode, replicaType, watch, signal);
157
- return done;
171
+ let mocPath = "";
172
+ let wasmtimePath = "";
173
+
174
+ async function runAll(
175
+ reporterName: ReporterName | undefined,
176
+ filter = "",
177
+ mode: TestMode = "interpreter",
178
+ replicaType: ReplicaName,
179
+ watch = false,
180
+ signal?: AbortSignal,
181
+ ): Promise<boolean> {
182
+ let done = await testWithReporter(
183
+ reporterName,
184
+ filter,
185
+ mode,
186
+ replicaType,
187
+ watch,
188
+ signal,
189
+ );
190
+ return done;
158
191
  }
159
192
 
160
- export async function testWithReporter(reporterName : ReporterName | Reporter | undefined, filter = '', defaultMode : TestMode = 'interpreter', replicaType : ReplicaName, watch = false, signal ?: AbortSignal) : Promise<boolean> {
161
- let rootDir = getRootDir();
162
- let files : string[] = [];
163
- let libFiles = globSync('**/test?(s)/lib.mo', globConfig);
164
- if (libFiles[0]) {
165
- files = [libFiles[0]];
166
- }
167
- else {
168
- let globStr = '**/test?(s)/**/*.test.mo';
169
- if (filter) {
170
- globStr = `**/test?(s)/**/*${filter}*.mo`;
171
- }
172
- files = globSync(path.join(rootDir, globStr), globConfig);
173
- }
174
- if (!files.length) {
175
- if (filter) {
176
- console.log(`No test files found for filter '${filter}'`);
177
- return false;
178
- }
179
- console.log('No test files found');
180
- console.log('Put your tests in \'test\' directory in *.test.mo files');
181
- return false;
182
- }
183
-
184
-
185
- let reporter : Reporter;
186
-
187
- if (!reporterName || typeof reporterName === 'string') {
188
- if (!reporterName) {
189
- reporterName = files.length > 1 ? 'files' : 'verbose';
190
- }
191
-
192
- if (reporterName == 'compact') {
193
- reporter = new CompactReporter;
194
- }
195
- else if (reporterName == 'files') {
196
- reporter = new FilesReporter;
197
- }
198
- else if (reporterName == 'silent') {
199
- reporter = new SilentReporter;
200
- }
201
- else {
202
- reporter = new VerboseReporter;
203
- }
204
- }
205
- else {
206
- reporter = reporterName;
207
- }
208
-
209
- reporter.addFiles(files);
210
-
211
- let config = readConfig();
212
- let sourcesArr = await sources();
213
-
214
- if (!mocPath) {
215
- mocPath = await toolchain.bin('moc', {fallback: true});
216
- }
217
-
218
- let testTempDir = path.join(getRootDir(), '.mops/.test/');
219
- replica.dir = testTempDir;
220
-
221
- fs.rmSync(testTempDir, {recursive: true, force: true});
222
- fs.mkdirSync(testTempDir, {recursive: true});
223
-
224
- let filesWithMode = files.map((file) => {
225
- let lines = fs.readFileSync(file, 'utf8').split('\n');
226
- let mode = defaultMode;
227
- if (lines.includes('// @testmode wasi')) {
228
- mode = 'wasi';
229
- }
230
- else if (lines.includes('// @testmode replica') || lines.find(line => line.match(/^(persistent )?actor( class)?/))) {
231
- mode = 'replica';
232
- }
233
- return {file, mode};
234
- });
235
-
236
- let hasWasiTests = filesWithMode.some(({mode}) => mode === 'wasi');
237
- let hasReplicaTests = filesWithMode.some(({mode}) => mode === 'replica');
238
-
239
- // prepare wasmtime path
240
- if (hasWasiTests && !wasmtimePath) {
241
- // ensure wasmtime is installed or specified in config
242
- if (config.toolchain?.wasmtime) {
243
- wasmtimePath = await toolchain.bin('wasmtime');
244
- }
245
- // fallback wasmtime to global binary if not specified in config (legacy)
246
- else {
247
- wasmtimePath = 'wasmtime';
248
- console.log(chalk.yellow('Warning:'), 'Wasmtime is not specified in config. Using global binary "wasmtime". This will be removed in the future.');
249
- console.log(`Run ${chalk.green('mops toolchain use wasmtime')} or add ${chalk.green('wasmtime = "<version>"')} in mops.toml to avoid breaking changes with future versions of mops.`);
250
- }
251
- }
252
-
253
- let runTestFile = async ({file, mode} : {file : string, mode : TestMode}) => {
254
- if (signal?.aborted) {
255
- return;
256
- }
257
-
258
- // print logs immediately for replica tests because we run them one-by-one
259
- let mmf = new MMF1(mode === 'replica' ? 'print' : 'store', absToRel(file));
260
-
261
- let promise = new Promise<void>((resolve) => {
262
- let mocArgs = ['--hide-warnings', '--error-detail=2', ...sourcesArr.join(' ').split(' '), file].filter(x => x);
263
-
264
- // interpret
265
- if (mode === 'interpreter') {
266
- let proc = spawn(mocPath, ['-r', '-ref-system-api', ...mocArgs], {signal});
267
- proc.addListener('error', (error : any) => {
268
- if (error?.code === 'ABORT_ERR') {
269
- return;
270
- }
271
- throw error;
272
- });
273
- pipeMMF(proc, mmf).then(resolve);
274
- }
275
- // build and run wasm
276
- else if (mode === 'wasi') {
277
- let wasmFile = `${path.join(testTempDir, path.parse(file).name)}.wasm`;
278
-
279
- // build
280
- let buildProc = spawn(mocPath, [`-o=${wasmFile}`, '-wasi-system-api', ...mocArgs], {signal});
281
- buildProc.addListener('error', (error : any) => {
282
- if (error?.code === 'ABORT_ERR') {
283
- return;
284
- }
285
- throw error;
286
- });
287
- pipeMMF(buildProc, mmf).then(async () => {
288
- if (mmf.failed > 0) {
289
- return;
290
- }
291
- // run
292
- let wasmtimeArgs = [];
293
- if (config.toolchain?.wasmtime && config.toolchain?.wasmtime >= '14.0.0') {
294
- wasmtimeArgs = [
295
- '-S', 'preview2=n',
296
- '-C', 'cache=n',
297
- '-W', 'bulk-memory',
298
- '-W', 'multi-memory',
299
- '-W', 'memory64',
300
- '-W', 'max-wasm-stack=4000000',
301
- '-W', 'nan-canonicalization=y',
302
- wasmFile,
303
- ];
304
- }
305
- else {
306
- console.error(chalk.red('Minimum wasmtime version is 14.0.0. Please update wasmtime to the latest version'));
307
- process.exit(1);
308
- }
309
-
310
- let proc = spawn(wasmtimePath, wasmtimeArgs, {signal});
311
- proc.addListener('error', (error : any) => {
312
- if (error?.code === 'ABORT_ERR') {
313
- return;
314
- }
315
- throw error;
316
- });
317
-
318
- await pipeMMF(proc, mmf);
319
- }).finally(() => {
320
- fs.rmSync(wasmFile, {force: true});
321
- }).then(resolve);
322
- }
323
- // build and execute in replica
324
- else if (mode === 'replica') {
325
- let wasmFile = `${path.join(testTempDir, path.parse(file).name)}.wasm`;
326
-
327
- // build
328
- let buildProc = spawn(mocPath, [`-o=${wasmFile}`, ...mocArgs], {signal});
329
- buildProc.addListener('error', (error : any) => {
330
- if (error?.code === 'ABORT_ERR') {
331
- return;
332
- }
333
- throw error;
334
- });
335
-
336
- pipeMMF(buildProc, mmf).then(async () => {
337
- if (mmf.failed > 0) {
338
- return;
339
- }
340
-
341
- await startReplicaOnce(replica, replicaType);
342
-
343
- if (signal?.aborted) {
344
- return;
345
- }
346
-
347
- let canisterName = path.parse(file).name;
348
- let idlFactory = ({IDL} : any) => {
349
- return IDL.Service({'runTests': IDL.Func([], [], [])});
350
- };
351
- interface _SERVICE {'runTests' : ActorMethod<[], undefined>;}
352
-
353
- let canister = await replica.deploy(canisterName, wasmFile, idlFactory, undefined, signal);
354
-
355
- if (signal?.aborted || !canister) {
356
- return;
357
- }
358
-
359
- pipeStdoutToMMF(canister.stream, mmf);
360
-
361
- let actor = await replica.getActor(canisterName) as _SERVICE;
362
-
363
- try {
364
- if (globalThis.mopsReplicaTestRunning) {
365
- await new Promise<void>((resolve) => {
366
- let timerId = setInterval(() => {
367
- if (!globalThis.mopsReplicaTestRunning) {
368
- resolve();
369
- clearInterval(timerId);
370
- }
371
- }, Math.random() * 1000 | 0);
372
- });
373
- }
374
-
375
- if (signal?.aborted) {
376
- return;
377
- }
378
-
379
- globalThis.mopsReplicaTestRunning = true;
380
- await actor.runTests();
381
- globalThis.mopsReplicaTestRunning = false;
382
-
383
- mmf.pass();
384
- }
385
- catch (e : any) {
386
- let stderrStream = new PassThrough();
387
- pipeStderrToMMF(stderrStream, mmf, path.dirname(file));
388
- stderrStream.write(e.message);
389
- }
390
- }).finally(async () => {
391
- globalThis.mopsReplicaTestRunning = false;
392
- fs.rmSync(wasmFile, {force: true});
393
- }).then(resolve);
394
- }
395
- });
396
-
397
- if (signal?.aborted) {
398
- return;
399
- }
400
-
401
- reporter.addRun(file, mmf, promise, mode);
402
-
403
- await promise;
404
- };
405
-
406
- await parallel(os.cpus().length, filesWithMode.filter(({mode}) => mode !== 'replica'), runTestFile);
407
- await parallel(1, filesWithMode.filter(({mode}) => mode === 'replica'), runTestFile);
408
-
409
- if (hasReplicaTests && !watch) {
410
- await replica.stop();
411
- fs.rmSync(testTempDir, {recursive: true, force: true});
412
- }
413
-
414
- if (signal?.aborted) {
415
- return false;
416
- }
417
-
418
- return reporter.done();
419
- }
193
+ export async function testWithReporter(
194
+ reporterName: ReporterName | Reporter | undefined,
195
+ filter = "",
196
+ defaultMode: TestMode = "interpreter",
197
+ replicaType: ReplicaName,
198
+ watch = false,
199
+ signal?: AbortSignal,
200
+ ): Promise<boolean> {
201
+ let rootDir = getRootDir();
202
+ let files: string[] = [];
203
+ let libFiles = globSync("**/test?(s)/lib.mo", globConfig);
204
+ if (libFiles[0]) {
205
+ files = [libFiles[0]];
206
+ } else {
207
+ let globStr = "**/test?(s)/**/*.test.mo";
208
+ if (filter) {
209
+ globStr = `**/test?(s)/**/*${filter}*.mo`;
210
+ }
211
+ files = globSync(path.join(rootDir, globStr), globConfig);
212
+ }
213
+ if (!files.length) {
214
+ if (filter) {
215
+ console.log(`No test files found for filter '${filter}'`);
216
+ return false;
217
+ }
218
+ console.log("No test files found");
219
+ console.log("Put your tests in 'test' directory in *.test.mo files");
220
+ return false;
221
+ }
222
+
223
+ let reporter: Reporter;
224
+
225
+ if (!reporterName || typeof reporterName === "string") {
226
+ if (!reporterName) {
227
+ reporterName = files.length > 1 ? "files" : "verbose";
228
+ }
229
+
230
+ if (reporterName == "compact") {
231
+ reporter = new CompactReporter();
232
+ } else if (reporterName == "files") {
233
+ reporter = new FilesReporter();
234
+ } else if (reporterName == "silent") {
235
+ reporter = new SilentReporter();
236
+ } else {
237
+ reporter = new VerboseReporter();
238
+ }
239
+ } else {
240
+ reporter = reporterName;
241
+ }
242
+
243
+ reporter.addFiles(files);
244
+
245
+ let config = readConfig();
246
+ let sourcesArr = await sources();
247
+
248
+ if (!mocPath) {
249
+ mocPath = await toolchain.bin("moc", { fallback: true });
250
+ }
251
+
252
+ let testTempDir = path.join(getRootDir(), ".mops/.test/");
253
+ replica.dir = testTempDir;
254
+
255
+ fs.rmSync(testTempDir, { recursive: true, force: true });
256
+ fs.mkdirSync(testTempDir, { recursive: true });
257
+
258
+ let filesWithMode = files.map((file) => {
259
+ let lines = fs.readFileSync(file, "utf8").split("\n");
260
+ let mode = defaultMode;
261
+ if (lines.includes("// @testmode wasi")) {
262
+ mode = "wasi";
263
+ } else if (
264
+ lines.includes("// @testmode replica") ||
265
+ lines.find((line) => line.match(/^(persistent )?actor( class)?/))
266
+ ) {
267
+ mode = "replica";
268
+ }
269
+ return { file, mode };
270
+ });
271
+
272
+ let hasWasiTests = filesWithMode.some(({ mode }) => mode === "wasi");
273
+ let hasReplicaTests = filesWithMode.some(({ mode }) => mode === "replica");
274
+
275
+ // prepare wasmtime path
276
+ if (hasWasiTests && !wasmtimePath) {
277
+ // ensure wasmtime is installed or specified in config
278
+ if (config.toolchain?.wasmtime) {
279
+ wasmtimePath = await toolchain.bin("wasmtime");
280
+ }
281
+ // fallback wasmtime to global binary if not specified in config (legacy)
282
+ else {
283
+ wasmtimePath = "wasmtime";
284
+ console.log(
285
+ chalk.yellow("Warning:"),
286
+ 'Wasmtime is not specified in config. Using global binary "wasmtime". This will be removed in the future.',
287
+ );
288
+ console.log(
289
+ `Run ${chalk.green("mops toolchain use wasmtime")} or add ${chalk.green('wasmtime = "<version>"')} in mops.toml to avoid breaking changes with future versions of mops.`,
290
+ );
291
+ }
292
+ }
293
+
294
+ let runTestFile = async ({
295
+ file,
296
+ mode,
297
+ }: {
298
+ file: string;
299
+ mode: TestMode;
300
+ }) => {
301
+ if (signal?.aborted) {
302
+ return;
303
+ }
304
+
305
+ // print logs immediately for replica tests because we run them one-by-one
306
+ let mmf = new MMF1(mode === "replica" ? "print" : "store", absToRel(file));
307
+
308
+ let promise = new Promise<void>((resolve) => {
309
+ let mocArgs = [
310
+ "--hide-warnings",
311
+ "--error-detail=2",
312
+ ...sourcesArr.join(" ").split(" "),
313
+ file,
314
+ ].filter((x) => x);
315
+
316
+ // interpret
317
+ if (mode === "interpreter") {
318
+ let proc = spawn(mocPath, ["-r", "-ref-system-api", ...mocArgs], {
319
+ signal,
320
+ });
321
+ proc.addListener("error", (error: any) => {
322
+ if (error?.code === "ABORT_ERR") {
323
+ return;
324
+ }
325
+ throw error;
326
+ });
327
+ pipeMMF(proc, mmf).then(resolve);
328
+ }
329
+ // build and run wasm
330
+ else if (mode === "wasi") {
331
+ let wasmFile = `${path.join(testTempDir, path.parse(file).name)}.wasm`;
332
+
333
+ // build
334
+ let buildProc = spawn(
335
+ mocPath,
336
+ [`-o=${wasmFile}`, "-wasi-system-api", ...mocArgs],
337
+ { signal },
338
+ );
339
+ buildProc.addListener("error", (error: any) => {
340
+ if (error?.code === "ABORT_ERR") {
341
+ return;
342
+ }
343
+ throw error;
344
+ });
345
+ pipeMMF(buildProc, mmf)
346
+ .then(async () => {
347
+ if (mmf.failed > 0) {
348
+ return;
349
+ }
350
+ // run
351
+ let wasmtimeArgs = [];
352
+ if (
353
+ config.toolchain?.wasmtime &&
354
+ config.toolchain?.wasmtime >= "14.0.0"
355
+ ) {
356
+ wasmtimeArgs = [
357
+ "-S",
358
+ "preview2=n",
359
+ "-C",
360
+ "cache=n",
361
+ "-W",
362
+ "bulk-memory",
363
+ "-W",
364
+ "multi-memory",
365
+ "-W",
366
+ "memory64",
367
+ "-W",
368
+ "max-wasm-stack=4000000",
369
+ "-W",
370
+ "nan-canonicalization=y",
371
+ wasmFile,
372
+ ];
373
+ } else {
374
+ console.error(
375
+ chalk.red(
376
+ "Minimum wasmtime version is 14.0.0. Please update wasmtime to the latest version",
377
+ ),
378
+ );
379
+ process.exit(1);
380
+ }
381
+
382
+ let proc = spawn(wasmtimePath, wasmtimeArgs, { signal });
383
+ proc.addListener("error", (error: any) => {
384
+ if (error?.code === "ABORT_ERR") {
385
+ return;
386
+ }
387
+ throw error;
388
+ });
389
+
390
+ await pipeMMF(proc, mmf);
391
+ })
392
+ .finally(() => {
393
+ fs.rmSync(wasmFile, { force: true });
394
+ })
395
+ .then(resolve);
396
+ }
397
+ // build and execute in replica
398
+ else if (mode === "replica") {
399
+ let wasmFile = `${path.join(testTempDir, path.parse(file).name)}.wasm`;
400
+
401
+ // build
402
+ let buildProc = spawn(mocPath, [`-o=${wasmFile}`, ...mocArgs], {
403
+ signal,
404
+ });
405
+ buildProc.addListener("error", (error: any) => {
406
+ if (error?.code === "ABORT_ERR") {
407
+ return;
408
+ }
409
+ throw error;
410
+ });
411
+
412
+ pipeMMF(buildProc, mmf)
413
+ .then(async () => {
414
+ if (mmf.failed > 0) {
415
+ return;
416
+ }
417
+
418
+ await startReplicaOnce(replica, replicaType);
419
+
420
+ if (signal?.aborted) {
421
+ return;
422
+ }
423
+
424
+ let canisterName = path.parse(file).name;
425
+ let idlFactory = ({ IDL }: any) => {
426
+ return IDL.Service({ runTests: IDL.Func([], [], []) });
427
+ };
428
+ interface _SERVICE {
429
+ runTests: ActorMethod<[], undefined>;
430
+ }
431
+
432
+ let canister = await replica.deploy(
433
+ canisterName,
434
+ wasmFile,
435
+ idlFactory,
436
+ undefined,
437
+ signal,
438
+ );
439
+
440
+ if (signal?.aborted || !canister) {
441
+ return;
442
+ }
443
+
444
+ pipeStdoutToMMF(canister.stream, mmf);
445
+
446
+ let actor = (await replica.getActor(canisterName)) as _SERVICE;
447
+
448
+ try {
449
+ if (globalThis.mopsReplicaTestRunning) {
450
+ await new Promise<void>((resolve) => {
451
+ let timerId = setInterval(
452
+ () => {
453
+ if (!globalThis.mopsReplicaTestRunning) {
454
+ resolve();
455
+ clearInterval(timerId);
456
+ }
457
+ },
458
+ (Math.random() * 1000) | 0,
459
+ );
460
+ });
461
+ }
462
+
463
+ if (signal?.aborted) {
464
+ return;
465
+ }
466
+
467
+ globalThis.mopsReplicaTestRunning = true;
468
+ await actor.runTests();
469
+ globalThis.mopsReplicaTestRunning = false;
470
+
471
+ mmf.pass();
472
+ } catch (e: any) {
473
+ let stderrStream = new PassThrough();
474
+ pipeStderrToMMF(stderrStream, mmf, path.dirname(file));
475
+ stderrStream.write(e.message);
476
+ }
477
+ })
478
+ .finally(async () => {
479
+ globalThis.mopsReplicaTestRunning = false;
480
+ fs.rmSync(wasmFile, { force: true });
481
+ })
482
+ .then(resolve);
483
+ }
484
+ });
485
+
486
+ if (signal?.aborted) {
487
+ return;
488
+ }
489
+
490
+ reporter.addRun(file, mmf, promise, mode);
491
+
492
+ await promise;
493
+ };
494
+
495
+ await parallel(
496
+ os.cpus().length,
497
+ filesWithMode.filter(({ mode }) => mode !== "replica"),
498
+ runTestFile,
499
+ );
500
+ await parallel(
501
+ 1,
502
+ filesWithMode.filter(({ mode }) => mode === "replica"),
503
+ runTestFile,
504
+ );
505
+
506
+ if (hasReplicaTests && !watch) {
507
+ await replica.stop();
508
+ fs.rmSync(testTempDir, { recursive: true, force: true });
509
+ }
510
+
511
+ if (signal?.aborted) {
512
+ return false;
513
+ }
514
+
515
+ return reporter.done();
516
+ }