introduce interface for better mocking

As one could fall in a trap of not defining the right methods on the mock
This commit is contained in:
fryorcraken 2025-07-21 14:47:07 +10:00
parent 1e7e0291fa
commit d4429702c2
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
6 changed files with 33 additions and 29 deletions

View File

@ -15,7 +15,7 @@ import { ConnectionManager } from "./connection_manager.js";
import { DiscoveryDialer } from "./discovery_dialer.js";
import { KeepAliveManager } from "./keep_alive_manager.js";
import { NetworkMonitor } from "./network_monitor.js";
import { ShardReader } from "./shard_reader.js";
import { IShardReader, ShardReader } from "./shard_reader.js";
describe("ConnectionManager", () => {
let libp2p: Libp2p;
@ -30,7 +30,7 @@ describe("ConnectionManager", () => {
// Mock internal components
let mockKeepAliveManager: sinon.SinonStubbedInstance<KeepAliveManager>;
let mockDiscoveryDialer: sinon.SinonStubbedInstance<DiscoveryDialer>;
let mockShardReader: sinon.SinonStubbedInstance<ShardReader>;
let mockShardReader: sinon.SinonStubbedInstance<IShardReader>;
let mockNetworkMonitor: sinon.SinonStubbedInstance<NetworkMonitor>;
let mockConnectionLimiter: sinon.SinonStubbedInstance<ConnectionLimiter>;
@ -87,7 +87,7 @@ describe("ConnectionManager", () => {
mockShardReader = {
isPeerOnTopic: sinon.stub().resolves(true)
} as unknown as sinon.SinonStubbedInstance<ShardReader>;
} as unknown as sinon.SinonStubbedInstance<IShardReader>;
mockNetworkMonitor = {
start: sinon.stub(),

View File

@ -1,7 +1,6 @@
import { type Peer, type PeerId, type Stream } from "@libp2p/interface";
import { MultiaddrInput } from "@multiformats/multiaddr";
import {
ClusterId,
ConnectionManagerOptions,
IConnectionManager,
IRelay,
@ -47,7 +46,7 @@ export class ConnectionManager implements IConnectionManager {
private readonly networkMonitor: NetworkMonitor;
private readonly connectionLimiter: ConnectionLimiter;
private options: ConnectionManagerOptions;
private readonly options: ConnectionManagerOptions;
private libp2p: Libp2p;
public constructor(options: ConnectionManagerConstructorOptions) {
@ -200,9 +199,8 @@ export class ConnectionManager implements IConnectionManager {
public async isPeerOnShard(
peerId: PeerId,
clusterId: ClusterId,
shardId: ShardId
): Promise<boolean> {
return this.shardReader.isPeerOnShard(peerId, clusterId, shardId);
return this.shardReader.isPeerOnShard(peerId, shardId);
}
}

View File

@ -177,7 +177,6 @@ describe("ShardReader", function () {
const result = await shardReader.isPeerOnShard(
testPeerId,
testClusterId,
testShardIndex
);
@ -192,9 +191,13 @@ describe("ShardReader", function () {
mockPeerStore.get.resolves(mockPeer);
const result = await shardReader.isPeerOnShard(
const shardReaderCluster5 = new ShardReader({
libp2p: mockLibp2p as any,
networkConfig: { clusterId: 5 }
});
const result = await shardReaderCluster5.isPeerOnShard(
testPeerId,
5,
testShardIndex
);
@ -211,7 +214,6 @@ describe("ShardReader", function () {
const result = await shardReader.isPeerOnShard(
testPeerId,
testClusterId,
testShardIndex + 100
);
@ -223,7 +225,6 @@ describe("ShardReader", function () {
const result = await shardReader.isPeerOnShard(
testPeerId,
testClusterId,
testShardIndex
);

View File

@ -20,7 +20,7 @@ type ShardReaderConstructorOptions = {
networkConfig: NetworkConfig;
};
interface IShardReader {
export interface IShardReader {
hasShardInfo(id: PeerId): Promise<boolean>;
isPeerOnCluster(id: PeerId): Promise<boolean>;
isPeerOnShard(
@ -66,7 +66,8 @@ export class ShardReader implements IShardReader {
): Promise<boolean> {
try {
const { clusterId, shard } = pubsubTopicToSingleShardInfo(pubsubTopic);
return await this.isPeerOnShard(id, clusterId, shard);
if (clusterId !== this.clusterId) return false;
return await this.isPeerOnShard(id, shard);
} catch (error) {
log.error(
`Error comparing pubsub topic ${pubsubTopic} with shard info for ${id}`,
@ -76,14 +77,10 @@ export class ShardReader implements IShardReader {
}
}
public async isPeerOnShard(
id: PeerId,
clusterId: ClusterId,
shard: ShardId
): Promise<boolean> {
public async isPeerOnShard(id: PeerId, shard: ShardId): Promise<boolean> {
const peerShardInfo = await this.getRelayShards(id);
log.info(
`Checking if peer on same shard: this { clusterId: ${clusterId}, shardId: ${shard} },` +
`Checking if peer on same shard: this { clusterId: ${this.clusterId}, shardId: ${shard} },` +
`${id} { clusterId: ${peerShardInfo?.clusterId}, shards: ${peerShardInfo?.shards} }`
);
if (!peerShardInfo) {
@ -91,7 +88,7 @@ export class ShardReader implements IShardReader {
}
return (
peerShardInfo.clusterId === clusterId &&
peerShardInfo.clusterId === this.clusterId &&
peerShardInfo.shards.includes(shard)
);
}

View File

@ -1,6 +1,8 @@
import type { Peer, PeerId, Stream } from "@libp2p/interface";
import type { MultiaddrInput } from "@multiformats/multiaddr";
import { ShardId } from "./sharding.js";
// Peer tags
export enum Tags {
BOOTSTRAP = "bootstrap",
@ -161,4 +163,14 @@ export interface IConnectionManager {
* @returns Promise resolving to true if the peer has shard info, false otherwise
*/
hasShardInfo(peerId: PeerId): Promise<boolean>;
/**
* Returns true if the passed peer is on the passed pubsub topic
*/
isPeerOnTopic(peerId: PeerId, pubsubTopic: string): Promise<boolean>;
/**
* Returns true if the passed peer is on the passed shard
*/
isPeerOnShard(peerId: PeerId, shardId: ShardId): Promise<boolean>;
}

View File

@ -4,14 +4,10 @@ import {
PeerId,
TypedEventEmitter
} from "@libp2p/interface";
import {
ConnectionManager,
FilterCodecs,
LightPushCodec,
StoreCodec
} from "@waku/core";
import { FilterCodecs, LightPushCodec, StoreCodec } from "@waku/core";
import {
CONNECTION_LOCKED_TAG,
type IConnectionManager,
Libp2p,
Libp2pEventHandler,
Protocols
@ -29,7 +25,7 @@ type PeerManagerConfig = {
type PeerManagerParams = {
libp2p: Libp2p;
config?: PeerManagerConfig;
connectionManager: ConnectionManager;
connectionManager: IConnectionManager;
};
type GetPeersParams = {
@ -67,7 +63,7 @@ export class PeerManager {
private readonly numPeersToUse: number;
private readonly libp2p: Libp2p;
private readonly connectionManager: ConnectionManager;
private readonly connectionManager: IConnectionManager;
private readonly lockedPeers = new Set<string>();
private readonly unlockedPeers = new Map<string, number>();