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.
138 lines
4.4 KiB
138 lines
4.4 KiB
|
2 days ago
|
// The head of format 3 against Go: test/vectors/open_heads.json, which
|
||
|
|
// tool/open_go_vectors.go writes with capsule.DecodeHead and EncodeHead of
|
||
|
|
// the reference; testdata/vectors/head_schema.json, with the detail of each
|
||
|
|
// ERR_HEAD_INVALID; and the trees of testdata/vectors/paths.json, each a
|
||
|
|
// head of files of 0 bytes, through the decoder of the head, from layer 3
|
||
|
|
// to layer 4.
|
||
|
|
@TestOn('vm')
|
||
|
|
library;
|
||
|
|
|
||
|
|
import 'dart:convert';
|
||
|
|
import 'dart:io';
|
||
|
|
import 'dart:typed_data';
|
||
|
|
|
||
|
|
import 'package:datekeys/datekeys.dart';
|
||
|
|
import 'package:datekeys/src/sha256.dart' show sha256;
|
||
|
|
import 'package:test/test.dart';
|
||
|
|
|
||
|
|
import 'open_vectors_support.dart';
|
||
|
|
|
||
|
|
Json readJson(String path) => jsonDecode(File(path).readAsStringSync()) as Json;
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
final heads = readJson('test/vectors/open_heads.json');
|
||
|
|
|
||
|
|
test('open_heads.json: every head decodes as in Go', () {
|
||
|
|
expect(heads['spec'], specVersion);
|
||
|
|
final cases = (heads['decode']! as List).cast<Json>();
|
||
|
|
expect(cases, hasLength(greaterThan(300)));
|
||
|
|
checkDecodeCases(cases);
|
||
|
|
// Every kind of result, and both orders of U+FF5E and U+1F600.
|
||
|
|
expect(
|
||
|
|
{for (final c in cases) c['result']},
|
||
|
|
{
|
||
|
|
'ok',
|
||
|
|
'ERR_NON_CANONICAL_CBOR',
|
||
|
|
'ERR_UNSUPPORTED_VERSION',
|
||
|
|
'ERR_HEAD_INVALID',
|
||
|
|
'ERR_EXTENSION_CRITICAL_UNKNOWN',
|
||
|
|
},
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('open_heads.json: every head encodes as in Go', () {
|
||
|
|
final cases = (heads['encode']! as List).cast<Json>();
|
||
|
|
expect(cases, hasLength(greaterThan(20)));
|
||
|
|
checkEncodeCases(cases);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('head_schema.json: the result and the detail of each head', () {
|
||
|
|
final f = readJson('testdata/vectors/head_schema.json');
|
||
|
|
expect(f['spec'], specVersion);
|
||
|
|
final cases = (f['heads']! as List).cast<Json>();
|
||
|
|
expect(cases, hasLength(63));
|
||
|
|
for (final c in cases) {
|
||
|
|
final b = fromHex(c['hex']! as String);
|
||
|
|
var result = 'ok';
|
||
|
|
var detail = '';
|
||
|
|
try {
|
||
|
|
decodeHead(b);
|
||
|
|
} on DateKeysException catch (e) {
|
||
|
|
result = e.code.code;
|
||
|
|
if (e.code == ErrorCode.headInvalid) {
|
||
|
|
detail = headDetail(e);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
expect(result, c['result'], reason: c['name'] as String?);
|
||
|
|
expect(detail, c['detail'] ?? '', reason: c['name'] as String?);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('paths.json: the trees, as heads of files of 0 bytes', () {
|
||
|
|
final f = readJson('testdata/vectors/paths.json');
|
||
|
|
final trees = (f['trees']! as List).cast<Json>();
|
||
|
|
expect(trees, hasLength(greaterThan(10)));
|
||
|
|
final empty = sha256(Uint8List(0));
|
||
|
|
for (final c in trees) {
|
||
|
|
// TreeHead of the reference: a zero salt and a file of 0 bytes for
|
||
|
|
// each path, in the order given.
|
||
|
|
final b = encodeHead(
|
||
|
|
Head(
|
||
|
|
salt: Uint8List(saltSize),
|
||
|
|
files: [
|
||
|
|
for (final p in (c['paths']! as List).cast<String>())
|
||
|
|
HeadFile(path: p, size: 0, start: 0, end: 0, sha256: empty),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
);
|
||
|
|
var result = 'ok';
|
||
|
|
var detail = '';
|
||
|
|
try {
|
||
|
|
decodeHead(b);
|
||
|
|
} on DateKeysException catch (e) {
|
||
|
|
result = e.code.code;
|
||
|
|
if (e.code == ErrorCode.headInvalid) detail = headDetail(e);
|
||
|
|
}
|
||
|
|
expect(result, c['result'], reason: c['name'] as String?);
|
||
|
|
expect(detail, c['detail'] ?? '', reason: c['name'] as String?);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
test('the files of every format 3 fixture, from its record', () {
|
||
|
|
final names = Directory('testdata/fixtures')
|
||
|
|
.listSync()
|
||
|
|
.map((f) => f.uri.pathSegments.last)
|
||
|
|
.where((n) => n.startsWith('format3_') && n.endsWith('.json'))
|
||
|
|
.where((n) => !n.endsWith('.inspect.json') && !n.contains('.dkk'))
|
||
|
|
.toList();
|
||
|
|
expect(names, hasLength(12));
|
||
|
|
for (final n in names) {
|
||
|
|
final r = readJson('testdata/fixtures/$n');
|
||
|
|
final hb = fromHex(r['head_cbor']! as String);
|
||
|
|
final h = decodeHead(hb);
|
||
|
|
expect(toHex(h.salt), r['salt'], reason: n);
|
||
|
|
expect(
|
||
|
|
[h.comment, h.author],
|
||
|
|
[r['comment'] ?? '', r['declared_author'] ?? ''],
|
||
|
|
reason: n,
|
||
|
|
);
|
||
|
|
expect(
|
||
|
|
[
|
||
|
|
for (final f in h.files)
|
||
|
|
{
|
||
|
|
'path': f.path,
|
||
|
|
'size': f.size,
|
||
|
|
'start': f.start,
|
||
|
|
'end': f.end,
|
||
|
|
'sha256': toHex(f.sha256),
|
||
|
|
if (f.mtime != null) 'mtime': f.mtime,
|
||
|
|
},
|
||
|
|
],
|
||
|
|
r['files'] ?? <Object?>[],
|
||
|
|
reason: n,
|
||
|
|
);
|
||
|
|
expect(encodeHead(h), hb, reason: n);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|