| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 import 'dart:async'; | |
| 6 import 'dart:convert'; | |
| 7 import 'dart:math'; | |
| 8 | |
| 9 import "package:charcode/ascii.dart"; | |
| 10 import "package:crypto/crypto.dart"; | |
| 11 import "package:test/test.dart"; | |
| 12 | |
| 13 void main() { | |
| 14 group("encoder", () { | |
| 15 test("for simple inputs", () { | |
| 16 expect(BASE64.encode([]), equals('')); | |
| 17 expect(BASE64.encode([$f]), equals('Zg==')); | |
| 18 expect(BASE64.encode([$f, $o]), equals('Zm8=')); | |
| 19 expect(BASE64.encode([$f, $o, $o]), equals('Zm9v')); | |
| 20 expect(BASE64.encode([$f, $o, $o, $b]), equals('Zm9vYg==')); | |
| 21 expect(BASE64.encode([$f, $o, $o, $b, $a]), equals('Zm9vYmE=')); | |
| 22 expect(BASE64.encode([$f, $o, $o, $b, $a, $r]), equals('Zm9vYmFy')); | |
| 23 }); | |
| 24 | |
| 25 test("for inputs with zeroes", () { | |
| 26 expect(BASE64.encode([0]), equals('AA==')); | |
| 27 expect(BASE64.encode([0, 0]), equals('AAA=')); | |
| 28 expect(BASE64.encode([0, 0, 0]), equals('AAAA')); | |
| 29 expect(BASE64.encode([0, 0, 0, 0]), equals('AAAAAA==')); | |
| 30 }); | |
| 31 | |
| 32 test("for a large input with line separators", () { | |
| 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 }); | |
| 277 } | |
| 278 | |
| 279 /// Performs chunked Base64 decoding of [chunks] and returns the result as a | |
| 280 /// byte array. | |
| 281 List<int> _decodeChunked(Iterable<String> chunks) { | |
| 282 var bytes; | |
| 283 var innerSink = new ByteConversionSink.withCallback( | |
| 284 (result) => bytes = result); | |
| 285 var sink = BASE64.decoder.startChunkedConversion(innerSink); | |
| 286 | |
| 287 for (var chunk in chunks) { | |
| 288 sink.add(chunk); | |
| 289 } | |
| 290 sink.close(); | |
| 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); | |
| 304 } | |
| 305 sink.close(); | |
| 306 | |
| 307 return string; | |
| 308 } | |
| OLD | NEW |