8000 Rdbms extension exec tests by f3l1x98 · Pull Request #473 · jvalue/jayvee · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Rdbms extension exec tests #473

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,15 @@
},
{
"files": ["*.spec.ts", "*.spec.tsx", "*.spec.js", "*.spec.jsx"],
"plugins": ["jest"],
"env": {
"jest": true
},
"rules": {}
"rules": {
// you should turn the original rule off *only* for test files
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an open TODO?

"@typescript-eslint/unbound-method": "off",
"jest/unbound-method": "error"
}
}
]
}
174 changes: 174 additions & 0 deletions libs/extensions/rdbms/exec/src/lib/postgres-loader-executor.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg
//
// SPDX-License-Identifier: AGPL-3.0-only

import * as path from 'path';

import * as R from '@jvalue/jayvee-execution';
import {
constructTable,
getTestExecutionContext,
} from '@jvalue/jayvee-execution/test';
import {
BlockDefinition,
IOType,
PrimitiveValuetypes,
createJayveeServices,
} from '@jvalue/jayvee-language-server';
import {
ParseHelperOptions,
expectNoParserAndLexerErrors,
loadTestExtensions,
parseHelper,
readJvTestAssetHelper,
} from '@jvalue/jayvee-language-server/test';
import { AstNode, AstNodeLocator, LangiumDocument } from 'langium';
import { NodeFileSystem } from 'langium/node';

import { PostgresLoaderExecutor } from './postgres-loader-executor';

// eslint-disable-next-line no-var
var databaseConnectMock: jest.Mock;
// eslint-disable-next-line no-var
var databaseQueryMock: jest.Mock;
// eslint-disable-next-line no-var
var databaseEndMock: jest.Mock;
jest.mock('pg', () => {
databaseConnectMock = jest.fn();
databaseQueryMock = jest.fn();
databaseEndMock = jest.fn();
const mClient = {
connect: databaseConnectMock,
query: databaseQueryMock,
end: databaseEndMock,
};
return { Client: jest.fn(() => mClient) };
});

describe('Validation of PostgresLoaderExecutor', () => {
let parse: (
input: string,
options?: ParseHelperOptions,
) => Promise<LangiumDocument<AstNode>>;

let locator: AstNodeLocator;

const readJvTestAsset = readJvTestAssetHelper(
__dirname,
'../../test/assets/postgres-loader-executor/',
);

async function parseAndExecuteExecutor(
input: string,
IOInput: R.Table,
): Promise<R.Result<R.None>> {
const document = await parse(input, { validationChecks: 'all' });
expectNoParserAndLexerErrors(document);

const block = locator.getAstNode<BlockDefinition>(
document.parseResult.value,
'pipelines@0/blocks@1',
) as BlockDefinition;

return new PostgresLoaderExecutor().doExecute(
IOInput,
getTestExecutionContext(locator, document, [block]),
);
}

beforeAll(async () => {
// Create language services
const services = createJayveeServices(NodeFileSystem).Jayvee;
await loadTestExtensions(services, [
path.resolve(__dirname, '../../test/test-extension/TestBlockTypes.jv'),
]);
locator = services.workspace.AstNodeLocator;
// Parse function for Jayvee (without validation)
parse = parseHelper(services);
});
afterEach(() => {
jest.clearAllMocks();
});

it('should diagnose no error on valid loader config', async () => {
const text = readJvTestAsset('valid-postgres-loader.jv');

const inputTable = constructTable(
[
{
columnName: 'Column1',
column: {
values: ['value 1'],
valuetype: PrimitiveValuetypes.Text,
},
},
{
columnName: 'Column2',
column: {
values: [20.2],
valuetype: PrimitiveValuetypes.Decimal,
},
},
],
1,
);
const result = await parseAndExecuteExecutor(text, inputTable);

expect(R.isErr(result)).toEqual(false);
if (R.isOk(result)) {
expect(result.right.ioType).toEqual(IOType.NONE);
expect(databaseConnectMock).toBeCalledTimes(1);
expect(databaseQueryMock).nthCalledWith(
1,
'DROP TABLE IF EXISTS "Test";',
);
expect(databaseQueryMock).nthCalledWith(
2,
`CREATE TABLE IF NOT EXISTS "Test" ("Column1" text,"Column2" real);`,
);
expect(databaseQueryMock).nthCalledWith(
3,
`INSERT INTO "Test" ("Column1","Column2") VALUES ('value 1',20.2)`,
);
expect(databaseEndMock).toBeCalledTimes(1);
}
});

it('should diagnose error on pg client connect error', async () => {
const text = readJvTestAsset('valid-postgres-loader.jv');

const inputTable = constructTable(
[
{
columnName: 'Column1',
column: {
values: ['value 1'],
valuetype: PrimitiveValuetypes.Text,
},
},
{
columnName: 'Column2',
column: {
values: [20.2],
valuetype: PrimitiveValuetypes.Decimal,
},
},
],
1,
);
databaseConnectMock.mockImplementation(() => {
throw new Error('Connection error');
});
const result = await parseAndExecuteExecutor(text, inputTable);

expect(R.isOk(result)).toEqual(false);
if (R.isErr(result)) {
expect(result.left.message).toEqual(
'Could not write to postgres database: Connection error',
8000 );
expect(databaseConnectMock).toBeCalledTimes(1);
expect(databaseQueryMock).toBeCalledTimes(0);
expect(databaseEndMock).toBeCalledTimes(1);
}
});
});
200 changes: 200 additions & 0 deletions libs/extensions/rdbms/exec/src/lib/sqlite-loader-executor.spec.ts
9E81
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg
//
// SPDX-License-Identifier: AGPL-3.0-only

