You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dateKeys-dart/test/cbor_vectors_test.dart

121 lines
3.8 KiB

// The shared vectors of the CBOR profile of spec §58,
// testdata/vectors/cbor.json, as vectors_test.go of package codec of
// datekeys-go: walkCbor accepts exactly the accept list, with the value
// recorded for unsigned integers, and rejects the reject list with the
// recorded code.
@TestOn('vm')
library;
import 'dart:convert';
import 'dart:io';
import 'package:datekeys/datekeys.dart';
import 'package:test/test.dart';
void main() {
final file = jsonDecode(
File('testdata/vectors/cbor.json').readAsStringSync(),
) as Map<String, Object?>;
final walk = file['walk']! as Map<String, Object?>;
final maxDepth = walk['max_depth']! as int;
final maxLen = walk['max_len']! as int;
List<Map<String, Object?>> list(String key) =>
(file[key]! as List).cast<Map<String, Object?>>();
final accept = list('accept');
final reject = list('reject');
final schemas = list('schemas');
test('the vector file is complete', () {
expect(file['spec'], specVersion);
expect(accept, isNotEmpty);
expect(reject, isNotEmpty);
expect(maxDepth, isPositive);
expect(maxLen, isPositive);
});
group('accept', () {
for (final v in accept) {
test(v['name'], () {
final input = fromHex(v['hex']! as String);
walkCbor(input, maxDepth, maxLen);
// An unsigned integer records its value: a JSON number up to 2^53-1
// and a decimal string above, so that no reader loses precision.
final isUint = input.isNotEmpty && input[0] >> 5 == 0;
expect(v.containsKey('value'), isUint);
if (!isUint) return;
final n = CborDecoder(input).uint64();
if (n > BigInt.from(maxSafeUint)) {
expect(v['value'], '$n');
} else {
expect(v['value'], n.toInt());
}
});
}
});
group('reject', () {
for (final v in reject) {
test(v['name'], () {
final input = fromHex(v['hex']! as String);
var code = '';
try {
walkCbor(input, maxDepth, maxLen);
} on DateKeysException catch (e) {
code = e.code.code;
}
expect(code, v['error']);
});
}
});
// The schemas block is decoded with the decoder of each schema: Provider
// Profile, PUBLIC_HEADER, CONTROL_CBOR and the body of a .dkk, which arrive
// with stage 4 of docs/PLAN_dart.md. Until then the block is only read: its
// shape is checked, and the objects it holds as valid are items of the
// profile whose type tag peekSchema reads.
group('schemas', () {
const typeTags = {
'provider_profile': 'datekeys-provider-profile',
'public_header': 'datekeycap',
'control_cbor': 'datekeys-control',
'dkk_body': 'datekeys-access-key',
};
final codes = {for (final c in ErrorCode.values) c.code};
test('the block is well formed', () {
expect(schemas, isNotEmpty);
for (final v in schemas) {
expect(typeTags.keys, contains(v['schema']), reason: '${v['name']}');
expect(v['block'], isA<String>());
expect(v['name'], isA<String>());
expect(fromHex(v['hex']! as String), isNotEmpty);
expect(
v['result'] == 'ok' || codes.contains(v['result']),
isTrue,
reason: '${v['name']}: ${v['result']}',
);
}
});
test('the valid objects are items of the profile with their type tag', () {
final valid = schemas.where((v) => v['result'] == 'ok').toList();
expect(valid, isNotEmpty);
for (final v in valid) {
final input = fromHex(v['hex']! as String);
walkCbor(input, 16, input.length);
expect(
peekSchema(input).typeTag,
typeTags[v['schema']],
reason: '${v['name']}',
);
}
});
test(
'the vectors decode with the decoders of their schemas',
() {},
skip: 'the decoders of the schemas arrive with stage 4',
);
});
}

Powered by TurnKey Linux.