@@ -16,7 +16,7 @@ import kotlinx.coroutines.CoroutineScope
1616import kotlinx.coroutines.Job
1717import kotlinx.coroutines.delay
1818import kotlinx.coroutines.launch
19- import software.amazon.awssdk.services.codewhispererruntime.model.CodeWhispererRuntimeException
19+ import software.amazon.awssdk.core.exception.SdkServiceException
2020import software.amazon.awssdk.services.codewhispererruntime.model.GetTestGenerationResponse
2121import software.amazon.awssdk.services.codewhispererruntime.model.Range
2222import software.amazon.awssdk.services.codewhispererruntime.model.StartTestGenerationResponse
@@ -38,9 +38,13 @@ import software.aws.toolkits.jetbrains.services.amazonqCodeTest.session.BuildAnd
3838import software.aws.toolkits.jetbrains.services.amazonqCodeTest.session.Session
3939import software.aws.toolkits.jetbrains.services.amazonqCodeTest.utils.combineBuildAndExecuteLogFiles
4040import software.aws.toolkits.jetbrains.services.codemodernizer.utils.calculateTotalLatency
41+ import software.aws.toolkits.jetbrains.services.codewhisperer.codetest.CodeTestException
4142import software.aws.toolkits.jetbrains.services.codewhisperer.codetest.sessionconfig.CodeTestSessionConfig
43+ import software.aws.toolkits.jetbrains.services.codewhisperer.codetest.testGenStoppedError
4244import software.aws.toolkits.jetbrains.services.codewhisperer.credentials.CodeWhispererClientAdaptor
45+ import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererConstants
4346import software.aws.toolkits.jetbrains.services.codewhisperer.util.CodeWhispererUtil.promptReAuth
47+ import software.aws.toolkits.jetbrains.services.codewhisperer.util.getTelemetryErrorMessage
4448import software.aws.toolkits.jetbrains.services.cwc.controller.chat.telemetry.getStartUrl
4549import software.aws.toolkits.jetbrains.services.cwc.messages.ChatMessageType
4650import software.aws.toolkits.jetbrains.services.cwc.messages.CodeReference
@@ -67,7 +71,7 @@ class CodeWhispererUTGChatManager(val project: Project, private val cs: Coroutin
6771
6872 private fun throwIfCancelled (session : Session ) {
6973 if (! session.isGeneratingTests) {
70- error(message( " testgen.message.cancelled " ) )
74+ testGenStoppedError( )
7175 }
7276 }
7377
@@ -104,24 +108,38 @@ class CodeWhispererUTGChatManager(val project: Project, private val cs: Coroutin
104108 }
105109
106110 // 2nd API call: StartTestGeneration
107- val startTestGenerationResponse = startTestGeneration(
108- uploadId = createUploadUrlResponse.uploadId(),
109- targetCode = listOf (
110- TargetCode .builder()
111- .relativeTargetPath(codeTestResponseContext.currentFileRelativePath.toString())
112- .targetLineRangeList(
113- if (selectionRange != null ) {
114- listOf (
115- selectionRange
116- )
117- } else {
118- emptyList()
119- }
120- )
121- .build()
122- ),
123- userInput = prompt
124- )
111+ val startTestGenerationResponse = try {
112+ startTestGeneration(
113+ uploadId = createUploadUrlResponse.uploadId(),
114+ targetCode = listOf (
115+ TargetCode .builder()
116+ .relativeTargetPath(codeTestResponseContext.currentFileRelativePath.toString())
117+ .targetLineRangeList(
118+ if (selectionRange != null ) {
119+ listOf (
120+ selectionRange
121+ )
122+ } else {
123+ emptyList()
124+ }
125+ )
126+ .build()
127+ ),
128+ userInput = prompt
129+ )
130+ } catch (e: Exception ) {
131+ val statusCode = when {
132+ e is SdkServiceException -> e.statusCode()
133+ else -> 400
134+ }
135+ LOG .error(e) { " Unexpected error while creating test generation job" }
136+ val errorMessage = getTelemetryErrorMessage(e, CodeWhispererConstants .FeatureName .TEST_GENERATION )
137+ throw CodeTestException (
138+ " CreateTestJobError: $errorMessage " ,
139+ " CreateTestJobError" ,
140+ message(" testgen.error.generic_technical_error_message" )
141+ )
142+ }
125143
126144 val job = startTestGenerationResponse.testGenerationJob()
127145 session.startTestGenerationRequestId = startTestGenerationResponse.responseMetadata().requestId()
@@ -173,7 +191,12 @@ class CodeWhispererUTGChatManager(val project: Project, private val cs: Coroutin
173191 }
174192 // update test summary card
175193 } else {
176- throw Exception (message(" testgen.message.failed" ))
194+ // If job status is Completed and has no ShortAnswer then there might be some issue in the backend.
195+ throw CodeTestException (
196+ " TestGenFailedError: " + message(" testgen.message.failed" ),
197+ " TestGenFailedError" ,
198+ message(" testgen.error.generic_technical_error_message" )
199+ )
177200 }
178201 } else if (status == TestGenerationJobStatus .FAILED ) {
179202 LOG .debug {
@@ -183,12 +206,16 @@ class CodeWhispererUTGChatManager(val project: Project, private val cs: Coroutin
183206 if (testGenerationResponse.testGenerationJob().shortAnswer() != null ) {
184207 shortAnswer = parseShortAnswerString(testGenerationResponse.testGenerationJob().shortAnswer())
185208 if (shortAnswer.stopIteration == " true" ) {
186- throw Exception ( " ${shortAnswer.planSummary} " )
209+ throw CodeTestException ( " TestGenFailedError: ${shortAnswer.planSummary} " , " TestGenFailedError " , shortAnswer.planSummary )
187210 }
188211 }
189212
190- // TODO: Modify text according to FnF
191- throw Exception (message(" testgen.message.failed" ))
213+ // If job status is Failed and has no ShortAnswer then there might be some issue in the backend.
214+ throw CodeTestException (
215+ " TestGenFailedError: " + message(" testgen.message.failed" ),
216+ " TestGenFailedError" ,
217+ message(" testgen.error.generic_technical_error_message" )
218+ )
192219 } else {
193220 // In progress
194221 LOG .debug {
@@ -200,7 +227,7 @@ class CodeWhispererUTGChatManager(val project: Project, private val cs: Coroutin
200227 if (previousIterationContext == null && testGenerationResponse.testGenerationJob().shortAnswer() != null ) {
201228 shortAnswer = parseShortAnswerString(testGenerationResponse.testGenerationJob().shortAnswer())
202229 if (shortAnswer.stopIteration == " true" ) {
203- throw Exception ( " ${shortAnswer.planSummary} " )
230+ throw CodeTestException ( " TestGenFailedError: ${shortAnswer.planSummary} " , " TestGenFailedError " , shortAnswer.planSummary )
204231 }
205232 codeTestChatHelper.updateAnswer(
206233 CodeTestChatMessageContent (
@@ -232,6 +259,11 @@ class CodeWhispererUTGChatManager(val project: Project, private val cs: Coroutin
232259 },
233260 { e ->
234261 LOG .error(e) { " ExportResultArchive failed: ${e.message} " }
262+ throw CodeTestException (
263+ " ExportResultsArchiveError: ${e.message} " ,
264+ " ExportResultsArchiveError" ,
265+ message(" testgen.error.generic_technical_error_message" )
266+ )
235267 },
236268 { startTime ->
237269 LOG .info { " ExportResultArchive latency: ${calculateTotalLatency(startTime, Instant .now())} " }
@@ -493,14 +525,16 @@ class CodeWhispererUTGChatManager(val project: Project, private val cs: Coroutin
493525 launchTestGenFlow(prompt, codeTestChatHelper, previousIterationContext, selectionRange)
494526 } catch (e: Exception ) {
495527 // Add an answer for displaying error message
496- var errorMessage = e.message
497- if (e is JsonParseException ) {
498- errorMessage = message(" testgen.error.generic_error_message" )
528+ val errorMessage = when {
529+ e is CodeTestException &&
530+ e.message?.startsWith(" CreateTestJobError: Maximum" ) == true ->
531+ message(" testgen.error.maximum_generations_reach" )
532+
533+ e is CodeTestException -> e.uiMessage
534+ e is JsonParseException -> message(" testgen.error.generic_technical_error_message" )
535+ else -> message(" testgen.error.generic_error_message" )
499536 }
500537
501- if (e is CodeWhispererRuntimeException ) {
502- errorMessage = message(" testgen.error.maximum_generations_reach" )
503- }
504538 codeTestChatHelper.addAnswer(
505539 CodeTestChatMessageContent (
506540 message = errorMessage,
@@ -518,8 +552,8 @@ class CodeWhispererUTGChatManager(val project: Project, private val cs: Coroutin
518552 jobGroup = session.testGenerationJobGroupName,
519553 jobId = session.testGenerationJob,
520554 result = if (e.message == message(" testgen.message.cancelled" )) MetricResult .Cancelled else MetricResult .Failed ,
521- reason = e.javaClass.name ,
522- reasonDesc = e.message,
555+ reason = (e as CodeTestException ).code ? : " DefaultError " ,
556+ reasonDesc = if (e.message == message( " testgen.message.cancelled " )) " ${e.code} : ${e.message} " else e.message,
523557 perfClientLatency = (Instant .now().toEpochMilli() - session.startTimeOfTestGeneration),
524558 isCodeBlockSelected = session.isCodeBlockSelected,
525559 artifactsUploadDuration = session.artifactUploadDuration,
0 commit comments