Example #1
0
        /// <summary>
        /// The GetListItemChangesSinceToken operation is used to return changes made to a specified list after the event
        /// expressed by the change token, if specified, or to return all the list items in the list.
        /// </summary>
        /// <param name="listName">The name of the list from which version collection will be got</param>
        /// <param name="viewName">The GUID refers to a view of the list</param>
        /// <param name="query">The query to determine which records from the list are to be
        /// returned and the order in which they will be returned</param>
        /// <param name="viewFields">Specifies which fields of the list item will be returned</param>
        /// <param name="rowLimit">Indicate the maximum number of rows of data to return</param>
        /// <param name="queryOptions">Specifies various options for modifying the query</param>
        /// <param name="changeToken">Assigned a string comprising a token returned by a previous
        /// call to this operation.</param>
        /// <param name="contains">Specifies a value to search for</param>
        /// <returns>A return value represent the list item changes since the specified token</returns>
        public GetListItemChangesSinceTokenResponseGetListItemChangesSinceTokenResult GetListItemChangesSinceToken(string listName, string viewName, GetListItemChangesSinceTokenQuery query, CamlViewFields viewFields, string rowLimit, CamlQueryOptions queryOptions, string changeToken, CamlContains contains)
        {
            if (null == this.listsProxy)
            {
                throw new InvalidOperationException("The Proxy instance is NULL, need to initialize the adapter");
            }

            GetListItemChangesSinceTokenResponseGetListItemChangesSinceTokenResult result = null;

            result = this.listsProxy.GetListItemChangesSinceToken(listName, viewName, query, viewFields, rowLimit, queryOptions, changeToken, contains);
            this.VerifyTransportRequirement();
            this.VerifyGetListItemChangesSinceTokenResponse(result);

            return(result);
        }
Example #2
0
        /// <summary>
        /// A method used to get IF-MATCH header value by specified attachment url.
        /// </summary>
        /// <param name="getListItemChangesRes">A parameter represents a response of "GetListItemChangesSinceToken" operation where method will find the expected IF-MATCH header value.</param>
        /// <param name="attachmentFullUrl">A parameter represents the full url of attachment which is used to match attachment field value.</param>
        /// <param name="listItemId">A parameter represents the list item id of a list item where the attachment is added.</param>
        /// <returns>A return value represents the expected IF-MATCH header value.</returns>
        private string GetIfMatchHeaderValueFromResponse(GetListItemChangesSinceTokenResponseGetListItemChangesSinceTokenResult getListItemChangesRes, string attachmentFullUrl, int listItemId)
        {
            if (null == getListItemChangesRes || null == getListItemChangesRes.listitems || null == getListItemChangesRes.listitems.data ||
                null == getListItemChangesRes.listitems.data.Any)
            {
                throw new ArgumentException("Should contain valid item changed data.", "getListItemChangesRes");
            }

            if (listItemId <= 0)
            {
                throw new ArgumentException("The value should be large than Zero.", "listItemId");
            }

            if (string.IsNullOrEmpty(attachmentFullUrl))
            {
                throw new ArgumentException("The value should have non-empty string value", "attachmentFullUrl");
            }

            if (0 == getListItemChangesRes.listitems.data.Any.Length)
            {
                throw new InvalidOperationException("Could not get the attachment changed record.");
            }

            // Get attachment field value.
            XmlNode[] changesRecords       = this.GetZrowItems(getListItemChangesRes.listitems.data.Any);
            string    attachmentFieldValue = Common.GetZrowAttributeValue(changesRecords, listItemId - 1, "ows_attachments");

            if (!attachmentFieldValue.StartsWith(@";#", StringComparison.OrdinalIgnoreCase))
            {
                this.Site.Assert.Fail("the attachment field value must begin with [;#].");
            }

            if (!attachmentFieldValue.EndsWith(@";#", StringComparison.OrdinalIgnoreCase))
            {
                this.Site.Assert.Fail("the attachment field value must end with [;#].");
            }

            string[] splitValues = attachmentFieldValue.Split(new string[] { @";#" }, StringSplitOptions.RemoveEmptyEntries);

            // The parse logic is described in MS-LISTSWS section 2.2.4.4
            string expectedHeaderValue = string.Empty;

            for (int index = 0; index < splitValues.Length; index++)
            {
                if (splitValues[index].Equals(attachmentFullUrl, StringComparison.OrdinalIgnoreCase) &&
                    index + 1 < splitValues.Length)
                {
                    expectedHeaderValue = splitValues[index + 1];
                    break;
                }
            }

            if (string.IsNullOrEmpty(expectedHeaderValue))
            {
                string errorMsg = string.Format("Could not find expected [IF-Match] header value by specified attachment url[{0}]", attachmentFullUrl);
                this.Site.Assert.Fail(errorMsg);
            }

            expectedHeaderValue = string.Format(@"""{0}""", expectedHeaderValue);
            return(expectedHeaderValue);
        }
