OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 import 'dart:convert'; |
| 6 |
| 7 import 'package:expect/expect.dart'; |
| 8 |
| 9 // This test implements a new special interface that can be used to |
| 10 // send data more efficiently between two converters. |
| 11 |
| 12 class MyChunkedIntInterface extends ChunkedConversionInterface { |
| 13 const MyChunkedIntInterface(); |
| 14 |
| 15 MyChunkedIntSink adapt(ChunkedConversionSink sink) { |
| 16 if (sink.interface == MyChunkedIntSink.INTERFACE) return sink; |
| 17 return new IntAdapterSink(sink); |
| 18 } |
| 19 |
| 20 MyChunkedIntSink createSink(callback) { |
| 21 return adapt(ChunkedConversionSink.INTERFACE.createSink(callback)); |
| 22 } |
| 23 } |
| 24 |
| 25 abstract class MyChunkedIntSink extends ChunkedConversionSink<int> { |
| 26 static const INTERFACE = const MyChunkedIntInterface(); |
| 27 |
| 28 add(int i); |
| 29 close(); |
| 30 |
| 31 // The special method. |
| 32 specialI(i); |
| 33 |
| 34 get interface => INTERFACE; |
| 35 } |
| 36 |
| 37 class IntAdapterSink extends MyChunkedIntSink { |
| 38 final _sink; |
| 39 IntAdapterSink(this._sink); |
| 40 add(o) => _sink.add(o); |
| 41 close() => _sink.close(); |
| 42 specialI(o) => add(o); |
| 43 } |
| 44 |
| 45 class MyChunkedBoolInterface extends ChunkedConversionInterface { |
| 46 const MyChunkedBoolInterface(); |
| 47 |
| 48 MyChunkedBoolSink adapt(ChunkedConversionSink sink) { |
| 49 if (sink.interface == MyChunkedBoolSink.INTERFACE) return sink; |
| 50 return new BoolAdapterSink(sink); |
| 51 } |
| 52 |
| 53 MyChunkedBoolSink createSink(callback) { |
| 54 return adapt(ChunkedConversionSink.INTERFACE.createSink(callback)); |
| 55 } |
| 56 } |
| 57 |
| 58 class MyChunkedBoolSink extends ChunkedConversionSink<bool> { |
| 59 static const INTERFACE = const MyChunkedBoolInterface(); |
| 60 |
| 61 add(bool b); |
| 62 close(); |
| 63 |
| 64 specialB(bool b); |
| 65 |
| 66 get interface => INTERFACE; |
| 67 } |
| 68 |
| 69 class BoolAdapterSink extends MyChunkedBoolSink { |
| 70 final _sink; |
| 71 BoolAdapterSink(this._sink); |
| 72 add(o) => _sink.add(o); |
| 73 close() => _sink.close(); |
| 74 specialB(o) => add(o); |
| 75 } |
| 76 |
| 77 class IntBoolConverter1 extends Converter<List<int>, List<bool>> { |
| 78 List<bool> convert(List<int> input) => input.map((x) => x > 0).toList(); |
| 79 |
| 80 startChunkedConversion(sink) { |
| 81 return new IntBoolConverter1Sink(outputInterface.adapt(sink)); |
| 82 } |
| 83 |
| 84 get outputInterface => MyChunkedBoolSink.INTERFACE; |
| 85 get inputInterface => MyChunkedIntSink.INTERFACE; |
| 86 } |
| 87 |
| 88 class BoolIntConverter1 extends Converter<List<bool>, List<int>> { |
| 89 List<int> convert(List<bool> input) => input.map((x) => x ? 1 : 0).toList(); |
| 90 |
| 91 startChunkedConversion(sink) { |
| 92 return new BoolIntConverter1Sink(outputInterface.adapt(sink)); |
| 93 } |
| 94 |
| 95 get outputInterface => MyChunkedIntSink.INTERFACE; |
| 96 get inputInterface => MyChunkedBoolSink.INTERFACE; |
| 97 } |
| 98 |
| 99 int specialICounter = 0; |
| 100 int specialBCounter = 0; |
| 101 |
| 102 class IntBoolConverter1Sink extends MyChunkedIntSink { |
| 103 var outSink; |
| 104 IntBoolConverter1Sink(this.outSink); |
| 105 |
| 106 add(int i) { |
| 107 outSink.specialB(i > 0); |
| 108 } |
| 109 specialI(int i) { |
| 110 specialICounter++; |
| 111 add(i); |
| 112 } |
| 113 close() => outSink.close(); |
| 114 } |
| 115 |
| 116 class BoolIntConverter1Sink extends MyChunkedBoolSink { |
| 117 var outSink; |
| 118 BoolIntConverter1Sink(this.outSink); |
| 119 |
| 120 add(bool b) { |
| 121 outSink.specialI(b ? 1 : 0); |
| 122 } |
| 123 |
| 124 specialB(bool b) { |
| 125 specialBCounter++; |
| 126 add(b); |
| 127 } |
| 128 close() => outSink.close(); |
| 129 } |
| 130 |
| 131 class IdentityConverter extends Converter { |
| 132 convert(x) => x; |
| 133 |
| 134 startChunkedConversion(sink) { |
| 135 return new IdentitySink(sink); |
| 136 } |
| 137 |
| 138 get outputInterface => ChunkedConversionSink.INTERFACE; |
| 139 get inputInterface => ChunkedConversionSink.INTERFACE; |
| 140 } |
| 141 |
| 142 class IdentitySink extends ChunkedConversionSink { |
| 143 final _sink; |
| 144 IdentitySink(this._sink); |
| 145 add(o) => _sink.add(o); |
| 146 close() => _sink.close(); |
| 147 } |
| 148 |
| 149 main() { |
| 150 var converter1, converter2, intSink, intSink2, hasExecuted, boolSink, fused; |
| 151 var converter3, fused2, sink, sink2; |
| 152 |
| 153 // Test int->bool converter individually. |
| 154 converter1 = new IntBoolConverter1(); |
| 155 Expect.listEquals([true, false, true], converter1.convert([2, -2, 2])); |
| 156 hasExecuted = false; |
| 157 boolSink = MyChunkedBoolSink.INTERFACE.createSink((value) { |
| 158 hasExecuted = true; |
| 159 Expect.listEquals([true, false, true], value); |
| 160 }); |
| 161 intSink = converter1.startChunkedConversion(boolSink); |
| 162 intSink.add(3); |
| 163 intSink.specialI(-3); |
| 164 intSink.add(3); |
| 165 intSink.close(); |
| 166 Expect.isTrue(hasExecuted); |
| 167 Expect.equals(1, specialICounter); |
| 168 specialICounter = 0; |
| 169 hasExecuted = false; |
| 170 |
| 171 // Test bool->int converter individually. |
| 172 converter2 = new BoolIntConverter1(); |
| 173 Expect.listEquals([1, 0, 1], converter2.convert([true, false, true])); |
| 174 hasExecuted = false; |
| 175 intSink = MyChunkedIntSink.INTERFACE.createSink((value) { |
| 176 hasExecuted = true; |
| 177 Expect.listEquals([1, 0, 1], value); |
| 178 }); |
| 179 boolSink = converter2.startChunkedConversion(intSink); |
| 180 boolSink.specialB(true); |
| 181 boolSink.add(false); |
| 182 boolSink.add(true); |
| 183 boolSink.close(); |
| 184 Expect.isTrue(hasExecuted); |
| 185 Expect.equals(1, specialBCounter); |
| 186 specialBCounter = 0; |
| 187 hasExecuted = false; |
| 188 |
| 189 // Test identity converter indidivually. |
| 190 converter3 = new IdentityConverter(); |
| 191 hasExecuted = false; |
| 192 sink = ChunkedConversionSink.INTERFACE.createSink((value) { |
| 193 hasExecuted = true; |
| 194 Expect.listEquals([1, 2, 3], value); |
| 195 }); |
| 196 sink2 = converter3.startChunkedConversion(sink); |
| 197 [1, 2, 3].forEach(sink2.add); |
| 198 sink2.close(); |
| 199 Expect.isTrue(hasExecuted); |
| 200 hasExecuted = false; |
| 201 |
| 202 // Test fused converters. |
| 203 fused = converter1.fuse(converter2); |
| 204 Expect.listEquals([1, 0, 1], fused.convert([2, -2, 2])); |
| 205 hasExecuted = false; |
| 206 intSink2 = MyChunkedIntSink.INTERFACE.createSink((value) { |
| 207 hasExecuted = true; |
| 208 Expect.listEquals([1, 0, 1], value); |
| 209 }); |
| 210 intSink = fused.startChunkedConversion(intSink2); |
| 211 intSink.specialI(3); |
| 212 intSink.add(-3); |
| 213 intSink.add(3); |
| 214 intSink.close(); |
| 215 Expect.isTrue(hasExecuted); |
| 216 Expect.equals(3, specialBCounter); |
| 217 specialBCounter = 0; |
| 218 Expect.equals(1, specialICounter); |
| 219 specialICounter = 0; |
| 220 hasExecuted = false; |
| 221 |
| 222 // With identity in front. |
| 223 fused2 = converter3.fuse(fused); |
| 224 hasExecuted = false; |
| 225 intSink2 = MyChunkedIntSink.INTERFACE.createSink((value) { |
| 226 hasExecuted = true; |
| 227 Expect.listEquals([1, 0, 1], value); |
| 228 }); |
| 229 sink = fused2.startChunkedConversion(intSink2); |
| 230 Expect.isFalse(sink is MyChunkedIntSink); |
| 231 sink.add(3); |
| 232 sink.add(-3); |
| 233 sink.add(3); |
| 234 sink.close(); |
| 235 Expect.isTrue(hasExecuted); |
| 236 Expect.equals(3, specialBCounter); |
| 237 specialBCounter = 0; |
| 238 Expect.equals(0, specialICounter); |
| 239 specialICounter = 0; |
| 240 hasExecuted = false; |
| 241 |
| 242 // With identity at the end. |
| 243 fused2 = fused.fuse(converter3); |
| 244 hasExecuted = false; |
| 245 sink = ChunkedConversionSink.INTERFACE.createSink((value) { |
| 246 hasExecuted = true; |
| 247 Expect.listEquals([1, 0, 1], value); |
| 248 }); |
| 249 intSink = fused2.startChunkedConversion(sink); |
| 250 Expect.isTrue(intSink is MyChunkedIntSink); |
| 251 intSink.specialI(3); |
| 252 intSink.add(-3); |
| 253 intSink.specialI(3); |
| 254 intSink.close(); |
| 255 Expect.isTrue(hasExecuted); |
| 256 Expect.equals(3, specialBCounter); |
| 257 specialBCounter = 0; |
| 258 Expect.equals(2, specialICounter); |
| 259 specialICounter = 0; |
| 260 hasExecuted = false; |
| 261 |
| 262 // With identity between the two converters. |
| 263 fused = converter1.fuse(converter3).fuse(converter2); |
| 264 Expect.listEquals([1, 0, 1], fused.convert([2, -2, 2])); |
| 265 hasExecuted = false; |
| 266 intSink2 = MyChunkedIntSink.INTERFACE.createSink((value) { |
| 267 hasExecuted = true; |
| 268 Expect.listEquals([1, 0, 1], value); |
| 269 }); |
| 270 intSink = fused.startChunkedConversion(intSink2); |
| 271 intSink.specialI(3); |
| 272 intSink.add(-3); |
| 273 intSink.add(3); |
| 274 intSink.close(); |
| 275 Expect.isTrue(hasExecuted); |
| 276 Expect.equals(0, specialBCounter); |
| 277 specialBCounter = 0; |
| 278 Expect.equals(1, specialICounter); |
| 279 specialICounter = 0; |
| 280 hasExecuted = false; |
| 281 } |
OLD | NEW |