yomichan/test/test-database.js

887 lines
26 KiB
JavaScript
Raw Normal View History

2020-02-23 18:05:48 +00:00
/*
* Copyright (C) 2020-2022 Yomichan Authors
2020-02-23 18:05:48 +00:00
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
2020-02-22 17:47:09 +00:00
const path = require('path');
2020-02-19 03:19:55 +00:00
const assert = require('assert');
const {createDictionaryArchive, testMain} = require('../dev/util');
const {DatabaseVM, DatabaseVMDictionaryImporterMediaLoader} = require('../dev/database-vm');
2020-04-11 18:24:03 +00:00
const vm = new DatabaseVM();
vm.execute([
Move mixed/js (#1383) * Move mixed/js/core.js to js/core.js * Move mixed/js/yomichan.js to js/yomichan.js * Move mixed/js/timer.js to js/debug/timer.js * Move mixed/js/hotkey-handler.js to js/input/hotkey-handler.js * Move mixed/js/hotkey-help-controller.js to js/input/hotkey-help-controller.js * Move mixed/js/hotkey-util.js to js/input/hotkey-util.js * Move mixed/js/audio-system.js to js/input/audio-system.js * Move mixed/js/media-loader.js to js/input/media-loader.js * Move mixed/js/text-to-speech-audio.js to js/input/text-to-speech-audio.js * Move mixed/js/comm.js to js/comm/cross-frame-api.js * Move mixed/js/api.js to js/comm/api.js * Move mixed/js/frame-client.js to js/comm/frame-client.js * Move mixed/js/frame-endpoint.js to js/comm/frame-endpoint.js * Move mixed/js/display.js to js/display/display.js * Move mixed/js/display-audio.js to js/display/display-audio.js * Move mixed/js/display-generator.js to js/display/display-generator.js * Move mixed/js/display-history.js to js/display/display-history.js * Move mixed/js/display-notification.js to js/display/display-notification.js * Move mixed/js/display-profile-selection.js to js/display/display-profile-selection.js * Move mixed/js/japanese.js to js/language/japanese-util.js * Move mixed/js/dictionary-data-util.js to js/language/dictionary-data-util.js * Move mixed/js/document-focus-controller.js to js/dom/document-focus-controller.js * Move mixed/js/document-util.js to js/dom/document-util.js * Move mixed/js/dom-data-binder.js to js/dom/dom-data-binder.js * Move mixed/js/html-template-collection.js to js/dom/html-template-collection.js * Move mixed/js/panel-element.js to js/dom/panel-element.js * Move mixed/js/popup-menu.js to js/dom/popup-menu.js * Move mixed/js/selector-observer.js to js/dom/selector-observer.js * Move mixed/js/scroll.js to js/dom/window-scroll.js * Move mixed/js/text-scanner.js to js/language/text-scanner.js * Move mixed/js/cache-map.js to js/general/cache-map.js * Move mixed/js/object-property-accessor.js to js/general/object-property-accessor.js * Move mixed/js/task-accumulator.js to js/general/task-accumulator.js * Move mixed/js/environment.js to js/background/environment.js * Move mixed/js/dynamic-loader.js to js/scripting/dynamic-loader.js * Move mixed/js/dynamic-loader-sentinel.js to js/scripting/dynamic-loader-sentinel.js
2021-02-14 03:52:28 +00:00
'js/core.js',
'js/general/cache-map.js',
Move bg/js (#1387) * Move bg/js/anki.js to js/comm/anki.js * Move bg/js/mecab.js to js/comm/mecab.js * Move bg/js/search-main.js to js/display/search-main.js * Move bg/js/template-patcher.js to js/templates/template-patcher.js * Move bg/js/template-renderer-frame-api.js to js/templates/template-renderer-frame-api.js * Move bg/js/template-renderer-frame-main.js to js/templates/template-renderer-frame-main.js * Move bg/js/template-renderer-proxy.js to js/templates/template-renderer-proxy.js * Move bg/js/template-renderer.js to js/templates/template-renderer.js * Move bg/js/media-utility.js to js/media/media-utility.js * Move bg/js/native-simple-dom-parser.js to js/dom/native-simple-dom-parser.js * Move bg/js/simple-dom-parser.js to js/dom/simple-dom-parser.js * Move bg/js/audio-downloader.js to js/media/audio-downloader.js * Move bg/js/deinflector.js to js/language/deinflector.js * Move bg/js/backend.js to js/background/backend.js * Move bg/js/translator.js to js/language/translator.js * Move bg/js/search-display-controller.js to js/display/search-display-controller.js * Move bg/js/request-builder.js to js/background/request-builder.js * Move bg/js/text-source-map.js to js/general/text-source-map.js * Move bg/js/clipboard-reader.js to js/comm/clipboard-reader.js * Move bg/js/clipboard-monitor.js to js/comm/clipboard-monitor.js * Move bg/js/query-parser.js to js/display/query-parser.js * Move bg/js/profile-conditions.js to js/background/profile-conditions.js * Move bg/js/dictionary-database.js to js/language/dictionary-database.js * Move bg/js/dictionary-importer.js to js/language/dictionary-importer.js * Move bg/js/anki-note-builder.js to js/data/anki-note-builder.js * Move bg/js/anki-note-data.js to js/data/anki-note-data.js * Move bg/js/database.js to js/data/database.js * Move bg/js/json-schema.js to js/data/json-schema.js * Move bg/js/options.js to js/data/options-util.js * Move bg/js/background-main.js to js/background/background-main.js * Move bg/js/permissions-util.js to js/data/permissions-util.js * Move bg/js/context-main.js to js/pages/action-popup-main.js * Move bg/js/generic-page-main.js to js/pages/generic-page-main.js * Move bg/js/info-main.js to js/pages/info-main.js * Move bg/js/permissions-main.js to js/pages/permissions-main.js * Move bg/js/welcome-main.js to js/pages/welcome-main.js
2021-02-14 16:19:54 +00:00
'js/data/json-schema.js',
'js/media/media-util.js',
Move bg/js (#1387) * Move bg/js/anki.js to js/comm/anki.js * Move bg/js/mecab.js to js/comm/mecab.js * Move bg/js/search-main.js to js/display/search-main.js * Move bg/js/template-patcher.js to js/templates/template-patcher.js * Move bg/js/template-renderer-frame-api.js to js/templates/template-renderer-frame-api.js * Move bg/js/template-renderer-frame-main.js to js/templates/template-renderer-frame-main.js * Move bg/js/template-renderer-proxy.js to js/templates/template-renderer-proxy.js * Move bg/js/template-renderer.js to js/templates/template-renderer.js * Move bg/js/media-utility.js to js/media/media-utility.js * Move bg/js/native-simple-dom-parser.js to js/dom/native-simple-dom-parser.js * Move bg/js/simple-dom-parser.js to js/dom/simple-dom-parser.js * Move bg/js/audio-downloader.js to js/media/audio-downloader.js * Move bg/js/deinflector.js to js/language/deinflector.js * Move bg/js/backend.js to js/background/backend.js * Move bg/js/translator.js to js/language/translator.js * Move bg/js/search-display-controller.js to js/display/search-display-controller.js * Move bg/js/request-builder.js to js/background/request-builder.js * Move bg/js/text-source-map.js to js/general/text-source-map.js * Move bg/js/clipboard-reader.js to js/comm/clipboard-reader.js * Move bg/js/clipboard-monitor.js to js/comm/clipboard-monitor.js * Move bg/js/query-parser.js to js/display/query-parser.js * Move bg/js/profile-conditions.js to js/background/profile-conditions.js * Move bg/js/dictionary-database.js to js/language/dictionary-database.js * Move bg/js/dictionary-importer.js to js/language/dictionary-importer.js * Move bg/js/anki-note-builder.js to js/data/anki-note-builder.js * Move bg/js/anki-note-data.js to js/data/anki-note-data.js * Move bg/js/database.js to js/data/database.js * Move bg/js/json-schema.js to js/data/json-schema.js * Move bg/js/options.js to js/data/options-util.js * Move bg/js/background-main.js to js/background/background-main.js * Move bg/js/permissions-util.js to js/data/permissions-util.js * Move bg/js/context-main.js to js/pages/action-popup-main.js * Move bg/js/generic-page-main.js to js/pages/generic-page-main.js * Move bg/js/info-main.js to js/pages/info-main.js * Move bg/js/permissions-main.js to js/pages/permissions-main.js * Move bg/js/welcome-main.js to js/pages/welcome-main.js
2021-02-14 16:19:54 +00:00
'js/language/dictionary-importer.js',
'js/data/database.js',
'js/language/dictionary-database.js'
]);
const DictionaryImporter = vm.get('DictionaryImporter');
const DictionaryDatabase = vm.get('DictionaryDatabase');
2020-02-19 03:19:55 +00:00
function createTestDictionaryArchive(dictionary, dictionaryName) {
const dictionaryDirectory = path.join(__dirname, 'data', 'dictionaries', dictionary);
return createDictionaryArchive(dictionaryDirectory, dictionaryName);
}
function createDictionaryImporter(onProgress) {
const dictionaryImporterMediaLoader = new DatabaseVMDictionaryImporterMediaLoader();
return new DictionaryImporter(dictionaryImporterMediaLoader, (...args) => {
const {stepIndex, stepCount, index, count} = args[0];
assert.ok(stepIndex < stepCount);
assert.ok(index <= count);
if (typeof onProgress === 'function') {
onProgress(...args);
}
});
}
function countDictionaryDatabaseEntriesWithTerm(dictionaryDatabaseEntries, term) {
return dictionaryDatabaseEntries.reduce((i, v) => (i + (v.term === term ? 1 : 0)), 0);
2020-02-19 03:19:55 +00:00
}
function countDictionaryDatabaseEntriesWithReading(dictionaryDatabaseEntries, reading) {
return dictionaryDatabaseEntries.reduce((i, v) => (i + (v.reading === reading ? 1 : 0)), 0);
2020-02-19 03:19:55 +00:00
}
function countMetasWithMode(metas, mode) {
return metas.reduce((i, v) => (i + (v.mode === mode ? 1 : 0)), 0);
}
function countKanjiWithCharacter(kanji, character) {
return kanji.reduce((i, v) => (i + (v.character === character ? 1 : 0)), 0);
}
function clearDatabase(timeout) {
return new Promise((resolve, reject) => {
2020-02-23 16:44:24 +00:00
let timer = setTimeout(() => {
timer = null;
reject(new Error(`clearDatabase failed to resolve after ${timeout}ms`));
}, timeout);
(async () => {
const indexedDB = vm.indexedDB;
for (const {name} of await indexedDB.databases()) {
2020-02-22 19:54:57 +00:00
await new Promise((resolve2, reject2) => {
const request = indexedDB.deleteDatabase(name);
2020-02-22 19:54:57 +00:00
request.onerror = (e) => reject2(e);
request.onsuccess = () => resolve2();
});
}
2020-02-23 16:44:24 +00:00
if (timer !== null) {
clearTimeout(timer);
}
resolve();
})();
});
2020-02-20 01:00:44 +00:00
}
2020-02-19 03:19:55 +00:00
async function testDatabase1() {
// Load dictionary data
const testDictionary = createTestDictionaryArchive('valid-dictionary1');
const testDictionarySource = await testDictionary.generateAsync({type: 'arraybuffer'});
2020-02-19 03:19:55 +00:00
const testDictionaryIndex = JSON.parse(await testDictionary.files['index.json'].async('string'));
const title = testDictionaryIndex.title;
2020-02-22 19:42:05 +00:00
const titles = new Map([
[title, {priority: 0, allowSecondarySearches: false}]
]);
2020-02-19 03:19:55 +00:00
// Setup iteration data
const iterations = [
{
cleanup: async () => {
// Test purge
await dictionaryDatabase.purge();
await testDatabaseEmpty1(dictionaryDatabase);
2020-02-19 03:19:55 +00:00
}
},
{
cleanup: async () => {
// Test deleteDictionary
let progressEvent = false;
await dictionaryDatabase.deleteDictionary(
2020-02-19 03:19:55 +00:00
title,
1000,
2020-02-19 03:19:55 +00:00
() => {
progressEvent = true;
}
2020-02-19 03:19:55 +00:00
);
assert.ok(progressEvent);
await testDatabaseEmpty1(dictionaryDatabase);
2020-02-19 03:19:55 +00:00
}
},
{
cleanup: async () => {}
}
];
// Setup database
const dictionaryDatabase = new DictionaryDatabase();
await dictionaryDatabase.prepare();
2020-02-19 03:19:55 +00:00
for (const {cleanup} of iterations) {
2020-02-19 23:46:27 +00:00
const expectedSummary = {
title,
revision: 'test',
sequenced: true,
version: 3,
importDate: 0,
prefixWildcardsSupported: true,
counts: {
kanji: {total: 2},
kanjiMeta: {total: 6, freq: 6},
media: {total: 4},
tagMeta: {total: 15},
termMeta: {total: 38, freq: 31, pitch: 7},
terms: {total: 21}
}
2020-02-19 23:46:27 +00:00
};
2020-02-19 03:19:55 +00:00
// Import data
let progressEvent = false;
const dictionaryImporter = createDictionaryImporter(() => { progressEvent = true; });
const {result, errors} = await dictionaryImporter.importDictionary(
dictionaryDatabase,
2020-02-19 03:19:55 +00:00
testDictionarySource,
{prefixWildcardsSupported: true}
2020-02-19 03:19:55 +00:00
);
expectedSummary.importDate = result.importDate;
vm.assert.deepStrictEqual(errors, []);
vm.assert.deepStrictEqual(result, expectedSummary);
2020-02-19 03:19:55 +00:00
assert.ok(progressEvent);
// Get info summary
const info = await dictionaryDatabase.getDictionaryInfo();
vm.assert.deepStrictEqual(info, [expectedSummary]);
2020-02-19 03:19:55 +00:00
// Get counts
const counts = await dictionaryDatabase.getDictionaryCounts(
2020-02-19 03:19:55 +00:00
info.map((v) => v.title),
true
);
vm.assert.deepStrictEqual(counts, {
counts: [{kanji: 2, kanjiMeta: 6, terms: 21, termMeta: 38, tagMeta: 15, media: 4}],
total: {kanji: 2, kanjiMeta: 6, terms: 21, termMeta: 38, tagMeta: 15, media: 4}
2020-02-19 03:19:55 +00:00
});
// Test find* functions
await testFindTermsBulkTest1(dictionaryDatabase, titles);
await testTindTermsExactBulk1(dictionaryDatabase, titles);
await testFindTermsBySequenceBulk1(dictionaryDatabase, title);
await testFindTermMetaBulk1(dictionaryDatabase, titles);
await testFindKanjiBulk1(dictionaryDatabase, titles);
await testFindKanjiMetaBulk1(dictionaryDatabase, titles);
await testFindTagForTitle1(dictionaryDatabase, title);
2020-02-19 03:19:55 +00:00
// Cleanup
await cleanup();
}
2020-02-20 00:59:24 +00:00
await dictionaryDatabase.close();
2020-02-19 03:19:55 +00:00
}
async function testDatabaseEmpty1(database) {
const info = await database.getDictionaryInfo();
vm.assert.deepStrictEqual(info, []);
2020-02-19 03:19:55 +00:00
const counts = await database.getDictionaryCounts([], true);
vm.assert.deepStrictEqual(counts, {
2020-02-19 03:19:55 +00:00
counts: [],
total: {kanji: 0, kanjiMeta: 0, terms: 0, termMeta: 0, tagMeta: 0, media: 0}
2020-02-19 03:19:55 +00:00
});
}
async function testFindTermsBulkTest1(database, titles) {
const data = [
{
inputs: [
{
matchType: null,
2020-02-19 03:19:55 +00:00
termList: ['打', '打つ', '打ち込む']
},
{
matchType: null,
2020-02-19 03:19:55 +00:00
termList: ['だ', 'ダース', 'うつ', 'ぶつ', 'うちこむ', 'ぶちこむ']
},
{
matchType: 'prefix',
2020-02-19 03:19:55 +00:00
termList: ['打']
}
],
expectedResults: {
total: 10,
terms: [
2020-02-19 03:19:55 +00:00
['打', 2],
['打つ', 4],
['打ち込む', 4]
2020-02-19 03:19:55 +00:00
],
readings: [
['だ', 1],
['ダース', 1],
['うつ', 2],
2020-02-19 03:19:55 +00:00
['ぶつ', 2],
['うちこむ', 2],
['ぶちこむ', 2]
2020-02-19 03:19:55 +00:00
]
}
},
{
inputs: [
{
matchType: null,
2020-02-19 03:19:55 +00:00
termList: ['込む']
}
],
expectedResults: {
total: 0,
terms: [],
2020-02-19 03:19:55 +00:00
readings: []
}
},
{
inputs: [
{
matchType: 'suffix',
2020-02-19 03:19:55 +00:00
termList: ['込む']
}
],
expectedResults: {
total: 4,
terms: [
['打ち込む', 4]
2020-02-19 03:19:55 +00:00
],
readings: [
['うちこむ', 2],
['ぶちこむ', 2]
2020-02-19 03:19:55 +00:00
]
}
},
{
inputs: [
{
matchType: null,
2020-02-19 03:19:55 +00:00
termList: []
}
],
expectedResults: {
total: 0,
terms: [],
2020-02-19 03:19:55 +00:00
readings: []
}
}
];
for (const {inputs, expectedResults} of data) {
for (const {termList, matchType} of inputs) {
const results = await database.findTermsBulk(termList, titles, matchType);
2020-02-19 03:19:55 +00:00
assert.strictEqual(results.length, expectedResults.total);
for (const [term, count] of expectedResults.terms) {
assert.strictEqual(countDictionaryDatabaseEntriesWithTerm(results, term), count);
2020-02-19 03:19:55 +00:00
}
for (const [reading, count] of expectedResults.readings) {
assert.strictEqual(countDictionaryDatabaseEntriesWithReading(results, reading), count);
2020-02-19 03:19:55 +00:00
}
}
}
}
async function testTindTermsExactBulk1(database, titles) {
const data = [
{
inputs: [
{
termList: [
{term: '打', reading: 'だ'},
{term: '打つ', reading: 'うつ'},
{term: '打ち込む', reading: 'うちこむ'}
]
2020-02-19 03:19:55 +00:00
}
],
expectedResults: {
total: 5,
terms: [
2020-02-19 03:19:55 +00:00
['打', 1],
['打つ', 2],
['打ち込む', 2]
2020-02-19 03:19:55 +00:00
],
readings: [
['だ', 1],
['うつ', 2],
['うちこむ', 2]
2020-02-19 03:19:55 +00:00
]
}
},
{
inputs: [
{
termList: [
{term: '打', reading: 'だ?'},
{term: '打つ', reading: 'うつ?'},
{term: '打ち込む', reading: 'うちこむ?'}
]
2020-02-19 03:19:55 +00:00
}
],
expectedResults: {
total: 0,
terms: [],
2020-02-19 03:19:55 +00:00
readings: []
}
},
{
inputs: [
{
termList: [
{term: '打つ', reading: 'うつ'},
{term: '打つ', reading: 'ぶつ'}
]
2020-02-19 03:19:55 +00:00
}
],
expectedResults: {
total: 4,
terms: [
['打つ', 4]
2020-02-19 03:19:55 +00:00
],
readings: [
['うつ', 2],
2020-02-19 03:19:55 +00:00
['ぶつ', 2]
]
}
},
{
inputs: [
{
termList: [
{term: '打つ', reading: 'うちこむ'}
]
2020-02-19 03:19:55 +00:00
}
],
expectedResults: {
total: 0,
terms: [],
2020-02-19 03:19:55 +00:00
readings: []
}
},
{
inputs: [
{
termList: []
2020-02-19 03:19:55 +00:00
}
],
expectedResults: {
total: 0,
terms: [],
2020-02-19 03:19:55 +00:00
readings: []
}
}
];
for (const {inputs, expectedResults} of data) {
for (const {termList} of inputs) {
const results = await database.findTermsExactBulk(termList, titles);
2020-02-19 03:19:55 +00:00
assert.strictEqual(results.length, expectedResults.total);
for (const [term, count] of expectedResults.terms) {
assert.strictEqual(countDictionaryDatabaseEntriesWithTerm(results, term), count);
2020-02-19 03:19:55 +00:00
}
for (const [reading, count] of expectedResults.readings) {
assert.strictEqual(countDictionaryDatabaseEntriesWithReading(results, reading), count);
2020-02-19 03:19:55 +00:00
}
}
}
}
async function testFindTermsBySequenceBulk1(database, mainDictionary) {
const data = [
{
inputs: [
{
sequenceList: [1, 2, 3, 4, 5]
2020-02-19 03:19:55 +00:00
}
],
expectedResults: {
total: 11,
terms: [
2020-02-19 03:19:55 +00:00
['打', 2],
['打つ', 4],
['打ち込む', 4],
['画像', 1]
2020-02-19 03:19:55 +00:00
],
readings: [
['だ', 1],
['ダース', 1],
['うつ', 2],
2020-02-19 03:19:55 +00:00
['ぶつ', 2],
['うちこむ', 2],
['ぶちこむ', 2],
['がぞう', 1]
2020-02-19 03:19:55 +00:00
]
}
},
{
inputs: [
{
sequenceList: [1]
}
],
expectedResults: {
total: 1,
terms: [
2020-02-19 03:19:55 +00:00
['打', 1]
],
readings: [
['だ', 1]
]
}
},
{
inputs: [
{
sequenceList: [2]
}
],
expectedResults: {
total: 1,
terms: [
2020-02-19 03:19:55 +00:00
['打', 1]
],
readings: [
['ダース', 1]
]
}
},
{
inputs: [
{
sequenceList: [3]
}
],
expectedResults: {
total: 4,
terms: [
['打つ', 4]
2020-02-19 03:19:55 +00:00
],
readings: [
['うつ', 2],
['ぶつ', 2]
2020-02-19 03:19:55 +00:00
]
}
},
{
inputs: [
{
sequenceList: [4]
}
],
expectedResults: {
total: 4,
terms: [
['打ち込む', 4]
2020-02-19 03:19:55 +00:00
],
readings: [
['うちこむ', 2],
['ぶちこむ', 2]
2020-02-19 03:19:55 +00:00
]
}
},
{
inputs: [
{
sequenceList: [5]
}
],
expectedResults: {
total: 1,
terms: [
['画像', 1]
2020-02-19 03:19:55 +00:00
],
readings: [
['がぞう', 1]
2020-02-19 03:19:55 +00:00
]
}
},
{
inputs: [
{
sequenceList: [-1]
}
],
expectedResults: {
total: 0,
terms: [],
2020-02-19 03:19:55 +00:00
readings: []
}
},
{
inputs: [
{
sequenceList: []
}
],
expectedResults: {
total: 0,
terms: [],
2020-02-19 03:19:55 +00:00
readings: []
}
}
];
for (const {inputs, expectedResults} of data) {
for (const {sequenceList} of inputs) {
const results = await database.findTermsBySequenceBulk(sequenceList.map((query) => ({query, dictionary: mainDictionary})));
2020-02-19 03:19:55 +00:00
assert.strictEqual(results.length, expectedResults.total);
for (const [term, count] of expectedResults.terms) {
assert.strictEqual(countDictionaryDatabaseEntriesWithTerm(results, term), count);
2020-02-19 03:19:55 +00:00
}
for (const [reading, count] of expectedResults.readings) {
assert.strictEqual(countDictionaryDatabaseEntriesWithReading(results, reading), count);
2020-02-19 03:19:55 +00:00
}
}
}
}
async function testFindTermMetaBulk1(database, titles) {
const data = [
{
inputs: [
{
termList: ['打']
}
],
expectedResults: {
total: 11,
2020-02-19 03:19:55 +00:00
modes: [
['freq', 11]
2020-02-19 03:19:55 +00:00
]
}
},
{
inputs: [
{
termList: ['打つ']
}
],
expectedResults: {
total: 10,
2020-02-19 03:19:55 +00:00
modes: [
['freq', 10]
2020-02-19 03:19:55 +00:00
]
}
},
{
inputs: [
{
termList: ['打ち込む']
}
],
expectedResults: {
total: 12,
2020-02-19 03:19:55 +00:00
modes: [
['freq', 10],
['pitch', 2]
2020-02-19 03:19:55 +00:00
]
}
},
{
inputs: [
{
termList: ['?']
}
],
expectedResults: {
total: 0,
modes: []
}
}
];
for (const {inputs, expectedResults} of data) {
for (const {termList} of inputs) {
const results = await database.findTermMetaBulk(termList, titles);
assert.strictEqual(results.length, expectedResults.total);
for (const [mode, count] of expectedResults.modes) {
assert.strictEqual(countMetasWithMode(results, mode), count);
}
}
}
}
async function testFindKanjiBulk1(database, titles) {
const data = [
{
inputs: [
{
kanjiList: ['打']
}
],
expectedResults: {
total: 1,
kanji: [
['打', 1]
]
}
},
{
inputs: [
{
kanjiList: ['込']
}
],
expectedResults: {
total: 1,
kanji: [
['込', 1]
]
}
},
{
inputs: [
{
kanjiList: ['?']
}
],
expectedResults: {
total: 0,
kanji: []
}
}
];
for (const {inputs, expectedResults} of data) {
for (const {kanjiList} of inputs) {
const results = await database.findKanjiBulk(kanjiList, titles);
assert.strictEqual(results.length, expectedResults.total);
for (const [kanji, count] of expectedResults.kanji) {
assert.strictEqual(countKanjiWithCharacter(results, kanji), count);
}
}
}
}
async function testFindKanjiMetaBulk1(database, titles) {
const data = [
{
inputs: [
{
kanjiList: ['打']
}
],
expectedResults: {
total: 3,
2020-02-19 03:19:55 +00:00
modes: [
['freq', 3]
2020-02-19 03:19:55 +00:00
]
}
},
{
inputs: [
{
kanjiList: ['込']
}
],
expectedResults: {
total: 3,
2020-02-19 03:19:55 +00:00
modes: [
['freq', 3]
2020-02-19 03:19:55 +00:00
]
}
},
{
inputs: [
{
kanjiList: ['?']
}
],
expectedResults: {
total: 0,
modes: []
}
}
];
for (const {inputs, expectedResults} of data) {
for (const {kanjiList} of inputs) {
const results = await database.findKanjiMetaBulk(kanjiList, titles);
assert.strictEqual(results.length, expectedResults.total);
for (const [mode, count] of expectedResults.modes) {
assert.strictEqual(countMetasWithMode(results, mode), count);
}
}
}
}
async function testFindTagForTitle1(database, title) {
const data = [
{
inputs: [
{
name: 'E1'
2020-02-19 03:19:55 +00:00
}
],
expectedResults: {
value: {category: 'default', dictionary: title, name: 'E1', notes: 'example tag 1', order: 0, score: 0}
2020-02-19 03:19:55 +00:00
}
},
{
inputs: [
{
name: 'K1'
2020-02-19 03:19:55 +00:00
}
],
expectedResults: {
value: {category: 'default', dictionary: title, name: 'K1', notes: 'example kanji tag 1', order: 0, score: 0}
2020-02-19 03:19:55 +00:00
}
},
{
inputs: [
{
name: 'kstat1'
}
],
expectedResults: {
value: {category: 'class', dictionary: title, name: 'kstat1', notes: 'kanji stat 1', order: 0, score: 0}
2020-02-19 03:19:55 +00:00
}
},
{
inputs: [
{
name: 'invalid'
}
],
expectedResults: {
value: null
}
}
];
for (const {inputs, expectedResults} of data) {
for (const {name} of inputs) {
const result = await database.findTagForTitle(name, title);
vm.assert.deepStrictEqual(result, expectedResults.value);
2020-02-19 03:19:55 +00:00
}
}
}
2020-02-20 01:00:44 +00:00
async function testDatabase2() {
// Load dictionary data
const testDictionary = createTestDictionaryArchive('valid-dictionary1');
const testDictionarySource = await testDictionary.generateAsync({type: 'arraybuffer'});
2020-02-20 01:00:44 +00:00
const testDictionaryIndex = JSON.parse(await testDictionary.files['index.json'].async('string'));
const title = testDictionaryIndex.title;
2020-02-22 19:42:05 +00:00
const titles = new Map([
[title, {priority: 0, allowSecondarySearches: false}]
]);
2020-02-20 01:00:44 +00:00
// Setup database
const dictionaryDatabase = new DictionaryDatabase();
2020-02-20 01:00:44 +00:00
// Error: not prepared
await assert.rejects(async () => await dictionaryDatabase.deleteDictionary(title, 1000));
await assert.rejects(async () => await dictionaryDatabase.findTermsBulk(['?'], titles, null));
await assert.rejects(async () => await dictionaryDatabase.findTermsExactBulk([{term: '?', reading: '?'}], titles));
await assert.rejects(async () => await dictionaryDatabase.findTermsBySequenceBulk([{query: 1, dictionary: title}]));
await assert.rejects(async () => await dictionaryDatabase.findTermMetaBulk(['?'], titles));
await assert.rejects(async () => await dictionaryDatabase.findTermMetaBulk(['?'], titles));
await assert.rejects(async () => await dictionaryDatabase.findKanjiBulk(['?'], titles));
await assert.rejects(async () => await dictionaryDatabase.findKanjiMetaBulk(['?'], titles));
await assert.rejects(async () => await dictionaryDatabase.findTagForTitle('tag', title));
await assert.rejects(async () => await dictionaryDatabase.getDictionaryInfo());
await assert.rejects(async () => await dictionaryDatabase.getDictionaryCounts(titles, true));
await assert.rejects(async () => await createDictionaryImporter().importDictionary(dictionaryDatabase, testDictionarySource, {}));
await dictionaryDatabase.prepare();
2020-02-20 01:00:44 +00:00
// Error: already prepared
await assert.rejects(async () => await dictionaryDatabase.prepare());
2020-02-20 01:00:44 +00:00
await createDictionaryImporter().importDictionary(dictionaryDatabase, testDictionarySource, {});
2020-02-20 01:00:44 +00:00
// Error: dictionary already imported
await assert.rejects(async () => await createDictionaryImporter().importDictionary(dictionaryDatabase, testDictionarySource, {}));
2020-02-20 01:00:44 +00:00
await dictionaryDatabase.close();
2020-02-20 01:00:44 +00:00
}
async function testDatabase3() {
const invalidDictionaries = [
'invalid-dictionary1',
'invalid-dictionary2',
'invalid-dictionary3',
'invalid-dictionary4',
'invalid-dictionary5',
'invalid-dictionary6'
];
// Setup database
const dictionaryDatabase = new DictionaryDatabase();
await dictionaryDatabase.prepare();
for (const invalidDictionary of invalidDictionaries) {
const testDictionary = createTestDictionaryArchive(invalidDictionary);
const testDictionarySource = await testDictionary.generateAsync({type: 'arraybuffer'});
let error = null;
try {
await createDictionaryImporter().importDictionary(dictionaryDatabase, testDictionarySource, {});
} catch (e) {
error = e;
}
if (error === null) {
assert.ok(false, `Expected an error while importing ${invalidDictionary}`);
} else {
const prefix = 'Dictionary has invalid data';
const message = error.message;
assert.ok(typeof message, 'string');
assert.ok(message.startsWith(prefix), `Expected error message to start with '${prefix}': ${message}`);
}
}
await dictionaryDatabase.close();
}
2020-02-19 03:19:55 +00:00
async function main() {
const clearTimeout = 5000;
try {
await testDatabase1();
await clearDatabase(clearTimeout);
await testDatabase2();
await clearDatabase(clearTimeout);
await testDatabase3();
await clearDatabase(clearTimeout);
} catch (e) {
console.log(e);
process.exit(-1);
throw e;
}
2020-02-19 03:19:55 +00:00
}
if (require.main === module) { testMain(main); }