forked from microsoft/azuredatastudio
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Simple Account Picker for use with Always Encrypted (microsoft#9707)
Adds the ability for the user to select from two or more linked azure accounts, using an integrated UI dialog, when executing a query that requires a Always Encrypted column master key located in Azure Key Vault.
- Loading branch information
Showing
9 changed files
with
1,317 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"enabled": true, | ||
"relativeSourcePath": "..", | ||
"relativeCoverageDir": "../../coverage", | ||
"ignorePatterns": [ | ||
"**/node_modules/**", | ||
"**/test/**" | ||
], | ||
"includePid": false, | ||
"reports": [ | ||
"cobertura", | ||
"lcov" | ||
], | ||
"verbose": false, | ||
"remapOptions": { | ||
"basePath": "..", | ||
"useAbsolutePaths": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the Source EULA. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
import * as path from 'path'; | ||
const testRunner = require('vscodetestcover'); | ||
|
||
const suite = 'mssql Extension Tests'; | ||
|
||
const mochaOptions: any = { | ||
ui: 'bdd', | ||
useColors: true, | ||
timeout: 10000 | ||
}; | ||
|
||
// set relevant mocha options from the environment | ||
if (process.env.ADS_TEST_GREP) { | ||
mochaOptions.grep = process.env.ADS_TEST_GREP; | ||
console.log(`setting options.grep to: ${mochaOptions.grep}`); | ||
} | ||
if (process.env.ADS_TEST_INVERT_GREP) { | ||
mochaOptions.invert = parseInt(process.env.ADS_TEST_INVERT_GREP); | ||
console.log(`setting options.invert to: ${mochaOptions.invert}`); | ||
} | ||
if (process.env.ADS_TEST_TIMEOUT) { | ||
mochaOptions.timeout = parseInt(process.env.ADS_TEST_TIMEOUT); | ||
console.log(`setting options.timeout to: ${mochaOptions.timeout}`); | ||
} | ||
if (process.env.ADS_TEST_RETRIES) { | ||
mochaOptions.retries = parseInt(process.env.ADS_TEST_RETRIES); | ||
console.log(`setting options.retries to: ${mochaOptions.retries}`); | ||
} | ||
|
||
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) { | ||
mochaOptions.reporter = 'mocha-multi-reporters'; | ||
mochaOptions.reporterOptions = { | ||
reporterEnabled: 'spec, mocha-junit-reporter', | ||
mochaJunitReporterReporterOptions: { | ||
testsuitesTitle: `${suite} ${process.platform}`, | ||
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`) | ||
} | ||
}; | ||
} | ||
|
||
testRunner.configure(mochaOptions, { coverConfig: '../../coverConfig.json' }); | ||
|
||
export = testRunner; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the Source EULA. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
import { DataItemCache } from '../../util/dataCache'; | ||
import 'mocha'; | ||
import { should } from 'chai'; should(); | ||
import * as TypeMoq from "typemoq"; | ||
|
||
describe('DataItemCache', function (): void { | ||
|
||
const testCacheItem = 'Test Cache Item'; | ||
const fetchFunction = () => Promise.resolve(testCacheItem); | ||
let fetchFunctionMock: TypeMoq.IMock<() => Promise<string>>; | ||
let dataItemCache: DataItemCache<String>; | ||
|
||
beforeEach(function (): void { | ||
fetchFunctionMock = TypeMoq.Mock.ofInstance(fetchFunction); | ||
fetchFunctionMock.setup(fx => fx()).returns(() => Promise.resolve(testCacheItem)); | ||
dataItemCache = new DataItemCache<string>(fetchFunctionMock.object, 1); | ||
}); | ||
|
||
it('Should be initialized empty', function (): void { | ||
dataItemCache.should.have.property('cachedItem').and.be.undefined; | ||
}); | ||
|
||
it('Should be initialized as expired', function (): void { | ||
dataItemCache.isCacheExpired().should.be.true; | ||
}); | ||
|
||
it('Should not be expired immediately after first data fetch', async function (): Promise<void> { | ||
await dataItemCache.getData(); | ||
|
||
dataItemCache.isCacheExpired().should.be.false; | ||
}); | ||
|
||
it('Should return expected cached item from getValue()', async function (): Promise<void> { | ||
let actualValue = await dataItemCache.getData(); | ||
|
||
actualValue.should.equal(testCacheItem); | ||
}); | ||
|
||
it('Should be expired after data is fetched and TTL passes', async function (): Promise<void> { | ||
await dataItemCache.getData(); | ||
await sleep(1.1); | ||
|
||
dataItemCache.isCacheExpired().should.be.true; | ||
}); | ||
|
||
it('Should call fetch function once for consecutive getValue() calls prior to expiration', async function (): Promise<void> { | ||
await dataItemCache.getData(); | ||
await dataItemCache.getData(); | ||
await dataItemCache.getData(); | ||
|
||
fetchFunctionMock.verify(fx => fx() ,TypeMoq.Times.once()); | ||
}); | ||
|
||
it('Should call fetch function twice for consecutive getValue() calls if TTL expires in between', async function (): Promise<void> { | ||
await dataItemCache.getData(); | ||
await sleep(1.1); | ||
await dataItemCache.getData(); | ||
|
||
fetchFunctionMock.verify(fx => fx(), TypeMoq.Times.exactly(2)); | ||
}); | ||
}); | ||
|
||
const sleep = (seconds: number) => { | ||
return new Promise(resolve => setTimeout(resolve, 1000 * seconds)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the Source EULA. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
export class DataItemCache<T> { | ||
|
||
millisecondsToLive: number; | ||
getValueFunction: (...args: any[]) => Promise<T>; | ||
cachedItem: T; | ||
fetchDate: Date; | ||
|
||
constructor(getValueFunction: (...args: any[]) => Promise<T>, secondsToLive: number) { | ||
this.millisecondsToLive = secondsToLive * 1000; | ||
this.getValueFunction = getValueFunction; | ||
this.cachedItem = undefined; | ||
this.fetchDate = new Date(0); | ||
} | ||
|
||
public isCacheExpired(): boolean { | ||
return (this.fetchDate.getTime() + this.millisecondsToLive) < new Date().getTime(); | ||
} | ||
|
||
public async getData(...args: any[]): Promise<T> { | ||
if (!this.cachedItem || this.isCacheExpired()) { | ||
let data = await this.getValueFunction(...args); | ||
this.cachedItem = data; | ||
this.fetchDate = new Date(); | ||
return data; | ||
} | ||
return this.cachedItem; | ||
} | ||
|
||
public resetCache(): void { | ||
this.fetchDate = new Date(0); | ||
} | ||
} |
Oops, something went wrong.