Files
sdk/tests/isolate/message3_test.dart
T
Siva Annamalai 4ba69c4df5 Fixes for some strong mode issues in the isolate tests. Not able to turn
these tests on by default yet because of an issue in the stacktrace
package (see issue 31764)

Change-Id: Ifeb5dc4fc85e7d83b3011948133ce6d2a1998248
Reviewed-on: https://dart-review.googlesource.com/29480
Commit-Queue: Siva Annamalai <asiva@google.com>
Reviewed-by: Régis Crelier <regis@google.com>
2018-01-05 06:19:33 +00:00

469 lines
12 KiB
Dart

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Dart test program for testing serialization of messages.
// VMOptions=--enable_type_checks --enable_asserts
library MessageTest;
import 'dart:async';
import 'dart:collection';
import 'dart:isolate';
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
import 'dart:typed_data';
void echoMain(msg) {
SendPort replyTo = msg[0];
SendPort pong = msg[1];
ReceivePort port = new ReceivePort();
replyTo.send(port.sendPort);
port.listen((msg) {
if (msg == "halt") {
port.close();
} else {
pong.send(msg);
}
});
}
class A {
var field = 499;
A();
A.named(this.field);
}
class B extends A {
final field2;
B() : field2 = 99;
B.named(this.field2, x) : super.named(x);
}
class C extends B {
dynamic field = 33;
get superField => super.field;
get superField2 => super.field2;
}
class M {
get field2 => 11;
}
class D extends C with M {
var gee = 123;
}
class E {
Function fun;
E(this.fun);
static fooFun() => 499;
instanceFun() => 1234;
}
barFun() => 42;
class F {
final field = "field";
const F();
}
class G {
final field;
const G(this.field);
}
class Value {
final val;
Value(this.val);
operator ==(other) {
if (other is! Value) return false;
return other.val == val;
}
get hashCode => val;
}
void runTests(SendPort ping, Queue checks) {
ping.send("abc");
checks.add((x) => Expect.equals("abc", x));
ping.send([1, 2]);
checks.add((x) {
Expect.isTrue(x is List);
Expect.listEquals([1, 2], x);
// Make sure the list is mutable.
x[0] = 0;
Expect.equals(0, x[0]);
// List must be extendable.
x.add(3);
Expect.equals(3, x[2]);
});
List fixed = new List(2);
fixed[0] = 0;
fixed[1] = 1;
ping.send(fixed);
checks.add((x) {
Expect.isTrue(x is List);
Expect.listEquals([0, 1], x);
// List must be mutable.
x[0] = 3;
Expect.equals(3, x[0]);
// List must be fixed length.
Expect.throws(() {
x.add(5);
});
});
List cyclic = [];
cyclic.add(cyclic);
ping.send(cyclic);
checks.add((x) {
Expect.isTrue(x is List);
Expect.equals(1, x.length);
Expect.identical(x, x[0]);
// List must be mutable.
x[0] = 55;
Expect.equals(55, x[0]);
// List must be extendable.
x.add(42);
Expect.equals(42, x[1]);
});
List cyclic2 = new List(1);
cyclic2[0] = cyclic2;
ping.send(cyclic2);
checks.add((x) {
Expect.isTrue(x is List);
Expect.equals(1, x.length);
Expect.identical(x, x[0]);
// List must be mutable.
x[0] = 55;
Expect.equals(55, x[0]);
// List must be fixed.
Expect.throws(() => x.add(42));
});
List constList = const [1, 2];
ping.send(constList);
checks.add((x) {
Expect.isTrue(x is List);
Expect.listEquals([1, 2], x);
// Make sure the list is immutable.
Expect.throws(() => x[0] = 0); // //# constList: ok
// List must not be extendable.
Expect.throws(() => x.add(3));
Expect.identical(x, constList); // //# constList_identical: ok
});
Uint8List uint8 = new Uint8List(2);
uint8[0] = 0;
uint8[1] = 1;
ping.send(uint8);
checks.add((x) {
Expect.isTrue(x is Uint8List);
Expect.equals(2, x.length);
Expect.equals(0, x[0]);
Expect.equals(1, x[1]);
});
Uint16List uint16 = new Uint16List(2);
uint16[0] = 0;
uint16[1] = 1;
ByteBuffer byteBuffer = uint16.buffer;
ping.send(byteBuffer); // //# byteBuffer: ok
checks.add( // //# byteBuffer: ok
(x) {
Expect.isTrue(x is ByteBuffer);
Uint16List uint16View = new Uint16List.view(x);
Expect.equals(2, uint16View.length);
Expect.equals(0, uint16View[0]);
Expect.equals(1, uint16View[1]);
}
) // //# byteBuffer: ok
;
Int32x4List list32x4 = new Int32x4List(2);
list32x4[0] = new Int32x4(1, 2, 3, 4);
list32x4[1] = new Int32x4(5, 6, 7, 8);
ping.send(list32x4); // //# int32x4: ok
checks.add( // //# int32x4: ok
(x) {
Expect.isTrue(x is Int32x4List);
Expect.equals(2, x.length);
Int32x4 entry1 = x[0];
Int32x4 entry2 = x[1];
Expect.equals(1, entry1.x);
Expect.equals(2, entry1.y);
Expect.equals(3, entry1.z);
Expect.equals(4, entry1.w);
Expect.equals(5, entry2.x);
Expect.equals(6, entry2.y);
Expect.equals(7, entry2.z);
Expect.equals(8, entry2.w);
}
) // //# int32x4: ok
;
ping.send({"foo": 499, "bar": 32});
checks.add((x) {
Expect.isTrue(x is LinkedHashMap);
Expect.listEquals(["foo", "bar"], x.keys.toList());
Expect.listEquals([499, 32], x.values.toList());
Expect.equals(499, x["foo"]);
Expect.equals(32, x["bar"]);
// Must be mutable.
x["foo"] = 22;
Expect.equals(22, x["foo"]);
// Must be extendable.
x["gee"] = 499;
Expect.equals(499, x["gee"]);
});
Map<String, int> mapWithRemovedKey = {"foo": 499, "bar": 32};
mapWithRemovedKey.remove("foo");
ping.send(mapWithRemovedKey);
checks.add((x) {
Expect.isTrue(x is LinkedHashMap);
Expect.listEquals(["bar"], x.keys.toList());
Expect.listEquals([32], x.values.toList());
Expect.equals(32, x["bar"]);
});
// Test map where a key does not define ==/hashCode.
Map<A, int> mapWithIdentityKey = new Map<A, int>();
mapWithIdentityKey[new A()] = 499;
ping.send(mapWithIdentityKey);
checks.add((x) {
Expect.isTrue(x is LinkedHashMap);
int value = x.values.first;
Expect.equals(499, value);
A key = x.keys.first;
Expect.equals(499, x[key]);
});
ping.send({0: 499, 1: 32});
checks.add((x) {
Expect.isTrue(x is LinkedHashMap);
Expect.listEquals([0, 1], x.keys.toList());
Expect.listEquals([499, 32], x.values.toList());
// Must be mutable.
x[0] = 22;
Expect.equals(22, x[0]);
// Must be extendable.
x["gee"] = 499;
Expect.equals(499, x["gee"]);
});
Map cyclicMap = {};
cyclicMap["cycle"] = cyclicMap;
ping.send(cyclicMap);
checks.add((x) {
Expect.isTrue(x is LinkedHashMap);
Expect.identical(x, x["cycle"]);
// Must be mutable.
x["cycle"] = 22;
Expect.equals(22, x["cycle"]);
// Must be extendable.
x["gee"] = 499;
Expect.equals(499, x["gee"]);
});
Map constMap = const {'foo': 499};
ping.send(constMap);
checks.add((x) {
Expect.isTrue(x is Map);
print(x.length);
Expect.equals(1, x.length);
Expect.equals(499, x['foo']);
Expect.identical(constMap, x); // //# constMap: ok
Expect.throws(() => constMap['bar'] = 42);
});
ping.send(new A());
checks.add((x) {
Expect.isTrue(x is A);
Expect.equals(499, x.field);
});
ping.send(new A.named(42));
checks.add((x) {
Expect.isTrue(x is A);
Expect.equals(42, x.field);
});
ping.send(new B());
checks.add((x) {
Expect.isTrue(x is A);
Expect.isTrue(x is B);
Expect.equals(499, x.field);
Expect.equals(99, x.field2);
Expect.throws(() => x.field2 = 22);
});
ping.send(new B.named(1, 2));
checks.add((x) {
Expect.isTrue(x is A);
Expect.isTrue(x is B);
Expect.equals(2, x.field);
Expect.equals(1, x.field2);
Expect.throws(() => x.field2 = 22);
});
ping.send(new C());
checks.add((x) {
Expect.isTrue(x is A);
Expect.isTrue(x is B);
Expect.isTrue(x is C);
Expect.equals(33, x.field);
Expect.equals(99, x.field2);
Expect.equals(499, x.superField);
Expect.throws(() => x.field2 = 22);
});
ping.send(new D());
checks.add((x) {
Expect.isTrue(x is A);
Expect.isTrue(x is B);
Expect.isTrue(x is C);
Expect.isTrue(x is D);
Expect.isTrue(x is M);
Expect.equals(33, x.field);
Expect.equals(11, x.field2);
Expect.equals(499, x.superField);
Expect.equals(99, x.superField2);
Expect.throws(() => x.field2 = 22);
});
D cyclicD = new D();
cyclicD.field = cyclicD;
ping.send(cyclicD);
checks.add((x) {
Expect.isTrue(x is A);
Expect.isTrue(x is B);
Expect.isTrue(x is C);
Expect.isTrue(x is D);
Expect.isTrue(x is M);
Expect.identical(x, x.field);
Expect.equals(11, x.field2);
Expect.equals(499, x.superField);
Expect.equals(99, x.superField2);
Expect.throws(() => x.field2 = 22);
});
ping.send(new E(E.fooFun)); // //# fun: ok
checks.add((x) { // //# fun: continued
Expect.equals(E.fooFun, x.fun); // //# fun: continued
Expect.equals(499, x.fun()); // //# fun: continued
}); // //# fun: continued
ping.send(new E(barFun)); // //# fun: continued
checks.add((x) { // //# fun: continued
Expect.equals(barFun, x.fun); // //# fun: continued
Expect.equals(42, x.fun()); // //# fun: continued
}); // //# fun: continued
Expect.throws(() => ping.send(new E(new E(null).instanceFun)));
F nonConstF = new F();
ping.send(nonConstF);
checks.add((x) {
Expect.equals("field", x.field);
Expect.isFalse(identical(nonConstF, x));
});
const F constF = const F();
ping.send(constF);
checks.add((x) {
Expect.equals("field", x.field);
Expect.identical(constF, x); // //# constInstance: ok
});
G g1 = new G(nonConstF);
G g2 = new G(constF);
G g3 = const G(constF);
ping.send(g1);
ping.send(g2);
ping.send(g3);
checks.add((x) {
// g1.
Expect.isTrue(x is G);
Expect.isFalse(identical(g1, x));
F f = x.field;
Expect.equals("field", f.field);
Expect.isFalse(identical(nonConstF, f));
});
checks.add((x) {
// g2.
Expect.isTrue(x is G);
Expect.isFalse(identical(g1, x));
F f = x.field;
Expect.equals("field", f.field);
Expect.identical(constF, f); // //# constInstance: continued
});
checks.add((x) {
// g3.
Expect.isTrue(x is G);
Expect.identical(g3, x); // //# constInstance: continued
F f = x.field;
Expect.equals("field", f.field);
Expect.identical(constF, f); // //# constInstance: continued
});
// Make sure objects in a map are serialized and deserialized in the correct
// order.
Map m = new Map();
Value val1 = new Value(1);
Value val2 = new Value(2);
m[val1] = val2;
m[val2] = val1;
// Possible bug we want to catch:
// serializer runs through keys first, and then the values:
// - id1 = val1, id2 = val2, ref[id2], ref[id1]
// deserializer runs through the keys and values in order:
// - val1; // id1.
// - ref[id2]; // boom. Wasn't deserialized yet.
ping.send(m);
checks.add((x) {
Expect.isTrue(x is Map);
Expect.equals(2, x.length);
Expect.equals(val2, x[val1]);
Expect.equals(val1, x[val2]);
Expect.identical(x.keys.elementAt(0), x.values.elementAt(1));
Expect.identical(x.keys.elementAt(1), x.values.elementAt(0));
});
}
void main() {
asyncStart();
Queue checks = new Queue();
ReceivePort testPort = new ReceivePort();
Completer completer = new Completer();
testPort.listen((msg) {
Function check = checks.removeFirst();
check(msg);
if (checks.isEmpty) {
completer.complete();
testPort.close();
}
});
ReceivePort initialReplyPort = new ReceivePort();
Isolate
.spawn(echoMain, [initialReplyPort.sendPort, testPort.sendPort])
.then((_) => initialReplyPort.first)
.then((arg) {
SendPort ping = arg as SendPort;
runTests(ping, checks);
Expect.isTrue(checks.length > 0);
completer.future.then((_) => ping.send("halt")).then((_) => asyncEnd());
});
}