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.
114 lines
3.6 KiB
114 lines
3.6 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, in
|
|
// formats_vectors_test.dart. Here 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']}',
|
|
);
|
|
}
|
|
});
|
|
});
|
|
}
|