e79a142cf2
There is another batch of style changes coming out in 3.8, so I'm going through and reformatting the SDK again. (Well, I didn't finish the reformat the first time, so not fully "again", I guess.) Change-Id: I83d9809fc0da71010c0ef567c208981df68c351c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/425201 Commit-Queue: Lasse Nielsen <lrn@google.com> Reviewed-by: Lasse Nielsen <lrn@google.com> Auto-Submit: Bob Nystrom <rnystrom@google.com>
279 lines
7.9 KiB
Dart
279 lines
7.9 KiB
Dart
// Copyright (c) 2011, 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 for Splay-tree data structures.
|
|
library splay_tree_test;
|
|
|
|
import "package:expect/expect.dart";
|
|
import "package:expect/variations.dart";
|
|
import 'dart:collection';
|
|
|
|
main() {
|
|
// Simple tests.
|
|
SplayTreeMap tree = new SplayTreeMap();
|
|
tree[1] = "first";
|
|
tree[3] = "third";
|
|
tree[5] = "fifth";
|
|
tree[2] = "second";
|
|
tree[4] = "fourth";
|
|
|
|
var correctSolution = ["first", "second", "third", "fourth", "fifth"];
|
|
|
|
tree.forEach((key, value) {
|
|
Expect.equals(true, key >= 1);
|
|
Expect.equals(true, key <= 5);
|
|
Expect.equals(value, correctSolution[key - 1]);
|
|
});
|
|
|
|
for (var v in ["first", "second", "third", "fourth", "fifth"]) {
|
|
Expect.isTrue(tree.containsValue(v));
|
|
}
|
|
Expect.isFalse(tree.containsValue("sixth"));
|
|
|
|
tree[7] = "seventh";
|
|
|
|
Expect.equals(1, tree.firstKey());
|
|
Expect.equals(7, tree.lastKey());
|
|
|
|
Expect.equals(2, tree.lastKeyBefore(3));
|
|
Expect.equals(4, tree.firstKeyAfter(3));
|
|
|
|
Expect.equals(null, tree.lastKeyBefore(1));
|
|
Expect.equals(2, tree.firstKeyAfter(1));
|
|
|
|
Expect.equals(4, tree.lastKeyBefore(5));
|
|
Expect.equals(7, tree.firstKeyAfter(5));
|
|
|
|
Expect.equals(5, tree.lastKeyBefore(7));
|
|
Expect.equals(null, tree.firstKeyAfter(7));
|
|
|
|
Expect.equals(5, tree.lastKeyBefore(6));
|
|
Expect.equals(7, tree.firstKeyAfter(6));
|
|
|
|
testSetFrom();
|
|
regressRemoveWhere();
|
|
regressRemoveWhere2();
|
|
regressFromCompare();
|
|
regressIncomparable();
|
|
|
|
// Setting values do not break iteration.
|
|
// Setting values during iteration may show either old or new value,
|
|
// but must be consistent when read.
|
|
var map = SplayTreeMap<String, int>()
|
|
..["a"] = 1
|
|
..["b"] = 2;
|
|
var index = 0;
|
|
for (var v in map.values) {
|
|
if (index == 0) {
|
|
Expect.equals(1, v);
|
|
map["b"] = 42;
|
|
} else {
|
|
Expect.equals(1, index);
|
|
if (v != 42 && v != 2) {
|
|
Expect.fail('map["b"] not 2 or 42');
|
|
}
|
|
map["b"] = 2;
|
|
}
|
|
index++;
|
|
}
|
|
|
|
index = 0;
|
|
// Same using explicit iterator.
|
|
for (var iterator = map.values.iterator; iterator.moveNext(); index++) {
|
|
if (index == 0) {
|
|
Expect.equals(1, iterator.current);
|
|
map["b"] = 42;
|
|
} else {
|
|
Expect.equals(1, index);
|
|
var v = iterator.current;
|
|
if (v != 42 && v != 2) {
|
|
Expect.fail('map["b"] not 2 or 42');
|
|
}
|
|
map["b"] = 2;
|
|
var v2 = iterator.current;
|
|
Expect.equals(v, v2, "current getter not consistent: $v -> $v2");
|
|
}
|
|
}
|
|
|
|
// Same for values accessed through `.entries`.
|
|
for (var entry in map.entries) {
|
|
if (entry.key == "a") {
|
|
Expect.equals(1, entry.value);
|
|
map["b"] = 42;
|
|
} else {
|
|
Expect.equals("b", entry.key);
|
|
var v = entry.value;
|
|
if (v != 42 && v != 2) {
|
|
Expect.fail('map["b"] not 2 or 42');
|
|
}
|
|
map["b"] = 2;
|
|
var v2 = entry.value;
|
|
Expect.equals(v, v2, "current getter not consistent: $v -> $v2");
|
|
}
|
|
}
|
|
|
|
for (var iterator = map.entries.iterator; iterator.moveNext();) {
|
|
if (iterator.current.key == "a") {
|
|
Expect.equals(1, iterator.current.value);
|
|
map["b"] = 42;
|
|
} else {
|
|
Expect.equals("b", iterator.current.key);
|
|
var v = iterator.current.value;
|
|
if (v != 42 && v != 2) {
|
|
Expect.fail('map["b"] not 2 or 42');
|
|
}
|
|
map["b"] = 2;
|
|
var v2 = iterator.current.value;
|
|
Expect.equals(v, v2, "current getter not consistent: $v -> $v2");
|
|
}
|
|
}
|
|
}
|
|
|
|
void regressRemoveWhere() {
|
|
// Regression test. Fix in https://codereview.chromium.org/148523006/
|
|
var t = new SplayTreeSet();
|
|
t.addAll([1, 3, 5, 7, 2, 4, 6, 8, 0]);
|
|
var seen = new List<bool>.filled(9, false);
|
|
t.removeWhere((x) {
|
|
// Called only once per element.
|
|
Expect.isFalse(seen[x], "seen $x");
|
|
seen[x] = true;
|
|
return x.isOdd;
|
|
});
|
|
}
|
|
|
|
void regressRemoveWhere2() {
|
|
// Regression test for http://dartbug.com/18676
|
|
// Removing all elements with removeWhere causes error.
|
|
|
|
var t = new SplayTreeSet();
|
|
t.addAll([1, 2, 3, 4, 5]);
|
|
t.removeWhere((_) => true); // Should not throw.
|
|
Expect.isTrue(t.isEmpty);
|
|
t.addAll([1, 2, 3, 4, 5]);
|
|
t.retainWhere((_) => false); // Should not throw.
|
|
Expect.isTrue(t.isEmpty);
|
|
}
|
|
|
|
void testSetFrom() {
|
|
var set1 = new SplayTreeSet<num>()..addAll([1, 2, 3, 4, 5]);
|
|
var set2 = new SplayTreeSet<int>.from(set1);
|
|
Expect.equals(5, set2.length);
|
|
for (int i = 1; i <= 5; i++) {
|
|
Expect.isTrue(set2.contains(i));
|
|
}
|
|
|
|
set1 = new SplayTreeSet<num>()..addAll([0, 1, 2.4, 3.14, 5]);
|
|
set2 = new SplayTreeSet<int>.from(set1.where((x) => x is int));
|
|
Expect.equals(3, set2.length);
|
|
}
|
|
|
|
void regressFromCompare() {
|
|
// Regression test for http://dartbug.com/23387.
|
|
// The compare and isValidKey arguments to SplayTreeMap.from were ignored.
|
|
|
|
int compare(a, b) {
|
|
if (a is IncomparableKey && b is IncomparableKey) {
|
|
return b.id - a.id;
|
|
}
|
|
throw "isValidKey failure";
|
|
}
|
|
|
|
bool isValidKey(o) => o is IncomparableKey;
|
|
IncomparableKey key(int n) => new IncomparableKey(n);
|
|
|
|
var entries = {key(0): 0, key(1): 1, key(2): 2, key(0): 0};
|
|
Expect.equals(4, entries.length);
|
|
var map = new SplayTreeMap<IncomparableKey, int>.from(
|
|
entries,
|
|
compare,
|
|
isValidKey,
|
|
);
|
|
Expect.equals(3, map.length);
|
|
for (int i = 0; i < 3; i++) {
|
|
Expect.isTrue(map.containsKey(key(i)));
|
|
Expect.equals(i, map[key(i)]);
|
|
}
|
|
Expect.isFalse(map.containsKey(key(5)));
|
|
Expect.isFalse(map.containsKey(1));
|
|
Expect.isFalse(map.containsKey("string"));
|
|
Expect.equals(null, map[key(5)]);
|
|
Expect.equals(null, map[1]);
|
|
Expect.equals(null, map["string"]);
|
|
map[key(5)] = 42;
|
|
Expect.equals(4, map.length);
|
|
Expect.equals(42, map[key(5)]);
|
|
}
|
|
|
|
// Incomparable keys throw when added, even on an empty collection.
|
|
void regressIncomparable() {
|
|
// With no `compare` function given, it defaults to one that does
|
|
// dynamic downcast of both arguments to `Comparable<Object?>`,
|
|
// then invoking its `compareTo` with the latter.
|
|
// Since `IncomparableKey` can't be downcast to `Comparable`, it should throw.
|
|
var set = SplayTreeSet<Object?>();
|
|
Expect.throws(() => set.add(IncomparableKey(0)));
|
|
Expect.throws(() => set.lookup(IncomparableKey(0)));
|
|
set.add(1);
|
|
if (checkedImplicitDowncasts) {
|
|
Expect.throws(() => set.add(IncomparableKey(0)));
|
|
Expect.throws(() => set.lookup(IncomparableKey(0)));
|
|
}
|
|
|
|
var map = SplayTreeMap();
|
|
Expect.throws(() => map[IncomparableKey(0)] = 0);
|
|
Expect.throws(() => map.putIfAbsent(IncomparableKey(0), () => 0));
|
|
map[1] = 1;
|
|
if (checkedImplicitDowncasts) {
|
|
Expect.throws(() => map[IncomparableKey(0)] = 0);
|
|
Expect.throws(() => map.putIfAbsent(IncomparableKey(0), () => 0));
|
|
}
|
|
|
|
// But not if the compare function allows them.
|
|
// This now includes `null`.
|
|
int compare(Object? o1, Object? o2) {
|
|
if (o1 == null) return o2 == null ? 0 : -1;
|
|
if (o2 == null) return 1;
|
|
if (o1 is IncomparableKey && o2 is IncomparableKey) {
|
|
return o1.id - o2.id;
|
|
}
|
|
throw UnsupportedError("Nope");
|
|
}
|
|
|
|
for (var key in [null, IncomparableKey(0)]) {
|
|
set = SplayTreeSet<Object?>(compare);
|
|
set.add(key);
|
|
Expect.equals(1, set.length);
|
|
set.clear();
|
|
Expect.isNull(set.lookup(key));
|
|
set.clear();
|
|
set.add(IncomparableKey(1));
|
|
set.add(key);
|
|
Expect.identical(key, set.first);
|
|
Expect.identical(key, set.lookup(key));
|
|
|
|
map = SplayTreeMap<Object?, Object?>(compare);
|
|
map[key] = 0;
|
|
Expect.isTrue(map.containsKey(key));
|
|
map.clear();
|
|
map.putIfAbsent(key, () => 0);
|
|
Expect.isTrue(map.containsKey(key));
|
|
map.clear();
|
|
map[IncomparableKey(1)] = 0;
|
|
map[key] = 0;
|
|
Expect.isTrue(map.containsKey(key));
|
|
map.remove(key);
|
|
Expect.isFalse(map.containsKey(key));
|
|
map.putIfAbsent(key, () => 0);
|
|
Expect.isTrue(map.containsKey(key));
|
|
map.remove(key);
|
|
Expect.isFalse(map.containsKey(key));
|
|
}
|
|
}
|
|
|
|
class IncomparableKey {
|
|
final int id;
|
|
IncomparableKey(this.id);
|
|
}
|