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