halkyon/apps/learn/halkyon_learn_curator/test/mecab_test.dart
Tizian 「ティツィアーン」 649499be23
chore: Halkyon Learn moves into apps/learn
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>
2026-10-22 18:11:02 +02:00

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);
});
}