diff --git a/package-lock.json b/package-lock.json index fb5df9e58a..1a892453e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33367,7 +33367,8 @@ "@waku/proto": "^0.0.8", "@waku/utils": "0.0.20", "async-mutex": "^0.5.0", - "libp2p": "^1.8.1" + "libp2p": "^1.8.1", + "p-event": "^6.0.1" }, "devDependencies": { "@rollup/plugin-commonjs": "^25.0.7", @@ -33375,15 +33376,16 @@ "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-replace": "^5.0.5", "@types/chai": "^4.3.11", - "@types/mocha": "^10.0.6", + "@types/mocha": "^10.0.9", "@waku/build-utils": "*", - "chai": "^4.3.10", + "chai": "^5.1.1", "cspell": "^8.6.1", "interface-datastore": "^8.2.10", - "mocha": "^10.3.0", + "mocha": "^10.7.3", "npm-run-all": "^4.1.5", "rollup": "^4.12.0", - "sinon": "^18.0.0" + "sinon": "^19.0.2", + "ts-node": "^10.9.2" }, "engines": { "node": ">=20" diff --git a/packages/sdk/.mocharc.cjs b/packages/sdk/.mocharc.cjs index dc72692443..f7f8438d06 100644 --- a/packages/sdk/.mocharc.cjs +++ b/packages/sdk/.mocharc.cjs @@ -1,26 +1,27 @@ const config = { - extension: ['ts'], - spec: 'src/**/*.spec.ts', - require: ['ts-node/register', 'isomorphic-fetch'], - loader: 'ts-node/esm', - nodeOptions: [ - 'experimental-specifier-resolution=node', - 'loader=ts-node/esm' - ], - exit: true -}; - -if (process.env.CI) { - console.log("Running tests in parallel"); - config.parallel = true; - config.jobs = 6; - console.log("Activating allure reporting"); - config.reporter = 'mocha-multi-reporters'; - config.reporterOptions = { - configFile: '.mocha.reporters.json' + extension: ['ts'], + spec: 'src/**/*.spec.ts', + require: ['ts-node/register', 'isomorphic-fetch'], + loader: 'ts-node/esm', + nodeOptions: [ + 'experimental-specifier-resolution=node', + 'loader=ts-node/esm' + ], + exit: true }; -} else { - console.log("Running tests serially. To enable parallel execution update mocha config"); -} - -module.exports = config; + + if (process.env.CI) { + console.log("Running tests in parallel"); + config.parallel = true; + config.jobs = 6; + console.log("Activating allure reporting"); + config.reporter = 'mocha-multi-reporters'; + config.reporterOptions = { + configFile: '.mocha.reporters.json' + }; + } else { + console.log("Running tests serially. To enable parallel execution update mocha config"); + } + + module.exports = config; + diff --git a/packages/sdk/package.json b/packages/sdk/package.json index f64abf3543..ea1adc53bb 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -74,23 +74,25 @@ "@waku/utils": "0.0.20", "@waku/message-hash": "0.1.16", "async-mutex": "^0.5.0", - "libp2p": "^1.8.1" + "libp2p": "^1.8.1", + "p-event": "^6.0.1" }, "devDependencies": { - "@types/mocha": "^10.0.6", "@types/chai": "^4.3.11", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-json": "^6.0.0", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-replace": "^5.0.5", + "@types/mocha": "^10.0.9", "@waku/build-utils": "*", - "mocha": "^10.3.0", - "sinon": "^18.0.0", - "chai": "^4.3.10", + "chai": "^5.1.1", "cspell": "^8.6.1", "interface-datastore": "^8.2.10", + "mocha": "^10.7.3", "npm-run-all": "^4.1.5", - "rollup": "^4.12.0" + "rollup": "^4.12.0", + "sinon": "^19.0.2", + "ts-node": "^10.9.2" }, "peerDependencies": { "@libp2p/bootstrap": "^10" diff --git a/packages/sdk/src/protocols/peer_manager.spec.ts b/packages/sdk/src/protocols/peer_manager.spec.ts new file mode 100644 index 0000000000..bea3bb0c6d --- /dev/null +++ b/packages/sdk/src/protocols/peer_manager.spec.ts @@ -0,0 +1,148 @@ +import { Peer, PeerId } from "@libp2p/interface"; +import { ConnectionManager, LightPushCodec } from "@waku/core"; +import { BaseProtocol } from "@waku/core/lib/base_protocol"; +import { Logger } from "@waku/utils"; +import { expect } from "chai"; +import sinon from "sinon"; + +import { PeerManager } from "./peer_manager.js"; + +describe("PeerManager", () => { + let peerManager: PeerManager; + let mockConnectionManager: sinon.SinonStubbedInstance; + let mockCore: sinon.SinonStubbedInstance; + let mockLogger: any; + + beforeEach(() => { + mockConnectionManager = sinon.createStubInstance(ConnectionManager); + mockCore = sinon.createStubInstance(BaseProtocol); + mockLogger = { + info: sinon.stub(), + warn: sinon.stub(), + error: sinon.stub(), + debug: sinon.stub(), + extend: sinon.stub().returns({ + info: sinon.stub(), + warn: sinon.stub(), + error: sinon.stub(), + debug: sinon.stub() + }) + }; + + mockCore.multicodec = LightPushCodec; + + peerManager = new PeerManager( + mockConnectionManager as any, + mockCore as any, + mockLogger as Logger + ); + }); + + afterEach(() => { + sinon.restore(); + }); + + const createMockPeer = (id: string): Peer => + ({ + id: { + toString: () => id + } as PeerId + }) as Peer; + + describe("addPeer", () => { + it("should add a peer", async () => { + const peer = createMockPeer("peer1"); + await peerManager.addPeer(peer); + + expect(mockConnectionManager.attemptDial.calledWith(peer.id)).to.be.true; + expect( + mockLogger.info.calledWith(sinon.match(/Added and dialed peer: peer1/)) + ).to.be.true; + expect(await peerManager.getPeerCount()).to.equal(1); + }); + }); + + describe("removePeer", () => { + it("should remove a peer", async () => { + const peer = createMockPeer("peer1"); + await peerManager.addPeer(peer); + await peerManager.removePeer(peer.id); + + expect(mockLogger.info.calledWith(sinon.match(/Removed peer: peer1/))).to + .be.true; + expect(await peerManager.getPeerCount()).to.equal(0); + }); + }); + + describe("getPeerCount", () => { + it("should return the correct number of peers", async () => { + await peerManager.addPeer(createMockPeer("peer1")); + await peerManager.addPeer(createMockPeer("peer2")); + + const count = await peerManager.getPeerCount(); + expect(count).to.equal(2); + }); + }); + + describe("hasPeers", () => { + it("should return true when peers exist", async () => { + await peerManager.addPeer(createMockPeer("peer1")); + const result = await peerManager.hasPeers(); + expect(result).to.be.true; + }); + + it("should return false when no peers exist", async () => { + const result = await peerManager.hasPeers(); + expect(result).to.be.false; + }); + }); + + describe("removeExcessPeers", () => { + it("should remove the specified number of excess peers", async () => { + await peerManager.addPeer(createMockPeer("peer1")); + await peerManager.addPeer(createMockPeer("peer2")); + await peerManager.addPeer(createMockPeer("peer3")); + + await peerManager.removeExcessPeers(2); + + const count = await peerManager.getPeerCount(); + expect(count).to.equal(1); + expect(mockLogger.info.calledWith(`Removing 2 excess peer(s)`)).to.be + .true; + }); + }); + + describe("findAndAddPeers", () => { + it("should find and add new peers", async () => { + const newPeers = [createMockPeer("peer1"), createMockPeer("peer2")]; + mockCore.getPeers.resolves(newPeers); + + const addedPeers = await peerManager.findAndAddPeers(2); + + expect(addedPeers).to.have.lengthOf(2); + expect(mockConnectionManager.attemptDial.callCount).to.equal(2); + }); + + it("should not add existing peers", async () => { + const existingPeer = createMockPeer("existing"); + await peerManager.addPeer(existingPeer); + + const newPeers = [existingPeer, createMockPeer("new")]; + mockCore.getPeers.resolves(newPeers); + + const addedPeers = await peerManager.findAndAddPeers(2); + + expect(addedPeers).to.have.lengthOf(1); + expect(mockConnectionManager.attemptDial.callCount).to.equal(2); // Once for existing, once for new + }); + + it("should log when no additional peers are found", async () => { + mockCore.getPeers.resolves([]); + + await peerManager.findAndAddPeers(2); + + expect(mockLogger.warn.calledWith("No additional peers found")).to.be + .true; + }); + }); +}); diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json index eebbc51585..5c32edfbcc 100644 --- a/packages/sdk/tsconfig.json +++ b/packages/sdk/tsconfig.json @@ -5,6 +5,6 @@ "rootDir": "src", "tsBuildInfoFile": "dist/.tsbuildinfo" }, - "include": ["src"], - "exclude": ["src/**/*.spec.ts", "src/test_utils"] + "include": ["src/**/*.ts"], + "exclude": ["src/test_utils"] } diff --git a/packages/tests/tests/health-manager/node.spec.ts b/packages/tests/tests/health-manager/node.spec.ts index cbccb7d34e..f29e4d98b9 100644 --- a/packages/tests/tests/health-manager/node.spec.ts +++ b/packages/tests/tests/health-manager/node.spec.ts @@ -17,7 +17,7 @@ import { TestShardInfo } from "./utils.js"; -describe.only("Node Health Status Matrix Tests", function () { +describe("Node Health Status Matrix Tests", function () { let waku: LightNode; let serviceNodes: ServiceNode[];