Skip to content

Commit fc017b0

Browse files
authored
[Security Scans] Adding performance test for auto scans (#5420)
* Adding Performance tests for security scans.
1 parent e9e4222 commit fc017b0

File tree

1 file changed

+91
-2
lines changed

1 file changed

+91
-2
lines changed

packages/core/src/test/codewhisperer/commands/startSecurityScan.test.ts

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@ import assert from 'assert'
77
import * as vscode from 'vscode'
88
import * as sinon from 'sinon'
99
import * as semver from 'semver'
10+
import * as process from 'process'
1011
import { DefaultCodeWhispererClient } from '../../../codewhisperer/client/codewhisperer'
1112
import * as startSecurityScan from '../../../codewhisperer/commands/startSecurityScan'
1213
import { SecurityPanelViewProvider } from '../../../codewhisperer/views/securityPanelViewProvider'
1314
import { FakeExtensionContext } from '../../fakeExtensionContext'
1415
import * as diagnosticsProvider from '../../../codewhisperer/service/diagnosticsProvider'
1516
import { getTestWorkspaceFolder } from '../../../testInteg/integrationTestsUtilities'
1617
import { join } from 'path'
17-
import { assertTelemetry, closeAllEditors } from '../../testUtil'
18+
import { assertTelemetry, closeAllEditors, createTestWorkspaceFolder, toFile } from '../../testUtil'
1819
import { stub } from '../../utilities/stubber'
1920
import { AWSError, HttpResponse } from 'aws-sdk'
2021
import { getTestWindow } from '../../shared/vscode/window'
@@ -134,7 +135,6 @@ let editor: vscode.TextEditor
134135

135136
describe('startSecurityScan', function () {
136137
const workspaceFolder = getTestWorkspaceFolder()
137-
138138
beforeEach(async function () {
139139
extensionContext = await FakeExtensionContext.create()
140140
mockSecurityPanelViewProvider = new SecurityPanelViewProvider(extensionContext)
@@ -449,3 +449,92 @@ describe('startSecurityScan', function () {
449449
} as unknown as CodewhispererSecurityScan)
450450
})
451451
})
452+
453+
describe('startSecurityScanPerformanceTest', function () {
454+
beforeEach(async function () {
455+
extensionContext = await FakeExtensionContext.create()
456+
mockSecurityPanelViewProvider = new SecurityPanelViewProvider(extensionContext)
457+
const folder = await createTestWorkspaceFolder()
458+
const mockFilePath = join(folder.uri.fsPath, 'app.py')
459+
await toFile('hello_world', mockFilePath)
460+
appCodePath = mockFilePath
461+
editor = await openTestFile(appCodePath)
462+
await model.CodeScansState.instance.setScansEnabled(false)
463+
sinon.stub(timeoutUtils, 'sleep')
464+
})
465+
466+
afterEach(function () {
467+
sinon.restore()
468+
})
469+
470+
after(async function () {
471+
await closeAllEditors()
472+
})
473+
474+
const createClient = () => {
475+
const mockClient = stub(DefaultCodeWhispererClient)
476+
mockClient.createCodeScan.resolves(mockCreateCodeScanResponse)
477+
mockClient.createUploadUrl.resolves(mockCreateUploadUrlResponse)
478+
mockClient.getCodeScan.resolves(mockGetCodeScanResponse)
479+
mockClient.listCodeScanFindings.resolves(mockListCodeScanFindingsResponse)
480+
return mockClient
481+
}
482+
483+
const openTestFile = async (filePath: string) => {
484+
const doc = await vscode.workspace.openTextDocument(filePath)
485+
return await vscode.window.showTextDocument(doc, {
486+
selection: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 1)),
487+
})
488+
}
489+
490+
it('Should calculate cpu and memory usage for file scans', async function () {
491+
getFetchStubWithResponse({ status: 200, statusText: 'testing stub' })
492+
const commandSpy = sinon.spy(vscode.commands, 'executeCommand')
493+
const securityScanRenderSpy = sinon.spy(diagnosticsProvider, 'initSecurityScanRender')
494+
495+
await model.CodeScansState.instance.setScansEnabled(true)
496+
const startTime = process.hrtime()
497+
const startScanCpuUsage = process.cpuUsage()
498+
499+
await startSecurityScan.startSecurityScan(
500+
mockSecurityPanelViewProvider,
501+
editor,
502+
createClient(),
503+
extensionContext,
504+
CodeAnalysisScope.FILE
505+
)
506+
507+
// EndScanCpuUsage is the difference of CPU Usage from start of a scan to end of a scan.
508+
const EndScanCpuUsage = process.cpuUsage(startScanCpuUsage)
509+
const elapsedTime = process.hrtime(startTime)
510+
const elapsedSeconds = elapsedTime[0] + elapsedTime[1] / 1e9
511+
512+
const EndScanCpuUsageByUser = EndScanCpuUsage.user / 1000000 // Convert microseconds to seconds
513+
const EndScanCpuUsageBySystem = EndScanCpuUsage.system / 1000000
514+
515+
const EndScanMemoryUsage = process.memoryUsage().heapTotal
516+
const EndScanMemoryUsageInMB = EndScanMemoryUsage / (1024 * 1024) // Converting bytes to MB
517+
518+
const cpuUsagePercentage = ((EndScanCpuUsageByUser + EndScanCpuUsageBySystem) / elapsedSeconds) * 100
519+
520+
// These limits are considered after some observations but may vary with machine, OS etc factors.
521+
assert(
522+
cpuUsagePercentage < 50,
523+
`Expected CPU usage should be less than 50% of total CPU%, actual CPU usage is ${cpuUsagePercentage}`
524+
)
525+
526+
assert(
527+
EndScanMemoryUsageInMB < 400,
528+
'System memory usage for performing a file scan should not be greater than 400 MB'
529+
)
530+
531+
assert.ok(commandSpy.neverCalledWith('workbench.action.problems.focus'))
532+
assert.ok(securityScanRenderSpy.calledOnce)
533+
const warnings = getTestWindow().shownMessages.filter((m) => m.severity === SeverityLevel.Warning)
534+
assert.strictEqual(warnings.length, 0)
535+
assertTelemetry('codewhisperer_securityScan', {
536+
codewhispererCodeScanScope: 'FILE',
537+
passive: true,
538+
})
539+
})
540+
})

0 commit comments

Comments
 (0)