Skip to content

Commit

Permalink
Merge master into feature/cwltail
Browse files Browse the repository at this point in the history
  • Loading branch information
aws-toolkit-automation authored Oct 14, 2024
2 parents 79f7e55 + 1bb57a7 commit 9815c8b
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 271 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,130 +7,28 @@ import assert from 'assert'
import * as vscode from 'vscode'
import * as sinon from 'sinon'
import * as semver from 'semver'
import { DefaultCodeWhispererClient } from '../../../codewhisperer/client/codewhisperer'
import * as startSecurityScan from '../../../codewhisperer/commands/startSecurityScan'
import { SecurityPanelViewProvider } from '../../../codewhisperer/views/securityPanelViewProvider'
import { FakeExtensionContext } from '../../fakeExtensionContext'
import * as diagnosticsProvider from '../../../codewhisperer/service/diagnosticsProvider'
import { getTestWorkspaceFolder } from '../../../testInteg/integrationTestsUtilities'
import * as startSecurityScan from '../../codewhisperer/commands/startSecurityScan'
import { SecurityPanelViewProvider } from '../../codewhisperer/views/securityPanelViewProvider'
import { FakeExtensionContext } from '../fakeExtensionContext'
import * as diagnosticsProvider from '../../codewhisperer/service/diagnosticsProvider'
import { getTestWorkspaceFolder } from '../../testInteg/integrationTestsUtilities'
import { join } from 'path'
import {
assertTelemetry,
closeAllEditors,
createTestWorkspaceFolder,
getFetchStubWithResponse,
toFile,
} from '../../testUtil'
import { stub } from '../../utilities/stubber'
import { AWSError, HttpResponse } from 'aws-sdk'
import { getTestWindow } from '../../shared/vscode/window'
import { SeverityLevel } from '../../shared/vscode/message'
import { cancel } from '../../../shared/localizedText'
import { assertTelemetry, closeAllEditors, getFetchStubWithResponse } from '../testUtil'
import { AWSError } from 'aws-sdk'
import { getTestWindow } from '../shared/vscode/window'
import { SeverityLevel } from '../shared/vscode/message'
import { cancel } from '../../shared/localizedText'
import {
showScannedFilesMessage,
stopScanMessage,
CodeAnalysisScope,
projectScansLimitReached,
} from '../../../codewhisperer/models/constants'
import * as model from '../../../codewhisperer/models/model'
import { CodewhispererSecurityScan } from '../../../shared/telemetry/telemetry.gen'
import * as errors from '../../../shared/errors'
import * as timeoutUtils from '../../../shared/utilities/timeoutUtils'
import { performanceTest } from '../../../shared/performance/performance'

const mockCreateCodeScanResponse = {
$response: {
data: {
jobId: 'jobId',
status: 'Pending',
},
requestId: 'requestId',
hasNextPage: () => false,
error: undefined,
nextPage: () => undefined,
redirectCount: 0,
retryCount: 0,
httpResponse: new HttpResponse(),
},
jobId: 'jobId',
status: 'Pending',
}

const mockCreateUploadUrlResponse = {
$response: {
data: {
uploadId: 'uploadId',
uploadUrl: 'uploadUrl',
},
requestId: 'requestId',
hasNextPage: () => false,
error: undefined,
nextPage: () => undefined,
redirectCount: 0,
retryCount: 0,
httpResponse: new HttpResponse(),
},
uploadId: 'uploadId',
uploadUrl: 'https://test.com',
}

const mockGetCodeScanResponse = {
$response: {
data: {
status: 'Completed',
},
requestId: 'requestId',
hasNextPage: () => false,
error: undefined,
nextPage: () => undefined,
redirectCount: 0,
retryCount: 0,
httpResponse: new HttpResponse(),
},
status: 'Completed',
}

const mockCodeScanFindings = JSON.stringify([
{
filePath: 'workspaceFolder/python3.7-plain-sam-app/hello_world/app.py',
startLine: 1,
endLine: 1,
title: 'title',
description: {
text: 'text',
markdown: 'markdown',
},
detectorId: 'detectorId',
detectorName: 'detectorName',
findingId: 'findingId',
relatedVulnerabilities: [],
severity: 'High',
remediation: {
recommendation: {
text: 'text',
url: 'url',
},
suggestedFixes: [],
},
codeSnippet: [],
} satisfies model.RawCodeScanIssue,
])

