diff --git a/veilid-flutter/lib/veilid_encoding.dart b/veilid-flutter/lib/veilid_encoding.dart index be0d6247..7962dbc5 100644 --- a/veilid-flutter/lib/veilid_encoding.dart +++ b/veilid-flutter/lib/veilid_encoding.dart @@ -13,17 +13,12 @@ String base64UrlNoPadEncode(List bytes) { } Uint8List base64UrlNoPadDecode(String source) { - if(source.length % 4 != 0) { - source = base64.normalize(source); - } - return base64.decode(source); + source = base64Url.normalize(source); + return base64Url.decode(source); } -Uint8List base64UrlNoPadDecodeDynamic(dynamic source) { - source = source as String; - source = base64.normalize(source); - return base64.decode(source); -} +Uint8List base64UrlNoPadDecodeDynamic(dynamic source) => + base64UrlNoPadDecode(source as String); class Uint8ListJsonConverter implements JsonConverter { const Uint8ListJsonConverter(); @@ -36,7 +31,6 @@ class Uint8ListJsonConverter implements JsonConverter { @immutable abstract class EncodedString extends Equatable { - const EncodedString(String s) : contents = s; final String contents; @override @@ -76,7 +70,6 @@ abstract class EncodedString extends Equatable { @immutable class FixedEncodedString32 extends EncodedString { - factory FixedEncodedString32.fromBytes(Uint8List bytes) { if (bytes.length != decodedLength()) { throw Exception('length ${bytes.length} should be ${decodedLength()}'); @@ -103,7 +96,6 @@ class FixedEncodedString32 extends EncodedString { @immutable class FixedEncodedString43 extends EncodedString { - factory FixedEncodedString43.fromBytes(Uint8List bytes) { if (bytes.length != decodedLength()) { throw Exception('length ${bytes.length} should be ${decodedLength()}'); @@ -130,7 +122,6 @@ class FixedEncodedString43 extends EncodedString { @immutable class FixedEncodedString86 extends EncodedString { - factory FixedEncodedString86.fromBytes(Uint8List bytes) { if (bytes.length != decodedLength()) { throw Exception('length ${bytes.length} should be ${decodedLength()}'); diff --git a/veilid-flutter/test/test_encoding.dart b/veilid-flutter/test/test_encoding.dart new file mode 100644 index 00000000..bef8c57e --- /dev/null +++ b/veilid-flutter/test/test_encoding.dart @@ -0,0 +1,70 @@ +import 'dart:convert'; +import 'dart:math'; +import 'dart:typed_data'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:veilid/veilid_encoding.dart'; + +const knownVectors = [ + ['', ''], + ['f', 'Zg'], + ['fo', 'Zm8'], + ['foo', 'Zm9v'], + ['foob', 'Zm9vYg'], + ['fooba', 'Zm9vYmE'], + ['foobar', 'Zm9vYmFy'] +]; + +Future _testEncodingKnownVector(Uint8List k, String v) async { + final e = base64UrlNoPadEncode(k); + expect(e, v, reason: 'encode mismatch'); + + final d = base64UrlNoPadDecode(v); + expect(d, k, reason: 'decode mismatch'); + + final r = base64UrlNoPadDecode(e); + expect(r, k, reason: 'round trip mismatch'); +} + +Future testEncodingKnownVectors() async { + for (final kv in knownVectors) { + final k = Uint8List.fromList(kv[0].codeUnits); + final v = kv[1]; + + await _testEncodingKnownVector(k, v); + } +} + +Future testEncodeDecodeGarbage() async { + final random = Random(0); + for (var n = 0; n < 8192; n++) { + final kl = List.empty(growable: true); + for (var p = 0; p < n; p++) { + final v = random.nextInt(256); + kl.add(v); + } + final k = Uint8List.fromList(kl); + + final e = base64UrlNoPadEncode(k); + final r = base64UrlNoPadDecode(e); + + expect(r, k, reason: 'garbage round trip mismatch'); + } +} + +Future testEncodeDecodeGarbagePad() async { + final random = Random(0); + for (var n = 0; n < 8192; n++) { + final kl = List.empty(growable: true); + for (var p = 0; p < n; p++) { + final v = random.nextInt(256); + kl.add(v); + } + final k = Uint8List.fromList(kl); + + final e = base64Url.encode(k); + final r = base64UrlNoPadDecode(e); + + expect(r, k, reason: 'garbage w/pad round trip mismatch'); + } +} diff --git a/veilid-flutter/test/veilid_test.dart b/veilid-flutter/test/veilid_test.dart index 8e419017..b0100283 100644 --- a/veilid-flutter/test/veilid_test.dart +++ b/veilid-flutter/test/veilid_test.dart @@ -1,16 +1,14 @@ import 'package:flutter_test/flutter_test.dart'; -import 'package:veilid/veilid.dart'; +import 'test_encoding.dart'; void main() { - final api = Veilid.instance; - TestWidgetsFlutterBinding.ensureInitialized(); setUp(() {}); tearDown(() {}); - test('veilidVersionString', () async { - expect(api.veilidVersionString(), '0.1.0'); - }); + test('testEncodingKnownVectors', testEncodingKnownVectors); + test('testEncodeDecodeGarbage', testEncodeDecodeGarbage); + test('testEncodeDecodeGarbagePad', testEncodeDecodeGarbagePad); }