@@ -9,7 +9,9 @@ import dev.mokkery.spy
99import dev.mokkery.verify
1010import dev.mokkery.verify.VerifyMode.Companion.exactly
1111import dev.mokkery.verify.VerifyMode.Companion.not
12+ import dev.mokkery.verify.VerifyMode.Companion.order
1213import dev.mokkery.verifySuspend
14+ import io.github.trueangle.knative.lambda.runtime.LambdaEnvironmentException.*
1315import io.github.trueangle.knative.lambda.runtime.LambdaRuntimeException.Invocation.EventBodyParseException
1416import io.github.trueangle.knative.lambda.runtime.LambdaRuntimeException.Invocation.HandlerException
1517import io.github.trueangle.knative.lambda.runtime.ReservedRuntimeEnvironmentVariables.AWS_LAMBDA_FUNCTION_NAME
@@ -191,7 +193,7 @@ class LambdaRuntimeTest {
191193 }
192194
193195 @Test
194- fun `GIVEN api error WHEN retrieveNextEvent THEN terminate` () = runTest {
196+ fun `GIVEN env api error WHEN retrieveNextEvent THEN terminate` () = runTest {
195197 val lambdaRunner = createRunner(MockEngine { request ->
196198 val path = request.url.encodedPath
197199 when {
@@ -213,6 +215,75 @@ class LambdaRuntimeTest {
213215 verify { log.log(FATAL , any<Any >(), any()) }
214216 }
215217
218+ @Test
219+ fun `GIVEN bad request from env api WHEN sendResponse THEN skip event` () = runTest {
220+ val lambdaRunner = createRunner(MockEngine { request ->
221+ val path = request.url.encodedPath
222+ when {
223+ path.contains(" invocation/next" ) -> respondNextEventSuccess(" " )
224+ path.contains(" ${context.awsRequestId} /response" ) -> respondError(HttpStatusCode .BadGateway )
225+ else -> respondBadRequest()
226+ }
227+ })
228+ val client = lambdaRunner.client
229+ val handler = object : LambdaBufferedHandler <String , String > {
230+ override suspend fun handleRequest (input : String , context : Context ) = throw RuntimeException ()
231+ }
232+
233+ lambdaRunner.run (singleEventMode = true ) { handler }
234+
235+ verifySuspend { client.reportError(any<HandlerException >()) }
236+ verify(order) { log.log(ERROR , any<HandlerException >(), any()) }
237+ verify(order) { log.log(ERROR , any<BadRequestException >(), any()) }
238+ verify(not ) { log.log(FATAL , any<Any >(), any()) }
239+ verify(not ) { lambdaRunner.env.terminate() }
240+ }
241+
242+ @Test
243+ fun `GIVEN unknown http error from env api WHEN reportError THEN skip event` () = runTest {
244+ val lambdaRunner = createRunner(MockEngine { request ->
245+ val path = request.url.encodedPath
246+ when {
247+ path.contains(" invocation/next" ) -> respondNextEventSuccess(" " )
248+ else -> respondBadRequest()
249+ }
250+ })
251+ val client = lambdaRunner.client
252+ val handler = object : LambdaBufferedHandler <String , String > {
253+ override suspend fun handleRequest (input : String , context : Context ) = throw RuntimeException ()
254+ }
255+
256+ lambdaRunner.run (singleEventMode = true ) { handler }
257+
258+ verifySuspend { client.reportError(any<HandlerException >()) }
259+ verify(order) { log.log(ERROR , any<HandlerException >(), any()) }
260+ verify(order) { log.log(ERROR , any<BadRequestException >(), any()) }
261+ verify(not ) { log.log(FATAL , any<Any >(), any()) }
262+ verify(not ) { lambdaRunner.env.terminate() }
263+ }
264+
265+ @Test
266+ fun `GIVEN internal server error from env api WHEN reportError THEN terminate` () = runTest {
267+ val lambdaRunner = createRunner(MockEngine { request ->
268+ val path = request.url.encodedPath
269+ when {
270+ path.contains(" invocation/next" ) -> respondNextEventSuccess(" " )
271+ path.contains(" ${context.awsRequestId} /error" ) -> respondError(HttpStatusCode .InternalServerError )
272+ else -> respondBadRequest()
273+ }
274+ })
275+ val client = lambdaRunner.client
276+ val handler = object : LambdaBufferedHandler <String , String > {
277+ override suspend fun handleRequest (input : String , context : Context ) = throw RuntimeException ()
278+ }
279+
280+ assertFailsWith<TerminateException > { lambdaRunner.run (singleEventMode = true ) { handler } }
281+ verifySuspend { client.reportError(any<HandlerException >()) }
282+ verify { log.log(ERROR , any<HandlerException >(), any()) }
283+ verify { log.log(FATAL , any<NonRecoverableStateException >(), any()) }
284+ verify { lambdaRunner.env.terminate() }
285+ }
286+
216287 @Test
217288 fun `GIVEN EventBodyParseException WHEN retrieveNextEvent THEN report error AND skip event` () = runTest {
218289 val event = NonSerialObject (" " )
@@ -238,7 +309,7 @@ class LambdaRuntimeTest {
238309 }
239310
240311 @Test
241- fun `GIVEN Handler exception WHEN handleRequest THEN report error AND skip event` () = runTest {
312+ fun `GIVEN Handler exception WHEN invoke handler THEN report error AND skip event` () = runTest {
242313 val lambdaRunner = createRunner(MockEngine { request ->
243314 val path = request.url.encodedPath
244315 when {
@@ -261,7 +332,7 @@ class LambdaRuntimeTest {
261332 }
262333
263334 @Test
264- fun `GIVEN Handler exception WHEN streamingResponse THEN consume error` () = runTest {
335+ fun `GIVEN Handler exception WHEN invoke streaming handler THEN consume error` () = runTest {
265336 val lambdaRunner = createRunner(MockEngine { request ->
266337 val path = request.url.encodedPath
267338 when {
0 commit comments