| 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 | 
|---|