2020-02-23 18:05:48 +00:00
|
|
|
/*
|
2021-01-01 19:50:41 +00:00
|
|
|
* Copyright (C) 2020-2021 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');
|
2020-12-09 01:27:36 +00:00
|
|
|
const {createDictionaryArchive, testMain} = require('../dev/util');
|
|
|
|
const {DatabaseVM} = require('../dev/database-vm');
|
2020-04-11 18:24:03 +00:00
|
|
|
|
2020-03-03 03:20:47 +00:00
|
|
|
|
2020-12-09 01:27:36 +00:00
|
|
|
const vm = new DatabaseVM();
|
2020-03-03 03:20:47 +00:00
|
|
|
vm.execute([
|
2021-02-14 03:52:28 +00:00
|
|
|
'js/core.js',
|
|
|
|
'js/general/cache-map.js',
|
2021-02-14 16:19:54 +00:00
|
|
|
'js/data/json-schema.js',
|
2021-02-14 16:32:30 +00:00
|
|
|
'js/media/media-util.js',
|
2021-02-14 16:19:54 +00:00
|
|
|
'js/language/dictionary-importer.js',
|
|
|
|
'js/data/database.js',
|
|
|
|
'js/language/dictionary-database.js'
|
2020-03-03 03:20:47 +00:00
|
|
|
]);
|
2020-03-31 00:51:20 +00:00
|
|
|
const DictionaryImporter = vm.get('DictionaryImporter');
|
2020-06-28 21:24:06 +00:00
|
|
|
const DictionaryDatabase = vm.get('DictionaryDatabase');
|
2020-02-19 03:19:55 +00:00
|
|
|
|
|
|
|
|
2020-09-19 23:04:28 +00:00
|
|
|
function createTestDictionaryArchive(dictionary, dictionaryName) {
|
|
|
|
const dictionaryDirectory = path.join(__dirname, 'data', 'dictionaries', dictionary);
|
|
|
|
return createDictionaryArchive(dictionaryDirectory, dictionaryName);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-04-04 20:22:35 +00:00
|
|
|
function countDictionaryDatabaseEntriesWithTerm(dictionaryDatabaseEntries, term) {
|
|
|
|
return dictionaryDatabaseEntries.reduce((i, v) => (i + (v.term === term ? 1 : 0)), 0);
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
|
2021-04-04 20:22:35 +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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-22 18:09:18 +00:00
|
|
|
function clearDatabase(timeout) {
|
|
|
|
return new Promise((resolve, reject) => {
|
2020-02-23 16:44:24 +00:00
|
|
|
let timer = setTimeout(() => {
|
|
|
|
timer = null;
|
2020-02-22 18:09:18 +00:00
|
|
|
reject(new Error(`clearDatabase failed to resolve after ${timeout}ms`));
|
|
|
|
}, timeout);
|
|
|
|
|
|
|
|
(async () => {
|
2020-12-09 01:27:36 +00:00
|
|
|
const indexedDB = vm.indexedDB;
|
2020-02-22 18:09:18 +00:00
|
|
|
for (const {name} of await indexedDB.databases()) {
|
2020-02-22 19:54:57 +00:00
|
|
|
await new Promise((resolve2, reject2) => {
|
2020-02-22 18:09:18 +00:00
|
|
|
const request = indexedDB.deleteDatabase(name);
|
2020-02-22 19:54:57 +00:00
|
|
|
request.onerror = (e) => reject2(e);
|
|
|
|
request.onsuccess = () => resolve2();
|
2020-02-22 18:09:18 +00:00
|
|
|
});
|
|
|
|
}
|
2020-02-23 16:44:24 +00:00
|
|
|
if (timer !== null) {
|
|
|
|
clearTimeout(timer);
|
|
|
|
}
|
2020-02-22 18:09:18 +00:00
|
|
|
resolve();
|
|
|
|
})();
|
|
|
|
});
|
2020-02-20 01:00:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-19 03:19:55 +00:00
|
|
|
async function testDatabase1() {
|
|
|
|
// Load dictionary data
|
2020-08-10 01:00:37 +00:00
|
|
|
const testDictionary = createTestDictionaryArchive('valid-dictionary1');
|
2020-02-19 03:19:55 +00:00
|
|
|
const testDictionarySource = await testDictionary.generateAsync({type: 'string'});
|
|
|
|
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
|
2020-06-28 21:24:06 +00:00
|
|
|
await dictionaryDatabase.purge();
|
|
|
|
await testDatabaseEmpty1(dictionaryDatabase);
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cleanup: async () => {
|
|
|
|
// Test deleteDictionary
|
|
|
|
let progressEvent = false;
|
2020-06-28 21:24:06 +00:00
|
|
|
await dictionaryDatabase.deleteDictionary(
|
2020-02-19 03:19:55 +00:00
|
|
|
title,
|
2020-05-06 23:28:26 +00:00
|
|
|
{rate: 1000},
|
2020-02-19 03:19:55 +00:00
|
|
|
() => {
|
|
|
|
progressEvent = true;
|
2020-05-06 23:28:26 +00:00
|
|
|
}
|
2020-02-19 03:19:55 +00:00
|
|
|
);
|
|
|
|
assert.ok(progressEvent);
|
|
|
|
|
2020-06-28 21:24:06 +00:00
|
|
|
await testDatabaseEmpty1(dictionaryDatabase);
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
cleanup: async () => {}
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
// Setup database
|
2020-03-31 00:51:20 +00:00
|
|
|
const dictionaryImporter = new DictionaryImporter();
|
2020-06-28 21:24:06 +00:00
|
|
|
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,
|
|
|
|
prefixWildcardsSupported: true
|
|
|
|
};
|
|
|
|
|
2020-02-19 03:19:55 +00:00
|
|
|
// Import data
|
|
|
|
let progressEvent = false;
|
2020-07-20 02:05:37 +00:00
|
|
|
const {result, errors} = await dictionaryImporter.importDictionary(
|
2020-06-28 21:24:06 +00:00
|
|
|
dictionaryDatabase,
|
2020-02-19 03:19:55 +00:00
|
|
|
testDictionarySource,
|
2020-05-06 23:28:26 +00:00
|
|
|
{prefixWildcardsSupported: true},
|
2020-02-19 03:19:55 +00:00
|
|
|
() => {
|
|
|
|
progressEvent = true;
|
2020-05-06 23:28:26 +00:00
|
|
|
}
|
2020-02-19 03:19:55 +00:00
|
|
|
);
|
2020-03-03 03:20:47 +00:00
|
|
|
vm.assert.deepStrictEqual(errors, []);
|
|
|
|
vm.assert.deepStrictEqual(result, expectedSummary);
|
2020-02-19 03:19:55 +00:00
|
|
|
assert.ok(progressEvent);
|
|
|
|
|
|
|
|
// Get info summary
|
2020-06-28 21:24:06 +00:00
|
|
|
const info = await dictionaryDatabase.getDictionaryInfo();
|
2020-03-03 03:20:47 +00:00
|
|
|
vm.assert.deepStrictEqual(info, [expectedSummary]);
|
2020-02-19 03:19:55 +00:00
|
|
|
|
|
|
|
// Get counts
|
2020-06-28 21:24:06 +00:00
|
|
|
const counts = await dictionaryDatabase.getDictionaryCounts(
|
2020-02-19 03:19:55 +00:00
|
|
|
info.map((v) => v.title),
|
|
|
|
true
|
|
|
|
);
|
2020-03-03 03:20:47 +00:00
|
|
|
vm.assert.deepStrictEqual(counts, {
|
2021-07-16 02:39:33 +00:00
|
|
|
counts: [{kanji: 2, kanjiMeta: 2, terms: 15, termMeta: 15, tagMeta: 15, media: 2}],
|
|
|
|
total: {kanji: 2, kanjiMeta: 2, terms: 15, termMeta: 15, tagMeta: 15, media: 2}
|
2020-02-19 03:19:55 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
// Test find* functions
|
2020-06-28 21:24:06 +00:00
|
|
|
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
|
|
|
|
2020-06-28 21:24:06 +00:00
|
|
|
await dictionaryDatabase.close();
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async function testDatabaseEmpty1(database) {
|
|
|
|
const info = await database.getDictionaryInfo();
|
2020-03-03 03:20:47 +00:00
|
|
|
vm.assert.deepStrictEqual(info, []);
|
2020-02-19 03:19:55 +00:00
|
|
|
|
|
|
|
const counts = await database.getDictionaryCounts([], true);
|
2020-03-03 03:20:47 +00:00
|
|
|
vm.assert.deepStrictEqual(counts, {
|
2020-02-19 03:19:55 +00:00
|
|
|
counts: [],
|
2020-06-21 20:12:56 +00:00
|
|
|
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: [
|
|
|
|
{
|
|
|
|
wildcard: null,
|
|
|
|
termList: ['打', '打つ', '打ち込む']
|
|
|
|
},
|
|
|
|
{
|
|
|
|
wildcard: null,
|
|
|
|
termList: ['だ', 'ダース', 'うつ', 'ぶつ', 'うちこむ', 'ぶちこむ']
|
|
|
|
},
|
|
|
|
{
|
|
|
|
wildcard: 'suffix',
|
|
|
|
termList: ['打']
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2021-05-18 23:50:11 +00:00
|
|
|
total: 10,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [
|
2020-02-19 03:19:55 +00:00
|
|
|
['打', 2],
|
2021-05-18 23:50:11 +00:00
|
|
|
['打つ', 4],
|
|
|
|
['打ち込む', 4]
|
2020-02-19 03:19:55 +00:00
|
|
|
],
|
|
|
|
readings: [
|
|
|
|
['だ', 1],
|
|
|
|
['ダース', 1],
|
2021-05-18 23:50:11 +00:00
|
|
|
['うつ', 2],
|
2020-02-19 03:19:55 +00:00
|
|
|
['ぶつ', 2],
|
2021-05-18 23:50:11 +00:00
|
|
|
['うちこむ', 2],
|
|
|
|
['ぶちこむ', 2]
|
2020-02-19 03:19:55 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
wildcard: null,
|
|
|
|
termList: ['込む']
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
|
|
|
total: 0,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [],
|
2020-02-19 03:19:55 +00:00
|
|
|
readings: []
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
wildcard: 'prefix',
|
|
|
|
termList: ['込む']
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2021-05-18 23:50:11 +00:00
|
|
|
total: 4,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [
|
2021-05-18 23:50:11 +00:00
|
|
|
['打ち込む', 4]
|
2020-02-19 03:19:55 +00:00
|
|
|
],
|
|
|
|
readings: [
|
2021-05-18 23:50:11 +00:00
|
|
|
['うちこむ', 2],
|
|
|
|
['ぶちこむ', 2]
|
2020-02-19 03:19:55 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
wildcard: null,
|
|
|
|
termList: []
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
|
|
|
total: 0,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [],
|
2020-02-19 03:19:55 +00:00
|
|
|
readings: []
|
|
|
|
}
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
for (const {inputs, expectedResults} of data) {
|
|
|
|
for (const {termList, wildcard} of inputs) {
|
|
|
|
const results = await database.findTermsBulk(termList, titles, wildcard);
|
|
|
|
assert.strictEqual(results.length, expectedResults.total);
|
2021-04-04 20:22:35 +00:00
|
|
|
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) {
|
2021-04-04 20:22:35 +00:00
|
|
|
assert.strictEqual(countDictionaryDatabaseEntriesWithReading(results, reading), count);
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function testTindTermsExactBulk1(database, titles) {
|
|
|
|
const data = [
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
2021-03-15 02:51:20 +00:00
|
|
|
termList: [
|
2021-04-04 20:22:35 +00:00
|
|
|
{term: '打', reading: 'だ'},
|
|
|
|
{term: '打つ', reading: 'うつ'},
|
|
|
|
{term: '打ち込む', reading: 'うちこむ'}
|
2021-03-15 02:51:20 +00:00
|
|
|
]
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2021-05-18 23:50:11 +00:00
|
|
|
total: 5,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [
|
2020-02-19 03:19:55 +00:00
|
|
|
['打', 1],
|
2021-05-18 23:50:11 +00:00
|
|
|
['打つ', 2],
|
|
|
|
['打ち込む', 2]
|
2020-02-19 03:19:55 +00:00
|
|
|
],
|
|
|
|
readings: [
|
|
|
|
['だ', 1],
|
2021-05-18 23:50:11 +00:00
|
|
|
['うつ', 2],
|
|
|
|
['うちこむ', 2]
|
2020-02-19 03:19:55 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
2021-03-15 02:51:20 +00:00
|
|
|
termList: [
|
2021-04-04 20:22:35 +00:00
|
|
|
{term: '打', reading: 'だ?'},
|
|
|
|
{term: '打つ', reading: 'うつ?'},
|
|
|
|
{term: '打ち込む', reading: 'うちこむ?'}
|
2021-03-15 02:51:20 +00:00
|
|
|
]
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
|
|
|
total: 0,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [],
|
2020-02-19 03:19:55 +00:00
|
|
|
readings: []
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
2021-03-15 02:51:20 +00:00
|
|
|
termList: [
|
2021-04-04 20:22:35 +00:00
|
|
|
{term: '打つ', reading: 'うつ'},
|
|
|
|
{term: '打つ', reading: 'ぶつ'}
|
2021-03-15 02:51:20 +00:00
|
|
|
]
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2021-05-18 23:50:11 +00:00
|
|
|
total: 4,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [
|
2021-05-18 23:50:11 +00:00
|
|
|
['打つ', 4]
|
2020-02-19 03:19:55 +00:00
|
|
|
],
|
|
|
|
readings: [
|
2021-05-18 23:50:11 +00:00
|
|
|
['うつ', 2],
|
2020-02-19 03:19:55 +00:00
|
|
|
['ぶつ', 2]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
2021-03-15 02:51:20 +00:00
|
|
|
termList: [
|
2021-04-04 20:22:35 +00:00
|
|
|
{term: '打つ', reading: 'うちこむ'}
|
2021-03-15 02:51:20 +00:00
|
|
|
]
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
|
|
|
total: 0,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [],
|
2020-02-19 03:19:55 +00:00
|
|
|
readings: []
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
2021-03-15 02:51:20 +00:00
|
|
|
termList: []
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
|
|
|
total: 0,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [],
|
2020-02-19 03:19:55 +00:00
|
|
|
readings: []
|
|
|
|
}
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
for (const {inputs, expectedResults} of data) {
|
2021-03-15 02:51:20 +00:00
|
|
|
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);
|
2021-04-04 20:22:35 +00:00
|
|
|
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) {
|
2021-04-04 20:22:35 +00:00
|
|
|
assert.strictEqual(countDictionaryDatabaseEntriesWithReading(results, reading), count);
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function testFindTermsBySequenceBulk1(database, mainDictionary) {
|
|
|
|
const data = [
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
2020-12-09 01:27:36 +00:00
|
|
|
sequenceList: [1, 2, 3, 4, 5]
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2021-05-18 23:50:11 +00:00
|
|
|
total: 11,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [
|
2020-02-19 03:19:55 +00:00
|
|
|
['打', 2],
|
2021-05-18 23:50:11 +00:00
|
|
|
['打つ', 4],
|
|
|
|
['打ち込む', 4],
|
2020-12-09 01:27:36 +00:00
|
|
|
['画像', 1]
|
2020-02-19 03:19:55 +00:00
|
|
|
],
|
|
|
|
readings: [
|
|
|
|
['だ', 1],
|
|
|
|
['ダース', 1],
|
2021-05-18 23:50:11 +00:00
|
|
|
['うつ', 2],
|
2020-02-19 03:19:55 +00:00
|
|
|
['ぶつ', 2],
|
2021-05-18 23:50:11 +00:00
|
|
|
['うちこむ', 2],
|
|
|
|
['ぶちこむ', 2],
|
2020-12-09 01:27:36 +00:00
|
|
|
['がぞう', 1]
|
2020-02-19 03:19:55 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
sequenceList: [1]
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
|
|
|
total: 1,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [
|
2020-02-19 03:19:55 +00:00
|
|
|
['打', 1]
|
|
|
|
],
|
|
|
|
readings: [
|
|
|
|
['だ', 1]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
sequenceList: [2]
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
|
|
|
total: 1,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [
|
2020-02-19 03:19:55 +00:00
|
|
|
['打', 1]
|
|
|
|
],
|
|
|
|
readings: [
|
|
|
|
['ダース', 1]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
sequenceList: [3]
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2021-05-18 23:50:11 +00:00
|
|
|
total: 4,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [
|
2021-05-18 23:50:11 +00:00
|
|
|
['打つ', 4]
|
2020-02-19 03:19:55 +00:00
|
|
|
],
|
|
|
|
readings: [
|
2021-05-18 23:50:11 +00:00
|
|
|
['うつ', 2],
|
2020-12-09 01:27:36 +00:00
|
|
|
['ぶつ', 2]
|
2020-02-19 03:19:55 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
sequenceList: [4]
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2021-05-18 23:50:11 +00:00
|
|
|
total: 4,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [
|
2021-05-18 23:50:11 +00:00
|
|
|
['打ち込む', 4]
|
2020-02-19 03:19:55 +00:00
|
|
|
],
|
|
|
|
readings: [
|
2021-05-18 23:50:11 +00:00
|
|
|
['うちこむ', 2],
|
|
|
|
['ぶちこむ', 2]
|
2020-02-19 03:19:55 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
sequenceList: [5]
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2020-12-09 01:27:36 +00:00
|
|
|
total: 1,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [
|
2020-12-09 01:27:36 +00:00
|
|
|
['画像', 1]
|
2020-02-19 03:19:55 +00:00
|
|
|
],
|
|
|
|
readings: [
|
2020-12-09 01:27:36 +00:00
|
|
|
['がぞう', 1]
|
2020-02-19 03:19:55 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
sequenceList: [-1]
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
|
|
|
total: 0,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [],
|
2020-02-19 03:19:55 +00:00
|
|
|
readings: []
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
sequenceList: []
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
|
|
|
total: 0,
|
2021-04-04 20:22:35 +00:00
|
|
|
terms: [],
|
2020-02-19 03:19:55 +00:00
|
|
|
readings: []
|
|
|
|
}
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
for (const {inputs, expectedResults} of data) {
|
|
|
|
for (const {sequenceList} of inputs) {
|
2021-03-15 02:51:20 +00:00
|
|
|
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);
|
2021-04-04 20:22:35 +00:00
|
|
|
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) {
|
2021-04-04 20:22:35 +00:00
|
|
|
assert.strictEqual(countDictionaryDatabaseEntriesWithReading(results, reading), count);
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function testFindTermMetaBulk1(database, titles) {
|
|
|
|
const data = [
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
termList: ['打']
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2020-04-12 03:20:36 +00:00
|
|
|
total: 3,
|
2020-02-19 03:19:55 +00:00
|
|
|
modes: [
|
2020-04-12 03:20:36 +00:00
|
|
|
['freq', 3]
|
2020-02-19 03:19:55 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
termList: ['打つ']
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2020-04-12 03:20:36 +00:00
|
|
|
total: 3,
|
2020-02-19 03:19:55 +00:00
|
|
|
modes: [
|
2020-04-12 03:20:36 +00:00
|
|
|
['freq', 3]
|
2020-02-19 03:19:55 +00:00
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
termList: ['打ち込む']
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2020-04-12 03:20:36 +00:00
|
|
|
total: 5,
|
2020-02-19 03:19:55 +00:00
|
|
|
modes: [
|
2020-04-12 03:20:36 +00:00
|
|
|
['freq', 3],
|
2020-02-23 19:03:37 +00:00
|
|
|
['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: 1,
|
|
|
|
modes: [
|
|
|
|
['freq', 1]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
|
|
|
kanjiList: ['込']
|
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
|
|
|
total: 1,
|
|
|
|
modes: [
|
|
|
|
['freq', 1]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
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: [
|
|
|
|
{
|
2021-05-18 23:50:11 +00:00
|
|
|
name: 'E1'
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2021-05-18 23:50:11 +00:00
|
|
|
value: {category: 'default', dictionary: title, name: 'E1', notes: 'example tag 1', order: 0, score: 0}
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
inputs: [
|
|
|
|
{
|
2021-05-18 23:50:11 +00:00
|
|
|
name: 'K1'
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
],
|
|
|
|
expectedResults: {
|
2021-05-18 23:50:11 +00:00
|
|
|
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: {
|
2021-05-18 23:50:11 +00:00
|
|
|
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);
|
2020-03-03 03:20:47 +00:00
|
|
|
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
|
2020-08-10 01:00:37 +00:00
|
|
|
const testDictionary = createTestDictionaryArchive('valid-dictionary1');
|
2020-02-20 01:00:44 +00:00
|
|
|
const testDictionarySource = await testDictionary.generateAsync({type: 'string'});
|
|
|
|
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
|
2020-03-31 00:51:20 +00:00
|
|
|
const dictionaryImporter = new DictionaryImporter();
|
2020-06-28 21:24:06 +00:00
|
|
|
const dictionaryDatabase = new DictionaryDatabase();
|
2020-02-20 01:00:44 +00:00
|
|
|
|
|
|
|
// Error: not prepared
|
2020-06-28 21:24:06 +00:00
|
|
|
await assert.rejects(async () => await dictionaryDatabase.deleteDictionary(title, {rate: 1000}, () => {}));
|
|
|
|
await assert.rejects(async () => await dictionaryDatabase.findTermsBulk(['?'], titles, null));
|
2021-04-04 20:22:35 +00:00
|
|
|
await assert.rejects(async () => await dictionaryDatabase.findTermsExactBulk([{term: '?', reading: '?'}], titles));
|
2021-03-15 02:51:20 +00:00
|
|
|
await assert.rejects(async () => await dictionaryDatabase.findTermsBySequenceBulk([{query: 1, dictionary: title}]));
|
2020-06-28 21:24:06 +00:00
|
|
|
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));
|
2020-07-20 02:05:37 +00:00
|
|
|
await assert.rejects(async () => await dictionaryImporter.importDictionary(dictionaryDatabase, testDictionarySource, {}, () => {}));
|
2020-06-28 21:24:06 +00:00
|
|
|
|
|
|
|
await dictionaryDatabase.prepare();
|
2020-02-20 01:00:44 +00:00
|
|
|
|
|
|
|
// Error: already prepared
|
2020-06-28 21:24:06 +00:00
|
|
|
await assert.rejects(async () => await dictionaryDatabase.prepare());
|
2020-02-20 01:00:44 +00:00
|
|
|
|
2020-07-20 02:05:37 +00:00
|
|
|
await dictionaryImporter.importDictionary(dictionaryDatabase, testDictionarySource, {}, () => {});
|
2020-02-20 01:00:44 +00:00
|
|
|
|
|
|
|
// Error: dictionary already imported
|
2020-07-20 02:05:37 +00:00
|
|
|
await assert.rejects(async () => await dictionaryImporter.importDictionary(dictionaryDatabase, testDictionarySource, {}, () => {}));
|
2020-02-20 01:00:44 +00:00
|
|
|
|
2020-06-28 21:24:06 +00:00
|
|
|
await dictionaryDatabase.close();
|
2020-02-20 01:00:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-22 18:38:03 +00:00
|
|
|
async function testDatabase3() {
|
|
|
|
const invalidDictionaries = [
|
|
|
|
'invalid-dictionary1',
|
|
|
|
'invalid-dictionary2',
|
|
|
|
'invalid-dictionary3',
|
|
|
|
'invalid-dictionary4',
|
|
|
|
'invalid-dictionary5',
|
|
|
|
'invalid-dictionary6'
|
|
|
|
];
|
|
|
|
|
|
|
|
// Setup database
|
2020-03-31 00:51:20 +00:00
|
|
|
const dictionaryImporter = new DictionaryImporter();
|
2020-06-28 21:24:06 +00:00
|
|
|
const dictionaryDatabase = new DictionaryDatabase();
|
|
|
|
await dictionaryDatabase.prepare();
|
2020-02-22 18:38:03 +00:00
|
|
|
|
|
|
|
for (const invalidDictionary of invalidDictionaries) {
|
2020-08-10 01:00:37 +00:00
|
|
|
const testDictionary = createTestDictionaryArchive(invalidDictionary);
|
2020-02-22 18:38:03 +00:00
|
|
|
const testDictionarySource = await testDictionary.generateAsync({type: 'string'});
|
|
|
|
|
|
|
|
let error = null;
|
|
|
|
try {
|
2020-07-20 02:05:37 +00:00
|
|
|
await dictionaryImporter.importDictionary(dictionaryDatabase, testDictionarySource, {}, () => {});
|
2020-02-22 18:38:03 +00:00
|
|
|
} 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}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-28 21:24:06 +00:00
|
|
|
await dictionaryDatabase.close();
|
2020-02-22 18:38:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-19 03:19:55 +00:00
|
|
|
async function main() {
|
2020-02-22 18:09:18 +00:00
|
|
|
const clearTimeout = 5000;
|
|
|
|
try {
|
|
|
|
await testDatabase1();
|
|
|
|
await clearDatabase(clearTimeout);
|
|
|
|
|
|
|
|
await testDatabase2();
|
|
|
|
await clearDatabase(clearTimeout);
|
2020-02-22 18:38:03 +00:00
|
|
|
|
|
|
|
await testDatabase3();
|
|
|
|
await clearDatabase(clearTimeout);
|
2020-02-22 18:09:18 +00:00
|
|
|
} catch (e) {
|
|
|
|
console.log(e);
|
|
|
|
process.exit(-1);
|
|
|
|
throw e;
|
|
|
|
}
|
2020-02-19 03:19:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-07 16:34:14 +00:00
|
|
|
if (require.main === module) { testMain(main); }
|