Remove checks for integration testing (#9856)

* remove checks for testing

* fix schema compare tests

* move some files

* fix file location

* fixc another file path
This commit is contained in:
Anthony Dresser
2020-04-07 14:50:20 -07:00
committed by GitHub
parent d580c13be1
commit f056086662
13 changed files with 378 additions and 551 deletions

View File

@@ -7,11 +7,10 @@ import 'mocha';
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import * as mssql from '../../../mssql';
import * as utils from '../utils';
import * as uuid from '../uuid';
import { isTestSetupCompleted } from '../testContext';
import * as utils from './utils';
import * as uuid from './uuid';
import assert = require('assert');
import { getStandaloneServer, TestServerProfile } from '../testConfig';
import { getStandaloneServer, TestServerProfile } from './testConfig';
let cmsService: mssql.ICmsService;
let server: TestServerProfile;
@@ -23,143 +22,141 @@ const TEST_CMS_GROUP = `adsTestCmsGroup_${uuid.v4().asHex()}`;
const TEST_CMS_SERVER = `adsTestCmsServer_${uuid.v4().asHex()}`;
const TEST_CMS_REG_SERVER = `adsTestCmsRegisteredServer_${uuid.v4().asHex()}`;
if (isTestSetupCompleted()) {
suite('CMS integration test suite', () => {
suite('CMS integration test suite', () => {
setup(async function () {
// Set up CMS provider
if (!cmsService) {
cmsService = ((await vscode.extensions.getExtension(mssql.extension.name).activate() as mssql.IExtension)).cmsService;
assert(cmsService !== undefined);
}
setup(async function () {
// Set up CMS provider
if (!cmsService) {
cmsService = ((await vscode.extensions.getExtension(mssql.extension.name).activate() as mssql.IExtension)).cmsService;
assert(cmsService !== undefined);
}
// Set up connection
if (!server) {
server = await getStandaloneServer();
connectionId = await utils.connectToServer(server, SERVER_CONNECTION_TIMEOUT);
ownerUri = await azdata.connection.getConnectionString(connectionId, true);
console.log('Start CMS tests');
}
if (!ownerUri) {
ownerUri = await azdata.connection.getConnectionString(connectionId, true);
}
});
test('Create CMS Server', async function () {
// Should fail
await utils.assertThrowsAsync(
async () => await cmsService.createCmsServer(undefined, 'test_description', undefined, ownerUri),
'Cannot add a CMS server without a name or connection');
let connection = {
serverName: server.serverName,
userName: server.userName,
password: server.password,
authenticationType: server.authenticationTypeName,
database: server.database,
provider: server.provider,
version: server.version,
engineType: server.engineType,
options: {}
};
// Should create a CMS Server without an error
await cmsService.createCmsServer(TEST_CMS_NAME, 'test_description', connection, ownerUri);
});
test('Add and delete registered group to/from CMS server', async function () {
await utils.assertThrowsAsync(
async () => await cmsService.addServerGroup(ownerUri, '', undefined, 'test_description'),
'Cannot add a server group without a name');
// Should create a server group
let result = await cmsService.addServerGroup(ownerUri, '', TEST_CMS_GROUP, 'test_description');
assert(result === true, `Server group ${TEST_CMS_GROUP} was not added to CMS server successfully`);
let existingRegisteredServerGroupCount = (await cmsService.getRegisteredServers(ownerUri, '')).registeredServerGroups.length;
// Shouldn't be able to create a new server group with same name
await utils.assertThrowsAsync(
async () => await cmsService.addServerGroup(ownerUri, '', TEST_CMS_GROUP, 'test_description'),
'Cannot add a server group with existing name');
let cmsResources = await cmsService.getRegisteredServers(ownerUri, '');
assert(cmsResources.registeredServerGroups.length === existingRegisteredServerGroupCount,
`Unexpected number of Registered Server Groups after attempting to add group that already exists. Groups : [${cmsResources.registeredServerGroups.map(g => g.name).join(', ')}]`);
// Should remove the server group we added above
let deleteResult = await cmsService.removeServerGroup(ownerUri, '', TEST_CMS_GROUP);
assert(deleteResult === true, `Server group ${TEST_CMS_GROUP} was not removed successfully`);
cmsResources = await cmsService.getRegisteredServers(ownerUri, '');
assert(cmsResources.registeredServerGroups.find(g => g.name === TEST_CMS_GROUP) === undefined,
`The server group ${TEST_CMS_GROUP} was not removed successfully. Groups : [${cmsResources.registeredServerGroups.map(g => g.name).join(', ')}]`);
});
test('Add and delete registered server to/from CMS server', async function () {
await utils.assertThrowsAsync(
async () => cmsService.addRegisteredServer(ownerUri, '', undefined, 'test_description', undefined),
'Cannot add a registered without a name or connection');
let server = await getStandaloneServer('2019');
let connection = {
serverName: server.serverName,
userName: server.userName,
password: server.password,
authenticationType: server.authenticationTypeName,
database: server.database,
provider: server.provider,
version: server.version,
engineType: server.engineType,
options: {}
};
// Should create a registered server
let result = await cmsService.addRegisteredServer(ownerUri, '', TEST_CMS_SERVER, 'test_description', connection);
assert(result === true, `Registered server ${TEST_CMS_SERVER} was not added to CMS server successfully`);
// Shouldn't be able to create a new registered server with same name
await utils.assertThrowsAsync(
async () => await cmsService.addRegisteredServer(ownerUri, '', TEST_CMS_SERVER, 'test_description', connection),
'Cannot add a registered server with existing name');
// Should remove the registered server we added above
let deleteResult = await cmsService.removeRegisteredServer(ownerUri, '', TEST_CMS_SERVER);
assert(deleteResult === true, `Registered server ${TEST_CMS_SERVER} was not removed correctly`);
});
test('Add and delete registered server to/from server group', async function () {
// Should create a server group
let result = await cmsService.addServerGroup(ownerUri, '', TEST_CMS_GROUP, 'test_description');
assert(result === true, `Server group ${TEST_CMS_GROUP} was not created successfully`);
// Make sure server group is created
let cmsResources = await cmsService.getRegisteredServers(ownerUri, '');
assert(cmsResources.registeredServerGroups.find(g => g.name === TEST_CMS_GROUP),
`Registered Server Group ${TEST_CMS_GROUP} was not found after being added. Groups : [${cmsResources.registeredServerGroups.map(g => g.name).join(', ')}]`);
// Should create a registered server under the group
let server = await getStandaloneServer('2019');
let connection = {
serverName: server.serverName,
userName: server.userName,
password: server.password,
authenticationType: server.authenticationTypeName,
database: server.database,
provider: server.provider,
version: server.version,
engineType: server.engineType,
options: {}
};
let relativePath = cmsResources.registeredServerGroups[0].relativePath;
result = await cmsService.addRegisteredServer(ownerUri, relativePath, TEST_CMS_REG_SERVER, 'test_description', connection);
assert(result === true, `Registered server ${TEST_CMS_REG_SERVER} was not added to server group successfully`);
// Should remove the server group we added above
let deleteResult = await cmsService.removeServerGroup(ownerUri, '', TEST_CMS_GROUP);
assert(deleteResult === true, `Server group ${TEST_CMS_GROUP} was not deleted from CMS server successfully`);
});
// Set up connection
if (!server) {
server = await getStandaloneServer();
connectionId = await utils.connectToServer(server, SERVER_CONNECTION_TIMEOUT);
ownerUri = await azdata.connection.getConnectionString(connectionId, true);
console.log('Start CMS tests');
}
if (!ownerUri) {
ownerUri = await azdata.connection.getConnectionString(connectionId, true);
}
});
}
test('Create CMS Server', async function () {
// Should fail
await utils.assertThrowsAsync(
async () => await cmsService.createCmsServer(undefined, 'test_description', undefined, ownerUri),
'Cannot add a CMS server without a name or connection');
let connection = {
serverName: server.serverName,
userName: server.userName,
password: server.password,
authenticationType: server.authenticationTypeName,
database: server.database,
provider: server.provider,
version: server.version,
engineType: server.engineType,
options: {}
};
// Should create a CMS Server without an error
await cmsService.createCmsServer(TEST_CMS_NAME, 'test_description', connection, ownerUri);
});
test('Add and delete registered group to/from CMS server', async function () {
await utils.assertThrowsAsync(
async () => await cmsService.addServerGroup(ownerUri, '', undefined, 'test_description'),
'Cannot add a server group without a name');
// Should create a server group
let result = await cmsService.addServerGroup(ownerUri, '', TEST_CMS_GROUP, 'test_description');
assert(result === true, `Server group ${TEST_CMS_GROUP} was not added to CMS server successfully`);
let existingRegisteredServerGroupCount = (await cmsService.getRegisteredServers(ownerUri, '')).registeredServerGroups.length;
// Shouldn't be able to create a new server group with same name
await utils.assertThrowsAsync(
async () => await cmsService.addServerGroup(ownerUri, '', TEST_CMS_GROUP, 'test_description'),
'Cannot add a server group with existing name');
let cmsResources = await cmsService.getRegisteredServers(ownerUri, '');
assert(cmsResources.registeredServerGroups.length === existingRegisteredServerGroupCount,
`Unexpected number of Registered Server Groups after attempting to add group that already exists. Groups : [${cmsResources.registeredServerGroups.map(g => g.name).join(', ')}]`);
// Should remove the server group we added above
let deleteResult = await cmsService.removeServerGroup(ownerUri, '', TEST_CMS_GROUP);
assert(deleteResult === true, `Server group ${TEST_CMS_GROUP} was not removed successfully`);
cmsResources = await cmsService.getRegisteredServers(ownerUri, '');
assert(cmsResources.registeredServerGroups.find(g => g.name === TEST_CMS_GROUP) === undefined,
`The server group ${TEST_CMS_GROUP} was not removed successfully. Groups : [${cmsResources.registeredServerGroups.map(g => g.name).join(', ')}]`);
});
test('Add and delete registered server to/from CMS server', async function () {
await utils.assertThrowsAsync(
async () => cmsService.addRegisteredServer(ownerUri, '', undefined, 'test_description', undefined),
'Cannot add a registered without a name or connection');
let server = await getStandaloneServer('2019');
let connection = {
serverName: server.serverName,
userName: server.userName,
password: server.password,
authenticationType: server.authenticationTypeName,
database: server.database,
provider: server.provider,
version: server.version,
engineType: server.engineType,
options: {}
};
// Should create a registered server
let result = await cmsService.addRegisteredServer(ownerUri, '', TEST_CMS_SERVER, 'test_description', connection);
assert(result === true, `Registered server ${TEST_CMS_SERVER} was not added to CMS server successfully`);
// Shouldn't be able to create a new registered server with same name
await utils.assertThrowsAsync(
async () => await cmsService.addRegisteredServer(ownerUri, '', TEST_CMS_SERVER, 'test_description', connection),
'Cannot add a registered server with existing name');
// Should remove the registered server we added above
let deleteResult = await cmsService.removeRegisteredServer(ownerUri, '', TEST_CMS_SERVER);
assert(deleteResult === true, `Registered server ${TEST_CMS_SERVER} was not removed correctly`);
});
test('Add and delete registered server to/from server group', async function () {
// Should create a server group
let result = await cmsService.addServerGroup(ownerUri, '', TEST_CMS_GROUP, 'test_description');
assert(result === true, `Server group ${TEST_CMS_GROUP} was not created successfully`);
// Make sure server group is created
let cmsResources = await cmsService.getRegisteredServers(ownerUri, '');
assert(cmsResources.registeredServerGroups.find(g => g.name === TEST_CMS_GROUP),
`Registered Server Group ${TEST_CMS_GROUP} was not found after being added. Groups : [${cmsResources.registeredServerGroups.map(g => g.name).join(', ')}]`);
// Should create a registered server under the group
let server = await getStandaloneServer('2019');
let connection = {
serverName: server.serverName,
userName: server.userName,
password: server.password,
authenticationType: server.authenticationTypeName,
database: server.database,
provider: server.provider,
version: server.version,
engineType: server.engineType,
options: {}
};
let relativePath = cmsResources.registeredServerGroups[0].relativePath;
result = await cmsService.addRegisteredServer(ownerUri, relativePath, TEST_CMS_REG_SERVER, 'test_description', connection);
assert(result === true, `Registered server ${TEST_CMS_REG_SERVER} was not added to server group successfully`);
// Should remove the server group we added above
let deleteResult = await cmsService.removeServerGroup(ownerUri, '', TEST_CMS_GROUP);
assert(deleteResult === true, `Server group ${TEST_CMS_GROUP} was not deleted from CMS server successfully`);
});
});

View File

@@ -5,114 +5,111 @@
import 'mocha';
import * as azdata from 'azdata';
import * as utils from '../utils';
import * as utils from './utils';
import * as path from 'path';
import * as fs from 'fs';
import * as os from 'os';
import * as mssql from '../../../mssql';
import * as vscode from 'vscode';
import { isTestSetupCompleted } from '../testContext';
import { getStandaloneServer } from '../testConfig';
import { getStandaloneServer } from './testConfig';
import * as assert from 'assert';
import { promisify } from 'util';
const retryCount = 24; // 2 minutes
const dacpac1: string = path.join(__dirname, '../testData/Database1.dacpac');
if (isTestSetupCompleted()) {
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 vscode.extensions.getExtension(mssql.extension.name).activate() as mssql.IExtension)).dacFx;
assert(dacfxService, 'DacFx Service Provider is not available');
// Deploy dacpac
const deployResult = await dacfxService.deployDacpac(dacpac1, databaseName, false, ownerUri, azdata.TaskExecutionMode.execute);
await utils.assertDatabaseCreationResult(databaseName, ownerUri, retryCount);
const dbConnectionId = await utils.connectToServer({
serverName: server.serverName,
database: databaseName,
userName: server.userName,
password: server.password,
authenticationTypeName: server.authenticationTypeName,
providerName: server.providerName
});
const dbConnectionOwnerUri = await azdata.connection.getUriForConnection(dbConnectionId);
await utils.assertTableCreationResult('dbo', 'Table1', dbConnectionOwnerUri, retryCount);
await utils.assertTableCreationResult('dbo', 'Table2', dbConnectionOwnerUri, 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 (!(await promisify(fs.exists)(folderPath))) {
await fs.promises.mkdir(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(server, databaseName, ownerUri);
}
});
const bacpac1: string = path.join(__dirname, '..', 'testData', 'Database1.bacpac');
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 vscode.extensions.getExtension(mssql.extension.name).activate() as mssql.IExtension)).dacFx;
assert(dacfxService, 'DacFx Service Provider is not available');
// Import bacpac
const importResult = await dacfxService.importBacpac(bacpac1, databaseName, ownerUri, azdata.TaskExecutionMode.execute);
await utils.assertDatabaseCreationResult(databaseName, ownerUri, retryCount);
const dbConnectionId = await utils.connectToServer({
serverName: server.serverName,
database: databaseName,
userName: server.userName,
password: server.password,
authenticationTypeName: server.authenticationTypeName,
providerName: server.providerName
});
const dbConnectionOwnerUri = await azdata.connection.getUriForConnection(dbConnectionId);
await utils.assertTableCreationResult('dbo', 'Table1', dbConnectionOwnerUri, retryCount, true);
await utils.assertTableCreationResult('dbo', 'Table2', dbConnectionOwnerUri, retryCount, true);
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 (!(await promisify(fs.exists)(folderPath))) {
await fs.promises.mkdir(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(server, databaseName, ownerUri);
}
});
const dacpac1: string = path.join(__dirname, '../../testData/Database1.dacpac');
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 vscode.extensions.getExtension(mssql.extension.name).activate() as mssql.IExtension)).dacFx;
assert(dacfxService, 'DacFx Service Provider is not available');
// Deploy dacpac
const deployResult = await dacfxService.deployDacpac(dacpac1, databaseName, false, ownerUri, azdata.TaskExecutionMode.execute);
await utils.assertDatabaseCreationResult(databaseName, ownerUri, retryCount);
const dbConnectionId = await utils.connectToServer({
serverName: server.serverName,
database: databaseName,
userName: server.userName,
password: server.password,
authenticationTypeName: server.authenticationTypeName,
providerName: server.providerName
});
const dbConnectionOwnerUri = await azdata.connection.getUriForConnection(dbConnectionId);
await utils.assertTableCreationResult('dbo', 'Table1', dbConnectionOwnerUri, retryCount);
await utils.assertTableCreationResult('dbo', 'Table2', dbConnectionOwnerUri, 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 (!(await promisify(fs.exists)(folderPath))) {
await fs.promises.mkdir(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(server, databaseName, ownerUri);
}
});
const bacpac1: string = path.join(__dirname, '..', '..', 'testData', 'Database1.bacpac');
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 vscode.extensions.getExtension(mssql.extension.name).activate() as mssql.IExtension)).dacFx;
assert(dacfxService, 'DacFx Service Provider is not available');
// Import bacpac
const importResult = await dacfxService.importBacpac(bacpac1, databaseName, ownerUri, azdata.TaskExecutionMode.execute);
await utils.assertDatabaseCreationResult(databaseName, ownerUri, retryCount);
const dbConnectionId = await utils.connectToServer({
serverName: server.serverName,
database: databaseName,
userName: server.userName,
password: server.password,
authenticationTypeName: server.authenticationTypeName,
providerName: server.providerName
});
const dbConnectionOwnerUri = await azdata.connection.getUriForConnection(dbConnectionId);
await utils.assertTableCreationResult('dbo', 'Table1', dbConnectionOwnerUri, retryCount, true);
await utils.assertTableCreationResult('dbo', 'Table2', dbConnectionOwnerUri, retryCount, true);
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 (!(await promisify(fs.exists)(folderPath))) {
await fs.promises.mkdir(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(server, databaseName, ownerUri);
}
});
});

