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

Unified Diff: pkg/mdv_observe/test/list_change_test.dart

Issue 14732003: Implement Model-Driven-Views spec for Dart (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: try upload again Created 7 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: pkg/mdv_observe/test/list_change_test.dart
diff --git a/pkg/mdv_observe/test/list_change_test.dart b/pkg/mdv_observe/test/list_change_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e7e1249785bf12d68bf251416c769a74553135cb
--- /dev/null
+++ b/pkg/mdv_observe/test/list_change_test.dart
@@ -0,0 +1,290 @@
+// Copyright (c) 2013, 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.
+
+import 'package:mdv_observe/mdv_observe.dart';
+import 'package:unittest/unittest.dart';
+import 'utils.dart';
+
+// This file contains code ported from:
+// https://github.com/rafaelw/ChangeSummary/blob/master/tests/test.js
+
+main() {
+ // TODO(jmesserly): rename this? Is summarizeListChanges coming back?
+ group('summarizeListChanges', listChangeTests);
+}
+
+// TODO(jmesserly): port or write array fuzzer tests
+listChangeTests() {
+
+ test('sequential adds', () {
+ var model = toObservable([]);
+ model.add(0);
+
+ var summary;
+ var sub = model.changes.listen((r) { summary = _filter(r); });
+
+ model.add(1);
+ model.add(2);
+
+ expect(summary, null);
+ deliverChangeRecords();
+
+ expectChanges(summary, [_delta(1, 0, 2)]);
+ });
+
+ test('List Splice Truncate And Expand With Length', () {
+ var model = toObservable(['a', 'b', 'c', 'd', 'e']);
+
+ var summary;
+ var sub = model.changes.listen((r) { summary = _filter(r); });
+
+ model.length = 2;
+
+ deliverChangeRecords();
+ expectChanges(summary, [_delta(2, 3, 0)]);
+ summary = null;
+
+ model.length = 5;
+
+ deliverChangeRecords();
+ expectChanges(summary, [_delta(2, 0, 3)]);
+ });
+
+ group('List deltas can be applied', () {
+
+ var summary = null;
+
+ observeArray(model) {
+ model.changes.listen((records) { summary = _filter(records); });
+ }
+
+ applyAndCheckDeltas(model, copy) {
+ summary = null;
+ deliverChangeRecords();
+
+ // apply deltas to the copy
+ for (var delta in summary) {
+ copy.removeRange(delta.index, delta.index + delta.removedCount);
+ for (int i = delta.addedCount - 1; i >= 0; i--) {
+ copy.insert(delta.index, model[delta.index + i]);
+ }
+ }
+
+ // Note: compare strings for easier debugging.
+ expect('$copy', '$model', reason: '!!! summary $summary');
+ }
+
+ test('Contained', () {
+ var model = toObservable(['a', 'b']);
+ var copy = model.toList();
+ observeArray(model);
+
+ model.removeAt(1);
+ model.insertAll(0, ['c', 'd', 'e']);
+ model.removeRange(1, 3);
+ model.insert(1, 'f');
+
+ applyAndCheckDeltas(model, copy);
+ });
+
+ test('Delete Empty', () {
+ var model = toObservable([1]);
+ var copy = model.toList();
+ observeArray(model);
+
+ model.removeAt(0);
+ model.insertAll(0, ['a', 'b', 'c']);
+
+ applyAndCheckDeltas(model, copy);
+ });
+
+ test('Right Non Overlap', () {
+ var model = toObservable(['a', 'b', 'c', 'd']);
+ var copy = model.toList();
+ observeArray(model);
+
+ model.removeRange(0, 1);
+ model.insert(0, 'e');
+ model.removeRange(2, 3);
+ model.insertAll(2, ['f', 'g']);
+
+ applyAndCheckDeltas(model, copy);
+ });
+
+ test('Left Non Overlap', () {
+ var model = toObservable(['a', 'b', 'c', 'd']);
+ var copy = model.toList();
+ observeArray(model);
+
+ model.removeRange(3, 4);
+ model.insertAll(3, ['f', 'g']);
+ model.removeRange(0, 1);
+ model.insert(0, 'e');
+
+ applyAndCheckDeltas(model, copy);
+ });
+
+ test('Right Adjacent', () {
+ var model = toObservable(['a', 'b', 'c', 'd']);
+ var copy = model.toList();
+ observeArray(model);
+
+ model.removeRange(1, 2);
+ model.insert(3, 'e');
+ model.removeRange(2, 3);
+ model.insertAll(0, ['f', 'g']);
+
+ applyAndCheckDeltas(model, copy);
+ });
+
+ test('Left Adjacent', () {
+ var model = toObservable(['a', 'b', 'c', 'd']);
+ var copy = model.toList();
+ observeArray(model);
+
+ model.removeRange(2, 4);
+ model.insert(2, 'e');
+
+ model.removeAt(1);
+ model.insertAll(1, ['f', 'g']);
+
+ applyAndCheckDeltas(model, copy);
+ });
+
+ test('Right Overlap', () {
+ var model = toObservable(['a', 'b', 'c', 'd']);
+ var copy = model.toList();
+ observeArray(model);
+
+ model.removeAt(1);
+ model.insert(1, 'e');
+ model.removeAt(1);
+ model.insertAll(1, ['f', 'g']);
+
+ applyAndCheckDeltas(model, copy);
+ });
+
+ test('Left Overlap', () {
+ var model = toObservable(['a', 'b', 'c', 'd']);
+ var copy = model.toList();
+ observeArray(model);
+
+ model.removeAt(2);
+ model.insertAll(2, ['e', 'f', 'g']);
+ // a b [e f g] d
+ model.removeRange(1, 3);
+ model.insertAll(1, ['h', 'i', 'j']);
+ // a [h i j] f g d
+
+ applyAndCheckDeltas(model, copy);
+ });
+
+ test('Prefix And Suffix One In', () {
+ var model = toObservable(['a', 'b', 'c', 'd']);
+ var copy = model.toList();
+ observeArray(model);
+
+ model.insert(0, 'z');
+ model.add('z');
+
+ applyAndCheckDeltas(model, copy);
+ });
+
+ test('Remove First', () {
+ var model = toObservable([16, 15, 15]);
+ var copy = model.toList();
+ observeArray(model);
+
+ model.removeAt(0);
+
+ applyAndCheckDeltas(model, copy);
+ });
+
+ test('Update Remove', () {
+ var model = toObservable(['a', 'b', 'c', 'd']);
+ var copy = model.toList();
+ observeArray(model);
+
+ model.removeAt(2);
+ model.insertAll(2, ['e', 'f', 'g']); // a b [e f g] d
+ model[0] = 'h';
+ model.removeAt(1);
+
+ applyAndCheckDeltas(model, copy);
+ });
+
+ test('Remove Mid List', () {
+ var model = toObservable(['a', 'b', 'c', 'd']);
+ var copy = model.toList();
+ observeArray(model);
+
+ model.removeAt(2);
+
+ applyAndCheckDeltas(model, copy);
+ });
+ });
+
+ group('edit distance', () {
+ var summary = null;
+
+ observeArray(model) {
+ model.changes.listen((records) { summary = _filter(records); });
+ }
+
+ assertEditDistance(orig, expectDistance) {
+ summary = null;
+ deliverChangeRecords();
+ var actualDistance = 0;
+
+ if (summary != null) {
+ for (var delta in summary) {
+ actualDistance += delta.addedCount + delta.removedCount;
+ }
+ }
+
+ expect(actualDistance, expectDistance);
+ }
+
+ test('add items', () {
+ var model = toObservable([]);
+ observeArray(model);
+ model.addAll([1, 2, 3]);
+ assertEditDistance(model, 3);
+ });
+
+ test('trunacte and add, sharing a contiguous block', () {
+ var model = toObservable(['x', 'x', 'x', 'x', '1', '2', '3']);
+ observeArray(model);
+ model.length = 0;
+ model.addAll(['1', '2', '3', 'y', 'y', 'y', 'y']);
+ // Note: unlike the JS implementation, we don't perform a full diff.
+ // The change records are computed with no regards to the *contents* of
+ // the array. Thus, we get 14 instead of 8.
+ assertEditDistance(model, 14);
+ });
+
+ test('truncate and add, sharing a discontiguous block', () {
+ var model = toObservable(['1', '2', '3', '4', '5']);
+ observeArray(model);
+ model.length = 0;
+ model.addAll(['a', '2', 'y', 'y', '4', '5', 'z', 'z']);
+ // Note: unlike the JS implementation, we don't perform a full diff.
+ // The change records are computed with no regards to the *contents* of
+ // the array. Thus, we get 13 instead of 7.
+ assertEditDistance(model, 13);
+ });
+
+ test('insert at beginning and end', () {
+ var model = toObservable([2, 3, 4]);
+ observeArray(model);
+ model.insert(0, 5);
+ model[2] = 6;
+ model.add(7);
+ assertEditDistance(model, 4);
+ });
+ });
+}
+
+_delta(i, r, a) => new ListChangeRecord(i, removedCount: r, addedCount: a);
+_filter(records) => records.where((r) => r is ListChangeRecord).toList();

Powered by Google App Engine
This is Rietveld 408576698