Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: pkg/serialization/test/serialization_test.dart

Issue 584473004: Revert "remove serialization. it's moved to github" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/serialization/test/no_library_test.dart ('k') | pkg/serialization/test/test_models.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 library serialization_test;
6
7 import 'dart:convert';
8 import 'package:unittest/unittest.dart';
9 import 'package:serialization/serialization.dart';
10 import 'package:serialization/src/serialization_helpers.dart';
11 import 'package:serialization/src/mirrors_helpers.dart';
12 import 'dart:isolate';
13
14 part 'test_models.dart';
15
16 void main() {
17 var p1 = new Person();
18 var a1 = new Address();
19 a1.street = 'N 34th';
20 a1.city = 'Seattle';
21
22 var formats = [const InternalMapFormat(),
23 const SimpleFlatFormat(), const SimpleMapFormat(),
24 const SimpleJsonFormat(storeRoundTripInfo: true)];
25
26 test('Basic extraction of a simple object', () {
27 // TODO(alanknight): Switch these to use literal types. Issue
28 var s = new Serialization()
29 ..addRuleFor(Address).configureForMaps();
30 Map extracted = states(a1, s).first;
31 expect(extracted.length, 4);
32 expect(extracted['street'], 'N 34th');
33 expect(extracted['city'], 'Seattle');
34 expect(extracted['state'], null);
35 expect(extracted['zip'], null);
36 Reader reader = setUpReader(s, extracted);
37 Address a2 = readBackSimple(s, a1, reader);
38 expect(a2.street, 'N 34th');
39 expect(a2.city, 'Seattle');
40 expect(a2.state,null);
41 expect(a2.zip, null);
42 });
43
44 test('Slightly further with a simple object', () {
45 var p1 = new Person()..name = 'Alice'..address = a1;
46 var s = new Serialization()
47 ..addRuleFor(Person).configureForMaps()
48 ..addRuleFor(Address).configureForMaps();
49 // TODO(alanknight): Need a better API for getting to flat state without
50 // actually writing.
51 var w = new Writer(s, const InternalMapFormat());
52 w.write(p1);
53 var personRule = s.rules.firstWhere(
54 (x) => x is BasicRule && x.type == reflect(p1).type);
55 var flatPerson = w.states[personRule.number].first;
56 var primStates = w.states.first;
57 expect(primStates.isEmpty, true);
58 expect(flatPerson["name"], "Alice");
59 var ref = flatPerson["address"];
60 expect(ref is Reference, true);
61 var addressRule = s.rules.firstWhere(
62 (x) => x is BasicRule && x.type == reflect(a1).type);
63 expect(ref.ruleNumber, addressRule.number);
64 expect(ref.objectNumber, 0);
65 expect(w.states[addressRule.number].first['street'], 'N 34th');
66 });
67
68 test('exclude fields', () {
69 var s = new Serialization()
70 ..addRuleFor(Address,
71 excludeFields: ['state', 'zip']).configureForMaps();
72 var extracted = states(a1, s).first;
73 expect(extracted.length, 2);
74 expect(extracted['street'], 'N 34th');
75 expect(extracted['city'], 'Seattle');
76 Reader reader = setUpReader(s, extracted);
77 Address a2 = readBackSimple(s, a1, reader);
78 expect(a2.state, null);
79 expect(a2.city, 'Seattle');
80 });
81
82 test('list', () {
83 var list = [5, 4, 3, 2, 1];
84 var s = new Serialization();
85 var extracted = states(list, s).first;
86 expect(extracted.length, 5);
87 for (var i = 0; i < 5; i++) {
88 expect(extracted[i], (5 - i));
89 }
90 Reader reader = setUpReader(s, extracted);
91 var list2 = readBackSimple(s, list, reader);
92 expect(list, list2);
93 });
94
95 test('different kinds of fields', () {
96 var x = new Various.Foo("d", "e");
97 x.a = "a";
98 x.b = "b";
99 x._c = "c";
100 var s = new Serialization()
101 ..addRuleFor(Various,
102 constructor: "Foo",
103 constructorFields: ["d", "e"]);
104 var state = states(x, s).first;
105 expect(state.length, 4);
106 var expected = "abde";
107 for (var i in [0,1,2,3]) {
108 expect(state[i], expected[i]);
109 }
110 Reader reader = setUpReader(s, state);
111 Various y = readBackSimple(s, x, reader);
112 expect(x.a, y.a);
113 expect(x.b, y.b);
114 expect(x.d, y.d);
115 expect(x.e, y.e);
116 expect(y._c, 'default value');
117 });
118
119 test('Stream', () {
120 // This is an interesting case. The Stream doesn't expose its internal
121 // collection at all, and sets it in the constructor. So to get it we
122 // read a private field and then set that via the constructor. That works
123 // but should we have some kind of large red flag that you're using private
124 // state.
125 var stream = new Stream([3,4,5]);
126 expect((stream..next()).next(), 4);
127 expect(stream.position, 2);
128 // The Symbol class does not allow us to create symbols for private
129 // variables. However, the mirror system uses them. So we get the symbol
130 // we want from the mirror.
131 // TODO(alanknight): Either delete this test and decide we shouldn't
132 // attempt to access private variables or fix this properly.
133 var _collectionSym = reflect(stream).type.declarations.keys.firstWhere(
134 (x) => MirrorSystem.getName(x) == "_collection");
135 var s = new Serialization()
136 ..addRuleFor(Stream,
137 constructorFields: [_collectionSym]);
138 var state = states(stream, s).first;
139 // Define names for the variable offsets to make this more readable.
140 var _collection = 0, position = 1;
141 expect(state[_collection],[3,4,5]);
142 expect(state[position], 2);
143 });
144
145 test('date', () {
146 var date = new DateTime.now();
147 var utcDate = new DateTime.utc(date.year, date.month, date.day,
148 date.hour, date.minute, date.second, date.millisecond);
149 var s = new Serialization();
150 var out = s.write([date, utcDate]);
151 expect(s.selfDescribing, isTrue);
152 var input = s.read(out);
153 expect(input.first, date);
154 expect(input.last, utcDate);
155 });
156
157 test('Iteration helpers', () {
158 var map = {"a" : 1, "b" : 2, "c" : 3};
159 var list = [1, 2, 3];
160 var set = new Set.from(list);
161 var m = keysAndValues(map);
162 var l = keysAndValues(list);
163 var s = keysAndValues(set);
164
165 m.forEach((key, value) {expect(key.codeUnits[0], value + 96);});
166 l.forEach((key, value) {expect(key + 1, value);});
167 var index = 0;
168 var seen = new Set();
169 s.forEach((key, value) {
170 expect(key, index++);
171 expect(seen.contains(value), isFalse);
172 seen.add(value);
173 });
174 expect(seen.length, 3);
175
176 var i = 0;
177 m = values(map);
178 l = values(list);
179 s = values(set);
180 m.forEach((each) {expect(each, ++i);});
181 i = 0;
182 l.forEach((each) {expect(each, ++i);});
183 i = 0;
184 s.forEach((each) {expect(each, ++i);});
185 i = 0;
186
187 seen = new Set();
188 for (var each in m) {
189 expect(seen.contains(each), isFalse);
190 seen.add(each);
191 }
192 expect(seen.length, 3);
193 i = 0;
194 for (var each in l) {
195 expect(each, ++i);
196 }
197 });
198
199 Node n1 = new Node("1"), n2 = new Node("2"), n3 = new Node("3");
200 n1.children = [n2, n3];
201 n2.parent = n1;
202 n3.parent = n1;
203
204 test('Trace a cyclical structure', () {
205 var s = new Serialization();
206 var trace = new Trace(new Writer(s));
207 trace.writer.trace = trace;
208 trace.trace(n1);
209 var all = trace.writer.references.keys.toSet();
210 expect(all.length, 4);
211 expect(all.contains(n1), isTrue);
212 expect(all.contains(n2), isTrue);
213 expect(all.contains(n3), isTrue);
214 expect(all.contains(n1.children), isTrue);
215 });
216
217 test('Flatten references in a cyclical structure', () {
218 var s = new Serialization();
219 var w = new Writer(s, const InternalMapFormat());
220 w.trace = new Trace(w);
221 w.write(n1);
222 expect(w.states.length, 7); // prims, lists * 2, basic, symbol, date
223 var children = 0, name = 1, parent = 2;
224 var nodeRule = s.rules.firstWhere((x) => x is BasicRule);
225 List rootNode = w.states[nodeRule.number].where(
226 (x) => x[name] == "1").toList();
227 rootNode = rootNode.first;
228 expect(rootNode[parent], isNull);
229 var list = w.states[1].first;
230 expect(w.stateForReference(rootNode[children]), list);
231 var parentNode = w.stateForReference(list[0])[parent];
232 expect(w.stateForReference(parentNode), rootNode);
233 });
234
235 test('round-trip', () {
236 runRoundTripTest(nodeSerializerReflective);
237 });
238
239 test('round-trip with explicit self-description', () {
240 // We provide a setup function which, when run the second time,
241 // returns a blank serialization, to make sure it will fail
242 // the second time.
243 var s;
244 oneShotSetup(node) {
245 if (s == null) {
246 s = nodeSerializerReflective(node)..selfDescribing = true;
247 return s;
248 } else {
249 s = null;
250 return new Serialization.blank()
251 ..namedObjects['Node'] = reflect(new Node('')).type;
252 }
253 }
254
255 runRoundTripTest(oneShotSetup);
256 });
257
258 test('round-trip ClosureRule', () {
259 runRoundTripTest(nodeSerializerNonReflective);
260 });
261
262 test('round-trip with essential parent', () {
263 runRoundTripTest(nodeSerializerWithEssentialParent);
264 });
265
266 test('round-trip, flat format', () {
267 runRoundTripTestFlat(nodeSerializerReflective);
268 });
269
270 test('round-trip using Maps', () {
271 runRoundTripTest(nodeSerializerUsingMaps);
272 });
273
274 test('round-trip, flat format, using maps', () {
275 runRoundTripTestFlat(nodeSerializerUsingMaps);
276 });
277
278 test('round-trip with Node CustomRule', () {
279 runRoundTripTestFlat(nodeSerializerCustom);
280 });
281
282 test('round-trip with Node CustomRule, to maps', () {
283 runRoundTripTest(nodeSerializerCustom);
284 });
285
286 test('eating your own tail', () {
287 // Create a meta-serializer, that serializes serializations, then
288 // use it to serialize a basic serialization, then run a test on the
289 // the result.
290 var s = new Serialization.blank()
291 // Add the rules in a deliberately unusual order.
292 ..addRuleFor(Node, constructorFields: ['name'])
293 ..addRule(new ListRule())
294 ..addRule(new PrimitiveRule())
295 ..selfDescribing = false;
296 var meta = metaSerialization();
297 var metaWithMaps = metaSerializationUsingMaps();
298 for (var eachFormat in formats) {
299 for (var eachMeta in [meta, metaWithMaps]) {
300 var serialized = eachMeta.write(s, format: eachFormat);
301 var newSerialization = eachMeta.read(serialized, format: eachFormat,
302 externals: {"serialization_test.Node" : reflect(new Node('')).type}
303 );
304 runRoundTripTest((x) => newSerialization);
305 }
306 }
307 });
308
309 test("Verify we're not serializing lists twice if they're essential", () {
310 Node n1 = new Node("1"), n2 = new Node("2"), n3 = new Node("3");
311 n1.children = [n2, n3];
312 n2.parent = n1;
313 n3.parent = n1;
314 var s = new Serialization()
315 ..addRuleFor(Node, constructorFields: ["name"]).
316 setFieldWith("children", (parent, child) =>
317 parent.reflectee.children = child);
318 var w = new Writer(s);
319 w.write(n1);
320 expect(w.rules[2] is ListRuleEssential, isTrue);
321 expect(w.rules[1] is ListRule, isTrue);
322 expect(w.states[1].length, 0);
323 expect(w.states[2].length, 1);
324 s = new Serialization()
325 ..addRuleFor(Node, constructorFields: ["name"]);
326 w = new Writer(s);
327 w.write(n1);
328 expect(w.states[1].length, 1);
329 expect(w.states[2].length, 0);
330 });
331
332 test('Identity of equal objects preserved', () {
333 Node n1 = new NodeEqualByName("foo"),
334 n2 = new NodeEqualByName("foo"),
335 n3 = new NodeEqualByName("3");
336 n1.children = [n2, n3];
337 n2.parent = n1;
338 n3.parent = n1;
339 var s = new Serialization()
340 ..selfDescribing = false
341 ..addRuleFor(NodeEqualByName, constructorFields: ["name"]);
342 var m1 = writeAndReadBack(s, null, n1);
343 var m2 = m1.children.first;
344 var m3 = m1.children.last;
345 expect(m1, m2);
346 expect(identical(m1, m2), isFalse);
347 expect(m1 == m3, isFalse);
348 expect(identical(m2.parent, m3.parent), isTrue);
349 });
350
351 test("Constant values as fields", () {
352 var s = new Serialization()
353 ..selfDescribing = false
354 ..addRuleFor(Address,
355 constructor: 'withData',
356 constructorFields: ["street", "Kirkland", "WA", "98103"],
357 fields: []);
358 var out = s.write(a1);
359 var newAddress = s.read(out);
360 expect(newAddress.street, a1.street);
361 expect(newAddress.city, "Kirkland");
362 expect(newAddress.state, "WA");
363 expect(newAddress.zip, "98103");
364 });
365
366 test("Straight JSON format", () {
367 var s = new Serialization();
368 var writer = s.newWriter(const SimpleJsonFormat());
369 var out = JSON.encode(writer.write(a1));
370 var reconstituted = JSON.decode(out);
371 expect(reconstituted.length, 4);
372 expect(reconstituted[0], "Seattle");
373 });
374
375 test("Straight JSON format, nested objects", () {
376 var p1 = new Person()..name = 'Alice'..address = a1;
377 var s = new Serialization()..selfDescribing = false;
378 var addressRule = s.addRuleFor(Address)..configureForMaps();
379 var personRule = s.addRuleFor(Person)..configureForMaps();
380 var writer = s.newWriter(const SimpleJsonFormat(storeRoundTripInfo: true));
381 var out = JSON.encode(writer.write(p1));
382 var reconstituted = JSON.decode(out);
383 var expected = {
384 "name" : "Alice",
385 "rank" : null,
386 "serialNumber" : null,
387 "_rule" : personRule.number,
388 "address" : {
389 "street" : "N 34th",
390 "city" : "Seattle",
391 "state" : null,
392 "zip" : null,
393 "_rule" : addressRule.number
394 }
395 };
396 expect(expected, reconstituted);
397 });
398
399 test("Straight JSON format, round-trip", () {
400 // Note that we can't use the usual round-trip test because it has cycles.
401 var p1 = new Person()..name = 'Alice'..address = a1;
402 // Use maps for one rule, lists for the other.
403 var s = new Serialization()
404 ..addRuleFor(Address)
405 ..addRuleFor(Person).configureForMaps();
406 var p2 = writeAndReadBack(s,
407 const SimpleJsonFormat(storeRoundTripInfo: true), p1);
408 expect(p2.name, "Alice");
409 var a2 = p2.address;
410 expect(a2.street, "N 34th");
411 expect(a2.city, "Seattle");
412 });
413
414 test("Straight JSON format, non-string key", () {
415 // This tests what happens if we have a key that's not a string. That's
416 // not allowed by json, so we don't actually turn it into a json string,
417 // but someone might reasonably convert to a json-able structure without
418 // going through the string representation.
419 var p1 = new Person()..name = 'Alice'..address = a1;
420 var s = new Serialization()
421 ..addRule(new PersonRuleReturningMapWithNonStringKey());
422 var p2 = writeAndReadBack(s,
423 const SimpleJsonFormat(storeRoundTripInfo: true), p1);
424 expect(p2.name, "Alice");
425 expect(p2.address.street, "N 34th");
426 });
427
428 test("Root is a Map", () {
429 // Note that we can't use the usual round-trip test because it has cycles.
430 var p1 = new Person()..name = 'Alice'..address = a1;
431 // Use maps for one rule, lists for the other.
432 var s = new Serialization()
433 // Deliberately left as passing instances to test backward-compatibility.
434 ..addRuleFor(a1)
435 ..addRuleFor(p1).configureForMaps();
436 for (var eachFormat in formats) {
437 var w = s.newWriter(eachFormat);
438 var output = w.write({"stuff" : p1});
439 var result = s.read(output, format: w.format);
440 var p2 = result["stuff"];
441 expect(p2.name, "Alice");
442 var a2 = p2.address;
443 expect(a2.street, "N 34th");
444 expect(a2.city, "Seattle");
445 }
446 });
447
448 test("Root is a List", () {
449 var s = new Serialization();
450 for (var eachFormat in formats) {
451 var result = writeAndReadBack(s, eachFormat, [a1]);
452 var a2 = result.first;
453 expect(a2.street, "N 34th");
454 expect(a2.city, "Seattle");
455 }
456 });
457
458 test("Root is a simple object", () {
459 var s = new Serialization();
460 for (var eachFormat in formats) {
461 expect(writeAndReadBack(s, eachFormat, null), null);
462 expect(writeAndReadBack(s, eachFormat, [null]), [null]);
463 expect(writeAndReadBack(s, eachFormat, 3), 3);
464 expect(writeAndReadBack(s, eachFormat, [3]), [3]);
465 expect(writeAndReadBack(s, eachFormat, "hello"), "hello");
466 expect(writeAndReadBack(s, eachFormat, [3]), [3]);
467 expect(writeAndReadBack(s, eachFormat, {"hello" : "world"}),
468 {"hello" : "world"});
469 expect(writeAndReadBack(s, eachFormat, true), true);
470 }
471 });
472
473 test("Simple JSON format, round-trip with named objects", () {
474 // Note that we can't use the usual round-trip test because it has cycles.
475 var p1 = new Person()..name = 'Alice'..address = a1;
476 // Use maps for one rule, lists for the other.
477 var s = new Serialization()
478 ..selfDescribing = false
479 ..addRule(new NamedObjectRule())
480 ..addRuleFor(Address)
481 ..addRuleFor(Person).configureForMaps()
482 ..namedObjects["foo"] = a1;
483 var format = const SimpleJsonFormat(storeRoundTripInfo: true);
484 var out = s.write(p1, format: format);
485 var p2 = s.read(out, format: format, externals: {"foo" : 12});
486 expect(p2.name, "Alice");
487 var a2 = p2.address;
488 expect(a2, 12);
489 });
490
491 test("More complicated Maps", () {
492 var s = new Serialization()..selfDescribing = false;
493 var p1 = new Person()..name = 'Alice'..address = a1;
494 var data = new Map();
495 data["simple data"] = 1;
496 data[p1] = a1;
497 data[a1] = p1;
498 for (var eachFormat in formats) {
499 var output = s.write(data, format: eachFormat);
500 var input = s.read(output, format: eachFormat);
501 expect(input["simple data"], data["simple data"]);
502 var p2 = input.keys.firstWhere((x) => x is Person);
503 var a2 = input.keys.firstWhere((x) => x is Address);
504 if (eachFormat is SimpleJsonFormat) {
505 // JSON doesn't handle cycles, so these won't be identical.
506 expect(input[p2] is Address, isTrue);
507 expect(input[a2] is Person, isTrue);
508 var a3 = input[p2];
509 expect(a3.city, a2.city);
510 expect(a3.state, a2.state);
511 expect(a3.state, a2.state);
512 var p3 = input[a2];
513 expect(p3.name, p2.name);
514 expect(p3.rank, p2.rank);
515 expect(p3.address.city, a2.city);
516 } else {
517 expect(input[p2], same(a2));
518 expect(input[a2], same(p2));
519 }
520 }
521 });
522
523 test("Map with string keys stays that way", () {
524 var s = new Serialization()..addRuleFor(Person);
525 var data = {"abc" : 1, "def" : "ghi"};
526 data["person"] = new Person()..name = "Foo";
527 var output = s.write(data, format: const InternalMapFormat());
528 var mapRule = s.rules.firstWhere((x) => x is MapRule);
529 var map = output["data"][mapRule.number][0];
530 expect(map is Map, isTrue);
531 expect(map["abc"], 1);
532 expect(map["def"], "ghi");
533 expect(map["person"] is Reference, isTrue);
534 });
535
536 test("MirrorRule with lookup by qualified name rather than named object", () {
537 var s = new Serialization()..addRule(new MirrorRule());
538 var m = reflectClass(Address);
539 var output = s.write(m);
540 var input = s.read(output);
541 expect(input is ClassMirror, isTrue);
542 expect(MirrorSystem.getName(input.simpleName), "Address");
543 });
544
545 test('round-trip, default format, pass to isolate', () {
546 Node n1 = new Node("1"), n2 = new Node("2"), n3 = new Node("3");
547 n1.children = [n2, n3];
548 n2.parent = n1;
549 n3.parent = n1;
550 var s = nodeSerializerReflective(n1);
551 var output = s.write(n2);
552 ReceivePort port = new ReceivePort();
553 var remote = Isolate.spawn(echo, [output, port.sendPort]);
554 port.first.then(verify);
555 });
556 }
557
558 /**
559 * Verify serialized output that we have passed to an isolate and back.
560 */
561 void verify(input) {
562 var s2 = nodeSerializerReflective(new Node("a"));
563 var m2 = s2.read(input);
564 var m1 = m2.parent;
565 expect(m1 is Node, isTrue);
566 var children = m1.children;
567 expect(m1.name,"1");
568 var m3 = m1.children.last;
569 expect(m2.name, "2");
570 expect(m3.name, "3");
571 expect(m2.parent, m1);
572 expect(m3.parent, m1);
573 expect(m1.parent, isNull);
574 }
575
576 /******************************************************************************
577 * The end of the tests and the beginning of various helper functions to make
578 * it easier to write the repetitive sections.
579 ******************************************************************************/
580
581 writeAndReadBack(Serialization s, Format format, object) {
582 var output = s.write(object, format: format);
583 return s.read(output, format: format);
584 }
585
586 /** Create a Serialization for serializing Serializations. */
587 Serialization metaSerialization() {
588 // Make some bogus rule instances so we have something to feed rule creation
589 // and get their types. If only we had class literals implemented...
590 var basicRule = new BasicRule(reflect(null).type, '', [], [], []);
591
592 var meta = new Serialization()
593 ..selfDescribing = false
594 ..addRuleFor(ListRule)
595 ..addRuleFor(PrimitiveRule)
596 // TODO(alanknight): Handle CustomRule as well.
597 // Note that we're passing in a constant for one of the fields.
598 ..addRuleFor(BasicRule,
599 constructorFields: ['type',
600 'constructorName',
601 'constructorFields', 'regularFields', []],
602 fields: [])
603 ..addRuleFor(Serialization, constructor: "blank")
604 .setFieldWith('rules',
605 (InstanceMirror s, List rules) {
606 rules.forEach((x) => s.reflectee.addRule(x));
607 })
608 ..addRule(new NamedObjectRule())
609 ..addRule(new MirrorRule())
610 ..addRule(new MapRule());
611 return meta;
612 }
613
614 Serialization metaSerializationUsingMaps() {
615 var meta = metaSerialization();
616 meta.rules.where((each) => each is BasicRule)
617 .forEach((x) => x.configureForMaps());
618 return meta;
619 }
620
621 /**
622 * Read back a simple object, assumed to be the only one of its class in the
623 * reader.
624 */
625 readBackSimple(Serialization s, object, Reader reader) {
626 var rule = s.rulesFor(object, null).first;
627 reader.inflateForRule(rule);
628 var list2 = reader.allObjectsForRule(rule).first;
629 return list2;
630 }
631
632 /**
633 * Set up a basic reader with some fake data. Hard-codes the assumption
634 * of how many rules there are.
635 */
636 Reader setUpReader(aSerialization, sampleData) {
637 var reader = new Reader(aSerialization);
638 // We're not sure which rule needs the sample data, so put it everywhere
639 // and trust that the extra will just be ignored.
640
641 var fillValue = [sampleData];
642 var data = [];
643 for (int i = 0; i < 10; i++) {
644 data.add(fillValue);
645 }
646 reader.data = data;
647 return reader;
648 }
649
650 /** Return a serialization for Node objects, using a reflective rule. */
651 Serialization nodeSerializerReflective(Node n) {
652 return new Serialization()
653 ..addRuleFor(Node, constructorFields: ["name"])
654 ..namedObjects['Node'] = reflect(new Node('')).type;
655 }
656
657 /**
658 * Return a serialization for Node objects but using Maps for the internal
659 * representation rather than lists.
660 */
661 Serialization nodeSerializerUsingMaps(Node n) {
662 return new Serialization()
663 // Get the type using runtimeType to verify that works.
664 ..addRuleFor(n.runtimeType, constructorFields: ["name"]).configureForMaps()
665 ..namedObjects['Node'] = reflect(new Node('')).type;
666 }
667
668 /**
669 * Return a serialization for Node objects but using Maps for the internal
670 * representation rather than lists.
671 */
672 Serialization nodeSerializerCustom(Node n) {
673 return new Serialization()
674 ..addRule(new NodeRule());
675 }
676
677 /**
678 * Return a serialization for Node objects where the "parent" instance
679 * variable is considered essential state.
680 */
681 Serialization nodeSerializerWithEssentialParent(Node n) {
682 // Force the node rule to be first, in order to make a cycle which would
683 // not cause a problem if we handled the list first, because the list
684 // considers all of its state non-essential, thus breaking the cycle.
685 var s = new Serialization.blank()
686 ..addRuleFor(
687 Node,
688 constructor: "parentEssential",
689 constructorFields: ["parent"])
690 ..addDefaultRules()
691 ..namedObjects['Node'] = reflect(new Node('')).type
692 ..selfDescribing = false;
693 return s;
694 }
695
696 /** Return a serialization for Node objects using a ClosureToMapRule. */
697 Serialization nodeSerializerNonReflective(Node n) {
698 var rule = new ClosureRule(
699 n.runtimeType,
700 (o) => {"name" : o.name, "children" : o.children, "parent" : o.parent},
701 (map) => new Node(map["name"]),
702 (object, map) {
703 object
704 ..children = map["children"]
705 ..parent = map["parent"];
706 });
707 return new Serialization()
708 ..selfDescribing = false
709 ..addRule(rule);
710 }
711
712 /**
713 * Run a round-trip test on a simple tree of nodes, using a serialization
714 * that's returned by the [serializerSetUp] function.
715 */
716 void runRoundTripTest(Function serializerSetUp) {
717 Node n1 = new Node("1"), n2 = new Node("2"), n3 = new Node("3");
718 n1.children = [n2, n3];
719 n2.parent = n1;
720 n3.parent = n1;
721 var s = serializerSetUp(n1);
722 var output = s.write(n2);
723 var s2 = serializerSetUp(n1);
724 var m2 = s2.read(output);
725 var m1 = m2.parent;
726 expect(m1 is Node, isTrue);
727 var children = m1.children;
728 expect(m1.name,"1");
729 var m3 = m1.children.last;
730 expect(m2.name, "2");
731 expect(m3.name, "3");
732 expect(m2.parent, m1);
733 expect(m3.parent, m1);
734 expect(m1.parent, isNull);
735 }
736
737 /**
738 * Run a round-trip test on a simple of nodes, but using the flat format
739 * rather than the maps.
740 */
741 void runRoundTripTestFlat(serializerSetUp) {
742 Node n1 = new Node("1"), n2 = new Node("2"), n3 = new Node("3");
743 n1.children = [n2, n3];
744 n2.parent = n1;
745 n3.parent = n1;
746 var s = serializerSetUp(n1);
747 var output = s.write(n2, format: const SimpleFlatFormat());
748 expect(output is List, isTrue);
749 var s2 = serializerSetUp(n1);
750 var m2 = s2.read(output, format: const SimpleFlatFormat());
751 var m1 = m2.parent;
752 expect(m1 is Node, isTrue);
753 var children = m1.children;
754 expect(m1.name,"1");
755 var m3 = m1.children.last;
756 expect(m2.name, "2");
757 expect(m3.name, "3");
758 expect(m2.parent, m1);
759 expect(m3.parent, m1);
760 expect(m1.parent, isNull);
761 }
762
763 /** Extract the state from [object] using the rules in [s] and return it. */
764 List states(object, Serialization s) {
765 var rules = s.rulesFor(object, null);
766 return rules.map((x) => x.extractState(object, doNothing, null)).toList();
767 }
768
769 /** A hard-coded rule for serializing Node instances. */
770 class NodeRule extends CustomRule {
771 bool appliesTo(instance, _) => instance.runtimeType == Node;
772 getState(instance) => [instance.parent, instance.name, instance.children];
773 create(state) => new Node(state[1]);
774 void setState(Node node, state) {
775 node.parent = state[0];
776 node.children = state[2];
777 }
778 }
779
780 /**
781 * This is a rather silly rule which stores the address data in a map,
782 * but inverts the keys and values, so we look up values and find the
783 * corresponding key. This will lead to maps that aren't allowed in JSON,
784 * and which have keys that need to be dereferenced.
785 */
786 class PersonRuleReturningMapWithNonStringKey extends CustomRule {
787 appliesTo(instance, _) => instance is Person;
788 getState(instance) {
789 return new Map()
790 ..[instance.name] = "name"
791 ..[instance.address] = "address";
792 }
793 create(state) => new Person();
794 void setState(Person a, state) {
795 a.name = findValue("name", state);
796 a.address = findValue("address", state);
797 }
798 findValue(String key, Map state) {
799 var answer;
800 for (var each in state.keys) {
801 var value = state[each];
802 if (value == key) return each;
803 }
804 return null;
805 }
806 }
807
808 /**
809 * Function used in an isolate to make sure that the output passes through
810 * isolate serialization properly.
811 */
812 void echo(initialMessage) {
813 var msg = initialMessage[0];
814 var reply = initialMessage[1];
815 reply.send(msg);
816 }
OLDNEW
« no previous file with comments | « pkg/serialization/test/no_library_test.dart ('k') | pkg/serialization/test/test_models.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698