// Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only describe('ProtoBuf.js', () => { const { ProtoBuf } = window.dcodeIO; const sampleProto = `message Simple_v1 { optional string knownName = 1; optional string knownValue = 3; } message Simple_v2 { optional string knownName = 1; optional int32 unknownFlags = 2; optional string knownValue = 3; optional string unknownString = 4; }`; it('retains unknown fields', () => { const builder = ProtoBuf.loadProto(sampleProto); const protos = builder.build(); const v2 = new protos.Simple_v2(); v2.knownName = 'version2'; v2.unknownFlags = 42; v2.knownValue = 'known value'; v2.unknownString = 'f'; const v1 = protos.Simple_v1.decode(v2.encode()); const result = protos.Simple_v2.decode(v1.encode()); assert.equal(result.knownName, v2.knownName, 'known fields'); assert.equal(42, result.unknownFlags, 'unknown flag'); assert.equal('f', result.unknownString, 'unknown string'); assert.equal('known value', result.knownValue, 'known value'); }); it('supports nested unknown fields', () => { const nestedProto = ` ${sampleProto} message Container_v1 { optional Simple_v1 elem = 1; } message Container_v2 { optional Simple_v2 elem = 1; }`; const builder = ProtoBuf.loadProto(nestedProto); const protos = builder.build(); const v2 = new protos.Container_v2(); v2.elem = { knownName: 'nested v2', unknownFlags: 10, knownValue: 'hello world', }; const v1 = protos.Container_v1.decode(v2.encode()); const result = protos.Container_v2.decode(v1.encode()); assert.equal( v2.elem.knownName, result.elem.knownName, 'nested: known fields' ); assert.equal(10, result.elem.unknownFlags, 'nested: unknown flags'); assert.equal('hello world', result.elem.knownValue, 'known value'); }); it('allows multi-byte id', () => { const proto = `message Simple_v1 { optional string knownName = 1; optional string knownValue = 3; } message Simple_v2 { optional string knownName = 1; optional int32 unknownFlags = 296; optional string knownValue = 3; }`; const builder = ProtoBuf.loadProto(proto); const protos = builder.build(); const v2 = new protos.Simple_v2(); v2.knownName = 'v2 multibyte'; v2.unknownFlags = 16; v2.knownValue = 'foo bar'; const v1 = protos.Simple_v1.decode(v2.encode()); const result = protos.Simple_v2.decode(v1.encode()); assert.equal(result.knownName, v2.knownName, 'multibyte: known fields'); assert.equal(16, result.unknownFlags, 'multibyte: unknown fields'); assert.equal('foo bar', result.knownValue, 'multibyte: known value'); }); it('retains fields with 64bit type', () => { const proto = `message Simple_v1 { optional string knownName = 1; optional string knownValue = 3; } message Simple_v2 { optional string knownName = 1; optional double unknownFlags = 2; optional string knownValue = 3; }`; const builder = ProtoBuf.loadProto(proto); const protos = builder.build(); const v2 = new protos.Simple_v2(); v2.knownName = 'v2 double'; v2.unknownFlags = 0; v2.knownValue = 'double double'; const v1 = protos.Simple_v1.decode(v2.encode()); const result = protos.Simple_v2.decode(v1.encode()); assert.equal(result.knownName, v2.knownName, 'double: known fields'); assert.equal(0, result.unknownFlags, 'double: unknown fields'); assert.equal('double double', result.knownValue, 'double: known value'); }); });