Files
sdk/tests/lib_2/isolate/message3_test.dart
T
Erik Corry 5c7804fe32 [VM] Add SIMD arrays to raw snapshot code
This has not been done earlier because no decision was made about
how to handle endian issues. This change assumes the same low
level format at either end of the serialization/deserialization.

R=kustermann@google.com

Bug: 21818
Change-Id: I5d97c1d0b89badf9cb972f0b1977eba0d1c0b9f8
Reviewed-on: https://dart-review.googlesource.com/35962
Commit-Queue: Erik Corry <erikcorry@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2018-01-22 22:09:59 +00:00

501 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 {
var 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);
checks.add(
(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);
});
Float32x4List flist32x4 = new Float32x4List(2);
flist32x4[0] = new Float32x4(1.5, 2.5, 3.5, 4.5);
flist32x4[1] = new Float32x4(5.5, 6.5, 7.5, 8.5);
ping.send(flist32x4);
checks.add(
(x) {
Expect.isTrue(x is Float32x4List);
Expect.equals(2, x.length);
Float32x4 entry1 = x[0];
Float32x4 entry2 = x[1];
Expect.equals(1.5, entry1.x);
Expect.equals(2.5, entry1.y);
Expect.equals(3.5, entry1.z);
Expect.equals(4.5, entry1.w);
Expect.equals(5.5, entry2.x);
Expect.equals(6.5, entry2.y);
Expect.equals(7.5, entry2.z);
Expect.equals(8.5, entry2.w);
});
Float64x2List flist64x2 = new Float64x2List(2);
flist64x2[0] = new Float64x2(1.5, 2.5);
flist64x2[1] = new Float64x2(5.5, 6.5);
ping.send(flist64x2);
checks.add(
(x) {
Expect.isTrue(x is Float64x2List);
Expect.equals(2, x.length);
Float64x2 entry1 = x[0];
Float64x2 entry2 = x[1];
Expect.equals(1.5, entry1.x);
Expect.equals(2.5, entry1.y);
Expect.equals(5.5, entry2.x);
Expect.equals(6.5, entry2.y);
});
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[123] = 499;
Expect.equals(499, x[123]);
});
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();
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.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((_ping) {
SendPort ping = _ping;
runTests(ping, checks);
Expect.isTrue(checks.length > 0);
completer.future.then((_) => ping.send("halt")).then((_) => asyncEnd());
});
}