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

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

Issue 11931030: Add a MapRule (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Adds another test Created 7 years, 10 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
OLDNEW
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';
(...skipping 29 matching lines...) Expand all
40 // TODO(alanknight): Tests that rely on what index rules are going to be 40 // TODO(alanknight): Tests that rely on what index rules are going to be
41 // at are very fragile. At least abstract it to something calculated. 41 // at are very fragile. At least abstract it to something calculated.
42 var p1 = new Person()..name = 'Alice'..address = a1; 42 var p1 = new Person()..name = 'Alice'..address = a1;
43 var s = new Serialization() 43 var s = new Serialization()
44 ..addRuleFor(p1).configureForMaps() 44 ..addRuleFor(p1).configureForMaps()
45 ..addRuleFor(a1).configureForMaps(); 45 ..addRuleFor(a1).configureForMaps();
46 // TODO(alanknight): Need a better API for getting to flat state without 46 // TODO(alanknight): Need a better API for getting to flat state without
47 // actually writing. 47 // actually writing.
48 var w = new Writer(s); 48 var w = new Writer(s);
49 w.write(p1); 49 w.write(p1);
50 var flatPerson = w.states[3].first; 50 var personRule = s.rules.firstMatching(
51 (x) => x is BasicRule && x.type == reflect(p1).type);
Jennifer Messerly 2013/01/25 01:19:59 Do type literals work now? if so could this be "x.
Alan Knight 2013/01/26 01:33:38 They work syntactically, but they return a Type, a
52 var flatPerson = w.states[personRule.number].first;
51 var primStates = w.states.first; 53 var primStates = w.states.first;
52 expect(primStates.isEmpty, true); 54 expect(primStates.isEmpty, true);
53 expect(flatPerson["name"], "Alice"); 55 expect(flatPerson["name"], "Alice");
54 var ref = flatPerson["address"]; 56 var ref = flatPerson["address"];
55 expect(ref is Reference, true); 57 expect(ref is Reference, true);
56 expect(ref.ruleNumber, 4); 58 var addressRule = s.rules.firstMatching(
59 (x) => x is BasicRule && x.type == reflect(a1).type);
60 expect(ref.ruleNumber, addressRule.number);
57 expect(ref.objectNumber, 0); 61 expect(ref.objectNumber, 0);
58 expect(w.states[4].first['street'], 'N 34th'); 62 expect(w.states[addressRule.number].first['street'], 'N 34th');
59 }); 63 });
60 64
61 test('exclude fields', () { 65 test('exclude fields', () {
62 var s = new Serialization() 66 var s = new Serialization()
63 ..addRuleFor(a1, 67 ..addRuleFor(a1,
64 excludeFields: ['state', 'zip']).configureForMaps(); 68 excludeFields: ['state', 'zip']).configureForMaps();
65 var extracted = states(a1, s).first; 69 var extracted = states(a1, s).first;
66 expect(extracted.length, 2); 70 expect(extracted.length, 2);
67 expect(extracted['street'], 'N 34th'); 71 expect(extracted['street'], 'N 34th');
68 expect(extracted['city'], 'Seattle'); 72 expect(extracted['city'], 'Seattle');
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 expect(all.contains(n2), isTrue); 203 expect(all.contains(n2), isTrue);
200 expect(all.contains(n3), isTrue); 204 expect(all.contains(n3), isTrue);
201 expect(all.contains(n1.children), isTrue); 205 expect(all.contains(n1.children), isTrue);
202 }); 206 });
203 207
204 test('Flatten references in a cyclical structure', () { 208 test('Flatten references in a cyclical structure', () {
205 var s = new Serialization(); 209 var s = new Serialization();
206 var w = new Writer(s); 210 var w = new Writer(s);
207 w.trace = new Trace(w); 211 w.trace = new Trace(w);
208 w.write(n1); 212 w.write(n1);
209 expect(w.states.length, 4); // prims, lists, essential lists, basic 213 expect(w.states.length, 5); // prims, lists, essential lists, basic
210 var children = 0, name = 1, parent = 2; 214 var children = 0, name = 1, parent = 2;
211 List rootNode = w.states[3].where((x) => x[name] == "1").toList(); 215 var nodeRule = s.rules.firstMatching((x) => x is BasicRule);
216 List rootNode = w.states[nodeRule.number].where(
217 (x) => x[name] == "1").toList();
212 rootNode = rootNode.first; 218 rootNode = rootNode.first;
213 expect(rootNode[parent], isNull); 219 expect(rootNode[parent], isNull);
214 var list = w.states[1].first; 220 var list = w.states[1].first;
215 expect(w.stateForReference(rootNode[children]), list); 221 expect(w.stateForReference(rootNode[children]), list);
216 var parentNode = w.stateForReference(list[0])[parent]; 222 var parentNode = w.stateForReference(list[0])[parent];
217 expect(w.stateForReference(parentNode), rootNode); 223 expect(w.stateForReference(parentNode), rootNode);
218 }); 224 });
219 225
220 test('round-trip', () { 226 test('round-trip', () {
221 runRoundTripTest(nodeSerializerReflective); 227 runRoundTripTest(nodeSerializerReflective);
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 var writer = s.newWriter(new SimpleJsonFormat(storeRoundTripInfo: true)); 371 var writer = s.newWriter(new SimpleJsonFormat(storeRoundTripInfo: true));
366 var out = writer.write(p1); 372 var out = writer.write(p1);
367 var reader = s.newReader(new SimpleJsonFormat(storeRoundTripInfo: true)); 373 var reader = s.newReader(new SimpleJsonFormat(storeRoundTripInfo: true));
368 var p2 = reader.read(out); 374 var p2 = reader.read(out);
369 expect(p2.name, "Alice"); 375 expect(p2.name, "Alice");
370 var a2 = p2.address; 376 var a2 = p2.address;
371 expect(a2.street, "N 34th"); 377 expect(a2.street, "N 34th");
372 expect(a2.city, "Seattle"); 378 expect(a2.city, "Seattle");
373 }); 379 });
374 380
381 test("Straight JSON format, root is a Map", () {
382 // Note that we can't use the usual round-trip test because it has cycles.
383 var p1 = new Person()..name = 'Alice'..address = a1;
384 // Use maps for one rule, lists for the other.
385 var s = new Serialization()
386 ..addRuleFor(a1)
387 ..addRuleFor(p1).configureForMaps();
388 var writer = s.newWriter(new SimpleJsonFormat(storeRoundTripInfo: true));
389 var out = writer.write({"stuff" : p1});
390 var reader = s.newReader(new SimpleJsonFormat(storeRoundTripInfo: true));
Jennifer Messerly 2013/01/25 01:19:59 out of curiosity, would it work to use the same Si
Alan Knight 2013/01/26 01:33:38 Yes. Changed one of these to re-use the same one a
391 var p2 = reader.read(out)["stuff"];
392 expect(p2.name, "Alice");
393 var a2 = p2.address;
394 expect(a2.street, "N 34th");
395 expect(a2.city, "Seattle");
396 });
397
398
375 test("Straight JSON format, round-trip with named objects", () { 399 test("Straight JSON format, round-trip with named objects", () {
376 // Note that we can't use the usual round-trip test because it has cycles. 400 // Note that we can't use the usual round-trip test because it has cycles.
377 var p1 = new Person()..name = 'Alice'..address = a1; 401 var p1 = new Person()..name = 'Alice'..address = a1;
378 // Use maps for one rule, lists for the other. 402 // Use maps for one rule, lists for the other.
379 var s = new Serialization() 403 var s = new Serialization()
380 ..addRule(new NamedObjectRule()) 404 ..addRule(new NamedObjectRule())
381 ..addRuleFor(a1) 405 ..addRuleFor(a1)
382 ..addRuleFor(p1).configureForMaps() 406 ..addRuleFor(p1).configureForMaps()
383 ..namedObjects["foo"] = a1; 407 ..namedObjects["foo"] = a1;
384 var writer = s.newWriter(new SimpleJsonFormat(storeRoundTripInfo: true)); 408 var writer = s.newWriter(new SimpleJsonFormat(storeRoundTripInfo: true));
385 var out = writer.write(p1); 409 var out = writer.write(p1);
386 var reader = s.newReader(new SimpleJsonFormat(storeRoundTripInfo: true)); 410 var reader = s.newReader(new SimpleJsonFormat(storeRoundTripInfo: true));
387 var p2 = reader.read(out, {"foo" : 12}); 411 var p2 = reader.read(out, {"foo" : 12});
388 expect(p2.name, "Alice"); 412 expect(p2.name, "Alice");
389 var a2 = p2.address; 413 var a2 = p2.address;
390 expect(a2, 12); 414 expect(a2, 12);
391 }); 415 });
416
417 test("Maps", () {
418 var s = new Serialization()..selfDescribing = false;
419 var p1 = new Person()..name = 'Alice'..address = a1;
420 var data = new Map();
421 data["simple data"] = 1;
422 data[p1] = a1;
423 data[a1] = p1;
424 var formats = [new SimpleFlatFormat(), new SimpleMapFormat(),
425 new SimpleJsonFormat(storeRoundTripInfo: true)];
426 for (var eachFormat in formats) {
427 var output = s.write(data, eachFormat);
428 var reader = s.newReader(eachFormat);
429 var input = reader.read(output);
430 expect(input["simple data"], data["simple data"]);
431 var p2 = input.keys.firstMatching((x) => x is Person);
432 var a2 = input.keys.firstMatching((x) => x is Address);
433 if (eachFormat is SimpleJsonFormat) {
434 // JSON doesn't handle cycles, so these won't be identical.
435 expect(input[p2] is Address, isTrue);
436 expect(input[a2] is Person, isTrue);
437 var a3 = input[p2];
438 expect(a3.city, a2.city);
439 expect(a3.state, a2.state);
440 expect(a3.state, a2.state);
441 var p3 = input[a2];
442 expect(p3.name, p2.name);
443 expect(p3.rank, p2.rank);
444 expect(p3.address.city, a2.city);
445 } else {
446 expect(input[p2], same(a2));
447 expect(input[a2], same(p2));
448 }
449 }
450 });
451
452 test("Map with string keys stays that way", () {
453 var s = new Serialization()..addRuleFor(new Person());
454 var data = {"abc" : 1, "def" : "ghi"};
455 data["person"] = new Person()..name = "Foo";
456 var output = s.write(data, new SimpleMapFormat());
457 var mapRule = s.rules.firstMatching((x) => x is MapRule);
458 var map = json.parse(output)["data"][mapRule.number][0];
459 expect(map is Map, isTrue);
460 expect(map["abc"], 1);
461 expect(map["def"], "ghi");
462 expect(new Reader(s).asReference(map["person"]) is Reference, isTrue);
463 });
392 } 464 }
393 465
394 /****************************************************************************** 466 /******************************************************************************
395 * The end of the tests and the beginning of various helper functions to make 467 * The end of the tests and the beginning of various helper functions to make
396 * it easier to write the repetitive sections. 468 * it easier to write the repetitive sections.
397 ******************************************************************************/ 469 ******************************************************************************/
398 470
399 /** Create a Serialization for serializing Serializations. */ 471 /** Create a Serialization for serializing Serializations. */
400 Serialization metaSerialization() { 472 Serialization metaSerialization() {
401 // Make some bogus rule instances so we have something to feed rule creation 473 // Make some bogus rule instances so we have something to feed rule creation
402 // and get their types. If only we had class literals implemented... 474 // and get their types. If only we had class literals implemented...
403 var basicRule = new BasicRule(reflect(null).type, '', [], [], []); 475 var basicRule = new BasicRule(reflect(null).type, '', [], [], []);
404 476
405 var meta = new Serialization() 477 var meta = new Serialization()
406 ..selfDescribing = false 478 ..selfDescribing = false
407 ..addRuleFor(new ListRule()) 479 ..addRuleFor(new ListRule())
408 ..addRuleFor(new PrimitiveRule()) 480 ..addRuleFor(new PrimitiveRule())
409 // TODO(alanknight): Handle CustomRule as well. 481 // TODO(alanknight): Handle CustomRule as well.
410 // Note that we're passing in a constant for one of the fields. 482 // Note that we're passing in a constant for one of the fields.
411 ..addRuleFor(basicRule, 483 ..addRuleFor(basicRule,
412 constructorFields: ['type', 484 constructorFields: ['type',
413 'constructorName', 485 'constructorName',
414 'constructorFields', 'regularFields', []], 486 'constructorFields', 'regularFields', []],
415 fields: []) 487 fields: [])
416 ..addRuleFor(new Serialization()).setFieldWith('rules', 488 ..addRuleFor(new Serialization(), constructor: "blank")
417 (InstanceMirror s, List rules) { 489 .setFieldWith('rules',
490 (InstanceMirror s, List rules) {
418 rules.forEach((x) => s.reflectee.addRule(x)); 491 rules.forEach((x) => s.reflectee.addRule(x));
419 }) 492 })
420 ..addRule(new NamedObjectRule()) 493 ..addRule(new NamedObjectRule())
421 ..addRule(new MirrorRule()); 494 ..addRule(new MirrorRule());
422 return meta; 495 return meta;
423 } 496 }
424 497
425 /** 498 /**
426 * Read back a simple object, assumed to be the only one of its class in the 499 * Read back a simple object, assumed to be the only one of its class in the
427 * reader. 500 * reader.
428 */ 501 */
429 readBackSimple(Serialization s, object, Reader reader) { 502 readBackSimple(Serialization s, object, Reader reader) {
430 var rule = s.rulesFor(object, null).first; 503 var rule = s.rulesFor(object, null).first;
431 reader.inflateForRule(rule); 504 reader.inflateForRule(rule);
432 var list2 = reader.allObjectsForRule(rule).first; 505 var list2 = reader.allObjectsForRule(rule).first;
433 return list2; 506 return list2;
434 } 507 }
435 508
436 /** 509 /**
437 * Set up a basic reader with some fake data. Hard-codes the assumption 510 * Set up a basic reader with some fake data. Hard-codes the assumption
438 * of how many rules there are. 511 * of how many rules there are.
439 */ 512 */
440 Reader setUpReader(aSerialization, sampleData) { 513 Reader setUpReader(aSerialization, sampleData) {
441 var reader = new Reader(aSerialization); 514 var reader = new Reader(aSerialization);
442 // We're not sure which rule needs the sample data, so put it everywhere 515 // We're not sure which rule needs the sample data, so put it everywhere
443 // and trust that the extra will just be ignored. 516 // and trust that the extra will just be ignored.
444 reader.data = [[sampleData], [sampleData], [sampleData], [sampleData]]; 517 reader.data = new List(10).mappedBy((x) => [sampleData]).toList();
Jennifer Messerly 2013/01/25 01:19:59 Would it work to use "new List.filled(10, [sampleD
Alan Knight 2013/01/26 01:33:38 Yes, done.
445 return reader; 518 return reader;
446 } 519 }
447 520
448 /** Return a serialization for Node objects, using a reflective rule. */ 521 /** Return a serialization for Node objects, using a reflective rule. */
449 Serialization nodeSerializerReflective(Node n) { 522 Serialization nodeSerializerReflective(Node n) {
450 return new Serialization() 523 return new Serialization()
451 ..addRuleFor(n, constructorFields: ["name"]) 524 ..addRuleFor(n, constructorFields: ["name"])
452 ..namedObjects['Node'] = reflect(new Node('')).type; 525 ..namedObjects['Node'] = reflect(new Node('')).type;
453 } 526 }
454 527
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 640
568 /** A hard-coded rule for serializing Node instances. */ 641 /** A hard-coded rule for serializing Node instances. */
569 class NodeRule extends CustomRule { 642 class NodeRule extends CustomRule {
570 bool appliesTo(instance, _) => instance.runtimeType == Node; 643 bool appliesTo(instance, _) => instance.runtimeType == Node;
571 getState(instance) => [instance.parent, instance.name, instance.children]; 644 getState(instance) => [instance.parent, instance.name, instance.children];
572 create(state) => new Node(state[1]); 645 create(state) => new Node(state[1]);
573 setState(Node node, state) { 646 setState(Node node, state) {
574 node.parent = state[0]; 647 node.parent = state[0];
575 node.children = state[2]; 648 node.children = state[2];
576 } 649 }
577 } 650 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698