Fix WakuMessage (de)serialisation

This commit is contained in:
Franck Royer 2021-03-12 14:23:21 +11:00
parent 27c433f750
commit a7c666f108
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
3 changed files with 51 additions and 10 deletions

View File

@ -9,7 +9,7 @@ import { Message } from './waku_message';
import { CODEC, TOPIC, WakuRelay } from './waku_relay'; import { CODEC, TOPIC, WakuRelay } from './waku_relay';
test('Publishes message', async (t) => { test('Publishes message', async (t) => {
const message = Message.fromString('Bird bird bird, bird is the word!'); const message = Message.fromUtf8String('Bird bird bird, bird is the word!');
const [node1, node2] = await Promise.all([createNode(), createNode()]); const [node1, node2] = await Promise.all([createNode(), createNode()]);
const wakuRelayNode1 = new WakuRelay(node1.pubsub); const wakuRelayNode1 = new WakuRelay(node1.pubsub);
@ -123,7 +123,7 @@ test('Nim-interop: nim node sends message', async (t) => {
// Setup the promise before publishing to ensure the event is not missed // Setup the promise before publishing to ensure the event is not missed
const promise = waitForNextData(node.pubsub); const promise = waitForNextData(node.pubsub);
const message = Message.fromString('This is a message.'); const message = Message.fromUtf8String('This is a message.');
await delay(500); await delay(500);

View File

@ -1,15 +1,40 @@
import { fc, testProp } from 'ava-fast-check'; import { fc, testProp } from 'ava-fast-check';
import { WakuMessage } from '../gen/proto/waku/v2/waku_pb';
import { Message } from './waku_message'; import { Message } from './waku_message';
// This test is more about documenting how protobuf library works than testing it
testProp('Protobuf round trip binary serialisation', [fc.string()], (t, s) => {
const wakuMsg = new WakuMessage();
wakuMsg.setPayload(Buffer.from(s, 'utf-8'));
const binary = wakuMsg.serializeBinary();
const actual = WakuMessage.deserializeBinary(binary);
const payload = actual.getPayload();
let buf;
if (typeof payload === 'string') {
buf = Buffer.from(payload, 'base64');
} else {
buf = Buffer.from(payload);
}
t.deepEqual(s, buf.toString('utf-8'));
});
testProp( testProp(
'Waku message round trip binary serialisation', 'Waku message round trip binary serialisation',
[fc.string()], [fc.string()],
(t, s) => { (t, s) => {
const msg = Message.fromString(s); const msg = Message.fromUtf8String(s);
const binary = msg.toBinary(); const binary = msg.toBinary();
const actual = Message.fromBinary(binary); const actual = Message.fromBinary(binary);
t.true(actual.isEqualTo(msg)); t.true(
actual.isEqualTo(msg),
`${JSON.stringify(actual)}\n${JSON.stringify(msg)}`
);
} }
); );

View File

@ -3,7 +3,7 @@ import { WakuMessage } from '../gen/proto/waku/v2/waku_pb';
// Ensure that this class matches the proto interface while // Ensure that this class matches the proto interface while
// Protecting the user from protobuf oddities // Protecting the user from protobuf oddities
export class Message { export class Message {
public payload: Uint8Array | string; public payload: Uint8Array;
public contentTopic: number; public contentTopic: number;
public version: number; public version: number;
@ -12,12 +12,24 @@ export class Message {
const msg = protobuf.toObject(); const msg = protobuf.toObject();
this.payload = msg.payload; // Let's make is easier to avoid mistakes and only store in Uint8Array format
let payload;
if (typeof msg.payload === 'string') {
payload = Buffer.from(msg.payload, 'base64');
} else {
payload = msg.payload;
}
this.payload = payload;
this.contentTopic = msg.contentTopic; this.contentTopic = msg.contentTopic;
this.version = msg.version; this.version = msg.version;
} }
static fromString(message: string): Message { /**
* Create Message from utf-8 string
* @param message
* @returns {Message}
*/
static fromUtf8String(message: string): Message {
const wakuMsg = new WakuMessage(); const wakuMsg = new WakuMessage();
// Only Version 0 is implemented in Waku 2. // Only Version 0 is implemented in Waku 2.
@ -27,7 +39,10 @@ export class Message {
// This is the content topic commonly used at this time // This is the content topic commonly used at this time
wakuMsg.setContentTopic(1); wakuMsg.setContentTopic(1);
wakuMsg.setPayload(message); const buf = Buffer.from(message, 'utf-8');
// Only accepts Uint8Array or base64 string
wakuMsg.setPayload(buf);
return new Message(wakuMsg); return new Message(wakuMsg);
} }
@ -42,10 +57,11 @@ export class Message {
} }
// Purely for tests purposes. // Purely for tests purposes.
// We do not care about protobuf field when checking equality // We do consider protobuf field when checking equality
// As the content is held by the other fields.
isEqualTo(other: Message) { isEqualTo(other: Message) {
return ( return (
this.payload === other.payload && Buffer.compare(this.payload, other.payload) === 0 &&
this.contentTopic === other.contentTopic && this.contentTopic === other.contentTopic &&
this.version === other.version this.version === other.version
); );