@@ -17,6 +17,7 @@ import io.micrometer.core.instrument.simple.SimpleMeterRegistry
1717import io.vertx.core.Vertx
1818import io.vertx.core.json.JsonObject
1919import io.vertx.junit5.VertxExtension
20+ import linea.kotlin.encodeHex
2021import net.consensys.linea.async.get
2122import net.consensys.linea.errors.ErrorResponse
2223import net.consensys.linea.jsonrpc.client.JsonRpcClient
@@ -500,4 +501,172 @@ class TracesGeneratorJsonRpcClientV2Test {
500501 assertThat(result.value.tracesCounters).isEqualTo(TracesCountersV2 .EMPTY_TRACES_COUNT )
501502 assertThat(result.value.tracesEngineVersion).isEqualTo(expectedTracesApiVersion)
502503 }
504+
505+ @Test
506+ fun generateVirtualBlockConflatedTracesToFile () {
507+ val blockNumber = 50L
508+
509+ val tracesEngineVersion = " 0.0.1"
510+ val conflatedTracesFileName =
511+ " $blockNumber .conflated.v$tracesEngineVersion .json.gz"
512+
513+ val response =
514+ JsonObject .of(
515+ " jsonrpc" ,
516+ " 2.0" ,
517+ " id" ,
518+ 1 ,
519+ " result" ,
520+ mapOf (
521+ " tracesEngineVersion" to tracesEngineVersion,
522+ " conflatedTracesFileName" to conflatedTracesFileName,
523+ ),
524+ )
525+
526+ wiremock.stubFor(
527+ post(" /" )
528+ .withHeader(" Content-Type" , containing(" application/json" ))
529+ .willReturn(
530+ ok()
531+ .withHeader(" Content-type" , " application/json" )
532+ .withBody(response.toString().toByteArray()),
533+ ),
534+ )
535+
536+ val queryBlockNumber = 50UL
537+ val queryTxn = Random .nextBytes(32 )
538+
539+ val resultFuture =
540+ tracesGeneratorClient.generateVirtualBlockConflatedTracesToFile(
541+ queryBlockNumber,
542+ queryTxn,
543+ )
544+ resultFuture.get()
545+
546+ assertThat(resultFuture)
547+ .isCompletedWithValue(
548+ Ok (GenerateTracesResponse (conflatedTracesFileName, tracesEngineVersion)),
549+ )
550+
551+ val expectedJsonRequest =
552+ JsonObject .of(
553+ " jsonrpc" ,
554+ " 2.0" ,
555+ " id" ,
556+ 1 ,
557+ " method" ,
558+ " linea_generateVirtualBlockConflatedTracesToFileV1" ,
559+ " params" ,
560+ listOf (
561+ JsonObject .of(
562+ " blockNumber" ,
563+ queryBlockNumber.toLong(),
564+ " txsRlpEncoded" ,
565+ listOf (queryTxn.encodeHex()),
566+ ),
567+ ),
568+ )
569+ wiremock.verify(
570+ postRequestedFor(urlEqualTo(" /" ))
571+ .withHeader(" Content-Type" , equalTo(" application/json" ))
572+ .withRequestBody(equalToJson(expectedJsonRequest.toString(), false , true )),
573+ )
574+ }
575+
576+ @Test
577+ fun error_generateVirtualConflatedTracesToFile () {
578+ val errorMessage = " Internal error!"
579+ val data = " BLOCK_MISSING_IN_CHAIN: Block 1 doesn't exist in the chain"
580+ val response = jsonRpcErrorResponse(errorMessage, data)
581+
582+ wiremock.stubFor(
583+ post(" /" )
584+ .withHeader(" Content-Type" , containing(" application/json" ))
585+ .willReturn(
586+ ok()
587+ .withHeader(" Content-type" , " application/json" )
588+ .withBody(response.toString().toByteArray()),
589+ ),
590+ )
591+
592+ val queryBlockNumber = 1UL
593+ val queryTxn = Random .nextBytes(32 )
594+ val resultFuture =
595+ tracesGeneratorClient.generateVirtualBlockConflatedTracesToFile(
596+ queryBlockNumber,
597+ queryTxn,
598+ )
599+ resultFuture.get()
600+
601+ assertThat(resultFuture)
602+ .isCompletedWithValue(
603+ Err (ErrorResponse (TracesServiceErrorType .BLOCK_MISSING_IN_CHAIN , errorMessage)),
604+ )
605+ }
606+
607+ @Test
608+ fun error_generateVirtualBlockConflatedTracesToFile_retriesRequest () {
609+ val tracesEngineVersion = " 0.0.1"
610+ val errorMessage = " Internal error!"
611+ val data = " BLOCK_MISSING_IN_CHAIN: Block 1 doesn't exist in the chain"
612+ val jsonRpcErrorResponse = jsonRpcErrorResponse(errorMessage, data)
613+ wiremock.stubFor(
614+ post(" /" )
615+ .inScenario(" retry" )
616+ .whenScenarioStateIs(STARTED )
617+ .willSetStateTo(" first failure" )
618+ .withHeader(" Content-Type" , containing(" application/json" ))
619+ .willReturn(
620+ aResponse()
621+ .withStatus(500 )
622+ .withBody(" Internal Server Error" ),
623+ ),
624+ )
625+ wiremock.stubFor(
626+ post(" /" )
627+ .inScenario(" retry" )
628+ .whenScenarioStateIs(" first failure" )
629+ .willSetStateTo(" second failure" )
630+ .withHeader(" Content-Type" , containing(" application/json" ))
631+ .willReturn(
632+ aResponse()
633+ .withStatus(200 )
634+ .withBody(jsonRpcErrorResponse.toString()),
635+ ),
636+ )
637+ wiremock.stubFor(
638+ post(" /" )
639+ .inScenario(" retry" )
640+ .whenScenarioStateIs(" second failure" )
641+ .willSetStateTo(" success" )
642+ .withHeader(" Content-Type" , containing(" application/json" ))
643+ .willReturn(
644+ ok()
645+ .withHeader(" Content-type" , " application/json" )
646+ .withBody(
647+ JsonObject .of(
648+ " jsonrpc" ,
649+ " 2.0" ,
650+ " id" ,
651+ 1 ,
652+ " result" ,
653+ mapOf (
654+ " tracesEngineVersion" to tracesEngineVersion,
655+ " conflatedTracesFileName" to " conflated-traces-1.json" ,
656+ ),
657+ ).toString(),
658+ ),
659+ ),
660+ )
661+
662+ val queryBlockNumber = 1UL
663+ val queryTxn = Random .nextBytes(32 )
664+ val resultFuture =
665+ tracesGeneratorClient.generateVirtualBlockConflatedTracesToFile(
666+ queryBlockNumber,
667+ queryTxn,
668+ )
669+
670+ assertThat(resultFuture.get()).isInstanceOf(Ok ::class .java)
671+ }
503672}
0 commit comments