blob: c8e5dc886493706d33e5532011b4be3af9da6738 [file] [log] [blame]
// Copyright (c) 2019, 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 'dart:collection';
import 'package:expect/expect.dart';
class CustomMap with MapMixin<int, String> {
Iterable<int> get keys => [];
String? operator [](Object? key) => "";
operator []=(int key, String value) {}
String remove(Object? key) => throw UnsupportedError("unsupported");
void clear() => throw UnsupportedError("unsupported");
}
class CustomSet extends SetBase<int> {
bool add(int value) => throw UnsupportedError("unsupported");
bool contains(Object? value) => throw UnsupportedError("unsupported");
Iterator<int> get iterator => <int>[].iterator;
int get length => 0;
int? lookup(Object? value) => throw UnsupportedError("unsupported");
bool remove(Object? value) => throw UnsupportedError("unsupported");
Set<int> toSet() => this;
}
class Equality {
final int id;
final String name;
const Equality(this.id, this.name);
int get hashCode => id;
bool operator ==(Object other) => other is Equality && id == other.id;
String toString() => "$id:$name";
}
T expectDynamic<T>(dynamic value) {
Expect.equals(dynamic, T);
return value;
}
T expectInt<T>(dynamic value) {
Expect.equals(int, T);
return value;
}
T expectString<T>(dynamic value) {
Expect.equals(String, T);
return value;
}
Iterable<T> expectIntIterable<T>(dynamic value) {
Expect.equals(int, T);
return value;
}
Set<T> expectIntSet<T>() {
Expect.equals(int, T);
return Set();
}
Stream<T> expectIntStream<T>(dynamic elements) {
Expect.equals(int, T);
return Stream<T>.fromIterable(elements);
}
Set<T> expectDynamicSet<T>() {
Expect.equals(dynamic, T);
return Set();
}
/// Hacky way of testing the inferred generic type arguments of [object].
///
/// [Expect.type()] only performs a subtype test, which means that it will
/// return `true` when asked if a `List<int>` is a `List<num>` or
/// `List<dynamic>`. For inference, we want to test the type more precisely.
///
/// There isn't a good way to do that in tests yet so, for now, we just see if
/// the runtime type contains the given type argument string.
// TODO(rnystrom): Do something less horribly brittle.
void _expectTypeArguments(String typeArguments, Object object) {
var typeName = object.runtimeType.toString();
// If an implementation prints dynamic instantiations like a raw type,
// handle that.
if (!typeName.contains("<") &&
(typeArguments == "dynamic" || typeArguments == "dynamic, dynamic")) {
return;
}
if (!typeName.contains("<$typeArguments>")) {
Expect.fail("Object should have had generic type '<$typeArguments>', "
"but was '$typeName'.");
}
}
void expectListOf<T>(Object object) {
Expect.type<List>(object);
_expectTypeArguments(T.toString(), object);
}
void expectSetOf<T>(Object object) {
Expect.type<Set>(object);
_expectTypeArguments(T.toString(), object);
}
void expectMapOf<K, V>(Object object) {
Expect.type<Map>(object);
_expectTypeArguments("$K, $V", object);
}