Example #3
0
        public void MSOUTSPS_S01_TC04_OperateAttachment_TasksTemplateType()
        {
            #region Add a list item

            // Add one list into SUT.
            string listId = this.AddListToSUT(TemplateType.Tasks);

            // Add one list item
            List <string> addedListitems    = this.AddItemsToList(listId, 1);
            string        addedListitemId   = addedListitems[0];
            byte[]        attachmentContent = this.GenerateUniqueAttachmentContents(5);
            string        attachmentName    = this.GetUniqueAttachmentName();

            #endregion

            #region AddAttachment operation

            // Call AddAttachment operation.
            OutspsAdapter.AddAttachment(
                listId,
                addedListitemId,
                attachmentName,
                attachmentContent);

            #endregion

            #region HTTPGET operation

            // Get full URL of an attachment
            string fullUrlOfAttachment = this.GetAttachmentFullUrl(listId, addedListitemId, attachmentName);

            // Call HTTPGET operation.
            Uri fullUrlOfAttachmentPath;
            if (!Uri.TryCreate(fullUrlOfAttachment, UriKind.RelativeOrAbsolute, out fullUrlOfAttachmentPath))
            {
                this.Site.Assert.Fail("The full url of attachment should be valid Uri format string.");
            }

            byte[] getContentsOfAttachment = OutspsAdapter.HTTPGET(fullUrlOfAttachmentPath, "f");

            this.Site.Assert.AreEqual <int>(
                attachmentContent.Length,
                getContentsOfAttachment.Length,
                "The attachment content's length should equal to added by AddAttachment operation.");

            #endregion

            #region GetAttachmentCollection operation

            byte[] attachmentContentSecond = this.GenerateUniqueAttachmentContents(5);
            string attachmentNameSecond    = this.GetUniqueAttachmentName();

            // Call the AddAttachment operation.
            OutspsAdapter.AddAttachment(
                listId,
                addedListitemId,
                attachmentNameSecond,
                attachmentContentSecond);

            // Call GetAttachmentCollection operation.
            GetAttachmentCollectionResponseGetAttachmentCollectionResult getAttachementCollectionResult = OutspsAdapter.GetAttachmentCollection(listId, addedListitemId);

            // If add new attachment successfully, total attachment number is 2
            this.VerifyWhetherContainExpectedNumberAttachment(getAttachementCollectionResult, 2);

            #endregion

            if (Common.IsRequirementEnabled(106802, this.Site))
            {
                #region GetListItemChangesSinceToken operation

                // Set CamlQueryOptions and view fields make the "attachment" field present in response.
                CamlQueryOptions camloptions = new CamlQueryOptions();
                camloptions.QueryOptions = new CamlQueryOptionsQueryOptions();
                camloptions.QueryOptions.IncludeAttachmentUrls    = bool.TrueString;
                camloptions.QueryOptions.IncludeAttachmentVersion = bool.TrueString;
                CamlViewFields viewfieds = this.GenerateViewFields(false, new List <string> {
                    "Attachments"
                });

                // Call GetListItemChangesSinceToken operation.
                GetListItemChangesSinceTokenResponseGetListItemChangesSinceTokenResult getlistItemChangesRes = null;
                getlistItemChangesRes = OutspsAdapter.GetListItemChangesSinceToken(
                    listId,
                    null,
                    null,
                    viewfieds,
                    null,
                    camloptions,
                    null,
                    null);

                this.Site.Assert.IsNotNull(getlistItemChangesRes, "SUT should return a response contain data.");
                string headerValue = this.GetIfMatchHeaderValueFromResponse(getlistItemChangesRes, fullUrlOfAttachment, int.Parse(addedListitemId));

                #endregion

                #region HTTPPUT operation

                // Call HTTPPUT operation.
                fullUrlOfAttachmentPath = null;
                if (!Uri.TryCreate(fullUrlOfAttachment, UriKind.RelativeOrAbsolute, out fullUrlOfAttachmentPath))
                {
                    this.Site.Assert.Fail("The full url of attachment should be valid Uri format string.");
                }

                byte[] newattachmentContents = this.GenerateUniqueAttachmentContents(6);
                OutspsAdapter.HTTPPUT(fullUrlOfAttachmentPath, headerValue, newattachmentContents);

                // Verify updated attachment.
                this.VerifyAttachmentContentsLength(fullUrlOfAttachment, newattachmentContents.Length);
                #endregion
            }

            OutspsAdapter.DeleteAttachment(listId, addedListitemId, fullUrlOfAttachment);

            // Verify whether delete attachment succeed.
            this.VerifyDeleteAttachmentSucceed(fullUrlOfAttachment);
        }
