Skip to content

Commit 864041e

Browse files
committed
Add integration tests for database fetching
1 parent 16eac45 commit 864041e

5 files changed

Lines changed: 151 additions & 17 deletions

File tree

extensions/ql-vscode/src/databaseFetcher.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ import { logger } from './logging';
2020
/**
2121
* Prompts a user to fetch a database from a remote location. Database is assumed to be an archive file.
2222
*
23-
* @param databasesManager the DatabaseManager
23+
* @param databaseManager the DatabaseManager
2424
* @param storagePath where to store the unzipped database.
2525
*/
2626
export async function promptImportInternetDatabase(
27-
databasesManager: DatabaseManager,
27+
databaseManager: DatabaseManager,
2828
storagePath: string,
2929
progress: ProgressCallback,
3030
token: CancellationToken,
@@ -40,7 +40,7 @@ export async function promptImportInternetDatabase(
4040

4141
const item = await databaseArchiveFetcher(
4242
databaseUrl,
43-
databasesManager,
43+
databaseManager,
4444
storagePath,
4545
progress,
4646
token
@@ -59,11 +59,11 @@ export async function promptImportInternetDatabase(
5959
* User enters a project url and then the user is asked which language
6060
* to download (if there is more than one)
6161
*
62-
* @param databasesManager the DatabaseManager
62+
* @param databaseManager the DatabaseManager
6363
* @param storagePath where to store the unzipped database.
6464
*/
6565
export async function promptImportLgtmDatabase(
66-
databasesManager: DatabaseManager,
66+
databaseManager: DatabaseManager,
6767
storagePath: string,
6868
progress: ProgressCallback,
6969
token: CancellationToken
@@ -81,7 +81,7 @@ export async function promptImportLgtmDatabase(
8181
if (databaseUrl) {
8282
const item = await databaseArchiveFetcher(
8383
databaseUrl,
84-
databasesManager,
84+
databaseManager,
8585
storagePath,
8686
progress,
8787
token
@@ -102,20 +102,20 @@ export async function promptImportLgtmDatabase(
102102
* Imports a database from a local archive.
103103
*
104104
* @param databaseUrl the file url of the archive to import
105-
* @param databasesManager the DatabaseManager
105+
* @param databaseManager the DatabaseManager
106106
* @param storagePath where to store the unzipped database.
107107
*/
108108
export async function importArchiveDatabase(
109109
databaseUrl: string,
110-
databasesManager: DatabaseManager,
110+
databaseManager: DatabaseManager,
111111
storagePath: string,
112112
progress: ProgressCallback,
113113
token: CancellationToken,
114114
): Promise<DatabaseItem | undefined> {
115115
try {
116116
const item = await databaseArchiveFetcher(
117117
databaseUrl,
118-
databasesManager,
118+
databaseManager,
119119
storagePath,
120120
progress,
121121
token
@@ -140,14 +140,14 @@ export async function importArchiveDatabase(
140140
* or in the local filesystem.
141141
*
142142
* @param databaseUrl URL from which to grab the database
143-
* @param databasesManager the DatabaseManager
143+
* @param databaseManager the DatabaseManager
144144
* @param storagePath where to store the unzipped database.
145145
* @param progress callback to send progress messages to
146146
* @param token cancellation token
147147
*/
148148
async function databaseArchiveFetcher(
149149
databaseUrl: string,
150-
databasesManager: DatabaseManager,
150+
databaseManager: DatabaseManager,
151151
storagePath: string,
152152
progress: ProgressCallback,
153153
token: CancellationToken
@@ -189,8 +189,8 @@ async function databaseArchiveFetcher(
189189
});
190190
await ensureZippedSourceLocation(dbPath);
191191

192-
const item = await databasesManager.openDatabase(progress, token, Uri.file(dbPath));
193-
databasesManager.setCurrentDatabaseItem(item);
192+
const item = await databaseManager.openDatabase(progress, token, Uri.file(dbPath));
193+
await databaseManager.setCurrentDatabaseItem(item);
194194
return item;
195195
} else {
196196
throw new Error('Database not found in archive.');

extensions/ql-vscode/src/extension.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ export interface CodeQLExtensionInterface {
122122
readonly cliServer: CodeQLCliServer;
123123
readonly qs: qsClient.QueryServerClient;
124124
readonly distributionManager: DistributionManager;
125+
readonly databaseManager: DatabaseManager;
126+
readonly databaseUI: DatabaseUI;
125127
}
126128

127129
/**
@@ -675,7 +677,9 @@ async function activateWithInstalledDistribution(
675677
ctx,
676678
cliServer,
677679
qs,
678-
distributionManager
680+
distributionManager,
681+
databaseManager: dbm,
682+
databaseUI
679683
};
680684
}
681685

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import 'mocha';
2+
import 'sinon-chai';
3+
import * as sinon from 'sinon';
4+
import * as path from 'path';
5+
import * as tmp from 'tmp';
6+
7+
import { expect } from 'chai';
8+
import { ConfigurationTarget, workspace, extensions, CancellationToken, Uri } from 'vscode';
9+
import * as vscode from 'vscode';
10+
import * as fs from 'fs-extra';
11+
12+
import { CodeQLExtensionInterface } from '../../extension';
13+
import { DatabaseManager } from '../../databases';
14+
import { promptImportLgtmDatabase, importArchiveDatabase, promptImportInternetDatabase } from '../../databaseFetcher';
15+
import { ProgressCallback } from '../../helpers';
16+
import { fail } from 'assert';
17+
import fetch from 'node-fetch';
18+
19+
/**
20+
* Run various integration tests for databases
21+
*/
22+
describe('Databases', function() {
23+
const DB_URL = 'https://github.com/github/vscode-codeql/files/5586722/simple-db.zip';
24+
const LGTM_URL = 'https://lgtm.com/projects/g/aeisenberg/angular-bind-notifier/';
25+
26+
this.timeout(60000);
27+
28+
let databaseManager: DatabaseManager;
29+
let sandbox: sinon.SinonSandbox;
30+
let storagePath: string;
31+
let storagePathCleanup: () => void;
32+
let inputBoxStub: sinon.SinonStub;
33+
let progressCallback: ProgressCallback;
34+
35+
36+
beforeEach(async () => {
37+
try {
38+
// Set it here before activation to ensure we don't accidentally try to download a cli
39+
await workspace.getConfiguration().update('codeQL.cli.executablePath', process.env.CLI_PATH, ConfigurationTarget.Global);
40+
const extension = await extensions.getExtension<CodeQLExtensionInterface | {}>('GitHub.vscode-codeql')!.activate();
41+
if ('cliServer' in extension) {
42+
databaseManager = extension.databaseManager;
43+
} else {
44+
throw new Error('Extension not initialized. Make sure cli is downloaded and installed properly.');
45+
}
46+
47+
sandbox = sinon.createSandbox();
48+
const dir = tmp.dirSync();
49+
storagePath = dir.name;
50+
// the uri.fsPath function on windows returns a lowercase drive letter
51+
// so, force the storage path string to be lowercase, too.
52+
if (storagePath.substring(0, 2).match(/[A-Z]:/)) {
53+
storagePath = storagePath.substring(0, 1).toLocaleLowerCase() + storagePath.substring(1);
54+
}
55+
storagePathCleanup = dir.removeCallback;
56+
progressCallback = sandbox.spy();
57+
inputBoxStub = sandbox.stub(vscode.window, 'showInputBox');
58+
} catch (e) {
59+
fail(e);
60+
}
61+
});
62+
63+
afterEach(() => {
64+
try {
65+
databaseManager.dispose();
66+
sandbox.restore();
67+
storagePathCleanup();
68+
} catch (e) {
69+
fail(e);
70+
}
71+
});
72+
73+
it('should add a database from a folder', async () => {
74+
const result = await downloadDb();
75+
try {
76+
const progressCallback = sandbox.spy() as ProgressCallback;
77+
const uri = Uri.file(result.dbLoc);
78+
let dbItem = await importArchiveDatabase(uri.toString(true), databaseManager, storagePath, progressCallback, {} as CancellationToken);
79+
expect(dbItem).to.be.eq(databaseManager.currentDatabaseItem);
80+
expect(dbItem).to.be.eq(databaseManager.databaseItems[0]);
81+
expect(dbItem).not.to.be.undefined;
82+
dbItem = dbItem!;
83+
expect(dbItem.name).to.eq('db');
84+
expect(dbItem.databaseUri.fsPath).to.eq(path.join(storagePath, 'db', 'db'));
85+
} finally {
86+
result.removeCallback();
87+
}
88+
});
89+
90+
it('should add a database from lgtm with only one language', async () => {
91+
inputBoxStub.resolves(LGTM_URL);
92+
let dbItem = await promptImportLgtmDatabase(databaseManager, storagePath, progressCallback, {} as CancellationToken);
93+
expect(dbItem).not.to.be.undefined;
94+
dbItem = dbItem!;
95+
expect(dbItem.name).to.eq('aeisenberg_angular-bind-notifier_106179a');
96+
expect(dbItem.databaseUri.fsPath).to.eq(path.join(storagePath, 'javascript', 'aeisenberg_angular-bind-notifier_106179a'));
97+
});
98+
99+
it('should add a database from a url', async () => {
100+
inputBoxStub.resolves(DB_URL);
101+
102+
let dbItem = await promptImportInternetDatabase(databaseManager, storagePath, progressCallback, {} as CancellationToken);
103+
expect(dbItem).not.to.be.undefined;
104+
dbItem = dbItem!;
105+
expect(dbItem.name).to.eq('db');
106+
expect(dbItem.databaseUri.fsPath).to.eq(path.join(storagePath, 'simple-db', 'db'));
107+
});
108+
109+
async function downloadDb(): Promise<{
110+
removeCallback: () => void; dbLoc: string;
111+
}> {
112+
return new Promise((resolve, reject) => {
113+
fetch(DB_URL).then(response => {
114+
const dir = tmp.dirSync();
115+
const dbLoc = path.join(dir.name, 'db.zip');
116+
const dest = fs.createWriteStream(dbLoc);
117+
response.body.pipe(dest);
118+
119+
response.body.on('error', reject);
120+
dest.on('error', reject);
121+
dest.on('close', () => {
122+
resolve({
123+
removeCallback: dir.removeCallback,
124+
dbLoc
125+
});
126+
});
127+
});
128+
});
129+
}
130+
});

extensions/ql-vscode/src/vscode-tests/cli-integration/run-cli.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import 'mocha';
22
import 'sinon-chai';
33

4-
54
import { expect } from 'chai';
65
import { ConfigurationTarget, workspace, extensions } from 'vscode';
76
import { SemVer } from 'semver';

extensions/ql-vscode/src/vscode-tests/run-integration-tests.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
downloadAndUnzipVSCode,
77
resolveCliPathFromVSCodeExecutablePath
88
} from 'vscode-test';
9-
import { assertNever } from '../helpers-pure';
9+
import { assertNever } from '../pure/helpers-pure';
1010

1111
// For some reason, `TestOptions` is not exported directly from `vscode-test`,
1212
// but we can be tricky and import directly from the out file.
@@ -120,9 +120,10 @@ function getLaunchArgs(dir: TestDir) {
120120
];
121121

122122
case TestDir.CliIntegration:
123-
return undefined;
123+
break;
124124

125125
default:
126126
assertNever(dir);
127127
}
128+
return undefined;
128129
}

0 commit comments

Comments
 (0)