const mockListCodeScanFindingsResponse = {
$response: {
data: {
codeScanFindings: mockCodeScanFindings,
},
requestId: 'requestId',
hasNextPage: () => false,
error: undefined,
nextPage: () => undefined,
redirectCount: 0,
retryCount: 0,
httpResponse: new HttpResponse(),
},
codeScanFindings: mockCodeScanFindings,
}
} from '../../codewhisperer/models/constants'
import * as model from '../../codewhisperer/models/model'
import { CodewhispererSecurityScan } from '../../shared/telemetry/telemetry.gen'
import * as errors from '../../shared/errors'
import * as timeoutUtils from '../../shared/utilities/timeoutUtils'
import { createClient, mockGetCodeScanResponse } from './testUtil'

let extensionContext: FakeExtensionContext
let mockSecurityPanelViewProvider: SecurityPanelViewProvider
Expand All @@ -155,15 +53,6 @@ describe('startSecurityScan', function () {
after(async function () {
await closeAllEditors()
})
const createClient = () => {
const mockClient = stub(DefaultCodeWhispererClient)

mockClient.createCodeScan.resolves(mockCreateCodeScanResponse)
mockClient.createUploadUrl.resolves(mockCreateUploadUrlResponse)
mockClient.getCodeScan.resolves(mockGetCodeScanResponse)
mockClient.listCodeScanFindings.resolves(mockListCodeScanFindingsResponse)
return mockClient
}

const openTestFile = async (filePath: string) => {
const doc = await vscode.workspace.openTextDocument(filePath)
Expand Down Expand Up @@ -454,78 +343,3 @@ describe('startSecurityScan', function () {
} as unknown as CodewhispererSecurityScan)
})
})

describe('startSecurityScanPerformanceTest', function () {
beforeEach(async function () {
extensionContext = await FakeExtensionContext.create()
mockSecurityPanelViewProvider = new SecurityPanelViewProvider(extensionContext)
const folder = await createTestWorkspaceFolder()
const mockFilePath = join(folder.uri.fsPath, 'app.py')
await toFile('hello_world', mockFilePath)
appCodePath = mockFilePath
editor = await openTestFile(appCodePath)
await model.CodeScansState.instance.setScansEnabled(false)
sinon.stub(timeoutUtils, 'sleep')
})

afterEach(function () {
sinon.restore()
})

after(async function () {
await closeAllEditors()
})

const createClient = () => {
const mockClient = stub(DefaultCodeWhispererClient)
mockClient.createCodeScan.resolves(mockCreateCodeScanResponse)
mockClient.createUploadUrl.resolves(mockCreateUploadUrlResponse)
mockClient.getCodeScan.resolves(mockGetCodeScanResponse)
mockClient.listCodeScanFindings.resolves(mockListCodeScanFindingsResponse)
return mockClient
}

const openTestFile = async (filePath: string) => {
const doc = await vscode.workspace.openTextDocument(filePath)
return await vscode.window.showTextDocument(doc, {
selection: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 1)),
})
}

performanceTest({}, 'Should calculate cpu and memory usage for file scans', function () {
return {
setup: async () => {
getFetchStubWithResponse({ status: 200, statusText: 'testing stub' })
const commandSpy = sinon.spy(vscode.commands, 'executeCommand')
const securityScanRenderSpy = sinon.spy(diagnosticsProvider, 'initSecurityScanRender')
await model.CodeScansState.instance.setScansEnabled(true)
return { commandSpy, securityScanRenderSpy }
},
execute: async () => {
await startSecurityScan.startSecurityScan(
mockSecurityPanelViewProvider,
editor,
createClient(),
extensionContext,
CodeAnalysisScope.FILE
)
},
verify: ({
commandSpy,
securityScanRenderSpy,
}: {
commandSpy: sinon.SinonSpy
securityScanRenderSpy: sinon.SinonSpy
}) => {
assert.ok(commandSpy.neverCalledWith('workbench.action.problems.focus'))
assert.ok(securityScanRenderSpy.calledOnce)
const warnings = getTestWindow().shownMessages.filter((m) => m.severity === SeverityLevel.Warning)
assert.strictEqual(warnings.length, 0)
assertTelemetry('codewhisperer_securityScan', {
codewhispererCodeScanScope: 'FILE',
passive: true,
})
},
}
})
})
107 changes: 106 additions & 1 deletion packages/core/src/test/codewhisperer/testUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ import globals from '../../shared/extensionGlobals'
import { session } from '../../codewhisperer/util/codeWhispererSession'
import { DefaultAWSClientBuilder, ServiceOptions } from '../../shared/awsClientBuilder'
import { FakeAwsContext } from '../utilities/fakeAwsContext'
import { Service } from 'aws-sdk'
import { HttpResponse, Service } from 'aws-sdk'
import userApiConfig = require('./../../codewhisperer/client/user-service-2.json')
import CodeWhispererUserClient = require('../../codewhisperer/client/codewhispereruserclient')
import { codeWhispererClient } from '../../codewhisperer/client/codewhisperer'
import { RecommendationHandler } from '../../codewhisperer/service/recommendationHandler'
import * as model from '../../codewhisperer/models/model'
import { stub } from '../utilities/stubber'
import { Dirent } from 'fs' // eslint-disable-line no-restricted-imports

