OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 // Dart test program for testing serialization of messages. |
| 6 // VMOptions=--enable_type_checks --enable_asserts |
| 7 |
| 8 library MessageTest; |
| 9 import 'dart:async'; |
| 10 import 'dart:collection'; |
| 11 import 'dart:isolate'; |
| 12 import 'package:async_helper/async_helper.dart'; |
| 13 import 'package:expect/expect.dart'; |
| 14 import 'dart:typed_data'; |
| 15 |
| 16 void echoMain(msg) { |
| 17 SendPort replyTo = msg[0]; |
| 18 SendPort pong = msg[1]; |
| 19 ReceivePort port = new ReceivePort(); |
| 20 replyTo.send(port.sendPort); |
| 21 port.listen((msg) { |
| 22 if (msg == "halt") { |
| 23 port.close(); |
| 24 } else { |
| 25 pong.send(msg); |
| 26 } |
| 27 }); |
| 28 } |
| 29 |
| 30 class A { |
| 31 var field = 499; |
| 32 |
| 33 A(); |
| 34 A.named(this.field); |
| 35 } |
| 36 |
| 37 class B extends A { |
| 38 final field2; |
| 39 B() : field2 = 99; |
| 40 B.named(this.field2, x) : super.named(x); |
| 41 } |
| 42 |
| 43 class C extends B { |
| 44 var field = 33; |
| 45 |
| 46 get superField => super.field; |
| 47 get superField2 => super.field2; |
| 48 } |
| 49 |
| 50 class M { |
| 51 get field2 => 11; |
| 52 } |
| 53 |
| 54 class D extends C with M { |
| 55 var gee = 123; |
| 56 } |
| 57 |
| 58 class E { |
| 59 Function fun; |
| 60 E(this.fun); |
| 61 |
| 62 static fooFun() => 499; |
| 63 instanceFun() => 1234; |
| 64 } |
| 65 barFun() => 42; |
| 66 |
| 67 class F { |
| 68 final field = "field"; |
| 69 const F(); |
| 70 } |
| 71 |
| 72 class G { |
| 73 final field; |
| 74 const G(this.field); |
| 75 } |
| 76 |
| 77 class Value { |
| 78 final val; |
| 79 Value(this.val); |
| 80 |
| 81 operator==(other) { |
| 82 if (other is! Value) return false; |
| 83 return other.val == val; |
| 84 } |
| 85 |
| 86 get hashCode => val; |
| 87 } |
| 88 |
| 89 void runTests(SendPort ping, Queue checks) { |
| 90 ping.send("abc"); |
| 91 checks.add((x) => Expect.equals("abc", x)); |
| 92 |
| 93 ping.send([1, 2]); |
| 94 checks.add((x) { |
| 95 Expect.isTrue(x is List); |
| 96 Expect.listEquals([1, 2], x); |
| 97 // Make sure the list is mutable. |
| 98 x[0] = 0; |
| 99 Expect.equals(0, x[0]); |
| 100 // List must be extendable. |
| 101 x.add(3); |
| 102 Expect.equals(3, x[2]); |
| 103 }); |
| 104 |
| 105 List fixed = new List(2); |
| 106 fixed[0] = 0; |
| 107 fixed[1] = 1; |
| 108 ping.send(fixed); |
| 109 checks.add((x) { |
| 110 Expect.isTrue(x is List); |
| 111 Expect.listEquals([0, 1], x); |
| 112 // List must be mutable. |
| 113 x[0] = 3; |
| 114 Expect.equals(3, x[0]); |
| 115 // List must be fixed length. |
| 116 Expect.throws(() { x.add(5); }); |
| 117 }); |
| 118 |
| 119 List cyclic = []; |
| 120 cyclic.add(cyclic); |
| 121 ping.send(cyclic); |
| 122 checks.add((x) { |
| 123 Expect.isTrue(x is List); |
| 124 Expect.equals(1, x.length); |
| 125 Expect.identical(x, x[0]); |
| 126 // List must be mutable. |
| 127 x[0] = 55; |
| 128 Expect.equals(55, x[0]); |
| 129 // List must be extendable. |
| 130 x.add(42); |
| 131 Expect.equals(42, x[1]); |
| 132 }); |
| 133 |
| 134 List cyclic2 = new List(1); |
| 135 cyclic2[0] = cyclic2; |
| 136 ping.send(cyclic2); |
| 137 checks.add((x) { |
| 138 Expect.isTrue(x is List); |
| 139 Expect.equals(1, x.length); |
| 140 Expect.identical(x, x[0]); |
| 141 // List must be mutable. |
| 142 x[0] = 55; |
| 143 Expect.equals(55, x[0]); |
| 144 // List must be fixed. |
| 145 Expect.throws(() => x.add(42)); |
| 146 }); |
| 147 |
| 148 List constList = const [1, 2]; |
| 149 ping.send(constList); |
| 150 checks.add((x) { |
| 151 Expect.isTrue(x is List); |
| 152 Expect.listEquals([1, 2], x); |
| 153 // Make sure the list is immutable. |
| 154 Expect.throws(() => x[0] = 0); /// constList: ok |
| 155 // List must not be extendable. |
| 156 Expect.throws(() => x.add(3)); |
| 157 Expect.identical(x, constList); /// constList_identical: ok |
| 158 }); |
| 159 |
| 160 Uint8List uint8 = new Uint8List(2); |
| 161 uint8[0] = 0; |
| 162 uint8[1] = 1; |
| 163 ping.send(uint8); |
| 164 checks.add((x) { |
| 165 Expect.isTrue(x is Uint8List); |
| 166 Expect.equals(2, x.length); |
| 167 Expect.equals(0, x[0]); |
| 168 Expect.equals(1, x[1]); |
| 169 }); |
| 170 |
| 171 Uint16List uint16 = new Uint16List(2); |
| 172 uint16[0] = 0; |
| 173 uint16[1] = 1; |
| 174 ByteBuffer byteBuffer = uint16.buffer; |
| 175 ping.send(byteBuffer); /// byteBuffer: ok |
| 176 checks.add( /// byteBuffer: ok |
| 177 (x) { |
| 178 Expect.isTrue(x is ByteBuffer); |
| 179 Uint16List uint16View = new Uint16List.view(x); |
| 180 Expect.equals(2, uint16View.length); |
| 181 Expect.equals(0, uint16View[0]); |
| 182 Expect.equals(1, uint16View[1]); |
| 183 } |
| 184 ) /// byteBuffer: ok |
| 185 ; |
| 186 |
| 187 Int32x4List list32x4 = new Int32x4List(2); |
| 188 list32x4[0] = new Int32x4(1, 2, 3, 4); |
| 189 list32x4[1] = new Int32x4(5, 6, 7, 8); |
| 190 ping.send(list32x4); /// int32x4: ok |
| 191 checks.add( /// int32x4: ok |
| 192 (x) { |
| 193 Expect.isTrue(x is Int32x4List); |
| 194 Expect.equals(2, x.length); |
| 195 Int32x4 entry1 = x[0]; |
| 196 Int32x4 entry2 = x[1]; |
| 197 Expect.equals(1, entry1.x); |
| 198 Expect.equals(2, entry1.y); |
| 199 Expect.equals(3, entry1.z); |
| 200 Expect.equals(4, entry1.w); |
| 201 Expect.equals(5, entry2.x); |
| 202 Expect.equals(6, entry2.y); |
| 203 Expect.equals(7, entry2.z); |
| 204 Expect.equals(8, entry2.w); |
| 205 } |
| 206 ) /// int32x4: ok |
| 207 ; |
| 208 |
| 209 ping.send({"foo": 499, "bar": 32}); |
| 210 checks.add((x) { |
| 211 Expect.isTrue(x is LinkedHashMap); |
| 212 Expect.listEquals(["foo", "bar"], x.keys.toList()); |
| 213 Expect.listEquals([499, 32], x.values.toList()); |
| 214 // Must be mutable. |
| 215 x["foo"] = 22; |
| 216 Expect.equals(22, x["foo"]); |
| 217 // Must be extendable. |
| 218 x["gee"] = 499; |
| 219 Expect.equals(499, x["gee"]); |
| 220 }); |
| 221 |
| 222 ping.send({0: 499, 1: 32}); |
| 223 checks.add((x) { |
| 224 Expect.isTrue(x is LinkedHashMap); |
| 225 Expect.listEquals([0, 1], x.keys.toList()); |
| 226 Expect.listEquals([499, 32], x.values.toList()); |
| 227 // Must be mutable. |
| 228 x[0] = 22; |
| 229 Expect.equals(22, x[0]); |
| 230 // Must be extendable. |
| 231 x["gee"] = 499; |
| 232 Expect.equals(499, x["gee"]); |
| 233 }); |
| 234 |
| 235 Map cyclicMap = {}; |
| 236 cyclicMap["cycle"] = cyclicMap; |
| 237 ping.send(cyclicMap); |
| 238 checks.add((x) { |
| 239 Expect.isTrue(x is LinkedHashMap); |
| 240 Expect.identical(x, x["cycle"]); |
| 241 // Must be mutable. |
| 242 x["cycle"] = 22; |
| 243 Expect.equals(22, x["cycle"]); |
| 244 // Must be extendable. |
| 245 x["gee"] = 499; |
| 246 Expect.equals(499, x["gee"]); |
| 247 }); |
| 248 |
| 249 Map constMap = const {'foo': 499}; |
| 250 ping.send(constMap); |
| 251 checks.add((x) { |
| 252 Expect.isTrue(x is Map); |
| 253 print(x.length); |
| 254 Expect.equals(1, x.length); |
| 255 Expect.equals(499, x['foo']); |
| 256 Expect.identical(constMap, x); /// constMap: ok |
| 257 Expect.throws(() => constMap['bar'] = 42); |
| 258 }); |
| 259 |
| 260 ping.send(new A()); |
| 261 checks.add((x) { |
| 262 Expect.isTrue(x is A); |
| 263 Expect.equals(499, x.field); |
| 264 }); |
| 265 |
| 266 ping.send(new A.named(42)); |
| 267 checks.add((x) { |
| 268 Expect.isTrue(x is A); |
| 269 Expect.equals(42, x.field); |
| 270 }); |
| 271 |
| 272 ping.send(new B()); |
| 273 checks.add((x) { |
| 274 Expect.isTrue(x is A); |
| 275 Expect.isTrue(x is B); |
| 276 Expect.equals(499, x.field); |
| 277 Expect.equals(99, x.field2); |
| 278 Expect.throws(() => x.field2 = 22); |
| 279 }); |
| 280 |
| 281 ping.send(new B.named(1, 2)); |
| 282 checks.add((x) { |
| 283 Expect.isTrue(x is A); |
| 284 Expect.isTrue(x is B); |
| 285 Expect.equals(2, x.field); |
| 286 Expect.equals(1, x.field2); |
| 287 Expect.throws(() => x.field2 = 22); |
| 288 }); |
| 289 |
| 290 ping.send(new C()); |
| 291 checks.add((x) { |
| 292 Expect.isTrue(x is A); |
| 293 Expect.isTrue(x is B); |
| 294 Expect.isTrue(x is C); |
| 295 Expect.equals(33, x.field); |
| 296 Expect.equals(99, x.field2); |
| 297 Expect.equals(499, x.superField); |
| 298 Expect.throws(() => x.field2 = 22); |
| 299 }); |
| 300 |
| 301 ping.send(new D()); |
| 302 checks.add((x) { |
| 303 Expect.isTrue(x is A); |
| 304 Expect.isTrue(x is B); |
| 305 Expect.isTrue(x is C); |
| 306 Expect.isTrue(x is D); |
| 307 Expect.isTrue(x is M); |
| 308 Expect.equals(33, x.field); |
| 309 Expect.equals(11, x.field2); |
| 310 Expect.equals(499, x.superField); |
| 311 Expect.equals(99, x.superField2); |
| 312 Expect.throws(() => x.field2 = 22); |
| 313 }); |
| 314 |
| 315 D cyclicD = new D(); |
| 316 cyclicD.field = cyclicD; |
| 317 ping.send(cyclicD); |
| 318 checks.add((x) { |
| 319 Expect.isTrue(x is A); |
| 320 Expect.isTrue(x is B); |
| 321 Expect.isTrue(x is C); |
| 322 Expect.isTrue(x is D); |
| 323 Expect.isTrue(x is M); |
| 324 Expect.identical(x, x.field); |
| 325 Expect.equals(11, x.field2); |
| 326 Expect.equals(499, x.superField); |
| 327 Expect.equals(99, x.superField2); |
| 328 Expect.throws(() => x.field2 = 22); |
| 329 }); |
| 330 |
| 331 ping.send(new E(E.fooFun)); /// fun: ok |
| 332 checks.add((x) { /// fun: continued |
| 333 Expect.equals(E.fooFun, x.fun); /// fun: continued |
| 334 Expect.equals(499, x.fun()); /// fun: continued |
| 335 }); /// fun: continued |
| 336 |
| 337 ping.send(new E(barFun)); /// fun: continued |
| 338 checks.add((x) { /// fun: continued |
| 339 Expect.equals(barFun, x.fun); /// fun: continued |
| 340 Expect.equals(42, x.fun()); /// fun: continued |
| 341 }); /// fun: continued |
| 342 |
| 343 Expect.throws(() => ping.send(new E(new E(null).instanceFun))); |
| 344 |
| 345 F nonConstF = new F(); |
| 346 ping.send(nonConstF); |
| 347 checks.add((x) { |
| 348 Expect.equals("field", x.field); |
| 349 Expect.isFalse(identical(nonConstF, x)); |
| 350 }); |
| 351 |
| 352 const F constF = const F(); |
| 353 ping.send(constF); |
| 354 checks.add((x) { |
| 355 Expect.equals("field", x.field); |
| 356 Expect.identical(constF, x); /// constInstance: ok |
| 357 }); |
| 358 |
| 359 G g1 = new G(nonConstF); |
| 360 G g2 = new G(constF); |
| 361 G g3 = const G(constF); |
| 362 ping.send(g1); |
| 363 ping.send(g2); |
| 364 ping.send(g3); |
| 365 |
| 366 checks.add((x) { // g1. |
| 367 Expect.isTrue(x is G); |
| 368 Expect.isFalse(identical(g1, x)); |
| 369 F f = x.field; |
| 370 Expect.equals("field", f.field); |
| 371 Expect.isFalse(identical(nonConstF, f)); |
| 372 }); |
| 373 checks.add((x) { // g1. |
| 374 Expect.isTrue(x is G); |
| 375 Expect.isFalse(identical(g1, x)); |
| 376 F f = x.field; |
| 377 Expect.equals("field", f.field); |
| 378 Expect.identical(constF, f); /// constInstance: continued |
| 379 }); |
| 380 checks.add((x) { // g3. |
| 381 Expect.isTrue(x is G); |
| 382 Expect.identical(g1, x); /// constInstance: continued |
| 383 F f = x.field; |
| 384 Expect.equals("field", f.field); |
| 385 Expect.identical(constF, f); /// constInstance: continued |
| 386 }); |
| 387 |
| 388 // Make sure objects in a map are serialized and deserialized in the correct |
| 389 // order. |
| 390 Map m = new Map(); |
| 391 Value val1 = new Value(1); |
| 392 Value val2 = new Value(2); |
| 393 m[val1] = val2; |
| 394 m[val2] = val1; |
| 395 // Possible bug we want to catch: |
| 396 // serializer runs through keys first, and then the values: |
| 397 // - id1 = val1, id2 = val2, ref[id2], ref[id1] |
| 398 // deserializer runs through the keys and values in order: |
| 399 // - val1; // id1. |
| 400 // - ref[id2]; // boom. Wasn't deserialized yet. |
| 401 ping.send(m); |
| 402 checks.add((x) { |
| 403 Expect.isTrue(x is Map); |
| 404 Expect.equals(2, x.length); |
| 405 Expect.equals(val2, x[val1]); |
| 406 Expect.equals(val1, x[val2]); |
| 407 Expect.identical(x.keys.elementAt(0), x.values.elementAt(1)); |
| 408 Expect.identical(x.keys.elementAt(1), x.values.elementAt(0)); |
| 409 }); |
| 410 } |
| 411 |
| 412 void main() { |
| 413 asyncStart(); |
| 414 Queue checks = new Queue(); |
| 415 ReceivePort testPort = new ReceivePort(); |
| 416 Completer completer = new Completer(); |
| 417 |
| 418 testPort.listen((msg) { |
| 419 Function check = checks.removeFirst(); |
| 420 check(msg); |
| 421 if (checks.isEmpty) { |
| 422 completer.complete(); |
| 423 testPort.close(); |
| 424 } |
| 425 }); |
| 426 |
| 427 ReceivePort initialReplyPort = new ReceivePort(); |
| 428 Isolate |
| 429 .spawn(echoMain, [initialReplyPort.sendPort, testPort.sendPort]) |
| 430 .then((_) => initialReplyPort.first) |
| 431 .then((SendPort ping) { |
| 432 runTests(ping, checks); |
| 433 Expect.isTrue(checks.length > 0); |
| 434 completer.future |
| 435 .then((_) => ping.send("halt")) |
| 436 .then((_) => asyncEnd()); |
| 437 }); |
| 438 } |
OLD | NEW |