| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library serialization_test; | 5 library serialization_test; |
| 6 | 6 |
| 7 import 'dart:json' as json; | 7 import 'dart:json' as json; |
| 8 import 'package:unittest/unittest.dart'; | 8 import 'package:unittest/unittest.dart'; |
| 9 import 'package:serialization/serialization.dart'; | 9 import 'package:serialization/serialization.dart'; |
| 10 import 'package:serialization/src/serialization_helpers.dart'; | 10 import 'package:serialization/src/serialization_helpers.dart'; |
| 11 import 'package:serialization/src/mirrors_helpers.dart'; | 11 import 'package:serialization/src/mirrors_helpers.dart'; |
| 12 import 'dart:isolate'; |
| 12 | 13 |
| 13 part 'test_models.dart'; | 14 part 'test_models.dart'; |
| 14 | 15 |
| 15 main() { | 16 main() { |
| 16 var p1 = new Person(); | 17 var p1 = new Person(); |
| 17 var a1 = new Address(); | 18 var a1 = new Address(); |
| 18 a1.street = 'N 34th'; | 19 a1.street = 'N 34th'; |
| 19 a1.city = 'Seattle'; | 20 a1.city = 'Seattle'; |
| 20 | 21 |
| 21 var formats = [const SimpleFlatFormat(), const SimpleMapFormat(), | 22 var formats = [const InternalMapFormat(), |
| 23 const SimpleFlatFormat(), const SimpleMapFormat(), |
| 22 const SimpleJsonFormat(storeRoundTripInfo: true)]; | 24 const SimpleJsonFormat(storeRoundTripInfo: true)]; |
| 23 | 25 |
| 24 test('Basic extraction of a simple object', () { | 26 test('Basic extraction of a simple object', () { |
| 25 // TODO(alanknight): Switch these to use literal types. Issue | 27 // TODO(alanknight): Switch these to use literal types. Issue |
| 26 var s = new Serialization() | 28 var s = new Serialization() |
| 27 ..addRuleFor(a1).configureForMaps(); | 29 ..addRuleFor(a1).configureForMaps(); |
| 28 Map extracted = states(a1, s).first; | 30 Map extracted = states(a1, s).first; |
| 29 expect(extracted.length, 4); | 31 expect(extracted.length, 4); |
| 30 expect(extracted['street'], 'N 34th'); | 32 expect(extracted['street'], 'N 34th'); |
| 31 expect(extracted['city'], 'Seattle'); | 33 expect(extracted['city'], 'Seattle'); |
| 32 expect(extracted['state'], null); | 34 expect(extracted['state'], null); |
| 33 expect(extracted['zip'], null); | 35 expect(extracted['zip'], null); |
| 34 Reader reader = setUpReader(s, extracted); | 36 Reader reader = setUpReader(s, extracted); |
| 35 Address a2 = readBackSimple(s, a1, reader); | 37 Address a2 = readBackSimple(s, a1, reader); |
| 36 expect(a2.street, 'N 34th'); | 38 expect(a2.street, 'N 34th'); |
| 37 expect(a2.city, 'Seattle'); | 39 expect(a2.city, 'Seattle'); |
| 38 expect(a2.state,null); | 40 expect(a2.state,null); |
| 39 expect(a2.zip, null); | 41 expect(a2.zip, null); |
| 40 }); | 42 }); |
| 41 | 43 |
| 42 test('Slightly further with a simple object', () { | 44 test('Slightly further with a simple object', () { |
| 43 var p1 = new Person()..name = 'Alice'..address = a1; | 45 var p1 = new Person()..name = 'Alice'..address = a1; |
| 44 var s = new Serialization() | 46 var s = new Serialization() |
| 45 ..addRuleFor(p1).configureForMaps() | 47 ..addRuleFor(p1).configureForMaps() |
| 46 ..addRuleFor(a1).configureForMaps(); | 48 ..addRuleFor(a1).configureForMaps(); |
| 47 // TODO(alanknight): Need a better API for getting to flat state without | 49 // TODO(alanknight): Need a better API for getting to flat state without |
| 48 // actually writing. | 50 // actually writing. |
| 49 var w = new Writer(s); | 51 var w = new Writer(s, const InternalMapFormat()); |
| 50 w.write(p1); | 52 w.write(p1); |
| 51 var personRule = s.rules.firstWhere( | 53 var personRule = s.rules.firstWhere( |
| 52 (x) => x is BasicRule && x.type == reflect(p1).type); | 54 (x) => x is BasicRule && x.type == reflect(p1).type); |
| 53 var flatPerson = w.states[personRule.number].first; | 55 var flatPerson = w.states[personRule.number].first; |
| 54 var primStates = w.states.first; | 56 var primStates = w.states.first; |
| 55 expect(primStates.isEmpty, true); | 57 expect(primStates.isEmpty, true); |
| 56 expect(flatPerson["name"], "Alice"); | 58 expect(flatPerson["name"], "Alice"); |
| 57 var ref = flatPerson["address"]; | 59 var ref = flatPerson["address"]; |
| 58 expect(ref is Reference, true); | 60 expect(ref is Reference, true); |
| 59 var addressRule = s.rules.firstWhere( | 61 var addressRule = s.rules.firstWhere( |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 var all = trace.writer.references.keys.toSet(); | 210 var all = trace.writer.references.keys.toSet(); |
| 209 expect(all.length, 4); | 211 expect(all.length, 4); |
| 210 expect(all.contains(n1), isTrue); | 212 expect(all.contains(n1), isTrue); |
| 211 expect(all.contains(n2), isTrue); | 213 expect(all.contains(n2), isTrue); |
| 212 expect(all.contains(n3), isTrue); | 214 expect(all.contains(n3), isTrue); |
| 213 expect(all.contains(n1.children), isTrue); | 215 expect(all.contains(n1.children), isTrue); |
| 214 }); | 216 }); |
| 215 | 217 |
| 216 test('Flatten references in a cyclical structure', () { | 218 test('Flatten references in a cyclical structure', () { |
| 217 var s = new Serialization(); | 219 var s = new Serialization(); |
| 218 var w = new Writer(s); | 220 var w = new Writer(s, const InternalMapFormat()); |
| 219 w.trace = new Trace(w); | 221 w.trace = new Trace(w); |
| 220 w.write(n1); | 222 w.write(n1); |
| 221 expect(w.states.length, 6); // prims, lists, essential lists, basic, symbol | 223 expect(w.states.length, 6); // prims, lists, essential lists, basic, symbol |
| 222 var children = 0, name = 1, parent = 2; | 224 var children = 0, name = 1, parent = 2; |
| 223 var nodeRule = s.rules.firstWhere((x) => x is BasicRule); | 225 var nodeRule = s.rules.firstWhere((x) => x is BasicRule); |
| 224 List rootNode = w.states[nodeRule.number].where( | 226 List rootNode = w.states[nodeRule.number].where( |
| 225 (x) => x[name] == "1").toList(); | 227 (x) => x[name] == "1").toList(); |
| 226 rootNode = rootNode.first; | 228 rootNode = rootNode.first; |
| 227 expect(rootNode[parent], isNull); | 229 expect(rootNode[parent], isNull); |
| 228 var list = w.states[1].first; | 230 var list = w.states[1].first; |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 expect(input[p2], same(a2)); | 522 expect(input[p2], same(a2)); |
| 521 expect(input[a2], same(p2)); | 523 expect(input[a2], same(p2)); |
| 522 } | 524 } |
| 523 } | 525 } |
| 524 }); | 526 }); |
| 525 | 527 |
| 526 test("Map with string keys stays that way", () { | 528 test("Map with string keys stays that way", () { |
| 527 var s = new Serialization()..addRuleFor(new Person()); | 529 var s = new Serialization()..addRuleFor(new Person()); |
| 528 var data = {"abc" : 1, "def" : "ghi"}; | 530 var data = {"abc" : 1, "def" : "ghi"}; |
| 529 data["person"] = new Person()..name = "Foo"; | 531 data["person"] = new Person()..name = "Foo"; |
| 530 var output = s.write(data, const SimpleMapFormat()); | 532 var output = s.write(data, const InternalMapFormat()); |
| 531 var mapRule = s.rules.firstWhere((x) => x is MapRule); | 533 var mapRule = s.rules.firstWhere((x) => x is MapRule); |
| 532 var map = output["data"][mapRule.number][0]; | 534 var map = output["data"][mapRule.number][0]; |
| 533 expect(map is Map, isTrue); | 535 expect(map is Map, isTrue); |
| 534 expect(map["abc"], 1); | 536 expect(map["abc"], 1); |
| 535 expect(map["def"], "ghi"); | 537 expect(map["def"], "ghi"); |
| 536 expect(new Reader(s).asReference(map["person"]) is Reference, isTrue); | 538 expect(map["person"] is Reference, isTrue); |
| 537 }); | 539 }); |
| 538 | 540 |
| 539 test("MirrorRule with lookup by qualified name rather than named object", () { | 541 test("MirrorRule with lookup by qualified name rather than named object", () { |
| 540 var s = new Serialization()..addRule(new MirrorRule()); | 542 var s = new Serialization()..addRule(new MirrorRule()); |
| 541 var m = reflectClass(Address); | 543 var m = reflectClass(Address); |
| 542 var output = s.write(m); | 544 var output = s.write(m); |
| 543 var input = s.read(output); | 545 var input = s.read(output); |
| 544 expect(input is ClassMirror, isTrue); | 546 expect(input is ClassMirror, isTrue); |
| 545 expect(MirrorSystem.getName(input.simpleName), "Address"); | 547 expect(MirrorSystem.getName(input.simpleName), "Address"); |
| 546 }); | 548 }); |
| 547 | 549 |
| 550 test('round-trip, default format, pass to isolate', () { |
| 551 Node n1 = new Node("1"), n2 = new Node("2"), n3 = new Node("3"); |
| 552 n1.children = [n2, n3]; |
| 553 n2.parent = n1; |
| 554 n3.parent = n1; |
| 555 var s = nodeSerializerReflective(n1); |
| 556 var output = s.write(n2); |
| 557 var port = spawnFunction(echo); |
| 558 port.call(output).then(expectAsync1((input) => verify(input))); |
| 559 }); |
| 560 } |
| 561 |
| 562 /** |
| 563 * Verify serialized output that we have passed to an isolate and back. |
| 564 */ |
| 565 verify(input) { |
| 566 var s2 = nodeSerializerReflective(new Node("a")); |
| 567 var reader = new Reader(s2); |
| 568 var m2 = reader.read(input); |
| 569 var m1 = m2.parent; |
| 570 expect(m1 is Node, isTrue); |
| 571 var children = m1.children; |
| 572 expect(m1.name,"1"); |
| 573 var m3 = m1.children.last; |
| 574 expect(m2.name, "2"); |
| 575 expect(m3.name, "3"); |
| 576 expect(m2.parent, m1); |
| 577 expect(m3.parent, m1); |
| 578 expect(m1.parent, isNull); |
| 548 } | 579 } |
| 549 | 580 |
| 550 /****************************************************************************** | 581 /****************************************************************************** |
| 551 * The end of the tests and the beginning of various helper functions to make | 582 * The end of the tests and the beginning of various helper functions to make |
| 552 * it easier to write the repetitive sections. | 583 * it easier to write the repetitive sections. |
| 553 ******************************************************************************/ | 584 ******************************************************************************/ |
| 554 | 585 |
| 555 writeAndReadBack(Serialization s, Format format, object) { | 586 writeAndReadBack(Serialization s, Format format, object) { |
| 556 var w = s.newWriter(format); | 587 var w = s.newWriter(format); |
| 557 var output = w.write(object); | 588 var output = w.write(object); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 } | 805 } |
| 775 findValue(String key, Map state) { | 806 findValue(String key, Map state) { |
| 776 var answer; | 807 var answer; |
| 777 for (var each in state.keys) { | 808 for (var each in state.keys) { |
| 778 var value = state[each]; | 809 var value = state[each]; |
| 779 if (value == key) return each; | 810 if (value == key) return each; |
| 780 } | 811 } |
| 781 return null; | 812 return null; |
| 782 } | 813 } |
| 783 } | 814 } |
| 815 |
| 816 /** |
| 817 * Function used in an isolate to make sure that the output passes through |
| 818 * isolate serialization properly. |
| 819 */ |
| 820 echo() { |
| 821 port.receive((msg, reply) { |
| 822 reply.send(msg); |
| 823 }); |
| 824 } |
| OLD | NEW |