2323import java .util .concurrent .atomic .AtomicBoolean ;
2424import java .util .concurrent .atomic .AtomicInteger ;
2525import java .util .concurrent .atomic .AtomicReference ;
26- import java .util .stream .Stream ;
2726import java .util .function .BiConsumer ;
2827import java .util .function .Consumer ;
2928
30- import jakarta .ws .rs .core .MediaType ;
31-
32- import com .fasterxml .jackson .core .JsonProcessingException ;
33-
3429import io .a2a .client .Client ;
3530import io .a2a .client .ClientEvent ;
3631import io .a2a .client .ClientFactory ;
3732import io .a2a .client .MessageEvent ;
3833import io .a2a .client .TaskUpdateEvent ;
3934import io .a2a .client .config .ClientConfig ;
4035import io .a2a .client .config .ClientTransportConfig ;
41- import io .a2a .client .transport .jsonrpc .JSONRPCTransportConfig ;
42- import io .a2a .client .transport .grpc .GrpcTransportConfig ;
43- import io .a2a .client .http .JdkA2AHttpClient ;
44- import io .grpc .ManagedChannelBuilder ;
4536import io .a2a .spec .A2AClientException ;
4637import io .a2a .spec .AgentCard ;
4738import io .a2a .spec .AgentCapabilities ;
4839import io .a2a .spec .AgentInterface ;
49- import io .a2a .spec .TransportProtocol ;
5040import io .a2a .spec .Artifact ;
5141import io .a2a .spec .DeleteTaskPushNotificationConfigParams ;
5242import io .a2a .spec .Event ;
53- import io .a2a .spec .GetAuthenticatedExtendedCardRequest ;
54- import io .a2a .spec .GetAuthenticatedExtendedCardResponse ;
5543import io .a2a .spec .GetTaskPushNotificationConfigParams ;
5644import io .a2a .spec .ListTaskPushNotificationConfigParams ;
5745import io .a2a .spec .Message ;
58- import io .a2a .spec .MessageSendParams ;
5946import io .a2a .spec .Part ;
6047import io .a2a .spec .PushNotificationConfig ;
61- import io .a2a .spec .SendStreamingMessageRequest ;
62- import io .a2a .spec .SendStreamingMessageResponse ;
63- import io .a2a .spec .StreamingJSONRPCRequest ;
6448import io .a2a .spec .Task ;
6549import io .a2a .spec .TaskArtifactUpdateEvent ;
6650import io .a2a .spec .TaskIdParams ;
7458import io .a2a .spec .UnsupportedOperationError ;
7559import io .a2a .util .Utils ;
7660
77- import org .junit .jupiter .api .Assertions ;
78- import org .junit .jupiter .api .Assumptions ;
7961import org .junit .jupiter .api .Test ;
8062import org .junit .jupiter .api .Timeout ;
8163
@@ -109,14 +91,14 @@ public abstract class AbstractA2AServerTest {
10991 .status (new TaskStatus (TaskState .SUBMITTED ))
11092 .build ();
11193
112- private static final Message MESSAGE = new Message .Builder ()
94+ protected static final Message MESSAGE = new Message .Builder ()
11395 .messageId ("111" )
11496 .role (Message .Role .AGENT )
11597 .parts (new TextPart ("test message" ))
11698 .build ();
11799 public static final String APPLICATION_JSON = "application/json" ;
118100
119- private final int serverPort ;
101+ protected final int serverPort ;
120102 private Client client ;
121103 private Client nonStreamingClient ;
122104
@@ -586,72 +568,6 @@ public void testResubscribeNoExistingTaskError() throws Exception {
586568 }
587569 }
588570
589- @ Test
590- public void testStreamingMethodWithAcceptHeader () throws Exception {
591- // Skip this test for gRPC transport as it uses HTTP SSE which is JSONRPC-specific
592- Assumptions .assumeTrue (TransportProtocol .JSONRPC .asString ().equals (getTransportProtocol ()),
593- "HTTP streaming tests are only supported for JSONRPC transport" );
594- testSendStreamingMessage (MediaType .SERVER_SENT_EVENTS );
595- }
596-
597- @ Test
598- public void testSendMessageStreamNewMessageSuccess () throws Exception {
599- // Skip this test for gRPC transport as it uses HTTP SSE which is JSONRPC-specific
600- Assumptions .assumeTrue (TransportProtocol .JSONRPC .asString ().equals (getTransportProtocol ()),
601- "HTTP streaming tests are only supported for JSONRPC transport" );
602- testSendStreamingMessage (null );
603- }
604-
605- private void testSendStreamingMessage (String mediaType ) throws Exception {
606- Message message = new Message .Builder (MESSAGE )
607- .taskId (MINIMAL_TASK .getId ())
608- .contextId (MINIMAL_TASK .getContextId ())
609- .build ();
610- SendStreamingMessageRequest request = new SendStreamingMessageRequest (
611- "1" , new MessageSendParams (message , null , null ));
612-
613- CompletableFuture <HttpResponse <Stream <String >>> responseFuture = initialiseStreamingRequest (request , mediaType );
614-
615- CountDownLatch latch = new CountDownLatch (1 );
616- AtomicReference <Throwable > errorRef = new AtomicReference <>();
617-
618- responseFuture .thenAccept (response -> {
619- if (response .statusCode () != 200 ) {
620- //errorRef.set(new IllegalStateException("Status code was " + response.statusCode()));
621- throw new IllegalStateException ("Status code was " + response .statusCode ());
622- }
623- response .body ().forEach (line -> {
624- try {
625- SendStreamingMessageResponse jsonResponse = extractJsonResponseFromSseLine (line );
626- if (jsonResponse != null ) {
627- assertNull (jsonResponse .getError ());
628- Message messageResponse = (Message ) jsonResponse .getResult ();
629- assertEquals (MESSAGE .getMessageId (), messageResponse .getMessageId ());
630- assertEquals (MESSAGE .getRole (), messageResponse .getRole ());
631- Part <?> part = messageResponse .getParts ().get (0 );
632- assertEquals (Part .Kind .TEXT , part .getKind ());
633- assertEquals ("test message" , ((TextPart ) part ).getText ());
634- latch .countDown ();
635- }
636- } catch (JsonProcessingException e ) {
637- throw new RuntimeException (e );
638- }
639- });
640- }).exceptionally (t -> {
641- if (!isStreamClosedError (t )) {
642- errorRef .set (t );
643- }
644- latch .countDown ();
645- return null ;
646- });
647-
648-
649- boolean dataRead = latch .await (20 , TimeUnit .SECONDS );
650- Assertions .assertTrue (dataRead );
651- Assertions .assertNull (errorRef .get ());
652-
653- }
654-
655571 @ Test
656572 public void testListPushNotificationConfigWithConfigId () throws Exception {
657573 saveTaskInTaskStore (MINIMAL_TASK );
@@ -871,23 +787,7 @@ public void testDeletePushNotificationConfigSetWithoutConfigId() throws Exceptio
871787 }
872788 }
873789
874- private SendStreamingMessageResponse extractJsonResponseFromSseLine (String line ) throws JsonProcessingException {
875- line = extractSseData (line );
876- if (line != null ) {
877- return Utils .OBJECT_MAPPER .readValue (line , SendStreamingMessageResponse .class );
878- }
879- return null ;
880- }
881-
882- private static String extractSseData (String line ) {
883- if (line .startsWith ("data:" )) {
884- line = line .substring (5 ).trim ();
885- return line ;
886- }
887- return null ;
888- }
889-
890- private boolean isStreamClosedError (Throwable throwable ) {
790+ protected boolean isStreamClosedError (Throwable throwable ) {
891791 // Unwrap the CompletionException
892792 Throwable cause = throwable ;
893793
@@ -900,29 +800,6 @@ private boolean isStreamClosedError(Throwable throwable) {
900800 return false ;
901801 }
902802
903- private CompletableFuture <HttpResponse <Stream <String >>> initialiseStreamingRequest (
904- StreamingJSONRPCRequest <?> request , String mediaType ) throws Exception {
905-
906- // Create the client
907- HttpClient client = HttpClient .newBuilder ()
908- .version (HttpClient .Version .HTTP_2 )
909- .build ();
910-
911- // Create the request
912- HttpRequest .Builder builder = HttpRequest .newBuilder ()
913- .uri (URI .create ("http://localhost:" + serverPort + "/" ))
914- .POST (HttpRequest .BodyPublishers .ofString (Utils .OBJECT_MAPPER .writeValueAsString (request )))
915- .header ("Content-Type" , APPLICATION_JSON );
916- if (mediaType != null ) {
917- builder .header ("Accept" , mediaType );
918- }
919- HttpRequest httpRequest = builder .build ();
920-
921-
922- // Send request async and return the CompletableFuture
923- return client .sendAsync (httpRequest , HttpResponse .BodyHandlers .ofLines ());
924- }
925-
926803 protected void saveTaskInTaskStore (Task task ) throws Exception {
927804 HttpClient client = HttpClient .newBuilder ()
928805 .version (HttpClient .Version .HTTP_2 )
0 commit comments