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/open_cases_test.dart

122 lines
4.7 KiB

// The opening against Go: every case of test/vectors/open_cases.json, which
// tool/open_go_vectors.go writes with capsule.Open of the reference, opened
// in memory and from a source read in pieces: the same result, text, checks
// with their details, release requests, state of the sink, content or files,
// and unusable extensions, and an output that is closed only when a capsule
// of format 1 or 2 opens and aborted after any failure (spec §56).
@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_support.dart';
Json readJson(String path) => jsonDecode(File(path).readAsStringSync()) as Json;
final _fixtures = <String, Uint8List>{};
Uint8List fixture(String file) => _fixtures.putIfAbsent(
file,
() => File('testdata/fixtures/$file').readAsBytesSync(),
);
void main() {
final vectors = readJson('test/vectors/open_cases.json');
final fixtures = (vectors['fixtures']! as List).cast<Json>();
final steps = (vectors['steps']! as List).cast<Json>();
test('open_cases.json is of this spec, from the generator of this repo', () {
expect(vectors['spec'], specVersion);
expect(vectors['generator'], 'tool/open_go_vectors.go');
expect(fixtures, hasLength(greaterThanOrEqualTo(48)));
expect(steps, hasLength(greaterThan(100)));
// Every fixture opens with each of its credentials.
final names = {for (final c in fixtures) str(c, 'name').split(':').first};
final files = Directory('testdata/fixtures')
.listSync()
.map((f) => f.uri.pathSegments.last)
.where((n) => n.endsWith('.dkc'))
.map((n) => n.substring(0, n.length - 4))
.toSet();
expect(names, files);
expect(fixtures.every((c) => c['result'] == 'ok'), isTrue);
// The steps that the mutation corpus does not reach are here.
final failed = {
for (final c in steps)
if (c['result'] != 'ok') ((c['checks']! as List).last as List)[0],
};
expect(failed, containsAll(<int>[2, 3, 7, 8, 9, 10, 11, 12, 13, 14]));
expect(failed, containsAll(<int>[15, 17]));
});
test('every fixture opens to its plaintext, or to the files of its record, '
'with each credential', () async {
for (final c in fixtures) {
final name = str(c, 'name').split(':').first;
final r = readJson('testdata/fixtures/$name.json');
final plaintext = fixture(str(r, 'plaintext_file'));
expect(toHex(sha256(plaintext)), r['plaintext_sha256'], reason: name);
final o = await openCase(c, capsuleOf(c, fixture));
expect(o.opened.ok, isTrue, reason: str(c, 'name'));
if (r['format'] != 3) {
expect(o.output.received.toBytes(), plaintext, reason: str(c, 'name'));
continue;
}
// Format 3: each file is the range of BODY that the record names.
final at = r['content_offset']! as int;
final files = (r['files'] as List? ?? const []).cast<Json>();
expect(o.sink.files, hasLength(files.length), reason: str(c, 'name'));
for (var i = 0; i < files.length; i++) {
final f = files[i];
expect(
o.sink.files[i].toBytes(),
plaintext.sublist(at + (f['start']! as int), at + (f['end']! as int)),
reason: '${c['name']}: ${f['path']}',
);
}
expect(
[o.opened.head!.comment, o.opened.head!.author, o.opened.areaLen],
[r['comment'] ?? '', r['declared_author'] ?? '', r['area_len']],
reason: str(c, 'name'),
);
}
});
test('the comparison sees every field', () async {
final c = steps.firstWhere((c) => c['name'] == 'format 3: two files');
final o = await openCase(c, capsuleOf(c, fixture));
expect(differences(c, o), isEmpty);
for (final (key, value) in <(String, Object?)>[
('result', 'ERR_INTEGRITY'),
('text', 'ok.'),
('checks', (c['checks']! as List).sublist(1)),
('release_requests', 0),
('sink', 'aborted'),
('files', <Object?>[]),
('unusable', {'head': <Object?>[]}),
]) {
expect(differences({...c, key: value}, o), hasLength(1), reason: key);
}
});
for (final (section, cases) in [('fixtures', fixtures), ('steps', steps)]) {
group(section, () {
for (final c in cases) {
test(str(c, 'name'), () async {
final dkc = capsuleOf(c, fixture);
final memory = await openCase(c, dkc);
expect(differences(c, memory), isEmpty, reason: 'in memory');
final source = await openCase(c, dkc, fromSource: true);
expect(differences(c, source), isEmpty, reason: 'from a source');
});
}
});
}
}

Powered by TurnKey Linux.