Its server, client, app and curator, and the tools that write its assets (maps, Anki fixtures, icons), as they are; paths are fixed in the commits that follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
86 lines
2.6 KiB
Dart
86 lines
2.6 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:archive/archive.dart';
|
|
import 'package:halkyon_learn_curator/src/mecab.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
void main() {
|
|
late Directory compiled;
|
|
late Directory into;
|
|
|
|
setUp(() async {
|
|
compiled = await Directory.systemTemp.createTemp('compiled');
|
|
into = await Directory.systemTemp.createTemp('dictionaries');
|
|
for (final name in [
|
|
'char.bin',
|
|
'dicrc',
|
|
'matrix.bin',
|
|
'sys.dic',
|
|
'unk.dic',
|
|
]) {
|
|
await File('${compiled.path}/$name').writeAsString('$name of IPADIC');
|
|
}
|
|
});
|
|
tearDown(() async {
|
|
await compiled.delete(recursive: true);
|
|
await into.delete(recursive: true);
|
|
});
|
|
|
|
test('packs the files MeCab reads, the licence and an empty mecabrc into '
|
|
'one gzipped tar beside the dictionary files', () async {
|
|
final licence = File('${compiled.path}/copyright')
|
|
..writeAsStringSync('Copyright 2000, 2001, 2002, 2003 Nara Institute');
|
|
|
|
final packed = await packIpadic(compiled, into, licence: licence);
|
|
|
|
expect(packed?.path, '${into.path}/$ipadicFile');
|
|
final files = {
|
|
for (final file in TarDecoder().decodeBytes(
|
|
const GZipDecoder().decodeBytes(packed!.readAsBytesSync()),
|
|
))
|
|
file.name: String.fromCharCodes(file.content),
|
|
};
|
|
expect(files.keys, {
|
|
'char.bin',
|
|
'dicrc',
|
|
'matrix.bin',
|
|
'sys.dic',
|
|
'unk.dic',
|
|
'COPYING',
|
|
'mecabrc',
|
|
});
|
|
expect(files['sys.dic'], 'sys.dic of IPADIC');
|
|
expect(files['COPYING'], startsWith('Copyright'));
|
|
expect(files['mecabrc'], isEmpty);
|
|
// Nothing the server would load as a dictionary.
|
|
expect(
|
|
into.listSync().where(
|
|
(file) =>
|
|
file.path.endsWith('.jsonl') || file.path.endsWith('.jsonl.gz'),
|
|
),
|
|
isEmpty,
|
|
);
|
|
});
|
|
|
|
test('leaves the pack as it is when the dictionary is the same, so devices '
|
|
'download it again only once it changed', () async {
|
|
final first = await packIpadic(compiled, into);
|
|
final bytes = first!.readAsBytesSync();
|
|
|
|
expect(await packIpadic(compiled, into), isNull);
|
|
expect(File('${into.path}/$ipadicFile').readAsBytesSync(), bytes);
|
|
|
|
await File('${compiled.path}/sys.dic').writeAsString('a newer IPADIC');
|
|
expect(await packIpadic(compiled, into), isNotNull);
|
|
});
|
|
|
|
test('refuses a dictionary missing a file MeCab reads', () async {
|
|
await File('${compiled.path}/matrix.bin').delete();
|
|
|
|
await expectLater(
|
|
packIpadic(compiled, into),
|
|
throwsA(isA<FileSystemException>()),
|
|
);
|
|
expect(File('${into.path}/$ipadicFile').existsSync(), isFalse);
|
|
});
|
|
}
|