Skip to content

Commit 0af1691

Browse files
authored
added live tests with session records for calling server (Azure#29780)
* added live tests for calling server * adding logic to check for successful hang up in sdk live tests * update test.yml * fix pipeline * fix skip live test * add log * pull from main * remove logs
1 parent 42b54ef commit 0af1691

File tree

9 files changed

+1161
-1
lines changed

9 files changed

+1161
-1
lines changed

sdk/communication/Azure.Communication.CallingServer/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ extends:
1717
- $(sub-config-communication-int-test-resources-net)
1818
Clouds: Public
1919
EnvVars:
20-
# SKIP_CALLINGSERVER_INTERACTION_LIVE_TESTS skips certain CallAutomation tests that required human interaction
20+
# SKIP_CALLINGSERVER_INTERACTION_LIVE_TESTS skips certain CallAutomation tests that required human interactions
2121
SKIP_CALLINGSERVER_INTERACTION_LIVE_TESTS: TRUE
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Threading.Tasks;
6+
using NUnit.Framework;
7+
using NUnit.Framework.Internal;
8+
9+
namespace Azure.Communication.CallingServer
10+
{
11+
internal class CallAutomationClientLiveTests : CallAutomationClientLiveTestsBase
12+
{
13+
public CallAutomationClientLiveTests(bool isAsync) : base(isAsync)
14+
{
15+
}
16+
17+
[Test]
18+
public async Task CreateCallToACSGetCallAndHangUpCallTest()
19+
{
20+
/* Test case: ACS to ACS call
21+
* 1. create a CallAutomationClient.
22+
* 2. create a call from source to one ACS target.
23+
* 3. get updated call properties and check for the connected state.
24+
* 4. hang up the call.
25+
* 5. once call is hung up, verify that call connection cannot be found.
26+
*/
27+
if (SkipCallingServerInteractionLiveTests)
28+
Assert.Ignore("Skip callingserver interaction live tests flag is on.");
29+
30+
CallAutomationClient client = CreateInstrumentedCallAutomationClientWithConnectionString();
31+
bool wasConnected = false;
32+
33+
try
34+
{
35+
var user = await CreateIdentityUserAsync().ConfigureAwait(false);
36+
var targets = new CommunicationIdentifier[] { new CommunicationUserIdentifier(TestEnvironment.TargetUserId) };
37+
CreateCallResult response = await client.CreateCallAsync(new CallSource(user), targets, new Uri(TestEnvironment.AppCallbackUrl)).ConfigureAwait(false);
38+
Assert.IsNotEmpty(response.CallConnectionProperties.CallConnectionId);
39+
Assert.AreEqual(CallConnectionState.Connecting, response.CallConnectionProperties.CallConnectionState);
40+
await WaitForOperationCompletion().ConfigureAwait(false);
41+
42+
Response<CallConnectionProperties> properties = await response.CallConnection.GetCallConnectionPropertiesAsync().ConfigureAwait(false);
43+
Assert.AreEqual(CallConnectionState.Connected, properties.Value.CallConnectionState);
44+
wasConnected = true;
45+
46+
await response.CallConnection.HangUpAsync(true).ConfigureAwait(false);
47+
await WaitForOperationCompletion().ConfigureAwait(false);
48+
properties = await response.CallConnection.GetCallConnectionPropertiesAsync().ConfigureAwait(false);
49+
50+
Assert.Fail("Call Connection should not be found after calling HangUp");
51+
}
52+
catch (RequestFailedException ex)
53+
{
54+
if (ex.Status == 404 && wasConnected)
55+
{
56+
// call hung up successfully
57+
Assert.Pass();
58+
}
59+
Assert.Fail($"Unexpected error: {ex}");
60+
}
61+
catch (Exception ex)
62+
{
63+
Assert.Fail($"Unexpected error: {ex}");
64+
}
65+
}
66+
67+
[Test]
68+
public async Task CreateCallToPSTNGetCallAndHangUpCallTest()
69+
{
70+
/* Test case: ACS to PSTN call
71+
* 1. create a CallAutomationClient.
72+
* 2. create a call from source to one PSTN target.
73+
* 3. get updated call properties and check for the connected state.
74+
* 4. hang up the call.
75+
* 5. once call is hung up, verify that call connection cannot be found.
76+
*/
77+
78+
if (SkipCallingServerInteractionLiveTests)
79+
Assert.Ignore("Skip callingserver interaction live tests flag is on.");
80+
81+
CallAutomationClient client = CreateInstrumentedCallAutomationClientWithConnectionString();
82+
bool wasConnected = false;
83+
84+
try
85+
{
86+
var user = await CreateIdentityUserAsync().ConfigureAwait(false);
87+
var source = new CallSource(user) {
88+
CallerId = new PhoneNumberIdentifier(TestEnvironment.SourcePhoneNumber)
89+
};
90+
91+
var targets = new CommunicationIdentifier[] { new PhoneNumberIdentifier(TestEnvironment.TargetPhoneNumber) };
92+
CreateCallResult response = await client.CreateCallAsync(source, targets, new Uri(TestEnvironment.AppCallbackUrl)).ConfigureAwait(false);
93+
Assert.IsNotEmpty(response.CallConnectionProperties.CallConnectionId);
94+
Assert.AreEqual("connecting", response.CallConnectionProperties.CallConnectionState.ToString());
95+
await WaitForOperationCompletion().ConfigureAwait(false);
96+
97+
Response<CallConnectionProperties> properties = await response.CallConnection.GetCallConnectionPropertiesAsync().ConfigureAwait(false);
98+
Assert.AreEqual(CallConnectionState.Connected, properties.Value.CallConnectionState);
99+
wasConnected = true;
100+
101+
await response.CallConnection.HangUpAsync(true).ConfigureAwait(false);
102+
await WaitForOperationCompletion().ConfigureAwait(false);
103+
properties = await response.CallConnection.GetCallConnectionPropertiesAsync().ConfigureAwait(false);
104+
105+
Assert.Fail("Call Connection should not be found after calling HangUp");
106+
}
107+
catch (RequestFailedException ex)
108+
{
109+
if (ex.Status == 404 && wasConnected)
110+
{
111+
// call hung up successfully
112+
Assert.Pass();
113+
}
114+
Assert.Fail($"Request failed error: {ex}");
115+
}
116+
catch (Exception ex)
117+
{
118+
Assert.Fail($"Unexpected error: {ex}");
119+
}
120+
}
121+
}
122+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Threading.Tasks;
6+
using Azure.Communication.Identity;
7+
using Azure.Core.TestFramework;
8+
using Azure.Core.TestFramework.Models;
9+
10+
namespace Azure.Communication.CallingServer
11+
{
12+
internal class CallAutomationClientLiveTestsBase : RecordedTestBase<CallAutomationClientTestEnvironment>
13+
{
14+
private const string URIDomainRegEx = @"https://([^/?]+)";
15+
16+
public CallAutomationClientLiveTestsBase(bool isAsync) : base(isAsync)
17+
{
18+
SanitizedHeaders.Add("x-ms-content-sha256");
19+
SanitizedHeaders.Add("X-FORWARDED-HOST");
20+
JsonPathSanitizers.Add("$..id");
21+
JsonPathSanitizers.Add("$..rawId");
22+
JsonPathSanitizers.Add("$..value");
23+
UriRegexSanitizers.Add(new UriRegexSanitizer(URIDomainRegEx, "https://sanitized.skype.com"));
24+
}
25+
26+
public bool SkipCallingServerInteractionLiveTests
27+
=> TestEnvironment.Mode != RecordedTestMode.Playback && Environment.GetEnvironmentVariable("SKIP_CALLINGSERVER_INTERACTION_LIVE_TESTS")== "TRUE";
28+
29+
/// <summary>
30+
/// Creates a <see cref="CallAutomationClient" />
31+
/// </summary>
32+
/// <returns>The instrumented <see cref="CallAutomationClient" />.</returns>
33+
protected CallAutomationClient CreateInstrumentedCallAutomationClientWithConnectionString()
34+
{
35+
var connectionString = TestEnvironment.LiveTestStaticConnectionString;
36+
37+
CallAutomationClient callAutomationClient;
38+
if (TestEnvironment.PMAEndpoint == null || TestEnvironment.PMAEndpoint.Length == 0)
39+
{
40+
callAutomationClient = new CallAutomationClient(connectionString, CreateServerCallingClientOptionsWithCorrelationVectorLogs());
41+
}
42+
else
43+
{
44+
callAutomationClient = new CallAutomationClient(new Uri(TestEnvironment.PMAEndpoint), connectionString, CreateServerCallingClientOptionsWithCorrelationVectorLogs());
45+
}
46+
47+
return InstrumentClient(callAutomationClient);
48+
}
49+
50+
/// <summary>
51+
/// Creates a <see cref="CallAutomationClientOptions" />
52+
/// </summary>
53+
/// <returns>The instrumented <see cref="CallAutomationClientOptions" />.</returns>
54+
private CallAutomationClientOptions CreateServerCallingClientOptionsWithCorrelationVectorLogs()
55+
{
56+
CallAutomationClientOptions callClientOptions = new CallAutomationClientOptions();
57+
callClientOptions.Diagnostics.LoggedHeaderNames.Add("MS-CV");
58+
return InstrumentClientOptions(callClientOptions);
59+
}
60+
61+
protected async Task WaitForOperationCompletion(int milliSeconds = 10000)
62+
{
63+
if (TestEnvironment.Mode != RecordedTestMode.Playback)
64+
await Task.Delay(10000);
65+
}
66+
67+
protected string GetResourceId()
68+
{
69+
return TestEnvironment.ResourceIdentifier;
70+
}
71+
72+
/// <summary>
73+
/// Creates a <see cref="CommunicationIdentityClient" /> with the connectionstring via environment
74+
/// variables and instruments it to make use of the Azure Core Test Framework functionalities.
75+
/// </summary>
76+
/// <returns>The instrumented <see cref="CommunicationIdentityClient" />.</returns>
77+
protected CommunicationIdentityClient CreateInstrumentedCommunicationIdentityClient()
78+
=> InstrumentClient(
79+
new CommunicationIdentityClient(
80+
TestEnvironment.LiveTestStaticConnectionString,
81+
InstrumentClientOptions(new CommunicationIdentityClientOptions(CommunicationIdentityClientOptions.ServiceVersion.V2021_03_07))));
82+
83+
protected async Task<CommunicationUserIdentifier> CreateIdentityUserAsync() {
84+
CommunicationIdentityClient communicationIdentityClient = CreateInstrumentedCommunicationIdentityClient();
85+
return await communicationIdentityClient.CreateUserAsync().ConfigureAwait(false);
86+
}
87+
}
88+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Net;
6+
using Azure.Communication.Tests;
7+
8+
namespace Azure.Communication.CallingServer
9+
{
10+
internal class CallAutomationClientTestEnvironment : CommunicationTestEnvironment
11+
{
12+
public const string ResourceId = "COMMUNICATION_LIVETEST_STATIC_RESOURCE_IDENTIFIER";
13+
14+
public const string TargetUser = "TARGET_USER_ID";
15+
16+
public const string TargetNumber = "TARGET_PHONE_NUMBER";
17+
18+
public const string Endpoint = "PMA_Endpoint";
19+
20+
private const string randomResourceIdentifier = "82e890fc-188a-4b67-bb7d-deff073d7d1e";
21+
22+
private string randomAcsUser = $"8:acs:{randomResourceIdentifier}_95a3d4a6-abbe-44ad-9f37-b0a72a616d0b";
23+
/// <summary>
24+
/// The resource identifier associated with the Azure Communication Service.
25+
/// </summary>
26+
public string ResourceIdentifier => GetRecordedVariable(ResourceId, options => options.IsSecret(randomResourceIdentifier));
27+
28+
/// <summary>
29+
/// The phone number associated with the ACS resource. Required to make a PSTN call.
30+
/// </summary>
31+
public string SourcePhoneNumber => GetRecordedVariable(AzurePhoneNumber, options => options.IsSecret("+18771234567"));
32+
33+
/// <summary>
34+
/// The target ACS user id represented in string formatted as "8:acs:ResourceId_UUID".
35+
/// </summary>
36+
public string TargetUserId => GetRecordedVariable(TargetUser, options => options.IsSecret(randomAcsUser));
37+
38+
/// <summary>
39+
/// The target phone number to call in string formated as "+1<PhoneNumber>".
40+
/// </summary>
41+
public string TargetPhoneNumber => GetRecordedVariable(TargetNumber, options => options.IsSecret("+16041234567"));
42+
43+
/// <summary>
44+
/// Endpoint for the targetted PMA in string. If not set, default endpoint is used.
45+
/// </summary>
46+
public string PMAEndpoint => GetRecordedVariable(Endpoint, options => options.IsSecret("https://sanitized.com"));
47+
48+
/// <summary>
49+
/// The secret for validating incoming request.
50+
/// </summary>
51+
public string IncomingRequestSecret => "helloworld";
52+
53+
/// <summary>
54+
/// The base url of the applicaiton.
55+
/// </summary>
56+
public string AppBaseUrl => "https://dummy.ngrok.io";
57+
58+
/// <summary>
59+
/// The callback url of the application where notification would be received.
60+
/// </summary>
61+
public string AppCallbackUrl => $"{AppBaseUrl}/api/incident/callback?SecretKey={WebUtility.UrlEncode(IncomingRequestSecret)}";
62+
}
63+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using Azure.Core;
55
using Azure.Core.TestFramework;
6+
67
namespace Azure.Communication.CallingServer
78
{
89
public class CallAutomationTestBase

0 commit comments

Comments
 (0)