mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 15:01:29 +00:00
b101a7d002
Change-Id: Ib33169c3e0ffc870915c189404074a1dea472546 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196548 Reviewed-by: Bob Nystrom <rnystrom@google.com> Commit-Queue: Leaf Petersen <leafp@google.com>
262 lines
7 KiB
Dart
262 lines
7 KiB
Dart
// 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.
|
|
|
|
// @dart = 2.9
|
|
|
|
import 'dart:convert';
|
|
|
|
import 'package:expect/expect.dart';
|
|
|
|
// This test implements a new special interface that can be used to
|
|
// send data more efficiently between two converters.
|
|
|
|
abstract class MyChunkedIntSink extends ChunkedConversionSink<int> {
|
|
MyChunkedIntSink();
|
|
factory MyChunkedIntSink.from(sink) = IntAdapterSink;
|
|
factory MyChunkedIntSink.withCallback(callback) {
|
|
var sink = new ChunkedConversionSink.withCallback(callback);
|
|
return new MyChunkedIntSink.from(sink);
|
|
}
|
|
|
|
add(int i);
|
|
close();
|
|
|
|
// The special method.
|
|
void specialI(int i);
|
|
}
|
|
|
|
class IntAdapterSink extends MyChunkedIntSink {
|
|
final _sink;
|
|
IntAdapterSink(this._sink);
|
|
add(o) => _sink.add(o);
|
|
close() => _sink.close();
|
|
void specialI(int o) => add(o);
|
|
}
|
|
|
|
abstract class MyChunkedBoolSink extends ChunkedConversionSink<bool> {
|
|
MyChunkedBoolSink();
|
|
factory MyChunkedBoolSink.from(sink) = BoolAdapterSink;
|
|
factory MyChunkedBoolSink.withCallback(callback) {
|
|
var sink = new ChunkedConversionSink.withCallback(callback);
|
|
return new MyChunkedBoolSink.from(sink);
|
|
}
|
|
|
|
add(bool b);
|
|
close();
|
|
|
|
specialB(bool b);
|
|
}
|
|
|
|
class BoolAdapterSink extends MyChunkedBoolSink {
|
|
final _sink;
|
|
BoolAdapterSink(this._sink);
|
|
add(o) => _sink.add(o);
|
|
close() => _sink.close();
|
|
specialB(o) => add(o);
|
|
}
|
|
|
|
class IntBoolConverter1 extends Converter<int, bool> {
|
|
bool convert(int input) => input > 0;
|
|
|
|
startChunkedConversion(sink) {
|
|
if (sink is! MyChunkedBoolSink) sink = new MyChunkedBoolSink.from(sink);
|
|
return new IntBoolConverter1Sink(sink);
|
|
}
|
|
}
|
|
|
|
class BoolIntConverter1 extends Converter<bool, int> {
|
|
int convert(bool input) => input ? 1 : 0;
|
|
|
|
startChunkedConversion(sink) {
|
|
if (sink is! MyChunkedIntSink) sink = new MyChunkedIntSink.from(sink);
|
|
return new BoolIntConverter1Sink(sink);
|
|
}
|
|
}
|
|
|
|
int specialICounter = 0;
|
|
int specialBCounter = 0;
|
|
|
|
class IntBoolConverter1Sink extends MyChunkedIntSink {
|
|
var outSink;
|
|
IntBoolConverter1Sink(this.outSink);
|
|
|
|
add(int i) {
|
|
outSink.specialB(i > 0);
|
|
}
|
|
|
|
void specialI(int i) {
|
|
specialICounter++;
|
|
add(i);
|
|
}
|
|
|
|
close() => outSink.close();
|
|
}
|
|
|
|
class BoolIntConverter1Sink extends MyChunkedBoolSink {
|
|
var outSink;
|
|
BoolIntConverter1Sink(this.outSink);
|
|
|
|
add(bool b) {
|
|
outSink.specialI(b ? 1 : 0);
|
|
}
|
|
|
|
specialB(bool b) {
|
|
specialBCounter++;
|
|
add(b);
|
|
}
|
|
|
|
close() => outSink.close();
|
|
}
|
|
|
|
class IdentityConverter<T> extends Converter<T, T> {
|
|
T convert(T x) => x;
|
|
|
|
startChunkedConversion(sink) {
|
|
return new IdentitySink<T>(sink);
|
|
}
|
|
}
|
|
|
|
class IdentitySink<T> extends ChunkedConversionSink<T> {
|
|
final _sink;
|
|
IdentitySink(this._sink);
|
|
void add(T o) => _sink.add(o);
|
|
close() => _sink.close();
|
|
}
|
|
|
|
main() {
|
|
var intSink, boolSink, sink, sink2;
|
|
|
|
// Test int->bool converter individually.
|
|
Converter<int, bool> int2boolConverter = new IntBoolConverter1();
|
|
Expect.listEquals(
|
|
[true, false, true], [2, -2, 2].map(int2boolConverter.convert).toList());
|
|
var hasExecuted = false;
|
|
boolSink = new MyChunkedBoolSink.withCallback((value) {
|
|
hasExecuted = true;
|
|
Expect.listEquals([true, false, true], value);
|
|
});
|
|
intSink = int2boolConverter.startChunkedConversion(boolSink);
|
|
intSink.add(3);
|
|
intSink.specialI(-3);
|
|
intSink.add(3);
|
|
intSink.close();
|
|
Expect.isTrue(hasExecuted);
|
|
Expect.equals(1, specialICounter);
|
|
specialICounter = 0;
|
|
hasExecuted = false;
|
|
|
|
// Test bool->int converter individually.
|
|
Converter<bool, int> bool2intConverter = new BoolIntConverter1();
|
|
Expect.listEquals(
|
|
[1, 0, 1], [true, false, true].map(bool2intConverter.convert).toList());
|
|
hasExecuted = false;
|
|
intSink = new MyChunkedIntSink.withCallback((value) {
|
|
hasExecuted = true;
|
|
Expect.listEquals([1, 0, 1], value);
|
|
});
|
|
boolSink = bool2intConverter.startChunkedConversion(intSink);
|
|
boolSink.specialB(true);
|
|
boolSink.add(false);
|
|
boolSink.add(true);
|
|
boolSink.close();
|
|
Expect.isTrue(hasExecuted);
|
|
Expect.equals(1, specialBCounter);
|
|
specialBCounter = 0;
|
|
hasExecuted = false;
|
|
|
|
// Test identity converter individually.
|
|
var identityConverter = new IdentityConverter();
|
|
hasExecuted = false;
|
|
sink = new ChunkedConversionSink.withCallback((value) {
|
|
hasExecuted = true;
|
|
Expect.listEquals([1, 2, 3], value);
|
|
});
|
|
sink2 = identityConverter.startChunkedConversion(sink);
|
|
[1, 2, 3].forEach(sink2.add);
|
|
sink2.close();
|
|
Expect.isTrue(hasExecuted);
|
|
hasExecuted = false;
|
|
|
|
// Test fused converters.
|
|
Converter<int, int> fused = int2boolConverter.fuse(bool2intConverter);
|
|
Expect.listEquals([1, 0, 1], [2, -2, 2].map(fused.convert).toList());
|
|
hasExecuted = false;
|
|
Sink<int> intSink2 = new MyChunkedIntSink.withCallback((value) {
|
|
hasExecuted = true;
|
|
Expect.listEquals([1, 0, 1], value);
|
|
});
|
|
intSink = fused.startChunkedConversion(intSink2);
|
|
intSink.specialI(3);
|
|
intSink.add(-3);
|
|
intSink.add(3);
|
|
intSink.close();
|
|
Expect.isTrue(hasExecuted);
|
|
Expect.equals(3, specialBCounter);
|
|
specialBCounter = 0;
|
|
Expect.equals(1, specialICounter);
|
|
specialICounter = 0;
|
|
hasExecuted = false;
|
|
|
|
// With identity in front.
|
|
Converter<int, int> fused2 = new IdentityConverter<int>().fuse(fused);
|
|
hasExecuted = false;
|
|
intSink2 = new MyChunkedIntSink.withCallback((value) {
|
|
hasExecuted = true;
|
|
Expect.listEquals([1, 0, 1], value);
|
|
});
|
|
sink = fused2.startChunkedConversion(intSink2);
|
|
Expect.isFalse(sink is MyChunkedIntSink);
|
|
sink.add(3);
|
|
sink.add(-3);
|
|
sink.add(3);
|
|
sink.close();
|
|
Expect.isTrue(hasExecuted);
|
|
Expect.equals(3, specialBCounter);
|
|
specialBCounter = 0;
|
|
Expect.equals(0, specialICounter);
|
|
specialICounter = 0;
|
|
hasExecuted = false;
|
|
|
|
// With identity at the end.
|
|
fused2 = fused.fuse(new IdentityConverter());
|
|
hasExecuted = false;
|
|
sink = new ChunkedConversionSink<int>.withCallback((value) {
|
|
hasExecuted = true;
|
|
Expect.listEquals([1, 0, 1], value);
|
|
});
|
|
intSink = fused2.startChunkedConversion(sink);
|
|
Expect.isTrue(intSink is MyChunkedIntSink);
|
|
intSink.specialI(3);
|
|
intSink.add(-3);
|
|
intSink.specialI(3);
|
|
intSink.close();
|
|
Expect.isTrue(hasExecuted);
|
|
Expect.equals(3, specialBCounter);
|
|
specialBCounter = 0;
|
|
Expect.equals(2, specialICounter);
|
|
specialICounter = 0;
|
|
hasExecuted = false;
|
|
|
|
// With identity between the two converters.
|
|
fused =
|
|
int2boolConverter.fuse(new IdentityConverter()).fuse(bool2intConverter);
|
|
Expect.listEquals([1, 0, 1], [2, -2, 2].map(fused.convert).toList());
|
|
hasExecuted = false;
|
|
intSink2 = new MyChunkedIntSink.withCallback((value) {
|
|
hasExecuted = true;
|
|
Expect.listEquals([1, 0, 1], value);
|
|
});
|
|
intSink = fused.startChunkedConversion(intSink2);
|
|
intSink.specialI(3);
|
|
intSink.add(-3);
|
|
intSink.add(3);
|
|
intSink.close();
|
|
Expect.isTrue(hasExecuted);
|
|
Expect.equals(0, specialBCounter);
|
|
specialBCounter = 0;
|
|
Expect.equals(1, specialICounter);
|
|
specialICounter = 0;
|
|
hasExecuted = false;
|
|
}
|