export async function resetCodeWhispererGlobalVariables() {
Expand Down Expand Up @@ -208,6 +210,109 @@ export function createMockDirentFile(fileName: string): Dirent {
return dirent
}

export const mockGetCodeScanResponse = {
$response: {
data: {
status: 'Completed',
},
requestId: 'requestId',
hasNextPage: () => false,
error: undefined,
nextPage: () => undefined,
redirectCount: 0,
retryCount: 0,
httpResponse: new HttpResponse(),
},
status: 'Completed',
}

export function createClient() {
const mockClient = stub(codewhispererClient.DefaultCodeWhispererClient)

const mockCreateCodeScanResponse = {
$response: {
data: {
jobId: 'jobId',
status: 'Pending',
},
requestId: 'requestId',
hasNextPage: () => false,
error: undefined,
nextPage: () => undefined,
redirectCount: 0,
retryCount: 0,
httpResponse: new HttpResponse(),
},
jobId: 'jobId',
status: 'Pending',
}
const mockCreateUploadUrlResponse = {
$response: {
data: {
uploadId: 'uploadId',
uploadUrl: 'uploadUrl',
},
requestId: 'requestId',
hasNextPage: () => false,
error: undefined,
nextPage: () => undefined,
redirectCount: 0,
retryCount: 0,
httpResponse: new HttpResponse(),
},
uploadId: 'uploadId',
uploadUrl: 'https://test.com',
}

const mockCodeScanFindings = JSON.stringify([
{
filePath: 'workspaceFolder/python3.7-plain-sam-app/hello_world/app.py',
startLine: 1,
endLine: 1,
title: 'title',
description: {
text: 'text',
markdown: 'markdown',
},
detectorId: 'detectorId',
detectorName: 'detectorName',
findingId: 'findingId',
relatedVulnerabilities: [],
severity: 'High',
remediation: {
recommendation: {
text: 'text',
url: 'url',
},
suggestedFixes: [],
},
codeSnippet: [],
} satisfies model.RawCodeScanIssue,
])

const mockListCodeScanFindingsResponse = {
$response: {
data: {
codeScanFindings: mockCodeScanFindings,
},
requestId: 'requestId',
hasNextPage: () => false,
error: undefined,
nextPage: () => undefined,
redirectCount: 0,
retryCount: 0,
httpResponse: new HttpResponse(),
},
codeScanFindings: mockCodeScanFindings,
}

mockClient.createCodeScan.resolves(mockCreateCodeScanResponse)
mockClient.createUploadUrl.resolves(mockCreateUploadUrlResponse)
mockClient.getCodeScan.resolves(mockGetCodeScanResponse)
mockClient.listCodeScanFindings.resolves(mockListCodeScanFindingsResponse)
return mockClient
}

export function aStringWithLineCount(lineCount: number, start: number = 0): string {
let s = ''
for (let i = start; i < start + lineCount; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { performanceTest } from '../shared/performance/performance'
import { performanceTest } from '../../shared/performance/performance'
import * as sinon from 'sinon'
import * as vscode from 'vscode'
import assert from 'assert'
import { LspClient, LspController } from '../amazonq'
import { LspClient, LspController } from '../../amazonq'
import { LanguageClient, ServerOptions } from 'vscode-languageclient'
import { createTestWorkspace } from '../test/testUtil'
import { GetUsageRequestType, IndexRequestType } from '../amazonq/lsp/types'
import { getRandomString } from '../shared'
import { createTestWorkspace } from '../../test/testUtil'
import { GetUsageRequestType, IndexRequestType } from '../../amazonq/lsp/types'
import { getRandomString } from '../../shared'

interface SetupResult {
clientReqStub: sinon.SinonStub
Expand Down
Loading

0 comments on commit 9815c8b

Please sign in to comment.