Add integration tests for database fetching
This commit is contained in:
@@ -20,11 +20,11 @@ import { logger } from './logging';
|
||||
/**
|
||||
* Prompts a user to fetch a database from a remote location. Database is assumed to be an archive file.
|
||||
*
|
||||
* @param databasesManager the DatabaseManager
|
||||
* @param databaseManager the DatabaseManager
|
||||
* @param storagePath where to store the unzipped database.
|
||||
*/
|
||||
export async function promptImportInternetDatabase(
|
||||
databasesManager: DatabaseManager,
|
||||
databaseManager: DatabaseManager,
|
||||
storagePath: string,
|
||||
progress: ProgressCallback,
|
||||
token: CancellationToken,
|
||||
@@ -40,7 +40,7 @@ export async function promptImportInternetDatabase(
|
||||
|
||||
const item = await databaseArchiveFetcher(
|
||||
databaseUrl,
|
||||
databasesManager,
|
||||
databaseManager,
|
||||
storagePath,
|
||||
progress,
|
||||
token
|
||||
@@ -59,11 +59,11 @@ export async function promptImportInternetDatabase(
|
||||
* User enters a project url and then the user is asked which language
|
||||
* to download (if there is more than one)
|
||||
*
|
||||
* @param databasesManager the DatabaseManager
|
||||
* @param databaseManager the DatabaseManager
|
||||
* @param storagePath where to store the unzipped database.
|
||||
*/
|
||||
export async function promptImportLgtmDatabase(
|
||||
databasesManager: DatabaseManager,
|
||||
databaseManager: DatabaseManager,
|
||||
storagePath: string,
|
||||
progress: ProgressCallback,
|
||||
token: CancellationToken
|
||||
@@ -81,7 +81,7 @@ export async function promptImportLgtmDatabase(
|
||||
if (databaseUrl) {
|
||||
const item = await databaseArchiveFetcher(
|
||||
databaseUrl,
|
||||
databasesManager,
|
||||
databaseManager,
|
||||
storagePath,
|
||||
progress,
|
||||
token
|
||||
@@ -102,12 +102,12 @@ export async function promptImportLgtmDatabase(
|
||||
* Imports a database from a local archive.
|
||||
*
|
||||
* @param databaseUrl the file url of the archive to import
|
||||
* @param databasesManager the DatabaseManager
|
||||
* @param databaseManager the DatabaseManager
|
||||
* @param storagePath where to store the unzipped database.
|
||||
*/
|
||||
export async function importArchiveDatabase(
|
||||
databaseUrl: string,
|
||||
databasesManager: DatabaseManager,
|
||||
databaseManager: DatabaseManager,
|
||||
storagePath: string,
|
||||
progress: ProgressCallback,
|
||||
token: CancellationToken,
|
||||
@@ -115,7 +115,7 @@ export async function importArchiveDatabase(
|
||||
try {
|
||||
const item = await databaseArchiveFetcher(
|
||||
databaseUrl,
|
||||
databasesManager,
|
||||
databaseManager,
|
||||
storagePath,
|
||||
progress,
|
||||
token
|
||||
@@ -140,14 +140,14 @@ export async function importArchiveDatabase(
|
||||
* or in the local filesystem.
|
||||
*
|
||||
* @param databaseUrl URL from which to grab the database
|
||||
* @param databasesManager the DatabaseManager
|
||||
* @param databaseManager the DatabaseManager
|
||||
* @param storagePath where to store the unzipped database.
|
||||
* @param progress callback to send progress messages to
|
||||
* @param token cancellation token
|
||||
*/
|
||||
async function databaseArchiveFetcher(
|
||||
databaseUrl: string,
|
||||
databasesManager: DatabaseManager,
|
||||
databaseManager: DatabaseManager,
|
||||
storagePath: string,
|
||||
progress: ProgressCallback,
|
||||
token: CancellationToken
|
||||
@@ -189,8 +189,8 @@ async function databaseArchiveFetcher(
|
||||
});
|
||||
await ensureZippedSourceLocation(dbPath);
|
||||
|
||||
const item = await databasesManager.openDatabase(progress, token, Uri.file(dbPath));
|
||||
databasesManager.setCurrentDatabaseItem(item);
|
||||
const item = await databaseManager.openDatabase(progress, token, Uri.file(dbPath));
|
||||
await databaseManager.setCurrentDatabaseItem(item);
|
||||
return item;
|
||||
} else {
|
||||
throw new Error('Database not found in archive.');
|
||||
|
||||
@@ -122,6 +122,8 @@ export interface CodeQLExtensionInterface {
|
||||
readonly cliServer: CodeQLCliServer;
|
||||
readonly qs: qsClient.QueryServerClient;
|
||||
readonly distributionManager: DistributionManager;
|
||||
readonly databaseManager: DatabaseManager;
|
||||
readonly databaseUI: DatabaseUI;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -675,7 +677,9 @@ async function activateWithInstalledDistribution(
|
||||
ctx,
|
||||
cliServer,
|
||||
qs,
|
||||
distributionManager
|
||||
distributionManager,
|
||||
databaseManager: dbm,
|
||||
databaseUI
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
import 'mocha';
|
||||
import 'sinon-chai';
|
||||
import * as sinon from 'sinon';
|
||||
import * as path from 'path';
|
||||
import * as tmp from 'tmp';
|
||||
|
||||
import { expect } from 'chai';
|
||||
import { ConfigurationTarget, workspace, extensions, CancellationToken, Uri } from 'vscode';
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs-extra';
|
||||
|
||||
import { CodeQLExtensionInterface } from '../../extension';
|
||||
import { DatabaseManager } from '../../databases';
|
||||
import { promptImportLgtmDatabase, importArchiveDatabase, promptImportInternetDatabase } from '../../databaseFetcher';
|
||||
import { ProgressCallback } from '../../helpers';
|
||||
import { fail } from 'assert';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
/**
|
||||
* Run various integration tests for databases
|
||||
*/
|
||||
describe('Databases', function() {
|
||||
const DB_URL = 'https://github.com/github/vscode-codeql/files/5586722/simple-db.zip';
|
||||
const LGTM_URL = 'https://lgtm.com/projects/g/aeisenberg/angular-bind-notifier/';
|
||||
|
||||
this.timeout(60000);
|
||||
|
||||
let databaseManager: DatabaseManager;
|
||||
let sandbox: sinon.SinonSandbox;
|
||||
let storagePath: string;
|
||||
let storagePathCleanup: () => void;
|
||||
let inputBoxStub: sinon.SinonStub;
|
||||
let progressCallback: ProgressCallback;
|
||||
|
||||
|
||||
beforeEach(async () => {
|
||||
try {
|
||||
// Set it here before activation to ensure we don't accidentally try to download a cli
|
||||
await workspace.getConfiguration().update('codeQL.cli.executablePath', process.env.CLI_PATH, ConfigurationTarget.Global);
|
||||
const extension = await extensions.getExtension<CodeQLExtensionInterface | {}>('GitHub.vscode-codeql')!.activate();
|
||||
if ('cliServer' in extension) {
|
||||
databaseManager = extension.databaseManager;
|
||||
} else {
|
||||
throw new Error('Extension not initialized. Make sure cli is downloaded and installed properly.');
|
||||
}
|
||||
|
||||
sandbox = sinon.createSandbox();
|
||||
const dir = tmp.dirSync();
|
||||
storagePath = dir.name;
|
||||
// the uri.fsPath function on windows returns a lowercase drive letter
|
||||
// so, force the storage path string to be lowercase, too.
|
||||
if (storagePath.substring(0, 2).match(/[A-Z]:/)) {
|
||||
storagePath = storagePath.substring(0, 1).toLocaleLowerCase() + storagePath.substring(1);
|
||||
}
|
||||
storagePathCleanup = dir.removeCallback;
|
||||
progressCallback = sandbox.spy();
|
||||
inputBoxStub = sandbox.stub(vscode.window, 'showInputBox');
|
||||
} catch (e) {
|
||||
fail(e);
|
||||
}
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
try {
|
||||
databaseManager.dispose();
|
||||
sandbox.restore();
|
||||
storagePathCleanup();
|
||||
} catch (e) {
|
||||
fail(e);
|
||||
}
|
||||
});
|
||||
|
||||
it('should add a database from a folder', async () => {
|
||||
const result = await downloadDb();
|
||||
try {
|
||||
const progressCallback = sandbox.spy() as ProgressCallback;
|
||||
const uri = Uri.file(result.dbLoc);
|
||||
let dbItem = await importArchiveDatabase(uri.toString(true), databaseManager, storagePath, progressCallback, {} as CancellationToken);
|
||||
expect(dbItem).to.be.eq(databaseManager.currentDatabaseItem);
|
||||
expect(dbItem).to.be.eq(databaseManager.databaseItems[0]);
|
||||
expect(dbItem).not.to.be.undefined;
|
||||
dbItem = dbItem!;
|
||||
expect(dbItem.name).to.eq('db');
|
||||
expect(dbItem.databaseUri.fsPath).to.eq(path.join(storagePath, 'db', 'db'));
|
||||
} finally {
|
||||
result.removeCallback();
|
||||
}
|
||||
});
|
||||
|
||||
it('should add a database from lgtm with only one language', async () => {
|
||||
inputBoxStub.resolves(LGTM_URL);
|
||||
let dbItem = await promptImportLgtmDatabase(databaseManager, storagePath, progressCallback, {} as CancellationToken);
|
||||
expect(dbItem).not.to.be.undefined;
|
||||
dbItem = dbItem!;
|
||||
expect(dbItem.name).to.eq('aeisenberg_angular-bind-notifier_106179a');
|
||||
expect(dbItem.databaseUri.fsPath).to.eq(path.join(storagePath, 'javascript', 'aeisenberg_angular-bind-notifier_106179a'));
|
||||
});
|
||||
|
||||
it('should add a database from a url', async () => {
|
||||
inputBoxStub.resolves(DB_URL);
|
||||
|
||||
let dbItem = await promptImportInternetDatabase(databaseManager, storagePath, progressCallback, {} as CancellationToken);
|
||||
expect(dbItem).not.to.be.undefined;
|
||||
dbItem = dbItem!;
|
||||
expect(dbItem.name).to.eq('db');
|
||||
expect(dbItem.databaseUri.fsPath).to.eq(path.join(storagePath, 'simple-db', 'db'));
|
||||
});
|
||||
|
||||
async function downloadDb(): Promise<{
|
||||
removeCallback: () => void; dbLoc: string;
|
||||
}> {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(DB_URL).then(response => {
|
||||
const dir = tmp.dirSync();
|
||||
const dbLoc = path.join(dir.name, 'db.zip');
|
||||
const dest = fs.createWriteStream(dbLoc);
|
||||
response.body.pipe(dest);
|
||||
|
||||
response.body.on('error', reject);
|
||||
dest.on('error', reject);
|
||||
dest.on('close', () => {
|
||||
resolve({
|
||||
removeCallback: dir.removeCallback,
|
||||
dbLoc
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'mocha';
|
||||
import 'sinon-chai';
|
||||
|
||||
|
||||
import { expect } from 'chai';
|
||||
import { ConfigurationTarget, workspace, extensions } from 'vscode';
|
||||
import { SemVer } from 'semver';
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
downloadAndUnzipVSCode,
|
||||
resolveCliPathFromVSCodeExecutablePath
|
||||
} from 'vscode-test';
|
||||
import { assertNever } from '../helpers-pure';
|
||||
import { assertNever } from '../pure/helpers-pure';
|
||||
|
||||
// For some reason, `TestOptions` is not exported directly from `vscode-test`,
|
||||
// but we can be tricky and import directly from the out file.
|
||||
@@ -120,9 +120,10 @@ function getLaunchArgs(dir: TestDir) {
|
||||
];
|
||||
|
||||
case TestDir.CliIntegration:
|
||||
return undefined;
|
||||
break;
|
||||
|
||||
default:
|
||||
assertNever(dir);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user