Example #4
0
        public void MSOUTSPS_S01_TC01_OperateAttachment_AppointmentTemplateType()
        {
            #region Add a list item

            // Add one list into SUT.
            string listId = this.AddListToSUT(TemplateType.Events);

            // Add one list item
            List <string> addedListitems    = this.AddItemsToList(listId, 1);
            string        addedListitemId   = addedListitems[0];
            byte[]        attachmentContent = this.GenerateUniqueAttachmentContents(5);
            string        attachmentName    = this.GetUniqueAttachmentName();

            #endregion

            #region AddAttachment operation

            // Call AddAttachment operation.
            string fileUrl = OutspsAdapter.AddAttachment(
                listId,
                addedListitemId,
                attachmentName,
                attachmentContent);

            #endregion

            #region HTTPGET operation

            // Get full URL of an attachment
            string fullUrlOfAttachment = this.GetAttachmentFullUrl(listId, addedListitemId, attachmentName);
            Uri    fullUrlOfAttachmentPath;
            if (!Uri.TryCreate(fullUrlOfAttachment, UriKind.RelativeOrAbsolute, out fullUrlOfAttachmentPath))
            {
                this.Site.Assert.Fail("The full url of attachment should be valid Uri format string.");
            }

            // Call HTTPGET operation.
            byte[] getContentsOfAttachment = OutspsAdapter.HTTPGET(fullUrlOfAttachmentPath, "f");

            #endregion

            #region Capture R1062, R1070, R1073, R1075

            // If the length of attachment content in protocol SUT equal to added by AddAttachment operation, then capture R1062, R1070, R1073
            Site.CaptureRequirementIfAreEqual(
                attachmentContent.Length,
                getContentsOfAttachment.Length,
                1062,
                "[In Message Processing Events and Sequencing Rules][The operation]AddAttachment Adds an attachment to an item.");

            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1070
            Site.CaptureRequirementIfAreEqual(
                attachmentContent.Length,
                getContentsOfAttachment.Length,
                1070,
                "[In AddAttachment]AddAttachment is used by protocol clients to create a new attachment on an item on the protocol server.");

            // Verify MS-OUTSPS requirement: MS-OUTSPS_R10730
            Site.CaptureRequirementIfAreEqual(
                attachmentContent.Length,
                getContentsOfAttachment.Length,
                10730,
                "[In Messages]AddAttachmentResponse specified the response to a request to create a new attachment on an item on the protocol server.");

            // If the AddAttachment operation return valid attachment url, then Capture R1075
            Site.CaptureRequirementIfIsNotNull(
                fileUrl,
                1075,
                "[In AddAttachmentResponse]If an AddAttachmentResponse is received, then the upload was successful.");

            #endregion

            #region GetAttachmentCollection operation

            byte[] attachmentContentSecond = this.GenerateUniqueAttachmentContents(5);
            string attachmentNameSecond    = this.GetUniqueAttachmentName();

            // Call the AddAttachment operation.
            OutspsAdapter.AddAttachment(
                listId,
                addedListitemId,
                attachmentNameSecond,
                attachmentContentSecond);

            // Call GetAttachmentCollection operation.
            GetAttachmentCollectionResponseGetAttachmentCollectionResult getAttachementCollectionResult = OutspsAdapter.GetAttachmentCollection(listId, addedListitemId);

            #endregion

            #region Capture R1065, R11000

            // If add new attachment successfully, total attachment number is 2, Capture R1065, R11000
            bool isContainExpectedAttachment = this.VerifyWhetherContainExpectedNumberAttachment(getAttachementCollectionResult, 2);

            this.Site.CaptureRequirementIfIsTrue(
                isContainExpectedAttachment,
                1065,
                "[In Message Processing Events and Sequencing Rules][The operation]GetAttachmentCollection Gets a list of the attachments on an item.");

            this.Site.CaptureRequirementIfIsTrue(
                isContainExpectedAttachment,
                11000,
                "[In Messages]GetAttachmentCollectionResponse specified the response to a request to get the list of all attachments on a single item in one list.");

            #endregion

            if (Common.IsRequirementEnabled(106802, this.Site))
            {
                #region GetListItemChangesSinceToken operation

                // Set CamlQueryOptions and view fields make the "attachment" field present in response.
                CamlQueryOptions camloptions = new CamlQueryOptions();
                camloptions.QueryOptions = new CamlQueryOptionsQueryOptions();
                camloptions.QueryOptions.IncludeAttachmentUrls    = bool.TrueString;
                camloptions.QueryOptions.IncludeAttachmentVersion = bool.TrueString;
                CamlViewFields viewfieds = this.GenerateViewFields(false, new List <string> {
                    "Attachments"
                });

                // Call GetListItemChangesSinceToken operation.
                GetListItemChangesSinceTokenResponseGetListItemChangesSinceTokenResult getListItemChangesRes = null;
                getListItemChangesRes = OutspsAdapter.GetListItemChangesSinceToken(
                    listId,
                    null,
                    null,
                    viewfieds,
                    null,
                    camloptions,
                    null,
                    null);

                this.Site.Assert.IsNotNull(getListItemChangesRes, "SUT should return a response contain data.");
                string headerValue = this.GetIfMatchHeaderValueFromResponse(getListItemChangesRes, fullUrlOfAttachment, int.Parse(addedListitemId));

                #endregion

                #region Capture R1241

                // If the header is returned, then R1241 should be covered.
                this.Site.CaptureRequirementIfIsNotNull(
                    headerValue,
                    1241,
                    "[In HTTP PUT]The Attachments property MUST contain a file version if protocol clients have included the IncludeAttachmentUrls and IncludeAttachmentVersion elements specified in [MS-LISTSWS].");

                #endregion

                #region HTTPPUT operation

                // Call HTTPPUT operation to update the attachment contents for the first attachment.
                fullUrlOfAttachmentPath = null;
                if (!Uri.TryCreate(fullUrlOfAttachment, UriKind.RelativeOrAbsolute, out fullUrlOfAttachmentPath))
                {
                    this.Site.Assert.Fail("The full url of attachment should be valid Uri format string.");
                }

                byte[] newattachmentContents = this.GenerateUniqueAttachmentContents(6);
                OutspsAdapter.HTTPPUT(fullUrlOfAttachmentPath, headerValue, newattachmentContents);

                // Verify the updated attachment contents' length
                this.VerifyAttachmentContentsLength(fullUrlOfAttachment, newattachmentContents.Length);

                #endregion
            }

            OutspsAdapter.DeleteAttachment(listId, addedListitemId, fullUrlOfAttachment);

            #region Capture R10930

            // If the operation does not return SoapException, capture R10930 directly. Because the schema of the DeleteAttachmentResponse define in [MS-LISTSWS]: <s:element name="DeleteAttachmentResponse"><s:complexType/></s:element>, does not contain any complex type definition, so the proxy class marked this operation as void type return.
            this.Site.CaptureRequirement(
                10930,
                "[In Messages]DeleteAttachmentResponse specified the response to a request to delete attachments from an item on the protocol server.");

            #endregion

            // Verify whether the attachment was deleted.
            bool isDeleteSucceed = this.VerifyDeleteAttachmentSucceed(fullUrlOfAttachment);

            #region Capture R1064, R1091

            // Because the specified attachment was deleted, the HTTPGET operation could not find it, so there will have a soap exception.
            this.Site.CaptureRequirementIfIsTrue(
                isDeleteSucceed,
                1064,
                @"[In Message Processing Events and Sequencing Rules][The operation]DeleteAttachment Deletes an attachment from an item on a list.");

            this.Site.CaptureRequirementIfIsTrue(
                isDeleteSucceed,
                1091,
                @"[In DeleteAttachment]Protocol clients use DeleteAttachment to delete attachments from an item on the protocol server.");

            #endregion
        }
        /// <summary>
        /// A method used to verify response of GetGetListItemChangesSinceToken operation and capture related requirements.
        /// </summary>
        /// <param name="responseOfGetGetListItemChangesSinceToken">A parameter represents the response of GetGetListItemChangesSinceToken operation where this method perform the verification.</param>
        private void VerifyGetListItemChangesSinceTokenResponse(GetListItemChangesSinceTokenResponseGetListItemChangesSinceTokenResult responseOfGetGetListItemChangesSinceToken)
        {
            if (null == responseOfGetGetListItemChangesSinceToken)
            {
                throw new ArgumentNullException("responseOfGetGetListItemChangesSinceToken");
            }

            string formatedErrorMessage = @"The [{0}] should present in response of GetListItemChangesSinceToken operation.";
            this.Site.Assert.IsNotNull(
                                responseOfGetGetListItemChangesSinceToken.listitems,
                                formatedErrorMessage,
                                "listitems");
            GetListItemChangesSinceTokenResponseGetListItemChangesSinceTokenResultListitems listitemsIntance = responseOfGetGetListItemChangesSinceToken.listitems;

            // If the Changes.Id element is present in the response, it means there are special changes for stored data of list items, so that the protocol SUT does not query the information for list items, such as the list items are in Restore, Move, InvalidToken, Delete. The code return now since the expected data needed below will not be present in response.
            if (listitemsIntance.Changes.Id != null && listitemsIntance.Changes.Id.ChangeTypeSpecified)
            {
                return;
            }

            // If the protocol SUT query the valid changes and put them in the response and the AlternateUrls is not null or empty, then capture R1222
            this.Site.Assert.IsFalse(
                                    string.IsNullOrEmpty(listitemsIntance.AlternateUrls),
                                    formatedErrorMessage,
                                    "AlternateUrls");

            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1222
            this.Site.CaptureRequirement(
                                    1222,
                                    @"[In GetListItemChangesSinceTokenResponse][The element]AlternateUrl is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");

            // If there are any list items change data, then perform the verification. 
            if (!listitemsIntance.data.ItemCount.Equals("0"))
            {
                // If the EffectivePermMask is not null or empty, then capture R1227
                this.Site.Assert.IsFalse(
                                      string.IsNullOrEmpty(listitemsIntance.EffectivePermMask),
                                      formatedErrorMessage,
                                      "EffectivePermMask");

                // Verify MS-OUTSPS requirement: MS-OUTSPS_R1227
                this.Site.CaptureRequirement(
                                        1227,
                                        @"[In GetListItemChangesSinceTokenResponse][The element]EffectivePermMask is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");
            }
         
            // If the MaxBulkDocumentSyncSize is not null or empty, then capture R1228
            this.Site.Assert.IsTrue(
                                  listitemsIntance.MaxBulkDocumentSyncSizeSpecified,
                                  formatedErrorMessage,
                                  "MaxBulkDocumentSyncSize");

            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1228
            this.Site.CaptureRequirement(
                                    1228,
                                    @"[In GetListItemChangesSinceTokenResponse][The element]MaxBulkDocumentSyncSize is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");

            // If the MinTimeBetweenSyncs is not null or empty, then capture R1229
            this.Site.Assert.IsTrue(
                                  listitemsIntance.MinTimeBetweenSyncsSpecified,
                                  formatedErrorMessage,
                                  "MinTimeBetweenSyncs");

            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1229
            this.Site.CaptureRequirement(
                                   1229,
                                   @"[In GetListItemChangesSinceTokenResponse][The element]MinTimeBetweenSyncs is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");

            // If the RecommendedTimeBetweenSyncs is not null or empty, then capture R1230
            this.Site.Assert.IsTrue(
                                  listitemsIntance.RecommendedTimeBetweenSyncsSpecified,
                                  formatedErrorMessage,
                                  "RecommendedTimeBetweenSyncs");

            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1230
            this.Site.CaptureRequirement(
                                   1230,
                                   @"[In GetListItemChangesSinceTokenResponse][The element]RecommendedTimeBetweenSyncs is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");

            // Verify whether the changes element have instance.
            this.Site.Assert.IsNotNull(
                                   listitemsIntance.Changes,
                                    formatedErrorMessage,
                                    "Changes");

            // If the Changes.LastChangeToken is not null, then capture R1224.
            this.Site.Assert.IsFalse(
                                string.IsNullOrEmpty(listitemsIntance.Changes.LastChangeToken),
                                formatedErrorMessage,
                                "LastChangeToken");

            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1224
            this.Site.CaptureRequirement(
                                    1224,
                                    @"[In GetListItemChangesSinceTokenResponse][The attribute]Changes.LastChangeToken is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");

            // If upon verification pass, then capture R1221
            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1221
            this.Site.CaptureRequirement(
                                    1221,
                                    @"[In GetListItemChangesSinceTokenResponse]Each of these[AlternateUrls,Changes.Id.ChangeType,Changes.data.ListItemCollectionPositionNext,Changes.LastChangeToken,Changes.MoreChanges,EffectivePermMask,MaxBulkDocumentSyncSize,MinTimeBetweenSyncs,RecommendedTimeBetweenSyncs] is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");
        }
