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 |