1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// https://developers.google.com/protocol-buffers/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31// Test suite is written using Jasmine -- see http://jasmine.github.io/ 32 33goog.setTestOnly(); 34 35goog.require('goog.json'); 36goog.require('goog.testing.asserts'); 37goog.require('goog.userAgent'); 38 39// CommonJS-LoadFromFile: google-protobuf jspb 40goog.require('jspb.Message'); 41 42// CommonJS-LoadFromFile: test5_pb proto.jspb.exttest.beta 43goog.require('proto.jspb.exttest.beta.floatingStrField'); 44 45// CommonJS-LoadFromFile: test3_pb proto.jspb.exttest 46goog.require('proto.jspb.exttest.floatingMsgField'); 47 48// CommonJS-LoadFromFile: test4_pb proto.jspb.exttest 49goog.require('proto.jspb.exttest.floatingMsgFieldTwo'); 50 51// CommonJS-LoadFromFile: test_pb proto.jspb.test 52goog.require('proto.jspb.test.CloneExtension'); 53goog.require('proto.jspb.test.Complex'); 54goog.require('proto.jspb.test.DefaultValues'); 55goog.require('proto.jspb.test.Empty'); 56goog.require('proto.jspb.test.EnumContainer'); 57goog.require('proto.jspb.test.floatingMsgField'); 58goog.require('proto.jspb.test.FloatingPointFields'); 59goog.require('proto.jspb.test.floatingStrField'); 60goog.require('proto.jspb.test.HasExtensions'); 61goog.require('proto.jspb.test.IndirectExtension'); 62goog.require('proto.jspb.test.IsExtension'); 63goog.require('proto.jspb.test.OptionalFields'); 64goog.require('proto.jspb.test.OuterEnum'); 65goog.require('proto.jspb.test.OuterMessage.Complex'); 66goog.require('proto.jspb.test.Simple1'); 67goog.require('proto.jspb.test.Simple2'); 68goog.require('proto.jspb.test.SpecialCases'); 69goog.require('proto.jspb.test.TestClone'); 70goog.require('proto.jspb.test.TestGroup'); 71goog.require('proto.jspb.test.TestGroup1'); 72goog.require('proto.jspb.test.TestMessageWithOneof'); 73goog.require('proto.jspb.test.TestReservedNames'); 74goog.require('proto.jspb.test.TestReservedNamesExtension'); 75 76// CommonJS-LoadFromFile: test2_pb proto.jspb.test 77goog.require('proto.jspb.test.ExtensionMessage'); 78goog.require('proto.jspb.test.TestExtensionsMessage'); 79goog.require('proto.jspb.test.simple1'); 80 81 82 83describe('Message test suite', function() { 84 it('testEmptyProto', function() { 85 var empty1 = new proto.jspb.test.Empty([]); 86 var empty2 = new proto.jspb.test.Empty([]); 87 assertObjectEquals({}, empty1.toObject()); 88 assertObjectEquals('Message should not be corrupted:', empty2, empty1); 89 }); 90 91 it('testTopLevelEnum', function() { 92 var response = new proto.jspb.test.EnumContainer([]); 93 response.setOuterEnum(proto.jspb.test.OuterEnum.FOO); 94 assertEquals(proto.jspb.test.OuterEnum.FOO, response.getOuterEnum()); 95 }); 96 97 it('testByteStrings', function() { 98 var data = new proto.jspb.test.DefaultValues([]); 99 data.setBytesField('some_bytes'); 100 assertEquals('some_bytes', data.getBytesField()); 101 }); 102 103 it('testComplexConversion', function() { 104 var data1 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , true]; 105 var data2 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , true]; 106 var foo = new proto.jspb.test.Complex(data1); 107 var bar = new proto.jspb.test.Complex(data2); 108 var result = foo.toObject(); 109 assertObjectEquals( 110 { 111 aString: 'a', 112 anOutOfOrderBool: true, 113 aNestedMessage: {anInt: 11}, 114 aRepeatedMessageList: [{anInt: 22}, {anInt: 33}], 115 aRepeatedStringList: ['s1', 's2'] 116 }, 117 result); 118 119 // Now test with the jspb instances included. 120 result = foo.toObject(true /* opt_includeInstance */); 121 assertObjectEquals( 122 { 123 aString: 'a', 124 anOutOfOrderBool: true, 125 aNestedMessage: 126 {anInt: 11, $jspbMessageInstance: foo.getANestedMessage()}, 127 aRepeatedMessageList: [ 128 {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]}, 129 {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]} 130 ], 131 aRepeatedStringList: ['s1', 's2'], 132 $jspbMessageInstance: foo 133 }, 134 result); 135 }); 136 137 it('testMissingFields', function() { 138 var foo = new proto.jspb.test.Complex([ 139 undefined, undefined, undefined, [], undefined, undefined, undefined, 140 undefined 141 ]); 142 var bar = new proto.jspb.test.Complex([ 143 undefined, undefined, undefined, [], undefined, undefined, undefined, 144 undefined 145 ]); 146 var result = foo.toObject(); 147 assertObjectEquals( 148 { 149 aString: undefined, 150 anOutOfOrderBool: undefined, 151 aNestedMessage: {anInt: undefined}, 152 // Note: JsPb converts undefined repeated fields to empty arrays. 153 aRepeatedMessageList: [], 154 aRepeatedStringList: [] 155 }, 156 result); 157 }); 158 159 it('testNestedComplexMessage', function() { 160 // Instantiate the message and set a unique field, just to ensure that we 161 // are not getting jspb.test.Complex instead. 162 var msg = new proto.jspb.test.OuterMessage.Complex(); 163 msg.setInnerComplexField(5); 164 }); 165 166 it('testSpecialCases', function() { 167 // Note: Some property names are reserved in JavaScript. 168 // These names are converted to the Js property named pb_<reserved_name>. 169 var special = new proto.jspb.test.SpecialCases( 170 ['normal', 'default', 'function', 'var']); 171 var result = special.toObject(); 172 assertObjectEquals( 173 { 174 normal: 'normal', 175 pb_default: 'default', 176 pb_function: 'function', 177 pb_var: 'var' 178 }, 179 result); 180 }); 181 182 it('testDefaultValues', function() { 183 var defaultString = 'default<>\'"abc'; 184 var response = new proto.jspb.test.DefaultValues(); 185 186 // Test toObject 187 var expectedObject = { 188 stringField: defaultString, 189 boolField: true, 190 intField: 11, 191 enumField: 13, 192 emptyField: '', 193 bytesField: 'bW9v' 194 }; 195 assertObjectEquals(expectedObject, response.toObject()); 196 197 198 // Test getters 199 response = new proto.jspb.test.DefaultValues(); 200 assertEquals(defaultString, response.getStringField()); 201 assertEquals(true, response.getBoolField()); 202 assertEquals(11, response.getIntField()); 203 assertEquals(13, response.getEnumField()); 204 assertEquals('', response.getEmptyField()); 205 assertEquals('bW9v', response.getBytesField()); 206 207 function makeDefault(values) { 208 return new proto.jspb.test.DefaultValues(values); 209 } 210 211 // Test with undefined values, 212 // Use push to workaround IE treating undefined array elements as holes. 213 response = makeDefault([undefined, undefined, undefined, undefined]); 214 assertEquals(defaultString, response.getStringField()); 215 assertEquals(true, response.getBoolField()); 216 assertEquals(11, response.getIntField()); 217 assertEquals(13, response.getEnumField()); 218 assertFalse(response.hasStringField()); 219 assertFalse(response.hasBoolField()); 220 assertFalse(response.hasIntField()); 221 assertFalse(response.hasEnumField()); 222 223 // Test with null values, as would be returned by a JSON serializer. 224 response = makeDefault([null, null, null, null]); 225 assertEquals(defaultString, response.getStringField()); 226 assertEquals(true, response.getBoolField()); 227 assertEquals(11, response.getIntField()); 228 assertEquals(13, response.getEnumField()); 229 assertFalse(response.hasStringField()); 230 assertFalse(response.hasBoolField()); 231 assertFalse(response.hasIntField()); 232 assertFalse(response.hasEnumField()); 233 234 // Test with false-like values. 235 response = makeDefault(['', false, 0, 0]); 236 assertEquals('', response.getStringField()); 237 assertEquals(false, response.getBoolField()); 238 assertEquals(true, response.getIntField() == 0); 239 assertEquals(true, response.getEnumField() == 0); 240 assertTrue(response.hasStringField()); 241 assertTrue(response.hasBoolField()); 242 assertTrue(response.hasIntField()); 243 assertTrue(response.hasEnumField()); 244 245 // Test that clearing the values reverts them to the default state. 246 response = makeDefault(['blah', false, 111, 77]); 247 response.clearStringField(); 248 response.clearBoolField(); 249 response.clearIntField(); 250 response.clearEnumField(); 251 assertEquals(defaultString, response.getStringField()); 252 assertEquals(true, response.getBoolField()); 253 assertEquals(11, response.getIntField()); 254 assertEquals(13, response.getEnumField()); 255 assertFalse(response.hasStringField()); 256 assertFalse(response.hasBoolField()); 257 assertFalse(response.hasIntField()); 258 assertFalse(response.hasEnumField()); 259 260 // Test that setFoo(null) clears the values. 261 response = makeDefault(['blah', false, 111, 77]); 262 response.setStringField(null); 263 response.setBoolField(null); 264 response.setIntField(undefined); 265 response.setEnumField(undefined); 266 assertEquals(defaultString, response.getStringField()); 267 assertEquals(true, response.getBoolField()); 268 assertEquals(11, response.getIntField()); 269 assertEquals(13, response.getEnumField()); 270 assertFalse(response.hasStringField()); 271 assertFalse(response.hasBoolField()); 272 assertFalse(response.hasIntField()); 273 assertFalse(response.hasEnumField()); 274 }); 275 276 it('testClearFields', function() { 277 var data = ['str', true, [11], [[22], [33]], ['s1', 's2']]; 278 var foo = new proto.jspb.test.OptionalFields(data); 279 foo.clearAString(); 280 foo.clearABool(); 281 foo.clearANestedMessage(); 282 foo.clearARepeatedMessageList(); 283 foo.clearARepeatedStringList(); 284 assertEquals('', foo.getAString()); 285 assertEquals(false, foo.getABool()); 286 assertUndefined(foo.getANestedMessage()); 287 assertFalse(foo.hasAString()); 288 assertFalse(foo.hasABool()); 289 assertObjectEquals([], foo.getARepeatedMessageList()); 290 assertObjectEquals([], foo.getARepeatedStringList()); 291 // NOTE: We want the missing fields in 'expected' to be undefined, 292 // but we actually get a sparse array instead. We could use something 293 // like [1,undefined,2] to avoid this, except that this is still 294 // sparse on IE. No comment... 295 var expected = [, , , [], []]; 296 expected[0] = expected[1] = expected[2] = undefined; 297 assertObjectEquals(expected, foo.toArray()); 298 }); 299 300 it('testDifferenceRawObject', /** @suppress {visibility} */ function() { 301 var p1 = new proto.jspb.test.HasExtensions(['hi', 'diff', {}]); 302 var p2 = 303 new proto.jspb.test.HasExtensions(['hi', 'what', {1000: 'unique'}]); 304 var diff = /** @type {proto.jspb.test.HasExtensions} */ 305 (jspb.Message.difference(p1, p2)); 306 assertEquals('', diff.getStr1()); 307 assertEquals('what', diff.getStr2()); 308 assertEquals('', diff.getStr3()); 309 assertEquals('unique', diff.extensionObject_[1000]); 310 }); 311 312 it('testEqualsSimple', function() { 313 var s1 = new proto.jspb.test.Simple1(['hi']); 314 assertTrue(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi']))); 315 assertFalse(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['bye']))); 316 var s1b = new proto.jspb.test.Simple1(['hi', ['hello']]); 317 assertTrue(jspb.Message.equals( 318 s1b, new proto.jspb.test.Simple1(['hi', ['hello']]))); 319 assertTrue(jspb.Message.equals(s1b, new proto.jspb.test.Simple1([ 320 'hi', ['hello', undefined, undefined, undefined] 321 ]))); 322 assertFalse(jspb.Message.equals( 323 s1b, new proto.jspb.test.Simple1(['no', ['hello']]))); 324 // Test with messages of different types 325 var s2 = new proto.jspb.test.Simple2(['hi']); 326 assertFalse(jspb.Message.equals(s1, s2)); 327 }); 328 329 it('testEquals_softComparison', function() { 330 var s1 = new proto.jspb.test.Simple1(['hi', [], null]); 331 assertTrue( 332 jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi', []]))); 333 334 var s1b = new proto.jspb.test.Simple1(['hi', [], true]); 335 assertTrue( 336 jspb.Message.equals(s1b, new proto.jspb.test.Simple1(['hi', [], 1]))); 337 }); 338 339 it('testEqualsComplex', function() { 340 var data1 = ['a', , , [, 11], [[, 22], [, 33]], , ['s1', 's2'], , 1]; 341 var data2 = ['a', , , [, 11], [[, 22], [, 34]], , ['s1', 's2'], , 1]; 342 var data3 = ['a', , , [, 11], [[, 22]], , ['s1', 's2'], , 1]; 343 var data4 = ['hi']; 344 var c1a = new proto.jspb.test.Complex(data1); 345 var c1b = new proto.jspb.test.Complex(data1); 346 var c2 = new proto.jspb.test.Complex(data2); 347 var c3 = new proto.jspb.test.Complex(data3); 348 var s1 = new proto.jspb.test.Simple1(data4); 349 350 assertTrue(jspb.Message.equals(c1a, c1b)); 351 assertFalse(jspb.Message.equals(c1a, c2)); 352 assertFalse(jspb.Message.equals(c2, c3)); 353 assertFalse(jspb.Message.equals(c1a, s1)); 354 }); 355 356 it('testEqualsExtensionsConstructed', function() { 357 assertTrue(jspb.Message.equals( 358 new proto.jspb.test.HasExtensions([]), 359 new proto.jspb.test.HasExtensions([{}]))); 360 assertTrue(jspb.Message.equals( 361 new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]), 362 new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]))); 363 assertFalse(jspb.Message.equals( 364 new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]), 365 new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}]))); 366 assertTrue(jspb.Message.equals( 367 new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]), 368 new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]))); 369 assertTrue(jspb.Message.equals( 370 new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]), 371 new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}]))); 372 assertTrue(jspb.Message.equals( 373 new proto.jspb.test.HasExtensions([, , , {100: [{200: 'a'}]}]), 374 new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]))); 375 assertTrue(jspb.Message.equals( 376 new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]), 377 new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}]))); 378 assertTrue(jspb.Message.equals( 379 new proto.jspb.test.HasExtensions(['hi', , , {100: [{200: 'a'}]}]), 380 new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]))); 381 }); 382 383 it('testEqualsExtensionsUnconstructed', function() { 384 assertTrue(jspb.Message.compareFields([], [{}])); 385 assertTrue(jspb.Message.compareFields([, , , {}], [])); 386 assertTrue(jspb.Message.compareFields([, , , {}], [, , {}])); 387 assertTrue(jspb.Message.compareFields( 388 ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}])); 389 assertFalse(jspb.Message.compareFields( 390 ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'b'}]}])); 391 assertTrue(jspb.Message.compareFields( 392 [{100: [{200: 'a'}]}], [{100: [{200: 'a'}]}])); 393 assertTrue(jspb.Message.compareFields( 394 [{100: [{200: 'a'}]}], [, , , {100: [{200: 'a'}]}])); 395 assertTrue(jspb.Message.compareFields( 396 [, , , {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}])); 397 assertTrue(jspb.Message.compareFields( 398 ['hi', {100: [{200: 'a'}]}], ['hi', , , {100: [{200: 'a'}]}])); 399 assertTrue(jspb.Message.compareFields( 400 ['hi', , , {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}])); 401 }); 402 403 it('testToMap', function() { 404 var p1 = new proto.jspb.test.Simple1(['k', ['v']]); 405 var p2 = new proto.jspb.test.Simple1(['k1', ['v1', 'v2']]); 406 var soymap = jspb.Message.toMap( 407 [p1, p2], proto.jspb.test.Simple1.prototype.getAString, 408 proto.jspb.test.Simple1.prototype.toObject); 409 assertEquals('k', soymap['k'].aString); 410 assertArrayEquals(['v'], soymap['k'].aRepeatedStringList); 411 var protomap = jspb.Message.toMap( 412 [p1, p2], proto.jspb.test.Simple1.prototype.getAString); 413 assertEquals('k', protomap['k'].getAString()); 414 assertArrayEquals(['v'], protomap['k'].getARepeatedStringList()); 415 }); 416 417 it('testClone', function() { 418 var supportsUint8Array = 419 !goog.userAgent.IE || goog.userAgent.isVersionOrHigher('10'); 420 var original = new proto.jspb.test.TestClone(); 421 original.setStr('v1'); 422 var simple1 = new proto.jspb.test.Simple1(['x1', ['y1', 'z1']]); 423 var simple2 = new proto.jspb.test.Simple1(['x2', ['y2', 'z2']]); 424 var simple3 = new proto.jspb.test.Simple1(['x3', ['y3', 'z3']]); 425 original.setSimple1(simple1); 426 original.setSimple2List([simple2, simple3]); 427 var bytes1 = supportsUint8Array ? new Uint8Array([1, 2, 3]) : '123'; 428 original.setBytesField(bytes1); 429 var extension = new proto.jspb.test.CloneExtension(); 430 extension.setExt('e1'); 431 original.setExtension(proto.jspb.test.IsExtension.extField, extension); 432 var clone = original.clone(); 433 assertArrayEquals( 434 [ 435 'v1', , ['x1', ['y1', 'z1']], , 436 [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, , 437 {100: [, 'e1']} 438 ], 439 clone.toArray()); 440 clone.setStr('v2'); 441 var simple4 = new proto.jspb.test.Simple1(['a1', ['b1', 'c1']]); 442 var simple5 = new proto.jspb.test.Simple1(['a2', ['b2', 'c2']]); 443 var simple6 = new proto.jspb.test.Simple1(['a3', ['b3', 'c3']]); 444 clone.setSimple1(simple4); 445 clone.setSimple2List([simple5, simple6]); 446 if (supportsUint8Array) { 447 clone.getBytesField()[0] = 4; 448 assertObjectEquals(bytes1, original.getBytesField()); 449 } 450 var bytes2 = supportsUint8Array ? new Uint8Array([4, 5, 6]) : '456'; 451 clone.setBytesField(bytes2); 452 var newExtension = new proto.jspb.test.CloneExtension(); 453 newExtension.setExt('e2'); 454 clone.setExtension(proto.jspb.test.CloneExtension.extField, newExtension); 455 assertArrayEquals( 456 [ 457 'v2', , ['a1', ['b1', 'c1']], , 458 [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2, , 459 {100: [, 'e2']} 460 ], 461 clone.toArray()); 462 assertArrayEquals( 463 [ 464 'v1', , ['x1', ['y1', 'z1']], , 465 [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1, , 466 {100: [, 'e1']} 467 ], 468 original.toArray()); 469 }); 470 471 it('testCopyInto', function() { 472 var supportsUint8Array = 473 !goog.userAgent.IE || goog.userAgent.isVersionOrHigher('10'); 474 var original = new proto.jspb.test.TestClone(); 475 original.setStr('v1'); 476 var dest = new proto.jspb.test.TestClone(); 477 dest.setStr('override'); 478 var simple1 = new proto.jspb.test.Simple1(['x1', ['y1', 'z1']]); 479 var simple2 = new proto.jspb.test.Simple1(['x2', ['y2', 'z2']]); 480 var simple3 = new proto.jspb.test.Simple1(['x3', ['y3', 'z3']]); 481 var destSimple1 = new proto.jspb.test.Simple1(['ox1', ['oy1', 'oz1']]); 482 var destSimple2 = new proto.jspb.test.Simple1(['ox2', ['oy2', 'oz2']]); 483 var destSimple3 = new proto.jspb.test.Simple1(['ox3', ['oy3', 'oz3']]); 484 original.setSimple1(simple1); 485 original.setSimple2List([simple2, simple3]); 486 dest.setSimple1(destSimple1); 487 dest.setSimple2List([destSimple2, destSimple3]); 488 var bytes1 = supportsUint8Array ? new Uint8Array([1, 2, 3]) : '123'; 489 var bytes2 = supportsUint8Array ? new Uint8Array([4, 5, 6]) : '456'; 490 original.setBytesField(bytes1); 491 dest.setBytesField(bytes2); 492 var extension = new proto.jspb.test.CloneExtension(); 493 extension.setExt('e1'); 494 original.setExtension(proto.jspb.test.CloneExtension.extField, extension); 495 496 jspb.Message.copyInto(original, dest); 497 assertArrayEquals(original.toArray(), dest.toArray()); 498 assertEquals('x1', dest.getSimple1().getAString()); 499 assertEquals( 500 'e1', 501 dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt()); 502 dest.getSimple1().setAString('new value'); 503 assertNotEquals( 504 dest.getSimple1().getAString(), original.getSimple1().getAString()); 505 if (supportsUint8Array) { 506 dest.getBytesField()[0] = 7; 507 assertObjectEquals(bytes1, original.getBytesField()); 508 assertObjectEquals(new Uint8Array([7, 2, 3]), dest.getBytesField()); 509 } else { 510 dest.setBytesField('789'); 511 assertObjectEquals(bytes1, original.getBytesField()); 512 assertObjectEquals('789', dest.getBytesField()); 513 } 514 dest.getExtension(proto.jspb.test.CloneExtension.extField) 515 .setExt('new value'); 516 assertNotEquals( 517 dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt(), 518 original.getExtension(proto.jspb.test.CloneExtension.extField) 519 .getExt()); 520 }); 521 522 it('testCopyInto_notSameType', function() { 523 var a = new proto.jspb.test.TestClone(); 524 var b = new proto.jspb.test.Simple1(['str', ['s1', 's2']]); 525 526 var e = assertThrows(function() { 527 jspb.Message.copyInto(a, b); 528 }); 529 assertContains('should have the same type', e.message); 530 }); 531 532 it('testExtensions', function() { 533 var extension1 = new proto.jspb.test.IsExtension(['ext1field']); 534 var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2']]); 535 var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); 536 extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1); 537 extendable.setExtension( 538 proto.jspb.test.IndirectExtension.simple, extension2); 539 extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy'); 540 extendable.setExtension( 541 proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']); 542 var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]); 543 var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2']]); 544 extendable.setExtension( 545 proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]); 546 assertObjectEquals( 547 extension1, 548 extendable.getExtension(proto.jspb.test.IsExtension.extField)); 549 assertObjectEquals( 550 extension2, 551 extendable.getExtension(proto.jspb.test.IndirectExtension.simple)); 552 assertObjectEquals( 553 'xyzzy', 554 extendable.getExtension(proto.jspb.test.IndirectExtension.str)); 555 assertObjectEquals( 556 ['a', 'b'], 557 extendable.getExtension( 558 proto.jspb.test.IndirectExtension.repeatedStrList)); 559 assertObjectEquals( 560 [s1, s2], 561 extendable.getExtension( 562 proto.jspb.test.IndirectExtension.repeatedSimpleList)); 563 // Not supported yet, but it should work... 564 extendable.setExtension(proto.jspb.test.IndirectExtension.simple, null); 565 assertNull( 566 extendable.getExtension(proto.jspb.test.IndirectExtension.simple)); 567 extendable.setExtension(proto.jspb.test.IndirectExtension.str, null); 568 assertNull(extendable.getExtension(proto.jspb.test.IndirectExtension.str)); 569 570 571 // Extension fields with jspb.ignore = true are ignored. 572 assertUndefined(proto.jspb.test.IndirectExtension['ignored']); 573 assertUndefined(proto.jspb.test.HasExtensions['ignoredFloating']); 574 }); 575 576 it('testFloatingExtensions', function() { 577 // From an autogenerated container. 578 var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); 579 var extension = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]); 580 extendable.setExtension(proto.jspb.test.simple1, extension); 581 assertObjectEquals( 582 extension, extendable.getExtension(proto.jspb.test.simple1)); 583 584 // From _lib mode. 585 extension = new proto.jspb.test.ExtensionMessage(['s1']); 586 extendable = new proto.jspb.test.TestExtensionsMessage([16]); 587 extendable.setExtension(proto.jspb.test.floatingMsgField, extension); 588 extendable.setExtension(proto.jspb.test.floatingStrField, 's2'); 589 assertObjectEquals( 590 extension, extendable.getExtension(proto.jspb.test.floatingMsgField)); 591 assertObjectEquals( 592 's2', extendable.getExtension(proto.jspb.test.floatingStrField)); 593 assertNotUndefined(proto.jspb.exttest.floatingMsgField); 594 assertNotUndefined(proto.jspb.exttest.floatingMsgFieldTwo); 595 assertNotUndefined(proto.jspb.exttest.beta.floatingStrField); 596 }); 597 598 it('testToObject_extendedObject', function() { 599 var extension1 = new proto.jspb.test.IsExtension(['ext1field']); 600 var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2'], true]); 601 var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']); 602 extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1); 603 extendable.setExtension( 604 proto.jspb.test.IndirectExtension.simple, extension2); 605 extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy'); 606 extendable.setExtension( 607 proto.jspb.test.IndirectExtension.repeatedStrList, ['a', 'b']); 608 var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2'], true]); 609 var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2'], false]); 610 extendable.setExtension( 611 proto.jspb.test.IndirectExtension.repeatedSimpleList, [s1, s2]); 612 assertObjectEquals( 613 { 614 str1: 'v1', 615 str2: 'v2', 616 str3: 'v3', 617 extField: {ext1: 'ext1field'}, 618 simple: { 619 aString: 'str', 620 aRepeatedStringList: ['s1', 's2'], 621 aBoolean: true 622 }, 623 str: 'xyzzy', 624 repeatedStrList: ['a', 'b'], 625 repeatedSimpleList: [ 626 {aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true}, 627 {aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false} 628 ] 629 }, 630 extendable.toObject()); 631 632 // Now, with instances included. 633 assertObjectEquals( 634 { 635 str1: 'v1', 636 str2: 'v2', 637 str3: 'v3', 638 extField: { 639 ext1: 'ext1field', 640 $jspbMessageInstance: 641 extendable.getExtension(proto.jspb.test.IsExtension.extField) 642 }, 643 simple: { 644 aString: 'str', 645 aRepeatedStringList: ['s1', 's2'], 646 aBoolean: true, 647 $jspbMessageInstance: extendable.getExtension( 648 proto.jspb.test.IndirectExtension.simple) 649 }, 650 str: 'xyzzy', 651 repeatedStrList: ['a', 'b'], 652 repeatedSimpleList: [ 653 { 654 aString: 'foo', 655 aRepeatedStringList: ['s1', 's2'], 656 aBoolean: true, 657 $jspbMessageInstance: s1 658 }, 659 { 660 aString: 'bar', 661 aRepeatedStringList: ['t1', 't2'], 662 aBoolean: false, 663 $jspbMessageInstance: s2 664 } 665 ], 666 $jspbMessageInstance: extendable 667 }, 668 extendable.toObject(true /* opt_includeInstance */)); 669 }); 670 671 it('testInitialization_emptyArray', function() { 672 var msg = new proto.jspb.test.HasExtensions([]); 673 assertArrayEquals([], msg.toArray()); 674 }); 675 676 it('testInitialization_justExtensionObject', function() { 677 var msg = new proto.jspb.test.Empty([{1: 'hi'}]); 678 // The extensionObject is not moved from its original location. 679 assertArrayEquals([{1: 'hi'}], msg.toArray()); 680 }); 681 682 it('testInitialization_incompleteList', function() { 683 var msg = new proto.jspb.test.Empty([1, {4: 'hi'}]); 684 // The extensionObject is not moved from its original location. 685 assertArrayEquals([1, {4: 'hi'}], msg.toArray()); 686 }); 687 688 it('testInitialization_forwardCompatible', function() { 689 var msg = new proto.jspb.test.Empty([1, 2, 3, {1: 'hi'}]); 690 assertArrayEquals([1, 2, 3, {1: 'hi'}], msg.toArray()); 691 }); 692 693 it('testExtendedMessageEnsureObject', 694 /** @suppress {visibility} */ function() { 695 var data = 696 new proto.jspb.test.HasExtensions(['str1', {'a_key': 'an_object'}]); 697 assertEquals('an_object', data.extensionObject_['a_key']); 698 }); 699 700 it('testToObject_hasExtensionField', function() { 701 var data = new proto.jspb.test.HasExtensions(['str1', {100: ['ext1']}]); 702 var obj = data.toObject(); 703 assertEquals('str1', obj.str1); 704 assertEquals('ext1', obj.extField.ext1); 705 }); 706 707 it('testGetExtension', function() { 708 var data = new proto.jspb.test.HasExtensions(['str1', {100: ['ext1']}]); 709 assertEquals('str1', data.getStr1()); 710 var extension = data.getExtension(proto.jspb.test.IsExtension.extField); 711 assertNotNull(extension); 712 assertEquals('ext1', extension.getExt1()); 713 }); 714 715 it('testSetExtension', function() { 716 var data = new proto.jspb.test.HasExtensions(); 717 var extensionMessage = new proto.jspb.test.IsExtension(['is_extension']); 718 data.setExtension(proto.jspb.test.IsExtension.extField, extensionMessage); 719 var obj = data.toObject(); 720 assertNotNull(data.getExtension(proto.jspb.test.IsExtension.extField)); 721 assertEquals('is_extension', obj.extField.ext1); 722 }); 723 724 /** 725 * Note that group is long deprecated, we only support it because JsPb has 726 * a goal of being able to generate JS classes for all proto descriptors. 727 */ 728 it('testGroups', function() { 729 var group = new proto.jspb.test.TestGroup(); 730 var someGroup = new proto.jspb.test.TestGroup.RepeatedGroup(); 731 someGroup.setId('g1'); 732 someGroup.setSomeBoolList([true, false]); 733 group.setRepeatedGroupList([someGroup]); 734 var groups = group.getRepeatedGroupList(); 735 assertEquals('g1', groups[0].getId()); 736 assertObjectEquals([true, false], groups[0].getSomeBoolList()); 737 assertObjectEquals( 738 {id: 'g1', someBoolList: [true, false]}, groups[0].toObject()); 739 assertObjectEquals( 740 { 741 repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}], 742 requiredGroup: {id: undefined}, 743 optionalGroup: undefined, 744 requiredSimple: {aRepeatedStringList: [], aString: undefined}, 745 optionalSimple: undefined, 746 id: undefined 747 }, 748 group.toObject()); 749 var group1 = new proto.jspb.test.TestGroup1(); 750 group1.setGroup(someGroup); 751 assertEquals(someGroup, group1.getGroup()); 752 }); 753 754 it('testNonExtensionFieldsAfterExtensionRange', function() { 755 var data = [{'1': 'a_string'}]; 756 var message = new proto.jspb.test.Complex(data); 757 assertArrayEquals([], message.getARepeatedStringList()); 758 }); 759 760 it('testReservedGetterNames', function() { 761 var message = new proto.jspb.test.TestReservedNames(); 762 message.setExtension$(11); 763 message.setExtension(proto.jspb.test.TestReservedNamesExtension.foo, 12); 764 assertEquals(11, message.getExtension$()); 765 assertEquals( 766 12, 767 message.getExtension(proto.jspb.test.TestReservedNamesExtension.foo)); 768 assertObjectEquals({extension: 11, foo: 12}, message.toObject()); 769 }); 770 771 it('testInitializeMessageWithUnsetOneof', function() { 772 var message = new proto.jspb.test.TestMessageWithOneof([]); 773 assertEquals( 774 proto.jspb.test.TestMessageWithOneof.PartialOneofCase 775 .PARTIAL_ONEOF_NOT_SET, 776 message.getPartialOneofCase()); 777 assertEquals( 778 proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase 779 .RECURSIVE_ONEOF_NOT_SET, 780 message.getRecursiveOneofCase()); 781 }); 782 783 it('testInitializeMessageWithSingleValueSetInOneof', function() { 784 var message = new proto.jspb.test.TestMessageWithOneof([, , 'x']); 785 786 assertEquals('x', message.getPone()); 787 assertEquals('', message.getPthree()); 788 assertEquals( 789 proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE, 790 message.getPartialOneofCase()); 791 }); 792 793 it('testKeepsLastWireValueSetInUnion_multipleValues', function() { 794 var message = new proto.jspb.test.TestMessageWithOneof([, , 'x', , 'y']); 795 796 assertEquals('', message.getPone()); 797 assertEquals('y', message.getPthree()); 798 assertEquals( 799 proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE, 800 message.getPartialOneofCase()); 801 }); 802 803 it('testSettingOneofFieldClearsOthers', function() { 804 var message = new proto.jspb.test.TestMessageWithOneof; 805 assertEquals('', message.getPone()); 806 assertEquals('', message.getPthree()); 807 assertFalse(message.hasPone()); 808 assertFalse(message.hasPthree()); 809 810 message.setPone('hi'); 811 assertEquals('hi', message.getPone()); 812 assertEquals('', message.getPthree()); 813 assertTrue(message.hasPone()); 814 assertFalse(message.hasPthree()); 815 816 message.setPthree('bye'); 817 assertEquals('', message.getPone()); 818 assertEquals('bye', message.getPthree()); 819 assertFalse(message.hasPone()); 820 assertTrue(message.hasPthree()); 821 }); 822 823 it('testSettingOneofFieldDoesNotClearFieldsFromOtherUnions', function() { 824 var other = new proto.jspb.test.TestMessageWithOneof; 825 var message = new proto.jspb.test.TestMessageWithOneof; 826 assertEquals('', message.getPone()); 827 assertEquals('', message.getPthree()); 828 assertUndefined(message.getRone()); 829 assertFalse(message.hasPone()); 830 assertFalse(message.hasPthree()); 831 832 message.setPone('hi'); 833 message.setRone(other); 834 assertEquals('hi', message.getPone()); 835 assertEquals('', message.getPthree()); 836 assertEquals(other, message.getRone()); 837 assertTrue(message.hasPone()); 838 assertFalse(message.hasPthree()); 839 840 message.setPthree('bye'); 841 assertEquals('', message.getPone()); 842 assertEquals('bye', message.getPthree()); 843 assertEquals(other, message.getRone()); 844 assertFalse(message.hasPone()); 845 assertTrue(message.hasPthree()); 846 }); 847 848 it('testUnsetsOneofCaseWhenFieldIsCleared', function() { 849 var message = new proto.jspb.test.TestMessageWithOneof; 850 assertEquals( 851 proto.jspb.test.TestMessageWithOneof.PartialOneofCase 852 .PARTIAL_ONEOF_NOT_SET, 853 message.getPartialOneofCase()); 854 855 message.setPone('hi'); 856 assertEquals( 857 proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE, 858 message.getPartialOneofCase()); 859 860 message.clearPone(); 861 assertEquals( 862 proto.jspb.test.TestMessageWithOneof.PartialOneofCase 863 .PARTIAL_ONEOF_NOT_SET, 864 message.getPartialOneofCase()); 865 }); 866 867 it('testMessageWithDefaultOneofValues', function() { 868 var message = new proto.jspb.test.TestMessageWithOneof; 869 assertEquals(1234, message.getAone()); 870 assertEquals(0, message.getAtwo()); 871 assertEquals( 872 proto.jspb.test.TestMessageWithOneof.DefaultOneofACase 873 .DEFAULT_ONEOF_A_NOT_SET, 874 message.getDefaultOneofACase()); 875 876 message.setAone(567); 877 assertEquals(567, message.getAone()); 878 assertEquals(0, message.getAtwo()); 879 assertEquals( 880 proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE, 881 message.getDefaultOneofACase()); 882 883 message.setAtwo(890); 884 assertEquals(1234, message.getAone()); 885 assertEquals(890, message.getAtwo()); 886 assertEquals( 887 proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO, 888 message.getDefaultOneofACase()); 889 890 message.clearAtwo(); 891 assertEquals(1234, message.getAone()); 892 assertEquals(0, message.getAtwo()); 893 assertEquals( 894 proto.jspb.test.TestMessageWithOneof.DefaultOneofACase 895 .DEFAULT_ONEOF_A_NOT_SET, 896 message.getDefaultOneofACase()); 897 }); 898 899 it('testMessageWithDefaultOneofValues_defaultNotOnFirstField', function() { 900 var message = new proto.jspb.test.TestMessageWithOneof; 901 assertEquals(0, message.getBone()); 902 assertEquals(1234, message.getBtwo()); 903 assertFalse(message.hasBone()); 904 assertFalse(message.hasBtwo()); 905 assertEquals( 906 proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase 907 .DEFAULT_ONEOF_B_NOT_SET, 908 message.getDefaultOneofBCase()); 909 910 message.setBone(2); 911 assertEquals(2, message.getBone()); 912 assertEquals(1234, message.getBtwo()); 913 assertTrue(message.hasBone()); 914 assertFalse(message.hasBtwo()); 915 assertEquals( 916 proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE, 917 message.getDefaultOneofBCase()); 918 919 message.setBtwo(3); 920 assertEquals(0, message.getBone()); 921 assertFalse(message.hasBone()); 922 assertTrue(message.hasBtwo()); 923 assertEquals(3, message.getBtwo()); 924 assertEquals( 925 proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, 926 message.getDefaultOneofBCase()); 927 928 message.clearBtwo(); 929 assertEquals(0, message.getBone()); 930 assertFalse(message.hasBone()); 931 assertFalse(message.hasBtwo()); 932 assertEquals(1234, message.getBtwo()); 933 assertEquals( 934 proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase 935 .DEFAULT_ONEOF_B_NOT_SET, 936 message.getDefaultOneofBCase()); 937 }); 938 939 it('testInitializeMessageWithOneofDefaults', function() { 940 var message = 941 new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567)); 942 assertEquals(567, message.getAone()); 943 assertEquals(0, message.getAtwo()); 944 assertEquals( 945 proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE, 946 message.getDefaultOneofACase()); 947 948 message = 949 new proto.jspb.test.TestMessageWithOneof(new Array(10).concat(890)); 950 assertEquals(1234, message.getAone()); 951 assertEquals(890, message.getAtwo()); 952 assertEquals( 953 proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO, 954 message.getDefaultOneofACase()); 955 956 message = 957 new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567, 890)); 958 assertEquals(1234, message.getAone()); 959 assertEquals(890, message.getAtwo()); 960 assertEquals( 961 proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO, 962 message.getDefaultOneofACase()); 963 }); 964 965 it('testInitializeMessageWithOneofDefaults_defaultNotSetOnFirstField', 966 function() { 967 var message; 968 969 message = 970 new proto.jspb.test.TestMessageWithOneof(new Array(11).concat(567)); 971 assertEquals(567, message.getBone()); 972 assertEquals(1234, message.getBtwo()); 973 assertEquals( 974 proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE, 975 message.getDefaultOneofBCase()); 976 977 message = 978 new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890)); 979 assertEquals(0, message.getBone()); 980 assertEquals(890, message.getBtwo()); 981 assertEquals( 982 proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, 983 message.getDefaultOneofBCase()); 984 985 message = new proto.jspb.test.TestMessageWithOneof( 986 new Array(11).concat(567, 890)); 987 assertEquals(0, message.getBone()); 988 assertEquals(890, message.getBtwo()); 989 assertEquals( 990 proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO, 991 message.getDefaultOneofBCase()); 992 }); 993 994 it('testOneofContainingAnotherMessage', function() { 995 var message = new proto.jspb.test.TestMessageWithOneof; 996 assertEquals( 997 proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase 998 .RECURSIVE_ONEOF_NOT_SET, 999 message.getRecursiveOneofCase()); 1000 1001 var other = new proto.jspb.test.TestMessageWithOneof; 1002 message.setRone(other); 1003 assertEquals(other, message.getRone()); 1004 assertEquals('', message.getRtwo()); 1005 assertEquals( 1006 proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RONE, 1007 message.getRecursiveOneofCase()); 1008 1009 message.setRtwo('hi'); 1010 assertUndefined(message.getRone()); 1011 assertEquals('hi', message.getRtwo()); 1012 assertEquals( 1013 proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RTWO, 1014 message.getRecursiveOneofCase()); 1015 }); 1016 1017 it('testQueryingOneofCaseEnsuresOnlyOneFieldIsSetInUnderlyingArray', 1018 function() { 1019 var message = new proto.jspb.test.TestMessageWithOneof; 1020 message.setPone('x'); 1021 assertEquals('x', message.getPone()); 1022 assertEquals('', message.getPthree()); 1023 assertEquals( 1024 proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE, 1025 message.getPartialOneofCase()); 1026 1027 var array = message.toArray(); 1028 assertEquals('x', array[2]); 1029 assertUndefined(array[4]); 1030 array[4] = 'y'; 1031 1032 assertEquals( 1033 proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE, 1034 message.getPartialOneofCase()); 1035 assertUndefined(array[2]); 1036 assertEquals('y', array[4]); 1037 }); 1038 1039 it('testFloatingPointFieldsSupportNan', function() { 1040 var assertNan = function(x) { 1041 assertTrue( 1042 'Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.', 1043 typeof x === 'number' && isNaN(x)); 1044 }; 1045 1046 var message = new proto.jspb.test.FloatingPointFields([ 1047 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN', 'NaN', 'NaN', ['NaN', 'NaN'], 'NaN' 1048 ]); 1049 assertNan(message.getOptionalFloatField()); 1050 assertNan(message.getRequiredFloatField()); 1051 assertNan(message.getRepeatedFloatFieldList()[0]); 1052 assertNan(message.getRepeatedFloatFieldList()[1]); 1053 assertNan(message.getDefaultFloatField()); 1054 assertNan(message.getOptionalDoubleField()); 1055 assertNan(message.getRequiredDoubleField()); 1056 assertNan(message.getRepeatedDoubleFieldList()[0]); 1057 assertNan(message.getRepeatedDoubleFieldList()[1]); 1058 assertNan(message.getDefaultDoubleField()); 1059 }); 1060}); 1061