import * as path from 'path';

import * as R from '@jvalue/jayvee-execution';
import {
constructTable,
getTestExecutionContext,
} from '@jvalue/jayvee-execution/test';
import {
BlockDefinition,
IOType,
PrimitiveValuetypes,
createJayveeServices,
} from '@jvalue/jayvee-language-server';
import {
ParseHelperOptions,
expectNoParserAndLexerErrors,
loadTestExtensions,
parseHelper,
readJvTestAssetHelper,
} from '@jvalue/jayvee-language-server/test';
import { AstNode, AstNodeLocator, LangiumDocument } from 'langium';
import { NodeFileSystem } from 'langium/node';
import * as sqlite3 from 'sqlite3';

import { SQLiteLoaderExecutor } from './sqlite-loader-executor';

type SqliteRunCallbackType = (
result: sqlite3.RunResult,
err: Error | null,
) => void;
// eslint-disable-next-line no-var
var databaseMock: jest.Mock;
// eslint-disable-next-line no-var
var databaseRunMock: jest.Mock;
// eslint-disable-next-line no-var
var databaseCloseMock: jest.Mock;
jest.mock('sqlite3', () => {
databaseMock = jest.fn();
databaseRunMock = jest.fn();
databaseCloseMock = jest.fn();
return {
Database: databaseMock,
};
});
function mockDatabaseDefault() {
const mockDB = {
close: databaseCloseMock,
run: databaseRunMock,
};
databaseMock.mockImplementation(() => {
return mockDB;
});
}

describe('Validation of SQLiteLoaderExecutor', () => {
let parse: (
input: string,
options?: ParseHelperOptions,
) => Promise<LangiumDocument<AstNode>>;

let locator: AstNodeLocator;

const readJvTestAsset = readJvTestAssetHelper(
__dirname,
'../../test/assets/sqlite-loader-executor/',
);

async function parseAndExecuteExecutor(
input: string,
IOInput: R.Table,
): Promise<R.Result<R.None>> {
const document = await parse(input, { validationChecks: 'all' });
expectNoParserAndLexerErrors(document);

const block = locator.getAstNode<BlockDefinition>(
document.parseResult.value,
'pipelines@0/blocks@1',
) as BlockDefinition;

return new SQLiteLoaderExecutor().doExecute(
IOInput,
getTestExecutionContext(locator, document, [block]),
);
}

beforeAll(async () => {
// Create language services
const services = createJayveeServices(NodeFileSystem).Jayvee;
await loadTestExtensions(services, [
path.resolve(__dirname, '../../test/test-extension/TestBlockTypes.jv'),
]);
locator = services.workspace.AstNodeLocator;
// Parse function for Jayvee (without validation)
parse = parseHelper(services);
});
afterEach(() => {
jest.clearAllMocks();
});

it('should diagnose no error on valid loader config', async () => {
mockDatabaseDefault();
databaseRunMock.mockImplementation(
(sql: string, callback: SqliteRunCallbackType) => {
callback(
{
lastID: 0,
changes: 0,
} as sqlite3.RunResult,
null,
);
return this;
},
);
const text = readJvTestAsset('valid-sqlite-loader.jv');

const inputTable = constructTable(
[
{
columnName: 'Column1',
column: {
values: ['value 1'],
valuetype: PrimitiveValuetypes.Text,
},
},
{
columnName: 'Column2',
column: {
values: [20.2],
valuetype: PrimitiveValuetypes.Decimal,
},
},
],
1,
);
const result = await parseAndExecuteExecutor(text, inputTable);

expect(R.isErr(result)).toEqual(false);
if (R.isOk(result)) {
expect(result.right.ioType).toEqual(IOType.NONE);
expect(databaseRunMock).toBeCalledTimes(3);
expect(databaseRunMock).nthCalledWith(
1,
'DROP TABLE IF EXISTS "Test";',
expect.any(Function),
);
expect(databaseRunMock).nthCalledWith(
2,
`CREATE TABLE IF NOT EXISTS "Test" ("Column1" text,"Column2" real);`,
expect.any(Function),
);
expect(databaseRunMock).nthCalledWith(
3,
`INSERT INTO "Test" ("Column1","Column2") VALUES ('value 1',20.2)`,
expect.any(Function),
);
expect(databaseCloseMock).toBeCalledTimes(1);
}
});

it('should diagnose error on sqlite database open error', async () => {
databaseMock.mockImplementation(() => {
throw new Error('File not found');
});
const text = readJvTestAsset('valid-sqlite-loader.jv');

const inputTable = constructTable(
[
{
columnName: 'Column1',
column: {
values: ['value 1'],
valuetype: PrimitiveValuetypes.Text,
},
},
{
columnName: 'Column2',
column: {
values: [20.2],
valuetype: PrimitiveValuetypes.Decimal,
},
},
],
1,
);
const result = await parseAndExecuteExecutor(text, inputTable);

expect(R.isOk(result)).toEqual(false);
if (R.isErr(result)) {
expect(result.left.message).toEqual(
'Could not write to sqlite database: File not found',
);
expect(databaseRunMock).toBeCalledTimes(0);
expect(databaseCloseMock).toBeCalledTimes(0);
}
});
});
Loading
0