View File

@@ -7,102 +7,100 @@ import 'mocha';
import * as assert from 'assert';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { isTestSetupCompleted } from '../testContext';
import { sqlNotebookContent, writeNotebookToFile, sqlKernelMetadata, getFileName, pySparkNotebookContent, pySparkKernelMetadata, pythonKernelMetadata, sqlNotebookMultipleCellsContent, notebookContentForCellLanguageTest, sqlKernelSpec, pythonKernelSpec, pySparkKernelSpec, CellTypes } from '../notebook.util';
import { getConfigValue, EnvironmentVariable_PYTHON_PATH, TestServerProfile, getStandaloneServer } from '../testConfig';
import { connectToServer, sleep, testServerProfileToIConnectionProfile } from '../utils';
import { sqlNotebookContent, writeNotebookToFile, sqlKernelMetadata, getFileName, pySparkNotebookContent, pySparkKernelMetadata, pythonKernelMetadata, sqlNotebookMultipleCellsContent, notebookContentForCellLanguageTest, sqlKernelSpec, pythonKernelSpec, pySparkKernelSpec, CellTypes } from './notebook.util';
import { getConfigValue, EnvironmentVariable_PYTHON_PATH, TestServerProfile, getStandaloneServer } from './testConfig';
import { connectToServer, sleep, testServerProfileToIConnectionProfile } from './utils';
import * as fs from 'fs';
import { stressify } from 'adstest';
import { isNullOrUndefined, promisify } from 'util';
if (isTestSetupCompleted()) {
suite('Notebook integration test suite', function () {
setup(async function () {
console.log(`Start "${this.currentTest.title}"`);
let server = await getStandaloneServer();
assert(server && server.serverName, 'No server could be found');
await connectToServer(server, 6000);
});
teardown(async function () {
await (new NotebookTester()).cleanup(this.currentTest.title);
});
test('Sql NB test @UNSTABLE@', async function () {
await (new NotebookTester()).sqlNbTest(this.test.title);
});
test('Sql NB multiple cells test @UNSTABLE@', async function () {
await (new NotebookTester()).sqlNbMultipleCellsTest(this.test.title);
});
test('Sql NB run cells above and below test', async function () {
await (new NotebookTester()).sqlNbRunCellsAboveBelowTest(this.test.title);
});
test('Clear cell output - SQL notebook', async function () {
await (new NotebookTester()).sqlNbClearOutputs(this.test.title);
});
test('Clear all outputs - SQL notebook ', async function () {
await (new NotebookTester()).sqlNbClearAllOutputs(this.test.title);
});
test('sql language test', async function () {
await (new NotebookTester()).sqlLanguageTest(this.test.title);
});
// TODO: Need to make this test more reliable.
test('should not be dirty after saving notebook test @UNSTABLE@', async function () {
await (new NotebookTester().shouldNotBeDirtyAfterSavingNotebookTest(this.test.title));
});
if (process.env['RUN_PYTHON3_TEST'] === '1') {
test('Python3 notebook test', async function () {
await (new NotebookTester()).python3NbTest(this.test.title);
});
test('Clear all outputs - Python3 notebook ', async function () {
await (new NotebookTester()).python3ClearAllOutputs(this.test.title);
});
test('python language test', async function () {
await (new NotebookTester()).pythonLanguageTest(this.test.title);
});
test('Change kernel different provider SQL to Python to SQL', async function () {
await (new NotebookTester()).sqlNbChangeKernelDifferentProviderTest(this.test.title);
});
test('Change kernel different provider Python to SQL to Python', async function () {
await (new NotebookTester()).pythonChangeKernelDifferentProviderTest(this.test.title);
});
test('Change kernel same provider Python to PySpark to Python', async function () {
await (new NotebookTester()).pythonChangeKernelSameProviderTest(this.test.title);
});
}
if (process.env['RUN_PYSPARK_TEST'] === '1') {
test('PySpark notebook test', async function () {
await (new NotebookTester()).pySparkNbTest(this.test.title);
});
}
/* After https://github.com/microsoft/azuredatastudio/issues/5598 is fixed, enable these tests.
test('scala language test', async function () {
await (new NotebookTester()).scalaLanguageTest(this.test.title);
});
test('empty language test', async function () {
await (new NotebookTester()).emptyLanguageTest(this.test.title);
});
test('cplusplus language test', async function () {
await (new NotebookTester()).cplusplusLanguageTest(this.test.title);
});
*/
suite('Notebook integration test suite', function () {
setup(async function () {
console.log(`Start "${this.currentTest.title}"`);
let server = await getStandaloneServer();
assert(server && server.serverName, 'No server could be found');
await connectToServer(server, 6000);
});
}
teardown(async function () {
await (new NotebookTester()).cleanup(this.currentTest.title);
});
test('Sql NB test @UNSTABLE@', async function () {
await (new NotebookTester()).sqlNbTest(this.test.title);
});
test('Sql NB multiple cells test @UNSTABLE@', async function () {
await (new NotebookTester()).sqlNbMultipleCellsTest(this.test.title);
});
test('Sql NB run cells above and below test', async function () {
await (new NotebookTester()).sqlNbRunCellsAboveBelowTest(this.test.title);
});
test('Clear cell output - SQL notebook', async function () {
await (new NotebookTester()).sqlNbClearOutputs(this.test.title);
});
test('Clear all outputs - SQL notebook ', async function () {
await (new NotebookTester()).sqlNbClearAllOutputs(this.test.title);
});
test('sql language test', async function () {
await (new NotebookTester()).sqlLanguageTest(this.test.title);
});
// TODO: Need to make this test more reliable.
test('should not be dirty after saving notebook test @UNSTABLE@', async function () {
await (new NotebookTester().shouldNotBeDirtyAfterSavingNotebookTest(this.test.title));
});
if (process.env['RUN_PYTHON3_TEST'] === '1') {
test('Python3 notebook test', async function () {
await (new NotebookTester()).python3NbTest(this.test.title);
});
test('Clear all outputs - Python3 notebook ', async function () {
await (new NotebookTester()).python3ClearAllOutputs(this.test.title);
});
test('python language test', async function () {
await (new NotebookTester()).pythonLanguageTest(this.test.title);
});
test('Change kernel different provider SQL to Python to SQL', async function () {
await (new NotebookTester()).sqlNbChangeKernelDifferentProviderTest(this.test.title);
});
test('Change kernel different provider Python to SQL to Python', async function () {
await (new NotebookTester()).pythonChangeKernelDifferentProviderTest(this.test.title);
});
test('Change kernel same provider Python to PySpark to Python', async function () {
await (new NotebookTester()).pythonChangeKernelSameProviderTest(this.test.title);
});
}
if (process.env['RUN_PYSPARK_TEST'] === '1') {
test('PySpark notebook test', async function () {
await (new NotebookTester()).pySparkNbTest(this.test.title);
});
}
/* After https://github.com/microsoft/azuredatastudio/issues/5598 is fixed, enable these tests.
test('scala language test', async function () {
await (new NotebookTester()).scalaLanguageTest(this.test.title);
});
test('empty language test', async function () {
await (new NotebookTester()).emptyLanguageTest(this.test.title);
});
test('cplusplus language test', async function () {
await (new NotebookTester()).cplusplusLanguageTest(this.test.title);
});
*/
});
class NotebookTester {
private static ParallelCount = 1;

View File

@@ -0,0 +1,179 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'mocha';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
export class CellTypes {
public static readonly Code = 'code';
public static readonly Markdown = 'markdown';
public static readonly Raw = 'raw';
}
export const pySparkNotebookContent: azdata.nb.INotebookContents = {
cells: [{
cell_type: CellTypes.Code,
source: '1+1',
metadata: { language: 'python' },
execution_count: 1
}],
metadata: {
'kernelspec': {
'name': 'pysparkkernel',
'display_name': 'PySpark'
}
},
nbformat: 4,
nbformat_minor: 2
};
export const notebookContentForCellLanguageTest: azdata.nb.INotebookContents = {
cells: [{
cell_type: CellTypes.Code,
source: '1+1',
metadata: {},
execution_count: 1
}],
metadata: {
'kernelspec': {
'name': ''
},
},
nbformat: 4,
nbformat_minor: 2
};
export const pythonNotebookMultipleCellsContent: azdata.nb.INotebookContents = {
cells: [{
cell_type: CellTypes.Code,
source: '1+1',
metadata: { language: 'python' },
execution_count: 1
}, {
cell_type: CellTypes.Code,
source: '1+2',
metadata: { language: 'python' },
execution_count: 1
}, {
cell_type: CellTypes.Code,
source: '1+3',
metadata: { language: 'python' },
execution_count: 1
}, {
cell_type: CellTypes.Code,
source: '1+4',
metadata: { language: 'python' },
execution_count: 1
}],
metadata: {
'kernelspec': {
'name': 'python3',
'display_name': 'Python 3'
}
},
nbformat: 4,
nbformat_minor: 2
};
export const sqlNotebookContent: azdata.nb.INotebookContents = {
cells: [{
cell_type: CellTypes.Code,
source: 'select 1',
metadata: { language: 'sql' },
execution_count: 1
}],
metadata: {
'kernelspec': {
'name': 'SQL',
'display_name': 'SQL'
}
},
nbformat: 4,
nbformat_minor: 2
};
export const sqlNotebookMultipleCellsContent: azdata.nb.INotebookContents = {
cells: [{
cell_type: CellTypes.Code,
source: 'select 0',
metadata: { language: 'sql' },
execution_count: 1
}, {
cell_type: CellTypes.Code,
source: `WAITFOR DELAY '00:00:02'\nselect 1`,
metadata: { language: 'sql' },
execution_count: 1
}, {
cell_type: CellTypes.Code,
source: 'select 2',
metadata: { language: 'sql' },
execution_count: 1
}],
metadata: {
'kernelspec': {
'name': 'SQL',
'display_name': 'SQL'
}
},
nbformat: 4,
nbformat_minor: 2
};
export const pySparkKernelMetadata = {
'kernelspec': {
'name': 'pysparkkernel',
'display_name': 'PySpark'
}
};
export const pySparkKernelSpec = {
name: 'pyspark',
display_name: 'PySpark'
};
export const sqlKernelMetadata = {
'kernelspec': {
'name': 'SQL',
'display_name': 'SQL'
}
};
export const sqlKernelSpec: azdata.nb.IKernelSpec = {
name: 'SQL',
display_name: 'SQL'
};
export const pythonKernelMetadata = {
'kernelspec': {
'name': 'python3',
'display_name': 'Python 3'
}
};
export const pythonKernelSpec: azdata.nb.IKernelSpec = {
name: 'python3',
display_name: 'Python 3'
};
export function writeNotebookToFile(pythonNotebook: azdata.nb.INotebookContents, testName: string): vscode.Uri {
let fileName = getFileName(testName);
let notebookContentString = JSON.stringify(pythonNotebook);
// eslint-disable-next-line no-sync
fs.writeFileSync(fileName, notebookContentString);
console.log(`Local file is created: '${fileName}'`);
let uri = vscode.Uri.file(fileName);
return uri;
}
export function getFileName(testName: string): string {
if (testName) {
return path.join(os.tmpdir(), testName + '.ipynb');
}
return undefined;
}

View File

@@ -5,34 +5,31 @@
import 'mocha';
import * as azdata from 'azdata';
import { isTestSetupCompleted } from '../testContext';
import { getBdcServer, TestServerProfile, getAzureServer, getStandaloneServer } from '../testConfig';
import { connectToServer, createDB, deleteDB, DefaultConnectTimeoutInMs, asyncTimeout } from '../utils';
import { getBdcServer, TestServerProfile, getAzureServer, getStandaloneServer } from './testConfig';
import { connectToServer, createDB, deleteDB, DefaultConnectTimeoutInMs, asyncTimeout } from './utils';
import * as assert from 'assert';
import { stressify } from 'adstest';
if (isTestSetupCompleted()) {
suite('Object Explorer integration suite', () => {
test.skip('BDC instance node label test', async function () {
return await (new ObjectExplorerTester()).bdcNodeLabelTest();
});
test('Standalone instance node label test', async function () {
return await (new ObjectExplorerTester()).standaloneNodeLabelTest();
});
test('Azure SQL DB instance node label test @UNSTABLE@', async function () {
return await (new ObjectExplorerTester()).sqlDbNodeLabelTest();
});
test.skip('BDC instance context menu test', async function () {
return await (new ObjectExplorerTester()).bdcContextMenuTest();
});
test('Azure SQL DB context menu test @UNSTABLE@', async function () {
return await (new ObjectExplorerTester()).sqlDbContextMenuTest();
});
test('Standalone database context menu test', async function () {
return await (new ObjectExplorerTester()).standaloneContextMenuTest();
});
suite('Object Explorer integration suite', () => {
test.skip('BDC instance node label test', async function () {
return await (new ObjectExplorerTester()).bdcNodeLabelTest();
});
}
test('Standalone instance node label test', async function () {
return await (new ObjectExplorerTester()).standaloneNodeLabelTest();
});
test('Azure SQL DB instance node label test @UNSTABLE@', async function () {
return await (new ObjectExplorerTester()).sqlDbNodeLabelTest();
});
test.skip('BDC instance context menu test', async function () {
return await (new ObjectExplorerTester()).bdcContextMenuTest();
});
test('Azure SQL DB context menu test @UNSTABLE@', async function () {
return await (new ObjectExplorerTester()).sqlDbContextMenuTest();
});
test('Standalone database context menu test', async function () {
return await (new ObjectExplorerTester()).standaloneContextMenuTest();
});
});
class ObjectExplorerTester {
private static ParallelCount = 1;

View File

@@ -6,58 +6,55 @@
import 'mocha';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import * as utils from '../utils';
import * as utils from './utils';
import * as mssql from '../../../mssql';
import * as os from 'os';
import * as fs from 'fs';
const path = require('path');
import { isTestSetupCompleted } from '../testContext';
import * as assert from 'assert';
import { getStandaloneServer } from '../testConfig';
import { getStandaloneServer } from './testConfig';
import { stressify } from 'adstest';
import { promisify } from 'util';
let schemaCompareService: mssql.ISchemaCompareService;
let dacfxService: mssql.IDacFxService;
let schemaCompareTester: SchemaCompareTester;
const dacpac1: string = path.join(__dirname, '..','testData', 'Database1.dacpac');
const dacpac2: string = path.join(__dirname, '..', 'testData', 'Database2.dacpac');
const includeExcludeSourceDacpac: string = path.join(__dirname, '..', 'testData', 'SchemaCompareIncludeExcludeSource.dacpac');
const includeExcludeTargetDacpac: string = path.join(__dirname, '..', 'testData', 'SchemaCompareIncludeExcludeTarget.dacpac');
const dacpac1: string = path.join(__dirname, '..', '..', 'testData', 'Database1.dacpac');
const dacpac2: string = path.join(__dirname, '..', '..', 'testData', 'Database2.dacpac');
const includeExcludeSourceDacpac: string = path.join(__dirname, '..', '..', 'testData', 'SchemaCompareIncludeExcludeSource.dacpac');
const includeExcludeTargetDacpac: string = path.join(__dirname, '..', '..', 'testData', 'SchemaCompareIncludeExcludeTarget.dacpac');
const SERVER_CONNECTION_TIMEOUT: number = 3000;
const retryCount = 24; // 2 minutes
const folderPath = path.join(os.tmpdir(), 'SchemaCompareTest');
if (isTestSetupCompleted()) {
suite('Schema compare integration test suite', () => {
suiteSetup(async function () {
let attempts: number = 20;
while (attempts > 0) {
schemaCompareService = ((await vscode.extensions.getExtension(mssql.extension.name).activate() as mssql.IExtension)).schemaCompare;
if (schemaCompareService) {
break;
}
attempts--;
await utils.sleep(1000); // To ensure the providers are registered.
suite('Schema compare integration test suite', () => {
suiteSetup(async function () {
let attempts: number = 20;
while (attempts > 0) {
schemaCompareService = ((await vscode.extensions.getExtension(mssql.extension.name).activate() as mssql.IExtension)).schemaCompare;
if (schemaCompareService) {
break;
}
dacfxService = ((await vscode.extensions.getExtension(mssql.extension.name).activate() as mssql.IExtension)).dacFx;
schemaCompareTester = new SchemaCompareTester();
console.log(`Start schema compare tests`);
});
test('Schema compare dacpac to dacpac comparison and scmp', async function () {
await schemaCompareTester.SchemaCompareDacpacToDacpac();
});
test('Schema compare database to database comparison, script generation, and scmp', async function () {
await schemaCompareTester.SchemaCompareDatabaseToDatabase();
});
test('Schema compare dacpac to database comparison, script generation, and scmp', async function () {
await schemaCompareTester.SchemaCompareDacpacToDatabase();
});
test('Schema compare dacpac to dacpac comparison with include exclude', async function () {
await schemaCompareTester.SchemaCompareIncludeExcludeDacpacToDacpac();
});
attempts--;
await utils.sleep(1000); // To ensure the providers are registered.
}
dacfxService = ((await vscode.extensions.getExtension(mssql.extension.name).activate() as mssql.IExtension)).dacFx;
schemaCompareTester = new SchemaCompareTester();
console.log(`Start schema compare tests`);
});
}
test('Schema compare dacpac to dacpac comparison and scmp', async function () {
await schemaCompareTester.SchemaCompareDacpacToDacpac();
});
test('Schema compare database to database comparison, script generation, and scmp', async function () {
await schemaCompareTester.SchemaCompareDatabaseToDatabase();
});
test('Schema compare dacpac to database comparison, script generation, and scmp', async function () {
await schemaCompareTester.SchemaCompareDacpacToDatabase();
});
test('Schema compare dacpac to dacpac comparison with include exclude', async function () {
await schemaCompareTester.SchemaCompareIncludeExcludeDacpacToDacpac();
});
});
class SchemaCompareTester {
private static ParallelCount = 1;

View File

@@ -0,0 +1,171 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/*
TODO: Due to a runtime error, I duplicated this file at these 2 locations:
$/extensions/integration-test/src/testConfig.ts
$/test/smoke/src/sql/testConfig.ts
for now, make sure to keep both files in sync.
*/
interface ITestServerProfile {
serverName: string;
userName: string;
password: string;
authenticationType: AuthenticationType;
database: string;
provider: ConnectionProvider;
version: string;
engineType: EngineType;
}
interface INameDisplayNamePair {
name: string;
displayName: string;
}
export enum AuthenticationType {
Windows,
SqlLogin
}
export enum ConnectionProvider {
SQLServer
}
export enum EngineType {
Standalone,
Azure,
BigDataCluster
}
let connectionProviderMapping: { [key: string]: { name: string; displayName: string } } = {};
let authenticationTypeMapping: { [key: string]: { name: string; displayName: string } } = {};
connectionProviderMapping[ConnectionProvider.SQLServer] = { name: 'MSSQL', displayName: 'Microsoft SQL Server' };
authenticationTypeMapping[AuthenticationType.SqlLogin] = { name: 'SqlLogin', displayName: 'SQL Login' };
authenticationTypeMapping[AuthenticationType.Windows] = { name: 'Integrated', displayName: 'Windows Authentication' };
export function getConfigValue(name: string): string {
let configValue = process.env[name];
return configValue ? configValue.toString() : '';
}
export const EnvironmentVariable_BDC_SERVER: string = 'BDC_BACKEND_HOSTNAME';
export const EnvironmentVariable_BDC_USERNAME: string = 'BDC_BACKEND_USERNAME';
export const EnvironmentVariable_BDC_PASSWORD: string = 'BDC_BACKEND_PWD';
export const EnvironmentVariable_STANDALONE_SERVER: string = 'STANDALONE_SQL';
export const EnvironmentVariable_STANDALONE_USERNAME: string = 'STANDALONE_SQL_USERNAME';
export const EnvironmentVariable_STANDALONE_PASSWORD: string = 'STANDALONE_SQL_PWD';
export const EnvironmentVariable_AZURE_SERVER: string = 'AZURE_SQL';
export const EnvironmentVariable_AZURE_USERNAME: string = 'AZURE_SQL_USERNAME';
export const EnvironmentVariable_AZURE_PASSWORD: string = 'AZURE_SQL_PWD';
export const EnvironmentVariable_PYTHON_PATH: string = 'PYTHON_TEST_PATH';
export const EnvironmentVariable_STANDALONE_SERVER_2019: string = 'STANDALONE_SQL_2019';
export const EnvironmentVariable_STANDALONE_USERNAME_2019: string = 'STANDALONE_SQL_USERNAME_2019';
export const EnvironmentVariable_STANDALONE_PASSWORD_2019: string = 'STANDALONE_SQL_PWD_2019';
export interface TestConnectionInfo {
readonly serverName: string;
readonly database: string;
readonly userName: string;
readonly password: string;
readonly providerName: string;
readonly authenticationTypeName: string;
}
export class TestServerProfile implements TestConnectionInfo {
constructor(private _profile: ITestServerProfile) { }
public get serverName(): string { return this._profile.serverName; }
public get userName(): string { return this._profile.userName; }
public get password(): string { return this._profile.password; }
public get database(): string { return this._profile.database; }
public get version(): string { return this._profile.version; }
public get provider(): ConnectionProvider { return this._profile.provider; }
public get providerName(): string { return getEnumMappingEntry(connectionProviderMapping, this.provider).name; }
public get providerDisplayName(): string { return getEnumMappingEntry(connectionProviderMapping, this.provider).displayName; }
public get authenticationType(): AuthenticationType { return this._profile.authenticationType; }
public get authenticationTypeName(): string { return getEnumMappingEntry(authenticationTypeMapping, this.authenticationType).name; }
public get authenticationTypeDisplayName(): string { return getEnumMappingEntry(authenticationTypeMapping, this.authenticationType).displayName; }
public get engineType(): EngineType { return this._profile.engineType; }
}
let TestingServers: TestServerProfile[] = [
new TestServerProfile(
{
serverName: getConfigValue(EnvironmentVariable_STANDALONE_SERVER),
userName: getConfigValue(EnvironmentVariable_STANDALONE_USERNAME),
password: getConfigValue(EnvironmentVariable_STANDALONE_PASSWORD),
authenticationType: AuthenticationType.SqlLogin,
database: 'master',
provider: ConnectionProvider.SQLServer,
version: '2017',
engineType: EngineType.Standalone
}),
new TestServerProfile(
{
serverName: getConfigValue(EnvironmentVariable_AZURE_SERVER),
userName: getConfigValue(EnvironmentVariable_AZURE_USERNAME),
password: getConfigValue(EnvironmentVariable_AZURE_PASSWORD),
authenticationType: AuthenticationType.SqlLogin,
database: 'master',
provider: ConnectionProvider.SQLServer,
version: '2012',
engineType: EngineType.Azure
}),
new TestServerProfile(
{
serverName: getConfigValue(EnvironmentVariable_BDC_SERVER),
userName: getConfigValue(EnvironmentVariable_BDC_USERNAME),
password: getConfigValue(EnvironmentVariable_BDC_PASSWORD),
authenticationType: AuthenticationType.SqlLogin,
database: 'master',
provider: ConnectionProvider.SQLServer,
version: '2019',
engineType: EngineType.BigDataCluster
}),
new TestServerProfile(
{
serverName: getConfigValue(EnvironmentVariable_STANDALONE_SERVER_2019),
userName: getConfigValue(EnvironmentVariable_STANDALONE_USERNAME_2019),
password: getConfigValue(EnvironmentVariable_STANDALONE_PASSWORD_2019),
authenticationType: AuthenticationType.SqlLogin,
database: 'master',
provider: ConnectionProvider.SQLServer,
version: '2019',
engineType: EngineType.Standalone
})
];
function getEnumMappingEntry(mapping: any, enumValue: any): INameDisplayNamePair {
let entry = mapping[enumValue];
if (entry) {
return entry;
} else {
throw new Error(`Unknown enum type: ${enumValue.toString()}`);
}
}
export async function getAzureServer(): Promise<TestServerProfile> {
let servers = await getTestingServers();
return servers.filter(s => s.engineType === EngineType.Azure)[0];
}
export async function getStandaloneServer(version: '2017' | '2019' = '2017'): Promise<TestServerProfile> {
let servers = await getTestingServers();
return servers.filter(s => s.version === version && s.engineType === EngineType.Standalone)[0];
}
export async function getBdcServer(): Promise<TestServerProfile> {
let servers = await getTestingServers();
return servers.filter(s => s.version === '2019' && s.engineType === EngineType.BigDataCluster)[0];
}
export async function getTestingServers(): Promise<TestServerProfile[]> {
let promise = new Promise<TestServerProfile[]>(resolve => {
resolve(TestingServers);
});
await promise;
return promise;
}

View File

@@ -0,0 +1,294 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import * as fs from 'fs';
import { TestServerProfile, TestConnectionInfo } from './testConfig';
import { isNullOrUndefined, promisify } from 'util';
// default server connection timeout
export const DefaultConnectTimeoutInMs: number = 10000;
/**
* @param connectionInfo test connection profile
* @param timeout optional timeout parameter
* Returns connection id for a new connection
*/
export async function connectToServer(connectionInfo: TestConnectionInfo, timeout: number = DefaultConnectTimeoutInMs): Promise<string> {
let connectionProfile: azdata.IConnectionProfile = {
serverName: connectionInfo.serverName,
databaseName: connectionInfo.database,
authenticationType: connectionInfo.authenticationTypeName,
providerName: connectionInfo.providerName,
connectionName: '',
userName: connectionInfo.userName,
password: connectionInfo.password,
savePassword: false,
groupFullName: undefined,
saveProfile: true,
id: undefined,
groupId: undefined,
options: {}
};
await ensureConnectionViewOpened();
let result = <azdata.ConnectionResult>await azdata.connection.connect(connectionProfile);
assert(result.connected, `Failed to connect to "${connectionProfile.serverName}", error code: ${result.errorCode}, error message: ${result.errorMessage}`);
//workaround
//wait for OE to load
await pollTimeout(async () => {
const nodes = await azdata.objectexplorer.getActiveConnectionNodes();
let found = nodes.some(node => {
return node.connectionId === result.connectionId;
});
if (found === undefined) {
found = false;
}
return found;
}, 1000, timeout);
return result.connectionId;
}
export class PromiseCancelledError extends Error { }
/**
* Wait for a promise to resolve but timeout after a certain amount of time.
* It will throw CancelledError when it fails.
* @param p promise to wait on
* @param timeout time to wait
*/
export async function asyncTimeout<T>(p: Thenable<T>, timeout: number): Promise<(T | undefined)> {
const timeoutPromise = new Promise<T>((done, reject) => {
setTimeout(() => {
reject(new PromiseCancelledError('Promise did not resolve in time'));
}, timeout);
});
return Promise.race([p, timeoutPromise]);
}
export async function pollTimeout(predicate: () => Thenable<boolean>, intervalDelay: number, timeoutTime: number): Promise<boolean> {
let interval: NodeJS.Timer;
return new Promise(pollOver => {
const complete = (success = false) => {
clearInterval(interval);
pollOver(success);
};
interval = setInterval(async () => {
const predResult = await predicate();
if (predResult) {
complete(true);
}
}, intervalDelay);
setTimeout(complete, timeoutTime);
});
}
export async function ensureConnectionViewOpened() {
await vscode.commands.executeCommand('dataExplorer.servers.focus');
}
export async function sleep(ms: number): Promise<{}> {
return new Promise(resolve => setTimeout(resolve, ms));
}
export async function createDB(dbName: string, ownerUri: string): Promise<void> {
let query = `BEGIN TRY
CREATE DATABASE ${dbName}
SELECT 1 AS NoError
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH`;
let dbCreatedResult = await runQuery(query, ownerUri);
assert(dbCreatedResult.columnInfo[0].columnName !== 'ErrorMessage', 'DB creation threw error');
}
export async function deleteDB(server: TestServerProfile, dbName: string, ownerUri: string): Promise<void> {
let query = `BEGIN TRY
ALTER DATABASE ${dbName}
SET OFFLINE
WITH ROLLBACK IMMEDIATE
DROP DATABASE ${dbName}
SELECT 1 AS NoError
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH`;
ownerUri = await ensureServerConnected(server, ownerUri);
let dbDeleteResult = await runQuery(query, ownerUri);
assert(dbDeleteResult.columnInfo[0].columnName !== 'ErrorMessage', 'DB deletion threw error');
}
async function ensureServerConnected(server: TestServerProfile, ownerUri: string): Promise<string> {
try {
// The queries might fail if connection is removed
// Check if connection is present - if not create new connection and use OwnerUri from there
let connection = await azdata.connection.getConnection(ownerUri);
if (isNullOrUndefined(connection)) {
let connectionId = await connectToServer(server);
return azdata.connection.getUriForConnection(connectionId);
}
}
catch (ex) {
console.error('utils.ensureServerConnected : Failed to get or create connection');
console.error(ex); // not throwing here because it is a safety net and actual query will throw if failed.
}
return ownerUri;
}
export async function runQuery(query: string, ownerUri: string): Promise<azdata.SimpleExecuteResult> {
try {
let queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>('MSSQL', azdata.DataProviderType.QueryProvider);
let result = await queryProvider.runQueryAndReturn(ownerUri, query);
return result;
}
catch (ex) {
console.error('utils.runQuery : Failed to run query');
console.error(ex);
throw ex;
}
}
export async function assertThrowsAsync(fn: () => Promise<any>, msg: string): Promise<void> {
let f = () => {
// Empty
};
try {
await fn();
} catch (e) {
f = () => { throw e; };
} finally {
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;
// add state=0 to the query to make sure the database is online
const query = `BEGIN TRY
SELECT name FROM sys.databases WHERE name='${databaseName}' AND state=0
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH`;
try {
result = await runQuery(query, ownerUri);
if (result.rowCount > 0) {
break;
}
}
catch {
// exception will be thrown by the SQL Tools Service if no results is returned
// ignore it.
}
await sleep(5000);
}
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 = await promisify(fs.exists)(filepath);
await sleep(5000);
}
assert(exists, `File ${filepath} is expected to be present`);
assert((await fs.promises.readFile(filepath)).byteLength > 0, 'File ${filepath} should not be empty');
await fs.promises.unlink(filepath);
}
/**
*
* @param tableName table to look for
* @param schema schema to look for
* @param ownerUri owner uri
* @param retryCount number of times to retry with a 5 second wait between each try
* @param checkForData whether or not to check if the table has data
* Checks for table existing
*/
export async function assertTableCreationResult(schema: string, tableName: string, ownerUri: string, retryCount: number, checkForData?: boolean): Promise<void> {
let result: azdata.SimpleExecuteResult;
while (retryCount > 0) {
--retryCount;
let query = `BEGIN TRY
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '${schema}' AND TABLE_NAME = '${tableName}'
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH`;
result = await runQuery(query, ownerUri);
if (result.rowCount > 0) {
break;
}
await sleep(5000);
}
assert(result.rowCount === 1, `Table ${tableName} should be created. ${result.rowCount} rows were found`);
assert(result.columnInfo[0].columnName !== 'ErrorMessage', `Checking for table creation threw error ${result.rows[0][0].displayValue}`);
if (checkForData) {
while (retryCount > 0) {
let query = `BEGIN TRY
SELECT * FROM ${tableName}
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH`;
result = await runQuery(query, ownerUri);
if (result.rowCount > 0) {
break;
}
await sleep(5000);
}
assert(result.rowCount > 0, `Table ${tableName} should have at least one row of data. ${result.rowCount} rows were found`);
assert(result.columnInfo[0].columnName !== 'ErrorMessage', `Checking for table creation threw error ${result.rows[0][0].displayValue}`);
}
}
export function testServerProfileToIConnectionProfile(serverProfile: TestServerProfile): azdata.IConnectionProfile {
return {
serverName: serverProfile.serverName,
databaseName: serverProfile.database,
authenticationType: serverProfile.authenticationTypeName,
providerName: serverProfile.providerName,
connectionName: '',
userName: serverProfile.userName,
password: serverProfile.password,
savePassword: false,
groupFullName: undefined,
saveProfile: true,
id: undefined,
groupId: undefined,
options: {}
};
}

View File

@@ -0,0 +1,108 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* Represents a UUID as defined by rfc4122.
*/
export interface UUID {
/**
* @returns the canonical representation in sets of hexadecimal numbers separated by dashes.
*/
asHex(): string;
}
class ValueUUID implements UUID {
constructor(public _value: string) {
// empty
}
public asHex(): string {
return this._value;
}
}
class V4UUID extends ValueUUID {
private static readonly _chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
private static readonly _timeHighBits = ['8', '9', 'a', 'b'];
private static _oneOf(array: string[]): string {
return array[Math.floor(array.length * Math.random())];
}
private static _randomHex(): string {
return V4UUID._oneOf(V4UUID._chars);
}
constructor() {
super([
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
'-',
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
'-',
'4',
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
'-',
V4UUID._oneOf(V4UUID._timeHighBits),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
'-',
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
V4UUID._randomHex(),
].join(''));
}
}
export function v4(): UUID {
return new V4UUID();
}
const _UUIDPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
export function isUUID(value: string): boolean {
return _UUIDPattern.test(value);
}
/**
* Parses a UUID that is of the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
* @param value A uuid string.
*/
export function parse(value: string): UUID {
if (!isUUID(value)) {
throw new Error('invalid uuid');
}
return new ValueUUID(value);
}
export function generateUuid(): string {
return v4().asHex();
}