OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 // Library tag to allow the test to run on Dartium. | 5 import 'dart:async'; |
6 library base64_test; | 6 import 'dart:convert'; |
7 | |
8 import 'dart:math'; | 7 import 'dart:math'; |
9 import 'dart:async'; | 8 |
10 | 9 import "package:charcode/ascii.dart"; |
11 import "package:crypto/crypto.dart"; | 10 import "package:crypto/crypto.dart"; |
12 import "package:test/test.dart"; | 11 import "package:test/test.dart"; |
13 | 12 |
14 void main() { | 13 void main() { |
15 test('encoder', _testEncoder); | 14 group("encoder", () { |
16 test('decoder', _testDecoder); | 15 test("for simple inputs", () { |
17 test('decoder for malformed input', _testDecoderForMalformedInput); | 16 expect(BASE64.encode([]), equals('')); |
18 test('encode decode lists', _testEncodeDecodeLists); | 17 expect(BASE64.encode([$f]), equals('Zg==')); |
19 test('url safe encode-decode', _testUrlSafeEncodeDecode); | 18 expect(BASE64.encode([$f, $o]), equals('Zm8=')); |
20 test( | 19 expect(BASE64.encode([$f, $o, $o]), equals('Zm9v')); |
21 'percent-encoded padding character encode-decode', _testPaddingCharacter); | 20 expect(BASE64.encode([$f, $o, $o, $b]), equals('Zm9vYg==')); |
22 test('streaming encoder', _testStreamingEncoder); | 21 expect(BASE64.encode([$f, $o, $o, $b, $a]), equals('Zm9vYmE=')); |
23 test('streaming decoder', _testStreamingDecoder); | 22 expect(BASE64.encode([$f, $o, $o, $b, $a, $r]), equals('Zm9vYmFy')); |
24 test('streaming decoder for malformed input', | 23 }); |
25 _testStreamingDecoderForMalformedInput); | 24 |
26 test('streaming encoder for different decompositions of a list of bytes', | 25 test("for inputs with zeroes", () { |
27 _testStreamingEncoderForDecompositions); | 26 expect(BASE64.encode([0]), equals('AA==')); |
28 test('streaming decoder for different decompositions of a string', | 27 expect(BASE64.encode([0, 0]), equals('AAA=')); |
29 _testStreamingDecoderForDecompositions); | 28 expect(BASE64.encode([0, 0, 0]), equals('AAAA')); |
30 test('streaming for encoded padding character', | 29 expect(BASE64.encode([0, 0, 0, 0]), equals('AAAAAA==')); |
31 _testStreamingForEncodedPadding); | 30 }); |
32 test('old api', _testOldApi); | 31 |
33 test('url safe streaming encoder/decoder', _testUrlSafeStreaming); | 32 test("for a large input with line separators", () { |
34 test('performance', _testPerformance); | 33 expect( |
| 34 BASE64.encode( |
| 35 UTF8.encode( |
| 36 "Man is distinguished, not only by his reason, but by this " |
| 37 "singular passion from other animals, which is a lust of the " |
| 38 "mind, that by a perseverance of delight in the continued " |
| 39 "and indefatigable generation of knowledge, exceeds the " |
| 40 "short vehemence of any carnal pleasure."), |
| 41 addLineSeparator: true), |
| 42 equals( |
| 43 "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1" |
| 44 "dCBieSB0aGlz\r\n" |
| 45 "IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBh" |
| 46 "IGx1c3Qgb2Yg\r\n" |
| 47 "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0" |
| 48 "aGUgY29udGlu\r\n" |
| 49 "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBl" |
| 50 "eGNlZWRzIHRo\r\n" |
| 51 "ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=")); |
| 52 }); |
| 53 |
| 54 test("for a large input without line separators", () { |
| 55 expect( |
| 56 BASE64.encode( |
| 57 UTF8.encode( |
| 58 "Man is distinguished, not only by his reason, but by this " |
| 59 "singular passion from other animals, which is a lust of the " |
| 60 "mind, that by a perseverance of delight in the continued " |
| 61 "and indefatigable generation of knowledge, exceeds the " |
| 62 "short vehemence of any carnal pleasure.")), |
| 63 equals( |
| 64 "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1" |
| 65 "dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3" |
| 66 "aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFu" |
| 67 "Y2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxl" |
| 68 "IGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhl" |
| 69 "bWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=")); |
| 70 }); |
| 71 |
| 72 test("for chunked input", () { |
| 73 expect(_encodeChunked([ |
| 74 [102, 102], |
| 75 [111, 102], |
| 76 [ |
| 77 111, 111, 102, 111, 111, 98, 102, 111, 111, 98, 97, 102, 111, 111, |
| 78 98, 97, 114 |
| 79 ] |
| 80 ]), equals("ZmZvZm9vZm9vYmZvb2JhZm9vYmFy")); |
| 81 |
| 82 expect(_encodeChunked([[196, 16], [], [158], [196]]), equals("xBCexA==")); |
| 83 expect(_encodeChunked([[196, 16], [158, 196], [], []]), |
| 84 equals("xBCexA==")); |
| 85 expect(_encodeChunked([[196], [], [16], [], [], [158], [], [196]]), |
| 86 equals("xBCexA==")); |
| 87 expect(_encodeChunked([[196], [], [16], [158, 196], [], []]), |
| 88 equals("xBCexA==")); |
| 89 expect(_encodeChunked([[], [196], [], [], [16, 158], [], [196]]), |
| 90 equals("xBCexA==")); |
| 91 expect(_encodeChunked([[], [196], [16, 158, 196], []]), |
| 92 equals("xBCexA==")); |
| 93 expect(_encodeChunked([[196, 16, 158], [], [], [196]]), |
| 94 equals("xBCexA==")); |
| 95 expect(_encodeChunked([[196, 16, 158], [], [196], []]), |
| 96 equals("xBCexA==")); |
| 97 expect(_encodeChunked([[196, 16, 158, 196], [], [], []]), |
| 98 equals("xBCexA==")); |
| 99 }); |
| 100 |
| 101 test('with a URL-safe alphabet', () { |
| 102 expect(BASE64.encode(BASE64.decode('+/A='), urlSafe: true), |
| 103 equals('-_A=')); |
| 104 }); |
| 105 |
| 106 test('with a percent-encoded padding character', () { |
| 107 expect(BASE64.encode([2, 8], encodePaddingCharacter: true), |
| 108 equals('Agg%3D')); |
| 109 }); |
| 110 |
| 111 test('with the old API', () { |
| 112 expect(CryptoUtils.bytesToBase64([]), equals('')); |
| 113 expect(CryptoUtils.bytesToBase64([$f]), equals('Zg==')); |
| 114 expect(CryptoUtils.bytesToBase64([$f, $o]), equals('Zm8=')); |
| 115 expect(CryptoUtils.bytesToBase64([$f, $o, $o]), equals('Zm9v')); |
| 116 expect(CryptoUtils.bytesToBase64([$f, $o, $o, $b]), equals('Zm9vYg==')); |
| 117 expect(CryptoUtils.bytesToBase64([$f, $o, $o, $b, $a]), |
| 118 equals('Zm9vYmE=')); |
| 119 expect(CryptoUtils.bytesToBase64([$f, $o, $o, $b, $a, $r]), |
| 120 equals('Zm9vYmFy')); |
| 121 }); |
| 122 }); |
| 123 |
| 124 group("decoder", () { |
| 125 test("for simple inputs", () { |
| 126 expect(BASE64.decode(''), equals([])); |
| 127 expect(BASE64.decode('Zg=='), equals([$f])); |
| 128 expect(BASE64.decode('Zm8='), equals([$f, $o])); |
| 129 expect(BASE64.decode('Zm9v'), equals([$f, $o, $o])); |
| 130 expect(BASE64.decode('Zm9vYg=='), equals([$f, $o, $o, $b])); |
| 131 expect(BASE64.decode('Zm9vYmE='), equals([$f, $o, $o, $b, $a])); |
| 132 expect(BASE64.decode('Zm9vYmFy'), equals([$f, $o, $o, $b, $a, $r])); |
| 133 }); |
| 134 |
| 135 test("for inputs with zeroes", () { |
| 136 expect(BASE64.decode('AA=='), equals([0])); |
| 137 expect(BASE64.decode('AAA='), equals([0, 0])); |
| 138 expect(BASE64.decode('AAAA'), equals([0, 0, 0])); |
| 139 expect(BASE64.decode('AAAAAA=='), equals([0, 0, 0, 0])); |
| 140 }); |
| 141 |
| 142 test("for a large input with line separators", () { |
| 143 expect( |
| 144 BASE64.decode( |
| 145 "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1" |
| 146 "dCBieSB0aGlz\r\n" |
| 147 "IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBh" |
| 148 "IGx1c3Qgb2Yg\r\n" |
| 149 "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0" |
| 150 "aGUgY29udGlu\r\n" |
| 151 "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBl" |
| 152 "eGNlZWRzIHRo\r\n" |
| 153 "ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="), |
| 154 equals(UTF8.encode( |
| 155 "Man is distinguished, not only by his reason, but by this " |
| 156 "singular passion from other animals, which is a lust of the " |
| 157 "mind, that by a perseverance of delight in the continued and " |
| 158 "indefatigable generation of knowledge, exceeds the short " |
| 159 "vehemence of any carnal pleasure."))); |
| 160 }); |
| 161 |
| 162 test("for a large input without line separators", () { |
| 163 expect( |
| 164 BASE64.decode( |
| 165 "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1" |
| 166 "dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3" |
| 167 "aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFu" |
| 168 "Y2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxl" |
| 169 "IGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhl" |
| 170 "bWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="), |
| 171 equals(UTF8.encode( |
| 172 "Man is distinguished, not only by his reason, but by this " |
| 173 "singular passion from other animals, which is a lust of the " |
| 174 "mind, that by a perseverance of delight in the continued and " |
| 175 "indefatigable generation of knowledge, exceeds the short " |
| 176 "vehemence of any carnal pleasure."))); |
| 177 }); |
| 178 |
| 179 test("for chunked input", () { |
| 180 expect(_decodeChunked(['YmFz', 'ZTY', '0I', 'GRlY29kZXI=']), equals([ |
| 181 98, 97, 115, 101, 54, 52, 32, 100, 101, 99, 111, 100, 101, 114 |
| 182 ])); |
| 183 }); |
| 184 |
| 185 test("for chunked input containing zeroes", () { |
| 186 expect(_decodeChunked(['AAAA', 'AAA=', 'AA==', '']), |
| 187 equals([0, 0, 0, 0, 0, 0])); |
| 188 |
| 189 expect(_decodeChunked(["A", "", "BCD"]), equals([0, 16, 131])); |
| 190 expect(_decodeChunked(["A", "BCD", "", ""]), equals([0, 16, 131])); |
| 191 expect(_decodeChunked(["A", "B", "", "", "CD", ""]), |
| 192 equals([0, 16, 131])); |
| 193 expect(_decodeChunked(["", "A", "BC", "", "D"]), equals([0, 16, 131])); |
| 194 expect(_decodeChunked(["", "AB", "C", "", "", "D"]), |
| 195 equals([0, 16, 131])); |
| 196 expect(_decodeChunked(["AB", "CD", ""]), equals([0, 16, 131])); |
| 197 expect(_decodeChunked(["", "ABC", "", "D"]), equals([0, 16, 131])); |
| 198 expect(_decodeChunked(["", "ABC", "D", ""]), equals([0, 16, 131])); |
| 199 expect(_decodeChunked(["", "", "ABCD", ""]), equals([0, 16, 131])); |
| 200 expect(_decodeChunked(["A", "B", "C", "D"]), equals([0, 16, 131])); |
| 201 expect(_decodeChunked(["", "A", "B", "C", "D", ""]), |
| 202 equals([0, 16, 131])); |
| 203 expect(_decodeChunked(["", "A", "B", "", "", "C", "", "D", ""]), |
| 204 equals([0, 16, 131])); |
| 205 }); |
| 206 |
| 207 test("for chunked input with encoded padding", () { |
| 208 expect(_decodeChunked(['AA%', '3D', '%', '3', 'DEFGZ']), |
| 209 equals(BASE64.decode('AA==EFGZ'))); |
| 210 }); |
| 211 |
| 212 test('with a URL-safe alphabet', () { |
| 213 expect(BASE64.decode('-_A='), equals(BASE64.decode('+/A='))); |
| 214 }); |
| 215 |
| 216 test('with a percent-encoded padding character', () { |
| 217 expect(BASE64.decode('Agg%3D'), equals([2, 8])); |
| 218 }); |
| 219 |
| 220 test("with the old API", () { |
| 221 expect(CryptoUtils.base64StringToBytes(''), equals([])); |
| 222 expect(CryptoUtils.base64StringToBytes('Zg=='), equals([$f])); |
| 223 expect(CryptoUtils.base64StringToBytes('Zm8='), equals([$f, $o])); |
| 224 expect(CryptoUtils.base64StringToBytes('Zm9v'), equals([$f, $o, $o])); |
| 225 expect(CryptoUtils.base64StringToBytes('Zm9vYg=='), |
| 226 equals([$f, $o, $o, $b])); |
| 227 expect(CryptoUtils.base64StringToBytes('Zm9vYmE='), |
| 228 equals([$f, $o, $o, $b, $a])); |
| 229 expect(CryptoUtils.base64StringToBytes('Zm9vYmFy'), |
| 230 equals([$f, $o, $o, $b, $a, $r])); |
| 231 }); |
| 232 |
| 233 group("rejects", () { |
| 234 test("input of the wrong length", () { |
| 235 expect(() => BASE64.decode('A'), throwsFormatException); |
| 236 expect(() => BASE64.decode('AB'), throwsFormatException); |
| 237 expect(() => BASE64.decode('ABz'), throwsFormatException); |
| 238 expect(() => BASE64.decode('ABzdE'), throwsFormatException); |
| 239 expect(() => BASE64.decode('ABzdEf'), throwsFormatException); |
| 240 expect(() => BASE64.decode('ABzdEfg'), throwsFormatException); |
| 241 }); |
| 242 |
| 243 test("input with invalid characters", () { |
| 244 expect(() => BASE64.decode('AB~'), throwsFormatException); |
| 245 }); |
| 246 |
| 247 test("chunked input of the wrong length", () { |
| 248 expect(() => _decodeChunked(['ABz']), throwsFormatException); |
| 249 expect(() => _decodeChunked(['AB', 'Lx', 'z', 'xx']), |
| 250 throwsFormatException); |
| 251 }); |
| 252 |
| 253 test("input with the wrong padding", () { |
| 254 expect(() => BASE64.decode('A=='), throwsFormatException); |
| 255 expect(() => BASE64.decode('AB='), throwsFormatException); |
| 256 expect(() => BASE64.decode('ABz=='), throwsFormatException); |
| 257 expect(() => BASE64.decode('ABzdE='), throwsFormatException); |
| 258 }); |
| 259 |
| 260 test("input with the wrong encoded padding", () { |
| 261 expect(() => BASE64.decode('A%3D%3D'), throwsFormatException); |
| 262 expect(() => BASE64.decode('AB%3D'), throwsFormatException); |
| 263 expect(() => BASE64.decode('ABz%3D%3D'), throwsFormatException); |
| 264 expect(() => BASE64.decode('ABzdE%3D'), throwsFormatException); |
| 265 }); |
| 266 }); |
| 267 }); |
| 268 |
| 269 test('successfully round-trips data', () { |
| 270 for (var i = 0; i < 10; i++) { |
| 271 for (var j = 0; j < 256 - i; j++) { |
| 272 var data = new List.filled(i, j); |
| 273 expect(BASE64.decode(BASE64.encode(data)), equals(data)); |
| 274 } |
| 275 } |
| 276 }); |
35 } | 277 } |
36 | 278 |
37 // Data from http://tools.ietf.org/html/rfc4648. | 279 /// Performs chunked Base64 decoding of [chunks] and returns the result as a |
38 const _INPUTS = const ['', 'f', 'fo', 'foo', 'foob', 'fooba', 'foobar']; | 280 /// byte array. |
39 const _RESULTS = const [ | 281 List<int> _decodeChunked(Iterable<String> chunks) { |
40 '', | 282 var bytes; |
41 'Zg==', | 283 var innerSink = new ByteConversionSink.withCallback( |
42 'Zm8=', | 284 (result) => bytes = result); |
43 'Zm9v', | 285 var sink = BASE64.decoder.startChunkedConversion(innerSink); |
44 'Zm9vYg==', | 286 |
45 'Zm9vYmE=', | 287 for (var chunk in chunks) { |
46 'Zm9vYmFy' | 288 sink.add(chunk); |
47 ]; | |
48 | |
49 const _PADDING_INPUT = const [2, 8]; | |
50 | |
51 var _STREAMING_ENCODER_INPUT = [ | |
52 [102, 102], | |
53 [111, 102], | |
54 [ | |
55 111, 111, 102, 111, 111, 98, 102, 111, 111, 98, 97, 102, 111, 111, 98, 97, | |
56 114 | |
57 ] | |
58 ]; | |
59 | |
60 const _STREAMING_ENCODED = 'ZmZvZm9vZm9vYmZvb2JhZm9vYmFy'; | |
61 const _STREAMING_DECODER_INPUT = const ['YmFz', 'ZTY', '0I', 'GRlY29kZXI=']; | |
62 const _STREAMING_DECODED = const [ | |
63 98, 97, 115, 101, 54, 52, 32, 100, 101, 99, 111, 100, 101, 114 | |
64 ]; | |
65 const _STREAMING_DECODER_INPUT_FOR_ZEROES = const ['AAAA', 'AAA=', 'AA==', '']; | |
66 var _STREAMING_DECODED_ZEROES = [0, 0, 0, 0, 0, 0]; | |
67 | |
68 var _DECOMPOSITIONS_FOR_DECODING = [ | |
69 ["A", "", "BCD"], | |
70 ["A", "BCD", "", ""], | |
71 ["A", "B", "", "", "CD", ""], | |
72 ["", "A", "BC", "", "D"], | |
73 ["", "AB", "C", "", "", "D"], | |
74 ["AB", "CD", ""], | |
75 ["", "ABC", "", "D"], | |
76 ["", "ABC", "D", ""], | |
77 ["", "", "ABCD", ""], | |
78 ["A", "B", "C", "D"], | |
79 ["", "A", "B", "C", "D", ""], | |
80 ["", "A", "B", "", "", "C", "", "D", ""] | |
81 ]; | |
82 | |
83 const _DECOMPOSITION_DECODED = const [0, 16, 131]; | |
84 | |
85 var _DECOMPOSITIONS_FOR_ENCODING = [ | |
86 [[196, 16], [], [158], [196]], | |
87 [[196, 16], [158, 196], [], []], | |
88 [[196], [], [16], [], [], [158], [], [196]], | |
89 [[196], [], [16], [158, 196], [], []], | |
90 [[], [196], [], [], [16, 158], [], [196]], | |
91 [[], [196], [16, 158, 196], []], | |
92 [[196, 16, 158], [], [], [196]], | |
93 [[196, 16, 158], [], [196], []], | |
94 [[196, 16, 158, 196], [], [], []] | |
95 ]; | |
96 | |
97 const _DECOMPOSITION_ENCODED = 'xBCexA=='; | |
98 | |
99 // Test data with only zeroes. | |
100 var inputsWithZeroes = [[0, 0, 0], [0, 0], [0], []]; | |
101 const _RESULTS_WITH_ZEROS = const ['AAAA', 'AAA=', 'AA==', '']; | |
102 | |
103 const _LONG_LINE = | |
104 "Man is distinguished, not only by his reason, but by this singular " | |
105 "passion from other animals, which is a lust of the mind, that by a " | |
106 "perseverance of delight in the continued and indefatigable generation " | |
107 "of knowledge, exceeds the short vehemence of any carnal pleasure."; | |
108 | |
109 const _LONG_LINE_RESULT = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbm" | |
110 "x5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz\r\n" | |
111 "IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlci" | |
112 "BhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg\r\n" | |
113 "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcm" | |
114 "FuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu\r\n" | |
115 "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYX" | |
116 "Rpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo\r\n" | |
117 "ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm" | |
118 "5hbCBwbGVhc3VyZS4="; | |
119 | |
120 const _LONG_LINE_RESULT_NO_BREAK = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbm" | |
121 "x5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz" | |
122 "IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlci" | |
123 "BhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg" | |
124 "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcm" | |
125 "FuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu" | |
126 "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYX" | |
127 "Rpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo" | |
128 "ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm" | |
129 "5hbCBwbGVhc3VyZS4="; | |
130 | |
131 void _testEncoder() { | |
132 for (var i = 0; i < _INPUTS.length; i++) { | |
133 expect(BASE64.encode(_INPUTS[i].codeUnits), _RESULTS[i]); | |
134 } | 289 } |
135 for (var i = 0; i < inputsWithZeroes.length; i++) { | 290 sink.close(); |
136 expect(BASE64.encode(inputsWithZeroes[i]), _RESULTS_WITH_ZEROS[i]); | 291 |
| 292 return bytes; |
| 293 } |
| 294 |
| 295 /// Performs chunked Base64 encoding of [chunks] and returns the result. |
| 296 String _encodeChunked(Iterable<List<int>> chunks) { |
| 297 var string; |
| 298 var innerSink = new StringConversionSink.withCallback( |
| 299 (result) => string = result); |
| 300 var sink = BASE64.encoder.startChunkedConversion(innerSink); |
| 301 |
| 302 for (var chunk in chunks) { |
| 303 sink.add(chunk); |
137 } | 304 } |
138 expect(BASE64.encode(_LONG_LINE.codeUnits, addLineSeparator: true), | 305 sink.close(); |
139 _LONG_LINE_RESULT); | 306 |
140 expect(BASE64.encode(_LONG_LINE.codeUnits), _LONG_LINE_RESULT_NO_BREAK); | 307 return string; |
141 } | 308 } |
142 | |
143 void _testDecoder() { | |
144 for (var i = 0; i < _RESULTS.length; i++) { | |
145 expect(new String.fromCharCodes(BASE64.decode(_RESULTS[i])), _INPUTS[i]); | |
146 } | |
147 | |
148 for (var i = 0; i < _RESULTS_WITH_ZEROS.length; i++) { | |
149 expect(BASE64.decode(_RESULTS_WITH_ZEROS[i]), inputsWithZeroes[i]); | |
150 } | |
151 | |
152 var longLineDecoded = BASE64.decode(_LONG_LINE_RESULT); | |
153 expect(new String.fromCharCodes(longLineDecoded), _LONG_LINE); | |
154 | |
155 var longLineResultNoBreak = BASE64.decode(_LONG_LINE_RESULT); | |
156 expect(new String.fromCharCodes(longLineResultNoBreak), _LONG_LINE); | |
157 } | |
158 | |
159 void _testPaddingCharacter() { | |
160 var encoded = BASE64.encode(_PADDING_INPUT, encodePaddingCharacter: true); | |
161 expect(encoded, 'Agg%3D'); | |
162 expect(BASE64.decode(encoded), _PADDING_INPUT); | |
163 } | |
164 | |
165 Future _testStreamingEncoder() async { | |
166 expect( | |
167 await new Stream.fromIterable(_STREAMING_ENCODER_INPUT) | |
168 .transform(BASE64.encoder) | |
169 .join(), | |
170 _STREAMING_ENCODED); | |
171 } | |
172 | |
173 Future _testStreamingDecoder() async { | |
174 expect( | |
175 await new Stream.fromIterable(_STREAMING_DECODER_INPUT) | |
176 .transform(BASE64.decoder) | |
177 .expand((l) => l) | |
178 .toList(), | |
179 _STREAMING_DECODED); | |
180 | |
181 expect( | |
182 await new Stream.fromIterable(_STREAMING_DECODER_INPUT_FOR_ZEROES) | |
183 .transform(BASE64.decoder) | |
184 .expand((l) => l) | |
185 .toList(), | |
186 _STREAMING_DECODED_ZEROES); | |
187 } | |
188 | |
189 Future _testStreamingDecoderForMalformedInput() async { | |
190 expect(new Stream.fromIterable(['ABz']).transform(BASE64.decoder).toList(), | |
191 throwsFormatException); | |
192 | |
193 expect( | |
194 new Stream.fromIterable(['AB', 'Lx', 'z', 'xx']) | |
195 .transform(BASE64.decoder) | |
196 .toList(), | |
197 throwsFormatException); | |
198 } | |
199 | |
200 Future _testStreamingEncoderForDecompositions() async { | |
201 for (var decomposition in _DECOMPOSITIONS_FOR_ENCODING) { | |
202 expect( | |
203 await new Stream.fromIterable(decomposition) | |
204 .transform(BASE64.encoder) | |
205 .join(), | |
206 _DECOMPOSITION_ENCODED); | |
207 } | |
208 } | |
209 | |
210 Future _testStreamingDecoderForDecompositions() async { | |
211 for (var decomposition in _DECOMPOSITIONS_FOR_DECODING) { | |
212 expect( | |
213 await new Stream.fromIterable(decomposition) | |
214 .transform(BASE64.decoder) | |
215 .expand((x) => x) | |
216 .toList(), | |
217 _DECOMPOSITION_DECODED); | |
218 } | |
219 } | |
220 | |
221 void _testDecoderForMalformedInput() { | |
222 expect(() { | |
223 BASE64.decode('AB~'); | |
224 }, throwsFormatException); | |
225 | |
226 expect(() { | |
227 BASE64.decode('A'); | |
228 }, throwsFormatException); | |
229 } | |
230 | |
231 Future _testUrlSafeStreaming() async { | |
232 String encUrlSafe = '-_A='; | |
233 List<List<int>> dec = [BASE64.decode('+/A=')]; | |
234 var streamedResult = await new Stream.fromIterable(dec) | |
235 .transform(new Base64Encoder(urlSafe: true)) | |
236 .join(); | |
237 | |
238 expect(streamedResult, encUrlSafe); | |
239 } | |
240 | |
241 Future _testStreamingForEncodedPadding() async { | |
242 List<String> withEncodedPadding = ['AA%', '3D', '%', '3', 'DEFGZ']; | |
243 List<int> decoded = BASE64.decode('AA==EFGZ'); | |
244 var streamedResult = await new Stream.fromIterable(withEncodedPadding) | |
245 .transform(BASE64.decoder) | |
246 .expand((x) => x) | |
247 .toList(); | |
248 | |
249 expect(streamedResult, decoded); | |
250 } | |
251 | |
252 void _testUrlSafeEncodeDecode() { | |
253 List<int> decUrlSafe = BASE64.decode('-_A='); | |
254 List<int> dec = BASE64.decode('+/A='); | |
255 expect(decUrlSafe, orderedEquals(dec)); | |
256 expect(BASE64.encode(dec, urlSafe: true), '-_A='); | |
257 expect(BASE64.encode(dec), '+/A='); | |
258 } | |
259 | |
260 void _testEncodeDecodeLists() { | |
261 for (int i = 0; i < 10; i++) { | |
262 for (int j = 0; j < 256 - i; j++) { | |
263 List<int> x = new List<int>(i); | |
264 for (int k = 0; k < i; k++) { | |
265 x[k] = j; | |
266 } | |
267 var enc = BASE64.encode(x); | |
268 var dec = BASE64.decode(enc); | |
269 expect(dec, orderedEquals(x)); | |
270 } | |
271 } | |
272 } | |
273 | |
274 void _fillRandom(List<int> l) { | |
275 var random = new Random(0xBABE); | |
276 for (int j = 0; j < l.length; j++) { | |
277 l[j] = random.nextInt(255); | |
278 } | |
279 } | |
280 | |
281 void _testOldApi() { | |
282 for (int i = 0; i < _INPUTS.length; i++) { | |
283 expect(CryptoUtils.bytesToBase64(_INPUTS[i].codeUnits), _RESULTS[i]); | |
284 expect(CryptoUtils.base64StringToBytes(_RESULTS[i]), _INPUTS[i].codeUnits); | |
285 } | |
286 } | |
287 | |
288 void _testPerformance() { | |
289 var l = new List<int>(1024); | |
290 var iters = 5000; | |
291 _fillRandom(l); | |
292 String enc; | |
293 var w = new Stopwatch()..start(); | |
294 for (int i = 0; i < iters; ++i) { | |
295 enc = BASE64.encode(l); | |
296 } | |
297 int ms = w.elapsedMilliseconds; | |
298 int perSec = (iters * l.length) * 1000 ~/ ms; | |
299 // print("Encode 1024 bytes for $iters times: $ms msec. $perSec b/s"); | |
300 w..reset(); | |
301 for (int i = 0; i < iters; ++i) { | |
302 BASE64.decode(enc); | |
303 } | |
304 ms = w.elapsedMilliseconds; | |
305 perSec = (iters * l.length) * 1000 ~/ ms; | |
306 // ('''Decode into ${l.length} bytes for $iters | |
307 // times: $ms msec. $perSec b/s'''); | |
308 } | |
OLD | NEW |