mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
DacFx integration tests (#6049)
* tests working * add bacpac * formatting * addressing comments * ignore bacpacs for hygiene check * add check for error message when checking for db creation * adding comments
This commit is contained in:
@@ -92,7 +92,7 @@ const indentationFilter = [
|
|||||||
'!**/*.dockerfile',
|
'!**/*.dockerfile',
|
||||||
'!extensions/markdown-language-features/media/*.js',
|
'!extensions/markdown-language-features/media/*.js',
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
'!**/*.{xlf,docx,sql,vsix}',
|
'!**/*.{xlf,docx,sql,vsix,bacpac}',
|
||||||
'!extensions/mssql/sqltoolsservice/**',
|
'!extensions/mssql/sqltoolsservice/**',
|
||||||
'!extensions/import/flatfileimportservice/**',
|
'!extensions/import/flatfileimportservice/**',
|
||||||
'!extensions/admin-tool-ext-win/ssmsmin/**',
|
'!extensions/admin-tool-ext-win/ssmsmin/**',
|
||||||
@@ -156,7 +156,8 @@ const copyrightFilter = [
|
|||||||
'!extensions/notebook/resources/jupyter_config/**',
|
'!extensions/notebook/resources/jupyter_config/**',
|
||||||
'!**/*.gif',
|
'!**/*.gif',
|
||||||
'!**/*.xlf',
|
'!**/*.xlf',
|
||||||
'!**/*.dacpac'
|
'!**/*.dacpac',
|
||||||
|
'!**/*.bacpac'
|
||||||
];
|
];
|
||||||
|
|
||||||
const eslintFilter = [
|
const eslintFilter = [
|
||||||
|
|||||||
93
extensions/integration-tests/src/dacpac.test.ts
Normal file
93
extensions/integration-tests/src/dacpac.test.ts
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import 'mocha';
|
||||||
|
import * as azdata from 'azdata';
|
||||||
|
import * as utils from './utils';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as os from 'os';
|
||||||
|
import { context } from './testContext';
|
||||||
|
import { getStandaloneServer } from './testConfig';
|
||||||
|
import assert = require('assert');
|
||||||
|
|
||||||
|
const retryCount = 24; // 2 minutes
|
||||||
|
if (context.RunTest) {
|
||||||
|
suite('Dacpac integration test suite', () => {
|
||||||
|
suiteSetup(async function () {
|
||||||
|
await utils.sleep(5000); // To ensure the providers are registered.
|
||||||
|
console.log(`Start dacpac tests`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Deploy and extract dacpac', async function () {
|
||||||
|
const server = await getStandaloneServer();
|
||||||
|
await utils.connectToServer(server);
|
||||||
|
|
||||||
|
const nodes = <azdata.objectexplorer.ObjectExplorerNode[]>await azdata.objectexplorer.getActiveConnectionNodes();
|
||||||
|
const index = nodes.findIndex(node => node.nodePath.includes(server.serverName));
|
||||||
|
const ownerUri = await azdata.connection.getUriForConnection(nodes[index].connectionId);
|
||||||
|
const now = new Date();
|
||||||
|
const databaseName = 'ADS_deployDacpac_' + now.getTime().toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const dacfxService = await azdata.dataprotocol.getProvider<azdata.DacFxServicesProvider>('MSSQL', azdata.DataProviderType.DacFxServicesProvider);
|
||||||
|
assert(dacfxService, 'DacFx Service Provider is not available');
|
||||||
|
|
||||||
|
// Deploy dacpac
|
||||||
|
const deployResult = await dacfxService.deployDacpac(path.join(__dirname, 'testData/Database1.dacpac'), databaseName, false, ownerUri, azdata.TaskExecutionMode.execute);
|
||||||
|
await utils.assertDatabaseCreationResult(databaseName, ownerUri, retryCount);
|
||||||
|
assert(deployResult.success === true && deployResult.errorMessage === '', `Deploy dacpac should succeed Expected: there should be no error. Actual Error message: "${deployResult.errorMessage}"`);
|
||||||
|
|
||||||
|
// Extract dacpac
|
||||||
|
const folderPath = path.join(os.tmpdir(), 'DacFxTest');
|
||||||
|
if (!fs.existsSync(folderPath)) {
|
||||||
|
fs.mkdirSync(folderPath);
|
||||||
|
}
|
||||||
|
const packageFilePath = path.join(folderPath, `${databaseName}.dacpac`);
|
||||||
|
const extractResult = await dacfxService.extractDacpac(databaseName, packageFilePath, databaseName, '1.0.0.0', ownerUri, azdata.TaskExecutionMode.execute);
|
||||||
|
await utils.assertFileGenerationResult(packageFilePath, retryCount);
|
||||||
|
|
||||||
|
assert(extractResult.success === true && extractResult.errorMessage === '', `Extract dacpac should succeed. Expected: there should be no error. Actual Error message: "${extractResult.errorMessage}"`);
|
||||||
|
} finally {
|
||||||
|
await utils.deleteDB(databaseName, ownerUri);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Import and export bacpac', async function () {
|
||||||
|
const server = await getStandaloneServer();
|
||||||
|
await utils.connectToServer(server);
|
||||||
|
|
||||||
|
const nodes = <azdata.objectexplorer.ObjectExplorerNode[]>await azdata.objectexplorer.getActiveConnectionNodes();
|
||||||
|
const index = nodes.findIndex(node => node.nodePath.includes(server.serverName));
|
||||||
|
const ownerUri = await azdata.connection.getUriForConnection(nodes[index].connectionId);
|
||||||
|
const now = new Date();
|
||||||
|
const databaseName = 'ADS_importBacpac_' + now.getTime().toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
let dacfxService = await azdata.dataprotocol.getProvider<azdata.DacFxServicesProvider>('MSSQL', azdata.DataProviderType.DacFxServicesProvider);
|
||||||
|
assert(dacfxService, 'DacFx Service Provider is not available');
|
||||||
|
|
||||||
|
// Import bacpac
|
||||||
|
const importResult = await dacfxService.importBacpac(path.join(__dirname, 'testData/Database1.bacpac'), databaseName, ownerUri, azdata.TaskExecutionMode.execute);
|
||||||
|
await utils.assertDatabaseCreationResult(databaseName, ownerUri, retryCount);
|
||||||
|
assert(importResult.success === true && importResult.errorMessage === '', `Expected: Import bacpac should succeed and there should be no error. Actual Error message: "${importResult.errorMessage}"`);
|
||||||
|
|
||||||
|
// Export bacpac
|
||||||
|
const folderPath = path.join(os.tmpdir(), 'DacFxTest');
|
||||||
|
if (!fs.existsSync(folderPath)) {
|
||||||
|
fs.mkdirSync(folderPath);
|
||||||
|
}
|
||||||
|
const packageFilePath = path.join(folderPath, `${databaseName}.bacpac`);
|
||||||
|
const exportResult = await dacfxService.exportBacpac(databaseName, packageFilePath, ownerUri, azdata.TaskExecutionMode.execute);
|
||||||
|
await utils.assertFileGenerationResult(packageFilePath, retryCount);
|
||||||
|
assert(exportResult.success === true && exportResult.errorMessage === '', `Expected: Export bacpac should succeed and there should be no error. Actual Error message: "${exportResult.errorMessage}"`);
|
||||||
|
} finally {
|
||||||
|
await utils.deleteDB(databaseName, ownerUri);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
BIN
extensions/integration-tests/src/testData/Database1.bacpac
Normal file
BIN
extensions/integration-tests/src/testData/Database1.bacpac
Normal file
Binary file not shown.
@@ -6,6 +6,7 @@
|
|||||||
import assert = require('assert');
|
import assert = require('assert');
|
||||||
import * as azdata from 'azdata';
|
import * as azdata from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
|
import * as fs from 'fs';
|
||||||
import { TestServerProfile } from './testConfig';
|
import { TestServerProfile } from './testConfig';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,6 +78,12 @@ export async function deleteDB(dbName: string, ownerUri: string): Promise<void>
|
|||||||
await queryProvider.runQueryAndReturn(ownerUri, query);
|
await queryProvider.runQueryAndReturn(ownerUri, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function runQuery(query: string, ownerUri: string): Promise<azdata.SimpleExecuteResult> {
|
||||||
|
let queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>('MSSQL', azdata.DataProviderType.QueryProvider);
|
||||||
|
let result = await queryProvider.runQueryAndReturn(ownerUri, query);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
export async function assertThrowsAsync(fn: () => Promise<any>, msg: string): Promise<void> {
|
export async function assertThrowsAsync(fn: () => Promise<any>, msg: string): Promise<void> {
|
||||||
let f = () => {
|
let f = () => {
|
||||||
// Empty
|
// Empty
|
||||||
@@ -89,3 +96,51 @@ export async function assertThrowsAsync(fn: () => Promise<any>, msg: string): Pr
|
|||||||
assert.throws(f, msg);
|
assert.throws(f, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param databaseName name of database to check for
|
||||||
|
* @param ownerUri owner uri
|
||||||
|
* @param retryCount number of times to retry with a 5 second wait between each try
|
||||||
|
* Checks for database getting created for operations that have async database creation
|
||||||
|
*/
|
||||||
|
export async function assertDatabaseCreationResult(databaseName: string, ownerUri: string, retryCount: number): Promise<void> {
|
||||||
|
let result: azdata.SimpleExecuteResult;
|
||||||
|
while (retryCount > 0) {
|
||||||
|
--retryCount;
|
||||||
|
await sleep(5000);
|
||||||
|
|
||||||
|
let query = `BEGIN TRY
|
||||||
|
SELECT name FROM master.dbo.sysdatabases WHERE name='${databaseName}'
|
||||||
|
END TRY
|
||||||
|
BEGIN CATCH
|
||||||
|
SELECT ERROR_MESSAGE() AS ErrorMessage;
|
||||||
|
END CATCH`;
|
||||||
|
result = await runQuery(query, ownerUri);
|
||||||
|
if (result.rowCount > 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(result.rowCount === 1, `Database ${databaseName} should be created`);
|
||||||
|
assert(result.columnInfo[0].columnName !== 'ErrorMessage', 'Checking for db creation threw error');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param filepath File path to check for
|
||||||
|
* @param retryCount number of times to retry with a 5 second wait between each try
|
||||||
|
* Checks for file getting created for async file generation and deletes file
|
||||||
|
*/
|
||||||
|
export async function assertFileGenerationResult(filepath: string, retryCount: number): Promise<void> {
|
||||||
|
let exists = false;
|
||||||
|
while (retryCount > 0 && !exists) {
|
||||||
|
--retryCount;
|
||||||
|
exists = fs.existsSync(filepath);
|
||||||
|
await sleep(5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(exists, `File ${filepath} is expected to be present`);
|
||||||
|
assert(fs.readFileSync(filepath).byteLength > 0, 'File should not be empty');
|
||||||
|
fs.unlinkSync(filepath);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user