@peerbit/test-utils 2.3.15 → 2.3.16-91f84d0
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/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/session.d.ts +10 -0
- package/dist/src/session.d.ts.map +1 -1
- package/dist/src/session.js +128 -5
- package/dist/src/session.js.map +1 -1
- package/package.json +10 -10
- package/src/index.ts +3 -1
- package/src/session.ts +155 -5
package/dist/src/index.d.ts
CHANGED
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,QAAA,MAAM,UAAU,kCAA4B,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC"}
|
package/dist/src/index.js
CHANGED
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,UAAU,GAAG,WAAW,CAAC,aAAa,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC"}
|
package/dist/src/session.d.ts
CHANGED
|
@@ -11,10 +11,20 @@ type CreateOptions = {
|
|
|
11
11
|
export declare class TestSession {
|
|
12
12
|
private session;
|
|
13
13
|
private _peers;
|
|
14
|
+
private connectedGroups;
|
|
14
15
|
constructor(session: SSession<Libp2pExtendServices>, peers: Peerbit[]);
|
|
15
16
|
get peers(): ProgramClient[];
|
|
16
17
|
connect(groups?: ProgramClient[][]): Promise<void>;
|
|
18
|
+
private wrapPeerStartForReconnect;
|
|
17
19
|
stop(): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Create a "mock-ish" session intended for fast and stable Node.js tests.
|
|
22
|
+
*
|
|
23
|
+
* Uses TCP-only transport (no WebRTC/WebSockets/circuit-relay) and disables
|
|
24
|
+
* the libp2p relay service by default.
|
|
25
|
+
*/
|
|
26
|
+
static connectedMock(n: number, options?: CreateOptions | CreateOptions[]): Promise<TestSession>;
|
|
27
|
+
static disconnectedMock(n: number, options?: CreateOptions | CreateOptions[]): Promise<TestSession>;
|
|
18
28
|
static connected(n: number, options?: CreateOptions | CreateOptions[]): Promise<TestSession>;
|
|
19
29
|
static disconnected(n: number, options?: CreateOptions | CreateOptions[]): Promise<TestSession>;
|
|
20
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAGA,OAAO,EAEN,WAAW,IAAI,QAAQ,EAEvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAMtD,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE5C,OAAO,EACN,KAAK,mBAAmB,EAExB,KAAK,oBAAoB,EACzB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,MAAM,aAAa,GAAG,aAAa,CAAC,oBAAoB,CAAC,CAAC;AAEhE,KAAK,aAAa,GAAG;IAAE,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAC1E,qBAAa,WAAW;IACvB,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,eAAe,CAA6B;gBACxC,OAAO,EAAE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE;IAMrE,IAAW,KAAK,IAAI,aAAa,EAAE,CAElC;IAEK,OAAO,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,EAAE;IAQxC,OAAO,CAAC,yBAAyB;IAqD3B,IAAI;IAcV;;;;;OAKG;WACU,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,EAAE;WAYlE,gBAAgB,CAC5B,CAAC,EAAE,MAAM,EACT,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,EAAE;WAqC7B,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,EAAE;WAY9D,YAAY,CACxB,CAAC,EAAE,MAAM,EACT,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa,EAAE;CAgE1C"}
|
package/dist/src/session.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { yamux } from "@chainsafe/libp2p-yamux";
|
|
2
2
|
import { DirectBlock } from "@peerbit/blocks";
|
|
3
3
|
import { keychain } from "@peerbit/keychain";
|
|
4
|
-
import { TestSession as SSession } from "@peerbit/libp2p-test-utils";
|
|
4
|
+
import { listenFast, TestSession as SSession, transportsFast, } from "@peerbit/libp2p-test-utils";
|
|
5
5
|
import {} from "@peerbit/program";
|
|
6
6
|
import { DirectSub } from "@peerbit/pubsub";
|
|
7
7
|
import { waitForNeighbour as waitForPeersStreams, } from "@peerbit/stream";
|
|
@@ -12,20 +12,126 @@ import { Peerbit } from "peerbit";
|
|
|
12
12
|
export class TestSession {
|
|
13
13
|
session;
|
|
14
14
|
_peers;
|
|
15
|
+
connectedGroups;
|
|
15
16
|
constructor(session, peers) {
|
|
16
17
|
this.session = session;
|
|
17
18
|
this._peers = peers;
|
|
19
|
+
this.wrapPeerStartForReconnect();
|
|
18
20
|
}
|
|
19
21
|
get peers() {
|
|
20
22
|
return this._peers;
|
|
21
23
|
}
|
|
22
24
|
async connect(groups) {
|
|
23
25
|
await this.session.connect(groups?.map((x) => x.map((y) => y)));
|
|
26
|
+
this.connectedGroups = groups
|
|
27
|
+
? groups.map((group) => new Set(group))
|
|
28
|
+
: [new Set(this._peers)];
|
|
24
29
|
return;
|
|
25
30
|
}
|
|
31
|
+
wrapPeerStartForReconnect() {
|
|
32
|
+
const patchedKey = Symbol.for("@peerbit/test-session.reconnect-on-start");
|
|
33
|
+
for (const peer of this._peers) {
|
|
34
|
+
const anyPeer = peer;
|
|
35
|
+
if (anyPeer[patchedKey]) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
anyPeer[patchedKey] = true;
|
|
39
|
+
const originalStart = peer.start.bind(peer);
|
|
40
|
+
peer.start = async () => {
|
|
41
|
+
await originalStart();
|
|
42
|
+
// Only auto-reconnect for sessions that have been explicitly connected.
|
|
43
|
+
// This preserves `TestSession.disconnected*()` semantics.
|
|
44
|
+
if (!this.connectedGroups || peer.libp2p.status !== "started") {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const peerHash = peer.identity.publicKey.hashcode();
|
|
48
|
+
const peersToDial = new Set();
|
|
49
|
+
for (const group of this.connectedGroups) {
|
|
50
|
+
if (!group.has(peer))
|
|
51
|
+
continue;
|
|
52
|
+
for (const other of group) {
|
|
53
|
+
if (other === peer)
|
|
54
|
+
continue;
|
|
55
|
+
if (other.libp2p.status !== "started")
|
|
56
|
+
continue;
|
|
57
|
+
peersToDial.add(other);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Re-establish connectivity after a full stop/start. Without this, tests that
|
|
61
|
+
// restart a peer can fail to resolve programs/blocks because no node dials.
|
|
62
|
+
await Promise.all([...peersToDial].map(async (other) => {
|
|
63
|
+
await peer.dial(other);
|
|
64
|
+
// Also wait for the reverse direction to be fully established; some
|
|
65
|
+
// protocols require a writable stream on both sides to reply.
|
|
66
|
+
await Promise.all([
|
|
67
|
+
other.services.pubsub.waitFor(peerHash, {
|
|
68
|
+
target: "neighbor",
|
|
69
|
+
timeout: 10_000,
|
|
70
|
+
}),
|
|
71
|
+
other.services.blocks.waitFor(peerHash, {
|
|
72
|
+
target: "neighbor",
|
|
73
|
+
timeout: 10_000,
|
|
74
|
+
}),
|
|
75
|
+
]);
|
|
76
|
+
}));
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
26
80
|
async stop() {
|
|
27
|
-
await Promise.all(this._peers.map((
|
|
28
|
-
|
|
81
|
+
await Promise.all(this._peers.map((peer) => peer.stop()));
|
|
82
|
+
// `Peerbit.stop()` stops libp2p for sessions created by `Peerbit.create()`,
|
|
83
|
+
// but in case a test injected an already-started external libp2p instance,
|
|
84
|
+
// ensure it's stopped (without double-stopping).
|
|
85
|
+
await Promise.all(this._peers.map(async (peer) => {
|
|
86
|
+
if (peer.libp2p.status !== "stopped") {
|
|
87
|
+
await peer.libp2p.stop();
|
|
88
|
+
}
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Create a "mock-ish" session intended for fast and stable Node.js tests.
|
|
93
|
+
*
|
|
94
|
+
* Uses TCP-only transport (no WebRTC/WebSockets/circuit-relay) and disables
|
|
95
|
+
* the libp2p relay service by default.
|
|
96
|
+
*/
|
|
97
|
+
static async connectedMock(n, options) {
|
|
98
|
+
const session = await TestSession.disconnectedMock(n, options);
|
|
99
|
+
await session.connect();
|
|
100
|
+
// TODO types
|
|
101
|
+
await waitForPeersStreams(...session.peers.map((x) => x.services.blocks));
|
|
102
|
+
return session;
|
|
103
|
+
}
|
|
104
|
+
static async disconnectedMock(n, options) {
|
|
105
|
+
const applyMockDefaults = (o) => {
|
|
106
|
+
if (!o) {
|
|
107
|
+
return {
|
|
108
|
+
libp2p: {
|
|
109
|
+
transports: transportsFast(),
|
|
110
|
+
addresses: { listen: listenFast() },
|
|
111
|
+
services: { relay: null },
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
...o,
|
|
117
|
+
libp2p: {
|
|
118
|
+
...(o.libp2p ?? {}),
|
|
119
|
+
transports: o.libp2p?.transports ?? transportsFast(),
|
|
120
|
+
addresses: {
|
|
121
|
+
...(o.libp2p?.addresses ?? {}),
|
|
122
|
+
listen: o.libp2p?.addresses?.listen ?? listenFast(),
|
|
123
|
+
},
|
|
124
|
+
services: {
|
|
125
|
+
...(o.libp2p?.services ?? {}),
|
|
126
|
+
relay: o.libp2p?.services?.relay ?? null,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
const optionsWithMockDefaults = Array.isArray(options)
|
|
132
|
+
? options.map(applyMockDefaults)
|
|
133
|
+
: applyMockDefaults(options);
|
|
134
|
+
return TestSession.disconnected(n, optionsWithMockDefaults);
|
|
29
135
|
}
|
|
30
136
|
static async connected(n, options) {
|
|
31
137
|
const session = await TestSession.disconnected(n, options);
|
|
@@ -35,19 +141,36 @@ export class TestSession {
|
|
|
35
141
|
return session;
|
|
36
142
|
}
|
|
37
143
|
static async disconnected(n, options) {
|
|
144
|
+
const useMockSession = process.env.PEERBIT_TEST_SESSION === "mock" ||
|
|
145
|
+
process.env.PEERBIT_TEST_SESSION === "fast" ||
|
|
146
|
+
process.env.PEERBIT_TEST_SESSION === "tcp";
|
|
38
147
|
const m = (o) => {
|
|
39
148
|
const blocksDirectory = o?.directory
|
|
40
149
|
? path.join(o.directory, "/blocks").toString()
|
|
41
150
|
: undefined;
|
|
151
|
+
const libp2pOptions = {
|
|
152
|
+
...(o?.libp2p ?? {}),
|
|
153
|
+
};
|
|
154
|
+
if (useMockSession) {
|
|
155
|
+
libp2pOptions.transports = libp2pOptions.transports ?? transportsFast();
|
|
156
|
+
libp2pOptions.addresses = {
|
|
157
|
+
...(libp2pOptions.addresses ?? {}),
|
|
158
|
+
listen: libp2pOptions.addresses?.listen ?? listenFast(),
|
|
159
|
+
};
|
|
160
|
+
libp2pOptions.services = {
|
|
161
|
+
...(libp2pOptions.services ?? {}),
|
|
162
|
+
relay: libp2pOptions.services?.relay ?? null,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
42
165
|
return {
|
|
43
|
-
...
|
|
166
|
+
...libp2pOptions,
|
|
44
167
|
services: {
|
|
45
168
|
blocks: (c) => new DirectBlock(c, {
|
|
46
169
|
directory: blocksDirectory,
|
|
47
170
|
}),
|
|
48
171
|
pubsub: (c) => new DirectSub(c, { canRelayMessage: true }),
|
|
49
172
|
keychain: keychain(),
|
|
50
|
-
...
|
|
173
|
+
...libp2pOptions.services,
|
|
51
174
|
}, /// TODO types
|
|
52
175
|
streamMuxers: [yamux()],
|
|
53
176
|
connectionMonitor: {
|
package/dist/src/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peerbit/test-utils",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.16-91f84d0",
|
|
4
4
|
"description": "Test utils for Peerbit",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
@@ -63,19 +63,19 @@
|
|
|
63
63
|
"author": "dao.xyz",
|
|
64
64
|
"license": "MIT",
|
|
65
65
|
"dependencies": {
|
|
66
|
+
"@peerbit/libp2p-test-utils": "2.2.0-91f84d0",
|
|
67
|
+
"peerbit": "4.4.16-91f84d0",
|
|
66
68
|
"@chainsafe/libp2p-yamux": "^8.0.0",
|
|
69
|
+
"@peerbit/blocks": "3.1.7-91f84d0",
|
|
70
|
+
"@peerbit/keychain": "1.2.4-91f84d0",
|
|
71
|
+
"@peerbit/program": "5.6.1-91f84d0",
|
|
72
|
+
"@peerbit/pubsub": "4.1.4-91f84d0",
|
|
73
|
+
"@peerbit/stream": "4.6.0-91f84d0",
|
|
67
74
|
"libp2p": "^3.1.0",
|
|
68
|
-
"tty-table": "^4.2.1"
|
|
69
|
-
"peerbit": "4.4.15",
|
|
70
|
-
"@peerbit/keychain": "1.2.4",
|
|
71
|
-
"@peerbit/libp2p-test-utils": "2.2.0",
|
|
72
|
-
"@peerbit/program": "5.6.0",
|
|
73
|
-
"@peerbit/blocks": "3.1.6",
|
|
74
|
-
"@peerbit/pubsub": "4.1.3",
|
|
75
|
-
"@peerbit/stream": "4.5.3"
|
|
75
|
+
"tty-table": "^4.2.1"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
|
-
"@peerbit/time": "2.3.0"
|
|
78
|
+
"@peerbit/time": "2.3.0-91f84d0"
|
|
79
79
|
},
|
|
80
80
|
"localMaintainers": [
|
|
81
81
|
"dao.xyz"
|
package/src/index.ts
CHANGED
package/src/session.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { yamux } from "@chainsafe/libp2p-yamux";
|
|
2
2
|
import { DirectBlock } from "@peerbit/blocks";
|
|
3
3
|
import { keychain } from "@peerbit/keychain";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
listenFast,
|
|
6
|
+
TestSession as SSession,
|
|
7
|
+
transportsFast,
|
|
8
|
+
} from "@peerbit/libp2p-test-utils";
|
|
5
9
|
import { type ProgramClient } from "@peerbit/program";
|
|
6
10
|
import { DirectSub } from "@peerbit/pubsub";
|
|
7
11
|
import {
|
|
@@ -23,9 +27,11 @@ type CreateOptions = { libp2p?: Libp2pCreateOptions; directory?: string };
|
|
|
23
27
|
export class TestSession {
|
|
24
28
|
private session: SSession<Libp2pExtendServices>;
|
|
25
29
|
private _peers: Peerbit[];
|
|
30
|
+
private connectedGroups: Set<Peerbit>[] | undefined;
|
|
26
31
|
constructor(session: SSession<Libp2pExtendServices>, peers: Peerbit[]) {
|
|
27
32
|
this.session = session;
|
|
28
33
|
this._peers = peers;
|
|
34
|
+
this.wrapPeerStartForReconnect();
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
public get peers(): ProgramClient[] {
|
|
@@ -34,11 +40,134 @@ export class TestSession {
|
|
|
34
40
|
|
|
35
41
|
async connect(groups?: ProgramClient[][]) {
|
|
36
42
|
await this.session.connect(groups?.map((x) => x.map((y) => y)));
|
|
43
|
+
this.connectedGroups = groups
|
|
44
|
+
? groups.map((group) => new Set(group as Peerbit[]))
|
|
45
|
+
: [new Set(this._peers)];
|
|
37
46
|
return;
|
|
38
47
|
}
|
|
48
|
+
|
|
49
|
+
private wrapPeerStartForReconnect() {
|
|
50
|
+
const patchedKey = Symbol.for("@peerbit/test-session.reconnect-on-start");
|
|
51
|
+
for (const peer of this._peers) {
|
|
52
|
+
const anyPeer = peer as any;
|
|
53
|
+
if (anyPeer[patchedKey]) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
anyPeer[patchedKey] = true;
|
|
57
|
+
|
|
58
|
+
const originalStart = peer.start.bind(peer);
|
|
59
|
+
peer.start = async () => {
|
|
60
|
+
await originalStart();
|
|
61
|
+
|
|
62
|
+
// Only auto-reconnect for sessions that have been explicitly connected.
|
|
63
|
+
// This preserves `TestSession.disconnected*()` semantics.
|
|
64
|
+
if (!this.connectedGroups || peer.libp2p.status !== "started") {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const peerHash = peer.identity.publicKey.hashcode();
|
|
69
|
+
const peersToDial = new Set<Peerbit>();
|
|
70
|
+
for (const group of this.connectedGroups) {
|
|
71
|
+
if (!group.has(peer)) continue;
|
|
72
|
+
for (const other of group) {
|
|
73
|
+
if (other === peer) continue;
|
|
74
|
+
if (other.libp2p.status !== "started") continue;
|
|
75
|
+
peersToDial.add(other);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Re-establish connectivity after a full stop/start. Without this, tests that
|
|
80
|
+
// restart a peer can fail to resolve programs/blocks because no node dials.
|
|
81
|
+
await Promise.all(
|
|
82
|
+
[...peersToDial].map(async (other) => {
|
|
83
|
+
await peer.dial(other);
|
|
84
|
+
|
|
85
|
+
// Also wait for the reverse direction to be fully established; some
|
|
86
|
+
// protocols require a writable stream on both sides to reply.
|
|
87
|
+
await Promise.all([
|
|
88
|
+
other.services.pubsub.waitFor(peerHash, {
|
|
89
|
+
target: "neighbor",
|
|
90
|
+
timeout: 10_000,
|
|
91
|
+
}),
|
|
92
|
+
other.services.blocks.waitFor(peerHash, {
|
|
93
|
+
target: "neighbor",
|
|
94
|
+
timeout: 10_000,
|
|
95
|
+
}),
|
|
96
|
+
]);
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
39
102
|
async stop() {
|
|
40
|
-
await Promise.all(this._peers.map((
|
|
41
|
-
|
|
103
|
+
await Promise.all(this._peers.map((peer) => peer.stop()));
|
|
104
|
+
// `Peerbit.stop()` stops libp2p for sessions created by `Peerbit.create()`,
|
|
105
|
+
// but in case a test injected an already-started external libp2p instance,
|
|
106
|
+
// ensure it's stopped (without double-stopping).
|
|
107
|
+
await Promise.all(
|
|
108
|
+
this._peers.map(async (peer) => {
|
|
109
|
+
if (peer.libp2p.status !== "stopped") {
|
|
110
|
+
await peer.libp2p.stop();
|
|
111
|
+
}
|
|
112
|
+
}),
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Create a "mock-ish" session intended for fast and stable Node.js tests.
|
|
118
|
+
*
|
|
119
|
+
* Uses TCP-only transport (no WebRTC/WebSockets/circuit-relay) and disables
|
|
120
|
+
* the libp2p relay service by default.
|
|
121
|
+
*/
|
|
122
|
+
static async connectedMock(n: number, options?: CreateOptions | CreateOptions[]) {
|
|
123
|
+
const session = await TestSession.disconnectedMock(n, options);
|
|
124
|
+
await session.connect();
|
|
125
|
+
// TODO types
|
|
126
|
+
await waitForPeersStreams(
|
|
127
|
+
...session.peers.map(
|
|
128
|
+
(x) => x.services.blocks as any as DirectStream<any>,
|
|
129
|
+
),
|
|
130
|
+
);
|
|
131
|
+
return session;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
static async disconnectedMock(
|
|
135
|
+
n: number,
|
|
136
|
+
options?: CreateOptions | CreateOptions[],
|
|
137
|
+
) {
|
|
138
|
+
const applyMockDefaults = (o?: CreateOptions): CreateOptions | undefined => {
|
|
139
|
+
if (!o) {
|
|
140
|
+
return {
|
|
141
|
+
libp2p: {
|
|
142
|
+
transports: transportsFast(),
|
|
143
|
+
addresses: { listen: listenFast() },
|
|
144
|
+
services: { relay: null },
|
|
145
|
+
} as any,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
...o,
|
|
151
|
+
libp2p: {
|
|
152
|
+
...(o.libp2p ?? {}),
|
|
153
|
+
transports: o.libp2p?.transports ?? transportsFast(),
|
|
154
|
+
addresses: {
|
|
155
|
+
...(o.libp2p?.addresses ?? {}),
|
|
156
|
+
listen: o.libp2p?.addresses?.listen ?? listenFast(),
|
|
157
|
+
},
|
|
158
|
+
services: {
|
|
159
|
+
...(o.libp2p?.services ?? {}),
|
|
160
|
+
relay: o.libp2p?.services?.relay ?? null,
|
|
161
|
+
},
|
|
162
|
+
} as any,
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const optionsWithMockDefaults = Array.isArray(options)
|
|
167
|
+
? options.map(applyMockDefaults)
|
|
168
|
+
: applyMockDefaults(options);
|
|
169
|
+
|
|
170
|
+
return TestSession.disconnected(n, optionsWithMockDefaults as any);
|
|
42
171
|
}
|
|
43
172
|
|
|
44
173
|
static async connected(n: number, options?: CreateOptions | CreateOptions[]) {
|
|
@@ -57,13 +186,34 @@ export class TestSession {
|
|
|
57
186
|
n: number,
|
|
58
187
|
options?: CreateOptions | CreateOptions[],
|
|
59
188
|
) {
|
|
189
|
+
const useMockSession =
|
|
190
|
+
process.env.PEERBIT_TEST_SESSION === "mock" ||
|
|
191
|
+
process.env.PEERBIT_TEST_SESSION === "fast" ||
|
|
192
|
+
process.env.PEERBIT_TEST_SESSION === "tcp";
|
|
193
|
+
|
|
60
194
|
const m = (o?: CreateOptions): Libp2pCreateOptionsWithServices => {
|
|
61
195
|
const blocksDirectory = o?.directory
|
|
62
196
|
? path.join(o.directory, "/blocks").toString()
|
|
63
197
|
: undefined;
|
|
64
198
|
|
|
199
|
+
const libp2pOptions: Libp2pCreateOptions = {
|
|
200
|
+
...(o?.libp2p ?? {}),
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
if (useMockSession) {
|
|
204
|
+
libp2pOptions.transports = libp2pOptions.transports ?? transportsFast();
|
|
205
|
+
libp2pOptions.addresses = {
|
|
206
|
+
...(libp2pOptions.addresses ?? {}),
|
|
207
|
+
listen: libp2pOptions.addresses?.listen ?? listenFast(),
|
|
208
|
+
};
|
|
209
|
+
libp2pOptions.services = {
|
|
210
|
+
...(libp2pOptions.services ?? {}),
|
|
211
|
+
relay: libp2pOptions.services?.relay ?? null,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
65
215
|
return {
|
|
66
|
-
...
|
|
216
|
+
...libp2pOptions,
|
|
67
217
|
services: {
|
|
68
218
|
blocks: (c: any) =>
|
|
69
219
|
new DirectBlock(c, {
|
|
@@ -71,7 +221,7 @@ export class TestSession {
|
|
|
71
221
|
}),
|
|
72
222
|
pubsub: (c: any) => new DirectSub(c, { canRelayMessage: true }),
|
|
73
223
|
keychain: keychain(),
|
|
74
|
-
...
|
|
224
|
+
...libp2pOptions.services,
|
|
75
225
|
} as any, /// TODO types
|
|
76
226
|
streamMuxers: [yamux()],
|
|
77
227
|
connectionMonitor: {
|