OLD | NEW |
| (Empty) |
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 goog.require('goog.testing.asserts'); | |
32 goog.require('goog.userAgent'); | |
33 | |
34 // CommonJS-LoadFromFile: testbinary_pb proto.jspb.test | |
35 goog.require('proto.jspb.test.MapValueEnum'); | |
36 goog.require('proto.jspb.test.MapValueMessage'); | |
37 goog.require('proto.jspb.test.TestMapFields'); | |
38 | |
39 // CommonJS-LoadFromFile: test_pb proto.jspb.test | |
40 goog.require('proto.jspb.test.MapValueMessageNoBinary'); | |
41 goog.require('proto.jspb.test.TestMapFieldsNoBinary'); | |
42 | |
43 /** | |
44 * Helper: check that the given map has exactly this set of (sorted) entries. | |
45 * @param {!jspb.Map} map | |
46 * @param {!Array<!Array<?>>} entries | |
47 */ | |
48 function checkMapEquals(map, entries) { | |
49 var arr = map.toArray(); | |
50 assertEquals(arr.length, entries.length); | |
51 for (var i = 0; i < arr.length; i++) { | |
52 assertElementsEquals(arr[i], entries[i]); | |
53 } | |
54 } | |
55 | |
56 /** | |
57 * Converts an ES6 iterator to an array. | |
58 * @template T | |
59 * @param {!Iterator<T>} iter an iterator | |
60 * @return {!Array<T>} | |
61 */ | |
62 function toArray(iter) { | |
63 var arr = []; | |
64 while (true) { | |
65 var val = iter.next(); | |
66 if (val.done) { | |
67 break; | |
68 } | |
69 arr.push(val.value); | |
70 } | |
71 return arr; | |
72 } | |
73 | |
74 | |
75 /** | |
76 * Helper: generate test methods for this TestMapFields class. | |
77 * @param {?} msgInfo | |
78 * @param {?} submessageCtor | |
79 * @param {!string} suffix | |
80 */ | |
81 function makeTests(msgInfo, submessageCtor, suffix) { | |
82 /** | |
83 * Helper: fill all maps on a TestMapFields. | |
84 * @param {?} msg | |
85 */ | |
86 var fillMapFields = function(msg) { | |
87 msg.getMapStringStringMap().set('asdf', 'jkl;').set('key 2', 'hello world'); | |
88 msg.getMapStringInt32Map().set('a', 1).set('b', -2); | |
89 msg.getMapStringInt64Map().set('c', 0x100000000).set('d', 0x200000000); | |
90 msg.getMapStringBoolMap().set('e', true).set('f', false); | |
91 msg.getMapStringDoubleMap().set('g', 3.14159).set('h', 2.71828); | |
92 msg.getMapStringEnumMap() | |
93 .set('i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR) | |
94 .set('j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ); | |
95 msg.getMapStringMsgMap() | |
96 .set('k', new submessageCtor()) | |
97 .set('l', new submessageCtor()); | |
98 msg.getMapStringMsgMap().get('k').setFoo(42); | |
99 msg.getMapStringMsgMap().get('l').setFoo(84); | |
100 msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b'); | |
101 msg.getMapInt64StringMap().set(0x123456789abc, 'c').set(0xcba987654321, 'd')
; | |
102 msg.getMapBoolStringMap().set(false, 'e').set(true, 'f'); | |
103 }; | |
104 | |
105 /** | |
106 * Helper: check all maps on a TestMapFields. | |
107 * @param {?} msg | |
108 */ | |
109 var checkMapFields = function(msg) { | |
110 checkMapEquals(msg.getMapStringStringMap(), [ | |
111 ['asdf', 'jkl;'], | |
112 ['key 2', 'hello world'] | |
113 ]); | |
114 checkMapEquals(msg.getMapStringInt32Map(), [ | |
115 ['a', 1], | |
116 ['b', -2] | |
117 ]); | |
118 checkMapEquals(msg.getMapStringInt64Map(), [ | |
119 ['c', 0x100000000], | |
120 ['d', 0x200000000] | |
121 ]); | |
122 checkMapEquals(msg.getMapStringBoolMap(), [ | |
123 ['e', true], | |
124 ['f', false] | |
125 ]); | |
126 checkMapEquals(msg.getMapStringDoubleMap(), [ | |
127 ['g', 3.14159], | |
128 ['h', 2.71828] | |
129 ]); | |
130 checkMapEquals(msg.getMapStringEnumMap(), [ | |
131 ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR], | |
132 ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ] | |
133 ]); | |
134 checkMapEquals(msg.getMapInt32StringMap(), [ | |
135 [-1, 'a'], | |
136 [42, 'b'] | |
137 ]); | |
138 checkMapEquals(msg.getMapInt64StringMap(), [ | |
139 [0x123456789abc, 'c'], | |
140 [0xcba987654321, 'd'] | |
141 ]); | |
142 checkMapEquals(msg.getMapBoolStringMap(), [ | |
143 [false, 'e'], | |
144 [true, 'f'] | |
145 ]); | |
146 | |
147 assertEquals(msg.getMapStringMsgMap().getLength(), 2); | |
148 assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42); | |
149 assertEquals(msg.getMapStringMsgMap().get('l').getFoo(), 84); | |
150 | |
151 var entries = toArray(msg.getMapStringMsgMap().entries()); | |
152 assertEquals(entries.length, 2); | |
153 entries.forEach(function(entry) { | |
154 var key = entry[0]; | |
155 var val = entry[1]; | |
156 assert(val === msg.getMapStringMsgMap().get(key)); | |
157 }); | |
158 | |
159 msg.getMapStringMsgMap().forEach(function(val, key) { | |
160 assert(val === msg.getMapStringMsgMap().get(key)); | |
161 }); | |
162 }; | |
163 | |
164 it('testMapStringStringField' + suffix, function() { | |
165 var msg = new msgInfo.constructor(); | |
166 assertEquals(msg.getMapStringStringMap().getLength(), 0); | |
167 assertEquals(msg.getMapStringInt32Map().getLength(), 0); | |
168 assertEquals(msg.getMapStringInt64Map().getLength(), 0); | |
169 assertEquals(msg.getMapStringBoolMap().getLength(), 0); | |
170 assertEquals(msg.getMapStringDoubleMap().getLength(), 0); | |
171 assertEquals(msg.getMapStringEnumMap().getLength(), 0); | |
172 assertEquals(msg.getMapStringMsgMap().getLength(), 0); | |
173 | |
174 // Re-create to clear out any internally-cached wrappers, etc. | |
175 msg = new msgInfo.constructor(); | |
176 var m = msg.getMapStringStringMap(); | |
177 assertEquals(m.has('asdf'), false); | |
178 assertEquals(m.get('asdf'), undefined); | |
179 m.set('asdf', 'hello world'); | |
180 assertEquals(m.has('asdf'), true); | |
181 assertEquals(m.get('asdf'), 'hello world'); | |
182 m.set('jkl;', 'key 2'); | |
183 assertEquals(m.has('jkl;'), true); | |
184 assertEquals(m.get('jkl;'), 'key 2'); | |
185 assertEquals(m.getLength(), 2); | |
186 var it = m.entries(); | |
187 assertElementsEquals(it.next().value, ['asdf', 'hello world']); | |
188 assertElementsEquals(it.next().value, ['jkl;', 'key 2']); | |
189 assertEquals(it.next().done, true); | |
190 checkMapEquals(m, [ | |
191 ['asdf', 'hello world'], | |
192 ['jkl;', 'key 2'] | |
193 ]); | |
194 m.del('jkl;'); | |
195 assertEquals(m.has('jkl;'), false); | |
196 assertEquals(m.get('jkl;'), undefined); | |
197 assertEquals(m.getLength(), 1); | |
198 it = m.keys(); | |
199 assertEquals(it.next().value, 'asdf'); | |
200 assertEquals(it.next().done, true); | |
201 it = m.values(); | |
202 assertEquals(it.next().value, 'hello world'); | |
203 assertEquals(it.next().done, true); | |
204 | |
205 var count = 0; | |
206 m.forEach(function(value, key, map) { | |
207 assertEquals(map, m); | |
208 assertEquals(key, 'asdf'); | |
209 assertEquals(value, 'hello world'); | |
210 count++; | |
211 }); | |
212 assertEquals(count, 1); | |
213 | |
214 m.clear(); | |
215 assertEquals(m.getLength(), 0); | |
216 }); | |
217 | |
218 | |
219 /** | |
220 * Tests operations on maps with all key and value types. | |
221 */ | |
222 it('testAllMapTypes' + suffix, function() { | |
223 var msg = new msgInfo.constructor(); | |
224 fillMapFields(msg); | |
225 checkMapFields(msg); | |
226 }); | |
227 | |
228 | |
229 if (msgInfo.deserializeBinary) { | |
230 /** | |
231 * Tests serialization and deserialization in binary format. | |
232 */ | |
233 it('testBinaryFormat' + suffix, function() { | |
234 if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) { | |
235 // IE8/9 currently doesn't support binary format because they lack | |
236 // TypedArray. | |
237 return; | |
238 } | |
239 | |
240 // Check that the format is correct. | |
241 var msg = new msgInfo.constructor(); | |
242 msg.getMapStringStringMap().set('A', 'a'); | |
243 var serialized = msg.serializeBinary(); | |
244 var expectedSerialized = [ | |
245 0x0a, 0x6, // field 1 (map_string_string), delimited, length 6 | |
246 0x0a, 0x1, // field 1 in submessage (key), delimited, length 1 | |
247 0x41, // ASCII 'A' | |
248 0x12, 0x1, // field 2 in submessage (value), delimited, length 1 | |
249 0x61 // ASCII 'a' | |
250 ]; | |
251 assertEquals(serialized.length, expectedSerialized.length); | |
252 for (var i = 0; i < serialized.length; i++) { | |
253 assertEquals(serialized[i], expectedSerialized[i]); | |
254 } | |
255 | |
256 // Check that all map fields successfully round-trip. | |
257 msg = new msgInfo.constructor(); | |
258 fillMapFields(msg); | |
259 serialized = msg.serializeBinary(); | |
260 var decoded = msgInfo.deserializeBinary(serialized); | |
261 checkMapFields(decoded); | |
262 }); | |
263 } | |
264 | |
265 | |
266 /** | |
267 * Exercises the lazy map<->underlying array sync. | |
268 */ | |
269 it('testLazyMapSync' + suffix, function() { | |
270 // Start with a JSPB array containing a few map entries. | |
271 var entries = [ | |
272 ['a', 'entry 1'], | |
273 ['c', 'entry 2'], | |
274 ['b', 'entry 3'] | |
275 ]; | |
276 var msg = new msgInfo.constructor([entries]); | |
277 assertEquals(entries.length, 3); | |
278 assertEquals(entries[0][0], 'a'); | |
279 assertEquals(entries[1][0], 'c'); | |
280 assertEquals(entries[2][0], 'b'); | |
281 msg.getMapStringStringMap().del('a'); | |
282 assertEquals(entries.length, 3); // not yet sync'd | |
283 msg.toArray(); // force a sync | |
284 assertEquals(entries.length, 2); | |
285 assertEquals(entries[0][0], 'b'); // now in sorted order | |
286 assertEquals(entries[1][0], 'c'); | |
287 | |
288 var a = msg.toArray(); | |
289 assertEquals(a[0], entries); // retains original reference | |
290 }); | |
291 } | |
292 | |
293 describe('mapsTest', function() { | |
294 makeTests( | |
295 { | |
296 constructor: proto.jspb.test.TestMapFields, | |
297 deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary | |
298 }, | |
299 proto.jspb.test.MapValueMessage, '_Binary'); | |
300 makeTests( | |
301 { | |
302 constructor: proto.jspb.test.TestMapFieldsNoBinary, | |
303 deserializeBinary: null | |
304 }, | |
305 proto.jspb.test.MapValueMessageNoBinary, '_NoBinary'); | |
306 }); | |
OLD | NEW |