1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Tools: Added a few tools to make testing server easier

This commit is contained in:
Laurent Cozic 2021-10-10 16:37:26 +01:00
parent 0eb79ba932
commit c2e61f548f
3 changed files with 40 additions and 15 deletions

View File

@ -1,5 +1,5 @@
import { knex, Knex } from 'knex'; import { knex, Knex } from 'knex';
import { DatabaseConfig } from './utils/types'; import { DatabaseConfig, DatabaseConfigClient } from './utils/types';
import * as pathUtils from 'path'; import * as pathUtils from 'path';
import time from '@joplin/lib/time'; import time from '@joplin/lib/time';
import Logger from '@joplin/lib/Logger'; import Logger from '@joplin/lib/Logger';
@ -112,6 +112,23 @@ export async function waitForConnection(dbConfig: DatabaseConfig): Promise<Conne
} }
} }
export const clientType = (db: DbConnection): DatabaseConfigClient => {
return db.client.config.client;
};
export const isPostgres = (db: DbConnection) => {
return clientType(db) === DatabaseConfigClient.PostgreSQL;
};
export const isSqlite = (db: DbConnection) => {
return clientType(db) === DatabaseConfigClient.SQLite;
};
export const setCollateC = async (db: DbConnection, tableName: string, columnName: string): Promise<void> => {
if (!isPostgres(db)) return;
await db.raw(`ALTER TABLE ${tableName} ALTER COLUMN ${columnName} SET DATA TYPE character varying(32) COLLATE "C"`);
};
function makeSlowQueryHandler(duration: number, connection: any, sql: string, bindings: any[]) { function makeSlowQueryHandler(duration: number, connection: any, sql: string, bindings: any[]) {
return setTimeout(() => { return setTimeout(() => {
try { try {

View File

@ -1,15 +1,9 @@
import { createUserAndSession, beforeAllDb, afterAllTests, beforeEachDb, models, expectThrow, createFolder, createItemTree3, expectNotThrow } from '../utils/testing/testUtils'; import { createUserAndSession, beforeAllDb, afterAllTests, beforeEachDb, models, expectThrow, createFolder, createItemTree3, expectNotThrow } from '../utils/testing/testUtils';
import { ChangeType, Item, Uuid } from '../services/database/types'; import { ChangeType } from '../services/database/types';
import { msleep } from '../utils/time'; import { msleep } from '../utils/time';
import { ChangePagination } from './ChangeModel'; import { ChangePagination } from './ChangeModel';
import { SqliteMaxVariableNum } from '../db'; import { SqliteMaxVariableNum } from '../db';
async function makeTestItem(userId: Uuid, num: number): Promise<Item> {
return models().item().saveForUser(userId, {
name: `${num.toString().padStart(32, '0')}.md`,
});
}
describe('ChangeModel', function() { describe('ChangeModel', function() {
beforeAll(async () => { beforeAll(async () => {
@ -43,14 +37,14 @@ describe('ChangeModel', function() {
const itemModel = models().item(); const itemModel = models().item();
const changeModel = models().change(); const changeModel = models().change();
await msleep(1); const item1 = await makeTestItem(user.id, 1); // [1] CREATE 1 await msleep(1); const item1 = await models().item().makeTestItem(user.id, 1); // [1] CREATE 1
await msleep(1); await itemModel.saveForUser(user.id, { id: item1.id, name: '0000000000000000000000000000001A.md' }); // [2] UPDATE 1a await msleep(1); await itemModel.saveForUser(user.id, { id: item1.id, name: '0000000000000000000000000000001A.md' }); // [2] UPDATE 1a
await msleep(1); await itemModel.saveForUser(user.id, { id: item1.id, name: '0000000000000000000000000000001B.md' }); // [3] UPDATE 1b await msleep(1); await itemModel.saveForUser(user.id, { id: item1.id, name: '0000000000000000000000000000001B.md' }); // [3] UPDATE 1b
await msleep(1); const item2 = await makeTestItem(user.id, 2); // [4] CREATE 2 await msleep(1); const item2 = await models().item().makeTestItem(user.id, 2); // [4] CREATE 2
await msleep(1); await itemModel.saveForUser(user.id, { id: item2.id, name: '0000000000000000000000000000002A.md' }); // [5] UPDATE 2a await msleep(1); await itemModel.saveForUser(user.id, { id: item2.id, name: '0000000000000000000000000000002A.md' }); // [5] UPDATE 2a
await msleep(1); await itemModel.delete(item1.id); // [6] DELETE 1 await msleep(1); await itemModel.delete(item1.id); // [6] DELETE 1
await msleep(1); await itemModel.saveForUser(user.id, { id: item2.id, name: '0000000000000000000000000000002B.md' }); // [7] UPDATE 2b await msleep(1); await itemModel.saveForUser(user.id, { id: item2.id, name: '0000000000000000000000000000002B.md' }); // [7] UPDATE 2b
await msleep(1); const item3 = await makeTestItem(user.id, 3); // [8] CREATE 3 await msleep(1); const item3 = await models().item().makeTestItem(user.id, 3); // [8] CREATE 3
// Check that the 8 changes were created // Check that the 8 changes were created
const allUncompressedChanges = await changeModel.all(); const allUncompressedChanges = await changeModel.all();
@ -125,7 +119,7 @@ describe('ChangeModel', function() {
const changeModel = models().change(); const changeModel = models().change();
let i = 1; let i = 1;
await msleep(1); const item1 = await makeTestItem(user.id, 1); // CREATE 1 await msleep(1); const item1 = await models().item().makeTestItem(user.id, 1); // CREATE 1
await msleep(1); await itemModel.saveForUser(user.id, { id: item1.id, name: `test_mod${i++}` }); // UPDATE 1 await msleep(1); await itemModel.saveForUser(user.id, { id: item1.id, name: `test_mod${i++}` }); // UPDATE 1
await expectThrow(async () => changeModel.delta(user.id, { limit: 1, cursor: 'invalid' }), 'resyncRequired'); await expectThrow(async () => changeModel.delta(user.id, { limit: 1, cursor: 'invalid' }), 'resyncRequired');
@ -173,9 +167,7 @@ describe('ChangeModel', function() {
const { user } = await createUserAndSession(1, true); const { user } = await createUserAndSession(1, true);
for (let i = 0; i < 1010; i++) { await models().item().makeTestItems(user.id, 1010);
await makeTestItem(user.id, i);
}
let changeCount = 0; let changeCount = 0;
await expectNotThrow(async () => { await expectNotThrow(async () => {

View File

@ -549,6 +549,22 @@ export default class ItemModel extends BaseModel<Item> {
} }
} }
public async makeTestItem(userId: Uuid, num: number) {
return this.saveForUser(userId, {
name: `${num.toString().padStart(32, '0')}.md`,
});
}
public async makeTestItems(userId: Uuid, count: number) {
await this.withTransaction(async () => {
for (let i = 1; i <= count; i++) {
await this.saveForUser(userId, {
name: `${i.toString().padStart(32, '0')}.md`,
});
}
}, 'ItemModel::makeTestItems');
}
public async saveForUser(userId: Uuid, item: Item, options: SaveOptions = {}): Promise<Item> { public async saveForUser(userId: Uuid, item: Item, options: SaveOptions = {}): Promise<Item> {
if (!userId) throw new Error('userId is required'); if (!userId) throw new Error('userId is required');