public void MSOXCNOTIF_S01_TC06_VerifyAsyncRpcCall()
{
this.CheckWhetherSupportMAPIHTTP();
this.NotificationInitialize();
// Asynchronous RPC Notification can't be verified when use MAPIHTTP as transport.
Site.Assume.IsTrue(Common.GetConfigurationPropertyValue("TransportSeq", this.Site).ToLower() != "mapi_http", "Asynchronous RPC Notification can't be verified when use MAPIHTTP as transport.");
#region Subscribe NewMail event
this.CNOTIFAdapter.RegisterNotification(NotificationType.NewMail);
#endregion
#region Call EcDoAsyncConnectEx to acquire an asynchronous context handle
IntPtr acxh = this.CNOTIFAdapter.EcDoAsyncConnectEx();
#endregion
#region Verify that the server created an asynchronous context handle
// Add the debug information
this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCNOTIF_R298");
// Verify MS-OXCNOTIF requirement: MS-OXCNOTIF_R298
this.Site.CaptureRequirementIfAreNotEqual<IntPtr>(
IntPtr.Zero,
acxh,
298,
@"[In Receiving an EcDoAsyncConnectEx Method Call] When a call to the EcDoAsyncConnectEx RPC, as specified in [MS-OXCRPC] section 3.1.4.4, is received by the server, the server MUST create an asynchronous context handle.");
if (Common.IsRequirementEnabled(297, this.Site))
{
// Add the debug information
this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCNOTIF_R297");
// Verify MS-OXCNOTIF requirement: MS-OXCNOTIF_R297
this.Site.CaptureRequirementIfAreNotEqual<IntPtr>(
IntPtr.Zero,
acxh,
297,
@"[In Appendix A: Product Behavior] Implementation does support the EcDoAsyncConnectEx method call, as specified in [MS-OXCRPC] section 3.1.4.4. ( Exchange 2007 and above follow this behavior).");
}
#endregion
#region Call EcDoAsyncWaitEx with the valid ACXH
IntPtr asyncHandle;
this.CNOTIFAdapter.BeginAsyncWait(acxh, out asyncHandle);
// Get the status of EcDoAsyncWaitEx call.
// The event has not been triggered yet, so the call should not be completed.
RPCAsyncStatus status = this.CNOTIFAdapter.QueryAsyncWaitStatus(asyncHandle);
// Add the debug information
this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCNOTIF_R62");
// Verify MS-OXCNOTIF requirement: MS-OXCNOTIF_R62
// When the client can get a valid handle and the handle can be used in BeginAsyncWait successfully, this requirement can be verified.
bool isVerifiedR62 = acxh != IntPtr.Zero && status != RPCAsyncStatus.RPC_S_INVALID_ASYNC_HANDLE;
if (Common.IsRequirementEnabled(62, this.Site))
{
this.Site.CaptureRequirementIfIsTrue(
isVerifiedR62,
62,
@"[In Appendix A: Product Behavior] The EcDoAsyncConnectEx RPC method, as specified in [MS-OXCRPC] section 3.1.4.4, is used to acquire an asynchronous context handle on the implementation to use in subsequent EcDoAsyncWaitEx method calls, as specified in [MS-OXCRPC] section 3.3.4.1. (Exchange 2007 and above follow this behavior.)");
}
// Trigger the event
this.TriggerNewMailEvent();
// Get the status of EcDoAsyncWaitEx call again.
// The event has been triggered, so the call should be completed.
RPCAsyncStatus status2;
// The times to try getting a completed status.
int retryCount = int.Parse(Common.GetConfigurationPropertyValue("RetryCount", this.Site));
int sleepTime = int.Parse(Common.GetConfigurationPropertyValue("SleepTime", this.Site));
do
{
status2 = this.CNOTIFAdapter.QueryAsyncWaitStatus(asyncHandle);
Thread.Sleep(sleepTime);
retryCount--;
}
while (status2 != RPCAsyncStatus.RPC_S_OK && retryCount >= 0);
Site.Assert.AreEqual<RPCAsyncStatus>(RPCAsyncStatus.RPC_S_OK, status2, "RPC status should be completed.");
#endregion
#region Verify that the server does not complete the call until there is a notification
if (Common.IsRequirementEnabled(305, this.Site))
{
// Add the debug information
this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCNOTIF_R305");
// Verify MS-OXCNOTIF requirement: MS-OXCNOTIF_R305
bool isR305Satisfied = (status != RPCAsyncStatus.RPC_S_OK) && (status2 == RPCAsyncStatus.RPC_S_OK);
this.Site.CaptureRequirementIfIsTrue(
isR305Satisfied,
305,
@"[In Appendix A: Product Behavior] Implementation does not complete the call [EcDoAsyncWaitEx Method Call] until there is a notification for the client session. (Exchange 2007 and above follow this behavior.)");
}
#endregion
#region Complete the EcDoAsyncWaitEx call
int isPending;
this.CNOTIFAdapter.EndAsyncWait(asyncHandle, out isPending);
#endregion
#region Verify that the server returns the value NotificationPending in the output field pulFlagsOut.
if (Common.IsRequirementEnabled(302, this.Site))
{
// Add the debug information
Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCNOTIF_R302");
// The RPC method BeginAsyncWait and EndAsyncWait can run successfully without exception, so this requirement can be verified directly.
Site.CaptureRequirement(
302,
@"[In Appendix A: Product Behavior] Implementation does support the EcDoAsyncWaitEx method call, as specified in [MS-OXCRPC] section 3.3.4.1. (Exchange 2007 and above follow this behavior).");
}
// Add the debug information
this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCNOTIF_R310");
// Verify MS-OXCNOTIF requirement: MS-OXCNOTIF_R310
this.Site.CaptureRequirementIfAreEqual<int>(
0x00000001,
isPending,
310,
@"[In Receiving an EcDoAsyncWaitEx Method Call] If the server completes the outstanding RPC call when there is a notification for the client session, the server MUST return the value NotificationPending in the pulFlagsOut field.");
// Add the debug information
this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCNOTIF_R68");
if (Common.IsRequirementEnabled(68, this.Site))
{
// Verify MS-OXCNOTIF requirement: MS-OXCNOTIF_R68
this.Site.CaptureRequirementIfAreEqual<int>(
0x00000001,
isPending,
68,
@"[In Appendix A: Product Behavior] The EcDoAsyncWaitEx asynchronous RPC method, as specified in [MS-OXCRPC] section 3.3.4.1, is used to inform a client about pending notifications on the implementation. ( Exchange 2007 and above follow this behavior)");
}
#endregion
#region Get notification details.
IList<IDeserializable> response = this.CNOTIFAdapter.GetNotification(true);
RopNotifyResponse notifyResponse = (RopNotifyResponse)response.First(x => x is RopNotifyResponse);
Site.Assert.AreEqual<NotificationType>(NotificationType.NewMail, notifyResponse.NotificationData.NotificationType, "New mail should be returned successfully.");
bool isSupportRpcNotif = false;
foreach (IDeserializable resp in response)
{
if (resp is RopNotifyResponse)
{
isSupportRpcNotif = true;
}
}
#region Verify that the EcDoAsyncConnectEx and EcDoAsyncConnectEx support asynchronous RPC notifications
// Add the debug information
this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCNOTIF_R63");
// Verify MS-OXCNOTIF requirement: MS-OXCNOTIF_R63
// EcDoAsyncConnectEx has been called before getting notification, so if the response contains RopNotifyResponse, this requirement can be verified.
bool isVerifiedR63 = isSupportRpcNotif;
this.Site.CaptureRequirementIfIsTrue(
isVerifiedR63,
63,
@"[In EcDoAsyncConnectEx Method] The EcDoAsyncConnectEx method is used to support asynchronous RPC notifications.");
// Add the debug information
this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCNOTIF_R69");
// Verify MS-OXCNOTIF requirement: MS-OXCNOTIF_R69
// EcDoAsyncWaitEx has been called before getting notification, so if the response contains RopNotifyResponse, this requirement can be verified.
bool isVerifiedR69 = isSupportRpcNotif;
this.Site.CaptureRequirementIfIsTrue(
isVerifiedR69,
69,
@"[In EcDoAsyncWaitEx Method] The EcDoAsyncWaitEx method is used to support asynchronous RPC notifications.");
#endregion
#endregion
}