mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 09:43:08 +00:00
6f78471687
Changes signature of Iterable.singleWhere. Makes LinkedHashMap no longer be a HashMap. Change-Id: I7a12fea533d42b0fc8357086649df38ad01f3cdd Reviewed-on: https://dart-review.googlesource.com/39140 Commit-Queue: Leaf Petersen <leafp@google.com> Reviewed-by: William Hesse <whesse@google.com> Reviewed-by: Leaf Petersen <leafp@google.com> Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
343 lines
10 KiB
Dart
343 lines
10 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.
|
|
|
|
library json_map_test;
|
|
|
|
import "package:expect/expect.dart";
|
|
import 'dart:convert' show json;
|
|
import 'dart:collection' show LinkedHashMap, HashMap;
|
|
|
|
bool useReviver = false;
|
|
Map<String, dynamic> jsonify(Map map) {
|
|
String encoded = json.encode(map);
|
|
return useReviver
|
|
? json.decode(encoded, reviver: (key, value) => value)
|
|
: json.decode(encoded);
|
|
}
|
|
|
|
List listEach(Map map) {
|
|
var result = [];
|
|
map.forEach((key, value) {
|
|
result.add(key);
|
|
result.add(value);
|
|
});
|
|
return result;
|
|
}
|
|
|
|
void main() {
|
|
test(false);
|
|
test(true);
|
|
}
|
|
|
|
void test(bool revive) {
|
|
useReviver = revive;
|
|
testEmpty(jsonify({}));
|
|
testAtoB(jsonify({'a': 'b'}));
|
|
|
|
// You can write 'Map<String, dynamic>' here (or 'var' which infers the
|
|
// same), but if you write just 'Map' as the type, then the type of the
|
|
// constant argument in the addAll below is not inferred correctly.
|
|
var map = jsonify({});
|
|
map['a'] = 'b';
|
|
testAtoB(map);
|
|
|
|
map = jsonify({});
|
|
Expect.equals('b', map.putIfAbsent('a', () => 'b'));
|
|
testAtoB(map);
|
|
|
|
map = jsonify({});
|
|
map.addAll({'a': 'b'});
|
|
testAtoB(map);
|
|
|
|
testOrder(['a', 'b', 'c', 'd', 'e', 'f']);
|
|
|
|
testProto();
|
|
testToString();
|
|
testConcurrentModifications();
|
|
testType();
|
|
testClear();
|
|
|
|
testListEntry();
|
|
testMutation();
|
|
}
|
|
|
|
void testEmpty(Map map) {
|
|
for (int i = 0; i < 2; i++) {
|
|
Expect.equals(0, map.length);
|
|
Expect.isTrue(map.isEmpty);
|
|
Expect.isFalse(map.isNotEmpty);
|
|
Expect.listEquals([], map.keys.toList());
|
|
Expect.listEquals([], map.values.toList());
|
|
Expect.isNull(map['a']);
|
|
Expect.listEquals([], listEach(map));
|
|
Expect.isFalse(map.containsKey('a'));
|
|
Expect.isFalse(map.containsValue('a'));
|
|
Expect.isNull(map.remove('a'));
|
|
testLookupNonExistingKeys(map);
|
|
testLookupNonExistingValues(map);
|
|
map.clear();
|
|
}
|
|
}
|
|
|
|
void testAtoB(Map map) {
|
|
Expect.equals(1, map.length);
|
|
Expect.isFalse(map.isEmpty);
|
|
Expect.isTrue(map.isNotEmpty);
|
|
Expect.listEquals(['a'], map.keys.toList());
|
|
Expect.listEquals(['b'], map.values.toList());
|
|
Expect.equals('b', map['a']);
|
|
Expect.listEquals(['a', 'b'], listEach(map));
|
|
Expect.isTrue(map.containsKey('a'));
|
|
Expect.isFalse(map.containsKey('b'));
|
|
Expect.isTrue(map.containsValue('b'));
|
|
Expect.isFalse(map.containsValue('a'));
|
|
|
|
testLookupNonExistingKeys(map);
|
|
testLookupNonExistingValues(map);
|
|
Expect.equals('b', map.remove('a'));
|
|
Expect.isNull(map.remove('b'));
|
|
testLookupNonExistingKeys(map);
|
|
testLookupNonExistingValues(map);
|
|
|
|
map.clear();
|
|
testEmpty(map);
|
|
}
|
|
|
|
void testLookupNonExistingKeys(Map map) {
|
|
for (String key in ['__proto__', 'null', null]) {
|
|
Expect.isNull(map[key]);
|
|
Expect.isFalse(map.containsKey(key));
|
|
}
|
|
}
|
|
|
|
void testLookupNonExistingValues(Map map) {
|
|
for (var value in ['__proto__', 'null', null]) {
|
|
Expect.isFalse(map.containsValue(value));
|
|
}
|
|
}
|
|
|
|
void testOrder(List list) {
|
|
if (list.isEmpty)
|
|
return;
|
|
else
|
|
testOrder(list.skip(1).toList());
|
|
|
|
Map original = {};
|
|
for (int i = 0; i < list.length; i++) {
|
|
original[list[i]] = i;
|
|
}
|
|
|
|
Map map = jsonify(original);
|
|
Expect.equals(list.length, map.length);
|
|
Expect.listEquals(list, map.keys.toList());
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
map["$i"] = i;
|
|
Expect.equals(list.length + i + 1, map.length);
|
|
Expect.listEquals(list, map.keys.take(list.length).toList());
|
|
}
|
|
}
|
|
|
|
void testProto() {
|
|
Map map = jsonify({'__proto__': 0});
|
|
Expect.equals(1, map.length);
|
|
Expect.isTrue(map.containsKey('__proto__'));
|
|
Expect.listEquals(['__proto__'], map.keys.toList());
|
|
Expect.equals(0, map['__proto__']);
|
|
Expect.equals(0, map.remove('__proto__'));
|
|
testEmpty(map);
|
|
|
|
map = jsonify({'__proto__': null});
|
|
Expect.equals(1, map.length);
|
|
Expect.isTrue(map.containsKey('__proto__'));
|
|
Expect.listEquals(['__proto__'], map.keys.toList());
|
|
Expect.isNull(map['__proto__']);
|
|
Expect.isNull(map.remove('__proto__'));
|
|
testEmpty(map);
|
|
}
|
|
|
|
void testToString() {
|
|
Expect.equals("{}", jsonify({}).toString());
|
|
Expect.equals("{a: 0}", jsonify({'a': 0}).toString());
|
|
}
|
|
|
|
void testConcurrentModifications() {
|
|
void testIterate(Map map, Iterable iterable, Function f) {
|
|
Iterator iterator = iterable.iterator;
|
|
f(map);
|
|
iterator.moveNext();
|
|
}
|
|
|
|
void testKeys(Map map, Function f) => testIterate(map, map.keys, f);
|
|
void testValues(Map map, Function f) => testIterate(map, map.values, f);
|
|
|
|
void testForEach(Map map, Function f) {
|
|
map.forEach((key, value) {
|
|
f(map);
|
|
});
|
|
}
|
|
|
|
bool throwsCME(Function f) {
|
|
try {
|
|
f();
|
|
} on ConcurrentModificationError catch (e) {
|
|
return true;
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Map map = {};
|
|
Expect.isTrue(throwsCME(() => testKeys(jsonify(map), (map) => map['a'] = 0)));
|
|
Expect
|
|
.isTrue(throwsCME(() => testValues(jsonify(map), (map) => map['a'] = 0)));
|
|
Expect.isFalse(
|
|
throwsCME(() => testForEach(jsonify(map), (map) => map['a'] = 0)));
|
|
|
|
Expect.isFalse(throwsCME(() => testKeys(jsonify(map), (map) => map.clear())));
|
|
Expect
|
|
.isFalse(throwsCME(() => testValues(jsonify(map), (map) => map.clear())));
|
|
Expect.isFalse(
|
|
throwsCME(() => testForEach(jsonify(map), (map) => map.clear())));
|
|
|
|
Expect.isFalse(
|
|
throwsCME(() => testKeys(jsonify(map), (map) => map.remove('a'))));
|
|
Expect.isFalse(
|
|
throwsCME(() => testValues(jsonify(map), (map) => map.remove('a'))));
|
|
Expect.isFalse(
|
|
throwsCME(() => testForEach(jsonify(map), (map) => map.remove('a'))));
|
|
|
|
Expect.isTrue(throwsCME(
|
|
() => testKeys(jsonify(map), (map) => map.putIfAbsent('a', () => 0))));
|
|
Expect.isTrue(throwsCME(
|
|
() => testValues(jsonify(map), (map) => map.putIfAbsent('a', () => 0))));
|
|
Expect.isFalse(throwsCME(
|
|
() => testForEach(jsonify(map), (map) => map.putIfAbsent('a', () => 0))));
|
|
|
|
Expect.isFalse(
|
|
throwsCME(() => testKeys(jsonify(map), (map) => map.addAll({}))));
|
|
Expect.isFalse(
|
|
throwsCME(() => testValues(jsonify(map), (map) => map.addAll({}))));
|
|
Expect.isFalse(
|
|
throwsCME(() => testForEach(jsonify(map), (map) => map.addAll({}))));
|
|
|
|
Expect.isTrue(
|
|
throwsCME(() => testKeys(jsonify(map), (map) => map.addAll({'a': 0}))));
|
|
Expect.isTrue(
|
|
throwsCME(() => testValues(jsonify(map), (map) => map.addAll({'a': 0}))));
|
|
Expect.isFalse(throwsCME(
|
|
() => testForEach(jsonify(map), (map) => map.addAll({'a': 0}))));
|
|
|
|
map = {'a': 1};
|
|
Expect
|
|
.isFalse(throwsCME(() => testKeys(jsonify(map), (map) => map['a'] = 0)));
|
|
Expect.isFalse(
|
|
throwsCME(() => testValues(jsonify(map), (map) => map['a'] = 0)));
|
|
Expect.isFalse(
|
|
throwsCME(() => testForEach(jsonify(map), (map) => map['a'] = 0)));
|
|
|
|
Expect.isTrue(throwsCME(() => testKeys(jsonify(map), (map) => map['b'] = 0)));
|
|
Expect
|
|
.isTrue(throwsCME(() => testValues(jsonify(map), (map) => map['b'] = 0)));
|
|
Expect.isTrue(
|
|
throwsCME(() => testForEach(jsonify(map), (map) => map['b'] = 0)));
|
|
|
|
Expect.isTrue(throwsCME(() => testKeys(jsonify(map), (map) => map.clear())));
|
|
Expect
|
|
.isTrue(throwsCME(() => testValues(jsonify(map), (map) => map.clear())));
|
|
Expect
|
|
.isTrue(throwsCME(() => testForEach(jsonify(map), (map) => map.clear())));
|
|
|
|
Expect.isTrue(
|
|
throwsCME(() => testKeys(jsonify(map), (map) => map.remove('a'))));
|
|
Expect.isTrue(
|
|
throwsCME(() => testValues(jsonify(map), (map) => map.remove('a'))));
|
|
Expect.isTrue(
|
|
throwsCME(() => testForEach(jsonify(map), (map) => map.remove('a'))));
|
|
|
|
Expect.isFalse(
|
|
throwsCME(() => testKeys(jsonify(map), (map) => map.remove('b'))));
|
|
Expect.isFalse(
|
|
throwsCME(() => testValues(jsonify(map), (map) => map.remove('b'))));
|
|
Expect.isFalse(
|
|
throwsCME(() => testForEach(jsonify(map), (map) => map.remove('b'))));
|
|
|
|
Expect.isFalse(throwsCME(
|
|
() => testKeys(jsonify(map), (map) => map.putIfAbsent('a', () => 0))));
|
|
Expect.isFalse(throwsCME(
|
|
() => testValues(jsonify(map), (map) => map.putIfAbsent('a', () => 0))));
|
|
Expect.isFalse(throwsCME(
|
|
() => testForEach(jsonify(map), (map) => map.putIfAbsent('a', () => 0))));
|
|
|
|
Expect.isTrue(throwsCME(
|
|
() => testKeys(jsonify(map), (map) => map.putIfAbsent('b', () => 0))));
|
|
Expect.isTrue(throwsCME(
|
|
() => testValues(jsonify(map), (map) => map.putIfAbsent('b', () => 0))));
|
|
Expect.isTrue(throwsCME(
|
|
() => testForEach(jsonify(map), (map) => map.putIfAbsent('b', () => 0))));
|
|
|
|
Expect.isFalse(
|
|
throwsCME(() => testKeys(jsonify(map), (map) => map.addAll({}))));
|
|
Expect.isFalse(
|
|
throwsCME(() => testValues(jsonify(map), (map) => map.addAll({}))));
|
|
Expect.isFalse(
|
|
throwsCME(() => testForEach(jsonify(map), (map) => map.addAll({}))));
|
|
|
|
Expect.isFalse(
|
|
throwsCME(() => testKeys(jsonify(map), (map) => map.addAll({'a': 0}))));
|
|
Expect.isFalse(
|
|
throwsCME(() => testValues(jsonify(map), (map) => map.addAll({'a': 0}))));
|
|
Expect.isFalse(throwsCME(
|
|
() => testForEach(jsonify(map), (map) => map.addAll({'a': 0}))));
|
|
|
|
Expect.isTrue(
|
|
throwsCME(() => testKeys(jsonify(map), (map) => map.addAll({'b': 0}))));
|
|
Expect.isTrue(
|
|
throwsCME(() => testValues(jsonify(map), (map) => map.addAll({'b': 0}))));
|
|
Expect.isTrue(throwsCME(
|
|
() => testForEach(jsonify(map), (map) => map.addAll({'b': 0}))));
|
|
}
|
|
|
|
void testType() {
|
|
var map = jsonify({});
|
|
var type = "${map.runtimeType}";
|
|
|
|
// The documentation of json.decode doesn't actually specify that it returns
|
|
// a map (it's marked dynamic), but it's a reasonable expectation if you
|
|
// don't provide a reviver function.
|
|
Expect.isTrue(map is Map, type);
|
|
Expect.isTrue(map is Map<String, dynamic>, type);
|
|
Expect.isFalse(map is Map<int, dynamic>, type);
|
|
}
|
|
|
|
void testClear() {
|
|
Map map = jsonify({'a': 0});
|
|
map.clear();
|
|
Expect.equals(0, map.length);
|
|
}
|
|
|
|
void testListEntry() {
|
|
Map map = jsonify({
|
|
'a': [
|
|
7,
|
|
8,
|
|
{'b': 9}
|
|
]
|
|
});
|
|
List list = map['a'];
|
|
Expect.equals(3, list.length);
|
|
Expect.equals(7, list[0]);
|
|
Expect.equals(8, list[1]);
|
|
Expect.equals(9, list[2]['b']);
|
|
}
|
|
|
|
void testMutation() {
|
|
Map map = jsonify({'a': 0});
|
|
Expect.listEquals(['a', 0], listEach(map));
|
|
map['a'] = 1;
|
|
Expect.listEquals(['a', 1], listEach(map));
|
|
map['a']++;
|
|
Expect.listEquals(['a', 2], listEach(map));
|
|
}
|