From 4ec1325e701664cf047410c55db73eb37e296d17 Mon Sep 17 00:00:00 2001 From: Pilli Vamshi Date: Wed, 4 Dec 2024 18:04:29 +0530 Subject: [PATCH 1/4] Added custom calling context in answer api. --- .../CallAutomationAsyncClient.java | 9 +++++++++ .../models/AnswerCallOptions.java | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallAutomationAsyncClient.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallAutomationAsyncClient.java index 7364c21e4f76..a14945eda163 100644 --- a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallAutomationAsyncClient.java +++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallAutomationAsyncClient.java @@ -55,8 +55,10 @@ import reactor.core.publisher.Mono; import java.net.URISyntaxException; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import static com.azure.core.util.FluxUtil.monoError; @@ -395,6 +397,13 @@ Mono> answerCallWithResponseInternal(AnswerCallOption = getTranscriptionConfigurationInternal(answerCallOptions.getTranscriptionConfiguration()); request.setTranscriptionConfiguration(transcriptionConfigurationInternal); } + if (answerCallOptions.getCustomCallingContext().getSipHeaders() != null + || answerCallOptions.getCustomCallingContext().getVoipHeaders() != null) { + CustomCallingContext customContext = new CustomCallingContext(); + customContext.setSipHeaders(answerCallOptions.getCustomCallingContext().getSipHeaders()); + customContext.setVoipHeaders(answerCallOptions.getCustomCallingContext().getVoipHeaders()); + request.setCustomCallingContext(customContext); + } return azureCommunicationCallAutomationServiceInternal.answerCallWithResponseAsync(request, context) .map(response -> { diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/models/AnswerCallOptions.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/models/AnswerCallOptions.java index 0905727a284e..bf5db17d1776 100644 --- a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/models/AnswerCallOptions.java +++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/models/AnswerCallOptions.java @@ -3,6 +3,8 @@ package com.azure.communication.callautomation.models; +import java.util.HashMap; + import com.azure.core.annotation.Fluent; /** @@ -40,6 +42,11 @@ public final class AnswerCallOptions { */ private String operationContext; + /* + * Used by customer to send custom calling context to targets when answering On-Behalf-Of call + */ + private CustomCallingContext customCallingContext; + /** * Constructor * @@ -49,6 +56,7 @@ public final class AnswerCallOptions { public AnswerCallOptions(String incomingCallContext, String callbackUrl) { this.incomingCallContext = incomingCallContext; this.callbackUrl = callbackUrl; + this.customCallingContext = new CustomCallingContext(new HashMap(), new HashMap()); } /** @@ -148,4 +156,13 @@ public AnswerCallOptions setMediaStreamingConfiguration(MediaStreamingOptions me this.mediaStreamingOptions = mediaStreamingOptions; return this; } + + /** + * Get the Custom Calling Context. + * + * @return the customCallingContext. + */ + public CustomCallingContext getCustomCallingContext() { + return customCallingContext; + } } From 32c5654218b2650db3ef0dab03be0ee8c30e287e Mon Sep 17 00:00:00 2001 From: Pilli Vamshi Date: Thu, 5 Dec 2024 19:02:00 +0530 Subject: [PATCH 2/4] Added live and unit tests. --- ...tomationAsyncClientAutomatedLiveTests.java | 118 ++++++++++++++++++ .../CallAutomationAsyncClientUnitTests.java | 23 ++++ 2 files changed, 141 insertions(+) diff --git a/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientAutomatedLiveTests.java b/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientAutomatedLiveTests.java index fe7d182dacde..8cffb818f992 100644 --- a/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientAutomatedLiveTests.java +++ b/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientAutomatedLiveTests.java @@ -3,6 +3,7 @@ package com.azure.communication.callautomation; +import com.azure.communication.callautomation.implementation.models.CustomCallingContext; import com.azure.communication.callautomation.models.AnswerCallOptions; import com.azure.communication.callautomation.models.AnswerCallResult; import com.azure.communication.callautomation.models.CreateCallResult; @@ -211,4 +212,121 @@ public void createVOIPCallAndRejectAutomatedTest(HttpClient httpClient) { fail("Unexpected exception received", ex); } } + + @DoNotRecord(skipInPlayback = true) + @ParameterizedTest + @MethodSource("com.azure.core.test.TestBase#getHttpClients") + @DisabledIfEnvironmentVariable( + named = "SKIP_LIVE_TEST", + matches = "(?i)(true)", + disabledReason = "Requires environment to be set up") + public void createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest(HttpClient httpClient) { + /* Test case: ACS to ACS call + * 1. create a CallAutomationClient. + * 2. create a call from source to one ACS target. + * 3. get updated call properties and check for the connected state. + * 4. hang up the call. + * 5. once call is hung up, verify disconnected event + */ + + CommunicationIdentityAsyncClient identityAsyncClient + = getCommunicationIdentityClientUsingConnectionString(httpClient) + .addPolicy((context, next) -> logHeaders("createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest", next)) + .buildAsyncClient(); + + List callDestructors = new ArrayList<>(); + + try { + // create caller and receiver + CommunicationUserIdentifier caller = identityAsyncClient.createUser().block(); + CommunicationIdentifier target = identityAsyncClient.createUser().block(); + + // Create call automation client and use source as the caller. + CallAutomationAsyncClient callerAsyncClient = getCallAutomationClientUsingConnectionString(httpClient) + .addPolicy((context, next) -> logHeaders("createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest", next)) + .sourceIdentity(caller) + .buildAsyncClient(); + // Create call automation client for receivers. + CallAutomationAsyncClient receiverAsyncClient = getCallAutomationClientUsingConnectionString(httpClient) + .addPolicy((context, next) -> logHeaders("createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest", next)) + .buildAsyncClient(); + + String uniqueId = serviceBusWithNewCall(caller, target); + + // create a call + List targets = new ArrayList<>(Collections.singletonList(target)); + CreateGroupCallOptions createCallOptions + = new CreateGroupCallOptions(targets, DISPATCHER_CALLBACK + String.format("?q=%s", uniqueId)); + Response createCallResultResponse + = callerAsyncClient.createGroupCallWithResponse(createCallOptions).block(); + + assertNotNull(createCallResultResponse); + CreateCallResult createCallResult = createCallResultResponse.getValue(); + assertNotNull(createCallResult); + assertNotNull(createCallResult.getCallConnectionProperties()); + String callerConnectionId = createCallResult.getCallConnectionProperties().getCallConnectionId(); + assertNotNull(callerConnectionId); + + // wait for the incomingCallContext + String incomingCallContext = waitForIncomingCallContext(uniqueId, Duration.ofSeconds(10)); + assertNotNull(incomingCallContext); + + // answer the call + AnswerCallOptions answerCallOptions + = new AnswerCallOptions(incomingCallContext, DISPATCHER_CALLBACK + String.format("?q=%s", uniqueId)); + if (answerCallOptions.getCustomCallingContext().getSipHeaders() != null + || answerCallOptions.getCustomCallingContext().getVoipHeaders() != null) { + CustomCallingContext customContext = new CustomCallingContext(); + customContext.setSipHeaders(answerCallOptions.getCustomCallingContext().getSipHeaders()); + customContext.setVoipHeaders(answerCallOptions.getCustomCallingContext().getVoipHeaders()); + } + AnswerCallResult answerCallResult + = Objects.requireNonNull(receiverAsyncClient.answerCallWithResponse(answerCallOptions).block()) + .getValue(); + assertNotNull(answerCallResult); + assertNotNull(answerCallResult.getCallConnectionAsync()); + assertNotNull(answerCallResult.getCallConnectionProperties()); + String receiverConnectionId = answerCallResult.getCallConnectionProperties().getCallConnectionId(); + callDestructors.add(answerCallResult.getCallConnectionAsync()); + + // check events to caller side + CallConnected callerCallConnected + = waitForEvent(CallConnected.class, callerConnectionId, Duration.ofSeconds(10)); + ParticipantsUpdated callerParticipantUpdatedEvent + = waitForEvent(ParticipantsUpdated.class, callerConnectionId, Duration.ofSeconds(10)); + assertNotNull(callerCallConnected); + assertNotNull(callerParticipantUpdatedEvent); + + // check events to receiver side + CallConnected receiverCallConnected + = waitForEvent(CallConnected.class, receiverConnectionId, Duration.ofSeconds(10)); + ParticipantsUpdated receiverParticipantUpdatedEvent + = waitForEvent(ParticipantsUpdated.class, callerConnectionId, Duration.ofSeconds(10)); + assertNotNull(receiverCallConnected); + assertNotNull(receiverParticipantUpdatedEvent); + + // hang up the call. + answerCallResult.getCallConnectionAsync().hangUp(true).block(); + + // check if both parties had the call terminated. + CallDisconnected callerCallDisconnected + = waitForEvent(CallDisconnected.class, receiverConnectionId, Duration.ofSeconds(10)); + CallDisconnected receiverCallDisconnected + = waitForEvent(CallDisconnected.class, callerConnectionId, Duration.ofSeconds(10)); + assertNotNull(callerCallDisconnected); + assertNotNull(receiverCallDisconnected); + + } catch (Exception ex) { + fail("Unexpected exception received", ex); + } finally { + if (!callDestructors.isEmpty()) { + try { + callDestructors.forEach(callConnection -> callConnection.hangUpWithResponse(true).block()); + } catch (Exception ignored) { + // Some call might have been terminated during the test, and it will cause exceptions here. + // Do nothing and iterate to next call connection. + } + } + } + } } diff --git a/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientUnitTests.java b/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientUnitTests.java index e0a4fd89412a..c441f814dc12 100644 --- a/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientUnitTests.java +++ b/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientUnitTests.java @@ -133,6 +133,29 @@ public void answerCall() { assertNotNull(answerCallResult); } + @Test + public void answerCallWithResponseAndCustomContext() { + CallAutomationAsyncClient callAutomationAsyncClient = getCallAutomationAsyncClient(new ArrayList<>( + Collections.singletonList(new AbstractMap.SimpleEntry<>(generateCallProperties(CALL_CONNECTION_ID, + CALL_SERVER_CALL_ID, CALL_CALLER_ID, CALL_CALLER_DISPLAY_NAME, CALL_TARGET_ID, CALL_CONNECTION_STATE, + CALL_SUBJECT, CALL_CALLBACK_URL, MEDIA_SUBSCRIPTION_ID, DATA_SUBSCRIPTION_ID), 200)))); + + AnswerCallOptions answerCallOptions = new AnswerCallOptions(CALL_INCOMING_CALL_CONTEXT, CALL_CALLBACK_URL) + .setMediaStreamingConfiguration(MEDIA_STREAMING_CONFIGURATION) + .setTranscriptionConfiguration(TRANSCRIPTION_CONFIGURATION); + + Response answerCallResult + = callAutomationAsyncClient.answerCallWithResponse(answerCallOptions).block(); + + assertNotNull(answerCallResult); + assertEquals(200, answerCallResult.getStatusCode()); + assertNotNull(answerCallResult.getValue()); + assertEquals(MEDIA_SUBSCRIPTION_ID, + answerCallResult.getValue().getCallConnectionProperties().getMediaSubscriptionId()); + assertEquals(DATA_SUBSCRIPTION_ID, + answerCallResult.getValue().getCallConnectionProperties().getDataSubscriptionId()); + } + @Test public void answerCallWithResponse() { CallAutomationAsyncClient callAutomationAsyncClient = getCallAutomationAsyncClient(new ArrayList<>( From 874c727e75c772d8fed3c82988f594f68307c0e4 Mon Sep 17 00:00:00 2001 From: Pilli Vamshi Date: Fri, 27 Dec 2024 16:56:10 +0530 Subject: [PATCH 3/4] resolved buld issues. --- .../CallAutomationAsyncClient.java | 14 +- .../models/AnswerCallOptions.java | 16 +- ...tomationAsyncClientAutomatedLiveTests.java | 198 +++++++++--------- .../CallAutomationAsyncClientUnitTests.java | 2 + 4 files changed, 114 insertions(+), 116 deletions(-) diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallAutomationAsyncClient.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallAutomationAsyncClient.java index a14945eda163..b6ed1de56ceb 100644 --- a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallAutomationAsyncClient.java +++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallAutomationAsyncClient.java @@ -55,10 +55,8 @@ import reactor.core.publisher.Mono; import java.net.URISyntaxException; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; import static com.azure.core.util.FluxUtil.monoError; @@ -398,12 +396,12 @@ Mono> answerCallWithResponseInternal(AnswerCallOption request.setTranscriptionConfiguration(transcriptionConfigurationInternal); } if (answerCallOptions.getCustomCallingContext().getSipHeaders() != null - || answerCallOptions.getCustomCallingContext().getVoipHeaders() != null) { - CustomCallingContext customContext = new CustomCallingContext(); - customContext.setSipHeaders(answerCallOptions.getCustomCallingContext().getSipHeaders()); - customContext.setVoipHeaders(answerCallOptions.getCustomCallingContext().getVoipHeaders()); - request.setCustomCallingContext(customContext); - } + || answerCallOptions.getCustomCallingContext().getVoipHeaders() != null) { + CustomCallingContext customContext = new CustomCallingContext(); + customContext.setSipHeaders(answerCallOptions.getCustomCallingContext().getSipHeaders()); + customContext.setVoipHeaders(answerCallOptions.getCustomCallingContext().getVoipHeaders()); + request.setCustomCallingContext(customContext); + } return azureCommunicationCallAutomationServiceInternal.answerCallWithResponseAsync(request, context) .map(response -> { diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/models/AnswerCallOptions.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/models/AnswerCallOptions.java index bf5db17d1776..5e9d29f36423 100644 --- a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/models/AnswerCallOptions.java +++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/models/AnswerCallOptions.java @@ -42,10 +42,10 @@ public final class AnswerCallOptions { */ private String operationContext; - /* - * Used by customer to send custom calling context to targets when answering On-Behalf-Of call + /** + * Custom Context */ - private CustomCallingContext customCallingContext; + private final CustomCallingContext customCallingContext; /** * Constructor @@ -56,7 +56,8 @@ public final class AnswerCallOptions { public AnswerCallOptions(String incomingCallContext, String callbackUrl) { this.incomingCallContext = incomingCallContext; this.callbackUrl = callbackUrl; - this.customCallingContext = new CustomCallingContext(new HashMap(), new HashMap()); + this.customCallingContext + = new CustomCallingContext(new HashMap(), new HashMap()); } /** @@ -157,10 +158,9 @@ public AnswerCallOptions setMediaStreamingConfiguration(MediaStreamingOptions me return this; } - /** - * Get the Custom Calling Context. - * - * @return the customCallingContext. + /** + * get custom context + * @return custom context */ public CustomCallingContext getCustomCallingContext() { return customCallingContext; diff --git a/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientAutomatedLiveTests.java b/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientAutomatedLiveTests.java index 8cffb818f992..39bd04ac478d 100644 --- a/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientAutomatedLiveTests.java +++ b/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientAutomatedLiveTests.java @@ -3,7 +3,6 @@ package com.azure.communication.callautomation; -import com.azure.communication.callautomation.implementation.models.CustomCallingContext; import com.azure.communication.callautomation.models.AnswerCallOptions; import com.azure.communication.callautomation.models.AnswerCallResult; import com.azure.communication.callautomation.models.CreateCallResult; @@ -212,7 +211,7 @@ public void createVOIPCallAndRejectAutomatedTest(HttpClient httpClient) { fail("Unexpected exception received", ex); } } - + @DoNotRecord(skipInPlayback = true) @ParameterizedTest @MethodSource("com.azure.core.test.TestBase#getHttpClients") @@ -229,104 +228,103 @@ public void createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest(Http * 5. once call is hung up, verify disconnected event */ - CommunicationIdentityAsyncClient identityAsyncClient - = getCommunicationIdentityClientUsingConnectionString(httpClient) - .addPolicy((context, next) -> logHeaders("createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest", next)) - .buildAsyncClient(); - - List callDestructors = new ArrayList<>(); - - try { - // create caller and receiver - CommunicationUserIdentifier caller = identityAsyncClient.createUser().block(); - CommunicationIdentifier target = identityAsyncClient.createUser().block(); - - // Create call automation client and use source as the caller. - CallAutomationAsyncClient callerAsyncClient = getCallAutomationClientUsingConnectionString(httpClient) - .addPolicy((context, next) -> logHeaders("createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest", next)) - .sourceIdentity(caller) - .buildAsyncClient(); - // Create call automation client for receivers. - CallAutomationAsyncClient receiverAsyncClient = getCallAutomationClientUsingConnectionString(httpClient) - .addPolicy((context, next) -> logHeaders("createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest", next)) - .buildAsyncClient(); - - String uniqueId = serviceBusWithNewCall(caller, target); - - // create a call - List targets = new ArrayList<>(Collections.singletonList(target)); - CreateGroupCallOptions createCallOptions - = new CreateGroupCallOptions(targets, DISPATCHER_CALLBACK + String.format("?q=%s", uniqueId)); - Response createCallResultResponse - = callerAsyncClient.createGroupCallWithResponse(createCallOptions).block(); - - assertNotNull(createCallResultResponse); - CreateCallResult createCallResult = createCallResultResponse.getValue(); - assertNotNull(createCallResult); - assertNotNull(createCallResult.getCallConnectionProperties()); - String callerConnectionId = createCallResult.getCallConnectionProperties().getCallConnectionId(); - assertNotNull(callerConnectionId); - - // wait for the incomingCallContext - String incomingCallContext = waitForIncomingCallContext(uniqueId, Duration.ofSeconds(10)); - assertNotNull(incomingCallContext); - - // answer the call - AnswerCallOptions answerCallOptions - = new AnswerCallOptions(incomingCallContext, DISPATCHER_CALLBACK + String.format("?q=%s", uniqueId)); - if (answerCallOptions.getCustomCallingContext().getSipHeaders() != null - || answerCallOptions.getCustomCallingContext().getVoipHeaders() != null) { - CustomCallingContext customContext = new CustomCallingContext(); - customContext.setSipHeaders(answerCallOptions.getCustomCallingContext().getSipHeaders()); - customContext.setVoipHeaders(answerCallOptions.getCustomCallingContext().getVoipHeaders()); + CommunicationIdentityAsyncClient identityAsyncClient + = getCommunicationIdentityClientUsingConnectionString(httpClient).addPolicy( + (context, next) -> logHeaders("createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest", next)) + .buildAsyncClient(); + + List callDestructors = new ArrayList<>(); + + try { + // create caller and receiver + CommunicationUserIdentifier caller = identityAsyncClient.createUser().block(); + CommunicationIdentifier target = identityAsyncClient.createUser().block(); + + // Create call automation client and use source as the caller. + CallAutomationAsyncClient callerAsyncClient = getCallAutomationClientUsingConnectionString(httpClient) + .addPolicy((context, + next) -> logHeaders("createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest", next)) + .sourceIdentity(caller) + .buildAsyncClient(); + // Create call automation client for receivers. + CallAutomationAsyncClient receiverAsyncClient = getCallAutomationClientUsingConnectionString(httpClient) + .addPolicy((context, + next) -> logHeaders("createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest", next)) + .buildAsyncClient(); + + String uniqueId = serviceBusWithNewCall(caller, target); + + // create a call + List targets = new ArrayList<>(Collections.singletonList(target)); + CreateGroupCallOptions createCallOptions + = new CreateGroupCallOptions(targets, DISPATCHER_CALLBACK + String.format("?q=%s", uniqueId)); + Response createCallResultResponse + = callerAsyncClient.createGroupCallWithResponse(createCallOptions).block(); + + assertNotNull(createCallResultResponse); + CreateCallResult createCallResult = createCallResultResponse.getValue(); + assertNotNull(createCallResult); + assertNotNull(createCallResult.getCallConnectionProperties()); + String callerConnectionId = createCallResult.getCallConnectionProperties().getCallConnectionId(); + assertNotNull(callerConnectionId); + + // wait for the incomingCallContext + String incomingCallContext = waitForIncomingCallContext(uniqueId, Duration.ofSeconds(10)); + assertNotNull(incomingCallContext); + + // answer the call + AnswerCallOptions answerCallOptions + = new AnswerCallOptions(incomingCallContext, DISPATCHER_CALLBACK + String.format("?q=%s", uniqueId)); + answerCallOptions.getCustomCallingContext().addSipUui("OBOuuivalue"); + answerCallOptions.getCustomCallingContext().addSipX("XheaderOBO", "value"); + + AnswerCallResult answerCallResult + = Objects.requireNonNull(receiverAsyncClient.answerCallWithResponse(answerCallOptions).block()) + .getValue(); + assertNotNull(answerCallResult); + assertNotNull(answerCallResult.getCallConnectionAsync()); + assertNotNull(answerCallResult.getCallConnectionProperties()); + String receiverConnectionId = answerCallResult.getCallConnectionProperties().getCallConnectionId(); + callDestructors.add(answerCallResult.getCallConnectionAsync()); + + // check events to caller side + CallConnected callerCallConnected + = waitForEvent(CallConnected.class, callerConnectionId, Duration.ofSeconds(10)); + ParticipantsUpdated callerParticipantUpdatedEvent + = waitForEvent(ParticipantsUpdated.class, callerConnectionId, Duration.ofSeconds(10)); + assertNotNull(callerCallConnected); + assertNotNull(callerParticipantUpdatedEvent); + + // check events to receiver side + CallConnected receiverCallConnected + = waitForEvent(CallConnected.class, receiverConnectionId, Duration.ofSeconds(10)); + ParticipantsUpdated receiverParticipantUpdatedEvent + = waitForEvent(ParticipantsUpdated.class, callerConnectionId, Duration.ofSeconds(10)); + assertNotNull(receiverCallConnected); + assertNotNull(receiverParticipantUpdatedEvent); + + // hang up the call. + answerCallResult.getCallConnectionAsync().hangUp(true).block(); + + // check if both parties had the call terminated. + CallDisconnected callerCallDisconnected + = waitForEvent(CallDisconnected.class, receiverConnectionId, Duration.ofSeconds(10)); + CallDisconnected receiverCallDisconnected + = waitForEvent(CallDisconnected.class, callerConnectionId, Duration.ofSeconds(10)); + assertNotNull(callerCallDisconnected); + assertNotNull(receiverCallDisconnected); + + } catch (Exception ex) { + fail("Unexpected exception received", ex); + } finally { + if (!callDestructors.isEmpty()) { + try { + callDestructors.forEach(callConnection -> callConnection.hangUpWithResponse(true).block()); + } catch (Exception ignored) { + // Some call might have been terminated during the test, and it will cause exceptions here. + // Do nothing and iterate to next call connection. + } + } } - AnswerCallResult answerCallResult - = Objects.requireNonNull(receiverAsyncClient.answerCallWithResponse(answerCallOptions).block()) - .getValue(); - assertNotNull(answerCallResult); - assertNotNull(answerCallResult.getCallConnectionAsync()); - assertNotNull(answerCallResult.getCallConnectionProperties()); - String receiverConnectionId = answerCallResult.getCallConnectionProperties().getCallConnectionId(); - callDestructors.add(answerCallResult.getCallConnectionAsync()); - - // check events to caller side - CallConnected callerCallConnected - = waitForEvent(CallConnected.class, callerConnectionId, Duration.ofSeconds(10)); - ParticipantsUpdated callerParticipantUpdatedEvent - = waitForEvent(ParticipantsUpdated.class, callerConnectionId, Duration.ofSeconds(10)); - assertNotNull(callerCallConnected); - assertNotNull(callerParticipantUpdatedEvent); - - // check events to receiver side - CallConnected receiverCallConnected - = waitForEvent(CallConnected.class, receiverConnectionId, Duration.ofSeconds(10)); - ParticipantsUpdated receiverParticipantUpdatedEvent - = waitForEvent(ParticipantsUpdated.class, callerConnectionId, Duration.ofSeconds(10)); - assertNotNull(receiverCallConnected); - assertNotNull(receiverParticipantUpdatedEvent); - - // hang up the call. - answerCallResult.getCallConnectionAsync().hangUp(true).block(); - - // check if both parties had the call terminated. - CallDisconnected callerCallDisconnected - = waitForEvent(CallDisconnected.class, receiverConnectionId, Duration.ofSeconds(10)); - CallDisconnected receiverCallDisconnected - = waitForEvent(CallDisconnected.class, callerConnectionId, Duration.ofSeconds(10)); - assertNotNull(callerCallDisconnected); - assertNotNull(receiverCallDisconnected); - - } catch (Exception ex) { - fail("Unexpected exception received", ex); - } finally { - if (!callDestructors.isEmpty()) { - try { - callDestructors.forEach(callConnection -> callConnection.hangUpWithResponse(true).block()); - } catch (Exception ignored) { - // Some call might have been terminated during the test, and it will cause exceptions here. - // Do nothing and iterate to next call connection. - } - } - } } } diff --git a/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientUnitTests.java b/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientUnitTests.java index c441f814dc12..c54043478498 100644 --- a/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientUnitTests.java +++ b/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientUnitTests.java @@ -143,6 +143,8 @@ public void answerCallWithResponseAndCustomContext() { AnswerCallOptions answerCallOptions = new AnswerCallOptions(CALL_INCOMING_CALL_CONTEXT, CALL_CALLBACK_URL) .setMediaStreamingConfiguration(MEDIA_STREAMING_CONFIGURATION) .setTranscriptionConfiguration(TRANSCRIPTION_CONFIGURATION); + answerCallOptions.getCustomCallingContext().addSipUui("OBOuuivalue"); + answerCallOptions.getCustomCallingContext().addSipX("XheaderOBO", "value"); Response answerCallResult = callAutomationAsyncClient.answerCallWithResponse(answerCallOptions).block(); From 4db52be0a1c5b8115f375fb4bae40f6c971cef08 Mon Sep 17 00:00:00 2001 From: Vinothini Dharmaraj Date: Fri, 27 Dec 2024 13:27:40 -0800 Subject: [PATCH 4/4] fixing the build issue and recording the live test --- .../azure-communication-callautomation/assets.json | 2 +- .../callautomation/CallAutomationAsyncClient.java | 1 - ...allAutomationAsyncClientAutomatedLiveTests.java | 1 - .../CallAutomationAsyncClientUnitTests.java | 14 ++++---------- ...erWithCustomContextThenHangupAutomatedTest.json | 1 + 5 files changed, 6 insertions(+), 13 deletions(-) create mode 100644 sdk/communication/azure-communication-callautomation/src/test/resources/createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest.json diff --git a/sdk/communication/azure-communication-callautomation/assets.json b/sdk/communication/azure-communication-callautomation/assets.json index f9b4280a9b17..e011f2ddd486 100644 --- a/sdk/communication/azure-communication-callautomation/assets.json +++ b/sdk/communication/azure-communication-callautomation/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "java", "TagPrefix": "java/communication/azure-communication-callautomation", - "Tag": "java/communication/azure-communication-callautomation_8eed475b32" + "Tag": "java/communication/azure-communication-callautomation_cf67d9f149" } \ No newline at end of file diff --git a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallAutomationAsyncClient.java b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallAutomationAsyncClient.java index bc7bc6e07cda..ab277b6c9987 100644 --- a/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallAutomationAsyncClient.java +++ b/sdk/communication/azure-communication-callautomation/src/main/java/com/azure/communication/callautomation/CallAutomationAsyncClient.java @@ -66,7 +66,6 @@ import java.net.URISyntaxException; import java.security.InvalidParameterException; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; diff --git a/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientAutomatedLiveTests.java b/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientAutomatedLiveTests.java index f7adc53150ae..7b5c107f1c2d 100644 --- a/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientAutomatedLiveTests.java +++ b/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientAutomatedLiveTests.java @@ -213,7 +213,6 @@ public void createVOIPCallAndRejectAutomatedTest(HttpClient httpClient) { } } - @DoNotRecord(skipInPlayback = true) @ParameterizedTest @MethodSource("com.azure.core.test.TestBase#getHttpClients") @DisabledIfEnvironmentVariable( diff --git a/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientUnitTests.java b/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientUnitTests.java index e529a1ce2550..b3148f6c8baa 100644 --- a/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientUnitTests.java +++ b/sdk/communication/azure-communication-callautomation/src/test/java/com/azure/communication/callautomation/CallAutomationAsyncClientUnitTests.java @@ -117,13 +117,11 @@ public void answerCallWithResponseAndCustomContext() { CallAutomationAsyncClient callAutomationAsyncClient = getCallAutomationAsyncClient(new ArrayList<>( Collections.singletonList(new AbstractMap.SimpleEntry<>(generateCallProperties(CALL_CONNECTION_ID, CALL_SERVER_CALL_ID, CALL_CALLER_ID, CALL_CALLER_DISPLAY_NAME, CALL_TARGET_ID, CALL_CONNECTION_STATE, - CALL_SUBJECT, CALL_CALLBACK_URL, MEDIA_SUBSCRIPTION_ID, DATA_SUBSCRIPTION_ID), 200)))); + CALL_SUBJECT, CALL_CALLBACK_URL, null, null), 200)))); - AnswerCallOptions answerCallOptions = new AnswerCallOptions(CALL_INCOMING_CALL_CONTEXT, CALL_CALLBACK_URL) - .setMediaStreamingConfiguration(MEDIA_STREAMING_CONFIGURATION) - .setTranscriptionConfiguration(TRANSCRIPTION_CONFIGURATION); - answerCallOptions.getCustomCallingContext().addSipUui("OBOuuivalue"); - answerCallOptions.getCustomCallingContext().addSipX("XheaderOBO", "value"); + AnswerCallOptions answerCallOptions = new AnswerCallOptions(CALL_INCOMING_CALL_CONTEXT, CALL_CALLBACK_URL); + answerCallOptions.getCustomCallingContext().addSipUui("OBOuuivalue"); + answerCallOptions.getCustomCallingContext().addSipX("XheaderOBO", "value"); Response answerCallResult = callAutomationAsyncClient.answerCallWithResponse(answerCallOptions).block(); @@ -131,10 +129,6 @@ public void answerCallWithResponseAndCustomContext() { assertNotNull(answerCallResult); assertEquals(200, answerCallResult.getStatusCode()); assertNotNull(answerCallResult.getValue()); - assertEquals(MEDIA_SUBSCRIPTION_ID, - answerCallResult.getValue().getCallConnectionProperties().getMediaSubscriptionId()); - assertEquals(DATA_SUBSCRIPTION_ID, - answerCallResult.getValue().getCallConnectionProperties().getDataSubscriptionId()); } @Test diff --git a/sdk/communication/azure-communication-callautomation/src/test/resources/createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest.json b/sdk/communication/azure-communication-callautomation/src/test/resources/createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest.json new file mode 100644 index 000000000000..b8311df376ee --- /dev/null +++ b/sdk/communication/azure-communication-callautomation/src/test/resources/createVOIPCallAndAnswerWithCustomContextThenHangupAutomatedTest.json @@ -0,0 +1 @@ +["{\"to\":{\"kind\":\"communicationUser\",\"rawId\":\"REDACTED\",\"communicationUser\":{\"id\":\"REDACTED\"}},\"from\":{\"kind\":\"communicationUser\",\"rawId\":\"REDACTED\",\"communicationUser\":{\"id\":\"REDACTED\"}},\"serverCallId\":\"REDACTED\",\"callerDisplayName\":\"\",\"incomingCallContext\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\"}","[{\"id\":\"REDACTED\",\"source\":\"calling/callConnections/24002180-b059-4741-a392-a1aed1126925\",\"type\":\"Microsoft.Communication.CallConnected\",\"data\":{\"version\":\"2024-09-01-preview\",\"resultInformation\":{\"code\":200,\"subCode\":0,\"message\":\"\"},\"callConnectionId\":\"24002180-b059-4741-a392-a1aed1126925\",\"serverCallId\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\",\"publicEventType\":\"Microsoft.Communication.CallConnected\"},\"time\":\"2024-12-27T21:04:58.0090118\\u002B00:00\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"calling/callConnections/24002180-b059-4741-a392-a1aed1126925\"}]","[{\"id\":\"REDACTED\",\"source\":\"calling/callConnections/24002180-2951-4e61-aace-194bbd10bbb1\",\"type\":\"Microsoft.Communication.ParticipantsUpdated\",\"data\":{\"participants\":[{\"identifier\":{\"rawId\":\"REDACTED\",\"kind\":\"communicationUser\",\"communicationUser\":{\"id\":\"REDACTED\"}},\"isMuted\":false,\"isOnHold\":false},{\"identifier\":{\"rawId\":\"REDACTED\",\"kind\":\"communicationUser\",\"communicationUser\":{\"id\":\"REDACTED\"}},\"isMuted\":false,\"isOnHold\":false}],\"sequenceNumber\":1,\"resultInformation\":{\"code\":200,\"subCode\":0,\"message\":\"\"},\"version\":\"2024-09-01-preview\",\"callConnectionId\":\"24002180-2951-4e61-aace-194bbd10bbb1\",\"serverCallId\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\",\"publicEventType\":\"Microsoft.Communication.ParticipantsUpdated\"},\"time\":\"2024-12-27T21:04:58.0121227\\u002B00:00\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"calling/callConnections/24002180-2951-4e61-aace-194bbd10bbb1\"}]","[{\"id\":\"REDACTED\",\"source\":\"calling/callConnections/24002180-2951-4e61-aace-194bbd10bbb1\",\"type\":\"Microsoft.Communication.CallConnected\",\"data\":{\"version\":\"2024-09-01-preview\",\"resultInformation\":{\"code\":200,\"subCode\":0,\"message\":\"\"},\"callConnectionId\":\"24002180-2951-4e61-aace-194bbd10bbb1\",\"serverCallId\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\",\"publicEventType\":\"Microsoft.Communication.CallConnected\"},\"time\":\"2024-12-27T21:04:58.0090118\\u002B00:00\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"calling/callConnections/24002180-2951-4e61-aace-194bbd10bbb1\"}]","[{\"id\":\"REDACTED\",\"source\":\"calling/callConnections/24002180-b059-4741-a392-a1aed1126925\",\"type\":\"Microsoft.Communication.ParticipantsUpdated\",\"data\":{\"participants\":[{\"identifier\":{\"rawId\":\"REDACTED\",\"kind\":\"communicationUser\",\"communicationUser\":{\"id\":\"REDACTED\"}},\"isMuted\":false,\"isOnHold\":false},{\"identifier\":{\"rawId\":\"REDACTED\",\"kind\":\"communicationUser\",\"communicationUser\":{\"id\":\"REDACTED\"}},\"isMuted\":false,\"isOnHold\":false}],\"sequenceNumber\":1,\"resultInformation\":{\"code\":200,\"subCode\":0,\"message\":\"\"},\"version\":\"2024-09-01-preview\",\"callConnectionId\":\"24002180-b059-4741-a392-a1aed1126925\",\"serverCallId\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\",\"publicEventType\":\"Microsoft.Communication.ParticipantsUpdated\"},\"time\":\"2024-12-27T21:04:58.0121227\\u002B00:00\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"calling/callConnections/24002180-b059-4741-a392-a1aed1126925\"}]","[{\"id\":\"REDACTED\",\"source\":\"calling/callConnections/24002180-2951-4e61-aace-194bbd10bbb1\",\"type\":\"Microsoft.Communication.CallDisconnected\",\"data\":{\"version\":\"2024-09-01-preview\",\"resultInformation\":{\"code\":200,\"subCode\":7000,\"message\":\"The conversation has ended. DiagCode: 0#7000.@\"},\"callConnectionId\":\"24002180-2951-4e61-aace-194bbd10bbb1\",\"serverCallId\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\",\"publicEventType\":\"Microsoft.Communication.CallDisconnected\"},\"time\":\"2024-12-27T21:04:59.0901871\\u002B00:00\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"calling/callConnections/24002180-2951-4e61-aace-194bbd10bbb1\"}]","[{\"id\":\"REDACTED\",\"source\":\"calling/callConnections/24002180-b059-4741-a392-a1aed1126925\",\"type\":\"Microsoft.Communication.CallDisconnected\",\"data\":{\"version\":\"2024-09-01-preview\",\"resultInformation\":{\"code\":200,\"subCode\":5001,\"message\":\"This conversation has ended.. DiagCode: 0#5001.@\"},\"callConnectionId\":\"24002180-b059-4741-a392-a1aed1126925\",\"serverCallId\":\"REDACTED\",\"correlationId\":\"dd7b828d-5f8b-43d4-be3f-d95c675f19ca\",\"publicEventType\":\"Microsoft.Communication.CallDisconnected\"},\"time\":\"2024-12-27T21:04:59.3246749\\u002B00:00\",\"specversion\":\"1.0\",\"datacontenttype\":\"application/json\",\"subject\":\"calling/callConnections/24002180-b059-4741-a392-a1aed1126925\"}]"] \ No newline at end of file