12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267 |
- /*
- Copyright 2013 Daniel Wirtz <dcode@dcode.io>
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
- /**
- * ProtoBuf.js Test Suite.
- * @author Daniel Wirtz <dcode@dcode.io>
- */
- (function(global) {
- var FILE = "protobuf.js";
- var BROWSER = !!global.window;
- var StdOutFixture = require('fixture-stdout');
- var fixture = new StdOutFixture();
- var ProtoBuf = BROWSER ? global.dcodeIO.ProtoBuf : require(__dirname+"/../dist/"+FILE),
- ByteBuffer = BROWSER ? global.dcodeIO.ByteBuffer : ByteBuffer || require("bytebuffer"),
- util = BROWSER ? null : require("util"),
- fs = BROWSER ? null : require("fs");
- if (typeof __dirname == 'undefined') {
- __dirname = document.location.href.replace(/[\/\\][^\/\\]*$/, "");
- }
- /**
- * Constructs a new Sandbox for module loaders and shim testing.
- * @param {Object.<string,*>} properties Additional properties to set
- * @constructor
- */
- var Sandbox = function(properties) {
- this.ByteBuffer = function() {};
- for (var i in properties) {
- this[i] = properties[i];
- }
- this.console = {
- log: function(s) {
- console.log(s);
- }
- };
- };
- function fail(e) {
- throw(e);
- }
- /**
- * Validates the complexDotProto and complexInline tests.
- * @param {*} test Nodeunit test
- * @param {Object} Game Game namespace
- */
- function validateComplex(test, Game) {
- var Car = Game.Cars.Car,
- Vendor = Car.Vendor,
- Speed = Car.Speed;
- var vendor;
- // Car from class with argument list properties
- var car = new Car(
- "Rusty",
- // Vendor from class with object properties
- vendor = new Vendor({
- "name": "Iron Inc.",
- // Address from object
- "address": {
- "country": "US"
- },
- "models": ["m1"]
- }),
- // Speed from enum object
- Speed.SUPERFAST
- );
- test.equal(car.model, "Rusty");
- test.equal(car.vendor.name, "Iron Inc.");
- test.equal(car.vendor.address.country, "US");
- test.equal(car.vendor.address.country, car.getVendor().get_address().country);
- var bb = new ByteBuffer(32);
- car.encode(bb);
- test.equal(bb.flip().toString("debug"), "<0A 05 52 75 73 74 79 12 15 0A 09 49 72 6F 6E 20 49 6E 63 2E 12 04 0A 02 55 53 1A 02 6D 31 18 02>");
- var carDec = Car.decode(bb);
- test.equal(carDec.model, "Rusty");
- test.equal(carDec.vendor.name, "Iron Inc.");
- test.equal(carDec.vendor.address.country, "US");
- test.equal(carDec.vendor.address.country, carDec.getVendor().get_address().country);
- test.equal(carDec.vendor.models[0], "m1");
- }
- /**
- * Test suite.
- * @type {Object.<string,function>}
- */
- var suite = {
- "init": function(test) {
- test.ok(typeof ProtoBuf == "object");
- test.ok(typeof ProtoBuf.Reflect == 'object');
- test.ok(typeof ProtoBuf.loadProto == "function");
- test.ok(typeof ProtoBuf.loadProtoFile == "function");
- test.strictEqual(ProtoBuf.loadProto, ProtoBuf.protoFromString);
- test.strictEqual(ProtoBuf.loadProtoFile, ProtoBuf.protoFromFile);
- test.ok(ProtoBuf.ByteBuffer);
- test.done();
- },
- "IS_NODE": function(test) {
- test.ok(ProtoBuf.Util.IS_NODE);
- test.done();
- },
- // Example "A Simple Message" from the protobuf docs
- // https://developers.google.com/protocol-buffers/docs/encoding#simple
- "example1": function(test) {
- try{
- var builder = ProtoBuf.loadProtoFile(__dirname+"/example1.proto");
- var Test1 = builder.build("Test1");
- test.ok(typeof Test1 == 'function');
- var inst = new Test1(150);
- test.ok(inst instanceof ProtoBuf.Builder.Message);
- test.equal(inst.a, 150);
- test.equal(inst.getA(), 150);
- test.equal(inst.get_a(), 150);
- inst.setA(151);
- test.equal(inst.a, 151);
- test.equal(inst.getA(), 151);
- test.equal(inst.get_a(), 151);
- inst.set_a(152);
- test.equal(inst.a, 152);
- test.equal(inst.toString(), ".Test1");
- test.throws(function() {
- inst.setA(null); // required
- });
- test.throws(function() {
- inst.setA([]);
- });
- var size = inst.calculate();
- var bb = new ByteBuffer(3);
- inst.encode(bb);
- test.strictEqual(bb.offset, size);
- test.equal(bb.flip().toString("debug"), "<08 98 01>");
- var instDec = Test1.decode(bb);
- test.equal(instDec.a, 152);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // Basically the same as example1, but with an unsigned value.
- "example1u": function(test) {
- try{
- var builder = ProtoBuf.loadProtoFile(__dirname+"/example1u.proto");
- var Test1u = builder.build("Test1u");
- test.ok(typeof Test1u == 'function');
- var inst = new Test1u(-1);
- test.strictEqual(inst.a, 4294967295);
- var bb = new ByteBuffer(6);
- var size = inst.calculate();
- inst.encode(bb);
- test.strictEqual(bb.offset, size);
- test.equal(bb.flip().toString("debug"), "<08 FF FF FF FF 0F>");
- var instDec = Test1u.decode(bb);
- test.strictEqual(instDec.a, 4294967295);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // Example "Strings" from the protobuf docs
- // https://developers.google.com/protocol-buffers/docs/encoding#types
- "example2": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/example2.proto");
- var Test2 = builder.build("Test2");
- var inst = new Test2("testing");
- var bb = new ByteBuffer(9);
- var size = inst.calculate();
- inst.encode(bb);
- test.strictEqual(bb.offset, size);
- test.equal(bb.flip().toString("debug"), "<12 07 74 65 73 74 69 6E 67>");
- var instDec = Test2.decode(bb);
- test.equal(instDec.b, "testing");
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // Example "Embedded Messages" from the protobuf docs
- // https://developers.google.com/protocol-buffers/docs/encoding#embedded
- "example3": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/example3.proto");
- var root = builder.build();
- var Test1 = root.Test1;
- var Test3 = root.Test3;
- var inst = new Test3(new Test1(150));
- var bb = new ByteBuffer(5);
- test.equal(inst.c.a, 150);
- var size = inst.calculate();
- inst.encode(bb);
- test.strictEqual(bb.offset, size);
- test.equal(bb.flip().toString("debug"), "<1A 03 08 96 01>");
- var instDec = Test3.decode(bb);
- test.equal(instDec.c.a, 150);
- } catch(e) {
- fail(e);
- }
- test.done();
- },
- "example4": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/example4.proto");
- var Test4 = builder.build("Test4");
- var inst = new Test4([3, 270, 86942]);
- var bb = new ByteBuffer(8);
- test.equal(inst.d.length, 3);
- var size = inst.calculate();
- inst.encode(bb);
- test.strictEqual(bb.offset, size);
- test.equal(bb.flip().toString("debug"), "<22 06 03 8E 02 9E A7 05>");
- var instDec = Test4.decode(bb);
- test.equal(bb.toString("debug"), "22 06 03 8E 02 9E A7 05|");
- test.equal(instDec.d.length, 3);
- test.equal(instDec.d[2], 86942);
- } catch(e) {
- fail(e);
- }
- test.done();
- },
- "example5": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/example5.proto");
- builder.build();
- } catch(e) {
- fail(e);
- }
- test.done();
- },
- "constructor": function(test) {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/example1.proto");
- var Test1 = builder.build("Test1");
- var t1 = new Test1(123),
- t2 = new Test1({a: 123}),
- t3 = new Test1(t1);
- test.deepEqual(t1, t2);
- test.deepEqual(t2, t3);
- test.done();
- },
-
- "constructorWithOneofs": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/oneof.proto"),
- MyOneOf = builder.build("MyOneOf"),
- TOneOf = builder.lookup(".MyOneOf");
- test.ok(TOneOf.getChild("my_oneof"));
-
- var myOneOf = new MyOneOf();
- test.strictEqual(myOneOf.my_oneof, null);
- myOneOf.set("id", 1);
- test.strictEqual(myOneOf.my_oneof, "id");
- myOneOf.set("name", "me");
- test.strictEqual(myOneOf.my_oneof, "name");
- test.strictEqual(myOneOf.id, null);
-
- var copy = new MyOneOf(myOneOf); // this line is what was failing
- // Error: .MyOneOf#my_oneof is not a field: undefined
-
- test.deepEqual(myOneOf, copy);
-
- // Test same things are there
- test.strictEqual(copy.my_oneof, "name");
- test.strictEqual(copy.name, "me");
- test.strictEqual(copy.id, null);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "numberFormats": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/numberformats.proto");
- var Formats = builder.build("Formats");
- test.strictEqual(Formats.DEC, 1);
- test.strictEqual(Formats.HEX, 31);
- test.strictEqual(Formats.OCT, 15);
- var Msg = builder.build("Msg");
- var msg = new Msg();
- test.strictEqual(msg.dec, -1);
- test.strictEqual(msg.hex, -31);
- test.strictEqual(msg.hexUC, 521);
- test.strictEqual(msg.oct, -15);
- test.strictEqual(msg.exp, 0.1e5);
- test.strictEqual(msg.nod, 1.);
- test.strictEqual(msg.exn, 1e8);
- test.strictEqual(msg.sp1, Infinity);
- test.strictEqual(msg.sp2, -Infinity);
- test.ok(isNaN(msg.sp3));
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // Check encode/decode against a table of known correct pairs.
- // Note that javascript ArrayBuffer does not support signed Zero or NaN
- // bertdouglas (https://github.com/bertdouglas)
- "float": function(test) {
- try {
- var str_proto = "message Float {"
- + " required float f = 1;"
- + "}";
- var builder = ProtoBuf.loadProto(str_proto);
- var root = builder.build();
- var Float = root.Float;
- var in_tolerance = function (reference,actual) {
- var tol = 1e-6;
- var scale = 1.0;
- if (reference != 0.0 ) {
- scale = reference;
- };
- var err = Math.abs(reference - actual)/scale;
- return err < tol;
- };
- var f_vals = [
- // hex values are shown here in big-endian following IEEE754 notation
- // protobuf is little-endian
- // { f: -0.0 , b: "80 00 00 00" },
- { f: +0.0 , b: "00 00 00 00" },
- { f: -1e-10 , b: "AE DB E6 FF" },
- { f: +1e-10 , b: "2E DB E6 FF" },
- { f: -2e+10 , b: "D0 95 02 F9" },
- { f: +2e+10 , b: "50 95 02 F9" },
- { f: -3e-30 , b: "8E 73 63 90" },
- { f: +3e-30 , b: "0E 73 63 90" },
- { f: -4e+30 , b: "F2 49 F2 CA" },
- { f: +4e+30 , b: "72 49 F2 CA" },
- { f: -123456789.0 , b: "CC EB 79 A3" },
- { f: +123456789.0 , b: "4C EB 79 A3" },
- { f: -0.987654321 , b: "BF 7C D6 EA" },
- { f: +0.987654321 , b: "3F 7C D6 EA" },
- { f: -Infinity , b: "FF 80 00 00" },
- { f: +Infinity , b: "7F 80 00 00" }
- // { f: -NaN , b: "FF C0 00 00>" },
- // { f: +NaN , b: "7F C0 00 00" }
- ];
- f_vals.map( function(x) {
- // check encode
- var m1 = new Float();
- var b1 = new ByteBuffer();
- m1.f = x.f;
- m1.encode(b1);
- var q1 = b1.slice(1,5).compact().reverse();
- test.strictEqual('<' + x.b + '>', q1.toString("debug"));
- // check decode
- var b2 = new ByteBuffer();
- var s1 = x.b + ' 0D';
- var s2 = s1.split(" ");
- var s3 = s2.reverse();
- var i1 = s3.map(function(y) { return parseInt(y,16) } );
- i1.map(function(y) { b2.writeUint8(y) });
- b2.limit = b2.offset;
- b2.offset = 0;
- var m2 = Float.decode(b2);
- var s4 = "" + x.f +" " + m2.f;
- if ( isNaN(x.f) ) {
- test.ok( isNaN(m2.f), s4 );
- }
- else if ( ! isFinite( x.f) ) {
- test.ok( x.f === m2.f, s4 );
- }
- else {
- test.ok( in_tolerance(x.f, m2.f), s4 );
- }
- });
- } catch(e) {
- fail(e);
- }
- test.done();
- },
- "bytes": function(test) {
- try {
- var str_proto = "message Test { required bytes b = 1; }";
- var builder = ProtoBuf.loadProto(str_proto);
- var Test = builder.build("Test");
- var bb = new ByteBuffer(4).writeUint32(0x12345678).flip();
- var myTest = new Test(bb);
- test.strictEqual(myTest.b.array, bb.array);
- var bb2 = new ByteBuffer(6);
- var size = myTest.calculate();
- myTest.encode(bb2);
- test.strictEqual(bb2.offset, size);
- test.equal(bb2.flip().toString("debug"), "<0A 04 12 34 56 78>");
- myTest = Test.decode(bb2);
- test.equal(myTest.b.BE().readUint32(), 0x12345678);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "bytesFromFile": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message Image { required bytes data = 1; }"),
- Image = builder.build("Image"),
- data = fs.readFileSync(__dirname+"/../protobuf.png"),
- image = new Image({ data: data }),
- bb = image.encode(),
- imageDec = Image.decode(bb),
- dataDec = imageDec.data.toBuffer();
- test.strictEqual(data.length, dataDec.length);
- test.deepEqual(data, dataDec);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "notEnoughBytes": function(test) {
- var builder = ProtoBuf.loadProto("message Test { required bytes b = 1; }");
- var Test = builder.build("Test");
- var bb = new ByteBuffer().writeUint32(0x12345678).flip();
- var encoded = new ByteBuffer(6);
- new Test(bb).encode(encoded);
- test.equal(encoded.flip().toString("debug"), "<0A 04 12 34 56 78>");
- encoded = encoded.slice(0, 5); // chop off the last byte
- var err = null;
- try {
- Test.decode(encoded);
- } catch (caught) {
- err = caught;
- }
- test.ok(err && err.message && err.message.indexOf(": 4 required but got only 3") >= 0);
- test.done();
- },
- "bool": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message Test { optional bool ok = 1 [ default = false ]; }"),
- Test = builder.build("Test"),
- t = new Test();
- test.strictEqual(t.ok, null); // Not set as it is optional
- t.setOk(true);
- test.strictEqual(t.ok, true);
- test.strictEqual(Test.decode(t.encode()).ok, true);
- t.setOk(false);
- test.strictEqual(t.ok, false);
- t.setOk(null); // Not set
- test.strictEqual(Test.decode(t.encode()).ok, false); // = default when missing
- } catch (err) {
- fail(err);
- }
- test.done();
- },
- // As mentioned by Bill Katz
- "T139": function(test) {
- try{
- var builder = ProtoBuf.loadProtoFile(__dirname+"/T139.proto");
- var T139 = builder.build("T139");
- test.ok(typeof T139 == 'function');
- var inst = new T139(139,139);
- test.equal(inst.a, 139);
- test.equal(inst.b, 139);
- inst.setA(139);
- inst.setB(139);
- test.equal(inst.a, 139);
- test.equal(inst.b, 139);
- var bb = new ByteBuffer(3);
- inst.encode(bb);
- test.equal(bb.flip().toString("debug"), "<08 8B 01 10 8B 01>");
- var instDec = T139.decode(bb);
- test.equal(instDec.a, 139);
- test.equal(instDec.b, 139);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "emptyDefaultString": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message Test1 { required string test = 1 [default = \"\"]; }");
- var Test1;
- test.doesNotThrow(function() {
- Test1 = builder.build("Test1");
- });
- var test1 = new Test1();
- test.strictEqual(test1.test, "");
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "trailingSemicolon": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message Test1 { optional string test = 1; };");
- test.doesNotThrow(function() {
- var Test1 = builder.build("Test1");
- });
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "inner": {
- "longstr": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message Test { required Inner a = 1; message Inner { required string b = 1; } }");
- var Test = builder.build("Test");
- var t = new Test();
- var data = "0123456789"; // 10: 20, 40, 80, 160, 320 bytes
- for (var i=0; i<5; i++) data += data;
- test.equal(data.length, 320);
- t.a = new Test.Inner(data);
- var bb = t.encode();
- var t2 = Test.decode(bb);
- test.equal(t2.a.b.length, 320);
- test.equal(data, t2.a.b);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "multiple": function(test) {
- try {
- var str = "";
- for (var i=0; i<200; i++) str += 'a';
- var builder = ProtoBuf.loadProtoFile(__dirname+"/inner.proto");
- var fooCls = builder.build("Foo");
- var barCls = builder.build("Bar");
- var bazCls = builder.build("Baz");
- var foo = new fooCls(new barCls(str), new bazCls(str));
- var fooEncoded = foo.encode();
- test.doesNotThrow(function() {
- fooCls.decode(fooEncoded);
- });
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "float": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message Foo { required Bar bar = 1; } message Bar { required float baz = 1; }");
- var root = builder.build();
- var foo = new root.Foo(new root.Bar(4));
- var bb = foo.encode();
- var foo2 = root.Foo.decode(bb);
- test.equal(foo.bar.baz, 4);
- test.equal(foo2.bar.baz, foo.bar.baz);
- } catch (e) {
- fail(e);
- }
- test.done();
- }
- },
- "truncated": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message Test { required int32 a = 1; required int32 b = 2; }");
- var Test = builder.build("Test");
- var t = new Test(), bb = new ByteBuffer(2);
- t.setA(1);
- try {
- bb = t.encode(bb).flip();
- test.ok(false);
- } catch (e) {
- test.ok(e.encoded);
- bb = e.encoded.flip();
- test.equal(bb.toString("debug"), "<08 01>");
- }
- var t2;
- try /* to decode truncated message */ {
- t2 = Test.decode(bb);
- test.ok(false); // ^ throws
- } catch (e) {
- // But still be able to access the rest
- var t3 = e.decoded;
- test.strictEqual(t3.a, 1);
- test.strictEqual(t3.b, null);
- }
- test.strictEqual(t2, undefined);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // Options on all levels
- "options": {
- "parse": function(test) {
- try {
- var parser = new ProtoBuf.DotProto.Parser(ProtoBuf.Util.fetch(__dirname+"/options.proto"));
- var root = parser.parse();
- test.equal(root["package"], "My");
- test.strictEqual(root["options"]["(toplevel_1)"], 10);
- test.equal(root["options"]["(toplevel_2)"], "Hello world!");
- var opt = root["messages"][0]["fields"][0]["options"];
- test.equal(opt["default"], "Max");
- opt = root["messages"][0]["options"];
- test.strictEqual(opt["(inmessage)"], "My.Test");
- test.strictEqual(opt["(foo.my_option).bar"], false);
- opt = root["messages"][0]["fields"][1]["options"];
- test.strictEqual(opt["default"], "Shouldn't mix quotes");
- opt = root["messages"][0]["fields"][2]["options"];
- test.strictEqual(opt["default"], 'Shouldn"t mix quotes');
- opt = root["messages"][0]["fields"][3]["options"];
- test.strictEqual(opt["(foo_options).opt1"], 123);
- test.strictEqual(opt["(foo_options).opt2"], "baz");
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "export": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/options.proto");
- var My = builder.build("My");
- test.deepEqual(My.$options, {
- "(toplevel_1)": 10,
- "(toplevel_2)": "Hello world!"
- });
- test.strictEqual(My.$options['(toplevel_1)'], 10);
- test.deepEqual(My.Test.$options, {
- "(inmessage)": "My.Test",
- "(foo.my_option).bar": false
- });
- } catch (e) {
- fail(e);
- }
- test.done();
- }
- },
- // Comments
- "comments": function(test) {
- try {
- var tn = new ProtoBuf.DotProto.Tokenizer(ProtoBuf.Util.fetch(__dirname+'/comments.proto'));
- var token, tokens = [];
- do {
- token = tn.next();
- tokens.push(token);
- } while (token !== null);
- test.deepEqual(tokens, ['message', 'TestC', '{', 'required', 'int32', 'a', '=', '1', ';', '}', null]);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // A more or less complex proto with type references
- "complexProto": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/complex.proto");
- validateComplex(test, builder.build("Game"));
- var TCars = builder.lookup("Game.Cars");
- test.strictEqual(TCars.fqn(), ".Game.Cars");
- } catch(e) {
- fail(e);
- }
- test.done();
- },
- // The same created without calling upon the parser to do so
- "complexJSON": function(test) {
- try {
- var builder = ProtoBuf.loadJsonFile(__dirname+"/complex.json");
- validateComplex(test, builder.build("Game"));
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // Test error messages
- "errorMessage": function(test) {
- test.throws(function() {
- var builder = ProtoBuf.loadJsonFile(__dirname+"/complex.json");
- var Game = builder.build("Game");
- var car = new Game.Cars.Car();
- car.speed = "hello";
- car.encode();
- }, /Illegal value for speed/);
- test.done();
- },
- // Builder reused to add definitions from multiple sources
- "multiBuilder": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/example1.proto");
- ProtoBuf.loadProtoFile(__dirname+"/example2.proto", builder);
- var ns = builder.build();
- test.ok(!!ns.Test1);
- test.ok(!!ns.Test2);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // Inner messages test
- "inner": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/repeated.proto");
- var root = builder.build(),
- Outer = root.Outer,
- Inner = root.Inner;
- // Empty
- var outer = new Outer();
- var bb = new ByteBuffer(1).fill(0).flip();
- outer.encode(bb);
- test.equal(bb.flip().toString("debug"), "|00");
- var douter = Outer.decode(bb);
- test.ok(douter.inner instanceof Array);
- test.equal(douter.inner.length, 0);
- // Multiple
- outer = new Outer({ inner: [new Inner(1), new Inner(2)] });
- bb = new ByteBuffer(8);
- var size = outer.calculate();
- outer.encode(bb);
- test.strictEqual(bb.offset, size);
- test.equal(bb.flip().toString("debug"), "<0A 02 08 01 0A 02 08 02>");
- douter = Outer.decode(bb);
- test.ok(douter.inner instanceof Array);
- test.equal(douter.inner.length, 2);
- test.equal(douter.inner[0].inner_value, 1);
- test.equal(douter.inner[1].inner_value, 2);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // Packed vs. not packed repeated fields test
- "packed": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/packed.proto");
- var Message = builder.build("Message");
- // Both empty
- var message = new Message();
- var bb = new ByteBuffer(1).fill(0).flip();
- var size = message.calculate();
- message.encode(bb);
- test.strictEqual(bb.offset, size);
- test.equal(bb.flip().toString("debug"), "|00");
- message = Message.decode(bb);
- test.ok(message.a instanceof Array);
- test.equal(message.a.length, 0);
- test.ok(message.b instanceof Array);
- test.equal(message.b.length, 0);
- // Both non-empty
- message = new Message([1,2,3], [1,2,3]);
- size = message.calculate();
- message.encode(bb.resize(11));
- test.strictEqual(bb.offset, size);
- test.equal(bb.flip().toString("debug"), "<0A 03 01 02 03 10 01 10 02 10 03>");
- message = Message.decode(bb);
- test.ok(message.a instanceof Array);
- test.equal(message.a.length, 3);
- test.deepEqual(message.a, [1,2,3]);
- test.ok(message.b instanceof Array);
- test.equal(message.b.length, 3);
- test.deepEqual(message.b, [1,2,3]);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // Legacy groups test
- "groups": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/groups.proto");
- var root = builder.build();
- var Outer = root.Outer;
- var TOuter = builder.ns.getChild("Outer");
- var TInner = TOuter.getChild("MyInner");
- test.ok(TInner instanceof ProtoBuf.Reflect.Message);
- test.strictEqual(TInner.isGroup, true);
- var Tinner = TOuter.getChild("myinner");
- test.ok(Tinner instanceof ProtoBuf.Reflect.Message.Field);
- test.strictEqual(Tinner.id, 2);
- test.deepEqual(Tinner.options, { "deprecated": true });
- var Inner = root.Outer.MyInner;
- var outer = new Outer("a", [new Inner("hello")], "b", new Inner("world"));
- var bb = new ByteBuffer();
- var size = outer.calculate();
- outer.encode(bb);
- test.strictEqual(bb.offset, size);
- bb.flip().compact();
- var wiredMsg = [
- "0A", // 1|010 = id 1, wire type 2 (ldelim)
- "01", // length 1
- "61", // "a"
- "13", // 10|011 = id 2, wire type 3 (start group)
- "1A", // 11|010 = id 3, wire type 2 (ldelim)
- "05", // length 5
- "68 65 6C 6C 6F", // "hello"
- "14", // 10|100 = id 2, wire type 4 (end group)
- "22", // 100|010 = id 4, wire type 2 (ldelim)
- "01", // length 1
- "62", // "b"
- "2B", // 101|011 = id 5, wire type = 3 (start group)
- "1A", // 11|010 = id 3, wire type = 2 (ldelim)
- "05", // length 5
- "77 6F 72 6C 64", // "world"
- "2C" // 101|100 = id 5, wire type = 4 (end group)
- ];
- test.equal(bb.toString("debug"), "<" +wiredMsg.join(" ") + ">");
- var douter = Outer.decode(bb);
- test.strictEqual(douter.before, "a");
- test.strictEqual(douter.myinner.length, 1);
- test.strictEqual(douter.myinner[0].a, "hello");
- test.strictEqual(douter.after, "b");
- bb.offset = 0;
- douter = root.OuterSparse.decode(bb);
- test.strictEqual(bb.offset, bb.limit);
- test.strictEqual(douter.before, "a");
- test.strictEqual(douter.after, "b");
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "x64Fixed": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/x64.proto");
- var Test = builder.build("Test");
- var myTest = new Test();
- test.ok(myTest.val instanceof ByteBuffer.Long);
- test.equal(myTest.val.unsigned, false);
- test.equal(myTest.val.toNumber(), -1);
- test.ok(myTest.uval instanceof ByteBuffer.Long);
- test.equal(myTest.uval.unsigned, true);
- test.equal(myTest.uval.toNumber(), 1);
- myTest.setVal(-2);
- myTest.setUval(2);
- var bb = new ByteBuffer(18); // 2x tag + 2x 64bit
- var size = myTest.calculate();
- myTest.encode(bb);
- test.strictEqual(bb.offset, size);
- test.equal(bb.flip().toString("debug"), "<09 FE FF FF FF FF FF FF FF 11 02 00 00 00 00 00 00 00>");
- // ^ wireType=1, id=1 ^ wireType=1, id=2
- myTest = Test.decode(bb);
- test.ok(myTest.val instanceof ByteBuffer.Long);
- test.equal(myTest.val.unsigned, false);
- test.equal(myTest.val.toNumber(), -2);
- test.ok(myTest.uval instanceof ByteBuffer.Long);
- test.equal(myTest.uval.unsigned, true);
- test.equal(myTest.uval.toNumber(), 2);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "x64Varint": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/x64.proto");
- var Test = builder.build("Test2");
- var Test = builder.build("Test2");
- var myTest = new Test();
- test.ok(myTest.val instanceof ByteBuffer.Long);
- test.equal(myTest.val.unsigned, false);
- test.equal(myTest.val.toNumber(), -1);
- test.ok(myTest.uval instanceof ByteBuffer.Long);
- test.equal(myTest.uval.unsigned, true);
- test.equal(myTest.uval.toNumber(), 1);
- test.ok(myTest.sval instanceof ByteBuffer.Long);
- test.equal(myTest.sval.unsigned, false);
- test.equal(myTest.sval.toNumber(), -2);
- myTest.setVal(-2);
- myTest.setUval(2);
- myTest.setSval(-3);
- var bb = new ByteBuffer(3+10+2); // 3x tag + 1x varint 10byte + 2x varint 1byte
- var size = myTest.calculate();
- myTest.encode(bb);
- test.strictEqual(bb.offset, size);
- test.equal(bb.flip().toString("debug"), "<08 FE FF FF FF FF FF FF FF FF 01 10 02 18 05>");
- // 08: wireType=0, id=1, 18: wireType=0, id=2, ?: wireType=0, id=3
- myTest = Test.decode(bb);
- test.ok(myTest.val instanceof ByteBuffer.Long);
- test.equal(myTest.val.unsigned, false);
- test.equal(myTest.val.toNumber(), -2);
- test.ok(myTest.uval instanceof ByteBuffer.Long);
- test.equal(myTest.uval.unsigned, true);
- test.equal(myTest.uval.toNumber(), 2);
- test.ok(myTest.sval instanceof ByteBuffer.Long);
- test.equal(myTest.sval.unsigned, false);
- test.equal(myTest.sval.toNumber(), -3);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "keywords": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message Reserved { optional string get = 1; }");
- var My = builder.build();
- var myTest = new My.Reserved("a");
- test.doesNotThrow(function() {
- myTest.encode();
- });
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "imports": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/imports.proto");
- var root = builder.build();
- test.ok(!!root.Test1);
- test.ok(!!root.Test2);
- test.ok(!!root.My.Test3);
- test.notEqual(root.Test2, root.My.Test2);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "weakImports": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/imports-weak.proto");
- var root = builder.build();
- } catch (e) {
- test.ok(e.message.indexOf("unresolvable type reference") >= 0);
- test.done();
- return;
- }
- var e = new Error("Weak import was imported.");
- fail(e);
- },
- "importExtensions": function(test) {
- var x = "package x; \
- message Test { \
- extensions 1 to 10; \
- } \
- extend Test { \
- optional int32 first_val = 1; \
- }";
- var y = "package y; \
- extend x.Test { \
- optional int32 second_val = 2; \
- }";
- var builder = ProtoBuf.newBuilder();
- ProtoBuf.loadProto(x, builder);
- ProtoBuf.loadProto(y, builder);
- var Test = builder.build('x.Test');
- var inst = new Test();
- test.strictEqual(inst[".x.first_val"], null);
- test.strictEqual(inst[".y.second_val"], null);
- test.done();
- },
- "toplevel": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/toplevel.proto");
- var My = builder.build("My");
- test.ok(!!My.MyEnum);
- test.equal(My.MyEnum.ONE, 1);
- test.equal(My.MyEnum.TWO, 2);
- test.ok(!!My.Test);
- var myTest = new My.Test();
- test.equal(myTest.num, My.MyEnum.ONE);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "importsToplevel": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/imports-toplevel.proto");
- var My = builder.build("My");
- test.ok(!!My.MyEnum);
- test.equal(My.MyEnum1.ONE, 1);
- test.equal(My.MyEnum1.TWO, 2);
- test.ok(!!My.Test1);
- var myTest = new My.Test1();
- test.equal(myTest.num, My.MyEnum.ONE);
- test.equal(myTest.num1, My.MyEnum1.ONE);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "importDuplicate": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/import_a.proto");
- test.doesNotThrow(function() {
- ProtoBuf.loadProtoFile(__dirname+"/import_b.proto", builder);
- });
- var root = builder.build();
- test.ok(root.A);
- test.ok(root.B);
- test.ok(root.Common);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "importDuplicateDifferentBuilder": function(test) {
- try {
- var builderA = ProtoBuf.loadProtoFile(__dirname+"/import_a.proto");
- var builderB;
- test.doesNotThrow(function() {
- builderB = ProtoBuf.loadProtoFile(__dirname+"/import_b.proto");
- });
- var rootA = builderA.build();
- var rootB = builderB.build();
- test.ok(rootA.A);
- test.ok(rootB.B);
- test.ok(rootA.Common);
- test.ok(rootB.Common);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "dupimport": function(test) {
- try {
- // Suppress logging result to stdout
- fixture.capture(function() { return false;});
- require(__dirname+"/../cli/pbjs.js").main(["node", "bin/pbjs", __dirname+"/dupimport/main.proto", "--quiet"]);
- fixture.release();
- } catch (e) {
- fixture.release();
- fail(e);
- }
- test.done();
- },
- "field_name_same_as_package": function(test) {
- try {
- fixture.capture(function() { return false;});
- require(__dirname+"/../cli/pbjs.js").main(["node", "bin/pbjs", __dirname+"/field_name_same_as_package/main.proto", "--quiet"]);
- fixture.release();
- } catch (e) {
- fixture.release();
- fail(e);
- }
- test.done();
- },
- "importRoot": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile({
- root: __dirname,
- file: "importRoot/file1.proto"
- });
- var Test = builder.build("Test");
- test.ok(new Test() instanceof ProtoBuf.Builder.Message);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "extend": function(test) {
- try {
- var ast = new ProtoBuf.DotProto.Parser(fs.readFileSync(__dirname+"/extend.proto")).parse();
- test.deepEqual(ast, { package: null,
- messages:
- [ { ref: 'google.protobuf.MessageOptions',
- fields:
- [ { rule: 'optional',
- type: 'int32',
- name: 'foo',
- options: {},
- id: 1001 } ] },
- { name: 'Foo',
- fields: [],
- enums: [],
- messages: [],
- options: {},
- services: [],
- oneofs: {},
- extensions: [ [ 2, 536870911 ] ] },
- { ref: 'Foo',
- fields:
- [ { rule: 'optional',
- type: 'string',
- name: 'bar',
- options: {},
- id: 2 } ] },
- { name: 'Bar',
- fields: [],
- enums: [],
- messages:
- [ { name: 'Foo',
- fields: [],
- enums: [],
- messages: [],
- options: {},
- services: [],
- oneofs: {} },
- { ref: '.Foo',
- fields: [ { rule: 'optional', type: 'Foo', name: 'foo', options: {}, id: 3 } ] } ],
- options: {},
- services: [],
- oneofs: {} } ],
- enums: [],
- imports: [ 'google/protobuf/descriptor.proto' ],
- options: {},
- services: [] }
- );
- var builder = ProtoBuf.loadProtoFile(__dirname+"/extend.proto");
- var TFoo = builder.lookup(".Foo"),
- TBar = builder.lookup(".Bar"),
- TBarFoo = builder.lookup(".Bar.Foo"),
- fields = TFoo.getChildren(ProtoBuf.Reflect.Message.Field);
- test.strictEqual(fields.length, 2);
- test.strictEqual(fields[0].name, ".bar");
- test.strictEqual(fields[0].id, 2);
- test.strictEqual(fields[1].name, ".Bar.foo");
- test.strictEqual(fields[1].id, 3);
- test.deepEqual(TFoo.extensions, [[2, ProtoBuf.ID_MAX]]); // explicitly defined
- test.strictEqual(TBar.extensions, undefined); // none defined
- test.deepEqual(TBar.getChild("foo"), { builder: builder, parent: TBar, name: "foo", field: TFoo.getChild('.Bar.foo') });
- test.strictEqual(TBar.getChildren(ProtoBuf.Reflect.Message.Field).length, 0);
- var root = builder.build();
- test.strictEqual(TFoo.getChild(".Bar.foo").resolvedType, TBarFoo); // .Bar.Foo, not .Foo
- var foo = new root.Foo(),
- bar = new root.Bar();
- foo['.bar'] = "123";
- foo['.Bar.foo'] = bar;
- test.equal(foo.encode().compact().toString("debug"), "<12 03 31 32 33 1A 00>");
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // Custom options on all levels
- // victorr (https://github.com/victorr)
- "customOptions": function(test) {
- try {
- var parser = new ProtoBuf.DotProto.Parser(ProtoBuf.Util.fetch(__dirname+"/custom-options.proto"));
- var root = parser.parse();
- test.equal(root["options"]["(my_file_option)"], "Hello world!");
- test.equal(root["messages"][7]["options"]["(my_message_option)"], 1234);
- test.equal(root["messages"][7]["fields"][0]["options"]["(my_field_option)"], 4.5);
- // test.equal(root["services"]["MyService"]["options"]["my_service_option"], "FOO");
- // TODO: add tests for my_enum_option, my_enum_value_option
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "oneofs": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/oneof.proto"),
- MyOneOf = builder.build("MyOneOf"),
- TOneOf = builder.lookup(".MyOneOf");
- test.ok(TOneOf.getChild("my_oneof"));
- var myOneOf = new MyOneOf();
- test.strictEqual(myOneOf.my_oneof, null);
- myOneOf.set("id", 1);
- test.strictEqual(myOneOf.my_oneof, "id");
- myOneOf.set("name", "me");
- test.strictEqual(myOneOf.my_oneof, "name");
- test.strictEqual(myOneOf.id, null);
- var bb = myOneOf.encode().compact();
- test.strictEqual(bb.toString("debug"), "<12 02 6D 65>"); // id 2, wt 2, len 2
- myOneOf = MyOneOf.decode(bb);
- test.strictEqual(myOneOf.my_oneof, "name");
- test.strictEqual(myOneOf.name, "me");
- test.strictEqual(myOneOf.id, null);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "services": function(test) {
- try {
- var parser = new ProtoBuf.DotProto.Parser(ProtoBuf.Util.fetch(__dirname+"/custom-options.proto"));
- var root = parser.parse();
- test.deepEqual(root["services"], [{
- "name": "MyService",
- "rpc": {
- "MyMethod": {
- "request": "RequestType",
- "response": "ResponseType",
- "request_stream": false,
- "response_stream": false,
- "options": {
- "(my_method_option).foo": 567,
- "(my_method_option).bar": "Some string"
- }
- }
- },
- "options": {
- "(my_service_option)": "FOO"
- }
- }]);
- var builder = ProtoBuf.loadProtoFile(__dirname+"/custom-options.proto");
- var root = builder.build(),
- MyService = root.MyService,
- RequestType = root.RequestType,
- ResponseType = root.ResponseType,
- called = false;
- test.deepEqual(MyService.$options, {
- "(my_service_option)": "FOO"
- });
- test.deepEqual(MyService.MyMethod.$options, {
- "(my_method_option).foo": 567,
- "(my_method_option).bar": "Some string"
- });
- // Provide the service with your actual RPC implementation based on whatever framework you like most.
- var myService = new MyService(function(method, req, callback) {
- test.strictEqual(method, ".MyService.MyMethod");
- test.ok(req instanceof RequestType);
- called = true;
- // In this case we just return no error and our pre-built response. This must be properly async!
- setTimeout(callback.bind(this, null, (new ResponseType()).encode() /* as raw bytes for debugging */ ));
- });
- test.deepEqual(myService.$options, MyService.$options);
- test.deepEqual(myService.MyMethod.$options, MyService.MyMethod.$options);
- // Call the service with your request message and provide a callback. This will call your actual service
- // implementation to perform the request and gather a response before calling the callback. If the
- // request or response type is invalid i.e. not an instance of RequestType or ResponseType, your
- // implementation will not be called as ProtoBuf.js handles this case internally and directly hands the
- // error to your callback below.
- myService.MyMethod(new RequestType(), function(err, res) {
- // We get: err = null, res = our prebuilt response. And that's it.
- if (err !== null) {
- fail(err);
- }
- test.strictEqual(called, true);
- test.ok(res instanceof ResponseType);
- test.done();
- });
- myService.MyMethod(new RequestType().encode(), function(err, res) {
- // We get: err = null, res = our prebuilt response. And that's it.
- if (err !== null) {
- fail(err);
- }
- test.strictEqual(called, true);
- test.ok(res instanceof ResponseType);
- test.done();
- });
- } catch (e) {
- fail(e);
- }
- },
- // Properly ignore "syntax" and "extensions" keywords
- // The corresponding .proto file has been removed upon request
- /* "gtfs-realtime": function(test) {
- try {
- test.doesNotThrow(function() {
- ProtoBuf.loadProtoFile(__dirname+"/gtfs-realtime.proto");
- });
- } catch (e) {
- fail(e);
- }
- test.done();
- }, */
- "delimited": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message Position { required int32 x = 1; required int32 y = 2; }");
- var Position = builder.build("Position");
- var bb = new ByteBuffer();
- for (var i=0; i<2; i++) {
- var position = new Position(10,10);
- position.encodeDelimited(bb);
- }
- bb.flip();
- for (i=0; i<2; i++) {
- position = Position.decodeDelimited(bb);
- test.strictEqual(position.x, 10);
- test.strictEqual(position.y, 10);
- }
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "stringify": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message Position { required int32 x = 1; required int64 y = 2; }");
- var Position = builder.build("Position");
- var position = new Position(1, ProtoBuf.Long.fromNumber(2));
- var json = JSON.stringify(position);
- test.strictEqual(json, '{"x":1,"y":{"low":2,"high":0,"unsigned":false}}');
- position = new Position(JSON.parse(json));
- test.strictEqual(position.x, 1);
- test.ok(position.y instanceof ProtoBuf.Long);
- test.deepEqual(position.y, {"low":2,"high":0,"unsigned":false});
- // Also test if this encodes and decodes properly
- position = Position.decode(position.encode());
- test.ok(position.y instanceof ProtoBuf.Long);
- test.deepEqual(position.y, {"low": 2, "high": 0, "unsigned": false });
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "fields": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/optional.proto");
- var Test1 = builder.build("Test1");
- var test1 = new Test1();
- test.strictEqual(test1.a, null);
- test.deepEqual(Object.keys(test1), ['a','b']);
- var bb = test1.encode();
- test1 = Test1.decode(bb);
- test.strictEqual(test1.a, null);
- test.deepEqual(Object.keys(test1), ['a','b']);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "fieldsToCamelCase": function(test) {
- try {
- ProtoBuf.convertFieldsToCamelCase = true;
- var builder = ProtoBuf.loadProtoFile(__dirname+"/camelcase.proto");
- var Test = builder.build("Test"),
- TTest = builder.lookup("Test");
- var msg = new Test();
- // Reverted collision on 1st
- test.strictEqual(msg.some_field, null);
- test.strictEqual(msg.someField, null);
- test.equal(TTest.getChild("some_field").id, 1);
- test.equal(TTest.getChild("someField").id, 2);
- // Reverted collision on 2nd
- test.strictEqual(msg.aField, null);
- test.strictEqual(msg.a_field, null);
- test.equal(TTest.getChild("aField").id, 3);
- test.equal(TTest.getChild("a_field").id, 4);
- // No collision
- test.strictEqual(msg.itsAField, null);
- test.equal(TTest.getChild("itsAField").id, 5);
- test.ok(typeof msg.set_its_a_field === "function");
- test.ok(typeof msg.setItsAField === "function");
- ProtoBuf.convertFieldsToCamelCase = false;
- } catch (e) {
- ProtoBuf.convertFieldsToCamelCase = false;
- fail(e);
- }
- test.done();
- },
- "setarray": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/setarray.proto");
- var root = builder.build(),
- Outer = root.Outer,
- Inner = root.Inner,
- inners = [];
- // Array of repeated messages
- inners.push(new Inner("a"), new Inner("b"), new Inner("c"));
- var outer = new Outer();
- outer.setInners(inners);
- test.deepEqual(outer.inners, inners);
- // Array of repeated message objects
- inners = [];
- inners.push({ str: 'a' }, { str: 'b' }, { str: 'c' });
- outer.setInners(inners); // Converts
- test.ok(outer.inners[0] instanceof Inner);
- test.deepEqual(outer.inners, inners);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // Make sure that our example at https://github.com/dcodeIO/ProtoBuf.js/wiki is not nonsense
- "pingexample": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/PingExample.proto");
- var Message = builder.build("Message");
- var msg = new Message();
- msg.ping = new Message.Ping(123456789);
- var bb = msg.encode();
- test.strictEqual(bb.limit, 7);
- msg = Message.decode(bb);
- test.ok(msg.ping);
- test.notOk(msg.pong);
- test.strictEqual(msg.ping.time, 123456789);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "negInt32": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message Test { required int32 value = 2; }");
- var Test = builder.build("Test");
- var t = new Test(-1);
- var size = t.calculate();
- var bb = t.encode(); // flips
- test.strictEqual(bb.remaining(), size);
- test.strictEqual(bb.toBase64(), "EP///////////wE=");
- t = Test.decode(bb);
- test.strictEqual(t.value, -1);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "negEnumId": function(test) {
- try {
- test.doesNotThrow(function() {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/negid.proto");
- var Test = builder.build("Test");
- test.strictEqual(Test.LobbyType.INVALID, -1);
- var t = new Test(Test.LobbyType.INVALID);
- test.strictEqual(t.type, -1);
- var size = t.calculate();
- var bb = t.encode(); // flips
- test.strictEqual(bb.remaining(), size);
- t = Test.decode(bb);
- test.strictEqual(t.type, -1);
- });
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "base64": function(test) {
- try {
- var Message = ProtoBuf.loadProto("message Message { required string s = 1; }").build("Message");
- var msg = new Message("ProtoBuf.js");
- var b64 = msg.toBase64();
- test.strictEqual(b64, "CgtQcm90b0J1Zi5qcw==");
- var msg2 = Message.decode64(b64);
- test.deepEqual(msg, msg2);
- msg2 = Message.decode(b64, "base64");
- test.deepEqual(msg, msg2);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "hex": function(test) {
- try {
- var Message = ProtoBuf.loadProto("message Message { required string s = 1; }").build("Message");
- var msg = new Message("ProtoBuf.js");
- var hex = msg.toHex();
- test.strictEqual(hex, "0a0b50726f746f4275662e6a73");
- var msg2 = Message.decodeHex(hex);
- test.deepEqual(msg, msg2);
- msg2 = Message.decode(hex, "hex");
- test.deepEqual(msg, msg2);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "forwardComp": function(test) {
- try {
- var Message = ProtoBuf.loadProto("message Message { required int32 a = 1; required string b = 2; required float c = 3; }").build("Message");
- var msg = new Message(123, "abc", 0.123);
- var bb = msg.encode();
- Message = ProtoBuf.loadProto("message Message {}").build("Message");
- test.doesNotThrow(function() {
- Message.decode(bb);
- });
- test.strictEqual(bb.offset, bb.limit);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "tokenizerLine": function(test) {
- try {
- var parser = new ProtoBuf.DotProto.Parser("package test;\n\nmessage Message {\n\trequired string invalid = 1;}ERROR\n"),
- ast = null, err = null;
- try {
- ast = parser.parse();
- } catch (caught) {
- err = caught;
- }
- test.ok(err);
- test.notOk(ast);
- test.ok(err.message.indexOf("line 4:") >= 0);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "excludeFields": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message A { required int32 i = 1; } message B { required A A = 1; }");
- builder.build();
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "proto2jsExtend": function(test) {
- try {
- var builder = ProtoBuf.loadJsonFile(__dirname+"/proto2js/Bar.json");
- builder.build();
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "emptyMessage": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message EmptyMessage {}"),
- EmptyMessage = builder.build("EmptyMessage");
- var msg = new EmptyMessage(),
- ab = msg.toArrayBuffer();
- test.strictEqual(ab.byteLength, 0);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "toRaw": function(test) {
- try {
- var builder = ProtoBuf.loadProto("message MyMessage { required int32 a = 1; required int32 b = 2; required bytes c = 3; }"),
- MyMessage = builder.build("MyMessage");
- var raw = { a: 1, b: 2, c: "YWJj" },
- myMessage = new MyMessage(raw);
- test.deepEqual(myMessage.c.toBase64(), raw.c);
- test.deepEqual(myMessage.toRaw(true), raw);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "singleQuotedString": function(test) {
- try{
- var builder = ProtoBuf.loadProtoFile(__dirname+"/string_single_quote.proto");
- var TestSingleQuoteString = builder.build("TestSingleQuoteString");
- test.ok(typeof TestSingleQuoteString == 'function');
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "importDuplicateSingleQuote": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/import_a_single_quote.proto");
- test.doesNotThrow(function() {
- ProtoBuf.loadProtoFile(__dirname+"/import_b.proto", builder);
- });
- var root = builder.build();
- test.ok(root.A);
- test.ok(root.B);
- test.ok(root.Common);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "importStringSuccessively": function(test) {
- try {
- var proto1 = "message A { required string a = 1; };";
- var proto2 = "import \"proto1.proto\"; message B { required A a = 1; };";
- var builder = ProtoBuf.loadProto(proto1, "proto1.proto");
- ProtoBuf.loadProto(proto2, builder, "proto2.proto");
- var root = builder.build();
- test.ok(root.A);
- test.ok(root.B);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "multilineString": function(test) {
- try {
- var proto = "message TestMessage { required string test = 1 [default = \"1\" \"2\"\n\"3\"];}";
- var builder = ProtoBuf.loadProto(proto, "multilineString.proto");
- var TestMessage = builder.build("TestMessage"),
- testMessage = new TestMessage();
- test.strictEqual(testMessage.test, "123");
- test.done();
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "packable": function(test) {
- try {
- var proto = 'message Inner { required int32 id=2; }\nmessage Outer { repeated Inner inner = 1 [packed=true]; }';
- var builder = ProtoBuf.loadProto(proto);
- var root = builder.build();
- var inner = new root.Inner(1),
- outer = new root.Outer(inner);
- var bb = outer.encode().compact();
- test.strictEqual(bb.toDebug(), "<0A 02 10 01>");
- // 0A: wt 2, id 1
- // 02: len 2
- // 10: wt 0, id 2
- // 01: 1
- var outer2 = root.Outer.decode(bb);
- test.strictEqual(outer2.inner.id, 1);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "$type": function(test) {
- var builder = ProtoBuf.loadProto("message Test {}");
- var Test = builder.build("Test"),
- TTest = builder.lookup("Test");
- test.strictEqual(new Test().$type, TTest);
- test.done();
- },
- "descriptor": function(test) {
- try {
- var proto = 'import "./google/protobuf/descriptor.proto";';
- var builder = ProtoBuf.loadProto(proto, "tests/proto.proto");
- var root = builder.build("google.protobuf");
- test.ok(root.FileDescriptorSet);
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "mismatchedNesting": function(test) {
- try {
- var proto = "message Child { optional uint32 foo = 1; } message FakeChild { optional uint32 foo = 1; } message Parent { optional Child child = 1; }";
- var builder = ProtoBuf.loadProto(proto, "tests/mismatchedNesting.proto");
- var root = builder.build();
- var foo = new root.Parent({ child: new root.FakeChild({ foo: 1 })});
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- /* "mismatchedType": function(test) {
- try {
- var proto = "message Test1 { optional string foo = 1; }";
- proto += "message Test2 { optional int32 foo = 1; }";
- var builder = ProtoBuf.loadProto(proto, "tests/mistmatchedType.proto");
- var root = builder.build();
- var test1 = new root.Test1({ foo: 'bar' });
- var test2 = root.Test2.decode(test1.encode());
- } catch (e) {
- fail(e);
- }
- test.done();
- }, */
- "builderOptions": function(test) {
- try {
- var proto = "message Foo { optional uint32 foo_bar = 1; }";
- var builder = ProtoBuf.newBuilder({
- convertFieldsToCamelCase: true
- });
- ProtoBuf.loadProto(proto, builder, "tests/builderOptions.proto");
- var Foo = builder.build("Foo");
- test.strictEqual(ProtoBuf.convertFieldsToCamelCase, false);
- test.strictEqual(builder.options.convertFieldsToCamelCase, true);
- var foo = new Foo();
- test.ok(typeof foo.fooBar !== 'undefined');
- test.ok(typeof foo.foo_bar === 'undefined');
- test.done();
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- "proto3": function(test) {
- try {
- var builder = ProtoBuf.loadProtoFile(__dirname+"/proto3.proto");
- test.doesNotThrow(function() {
- ProtoBuf.loadProtoFile(__dirname+"/proto3.proto", builder);
- });
- var root = builder.build();
- test.ok(root.test.Foo.$type.syntax === 'proto3');
- } catch (e) {
- fail(e);
- }
- test.done();
- },
- // FIXME: This test relied on some bloated builder functionality that has been removed.
- // Is it even mandatory to strictly disallow proto2/3 mixing, even if that would be illegal in the official
- // implementation?
- /* "proto3DisallowedFeatures": function(test) {
- try {
- // Required field
- var proto = "syntax = \"proto3\"; message Foo { required int32 field = 1; }";
- var builder = ProtoBuf.newBuilder();
- ProtoBuf.loadProto(proto, builder, "tests/proto3DisallowedFeatures.proto");
- test.ok(false); // ^ should throw
- } catch (e) {
- test.ok(/^Not a valid definition/.test(e.message));
- }
- try {
- // Field with default value
- var proto = "syntax = \"proto3\"; message Foo { int32 field = 1 [default=42]; }";
- var builder = ProtoBuf.newBuilder();
- ProtoBuf.loadProto(proto, builder, "tests/proto3DisallowedFeatures.proto");
- test.ok(false); // ^ should throw
- } catch (e) {
- test.ok(/^Not a valid definition/.test(e.message));
- }
- try {
- // Message with extension range
- var proto = "syntax = \"proto3\"; message Foo { extensions 100 to max; } ";
- var builder = ProtoBuf.newBuilder();
- ProtoBuf.loadProto(proto, builder, "tests/proto3DisallowedFeatures.proto");
- test.ok(false); // ^ should throw
- } catch (e) {
- test.ok(/^Not a valid definition/.test(e.message));
- }
- try {
- // Message with extension
- var proto = "syntax = \"proto3\"; message Foo { extensions 100 to max; } " +
- "message Bar { extend Foo { optional Bar bar = 100; } }";
- var builder = ProtoBuf.newBuilder();
- ProtoBuf.loadProto(proto, builder, "tests/proto3DisallowedFeatures.proto");
- test.ok(false); // ^ should throw
- } catch (e) {
- test.ok(/^Not a valid definition/.test(e.message));
- }
- try {
- // Enum with non-zero first entry.
- var proto = "syntax = \"proto3\"; enum E { A = 1; B = 2; }";
- var builder = ProtoBuf.newBuilder();
- ProtoBuf.loadProto(proto, builder, "tests/proto3DisallowedFeatures.proto");
- test.ok(false); // ^ should throw
- } catch (e) {
- test.ok(/^Not a valid definition/.test(e.message));
- }
- try {
- // Proto3 message referring to proto2 enum.
- var proto2 = "syntax = \"proto2\"; enum E { A = 1; B = 2; }";
- var proto3 = "syntax = \"proto3\"; message Test { E enum_field = 1; }";
- var builder = ProtoBuf.newBuilder();
- ProtoBuf.loadProto(proto2, builder, "tests/proto3DisallowedFeatures1.proto");
- ProtoBuf.loadProto(proto3, builder, "tests/proto3DisallowedFeatures3.proto");
- test.ok(false); // ^ should throw
- } catch (e) {
- test.ok(/^Proto3 message refers to proto2 enum/.test(e.message));
- }
- test.done();
- }, */
- "proto3FieldPresence": function(test) {
- var proto =
- "syntax = \"proto3\";\n" +
- "message Test {\n" +
- " int32 field_int32 = 1;\n" +
- " int64 field_int64 = 2;\n" +
- " string field_str = 3;\n" +
- " bytes field_bytes = 4;\n" +
- " Test field_msg = 5;\n" +
- " Enum field_enum = 6;\n" +
- " repeated int32 rpt_int32 = 11;\n" +
- " repeated int64 rpt_int64 = 12;\n" +
- " repeated string rpt_str = 13;\n" +
- " repeated bytes rpt_bytes = 14;\n" +
- " repeated Test rpt_msg = 15;\n" +
- " repeated Enum rpt_enum = 16;\n" +
- " oneof oneof_type { bool oneof_bool = 17; };\n" +
- "}\n" +
- "enum Enum { Default = 0; A = 1; B = 2; }\n";
- var builder = ProtoBuf.newBuilder();
- ProtoBuf.loadProto(proto, builder, "test/proto3FieldPresence.proto");
- var Test = builder.build('Test'),
- Enum = builder.build('Enum');
- var testMsg = new Test();
- test.strictEqual(testMsg.field_int32, 0);
- test.strictEqual(testMsg.field_int64.low, 0);
- test.strictEqual(testMsg.field_int64.high, 0);
- test.strictEqual(testMsg.field_str, "");
- test.strictEqual(testMsg.field_msg, null);
- test.ok(testMsg.field_bytes instanceof ByteBuffer);
- test.strictEqual(testMsg.field_bytes.remaining(), 0);
- test.strictEqual(testMsg.rpt_int32.length, 0);
- test.strictEqual(testMsg.oneof_type, null);
- test.strictEqual(testMsg.oneof_bool, false);
- // No fields should go on the wire, even though they're set
- var encoded = testMsg.encode();
- test.strictEqual(encoded.remaining(), 0);
- testMsg.field_int32 = 42;
- encoded = testMsg.encode();
- test.strictEqual(encoded.remaining(), 2);
- testMsg.field_int32 = 0;
- encoded = testMsg.encode();
- test.strictEqual(encoded.remaining(), 0);
- // Enum fields should be able to carry arbitrary values.
- testMsg.field_enum = 42;
- test.strictEqual(testMsg.field_enum, 42);
- encoded = testMsg.encode();
- testMsg = Test.decode(encoded);
- test.strictEqual(testMsg.field_enum, 42);
- // Explicitly set fields that are part of an oneof should
- // be encoded even if set to their default value
- testMsg = new Test();
- testMsg.set("oneof_bool", false);
- test.strictEqual(testMsg.oneof_type, "oneof_bool");
- encoded = testMsg.encode().compact();
- test.strictEqual(encoded.toString("debug"), "<88 01 00>"); // 17|varint (0term) + varint 0
- var decoded = Test.decode(encoded);
- test.strictEqual(decoded.oneof_type, "oneof_bool");
- test.strictEqual(decoded.oneof_bool, false);
- test.done();
- },
- "mapContainer": function(test) {
- var proto =
- "message Test {\n" +
- " map<string, int32> map_string_int32 = 1;\n" +
- " map<string, int64> map_string_int64 = 2;\n" +
- " map<string, string> map_string_string = 3;\n" +
- " map<string, Test> map_string_msg = 4;\n" +
- " map<string, Enum> map_string_enum = 5;\n" +
- " map<int32, string> map_int32_string = 6;\n" +
- " map<int64, string> map_int64_string = 7;\n" +
- " map<bool, string> map_bool_string = 9;\n" +
- "}\n" +
- "enum Enum { Default = 0; A = 1; B = 2; }\n";
- var builder = ProtoBuf.newBuilder();
- ProtoBuf.loadProto(proto, builder, "test/mapContainer.proto");
- var map_string_int32 =
- new ProtoBuf.Map(builder.lookup("Test.map_string_int32"));
- test.strictEqual(map_string_int32.size, 0);
- test.strictEqual(map_string_int32.has("asdf"), false);
- test.strictEqual(map_string_int32.get("asdf"), undefined);
- map_string_int32.set("asdf", 42);
- test.strictEqual(map_string_int32.has("asdf"), true);
- test.strictEqual(map_string_int32.get("asdf"), 42);
- var it = map_string_int32.keys();
- var itVal = it.next();
- test.strictEqual(itVal.done, false);
- test.strictEqual(itVal.value, "asdf");
- itVal = it.next();
- test.strictEqual(itVal.done, true);
- it = map_string_int32.values();
- itVal = it.next();
- test.strictEqual(itVal.done, false);
- test.strictEqual(itVal.value, 42);
- itVal = it.next();
- test.strictEqual(itVal.done, true);
- it = map_string_int32.entries();
- itVal = it.next();
- test.strictEqual(itVal.done, false);
- test.deepEqual(itVal.value, ["asdf", 42]);
- itVal = it.next();
- test.strictEqual(itVal.done, true);
- map_string_int32.set("jkl;", 84);
- test.strictEqual(map_string_int32.has("jkl;"), true);
- test.strictEqual(map_string_int32.has("asdf"), true);
- test.strictEqual(map_string_int32.size, 2);
- map_string_int32.delete("jkl;");
- test.strictEqual(map_string_int32.has("jkl;"), false);
- test.strictEqual(map_string_int32.get("jkl;"), undefined);
- test.strictEqual(map_string_int32.size, 1);
- map_string_int32.clear();
- test.strictEqual(map_string_int32.size, 0);
- try {
- map_string_int32.set("asdf", 42.1);
- test.ok(false); // ^ should throw
- } catch(e) {
- test.ok(e.message.match(/not an integer/));
- }
- try {
- map_string_int32.set(42, 42);
- test.ok(false); // ^ should throw
- } catch(e) {
- test.ok(e.message.match(/not a string/));
- }
- // Test various key types to ensure that value->string->value
- // conversion works.
- var map_int32_string =
- new ProtoBuf.Map(builder.lookup("Test.map_int32_string"));
- test.strictEqual(map_int32_string.size, 0);
- map_int32_string.set(12345678, "asdf");
- test.strictEqual(map_int32_string.size, 1);
- test.strictEqual(map_int32_string.has(12345678), true);
- test.strictEqual(map_int32_string.get(12345678), "asdf");
- var map_int64_string =
- new ProtoBuf.Map(builder.lookup("Test.map_int64_string"));
- test.strictEqual(map_int64_string.size, 0);
- map_int64_string.set("9223372036854775807", "asdf");
- test.strictEqual(map_int64_string.size, 1);
- test.strictEqual(map_int64_string.has("9223372036854775807"), true);
- test.strictEqual(map_int64_string.get("9223372036854775807"), "asdf");
- // Ensure that initialization from a raw object works.
- var map_int32_string =
- new ProtoBuf.Map(builder.lookup("Test.map_int32_string"),
- { 42: "asdf" });
- test.strictEqual(map_int32_string.size, 1);
- test.strictEqual(map_int32_string.keys().next().value, 42);
- var map_int64_string =
- new ProtoBuf.Map(builder.lookup("Test.map_int64_string"),
- { "9223372036854775807": "asdf" });
- test.strictEqual(map_int64_string.size, 1);
- var i64 = map_int64_string.keys().next().value;
- test.ok(i64 instanceof ProtoBuf.Long);
- test.strictEqual(i64.toString(), "9223372036854775807");
- test.done();
- },
- "mapField": function(test) {
- var proto =
- "message Test {\n" +
- " map<string, int32> map_string_int32 = 1;\n" +
- " map<string, int64> map_string_int64 = 2;\n" +
- " map<string, string> map_string_string = 3;\n" +
- " map<string, Test> map_string_msg = 4;\n" +
- " map<string, Enum> map_string_enum = 5;\n" +
- " map<int32, string> map_int32_string = 6;\n" +
- " map<int64, string> map_int64_string = 7;\n" +
- " map<bool, string> map_bool_string = 9;\n" +
- "}\n" +
- "enum Enum { Default = 0; A = 1; B = 2; }\n";
- var builder = ProtoBuf.newBuilder();
- ProtoBuf.loadProto(proto, builder, "test/mapField.proto");
- var Test = builder.build('Test'),
- Enum = builder.build('Enum');
- var testMsg = new Test();
- test.strictEqual(testMsg.map_string_int32.size, 0);
- test.strictEqual(testMsg.map_string_int64.size, 0);
- test.strictEqual(testMsg.map_string_string.size, 0);
- test.strictEqual(testMsg.map_string_msg.size, 0);
- test.strictEqual(testMsg.map_string_enum.size, 0);
- test.strictEqual(testMsg.map_int32_string.size, 0);
- test.strictEqual(testMsg.map_int64_string.size, 0);
- test.strictEqual(testMsg.map_bool_string.size, 0);
- testMsg.$set('map_string_int32', { 'asdf': 42 });
- try {
- testMsg.$set('map_string_int32', { 'asdf': 42.1 });
- test.ok(false); // ^ should throw
- } catch (e) {
- test.ok(e.message.match(/Illegal/));
- }
- test.done();
- },
- "mapEncodeDecode": function(test) {
- var proto =
- "message Test {\n" +
- " map<string, int32> map_string_int32 = 1;\n" +
- " map<string, int64> map_string_int64 = 2;\n" +
- " map<string, string> map_string_string = 3;\n" +
- " map<string, Test> map_string_msg = 4;\n" +
- " map<string, Enum> map_string_enum = 5;\n" +
- " map<int32, string> map_int32_string = 6;\n" +
- " map<int64, string> map_int64_string = 7;\n" +
- " map<bool, string> map_bool_string = 9;\n" +
- "}\n" +
- "enum Enum { Default = 0; A = 1; B = 2; }\n";
- var builder = ProtoBuf.newBuilder();
- ProtoBuf.loadProto(proto, builder, "test/mapField.proto");
- var Test = builder.build('Test'),
- Enum = builder.build('Enum');
- var testMsg = new Test();
- testMsg.map_string_int32.set("a", 1);
- testMsg.map_string_int32.set("b", 2);
- testMsg.map_string_int64.set("c", "12345678901234");
- testMsg.map_string_int64.set("d", "98765432109876");
- testMsg.map_string_string.set("e", "asdf");
- testMsg.map_string_string.set("f", "jkl;");
- testMsg.map_string_enum.set("g", Enum.A);
- testMsg.map_string_enum.set("h", Enum.B);
- testMsg.map_int32_string.set(9, "a");
- testMsg.map_int32_string.set(10, "b");
- testMsg.map_int64_string.set("12345678901234", "a");
- testMsg.map_int64_string.set("98765432109876", "b");
- testMsg.map_bool_string.set(false, "a");
- testMsg.map_bool_string.set(true, "b");
- var encoded = testMsg.encode();
- testMsg = Test.decode(encoded);
- test.strictEqual(testMsg.map_string_int32.get("a"), 1);
- test.strictEqual(testMsg.map_string_int32.get("b"), 2);
- test.strictEqual(testMsg.map_string_int64.get("c").toString(), "12345678901234");
- test.strictEqual(testMsg.map_string_int64.get("d").toString(), "98765432109876");
- test.strictEqual(testMsg.map_string_string.get("e"), "asdf");
- test.strictEqual(testMsg.map_string_string.get("f"), "jkl;");
- test.strictEqual(testMsg.map_string_enum.get("g"), Enum.A);
- test.strictEqual(testMsg.map_string_enum.get("h"), Enum.B);
- test.strictEqual(testMsg.map_int32_string.get(9), "a");
- test.strictEqual(testMsg.map_int32_string.get(10), "b");
- test.strictEqual(testMsg.map_int64_string.get("12345678901234"), "a");
- test.strictEqual(testMsg.map_int64_string.get("98765432109876"), "b");
- test.strictEqual(testMsg.map_bool_string.get(false), "a");
- test.strictEqual(testMsg.map_bool_string.get(true), "b");
- test.done();
- },
- "proto3Json": function(test) {
- var proto =
- "syntax = \"proto3\";\n" +
- "message Test {\n" +
- " int32 optional_int32 = 1;\n" +
- " int64 optional_int64 = 2;\n" +
- " string optional_string = 3;\n" +
- " bytes optional_bytes = 4;\n" +
- " bool optional_bool = 5;\n" +
- " Enum optional_enum = 6;\n" +
- " repeated int32 repeated_int32 = 11;\n" +
- " repeated int64 repeated_int64 = 12;\n" +
- " repeated string repeated_string = 13;\n" +
- " repeated bytes repeated_bytes = 14;\n" +
- " repeated bool repeated_bool = 15;\n" +
- " repeated Enum repeated_enum = 16;\n" +
- " map<string, int32> map_string_int32 = 20;\n" +
- " map<string, int64> map_string_int64 = 21;\n" +
- " map<string, string> map_string_string = 22;\n" +
- " map<string, Enum> map_string_enum = 24;\n" +
- " map<int32, string> map_int32_string = 25;\n" +
- " map<int64, string> map_int64_string = 26;\n" +
- " map<bool, string> map_bool_string = 27;\n" +
- "}\n" +
- "enum Enum { Default = 0; A = 1; B = 2; }\n";
- var builder = ProtoBuf.newBuilder();
- ProtoBuf.loadProto(proto, builder, "test/mapField.proto");
- var Test = builder.build('Test'),
- Enum = builder.build('Enum');
- var testMsg = new Test();
- testMsg.optional_int32 = 1;
- testMsg.optional_int64 = "12345678901234";
- testMsg.optional_string = "hello";
- testMsg.optional_bytes = ProtoBuf.ByteBuffer.fromBinary("\x00\xFF\x80");
- testMsg.optional_bool = true;
- testMsg.optional_enum = Enum.A;
- testMsg.repeated_int32.push(1);
- testMsg.repeated_int64.push("12345678901234");
- testMsg.repeated_string.push("hello");
- testMsg.repeated_bytes.push(ProtoBuf.ByteBuffer.fromBinary("\x00\xFF\x80"));
- testMsg.repeated_bool.push(true);
- testMsg.repeated_enum.push(Enum.A);
- testMsg.map_string_int32.set("a", 1);
- testMsg.map_string_int32.set("b", 2);
- testMsg.map_string_int64.set("c", "12345678901234");
- testMsg.map_string_int64.set("d", "98765432109876");
- testMsg.map_string_string.set("e", "asdf");
- testMsg.map_string_string.set("f", "jkl;");
- testMsg.map_string_enum.set("g", Enum.A);
- testMsg.map_string_enum.set("h", Enum.B);
- testMsg.map_int32_string.set(9, "a");
- testMsg.map_int32_string.set(10, "b");
- testMsg.map_int64_string.set("12345678901234", "a");
- testMsg.map_int64_string.set("98765432109876", "b");
- testMsg.map_bool_string.set(false, "a");
- testMsg.map_bool_string.set(true, "b");
- var jsonObj = JSON.parse(testMsg.encodeJSON());
- test.deepEqual(jsonObj,
- {
- optional_int32: 1,
- optional_int64: "12345678901234",
- optional_string: "hello",
- optional_bytes: "AP+A", // base64
- optional_bool: true,
- optional_enum: "A",
- repeated_int32: [1],
- repeated_int64: ["12345678901234"],
- repeated_string: ["hello"],
- repeated_bytes: ["AP+A"], // base64
- repeated_bool: [true],
- repeated_enum: ["A"],
- map_string_int32: { "a": 1, "b": 2 },
- map_string_int64: { "c": "12345678901234", "d": "98765432109876" },
- map_string_string: { "e": "asdf", "f": "jkl;" },
- map_string_enum: { "g": "A", "h": "B" },
- map_int32_string: { "9": "a", "10": "b" },
- map_int64_string: { "12345678901234": "a", "98765432109876": "b" },
- map_bool_string: { "false": "a", "true": "b" },
- });
- var testMsg2 = Test.decodeJSON(testMsg.encodeJSON());
- test.strictEqual(testMsg2.encodeJSON(), testMsg.encodeJSON());
- test.done();
- },
- // Node.js only
- "loaders": BROWSER ? {} : {
- "commonjs": function(test) {
- var fs = require("fs")
- , vm = require("vm")
- , util = require('util');
- var code = fs.readFileSync(__dirname+"/../dist/"+FILE);
- var exports = {};
- var sandbox = new Sandbox({
- module: {
- exports: exports,
- id: "protobufjs"
- },
- exports: exports,
- require: (function() {
- function require(mod) {
- if (mod == 'bytebuffer') require.called = true;
- return ByteBuffer;
- }
- require.called = false;
- return require;
- })()
- });
- vm.runInNewContext(code, sandbox, "ProtoBuf.js in CommonJS-VM");
- // console.log(util.inspect(sandbox));
- test.ok(typeof sandbox.module.exports == 'object');
- test.ok(typeof sandbox.require != 'undefined' && sandbox.require.called);
- test.done();
- },
- "amd": function(test) {
- var fs = require("fs")
- , vm = require("vm")
- , util = require('util');
- var code = fs.readFileSync(__dirname+"/../dist/"+FILE);
- var sandbox = new Sandbox({
- define: (function() {
- function define() {
- define.called = true;
- }
- define.amd = true;
- define.called = false;
- return define;
- })()
- });
- vm.runInNewContext(code, sandbox, "ProtoBuf.js in AMD-VM");
- // console.log(util.inspect(sandbox));
- test.ok(sandbox.define.called == true);
- test.done();
- },
- "shim": function(test) {
- var fs = require("fs")
- , vm = require("vm")
- , util = require('util');
- var code = fs.readFileSync(__dirname+"/../dist/"+FILE);
- var sandbox = new Sandbox({
- dcodeIO: {
- ByteBuffer: ByteBuffer
- }
- });
- vm.runInNewContext(code, sandbox, "ProtoBuf.js in shim-VM");
- // console.log(util.inspect(sandbox));
- test.ok(typeof sandbox.dcodeIO != 'undefined' && typeof sandbox.dcodeIO.ProtoBuf != 'undefined');
- test.done();
- }
- }
- };
- if (typeof module != 'undefined' && module.exports) {
- module.exports = suite;
- } else {
- global["suite"] = suite;
- }
- })(this);
|