chore: move tests to separate package

This commit is contained in:
fryorcraken.eth
2022-11-01 20:13:09 +11:00
parent ce9938e464
commit 3d08cb28c8
13 changed files with 10 additions and 24 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
module.exports = {
parserOptions: {
tsconfigRootDir: __dirname,
project: "./tsconfig.dev.json",
project: "./tsconfig.json",
},
};
+4 -10
View File
@@ -41,21 +41,15 @@
"privacy"
],
"scripts": {
"build": "run-s build:**",
"build:esm": "tsc",
"fix": "run-s fix:*",
"fix:prettier": "prettier . --write",
"fix:lint": "eslint src --ext .ts --ext .cjs --fix",
"fix:lint": "eslint tests --ext .ts --ext .cjs --fix",
"check": "run-s check:*",
"check:lint": "eslint src --ext .ts",
"check:lint": "eslint tests --ext .ts",
"check:prettier": "prettier . --list-different",
"check:spelling": "cspell \"{README.md,src/**/*.ts}\"",
"check:tsc": "tsc -p tsconfig.dev.json",
"test": "exit 0 # Tested in @waku/core",
"proto": "exit 0 # no proto",
"doc": "exit 0",
"reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build",
"release": "exit 0"
"check:tsc": "tsc -p tsconfig.json",
"reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build"
},
"engines": {
"node": ">=16"
+115
View File
@@ -0,0 +1,115 @@
import { createPrivacyNode } from "@waku/create";
import type { WakuPrivacy } from "@waku/interfaces";
import { Protocols } from "@waku/interfaces";
import { expect } from "chai";
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
import { waitForRemotePeer } from "../wait_for_remote_peer";
import { ENR } from "./enr";
describe("ENR Interop: nwaku", function () {
let waku: WakuPrivacy;
let nwaku: Nwaku;
afterEach(async function () {
!!nwaku && nwaku.stop();
!!waku && waku.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("Relay", async function () {
this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
relay: true,
store: false,
filter: false,
lightpush: false,
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku = await createPrivacyNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(multiAddrWithId);
await waitForRemotePeer(waku, [Protocols.Relay]);
const nwakuInfo = await nwaku.info();
const nimPeerId = await nwaku.getPeerId();
expect(nwakuInfo.enrUri).to.not.be.undefined;
const dec = await ENR.decodeTxt(nwakuInfo.enrUri ?? "");
expect(dec.peerId?.toString()).to.eq(nimPeerId.toString());
expect(dec.waku2).to.deep.eq({
relay: true,
store: false,
filter: false,
lightPush: false,
});
});
it("Relay + Store", async function () {
this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
relay: true,
store: true,
filter: false,
lightpush: false,
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku = await createPrivacyNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(multiAddrWithId);
await waitForRemotePeer(waku, [Protocols.Relay]);
const nwakuInfo = await nwaku.info();
const nimPeerId = await nwaku.getPeerId();
expect(nwakuInfo.enrUri).to.not.be.undefined;
const dec = await ENR.decodeTxt(nwakuInfo.enrUri ?? "");
expect(dec.peerId?.toString()).to.eq(nimPeerId.toString());
expect(dec.waku2).to.deep.eq({
relay: true,
store: true,
filter: false,
lightPush: false,
});
});
it("All", async function () {
this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
relay: true,
store: true,
filter: true,
lightpush: true,
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku = await createPrivacyNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(multiAddrWithId);
await waitForRemotePeer(waku, [Protocols.Relay]);
const nwakuInfo = await nwaku.info();
const nimPeerId = await nwaku.getPeerId();
expect(nwakuInfo.enrUri).to.not.be.undefined;
const dec = await ENR.decodeTxt(nwakuInfo.enrUri ?? "");
expect(dec.peerId?.toString()).to.eq(nimPeerId.toString());
expect(dec.waku2).to.deep.eq({
relay: true,
store: true,
filter: true,
lightPush: true,
});
});
});
+111
View File
@@ -0,0 +1,111 @@
import { createFullNode } from "@waku/create";
import type { Message, WakuFull } from "@waku/interfaces";
import { Protocols } from "@waku/interfaces";
import { expect } from "chai";
import debug from "debug";
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
import { delay } from "../../test_utils/delay";
import { bytesToUtf8, utf8ToBytes } from "../utils";
import { waitForRemotePeer } from "../wait_for_remote_peer";
import { DecoderV0, EncoderV0 } from "../waku_message/version_0";
const log = debug("waku:test");
const TestContentTopic = "/test/1/waku-filter";
const TestEncoder = new EncoderV0(TestContentTopic);
const TestDecoder = new DecoderV0(TestContentTopic);
describe("Waku Filter", () => {
let waku: WakuFull;
let nwaku: Nwaku;
afterEach(async function () {
!!nwaku && nwaku.stop();
!!waku && waku.stop().catch((e) => console.log("Waku failed to stop", e));
});
beforeEach(async function () {
this.timeout(15000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({ filter: true, lightpush: true });
waku = await createFullNode({
staticNoiseKey: NOISE_KEY_1,
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } },
});
await waku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Filter, Protocols.LightPush]);
});
it("creates a subscription", async function () {
this.timeout(10000);
let messageCount = 0;
const messageText = "Filtering works!";
const message = { payload: utf8ToBytes(messageText) };
const callback = (msg: Message): void => {
log("Got a message");
messageCount++;
expect(msg.contentTopic).to.eq(TestContentTopic);
expect(bytesToUtf8(msg.payload!)).to.eq(messageText);
};
await waku.filter.subscribe([TestDecoder], callback);
// As the filter protocol does not cater for an ack of subscription
// we cannot know whether the subscription happened. Something we want to
// correct in future versions of the protocol.
await delay(200);
await waku.lightPush.push(TestEncoder, message);
while (messageCount === 0) {
await delay(250);
}
expect(messageCount).to.eq(1);
});
it("handles multiple messages", async function () {
this.timeout(10000);
let messageCount = 0;
const callback = (msg: Message): void => {
messageCount++;
expect(msg.contentTopic).to.eq(TestContentTopic);
};
await waku.filter.subscribe([TestDecoder], callback);
await delay(200);
await waku.lightPush.push(TestEncoder, {
payload: utf8ToBytes("Filtering works!"),
});
await waku.lightPush.push(TestEncoder, {
payload: utf8ToBytes("Filtering still works!"),
});
while (messageCount < 2) {
await delay(250);
}
expect(messageCount).to.eq(2);
});
it("unsubscribes", async function () {
let messageCount = 0;
const callback = (): void => {
messageCount++;
};
const unsubscribe = await waku.filter.subscribe([TestDecoder], callback);
await delay(200);
await waku.lightPush.push(TestEncoder, {
payload: utf8ToBytes("This should be received"),
});
await delay(100);
await unsubscribe();
await delay(200);
await waku.lightPush.push(TestEncoder, {
payload: utf8ToBytes("This should not be received"),
});
await delay(100);
expect(messageCount).to.eq(1);
});
});
@@ -0,0 +1,106 @@
import { createFullNode } from "@waku/create";
import type { WakuFull } from "@waku/interfaces";
import { Protocols } from "@waku/interfaces";
import { expect } from "chai";
import debug from "debug";
import {
makeLogFileName,
MessageRpcResponse,
NOISE_KEY_1,
Nwaku,
} from "../../test_utils";
import { delay } from "../../test_utils/delay";
import { bytesToUtf8, utf8ToBytes } from "../utils";
import { waitForRemotePeer } from "../wait_for_remote_peer";
import { EncoderV0 } from "../waku_message/version_0";
const log = debug("waku:test:lightpush");
const TestContentTopic = "/test/1/waku-light-push/utf8";
const TestEncoder = new EncoderV0(TestContentTopic);
describe("Waku Light Push [node only]", () => {
let waku: WakuFull;
let nwaku: Nwaku;
afterEach(async function () {
!!nwaku && nwaku.stop();
!!waku && waku.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("Push successfully", async function () {
this.timeout(15_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({ lightpush: true });
waku = await createFullNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.LightPush]);
const messageText = "Light Push works!";
const pushResponse = await waku.lightPush.push(TestEncoder, {
payload: utf8ToBytes(messageText),
});
expect(pushResponse.recipients.length).to.eq(1);
let msgs: MessageRpcResponse[] = [];
while (msgs.length === 0) {
await delay(200);
msgs = await nwaku.messages();
}
expect(msgs[0].contentTopic).to.equal(TestContentTopic);
expect(bytesToUtf8(new Uint8Array(msgs[0].payload))).to.equal(messageText);
});
it("Push on custom pubsub topic", async function () {
this.timeout(15_000);
const customPubSubTopic = "/waku/2/custom-dapp/proto";
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({ lightpush: true, topics: customPubSubTopic });
waku = await createFullNode({
pubSubTopic: customPubSubTopic,
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.LightPush]);
const nimPeerId = await nwaku.getPeerId();
const messageText = "Light Push works!";
log("Send message via lightpush");
const pushResponse = await waku.lightPush.push(
TestEncoder,
{ payload: utf8ToBytes(messageText) },
{
peerId: nimPeerId,
pubSubTopic: customPubSubTopic,
}
);
log("Ack received", pushResponse);
expect(pushResponse.recipients[0].toString()).to.eq(nimPeerId.toString());
let msgs: MessageRpcResponse[] = [];
log("Waiting for message to show in nwaku");
while (msgs.length === 0) {
await delay(200);
msgs = await nwaku.messages(customPubSubTopic);
}
expect(msgs[0].contentTopic).to.equal(TestContentTopic);
expect(bytesToUtf8(new Uint8Array(msgs[0].payload))!).to.equal(messageText);
});
});
+475
View File
@@ -0,0 +1,475 @@
import { PeerId } from "@libp2p/interface-peer-id";
import { createPrivacyNode } from "@waku/create";
import type { Message, WakuPrivacy } from "@waku/interfaces";
import { Protocols } from "@waku/interfaces";
import { expect } from "chai";
import debug from "debug";
import {
makeLogFileName,
MessageRpcResponse,
NOISE_KEY_1,
NOISE_KEY_2,
NOISE_KEY_3,
Nwaku,
} from "../../test_utils";
import { delay } from "../../test_utils/delay";
import { DefaultPubSubTopic } from "../constants";
import {
generatePrivateKey,
generateSymmetricKey,
getPublicKey,
} from "../crypto";
import { bytesToUtf8, utf8ToBytes } from "../utils";
import { waitForRemotePeer } from "../wait_for_remote_peer";
import { DecoderV0, EncoderV0, MessageV0 } from "../waku_message/version_0.js";
import {
AsymDecoder,
AsymEncoder,
SymDecoder,
SymEncoder,
} from "../waku_message/version_1.js";
const log = debug("waku:test");
const TestContentTopic = "/test/1/waku-relay/utf8";
const TestEncoder = new EncoderV0(TestContentTopic);
const TestDecoder = new DecoderV0(TestContentTopic);
describe("Waku Relay [node only]", () => {
// Node needed as we don't have a way to connect 2 js waku
// nodes in the browser yet
describe("2 js nodes", () => {
afterEach(function () {
if (this.currentTest?.state === "failed") {
console.log(`Test failed, log file name is ${makeLogFileName(this)}`);
}
});
let waku1: WakuPrivacy;
let waku2: WakuPrivacy;
beforeEach(async function () {
this.timeout(10000);
log("Starting JS Waku instances");
[waku1, waku2] = await Promise.all([
createPrivacyNode({ staticNoiseKey: NOISE_KEY_1 }).then((waku) =>
waku.start().then(() => waku)
),
createPrivacyNode({
staticNoiseKey: NOISE_KEY_2,
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } },
}).then((waku) => waku.start().then(() => waku)),
]);
log("Instances started, adding waku2 to waku1's address book");
waku1.addPeerToAddressBook(
waku2.libp2p.peerId,
// TODO: Upgrade libp2p package.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: New multiaddr type but they seem mostly compatible
waku2.libp2p.getMultiaddrs()
);
log("Wait for mutual pubsub subscription");
await Promise.all([
waitForRemotePeer(waku1, [Protocols.Relay]),
waitForRemotePeer(waku2, [Protocols.Relay]),
]);
log("before each hook done");
});
afterEach(async function () {
!!waku1 &&
waku1.stop().catch((e) => console.log("Waku failed to stop", e));
!!waku2 &&
waku2.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("Subscribe", async function () {
log("Getting subscribers");
const subscribers1 = waku1.libp2p.pubsub
.getSubscribers(DefaultPubSubTopic)
.map((p) => p.toString());
const subscribers2 = waku2.libp2p.pubsub
.getSubscribers(DefaultPubSubTopic)
.map((p) => p.toString());
log("Asserting mutual subscription");
expect(subscribers1).to.contain(waku2.libp2p.peerId.toString());
expect(subscribers2).to.contain(waku1.libp2p.peerId.toString());
});
it("Register correct protocols", async function () {
const protocols = waku1.libp2p.registrar.getProtocols();
expect(protocols).to.contain("/vac/waku/relay/2.0.0");
expect(protocols.findIndex((value) => value.match(/sub/))).to.eq(-1);
});
it("Publish", async function () {
this.timeout(10000);
const messageText = "JS to JS communication works";
const messageTimestamp = new Date("1995-12-17T03:24:00");
const message = {
payload: utf8ToBytes(messageText),
timestamp: messageTimestamp,
};
const receivedMsgPromise: Promise<Message> = new Promise((resolve) => {
waku2.relay.addObserver(TestDecoder, resolve);
});
await waku1.relay.send(TestEncoder, message);
const receivedMsg = await receivedMsgPromise;
expect(receivedMsg.contentTopic).to.eq(TestContentTopic);
expect(bytesToUtf8(receivedMsg.payload!)).to.eq(messageText);
expect(receivedMsg.timestamp?.valueOf()).to.eq(
messageTimestamp.valueOf()
);
});
it("Filter on content topics", async function () {
this.timeout(10000);
const fooMessageText = "Published on content topic foo";
const barMessageText = "Published on content topic bar";
const fooContentTopic = "foo";
const barContentTopic = "bar";
const fooEncoder = new EncoderV0(fooContentTopic);
const barEncoder = new EncoderV0(barContentTopic);
const fooDecoder = new DecoderV0(fooContentTopic);
const barDecoder = new DecoderV0(barContentTopic);
const fooMessages: Message[] = [];
waku2.relay.addObserver(fooDecoder, (msg) => {
fooMessages.push(msg);
});
const barMessages: Message[] = [];
waku2.relay.addObserver(barDecoder, (msg) => {
barMessages.push(msg);
});
await waku1.relay.send(barEncoder, {
payload: utf8ToBytes(barMessageText),
});
await waku1.relay.send(fooEncoder, {
payload: utf8ToBytes(fooMessageText),
});
while (!fooMessages.length && !barMessages.length) {
await delay(100);
}
expect(fooMessages[0].contentTopic).to.eq(fooContentTopic);
expect(bytesToUtf8(fooMessages[0].payload!)).to.eq(fooMessageText);
expect(barMessages[0].contentTopic).to.eq(barContentTopic);
expect(bytesToUtf8(barMessages[0].payload!)).to.eq(barMessageText);
expect(fooMessages.length).to.eq(1);
expect(barMessages.length).to.eq(1);
});
it("Decrypt messages", async function () {
this.timeout(10000);
const asymText = "This message is encrypted using asymmetric";
const asymTopic = "/test/1/asymmetric/proto";
const symText = "This message is encrypted using symmetric encryption";
const symTopic = "/test/1/symmetric/proto";
const privateKey = generatePrivateKey();
const symKey = generateSymmetricKey();
const publicKey = getPublicKey(privateKey);
const asymEncoder = new AsymEncoder(asymTopic, publicKey);
const symEncoder = new SymEncoder(symTopic, symKey);
const asymDecoder = new AsymDecoder(asymTopic, privateKey);
const symDecoder = new SymDecoder(symTopic, symKey);
const msgs: Message[] = [];
waku2.relay.addObserver(asymDecoder, (wakuMsg) => {
msgs.push(wakuMsg);
});
waku2.relay.addObserver(symDecoder, (wakuMsg) => {
msgs.push(wakuMsg);
});
await waku1.relay.send(asymEncoder, { payload: utf8ToBytes(asymText) });
await delay(200);
await waku1.relay.send(symEncoder, { payload: utf8ToBytes(symText) });
while (msgs.length < 2) {
await delay(200);
}
expect(msgs[0].contentTopic).to.eq(asymTopic);
expect(bytesToUtf8(msgs[0].payload!)).to.eq(asymText);
expect(msgs[1].contentTopic).to.eq(symTopic);
expect(bytesToUtf8(msgs[1].payload!)).to.eq(symText);
});
it("Delete observer", async function () {
this.timeout(10000);
const messageText =
"Published on content topic with added then deleted observer";
const contentTopic = "added-then-deleted-observer";
// The promise **fails** if we receive a message on this observer.
const receivedMsgPromise: Promise<Message> = new Promise(
(resolve, reject) => {
const deleteObserver = waku2.relay.addObserver(
new DecoderV0(contentTopic),
reject
);
deleteObserver();
setTimeout(resolve, 500);
}
);
await waku1.relay.send(new EncoderV0(contentTopic), {
payload: utf8ToBytes(messageText),
});
await receivedMsgPromise;
// If it does not throw then we are good.
});
});
describe("Custom pubsub topic", () => {
let waku1: WakuPrivacy;
let waku2: WakuPrivacy;
let waku3: WakuPrivacy;
afterEach(async function () {
!!waku1 &&
waku1.stop().catch((e) => console.log("Waku failed to stop", e));
!!waku2 &&
waku2.stop().catch((e) => console.log("Waku failed to stop", e));
!!waku3 &&
waku3.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("Publish", async function () {
this.timeout(10000);
const pubSubTopic = "/some/pubsub/topic";
// 1 and 2 uses a custom pubsub
// 3 uses the default pubsub
[waku1, waku2, waku3] = await Promise.all([
createPrivacyNode({
pubSubTopic: pubSubTopic,
staticNoiseKey: NOISE_KEY_1,
}).then((waku) => waku.start().then(() => waku)),
createPrivacyNode({
pubSubTopic: pubSubTopic,
staticNoiseKey: NOISE_KEY_2,
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } },
}).then((waku) => waku.start().then(() => waku)),
createPrivacyNode({
staticNoiseKey: NOISE_KEY_3,
}).then((waku) => waku.start().then(() => waku)),
]);
waku1.addPeerToAddressBook(
waku2.libp2p.peerId,
// TODO: Upgrade libp2p package.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: New multiaddr type but they seem mostly compatible
waku2.libp2p.getMultiaddrs()
);
waku3.addPeerToAddressBook(
waku2.libp2p.peerId,
// TODO: Upgrade libp2p package.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: New multiaddr type but they seem mostly compatible
waku2.libp2p.getMultiaddrs()
);
await Promise.all([
waitForRemotePeer(waku1, [Protocols.Relay]),
waitForRemotePeer(waku2, [Protocols.Relay]),
]);
const messageText = "Communicating using a custom pubsub topic";
const waku2ReceivedMsgPromise: Promise<Message> = new Promise(
(resolve) => {
waku2.relay.addObserver(TestDecoder, resolve);
}
);
// The promise **fails** if we receive a message on the default
// pubsub topic.
const waku3NoMsgPromise: Promise<Message> = new Promise(
(resolve, reject) => {
waku3.relay.addObserver(TestDecoder, reject);
setTimeout(resolve, 1000);
}
);
await waku1.relay.send(TestEncoder, {
payload: utf8ToBytes(messageText),
});
const waku2ReceivedMsg = await waku2ReceivedMsgPromise;
await waku3NoMsgPromise;
expect(bytesToUtf8(waku2ReceivedMsg.payload!)).to.eq(messageText);
});
});
describe("Interop: nwaku", function () {
let waku: WakuPrivacy;
let nwaku: Nwaku;
beforeEach(async function () {
this.timeout(30_000);
waku = await createPrivacyNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
nwaku = new Nwaku(this.test?.ctx?.currentTest?.title + "");
await nwaku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Relay]);
});
afterEach(async function () {
!!nwaku && nwaku.stop();
!!waku && waku.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("nwaku subscribes", async function () {
let subscribers: PeerId[] = [];
while (subscribers.length === 0) {
await delay(200);
subscribers = waku.libp2p.pubsub.getSubscribers(DefaultPubSubTopic);
}
const nimPeerId = await nwaku.getPeerId();
expect(subscribers.map((p) => p.toString())).to.contain(
nimPeerId.toString()
);
});
it("Publishes to nwaku", async function () {
this.timeout(30000);
const messageText = "This is a message";
await waku.relay.send(TestEncoder, { payload: utf8ToBytes(messageText) });
let msgs: MessageRpcResponse[] = [];
while (msgs.length === 0) {
console.log("Waiting for messages");
await delay(200);
msgs = await nwaku.messages();
}
expect(msgs[0].contentTopic).to.equal(TestContentTopic);
expect(msgs[0].version).to.equal(0);
expect(bytesToUtf8(new Uint8Array(msgs[0].payload))).to.equal(
messageText
);
});
it("Nwaku publishes", async function () {
await delay(200);
const messageText = "Here is another message.";
const receivedMsgPromise: Promise<MessageV0> = new Promise((resolve) => {
waku.relay.addObserver<MessageV0>(TestDecoder, (msg) => resolve(msg));
});
await nwaku.sendMessage(
Nwaku.toMessageRpcQuery({
contentTopic: TestContentTopic,
payload: utf8ToBytes(messageText),
})
);
const receivedMsg = await receivedMsgPromise;
expect(receivedMsg.contentTopic).to.eq(TestContentTopic);
expect(receivedMsg.version).to.eq(0);
expect(bytesToUtf8(receivedMsg.payload!)).to.eq(messageText);
});
describe.skip("Two nodes connected to nwaku", function () {
let waku1: WakuPrivacy;
let waku2: WakuPrivacy;
let nwaku: Nwaku;
afterEach(async function () {
!!nwaku && nwaku.stop();
!!waku1 &&
waku1.stop().catch((e) => console.log("Waku failed to stop", e));
!!waku2 &&
waku2.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("Js publishes, other Js receives", async function () {
this.timeout(60_000);
[waku1, waku2] = await Promise.all([
createPrivacyNode({
staticNoiseKey: NOISE_KEY_1,
emitSelf: true,
}).then((waku) => waku.start().then(() => waku)),
createPrivacyNode({
staticNoiseKey: NOISE_KEY_2,
}).then((waku) => waku.start().then(() => waku)),
]);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start();
const nwakuMultiaddr = await nwaku.getMultiaddrWithId();
await Promise.all([
waku1.dial(nwakuMultiaddr),
waku2.dial(nwakuMultiaddr),
]);
// Wait for identify protocol to finish
await Promise.all([
waitForRemotePeer(waku1, [Protocols.Relay]),
waitForRemotePeer(waku2, [Protocols.Relay]),
]);
await delay(2000);
// Check that the two JS peers are NOT directly connected
expect(await waku1.libp2p.peerStore.has(waku2.libp2p.peerId)).to.be
.false;
expect(waku2.libp2p.peerStore.has(waku1.libp2p.peerId)).to.be.false;
const msgStr = "Hello there!";
const message = { payload: utf8ToBytes(msgStr) };
const waku2ReceivedMsgPromise: Promise<Message> = new Promise(
(resolve) => {
waku2.relay.addObserver(TestDecoder, resolve);
}
);
await waku1.relay.send(TestEncoder, message);
console.log("Waiting for message");
const waku2ReceivedMsg = await waku2ReceivedMsgPromise;
expect(waku2ReceivedMsg.payload).to.eq(msgStr);
});
});
});
});
+571
View File
@@ -0,0 +1,571 @@
import { createFullNode } from "@waku/create";
import type { Message, WakuFull } from "@waku/interfaces";
import { Protocols } from "@waku/interfaces";
import { expect } from "chai";
import debug from "debug";
import {
makeLogFileName,
NOISE_KEY_1,
NOISE_KEY_2,
Nwaku,
} from "../../test_utils";
import {
generatePrivateKey,
generateSymmetricKey,
getPublicKey,
} from "../crypto";
import { bytesToUtf8, utf8ToBytes } from "../utils";
import { waitForRemotePeer } from "../wait_for_remote_peer";
import { DecoderV0, EncoderV0 } from "../waku_message/version_0.js";
import {
AsymDecoder,
AsymEncoder,
SymDecoder,
SymEncoder,
} from "../waku_message/version_1.js";
import { PageDirection } from "./history_rpc";
const log = debug("waku:test:store");
const TestContentTopic = "/test/1/waku-store/utf8";
const TestEncoder = new EncoderV0(TestContentTopic);
const TestDecoder = new DecoderV0(TestContentTopic);
describe("Waku Store", () => {
let waku: WakuFull;
let nwaku: Nwaku;
beforeEach(async function () {
this.timeout(15_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({ persistMessages: true, store: true, lightpush: true });
});
afterEach(async function () {
!!nwaku && nwaku.stop();
!!waku && waku.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("Generator", async function () {
this.timeout(15_000);
const totalMsgs = 20;
for (let i = 0; i < totalMsgs; i++) {
expect(
await nwaku.sendMessage(
Nwaku.toMessageRpcQuery({
payload: utf8ToBytes(`Message ${i}`),
contentTopic: TestContentTopic,
})
)
).to.be.true;
}
waku = await createFullNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Store]);
const messages: Message[] = [];
let promises: Promise<void>[] = [];
for await (const msgPromises of waku.store.queryGenerator([TestDecoder])) {
const _promises = msgPromises.map(async (promise) => {
const msg = await promise;
if (msg) {
messages.push(msg);
}
});
promises = promises.concat(_promises);
}
await Promise.all(promises);
expect(messages?.length).eq(totalMsgs);
const result = messages?.findIndex((msg) => {
return bytesToUtf8(msg.payload!) === "Message 0";
});
expect(result).to.not.eq(-1);
});
it("Generator, no message returned", async function () {
this.timeout(15_000);
waku = await createFullNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Store]);
const messages: Message[] = [];
let promises: Promise<void>[] = [];
for await (const msgPromises of waku.store.queryGenerator([TestDecoder])) {
const _promises = msgPromises.map(async (promise) => {
const msg = await promise;
if (msg) {
messages.push(msg);
}
});
promises = promises.concat(_promises);
}
await Promise.all(promises);
expect(messages?.length).eq(0);
});
it("Callback on promise", async function () {
this.timeout(15_000);
const totalMsgs = 15;
for (let i = 0; i < totalMsgs; i++) {
expect(
await nwaku.sendMessage(
Nwaku.toMessageRpcQuery({
payload: utf8ToBytes(`Message ${i}`),
contentTopic: TestContentTopic,
})
)
).to.be.true;
}
waku = await createFullNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Store]);
const messages: Message[] = [];
await waku.store.queryCallbackOnPromise(
[TestDecoder],
async (msgPromise) => {
const msg = await msgPromise;
if (msg) {
messages.push(msg);
}
}
);
expect(messages?.length).eq(totalMsgs);
const result = messages?.findIndex((msg) => {
return bytesToUtf8(msg.payload!) === "Message 0";
});
expect(result).to.not.eq(-1);
});
it("Callback on promise, aborts when callback returns true", async function () {
this.timeout(15_000);
const totalMsgs = 20;
for (let i = 0; i < totalMsgs; i++) {
expect(
await nwaku.sendMessage(
Nwaku.toMessageRpcQuery({
payload: utf8ToBytes(`Message ${i}`),
contentTopic: TestContentTopic,
})
)
).to.be.true;
}
waku = await createFullNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Store]);
const desiredMsgs = 14;
const messages: Message[] = [];
await waku.store.queryCallbackOnPromise(
[TestDecoder],
async (msgPromise) => {
const msg = await msgPromise;
if (msg) {
messages.push(msg);
}
return messages.length >= desiredMsgs;
},
{ pageSize: 7 }
);
expect(messages?.length).eq(desiredMsgs);
});
it("Ordered Callback - Forward", async function () {
this.timeout(15_000);
const totalMsgs = 18;
for (let i = 0; i < totalMsgs; i++) {
expect(
await nwaku.sendMessage(
Nwaku.toMessageRpcQuery({
payload: utf8ToBytes(`Message ${i}`),
contentTopic: TestContentTopic,
})
)
).to.be.true;
}
waku = await createFullNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Store]);
const messages: Message[] = [];
await waku.store.queryOrderedCallback(
[TestDecoder],
async (msg) => {
messages.push(msg);
},
{
pageDirection: PageDirection.FORWARD,
}
);
expect(messages?.length).eq(totalMsgs);
for (let index = 0; index < totalMsgs; index++) {
expect(
messages?.findIndex((msg) => {
return bytesToUtf8(msg.payload!) === `Message ${index}`;
})
).to.eq(index);
}
});
it("Ordered Callback - Backward", async function () {
this.timeout(15_000);
const totalMsgs = 18;
for (let i = 0; i < totalMsgs; i++) {
expect(
await nwaku.sendMessage(
Nwaku.toMessageRpcQuery({
payload: utf8ToBytes(`Message ${i}`),
contentTopic: TestContentTopic,
})
)
).to.be.true;
}
waku = await createFullNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Store]);
let messages: Message[] = [];
await waku.store.queryOrderedCallback(
[TestDecoder],
async (msg) => {
messages.push(msg);
},
{
pageDirection: PageDirection.BACKWARD,
}
);
messages = messages.reverse();
expect(messages?.length).eq(totalMsgs);
for (let index = 0; index < totalMsgs; index++) {
expect(
messages?.findIndex((msg) => {
return bytesToUtf8(msg.payload!) === `Message ${index}`;
})
).to.eq(index);
}
});
it("Generator, with asymmetric & symmetric encrypted messages", async function () {
this.timeout(15_000);
const asymText = "This message is encrypted for me using asymmetric";
const asymTopic = "/test/1/asymmetric/proto";
const symText =
"This message is encrypted for me using symmetric encryption";
const symTopic = "/test/1/symmetric/proto";
const clearText = "This is a clear text message for everyone to read";
const otherText =
"This message is not for and I must not be able to read it";
const timestamp = new Date();
const asymMsg = { payload: utf8ToBytes(asymText), timestamp };
const symMsg = {
payload: utf8ToBytes(symText),
timestamp: new Date(timestamp.valueOf() + 1),
};
const clearMsg = {
payload: utf8ToBytes(clearText),
timestamp: new Date(timestamp.valueOf() + 2),
};
const otherMsg = {
payload: utf8ToBytes(otherText),
timestamp: new Date(timestamp.valueOf() + 3),
};
const privateKey = generatePrivateKey();
const symKey = generateSymmetricKey();
const publicKey = getPublicKey(privateKey);
const asymEncoder = new AsymEncoder(asymTopic, publicKey);
const symEncoder = new SymEncoder(symTopic, symKey);
const otherEncoder = new AsymEncoder(
TestContentTopic,
getPublicKey(generatePrivateKey())
);
const asymDecoder = new AsymDecoder(asymTopic, privateKey);
const symDecoder = new SymDecoder(symTopic, symKey);
const [waku1, waku2, nimWakuMultiaddr] = await Promise.all([
createFullNode({
staticNoiseKey: NOISE_KEY_1,
}).then((waku) => waku.start().then(() => waku)),
createFullNode({
staticNoiseKey: NOISE_KEY_2,
}).then((waku) => waku.start().then(() => waku)),
nwaku.getMultiaddrWithId(),
]);
log("Waku nodes created");
await Promise.all([
waku1.dial(nimWakuMultiaddr),
waku2.dial(nimWakuMultiaddr),
]);
log("Waku nodes connected to nwaku");
await waitForRemotePeer(waku1, [Protocols.LightPush]);
log("Sending messages using light push");
await Promise.all([
waku1.lightPush.push(asymEncoder, asymMsg),
waku1.lightPush.push(symEncoder, symMsg),
waku1.lightPush.push(otherEncoder, otherMsg),
waku1.lightPush.push(TestEncoder, clearMsg),
]);
await waitForRemotePeer(waku2, [Protocols.Store]);
const messages: Message[] = [];
log("Retrieve messages from store");
for await (const msgPromises of waku2.store.queryGenerator([
asymDecoder,
symDecoder,
TestDecoder,
])) {
for (const promise of msgPromises) {
const msg = await promise;
if (msg) {
messages.push(msg);
}
}
}
// Messages are ordered from oldest to latest within a page (1 page query)
expect(bytesToUtf8(messages[0].payload!)).to.eq(asymText);
expect(bytesToUtf8(messages[1].payload!)).to.eq(symText);
expect(bytesToUtf8(messages[2].payload!)).to.eq(clearText);
expect(messages?.length).eq(3);
!!waku1 && waku1.stop().catch((e) => console.log("Waku failed to stop", e));
!!waku2 && waku2.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("Ordered callback, using start and end time", async function () {
this.timeout(20000);
const now = new Date();
const startTime = new Date();
// Set start time 5 minutes in the past
startTime.setTime(now.getTime() - 5 * 60 * 1000);
const message1Timestamp = new Date();
// Set first message was 4 minutes in the past
message1Timestamp.setTime(now.getTime() - 4 * 60 * 1000);
const message2Timestamp = new Date();
// Set second message 2 minutes in the past
message2Timestamp.setTime(now.getTime() - 2 * 60 * 1000);
const messageTimestamps = [message1Timestamp, message2Timestamp];
const endTime = new Date();
// Set end time 1 minute in the past
endTime.setTime(now.getTime() - 60 * 1000);
for (let i = 0; i < 2; i++) {
expect(
await nwaku.sendMessage(
Nwaku.toMessageRpcQuery({
payload: utf8ToBytes(`Message ${i}`),
contentTopic: TestContentTopic,
timestamp: messageTimestamps[i],
})
)
).to.be.true;
}
waku = await createFullNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Store]);
const nwakuPeerId = await nwaku.getPeerId();
const firstMessages: Message[] = [];
await waku.store.queryOrderedCallback(
[TestDecoder],
(msg) => {
if (msg) {
firstMessages.push(msg);
}
},
{
peerId: nwakuPeerId,
timeFilter: { startTime, endTime: message1Timestamp },
}
);
const bothMessages: Message[] = [];
await waku.store.queryOrderedCallback(
[TestDecoder],
async (msg) => {
bothMessages.push(msg);
},
{
peerId: nwakuPeerId,
timeFilter: {
startTime,
endTime,
},
}
);
expect(firstMessages?.length).eq(1);
expect(bytesToUtf8(firstMessages[0].payload!)).eq("Message 0");
expect(bothMessages?.length).eq(2);
});
it("Ordered callback, aborts when callback returns true", async function () {
this.timeout(15_000);
const totalMsgs = 20;
for (let i = 0; i < totalMsgs; i++) {
expect(
await nwaku.sendMessage(
Nwaku.toMessageRpcQuery({
payload: utf8ToBytes(`Message ${i}`),
contentTopic: TestContentTopic,
})
)
).to.be.true;
}
waku = await createFullNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Store]);
const desiredMsgs = 14;
const messages: Message[] = [];
await waku.store.queryOrderedCallback(
[TestDecoder],
async (msg) => {
messages.push(msg);
return messages.length >= desiredMsgs;
},
{ pageSize: 7 }
);
expect(messages?.length).eq(desiredMsgs);
});
});
describe("Waku Store, custom pubsub topic", () => {
const customPubSubTopic = "/waku/2/custom-dapp/proto";
let waku: WakuFull;
let nwaku: Nwaku;
beforeEach(async function () {
this.timeout(15_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
persistMessages: true,
store: true,
topics: customPubSubTopic,
});
});
afterEach(async function () {
!!nwaku && nwaku.stop();
!!waku && waku.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("Generator, custom pubsub topic", async function () {
this.timeout(15_000);
const totalMsgs = 20;
for (let i = 0; i < totalMsgs; i++) {
expect(
await nwaku.sendMessage(
Nwaku.toMessageRpcQuery({
payload: utf8ToBytes(`Message ${i}`),
contentTopic: TestContentTopic,
}),
customPubSubTopic
)
).to.be.true;
}
waku = await createFullNode({
staticNoiseKey: NOISE_KEY_1,
pubSubTopic: customPubSubTopic,
});
await waku.start();
await waku.dial(await nwaku.getMultiaddrWithId());
await waitForRemotePeer(waku, [Protocols.Store]);
const messages: Message[] = [];
let promises: Promise<void>[] = [];
for await (const msgPromises of waku.store.queryGenerator([TestDecoder])) {
const _promises = msgPromises.map(async (promise) => {
const msg = await promise;
if (msg) {
messages.push(msg);
}
});
promises = promises.concat(_promises);
}
await Promise.all(promises);
expect(messages?.length).eq(totalMsgs);
const result = messages?.findIndex((msg) => {
return bytesToUtf8(msg.payload!) === "Message 0";
});
expect(result).to.not.eq(-1);
});
});
@@ -0,0 +1,271 @@
import { createLightNode, createPrivacyNode } from "@waku/create";
import type { WakuLight, WakuPrivacy } from "@waku/interfaces";
import { Protocols } from "@waku/interfaces";
import { expect } from "chai";
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../test_utils";
import { delay } from "../test_utils/delay";
import { waitForRemotePeer } from "./wait_for_remote_peer";
describe("Wait for remote peer", function () {
let waku1: WakuPrivacy;
let waku2: WakuLight;
let nwaku: Nwaku | undefined;
afterEach(async function () {
if (nwaku) {
nwaku.stop();
nwaku = undefined;
}
waku1?.stop().catch((e) => console.log("Waku failed to stop", e));
waku2?.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("Relay - dialed first", async function () {
this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
relay: true,
store: false,
filter: false,
lightpush: false,
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku1 = await createPrivacyNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku1.start();
await waku1.dial(multiAddrWithId);
await delay(1000);
await waitForRemotePeer(waku1, [Protocols.Relay]);
const peers = waku1.relay.getMeshPeers();
const nimPeerId = multiAddrWithId.getPeerId();
expect(nimPeerId).to.not.be.undefined;
expect(peers).to.includes(nimPeerId);
});
it("Relay - dialed after", async function () {
this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
relay: true,
store: false,
filter: false,
lightpush: false,
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku1 = await createPrivacyNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku1.start();
const waitPromise = waitForRemotePeer(waku1, [Protocols.Relay]);
await delay(1000);
await waku1.dial(multiAddrWithId);
await waitPromise;
const peers = waku1.relay.getMeshPeers();
const nimPeerId = multiAddrWithId.getPeerId();
expect(nimPeerId).to.not.be.undefined;
expect(peers).includes(nimPeerId);
});
it("Relay - times out", function (done) {
this.timeout(5000);
createPrivacyNode({
staticNoiseKey: NOISE_KEY_1,
})
.then((waku1) => waku1.start().then(() => waku1))
.then((waku1) => {
waitForRemotePeer(waku1, [Protocols.Relay], 200).then(
() => {
throw "Promise expected to reject on time out";
},
(reason) => {
expect(reason).to.eq("Timed out waiting for a remote peer.");
done();
}
);
});
});
it("Store - dialed first", async function () {
this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
store: true,
relay: false,
lightpush: false,
filter: false,
persistMessages: true,
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku2 = await createLightNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku2.start();
await waku2.dial(multiAddrWithId);
await delay(1000);
await waitForRemotePeer(waku2, [Protocols.Store]);
const peers = (await waku2.store.peers()).map((peer) => peer.id.toString());
const nimPeerId = multiAddrWithId.getPeerId();
expect(nimPeerId).to.not.be.undefined;
expect(peers.includes(nimPeerId as string)).to.be.true;
});
it("Store - dialed after - with timeout", async function () {
this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
store: true,
relay: false,
lightpush: false,
filter: false,
persistMessages: true,
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku2 = await createLightNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku2.start();
const waitPromise = waitForRemotePeer(waku2, [Protocols.Store], 2000);
await delay(1000);
await waku2.dial(multiAddrWithId);
await waitPromise;
const peers = (await waku2.store.peers()).map((peer) => peer.id.toString());
const nimPeerId = multiAddrWithId.getPeerId();
expect(nimPeerId).to.not.be.undefined;
expect(peers.includes(nimPeerId as string)).to.be.true;
});
it("LightPush", async function () {
this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
lightpush: true,
filter: false,
relay: false,
store: false,
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku2 = await createLightNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku2.start();
await waku2.dial(multiAddrWithId);
await waitForRemotePeer(waku2, [Protocols.LightPush]);
const peers = (await waku2.lightPush.peers()).map((peer) =>
peer.id.toString()
);
const nimPeerId = multiAddrWithId.getPeerId();
expect(nimPeerId).to.not.be.undefined;
expect(peers.includes(nimPeerId as string)).to.be.true;
});
it("Filter", async function () {
this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
filter: true,
lightpush: false,
relay: false,
store: false,
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku2 = await createLightNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku2.start();
await waku2.dial(multiAddrWithId);
await waitForRemotePeer(waku2, [Protocols.Filter]);
const peers = (await waku2.filter.peers()).map((peer) =>
peer.id.toString()
);
const nimPeerId = multiAddrWithId.getPeerId();
expect(nimPeerId).to.not.be.undefined;
expect(peers.includes(nimPeerId as string)).to.be.true;
});
it("Light Node - default protocols", async function () {
this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
filter: true,
lightpush: true,
relay: false,
store: true,
persistMessages: true,
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku2 = await createLightNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku2.start();
await waku2.dial(multiAddrWithId);
await waitForRemotePeer(waku2);
const filterPeers = (await waku2.filter.peers()).map((peer) =>
peer.id.toString()
);
const storePeers = (await waku2.store.peers()).map((peer) =>
peer.id.toString()
);
const lightPushPeers = (await waku2.lightPush.peers()).map((peer) =>
peer.id.toString()
);
const nimPeerId = multiAddrWithId.getPeerId();
expect(nimPeerId).to.not.be.undefined;
expect(filterPeers.includes(nimPeerId as string)).to.be.true;
expect(storePeers.includes(nimPeerId as string)).to.be.true;
expect(lightPushPeers.includes(nimPeerId as string)).to.be.true;
});
it("Privacy Node - default protocol", async function () {
this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
filter: false,
lightpush: false,
relay: true,
store: false,
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku1 = await createPrivacyNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku1.start();
await waku1.dial(multiAddrWithId);
await waitForRemotePeer(waku1);
const peers = await waku1.relay.getMeshPeers();
const nimPeerId = multiAddrWithId.getPeerId();
expect(nimPeerId).to.not.be.undefined;
expect(peers.includes(nimPeerId as string)).to.be.true;
});
});
+187
View File
@@ -0,0 +1,187 @@
import type { PeerId } from "@libp2p/interface-peer-id";
import { createLightNode, createPrivacyNode } from "@waku/create";
import type { Message, Waku, WakuLight, WakuPrivacy } from "@waku/interfaces";
import { Protocols } from "@waku/interfaces";
import { expect } from "chai";
import {
makeLogFileName,
NOISE_KEY_1,
NOISE_KEY_2,
Nwaku,
} from "../test_utils/";
import { generateSymmetricKey } from "./crypto";
import { PeerDiscoveryStaticPeers } from "./peer_discovery_static_list";
import { bytesToUtf8, utf8ToBytes } from "./utils";
import { waitForRemotePeer } from "./wait_for_remote_peer";
import { SymDecoder, SymEncoder } from "./waku_message/version_1.js";
const TestContentTopic = "/test/1/waku/utf8";
describe("Waku Dial [node only]", function () {
describe("Interop: nwaku", function () {
let waku: Waku;
let nwaku: Nwaku;
afterEach(async function () {
!!nwaku && nwaku.stop();
!!waku && waku.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("connects to nwaku", async function () {
this.timeout(20_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start({
filter: true,
store: true,
lightpush: true,
persistMessages: true,
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku = await createLightNode({
staticNoiseKey: NOISE_KEY_1,
});
await waku.start();
await waku.dial(multiAddrWithId);
await waitForRemotePeer(waku);
const nimPeerId = await nwaku.getPeerId();
expect(await waku.libp2p.peerStore.has(nimPeerId)).to.be.true;
});
});
describe("Bootstrap", function () {
let waku: WakuLight;
let nwaku: Nwaku;
afterEach(async function () {
!!nwaku && nwaku.stop();
!!waku && waku.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("Passing an array", async function () {
this.timeout(10_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start();
const multiAddrWithId = await nwaku.getMultiaddrWithId();
waku = await createLightNode({
staticNoiseKey: NOISE_KEY_1,
libp2p: {
peerDiscovery: [new PeerDiscoveryStaticPeers([multiAddrWithId])],
},
});
await waku.start();
const connectedPeerID: PeerId = await new Promise((resolve) => {
waku.libp2p.connectionManager.addEventListener(
"peer:connect",
(evt) => {
resolve(evt.detail.remotePeer);
}
);
});
expect(connectedPeerID.toString()).to.eq(multiAddrWithId.getPeerId());
});
it("Using a function", async function () {
this.timeout(10_000);
nwaku = new Nwaku(makeLogFileName(this));
await nwaku.start();
waku = await createLightNode({
staticNoiseKey: NOISE_KEY_1,
libp2p: {
peerDiscovery: [
new PeerDiscoveryStaticPeers([await nwaku.getMultiaddrWithId()]),
],
},
});
await waku.start();
const connectedPeerID: PeerId = await new Promise((resolve) => {
waku.libp2p.connectionManager.addEventListener(
"peer:connect",
(evt) => {
resolve(evt.detail.remotePeer);
}
);
});
const multiAddrWithId = await nwaku.getMultiaddrWithId();
expect(connectedPeerID.toString()).to.eq(multiAddrWithId.getPeerId());
});
});
});
describe("Decryption Keys", () => {
afterEach(function () {
if (this.currentTest?.state === "failed") {
console.log(`Test failed, log file name is ${makeLogFileName(this)}`);
}
});
let waku1: WakuPrivacy;
let waku2: WakuPrivacy;
beforeEach(async function () {
this.timeout(5000);
[waku1, waku2] = await Promise.all([
createPrivacyNode({ staticNoiseKey: NOISE_KEY_1 }).then((waku) =>
waku.start().then(() => waku)
),
createPrivacyNode({
staticNoiseKey: NOISE_KEY_2,
libp2p: { addresses: { listen: ["/ip4/0.0.0.0/tcp/0/ws"] } },
}).then((waku) => waku.start().then(() => waku)),
]);
waku1.addPeerToAddressBook(
waku2.libp2p.peerId,
// TODO: Upgrade libp2p package.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore: New multiaddr type but they seem mostly compatible
waku2.libp2p.getMultiaddrs()
);
await Promise.all([
waitForRemotePeer(waku1, [Protocols.Relay]),
waitForRemotePeer(waku2, [Protocols.Relay]),
]);
});
afterEach(async function () {
!!waku1 && waku1.stop().catch((e) => console.log("Waku failed to stop", e));
!!waku2 && waku2.stop().catch((e) => console.log("Waku failed to stop", e));
});
it("Used by Waku Relay", async function () {
this.timeout(10000);
const symKey = generateSymmetricKey();
const decoder = new SymDecoder(TestContentTopic, symKey);
const encoder = new SymEncoder(TestContentTopic, symKey);
const messageText = "Message is encrypted";
const messageTimestamp = new Date("1995-12-17T03:24:00");
const message = {
payload: utf8ToBytes(messageText),
timestamp: messageTimestamp,
};
const receivedMsgPromise: Promise<Message> = new Promise((resolve) => {
waku2.relay.addObserver(decoder, resolve);
});
await waku1.relay.send(encoder, message);
const receivedMsg = await receivedMsgPromise;
expect(receivedMsg.contentTopic).to.eq(TestContentTopic);
expect(bytesToUtf8(receivedMsg.payload!)).to.eq(messageText);
expect(receivedMsg.timestamp?.valueOf()).to.eq(messageTimestamp.valueOf());
});
});
+42
View File
@@ -0,0 +1,42 @@
import type { PeerId } from "@libp2p/interface-peer-id";
import { createLightNode } from "@waku/create";
import type { WakuLight } from "@waku/interfaces";
import { expect } from "chai";
describe("Waku Dial", function () {
describe("Bootstrap [live data]", function () {
let waku: WakuLight;
afterEach(function () {
!!waku && waku.stop().catch((e) => console.log("Waku failed to stop", e));
});
before(function () {
if (process.env.CI) {
this.skip();
}
});
it("Enabling default [live data]", async function () {
// This test depends on fleets.status.im being online.
// This dependence must be removed once DNS discovery is implemented
this.timeout(20_000);
waku = await createLightNode({
defaultBootstrap: true,
});
await waku.start();
const connectedPeerID: PeerId = await new Promise((resolve) => {
waku.libp2p.connectionManager.addEventListener(
"peer:connect",
(evt) => {
resolve(evt.detail.remotePeer);
}
);
});
expect(connectedPeerID).to.not.be.undefined;
});
});
});
-8
View File
@@ -1,8 +0,0 @@
{
"extends": "./tsconfig",
"compilerOptions": {
"module": "esnext",
"noEmit": true
},
"exclude": []
}
+4 -4
View File
@@ -3,9 +3,10 @@
"incremental": true,
"target": "es2020",
"outDir": "dist/",
"rootDir": "src",
"rootDir": "tests",
"noEmit": true,
"moduleResolution": "node",
"module": "es2020",
"module": "esnext",
"declaration": true,
"sourceMap": true,
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
@@ -45,8 +46,7 @@
"types": ["node", "mocha"],
"typeRoots": ["node_modules/@types", "src/types"]
},
"include": ["src"],
"exclude": ["src/**/*.spec.ts", "src/test_utils"],
"include": ["tests"],
"compileOnSave": false,
"ts-node": {
"files": true
+1 -1
View File
@@ -1,5 +1,5 @@
{
"extends": "./tsconfig.dev",
"extends": "./tsconfig",
"compilerOptions": {
"noEmit": false
}