movehat 0.2.1 ā 0.2.2
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/dist/__tests__/deployContract.test.js +56 -47
- package/dist/__tests__/deployContract.test.js.map +1 -1
- package/dist/__tests__/exports.test.d.ts +2 -0
- package/dist/__tests__/exports.test.d.ts.map +1 -0
- package/dist/__tests__/exports.test.js +30 -0
- package/dist/__tests__/exports.test.js.map +1 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.d.ts +4 -3
- package/dist/__tests__/fixtures/sigint-deploy-harness.d.ts.map +1 -1
- package/dist/__tests__/fixtures/sigint-deploy-harness.js +8 -7
- package/dist/__tests__/fixtures/sigint-deploy-harness.js.map +1 -1
- package/dist/__tests__/fork/api.test.js +5 -0
- package/dist/__tests__/fork/api.test.js.map +1 -1
- package/dist/__tests__/fork/api.timeout.test.d.ts +2 -0
- package/dist/__tests__/fork/api.timeout.test.d.ts.map +1 -0
- package/dist/__tests__/fork/api.timeout.test.js +98 -0
- package/dist/__tests__/fork/api.timeout.test.js.map +1 -0
- package/dist/commands/__tests__/compile.toml-mutation.test.d.ts +2 -0
- package/dist/commands/__tests__/compile.toml-mutation.test.d.ts.map +1 -0
- package/dist/commands/__tests__/compile.toml-mutation.test.js +69 -0
- package/dist/commands/__tests__/compile.toml-mutation.test.js.map +1 -0
- package/dist/commands/__tests__/init.test.js +73 -11
- package/dist/commands/__tests__/init.test.js.map +1 -1
- package/dist/commands/init.d.ts +22 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +55 -6
- package/dist/commands/init.js.map +1 -1
- package/dist/core/AccountManager.d.ts.map +1 -1
- package/dist/core/AccountManager.js +14 -2
- package/dist/core/AccountManager.js.map +1 -1
- package/dist/core/Publisher.d.ts.map +1 -1
- package/dist/core/Publisher.js +52 -68
- package/dist/core/Publisher.js.map +1 -1
- package/dist/core/__tests__/AccountManager.global-state.test.d.ts +2 -0
- package/dist/core/__tests__/AccountManager.global-state.test.d.ts.map +1 -0
- package/dist/core/__tests__/AccountManager.global-state.test.js +69 -0
- package/dist/core/__tests__/AccountManager.global-state.test.js.map +1 -0
- package/dist/core/__tests__/movementProfile.test.d.ts +2 -0
- package/dist/core/__tests__/movementProfile.test.d.ts.map +1 -0
- package/dist/core/__tests__/movementProfile.test.js +112 -0
- package/dist/core/__tests__/movementProfile.test.js.map +1 -0
- package/dist/core/config.js +6 -5
- package/dist/core/config.js.map +1 -1
- package/dist/core/movementProfile.d.ts +55 -22
- package/dist/core/movementProfile.d.ts.map +1 -1
- package/dist/core/movementProfile.js +77 -99
- package/dist/core/movementProfile.js.map +1 -1
- package/dist/fork/__tests__/server.cors.test.d.ts +2 -0
- package/dist/fork/__tests__/server.cors.test.d.ts.map +1 -0
- package/dist/fork/__tests__/server.cors.test.js +79 -0
- package/dist/fork/__tests__/server.cors.test.js.map +1 -0
- package/dist/fork/api.d.ts +9 -1
- package/dist/fork/api.d.ts.map +1 -1
- package/dist/fork/api.js +37 -7
- package/dist/fork/api.js.map +1 -1
- package/dist/fork/server.d.ts +20 -1
- package/dist/fork/server.d.ts.map +1 -1
- package/dist/fork/server.js +19 -9
- package/dist/fork/server.js.map +1 -1
- package/dist/harness/Harness.d.ts +6 -2
- package/dist/harness/Harness.d.ts.map +1 -1
- package/dist/harness/Harness.js +8 -2
- package/dist/harness/Harness.js.map +1 -1
- package/dist/harness/codeObject.d.ts.map +1 -1
- package/dist/harness/codeObject.js +30 -33
- package/dist/harness/codeObject.js.map +1 -1
- package/dist/harness/script.d.ts +3 -3
- package/dist/harness/script.d.ts.map +1 -1
- package/dist/harness/script.js +33 -29
- package/dist/harness/script.js.map +1 -1
- package/dist/helpers/__tests__/setupLocalTesting.fork-network.test.d.ts +2 -0
- package/dist/helpers/__tests__/setupLocalTesting.fork-network.test.d.ts.map +1 -0
- package/dist/helpers/__tests__/setupLocalTesting.fork-network.test.js +172 -0
- package/dist/helpers/__tests__/setupLocalTesting.fork-network.test.js.map +1 -0
- package/dist/helpers/setupLocalTesting.d.ts.map +1 -1
- package/dist/helpers/setupLocalTesting.js +28 -2
- package/dist/helpers/setupLocalTesting.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/node/LocalNodeManager.d.ts +8 -0
- package/dist/node/LocalNodeManager.d.ts.map +1 -1
- package/dist/node/LocalNodeManager.js +10 -1
- package/dist/node/LocalNodeManager.js.map +1 -1
- package/dist/node/__tests__/LocalNodeManager.api-port.test.d.ts +2 -0
- package/dist/node/__tests__/LocalNodeManager.api-port.test.d.ts.map +1 -0
- package/dist/node/__tests__/LocalNodeManager.api-port.test.js +55 -0
- package/dist/node/__tests__/LocalNodeManager.api-port.test.js.map +1 -0
- package/dist/node/__tests__/LocalNodeManager.test.js +4 -3
- package/dist/node/__tests__/LocalNodeManager.test.js.map +1 -1
- package/dist/templates/move/Move.toml +1 -1
- package/dist/templates/move/sources/Counter.move +31 -4
- package/dist/templates/scripts/deploy-counter.ts +10 -0
- package/dist/types/config.d.ts +8 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/utils/__tests__/childProcessAdapter.maxBuffer.test.d.ts +2 -0
- package/dist/utils/__tests__/childProcessAdapter.maxBuffer.test.d.ts.map +1 -0
- package/dist/utils/__tests__/childProcessAdapter.maxBuffer.test.js +43 -0
- package/dist/utils/__tests__/childProcessAdapter.maxBuffer.test.js.map +1 -0
- package/dist/utils/childProcessAdapter.d.ts +7 -0
- package/dist/utils/childProcessAdapter.d.ts.map +1 -1
- package/dist/utils/childProcessAdapter.js +20 -2
- package/dist/utils/childProcessAdapter.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/deployContract.test.ts +59 -50
- package/src/__tests__/exports.test.ts +32 -0
- package/src/__tests__/fixtures/sigint-deploy-harness.ts +8 -7
- package/src/__tests__/fork/api.test.ts +5 -0
- package/src/__tests__/fork/api.timeout.test.ts +150 -0
- package/src/commands/__tests__/compile.toml-mutation.test.ts +77 -0
- package/src/commands/__tests__/init.test.ts +96 -11
- package/src/commands/init.ts +77 -6
- package/src/core/AccountManager.ts +18 -1
- package/src/core/Publisher.ts +58 -77
- package/src/core/__tests__/AccountManager.global-state.test.ts +83 -0
- package/src/core/__tests__/movementProfile.test.ts +131 -0
- package/src/core/config.ts +9 -5
- package/src/core/movementProfile.ts +75 -127
- package/src/fork/__tests__/server.cors.test.ts +101 -0
- package/src/fork/api.ts +69 -10
- package/src/fork/server.ts +38 -9
- package/src/harness/Harness.ts +11 -2
- package/src/harness/codeObject.ts +37 -43
- package/src/harness/script.ts +40 -39
- package/src/helpers/__tests__/setupLocalTesting.fork-network.test.ts +212 -0
- package/src/helpers/setupLocalTesting.ts +36 -2
- package/src/index.ts +9 -1
- package/src/node/LocalNodeManager.ts +24 -2
- package/src/node/__tests__/LocalNodeManager.api-port.test.ts +62 -0
- package/src/node/__tests__/LocalNodeManager.test.ts +4 -3
- package/src/templates/move/Move.toml +1 -1
- package/src/templates/move/sources/Counter.move +31 -4
- package/src/templates/scripts/deploy-counter.ts +10 -0
- package/src/types/config.ts +8 -1
- package/src/utils/__tests__/childProcessAdapter.maxBuffer.test.ts +51 -0
- package/src/utils/childProcessAdapter.ts +32 -2
|
@@ -126,17 +126,18 @@ describe("LocalNodeManager ā start / stop / lifecycle", () => {
|
|
|
126
126
|
expect(info.testDir).toBe(tmpDir);
|
|
127
127
|
});
|
|
128
128
|
|
|
129
|
-
it("honors custom ports
|
|
129
|
+
it("honors custom faucet/ready ports; apiPort is pinned to 8080 (see F9)", () => {
|
|
130
130
|
const { adapter } = buildFakeAdapter();
|
|
131
131
|
const mgr = new LocalNodeManager({
|
|
132
132
|
adapter,
|
|
133
133
|
testDir: tmpDir,
|
|
134
|
-
apiPort: 9000,
|
|
135
134
|
faucetPort: 9001,
|
|
136
135
|
readyPort: 9002,
|
|
137
136
|
});
|
|
138
137
|
const info = mgr.getNodeInfo();
|
|
139
|
-
|
|
138
|
+
// Movement CLI does not accept a flag for the REST API port; see
|
|
139
|
+
// LocalNodeManager.api-port.test.ts for the F9 contract.
|
|
140
|
+
expect(info.rpcUrl).toBe("http://127.0.0.1:8080");
|
|
140
141
|
expect(info.faucetUrl).toContain(":9001");
|
|
141
142
|
expect(info.readyUrl).toContain(":9002");
|
|
142
143
|
});
|
|
@@ -33,7 +33,16 @@ module counter::counter {
|
|
|
33
33
|
|
|
34
34
|
public entry fun increment(account: &signer) acquires Counter {
|
|
35
35
|
let account_addr = signer::address_of(account);
|
|
36
|
-
|
|
36
|
+
|
|
37
|
+
// Auto-init: create Counter if it doesn't exist yet. Defense in
|
|
38
|
+
// depth so the module stays usable even if a caller skips the
|
|
39
|
+
// dedicated `init` entry function.
|
|
40
|
+
if (!exists<Counter>(account_addr)) {
|
|
41
|
+
move_to(account, Counter {
|
|
42
|
+
value: 0,
|
|
43
|
+
increment_events: account::new_event_handle<IncrementEvent>(account),
|
|
44
|
+
});
|
|
45
|
+
};
|
|
37
46
|
|
|
38
47
|
let counter = borrow_global_mut<Counter>(account_addr);
|
|
39
48
|
let old_value = counter.value;
|
|
@@ -56,14 +65,32 @@ module counter::counter {
|
|
|
56
65
|
public fun test_increment(account: &signer) acquires Counter {
|
|
57
66
|
let addr = signer::address_of(account);
|
|
58
67
|
aptos_framework::account::create_account_for_test(addr);
|
|
59
|
-
|
|
68
|
+
|
|
60
69
|
init(account);
|
|
61
70
|
assert!(get(addr) == 0, 0);
|
|
62
|
-
|
|
71
|
+
|
|
63
72
|
increment(account);
|
|
64
73
|
assert!(get(addr) == 1, 1);
|
|
65
|
-
|
|
74
|
+
|
|
66
75
|
increment(account);
|
|
67
76
|
assert!(get(addr) == 2, 2);
|
|
68
77
|
}
|
|
78
|
+
|
|
79
|
+
// Regression guard: increment must auto-create the Counter resource
|
|
80
|
+
// when called against a never-initialized account. Locks the
|
|
81
|
+
// defense-in-depth behavior so a future refactor can't accidentally
|
|
82
|
+
// remove it.
|
|
83
|
+
#[test(account = @0x2)]
|
|
84
|
+
public fun test_increment_auto_inits(account: &signer) acquires Counter {
|
|
85
|
+
let addr = signer::address_of(account);
|
|
86
|
+
aptos_framework::account::create_account_for_test(addr);
|
|
87
|
+
|
|
88
|
+
// Skip init entirely ā increment must create the resource.
|
|
89
|
+
increment(account);
|
|
90
|
+
assert!(get(addr) == 1, 0);
|
|
91
|
+
|
|
92
|
+
// Idempotent: a second increment uses the now-existing resource.
|
|
93
|
+
increment(account);
|
|
94
|
+
assert!(get(addr) == 2, 1);
|
|
95
|
+
}
|
|
69
96
|
}
|
|
@@ -31,6 +31,16 @@ async function main() {
|
|
|
31
31
|
// Interact with the freshly deployed module via the runtime helper.
|
|
32
32
|
const counter = harness.runtime.getContract(deployment.address, "counter");
|
|
33
33
|
|
|
34
|
+
// Counter is a Move resource ā it must be created explicitly per
|
|
35
|
+
// account before any method that reads or mutates it. The dedicated
|
|
36
|
+
// `init` entry function does this once per signer. (The module also
|
|
37
|
+
// auto-inits inside `increment` as defense in depth, so this call is
|
|
38
|
+
// technically optional today, but kept for pedagogy: real-world Move
|
|
39
|
+
// modules usually require an explicit init step.)
|
|
40
|
+
console.log("\nš§ Initializing counter resource for this account...");
|
|
41
|
+
const initTx = await counter.call(harness.runtime.account, "init", []);
|
|
42
|
+
console.log(` Init tx: ${initTx.hash}`);
|
|
43
|
+
|
|
34
44
|
console.log("\nš Incrementing counter...");
|
|
35
45
|
const txResult = await counter.call(harness.runtime.account, "increment", []);
|
|
36
46
|
console.log(`ā
Transaction hash: ${txResult.hash}`);
|
package/src/types/config.ts
CHANGED
|
@@ -55,7 +55,14 @@ export interface LocalTestOptions {
|
|
|
55
55
|
nodeSilent?: boolean; // Suppress node output (default: false)
|
|
56
56
|
|
|
57
57
|
// Fork options (when mode='fork')
|
|
58
|
-
forkNetwork?: 'testnet' | string; // Network to fork from (default: 'testnet')
|
|
58
|
+
forkNetwork?: 'testnet' | 'mainnet' | string; // Network to fork from (default: 'testnet')
|
|
59
|
+
/**
|
|
60
|
+
* RPC URL override used when forking a non-built-in network.
|
|
61
|
+
* Required when `forkNetwork` is not one of the built-in names
|
|
62
|
+
* (`'testnet'`, `'mainnet'`). Ignored when a fork already exists
|
|
63
|
+
* on disk (the saved metadata's nodeUrl is reused).
|
|
64
|
+
*/
|
|
65
|
+
forkRpcUrl?: string;
|
|
59
66
|
forkName?: string; // Name for the fork (default: 'test-local')
|
|
60
67
|
forkPort?: number; // Fork server port (default: 8080)
|
|
61
68
|
forkResetState?: boolean; // Clear fork state before tests (default: true)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { defaultChildProcessAdapter } from "../childProcessAdapter.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* F4 ā `run()` must reject when child output exceeds `maxBuffer`.
|
|
6
|
+
*
|
|
7
|
+
* Without this cap, the stdout/stderr Buffer arrays in
|
|
8
|
+
* DefaultChildProcessAdapter grow without limit. A buggy or hostile
|
|
9
|
+
* subprocess can OOM the parent process. F4 adds an opt-in byte cap
|
|
10
|
+
* with kill-on-overflow semantics.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const NODE = process.execPath;
|
|
14
|
+
|
|
15
|
+
describe("F4 ā ChildProcessAdapter.run maxBuffer", () => {
|
|
16
|
+
it("rejects with a maxBuffer error when stdout exceeds the cap", async () => {
|
|
17
|
+
// 8KiB of output, cap at 1KiB ā must abort.
|
|
18
|
+
const script = `process.stdout.write('x'.repeat(8 * 1024)); setTimeout(() => {}, 30000);`;
|
|
19
|
+
await expect(
|
|
20
|
+
defaultChildProcessAdapter.run({
|
|
21
|
+
command: NODE,
|
|
22
|
+
args: ["-e", script],
|
|
23
|
+
maxBuffer: 1024,
|
|
24
|
+
timeoutMs: 10_000,
|
|
25
|
+
})
|
|
26
|
+
).rejects.toThrow(/maxBuffer|exceeded/i);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("rejects with a maxBuffer error when stderr exceeds the cap", async () => {
|
|
30
|
+
const script = `process.stderr.write('y'.repeat(8 * 1024)); setTimeout(() => {}, 30000);`;
|
|
31
|
+
await expect(
|
|
32
|
+
defaultChildProcessAdapter.run({
|
|
33
|
+
command: NODE,
|
|
34
|
+
args: ["-e", script],
|
|
35
|
+
maxBuffer: 1024,
|
|
36
|
+
timeoutMs: 10_000,
|
|
37
|
+
})
|
|
38
|
+
).rejects.toThrow(/maxBuffer|exceeded/i);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("does NOT throw when output stays under the cap", async () => {
|
|
42
|
+
const script = `process.stdout.write('ok'); process.exit(0);`;
|
|
43
|
+
const result = await defaultChildProcessAdapter.run({
|
|
44
|
+
command: NODE,
|
|
45
|
+
args: ["-e", script],
|
|
46
|
+
maxBuffer: 1024,
|
|
47
|
+
});
|
|
48
|
+
expect(result.exitCode).toBe(0);
|
|
49
|
+
expect(result.stdout).toBe("ok");
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -38,8 +38,17 @@ export interface RunInput {
|
|
|
38
38
|
* Default: `false`.
|
|
39
39
|
*/
|
|
40
40
|
inheritStdio?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Maximum combined bytes (stdout + stderr) the captured Buffers may
|
|
43
|
+
* grow to before the child is killed and the promise rejects. Defaults
|
|
44
|
+
* to 64 MiB. Set to `Infinity` to disable. Ignored when
|
|
45
|
+
* `inheritStdio` is `true` (no buffering happens).
|
|
46
|
+
*/
|
|
47
|
+
maxBuffer?: number;
|
|
41
48
|
}
|
|
42
49
|
|
|
50
|
+
const DEFAULT_MAX_BUFFER = 64 * 1024 * 1024;
|
|
51
|
+
|
|
43
52
|
export interface RunResult {
|
|
44
53
|
/**
|
|
45
54
|
* Numeric exit code from the child. `-1` when the child was terminated by
|
|
@@ -114,10 +123,31 @@ class DefaultChildProcessAdapter implements ChildProcessAdapter {
|
|
|
114
123
|
|
|
115
124
|
const stdoutChunks: Buffer[] = [];
|
|
116
125
|
const stderrChunks: Buffer[] = [];
|
|
126
|
+
let totalBytes = 0;
|
|
127
|
+
let overflowed = false;
|
|
128
|
+
const maxBuffer = input.maxBuffer ?? DEFAULT_MAX_BUFFER;
|
|
129
|
+
|
|
130
|
+
const onChunk = (chunks: Buffer[]) => (chunk: Buffer) => {
|
|
131
|
+
if (overflowed) return;
|
|
132
|
+
totalBytes += chunk.length;
|
|
133
|
+
if (totalBytes > maxBuffer) {
|
|
134
|
+
overflowed = true;
|
|
135
|
+
clearTimer();
|
|
136
|
+
input.signal?.removeEventListener('abort', onAbort);
|
|
137
|
+
child.kill('SIGTERM');
|
|
138
|
+
reject(
|
|
139
|
+
new Error(
|
|
140
|
+
`Command output exceeded maxBuffer (${maxBuffer} bytes): ${input.command}`
|
|
141
|
+
)
|
|
142
|
+
);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
chunks.push(chunk);
|
|
146
|
+
};
|
|
117
147
|
|
|
118
148
|
// Streams are null when stdio is 'inherit'; the `?.` covers that.
|
|
119
|
-
child.stdout?.on('data', (
|
|
120
|
-
child.stderr?.on('data', (
|
|
149
|
+
child.stdout?.on('data', onChunk(stdoutChunks));
|
|
150
|
+
child.stderr?.on('data', onChunk(stderrChunks));
|
|
121
151
|
|
|
122
152
|
let timeoutHandle: NodeJS.Timeout | undefined;
|
|
123
153
|
const clearTimer = () => {
|