/// <summary>
        /// Parses a response with multiple ROPs. In this scenario, the response is designed as only containing two ROPs: RopSetColumn and RopQueryRows.
        /// </summary>
        /// <param name="rgbOutput">The raw data that contains the ROP response payload</param>
        /// <returns>The ROP response list which contains RopSetColumnResponse and RopQueryRawResponse</returns>
        private List<IDeserializable> ParseMultipleRopsResponse(byte[] rgbOutput)
        {
            int parseByteLength = 0;
            List<IDeserializable> multipleRopsResponse = new List<IDeserializable>();
            RPC_HEADER_EXT rpcHeader = new RPC_HEADER_EXT
            {
                Version = BitConverter.ToUInt16(rgbOutput, parseByteLength)
            };

            // Parse RPC_HEADER_EXT structure
            parseByteLength += sizeof(short);
            rpcHeader.Flags = BitConverter.ToUInt16(rgbOutput, parseByteLength);
            parseByteLength += sizeof(short);
            rpcHeader.Size = BitConverter.ToUInt16(rgbOutput, parseByteLength);
            parseByteLength += sizeof(short);
            rpcHeader.SizeActual = BitConverter.ToUInt16(rgbOutput, parseByteLength);
            parseByteLength += sizeof(short);

            // Passed 2 bytes which is size of ROP response.
            parseByteLength += sizeof(short);

            // Parse RopSetColumns response
            RopSetColumnsResponse setColumnsResponse = new RopSetColumnsResponse();
            parseByteLength += setColumnsResponse.Deserialize(rgbOutput, parseByteLength);

            // Parse RopQueryRows response
            RopQueryRowsResponse queryRowsResponse = new RopQueryRowsResponse();
            parseByteLength += queryRowsResponse.Deserialize(rgbOutput, parseByteLength);

            multipleRopsResponse.Add(setColumnsResponse);
            multipleRopsResponse.Add(queryRowsResponse);

            return multipleRopsResponse;
        }
        /// <summary>
        /// Verify action type OP_MOVE.
        /// </summary>
        /// <param name="getFolderMailMessageContent">Message content gotten from the specified folder.</param>
        /// <param name="doesOriginalMessageExist">Whether the original message exists.</param>
        private void VerifyActionTypeOP_MOVE(RopQueryRowsResponse getFolderMailMessageContent, bool doesOriginalMessageExist)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R247: the message count in folder is {0}", getFolderMailMessageContent.RowCount);

            // Verify MS-OXORULE requirement: MS-OXORULE_R247
            bool isVerifyR247 = getFolderMailMessageContent.RowCount == 1 && !doesOriginalMessageExist;

            Site.CaptureRequirementIfIsTrue(
                 isVerifyR247,
                 247,
                 @"[In ActionBlock Structure] The meaning of action type OP_MOVE: Moves the message to a folder.");
        }
        /// <summary>
        /// Verify action type OP_COPY.
        /// </summary>
        /// <param name="mailSubject">The subject of the new mail.</param>
        /// <param name="getNewFolderMailMessageContent">The mail message content gotten from the new folder.</param>
        /// <param name="getInboxMailMessageContent">The mail message content gotten from the Inbox folder.</param>
        /// <param name="ruleProperties">The properties of the current rule.</param>
        private void VerifyActionTypeOP_COPY(string mailSubject, RopQueryRowsResponse getNewFolderMailMessageContent, RopQueryRowsResponse getInboxMailMessageContent, RuleProperties ruleProperties)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R250: the message count in newFolder is {0}, and in inboxFolder is {1}", getNewFolderMailMessageContent.RowCount, getInboxMailMessageContent.RowCount);

            // Verify MS-OXORULE requirement: MS-OXORULE_R250
            bool isVerifyR250 = mailSubject.Contains(ruleProperties.ConditionSubjectName) && getNewFolderMailMessageContent.RowCount == 1;

            Site.CaptureRequirementIfIsTrue(
                  isVerifyR250,
                  250,
                  @"[In ActionBlock Structure] The meaning of action type OP_COPY: Copies the message to a folder.");
        }
        /// <summary>
        /// Verify RopQueryRows Response
        /// </summary>
        /// <param name="queryRowsResponse">RopQueryRowsResponse structure data that needs verification</param>
        /// <param name="rowCountRequest">The RowCount that is specified in the request</param>
        private void VerifyRopQueryRowsResponse(RopQueryRowsResponse queryRowsResponse, ushort rowCountRequest)
        {
            this.VerifyRPCLayerRequirement();

            if (queryRowsResponse.RowCount > 0)
            {
                // The value of the following two properties are only valid for content table.
                if (this.tableType == TableType.CONTENT_TABLE)
                {
                    if (queryRowsResponse.RowData.PropertyRows != null)
                    {
                        for (int i = 0; i < queryRowsResponse.RowData.PropertyRows.Count; i++)
                        {
                            // Add the debug information
                            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R617");

                            // Verify MS-OXCTABL requirement: MS-OXCTABL_R617
                            Site.CaptureRequirementIfAreEqual<int>(
                                8,
                                queryRowsResponse.RowData.PropertyRows[i].PropertyValues[0].Value.Length,
                                617,
                                @"[In PidTagInstID] Data type: PtypInteger64 ([MS-OXCDATA] section 2.11.1).");

                            // Add the debug information
                            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R618");

                            // Verify MS-OXCTABL requirement: MS-OXCTABL_R618
                            Site.CaptureRequirementIfAreEqual<int>(
                                4,
                                queryRowsResponse.RowData.PropertyRows[i].PropertyValues[1].Value.Length,
                                618,
                                @"[In PidTagInstanceNum] Data type: PtypInteger32 ([MS-OXCDATA] section 2.11.1).");

                            // Add the debug information
                            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R619");

                            // Verify MS-OXCTABL requirement: MS-OXCTABL_R619
                            Site.CaptureRequirementIfAreEqual<int>(
                                4,
                                queryRowsResponse.RowData.PropertyRows[i].PropertyValues[3].Value.Length,
                                619,
                                @"[In PidTagRowType] Data type: PtypInteger32 ([MS-OXCDATA] section 2.11.1).");

                            // Add the debug information
                            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R620");

                            // Verify MS-OXCTABL requirement: MS-OXCTABL_R620
                            Site.CaptureRequirementIfAreEqual<int>(
                                4,
                                queryRowsResponse.RowData.PropertyRows[i].PropertyValues[4].Value.Length,
                                620,
                                @"[In PidTagDepth] Data type: PtypInteger32 property ([MS-OXCDATA] section 2.11.1).");
                        }
                    }

                    if (!this.areMultipleSortOrders && this.isExpanded == true)
                    {
                        int i = 0;
                        uint tempRowType = 0;
                        bool isLeafRowExist = false;
                        for (; i < queryRowsResponse.RowData.PropertyRows.Count; i++)
                        {
                            tempRowType = BitConverter.ToUInt32(queryRowsResponse.RowData.PropertyRows[i].PropertyValues[3].Value, 0);
                            if (tempRowType == 0x01)
                            {
                                isLeafRowExist = true;
                                break;
                            }
                        }

                        // Add the debug information
                        Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R15{0}", isLeafRowExist ? string.Empty : string.Format("There is no leaf row in the returned property rows!"));

                        // Verify MS-OXCTABL requirement: MS-OXCTABL_R15
                        Site.CaptureRequirementIfIsTrue(
                            isLeafRowExist,
                            15,
                            @"[In PidTagRowType] When the PidTagRowType is TBL_LEAF_ROW with value 0x00000001 means the row is a row of data.");
                    }

                    if (this.isExpanded == true)
                    {
                        int i = 0;
                        uint tempRowType = 0;
                        bool isExpandedHeaderExist = false;
                        for (; i < queryRowsResponse.RowData.PropertyRows.Count; i++)
                        {
                            tempRowType = BitConverter.ToUInt32(queryRowsResponse.RowData.PropertyRows[i].PropertyValues[3].Value, 0);
                            if (tempRowType == 0x03)
                            {
                                isExpandedHeaderExist = true;
                                break;
                            }
                        }

                        // Add the debug information
                        Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R17{0}", isExpandedHeaderExist ? string.Empty : string.Format("There is no expanded header row in the returned property rows!"));

                        // Verify MS-OXCTABL requirement: MS-OXCTABL_R17
                        Site.CaptureRequirementIfIsTrue(
                            isExpandedHeaderExist,
                            17,
                            @"[In PidTagRowType] When the PidTagRowType is TBL_EXPANDED_CATEGORY with value 0x00000003 means the row is a header row that is expanded.");
                    }
                    else if ((!this.areMultipleSortOrders && this.areAllSortOrdersUsedAsCategory) || (this.areMultipleSortOrders && !this.areAllSortOrdersUsedAsCategory))
                    {
                        int i = 0;
                        uint tempRowType = 0;
                        bool isCollapsedHeaderExist = false;
                        for (; i < queryRowsResponse.RowData.PropertyRows.Count; i++)
                        {
                            tempRowType = BitConverter.ToUInt32(queryRowsResponse.RowData.PropertyRows[i].PropertyValues[3].Value, 0);
                            if (tempRowType == 0x04)
                            {
                                isCollapsedHeaderExist = true;
                                break;
                            }
                        }

                        // Add the debug information
                        Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R18{0}", isCollapsedHeaderExist ? string.Empty : string.Format("There is no collapsed header row in the returned property rows!"));

                        // Verify MS-OXCTABL requirement: MS-OXCTABL_R18
                        Site.CaptureRequirementIfIsTrue(
                            isCollapsedHeaderExist,
                            18,
                            @"[In PidTagRowType] When the PidTagRowType is TBL_COLLAPSED_CATEGORY with value 0x00000004 means the row is a header row that is collapsed.");
                    }

                    // Since MS-OXCTABL_R15, MS-OXCTABL_R17 and MS-OXCTABL_R18 are verified, this requirement can be captured directly.    
                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R13");

                    // Verify MS-OXCTABL requirement: MS-OXCTABL_R13
                    Site.CaptureRequirement(
                        13,
                        @"[In PidTagRowType] The PidTagRowType property ([MS-OXPROPS] section 2.931) identifies the type of the row.");

                    if (this.areMultipleSortOrders && this.areAllSortOrdersUsedAsCategory && this.areAllCategoryExpanded)
                    {
                        int i = 0;
                        uint tempDepth = 0;
                        bool isCorrectDepth = false;

                        // There are no more than 2 categories in the response in this test suite.
                        for (; i < 3; i++)
                        {
                            tempDepth = BitConverter.ToUInt32(queryRowsResponse.RowData.PropertyRows[i].PropertyValues[4].Value, 0);
                            if (tempDepth == i)
                            {
                                isCorrectDepth = true;
                            }
                            else
                            {
                                break;
                            }
                        }

                        // Add the debug information
                        Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R19{0}", isCorrectDepth ? string.Empty : string.Format(": The no.{0} row depth is not correct and the value is {1}!", i, tempDepth));

                        // Verify MS-OXCTABL requirement: MS-OXCTABL_R19
                        Site.CaptureRequirementIfIsTrue(
                            isCorrectDepth,
                            19,
                            @"[In PidTagDepth] The PidTagDepth property ([MS-OXPROPS] section 2.664) specifies the number of nested categories in which a given row is contained.");
                    }
                }
            }

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R110: the value of the Origin field in the response for RopQueryRows is set to {0}", queryRowsResponse.Origin);

            // Verify MS-OXCTABL requirement: MS-OXCTABL_R110
            bool isVerifyR110 = (queryRowsResponse.Origin == 0x00) ||
                                (queryRowsResponse.Origin == 0x01) ||
                                (queryRowsResponse.Origin == 0x02);
            Site.CaptureRequirementIfIsTrue(
                isVerifyR110,
                110,
                @"[In RopQueryRows ROP Response Buffer] This field [Origin] MUST be set to one of the predefined bookmark values[0x00,0x01,0x02] specified in section 2.2.2.1.1.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R109");

            // Verify MS-OXCTABL requirement: MS-OXCTABL_R109
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                queryRowsResponse.Origin.GetType(),
                109,
                @"[In RopQueryRows ROP Response Buffer] Origin (1 byte): An enumeration that identifies the cursor position.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R111 (This is a WORD field)");

            // Verify MS-OXCTABL requirement: MS-OXCTABL_R111
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(ushort),
                queryRowsResponse.RowCount.GetType(),
                111,
                @"[In RopQueryRows ROP Response Buffer] RowCount (2 bytes): An unsigned integer that specifies the number of rows returned.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R112", rowCountRequest);

            // Verify MS-OXCTABL requirement: MS-OXCTABL_R112
            bool isVerifyR112 = (queryRowsResponse.RowCount <= rowCountRequest) &&
                                 (queryRowsResponse.RowCount >= 0x0000);
            Site.CaptureRequirementIfIsTrue(
                isVerifyR112,
                112,
                @"[In RopQueryRows ROP Response Buffer] Its [RowCount's] value MUST be less than or equal to the RowCount field value that is specified in the request, and it MUST be greater than or equal to 0x0000.");

            if (queryRowsResponse.RowData.PropertyRows != null)
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R113");

                // Verify MS-OXCTABL requirement: MS-OXCTABL_R113
                Site.CaptureRequirementIfAreEqual<ushort>(
                    (ushort)queryRowsResponse.RowData.PropertyRows.Count,
                    queryRowsResponse.RowCount,
                    113,
                    @"[In RopQueryRows ROP Response Buffer] It [RowCount] MUST be equal to the number of PropertyRow objects returned in the RowData field.");

                // If the propertyRows count in the queryrowsResponse is not zero, this requirement can be covered
                if (queryRowsResponse.RowData.PropertyRows.Count > 0)
                {
                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R114");

                    // Verify MS-OXCTABL requirement: MS-OXCTABL_R114
                    Site.CaptureRequirement(
                        114,
                        @"[In RopQueryRows ROP Response Buffer] RowData (variable): A list of PropertyRow structures that contains the array of rows returned.");
                }

                for (int i = 0; i < queryRowsResponse.RowData.PropertyRows.Count; i++)
                {
                    int totalSize = 0;
                    for (int j = 0; j < queryRowsResponse.RowData.PropertyRows[i].PropertyValues.Count; j++)
                    {
                        if (queryRowsResponse.RowData.PropertyRows[i].PropertyValues[j].Value == null)
                        {
                            continue;
                        }

                        if (queryRowsResponse.RowData.PropertyRows[i].PropertyValues[j].Value != null)
                        {
                            totalSize += queryRowsResponse.RowData.PropertyRows[i].PropertyValues[j].Size();
                        }
                    }

                    bool isVerifyR121 = totalSize <= 510 * sizeof(byte);

                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R121", 510 * sizeof(byte));

                    // Verify MS-OXCTABL requirement: MS-OXCTABL_R121
                    Site.CaptureRequirementIfIsTrue(
                        isVerifyR121,
                        121,
                        @"[In RopQueryRows ROP Response Buffer] Every property value returned in a row MUST be less than or equal to 510 bytes in size.");
                }

                foreach (PropertyRow propertyRow in queryRowsResponse.RowData.PropertyRows)
                {
                    this.VerifyPropertyRowStructure(propertyRow);
                }
            }
            else
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R113");

                // Verify MS-OXCTABL requirement: MS-OXCTABL_R113
                Site.CaptureRequirementIfAreEqual<ushort>(
                    0,
                    queryRowsResponse.RowCount,
                    113,
                    @"[In RopQueryRows ROP Response Buffer] It [RowCount] MUST be equal to the number of PropertyRow objects returned in the RowData field.");
            }

            for (int i = 0; i < queryRowsResponse.RowCount; i++)
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R115");

                // Verify MS-OXCTABL requirement: MS-OXCTABL_R115
                Site.CaptureRequirementIfAreEqual<Type>(
                    typeof(PropertyRow),
                    queryRowsResponse.RowData.PropertyRows[i].GetType(),
                    115,
                    @"[In RopQueryRows ROP Response Buffer] Each row is represented by a PropertyRow object, as specified in [MS-OXCDATA] section 2.8.1.");
            }

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R463: the value of the RowCount field in the response for RopQueryRows is set to {0}", queryRowsResponse.RowCount);

            // Verify MS-OXCTABL requirement: MS-OXCTABL_R463
            bool isVerifyR463 = queryRowsResponse.RowCount <= rowCountRequest;
            Site.CaptureRequirementIfIsTrue(
                isVerifyR463,
                463,
                @"[In Processing RopQueryRows] The number of rows sent in the ROP response MUST be less than or equal to the number of rows specified in the RowCount field.");
        }
        /// <summary>
        /// Verify the RopGetProperties in Rules Table.
        /// </summary>
        /// <param name="propertyTags">PropertyTag array.</param>
        /// <param name="quertyRowsResponse">Response of quertyRows.</param>
        private void VerifyPropertiesInTable(PropertyTag[] propertyTags, RopQueryRowsResponse quertyRowsResponse)
        {
            // propertyTags contains a list of PropertyTag.
            for (int i = 0; i < propertyTags.Length; i++)
            {
                // propertyId indicates the Id of a property.
                ushort propertyId = propertyTags[i].PropertyId;

                // propertyType indicates the Type of a property.
                ushort propertyType = propertyTags[i].PropertyType;

                // propertyValue indicates the value of a property.
                byte[] propertyValue = quertyRowsResponse.RowData.PropertyRows[quertyRowsResponse.RowData.PropertyRows.Count - 1].PropertyValues[i].Value;

                // If propertyId is 0x6674, it means the property is PidTagRuleId.
                if (propertyId == 0x6674)
                {
                    // Add the debug information.
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2699", "The length({0}) of the propertyValue should be 8 and the value of the propertyType({1}) should be 0x0014.", propertyValue.Length, propertyType);

                    // Verify MS-OXCDATA requirement: MS-OXCDATA_R2699.
                    bool isVerifyR2699 = propertyValue.Length == 8 && propertyType == 0x0014;

                    Site.CaptureRequirementIfIsTrue(
                        isVerifyR2699,
                        "MS-OXCDATA",
                        2699,
                        @"[In Property Data Types] PtypInteger64 (PT_LONGLONG, PT_I8, i8, ui8) is that 8 bytes; a 64-bit integer [MS-DTYP]: LONGLONG with Property Type Value 0x0014,%x14.00.");
                }

                // If propertyId is 0x001A, it means the property is PidTagMessageClass.
                if (propertyId == 0x001A)
                {
                    // Add the debug information.
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R351");

                    // Verify MS-OXORULE requirement: MS-OXORULE_R351.
                    Site.CaptureRequirementIfAreEqual<ushort>(
                        (ushort)PropertyType.PtypString,
                        propertyType,
                        351,
                        @"[In PidTagMessageClass] Type: PtypString ([MS-OXCDATA] section 2.11.1).");

                    if (this.targetOfRop == TargetOfRop.ForDAM)
                    {
                        // Add the debug information.
                        Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R352");

                        // Verify MS-OXORULE requirement: MS-OXORULE_R352.
                        Site.CaptureRequirementIfAreEqual<string>(
                            "IPC.Microsoft Exchange 4.0.Deferred Action",
                            AdapterHelper.PropertyValueConvertToString(propertyValue),
                            352,
                            @"[In PidTagMessageClass] The PidTagMessageClass property ([MS-OXCMSG] section 2.2.1.3) MUST be set to ""IPC.Microsoft Exchange 4.0.Deferred Action"".");
                    }
                }

                // If propertyId is 0x6647, it means the property is PidTagDamBackPatched.
                if (propertyId == 0x6647)
                {
                    // Add the debug information.
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2698", "The length({0}) of the propertyValue should be 1 and the value of the propertyType({1}) should be 0x000b.", propertyValue.Length, propertyType);

                    // Verify MS-OXCDATA requirement: MS-OXCDATA_R2698.
                    bool isVerifyR2698 = propertyValue.Length == 1 && propertyType == 0x000B;

                    Site.CaptureRequirementIfIsTrue(
                        isVerifyR2698,
                        "MS-OXCDATA",
                        2698,
                        @"[In Property Data Types] PtypBoolean (PT_BOOLEAN. bool) is that 1 byte, restricted to 1 or 0 [MS-DTYP]: BOOLEAN with Property Type Value 0x000B, %x0B.00.");

                    // Add the debug information.
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R353");

                    // Verify MS-OXORULE requirement: MS-OXORULE_R353.
                    Site.CaptureRequirementIfAreEqual<ushort>(
                        (ushort)PropertyType.PtypBoolean,
                        propertyType,
                        353,
                        @"[In PidTagDamBackPatched property] Type: PtypBoolean ([MS-OXCDATA] section 2.11.1).");
                }

                // If propertyId is 0x6646, it means the property is PidTagDamOriginalEntryId.
                if (propertyId == 0x6646)
                {
                    if (this.targetOfRop == TargetOfRop.ForDAM)
                    {
                        // Add the debug information.
                        Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R356");

                        // Verify MS-OXORULE requirement: MS-OXORULE_R356.
                        Site.CaptureRequirementIfAreEqual<ushort>(
                            (ushort)PropertyType.PtypBinary,
                            propertyType,
                            356,
                            @"[In PidTagDamOriginalEntryId] Type: PtypBinary ([MS-OXCDATA] section 2.11.1).");
                    }
                    else if (this.targetOfRop == TargetOfRop.ForDEM)
                    {
                        // Add the debug information. 
                        Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R712");

                        // Verify MS-OXORULE requirement: MS-OXORULE_R712.
                        Site.CaptureRequirementIfAreEqual<ushort>(
                            (ushort)PropertyType.PtypBinary,
                            propertyType,
                            712,
                            @"[In PidTagDamOriginalEntryId Property] Type: PtypBinary ([MS-OXCDATA] section 2.11.1).");
                    }
                }

                // If propertyId is 0x6681, it means the property is PidTagRuleProvider.
                if (propertyId == 0x6681)
                {
                    // Add the debug information.
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R358");

                    // Verify MS-OXORULE requirement: MS-OXORULE_R358.
                    Site.CaptureRequirementIfAreEqual<ushort>(
                        (ushort)PropertyType.PtypString,
                        propertyType,
                        358,
                        @"[In PidTagRuleProvider] Type: PtypString ([MS-OXCDATA] section 2.11.1).");
                }

                // If propertyId is 0x6651, it means the property is PidTagRuleFolderEntryId.
                if (propertyId == 0x6651)
                {
                    if (this.targetOfRop == TargetOfRop.ForDAM)
                    {
                        // Add the debug information.
                        Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R360");

                        // Verify MS-OXORULE requirement: MS-OXORULE_R360.
                        Site.CaptureRequirementIfAreEqual<ushort>(
                            (ushort)PropertyType.PtypBinary,
                            propertyType,
                            360,
                            @"[In PidTagRuleFolderEntryId] Type: PtypBinary ([MS-OXCDATA] section 2.11.1).");
                    }
                    else if (this.targetOfRop == TargetOfRop.ForDEM)
                    {
                        // Add the debug information. 
                        Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R714");

                        // Verify MS-OXORULE requirement: MS-OXORULE_R714.
                        Site.CaptureRequirementIfAreEqual<ushort>(
                            (ushort)PropertyType.PtypBinary,
                            propertyType,
                            714,
                            @"[In PidTagRuleFolderEntryId Property] Type: PtypBinary ([MS-OXCDATA] section 2.11.1).");
                    }
                }

                // If propertyId is 0x6645, it means the property is PidTagClientActions.
                if (propertyId == 0x6645)
                {
                    // Add the debug information.
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R362");

                    // Verify MS-OXORULE requirement: MS-OXORULE_R362.
                    Site.CaptureRequirementIfAreEqual<ushort>(
                        (ushort)PropertyType.PtypBinary,
                        propertyType,
                        362,
                        @"[In PidTagClientActions] Type: PtypBinary ([MS-OXCDATA] section 2.11.1).");

                    if (this.targetOfRop == TargetOfRop.ForDAM)
                    {
                        // Add the debug information.
                        Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R364");

                        // Verify MS-OXORULE requirement: MS-OXORULE_R364.
                        // Stack has constructed the rule action buffer according to section 2.2.5.
                        // If ruleAction is not null, it means the propertyValue of PidTagClientActions can be parsed as the RuleAction format successfully,
                        // which indicates this buffer has been packed according to this requirement.
                        RuleAction ruleAction = new RuleAction();
                        ruleAction = AdapterHelper.PropertyValueConvertToRuleAction(propertyValue);

                        Site.CaptureRequirementIfIsNotNull(
                            ruleAction,
                            364,
                            @"[In PidTagClientActions] The buffer MUST be packed according to the RuleAction structure specified in section 2.2.5.");
                    }
                }

                // If propertyId is 0x6675, it means the property is PidTagRuleIds.
                if (propertyId == 0x6675)
                {
                    // Add the debug information.
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R367");

                    // Verify MS-OXORULE requirement: MS-OXORULE_R367.
                    Site.CaptureRequirementIfAreEqual<ushort>(
                        (ushort)PropertyType.PtypBinary,
                        propertyType,
                        367,
                        @"[In PidTagRuleIds] Type: PtypBinary ([MS-OXCDATA] section 2.11.1).");

                    if (this.targetOfRop == TargetOfRop.ForDAM)
                    {
                        // Add the debug information.
                        Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R369");

                        // Verify MS-OXORULE requirement: MS-OXORULE_R369.
                        bool isVerifyR369 = AdapterHelper.PropertyValueConvertToBinary(propertyValue).Length % 8 == 0;

                        Site.CaptureRequirementIfIsTrue(
                            isVerifyR369,
                            369,
                            @"[In PidTagRuleIds] The length of this binary property[PidTagRuleIds] MUST be a multiple of 8 bytes.");
                    }
                }

                // If propertyId is 0x6741, it means the property is PidTagDeferredActionMessageOriginalEntryId.
                if (propertyId == 0x6741)
                {
                    // Add the debug information.
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R2704");

                    // Verify MS-OXCDATA requirement: MS-OXCDATA_R2704.
                    Site.CaptureRequirementIfAreEqual<ushort>(
                        0x00FB,
                        propertyType,
                        "MS-OXCDATA",
                        2704,
                        @"[In Property Value Types] PtypServerId (PT_SVREID) is that variable size; a 16-bit COUNT field followed by a structure specified in  section 2.11.1.4. with Property Type Value 0x00FB,%xFB.00.");

                    // Add the debug information.
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R370");

                    // Verify MS-OXORULE requirement: MS-OXORULE_R370.
                    Site.CaptureRequirementIfAreEqual<ushort>(
                        (ushort)PropertyType.PtypServerId,
                        propertyType,
                        370,
                        @"[In PidTagDeferredActionMessageOriginalEntryId Property] Type: PtypServerId ([MS-OXCDATA] section 2.11.1).");
                }

                // propertyID of PidTagHasDeferredActionMessages is 0x3FEA.
                if (propertyId == 0x3FEA)
                {
                    // Add the debug information.
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R722, the propertyType of the PidTagHasDeferredActionMessages is {0}", propertyType);

                    // Verify MS-OXORULE requirement: MS-OXORULE_R722.
                    Site.CaptureRequirementIfAreEqual<ushort>(
                        (ushort)PropertyType.PtypBoolean,
                        propertyType,
                        722,
                        @"[In PidTagHasDeferredActionMessages Property] Type: PtypBoolean ([MS-OXCDATA] section 2.11.1).");
                }

                // propertyID of PidTagRwRulesStream is 0x6802.
                if (propertyId == 0x6802)
                {
                    // Add the debug information.
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXORULE_R1010, the propertyType of the PidTagRwRulesStream is {0}", propertyType);

                    // Verify MS-OXORULE requirement: MS-OXORULE_R1010.
                    Site.CaptureRequirementIfAreEqual<ushort>(
                        (ushort)PropertyType.PtypBoolean,
                        propertyType,
                        1010,
                        @"[PidTagRwRulesStream Property] Type: PtypBinary ([MS-OXCDATA] section 2.11.1).");
                }
            }
        }
        /// <summary>
        /// Get the expected message properties included in a specific contents table after retry preconfigured times.
        /// </summary>
        /// <param name="folderHandle">Handle of a specific folder.</param>
        /// <param name="contentsTableHandle">Handle of a specific contents table.</param>
        /// <param name="propertyTagList">>Array of PropertyTag structures. This field specifies the property values that are visible in table rows.</param>
        /// <param name="expectedMessageIndex">The index of the specific message in the table.</param>
        /// <param name="expectedPropertyValue">The value of a specific property of the message to be found in the target mailbox.</param>
        /// <param name="expectedPropertyName">The property name of a specific property of the message to be found in the target mailbox, which type should be string. The default property name is PidTagSubject.</param>
        /// <returns>Response of the RopQueryRow ROP contents the expected message properties.</returns>
        protected RopQueryRowsResponse GetExpectedMessage(uint folderHandle, ref uint contentsTableHandle, PropertyTag[] propertyTagList, ref int expectedMessageIndex, string expectedPropertyValue, PropertyId expectedPropertyName = PropertyId.PidTagSubject)
        {
            RopQueryRowsResponse getNormalMailMessageContent = new RopQueryRowsResponse();
            uint repeatTime = 0;
            uint rowCount = 0;
            bool isExpectedPropertyInPropertyList = false;

            // If retry time more than expected, terminates the loop
            while (repeatTime < this.getMessageRepeatTime)
            {
                RopGetContentsTableResponse ropGetContentsTableResponse = this.OxoruleAdapter.RopGetContentsTable(folderHandle, ContentTableFlag.None, out contentsTableHandle);
                Site.Assert.AreEqual<uint>(0, ropGetContentsTableResponse.ReturnValue, "Getting contents table should succeed.");
                rowCount = ropGetContentsTableResponse.RowCount;
                repeatTime++;

                if (rowCount > 0)
                {
                    getNormalMailMessageContent = this.OxoruleAdapter.QueryPropertiesInTable(contentsTableHandle, propertyTagList);
                    Site.Assert.AreEqual<uint>(0, getNormalMailMessageContent.ReturnValue, "Getting mail message operation should succeed.");

                    for (int i = 0; i < propertyTagList.Length; i++)
                    {
                        if (propertyTagList[i].PropertyId == (ushort)expectedPropertyName)
                        {
                            isExpectedPropertyInPropertyList = true;
                            for (int j = 0; j < getNormalMailMessageContent.RowData.PropertyRows.Count; j++)
                            {
                                string propertyValue = AdapterHelper.PropertyValueConvertToString(getNormalMailMessageContent.RowData.PropertyRows[j].PropertyValues[i].Value);
                                if (propertyValue.Contains(expectedPropertyValue))
                                {
                                    expectedMessageIndex = j;
                                    return getNormalMailMessageContent;
                                }
                            }
                        }
                    }

                    Site.Assert.IsTrue(isExpectedPropertyInPropertyList, "The property {0} to be checked should be included in the property list.", expectedPropertyName.ToString());
                }

                if (repeatTime == this.getMessageRepeatTime)
                {
                    break;
                }

                Thread.Sleep(this.WaitForTheRuleToTakeEffect);
            }

            Site.Assert.Fail("Can't find the message which has a property {0} ant its value is {1} in the target mailbox.", expectedPropertyName.ToString(), expectedPropertyValue);
            return getNormalMailMessageContent;
        }
        /// <summary>
        /// Verify RopQueryRows Failure Response
        /// </summary>
        /// <param name="ropQueryRowsResponse">The response of RopQueryRows request</param>
        /// <param name="inputHandleIndex">The field of InputHandleIndex in RopQueryRows request</param>
        private void VerifyRopQueryRowsFailureResponse(RopQueryRowsResponse ropQueryRowsResponse, byte inputHandleIndex)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1193");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1193
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropQueryRowsResponse.RopId.GetType(),
                1193,
                @"[In RopQueryRows ROP Failure Response Buffer] RopId (1 byte): An unsigned integer.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1195");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1195
            Site.CaptureRequirementIfAreEqual<byte>(
                (byte)RopId.RopQueryRows,
                ropQueryRowsResponse.RopId,
                1195,
                @"[In RopQueryRows ROP Failure Response Buffer] RopId (1 byte): For this operation[RopQueryRows], this field[RopId (1 byte)] is set to 0x15.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1196");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1196
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropQueryRowsResponse.InputHandleIndex.GetType(),
                1196,
                @"[In RopQueryRows ROP Failure Response Buffer] InputHandleIndex (1 byte): An unsigned integer.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1197");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1197
            Site.CaptureRequirementIfAreEqual<byte>(
                inputHandleIndex,
                ropQueryRowsResponse.InputHandleIndex,
                1197,
                @"[In RopQueryRows ROP Failure Response Buffer] InputHandleIndex (1 byte): This index MUST be set to the value specified in the InputHandleIndex field in the request.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1198");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1198
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(uint),
                ropQueryRowsResponse.ReturnValue.GetType(),
                1198,
                @"[In RopQueryRows ROP Failure Response Buffer] ReturnValue (4 bytes): An unsigned integer.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1200");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1200
            Site.CaptureRequirementIfAreNotEqual<uint>(
                SuccessReturnValue,
                ropQueryRowsResponse.ReturnValue,
                1200,
                @"[In RopQueryRows ROP Failure Response Buffer] ReturnValue (4 bytes): For this response[Failure Response], this field is set to a value other than 0x00000000.");
        }
        /// <summary>
        /// Verify RopQueryRows Success Response
        /// </summary>
        /// <param name="ropQueryRowsResponse">The response of RopQueryRows request</param>
        /// <param name="inputHandleIndex">The field of InputHandleIndex in RopQueryRows request</param>
        /// <param name="propertyTags">Array of PropertyTag structures specifies the property values that are visible in table rows, set by a RopSetColumns request</param>
        private void VerifyRopQueryRowsSuccessResponse(RopQueryRowsResponse ropQueryRowsResponse, byte inputHandleIndex, PropertyTag[] propertyTags)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1176");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1176
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropQueryRowsResponse.RopId.GetType(),
                1176,
                @"[In RopQueryRows ROP Success Response Buffer] RopId (1 byte): An unsigned integer.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1178");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1178
            Site.CaptureRequirementIfAreEqual<byte>(
                (byte)RopId.RopQueryRows,
                ropQueryRowsResponse.RopId,
                1178,
                @"[In RopQueryRows ROP Success Response Buffer] RopId (1 byte): For this operation[RopQueryRows], this field[RopId (1 byte)] is set to 0x15.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1179");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1179
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropQueryRowsResponse.InputHandleIndex.GetType(),
                1179,
                @"[In RopQueryRows ROP Success Response Buffer] InputHandleIndex (1 byte): An unsigned integer.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1180");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1180
            Site.CaptureRequirementIfAreEqual<byte>(
                inputHandleIndex,
                ropQueryRowsResponse.InputHandleIndex,
                1180,
                @"[In RopQueryRows ROP Success Response Buffer] InputHandleIndex (1 byte): This index MUST be set to the value specified in the InputHandleIndex field in the request.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1181");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1181
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(uint),
                ropQueryRowsResponse.ReturnValue.GetType(),
                1181,
                @"[In RopQueryRows ROP Success Response Buffer] ReturnValue (4 bytes): An unsigned integer.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1183");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1183
            Site.CaptureRequirementIfAreEqual<uint>(
                SuccessReturnValue,
                ropQueryRowsResponse.ReturnValue,
                1183,
                @"[In RopQueryRows ROP Success Response Buffer] ReturnValue (4 bytes): For this response[Success Response], this field is set to 0x00000000.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1184");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1184
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropQueryRowsResponse.Origin.GetType(),
                1184,
                @"[In RopQueryRows ROP Success Response Buffer] Origin (1 byte): An enumeration.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1185,Origin:{0}", ropQueryRowsResponse.Origin);

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1185
            bool isVerifyR1185 = ((ropQueryRowsResponse.Origin & (byte)Origin.Beginning) == (byte)Origin.Beginning)
                                 || ((ropQueryRowsResponse.Origin & (byte)Origin.Current) == (byte)Origin.Current)
                                 || ((ropQueryRowsResponse.Origin & (byte)Origin.End) == (byte)Origin.End);

            Site.CaptureRequirementIfIsTrue(
                isVerifyR1185,
                1185,
                @"[In RopQueryRows ROP Success Response Buffer] Origin (1 byte): The possible values[the value of BOOKMARK_BEGINNING is 0x00, the value of BOOKMARK_CURRENT is 0x01 and the value of BOOKMARK_END is 0x02] for this enumeration are specified in [MS-OXCTABL] section 2.2.2.5.2.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1187");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1187
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(ushort),
                ropQueryRowsResponse.RowCount.GetType(),
                1187,
                @"[In RopQueryRows ROP Success Response Buffer] RowCount (2 bytes): An unsigned integer.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1189");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1189
            // The class PropertyRowSet is List of PropertRow, if the type of Rows is PropertyRowSet can verify R1189 
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(PropertyRowSet),
                ropQueryRowsResponse.RowData.GetType(),
                1189,
                @"[In RopQueryRows ROP Success Response Buffer] RowData (variable): A list of PropertyRow structures.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1190");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1190
            Site.CaptureRequirementIfAreEqual<ushort>(
                ropQueryRowsResponse.RowCount,
                (ushort)ropQueryRowsResponse.RowData.Count,
                1190,
                @"[In RopQueryRows ROP Success Response Buffer] RowData (variable): The number of structures contained in this field is specified by the RowCount field.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1192,RowData:{0}", ropQueryRowsResponse.RowData);

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1192
            // Assume the result is true. If one of rows element's count is not equal to the columns count, then false.
            bool isVerifyR1192 = true;
            foreach (PropertyRow propertyRow in ropQueryRowsResponse.RowData.PropertyRows)
            {
                isVerifyR1192 = isVerifyR1192 && (propertyRow.PropertyValues.Count == propertyTags.Length);

                // If one row element's count is not equal to the columns count then break the iteration
                if (!isVerifyR1192)
                {
                    break;
                }
            }

            Site.CaptureRequirementIfIsTrue(
                isVerifyR1192,
                1192,
                @"[In RopQueryRows ROP Success Response Buffer] RowData (variable): The columns used for these rows were those previously set on this table by a RopSetColumns ROP request (section 2.2.5.1).");
        }