Example #6
0
        /// <summary>
        /// A method used to verify response of GetGetListItemChangesSinceToken operation and capture related requirements.
        /// </summary>
        /// <param name="responseOfGetGetListItemChangesSinceToken">A parameter represents the response of GetGetListItemChangesSinceToken operation where this method perform the verification.</param>
        private void VerifyGetListItemChangesSinceTokenResponse(GetListItemChangesSinceTokenResponseGetListItemChangesSinceTokenResult responseOfGetGetListItemChangesSinceToken)
        {
            if (null == responseOfGetGetListItemChangesSinceToken)
            {
                throw new ArgumentNullException("responseOfGetGetListItemChangesSinceToken");
            }

            string formatedErrorMessage = @"The [{0}] should present in response of GetListItemChangesSinceToken operation.";

            this.Site.Assert.IsNotNull(
                responseOfGetGetListItemChangesSinceToken.listitems,
                formatedErrorMessage,
                "listitems");
            GetListItemChangesSinceTokenResponseGetListItemChangesSinceTokenResultListitems listitemsIntance = responseOfGetGetListItemChangesSinceToken.listitems;

            // If the Changes.Id element is present in the response, it means there are special changes for stored data of list items, so that the protocol SUT does not query the information for list items, such as the list items are in Restore, Move, InvalidToken, Delete. The code return now since the expected data needed below will not be present in response.
            if (listitemsIntance.Changes.Id != null && listitemsIntance.Changes.Id.ChangeTypeSpecified)
            {
                return;
            }

            // If the protocol SUT query the valid changes and put them in the response and the AlternateUrls is not null or empty, then capture R1222
            this.Site.Assert.IsFalse(
                string.IsNullOrEmpty(listitemsIntance.AlternateUrls),
                formatedErrorMessage,
                "AlternateUrls");

            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1222
            this.Site.CaptureRequirement(
                1222,
                @"[In GetListItemChangesSinceTokenResponse][The element]AlternateUrl is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");

            // If there are any list items change data, then perform the verification.
            if (!listitemsIntance.data.ItemCount.Equals("0"))
            {
                // If the EffectivePermMask is not null or empty, then capture R1227
                this.Site.Assert.IsFalse(
                    string.IsNullOrEmpty(listitemsIntance.EffectivePermMask),
                    formatedErrorMessage,
                    "EffectivePermMask");

                // Verify MS-OUTSPS requirement: MS-OUTSPS_R1227
                this.Site.CaptureRequirement(
                    1227,
                    @"[In GetListItemChangesSinceTokenResponse][The element]EffectivePermMask is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");
            }

            // If the MaxBulkDocumentSyncSize is not null or empty, then capture R1228
            this.Site.Assert.IsTrue(
                listitemsIntance.MaxBulkDocumentSyncSizeSpecified,
                formatedErrorMessage,
                "MaxBulkDocumentSyncSize");

            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1228
            this.Site.CaptureRequirement(
                1228,
                @"[In GetListItemChangesSinceTokenResponse][The element]MaxBulkDocumentSyncSize is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");

            // If the MinTimeBetweenSyncs is not null or empty, then capture R1229
            this.Site.Assert.IsTrue(
                listitemsIntance.MinTimeBetweenSyncsSpecified,
                formatedErrorMessage,
                "MinTimeBetweenSyncs");

            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1229
            this.Site.CaptureRequirement(
                1229,
                @"[In GetListItemChangesSinceTokenResponse][The element]MinTimeBetweenSyncs is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");

            // If the RecommendedTimeBetweenSyncs is not null or empty, then capture R1230
            this.Site.Assert.IsTrue(
                listitemsIntance.RecommendedTimeBetweenSyncsSpecified,
                formatedErrorMessage,
                "RecommendedTimeBetweenSyncs");

            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1230
            this.Site.CaptureRequirement(
                1230,
                @"[In GetListItemChangesSinceTokenResponse][The element]RecommendedTimeBetweenSyncs is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");

            // Verify whether the changes element have instance.
            this.Site.Assert.IsNotNull(
                listitemsIntance.Changes,
                formatedErrorMessage,
                "Changes");

            // If the Changes.LastChangeToken is not null, then capture R1224.
            this.Site.Assert.IsFalse(
                string.IsNullOrEmpty(listitemsIntance.Changes.LastChangeToken),
                formatedErrorMessage,
                "LastChangeToken");

            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1224
            this.Site.CaptureRequirement(
                1224,
                @"[In GetListItemChangesSinceTokenResponse][The attribute]Changes.LastChangeToken is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");

            // If upon verification pass, then capture R1221
            // Verify MS-OUTSPS requirement: MS-OUTSPS_R1221
            this.Site.CaptureRequirement(
                1221,
                @"[In GetListItemChangesSinceTokenResponse]Each of these[AlternateUrls,Changes.Id.ChangeType,Changes.data.ListItemCollectionPositionNext,Changes.LastChangeToken,Changes.MoreChanges,EffectivePermMask,MaxBulkDocumentSyncSize,MinTimeBetweenSyncs,RecommendedTimeBetweenSyncs] is contained within GetListItemChangesSinceTokenResponse.GetListItemChangesSinceTokenResult.listitems, as specified by [MS-LISTSWS].");
        }
        /// <summary>
        /// Verify the message syntax of GetListItemChangesSinceToken operation when the response 
        /// is received successfully.
        /// </summary>
        /// <param name="getListItemChangesSinceTokenResult">The result of the operation</param>
        /// <param name="queryOptions">Specifies various options for modifying the query</param>
        /// <param name="viewFields">Specifies which fields of the list item will be returned</param>
        private void VerifyGetListItemChangesSinceTokenOperation(
            GetListItemChangesSinceTokenResponseGetListItemChangesSinceTokenResult getListItemChangesSinceTokenResult,
            CamlQueryOptions queryOptions,
            CamlViewFields viewFields)
        {
            // Ensure the SOAP result is de-serialized successfully.
            Site.Assume.IsNotNull(getListItemChangesSinceTokenResult, "The result of GetListItemChangesSinceToken operation must not be null.");

            // Verify R1876
            // The response have been received successfully, then the following requirement can be captured.
            // If the response is not received and parsed successfully, the test case will fail before this requirement is captured 
            Site.CaptureRequirement(
                1876,
                @"[The schema of GetListItemChangesSinceToken is defined as:]"
                + @"<wsdl:operation name=""GetListItemChangesSinceToken"">"
                + @"    <wsdl:input message=""GetListItemChangesSinceTokenSoapIn"" />"
                + @"    <wsdl:output message=""GetListItemChangesSinceTokenSoapOut"" />"
                + @"</wsdl:operation>");

            // Verify R654
            // The response have been received successfully, then the following requirement can be captured.
            // If the response is not received and parsed successfully, the test case will fail before this requirement is captured 
            Site.CaptureRequirement(
                654,
                @"[In GetListItemChangesSinceToken operation] [If the protocol client sends a "
                + "GetListItemChangesSinceTokenSoapIn request message] the protocol server "
                + "responds with a GetListItemChangesSinceTokenSoapOut response message.");

            // Verify R1882
            // The response have been received successfully, then the following requirement can be captured.
            // If the response is not received and parsed successfully, the test case will fail before this requirement is captured 
            Site.CaptureRequirement(
                1882,
                @"[GetListItemChangesSinceTokenSoapOut]The SOAP Body contains a "
                + "GetListItemChangesSinceTokenResponse element.");

            // Verify R1897
            // The response have been received successfully, then the following requirement can be captured.
            // If the response is not received and parsed successfully, the test case will fail before this requirement is captured 
            Site.CaptureRequirement(
                1897,
                @"[The schema of GetListItemChangesSinceTokenResponse is defined as:] <s:element name=""GetListItemChangesSinceTokenResponse"">
              <s:complexType>
                <s:sequence>
                    <s:element minOccurs=""0"" maxOccurs=""1"" name=""GetListItemChangesSinceTokenResult"">
                     <s:complexType mixed=""true"">
                      <s:sequence>
                        <s:element name=""listitems"" >
                          <s:complexType>
                            <s:sequence>
                              <s:element name=""Changes"" >
                                <s:complexType>
                                  <s:sequence>
                                    <s:element name=""List"" type=""tns:ListDefinitionSchema""  
                                               minOccurs=""0"" />
                                    <s:element name=""Id"" type=""tns:ListItemChangeDefinition"" minOccurs=""0""/>                      
                                  </s:sequence>
                                  <s:attribute name=""LastChangeToken"" type=""s:string"" />
                                  <s:attribute name=""MoreChanges"" type=""core:TRUEFALSE"" />
                                  <s:attribute name=""MinTimeBetweenSyncs"" type=""s:unsignedInt"" />
                                  <s:attribute name=""RecommendedTimeBetweenSyncs"" type=""s:unsignedInt"" />
                                  <s:attribute name=""MaxBulkDocumentSyncSize"" type=""s:unsignedInt"" />
                                  <s:attribute name=""MaxRecommendedEmbeddedFileSize"" type=""s:unsignedInt"" />
                                  <s:attribute name=""AlternateUrls"" type=""s:string"" />
                                  <s:attribute name=""EffectivePermMask"" type=""s:string"" />
                                </s:complexType>
                              </s:element>
                              <s:any />
                            </s:sequence> 
                          </s:complexType>
                        </s:element>
                      </s:sequence>
                    </s:complexType>
                  </s:element>
                </s:sequence>     
              </s:complexType>
            </s:element>");

            // Verify R1898
            // The response have been received successfully, then the following requirement can be captured.
            // If the response is not received and parsed successfully, the test case will fail before this requirement is captured 
            Site.CaptureRequirement(
                1898,
                @"[GetListItemChangesSinceTokenResponse]GetListItemChangesSinceTokenResult:  The top-level element, which contains a listitems element.");

            // Verify R1908
            // In MS-LISTSWS.wsdl. The 'any' element has been replaced by rs:data.
            // The response have been received successfully, then the following requirement can be captured.
            // If the response is not received and parsed successfully, the test case will fail before this requirement is captured 
            Site.CaptureRequirement(
                1908,
                @"[GetListItemChangesSinceTokenResponse]The listitems element also contains an inner element named rs:data, which is of type DataDefinition ListItemCollectionPositionNext (section 2.2.4.7).");

            // Verify R2486
            if (Common.IsRequirementEnabled(2486, this.Site))
            {
                if (getListItemChangesSinceTokenResult.listitems.Changes.List != null)
                {
                    bool isFileFragmentExist = getListItemChangesSinceTokenResult.listitems.Changes.List.Fields.Field.Any(field => field.Name == "FileFragment");
                    Site.CaptureRequirementIfIsFalse(
                        isFileFragmentExist,
                        2486,
                        @"[In GetListItemChangesSinceToken operation]Implementation does not return the FileFragment element.[In Appendix B: Product Behavior] <61> Section 3.1.4.22.2.2: In Windows SharePoint Services 3.0, the FileFragment element is not returned.");
                }
            }

            // Verify the requirements of the DataDefinition complex type.
            if (getListItemChangesSinceTokenResult.listitems.data != null)
            {
                this.VerifyDataDefinition(getListItemChangesSinceTokenResult.listitems.data);
            }

            // Verify the requirements of the ListDefinitionSchema complex type.
            if (getListItemChangesSinceTokenResult.listitems.Changes.List != null)
            {
                this.VerifyListDefinitionSchema(getListItemChangesSinceTokenResult.listitems.Changes.List);
            }

            // Verify the requirements of the ListItemChangeDefinition complex type.
            if (null != getListItemChangesSinceTokenResult.listitems && null != getListItemChangesSinceTokenResult.listitems.Changes
                && null != getListItemChangesSinceTokenResult.listitems.Changes && null != getListItemChangesSinceTokenResult.listitems.Changes.Id)
            {
                this.VerifyListItemChangeDefinition(getListItemChangesSinceTokenResult.listitems.Changes.Id);
                this.VerifyServerChangeUnitAttributeNotReturn(getListItemChangesSinceTokenResult.listitems.Changes.Id);
            }

            // Verify the requirements of the EnumViewAttributes simple type.
            if (queryOptions != null)
            {
                if (getListItemChangesSinceTokenResult.listitems.data.Any != null)
                {
                    DataTable data = AdapterHelper.ExtractData(getListItemChangesSinceTokenResult.listitems.data.Any);
                    string author = data.Columns.Contains("ows_Author") ? Convert.ToString(data.Rows[0]["ows_Author"]) : null;
                    this.VerifyCamlQueryOptions(queryOptions, viewFields, author);
                }

                if (queryOptions.QueryOptions != null)
                {
                    if (queryOptions.QueryOptions.ViewAttributes != null)
                    {
                        if (queryOptions.QueryOptions.ViewAttributes.ScopeSpecified)
                        {
                            this.VerifyEnumViewAttributes();
                        }
                    }
                }
            }
            // Verify R1907
            // The response have been received successfully, then the following requirement can be captured.
            // If the response is not received and parsed successfully, the test case will fail before this requirement is captured 
            Site.CaptureRequirement(
                   1907,
                   @"[GetListItemChangesSinceTokenResponse]Note that set of fields returned by the method is restricted by the viewField or viewName parameter.");
        }
        /// <summary>
        /// A method used to verify the response of GetListItemChangesSinceToken operation whether contain zrow data structure under "listitems" element. If the response does not contain the structure, this method will throw Assert exception.
        /// </summary>
        /// <param name="listitemChangesRes">A parameter represents the response of GetListItemChangesSinceToken operation which expected to contain zrow data structure under "listitems" element.</param>
        protected void VerifyContainZrowDataStructure(GetListItemChangesSinceTokenResponseGetListItemChangesSinceTokenResult listitemChangesRes)
        {
            if (null == listitemChangesRes)
            {
                throw new ArgumentNullException("listitemChangesRes");
            }

            this.Site.Assert.IsNotNull(
                         listitemChangesRes.listitems.data,
                         "The response of GetListItemChangesSinceToken operation should contain [zrow] data structure under [listitems] element.");
        }