Example #1
0
            public void PreferHeader_UnrelatedRequests()
            {
                DSPMetadata metadata = PreferHeader_CreateMetadata();
                var item = new DSPSelfmodifyingResource(metadata.GetResourceType("Item"));
                item.SetRawValue("ID", 0);
                item.SetRawValue("ETagProperty", 0);
                item.SetRawValue("Self", item);
                var collection = new DSPResource(metadata.GetResourceType("Collection"));
                collection.SetRawValue("ID", 0);
                collection.SetRawValue("CollectionProperty", new List<int>() { 1, 2, 3 });
                var stream = new DSPSelfmodifyingResource(metadata.GetResourceType("Stream"));
                stream.SetRawValue("ID", 42);
                var namedStream = new DSPSelfmodifyingResource(metadata.GetResourceType("NamedStream"));
                namedStream.SetRawValue("ID", 42);
                DSPServiceDefinition service = PreferHeader_CreateService(metadata, item, collection, stream, namedStream);
                service.DataServiceBehavior.MaxProtocolVersion = ODataProtocolVersion.V4;

                var entityReferencePayload = new XElement(UnitTestsUtil.MetadataNamespace + "ref");
                entityReferencePayload.SetAttributeValue("id", "/Items(0)");

                var testCases = new[] {
                    new {
                        HttpMethod = "GET",
                        RequestUri = "/Items",
                        Payload = "", ContentType = ""
                    },
                    new {
                        HttpMethod = "GET",
                        RequestUri = "/Collection",
                        Payload = "", ContentType = ""
                    },
                    new {
                        HttpMethod = "GET",
                        RequestUri = "/$metadata",
                        Payload = "", ContentType = ""
                    },
                    new {
                        HttpMethod = "GET",
                        RequestUri = "/Items/$count",
                        Payload = "", ContentType = ""
                    },
                    new {
                        HttpMethod = "GET",
                        RequestUri = "/Items(0)/Self/$ref",
                        Payload = "", ContentType = ""
                    },
                    new {
                        HttpMethod = "DELETE",
                        RequestUri = "/Collection(0)/Description/$value",
                        Payload = "", ContentType = ""
                    },
                    new {
                        HttpMethod = "PUT",
                        RequestUri = "/Items(0)/Self/$ref",
                        Payload = entityReferencePayload.ToString(),
                        ContentType = UnitTestsUtil.MimeApplicationXml
                    },
                    new {  // GET MR
                        HttpMethod = "GET",
                        RequestUri = "/Streams(42)/$value",
                        Payload = "", ContentType = ""
                    },
                    new {  // GET named stream
                        HttpMethod = "GET",
                        RequestUri = "/NamedStreams(42)/NamedStream1",
                        Payload = "", ContentType = ""
                    },
                    new {  // PUT named stream
                        HttpMethod = "PUT",
                        RequestUri = "/NamedStreams(42)/NamedStream1",
                        Payload = "another text file",
                        ContentType = UnitTestsUtil.MimeTextPlain
                    },
                };

                using (TestWebRequest request = service.CreateForInProcess())
                {
                    TestUtil.RunCombinations(
                        testCases,
                        new string[] { null, "return=representation", "return=minimal" },
                        (testCase, preferHeader) =>
                    {
                        service.ClearChanges();

                        request.HttpMethod = testCase.HttpMethod;
                        request.RequestUriString = testCase.RequestUri;
                        request.RequestHeaders["Prefer"] = preferHeader;
                        request.RequestVersion = "4.0;";
                        request.RequestMaxVersion = "4.0;";
                        request.RequestContentType = string.IsNullOrEmpty(testCase.ContentType) ? null : testCase.ContentType;
                        string payload = testCase.Payload;
                        if (!string.IsNullOrEmpty(payload) && payload.StartsWith("["))
                        {
                            int i = payload.IndexOf("]");
                            string header = payload.Substring(1, i - 1);
                            string[] headervalue = header.Split(':');
                            request.RequestHeaders[headervalue[0]] = headervalue[1];
                            payload = payload.Substring(i + 1);
                        }

                        if (!string.IsNullOrEmpty(payload))
                        {
                            request.SetRequestStreamAsText(payload);
                        }

                        request.SendRequest();

                        string preferApplied;
                        request.ResponseHeaders.TryGetValue("Preference-Applied", out preferApplied);
                        Assert.IsNull(preferApplied, "No Preference-Applied header should be present on the response.");
                    });
                }
            }
Example #2
0
 public void ItemsChangeInterceptor(DSPSelfmodifyingResource resource, UpdateOperations operation)
 {
     LastItemsUpdateOperation = operation;
 }
Example #3
0
            public void PreferHeader_CrossFeature()
            {
                DSPMetadata metadata = PreferHeader_CreateMetadata();
                DSPSelfmodifyingResource existingItem = new DSPSelfmodifyingResource(metadata.GetResourceType("Item"));
                existingItem.SetRawValue("ID", 0);
                existingItem.SetRawValue("ETagProperty", 1);
                DSPServiceDefinition service = PreferHeader_CreateService(metadata, existingItem, null, null, null);

                ProcessingPipelineCallCount callCount = new ProcessingPipelineCallCount();
                service.ProcessingPipeline.ProcessingRequest += (sender, args) => { callCount.ProcessingRequestCallCount++; };
                service.ProcessingPipeline.ProcessedRequest += (sender, args) => { callCount.ProcessedRequestCallCount++; };
                service.ProcessingPipeline.ProcessingChangeset += (sender, args) => { callCount.ProcessingChangesetCallCount++; };
                service.ProcessingPipeline.ProcessedChangeset += (sender, args) => { callCount.ProcessedChangesetCallCount++; };
                service.DataServiceType = typeof(PreferHeader_InterceptorsService);

                ProcessingPipelineCallCount expectedCallCount = new ProcessingPipelineCallCount()
                {
                    ProcessingRequestCallCount = 1,
                    ProcessedRequestCallCount = 1,
                    ProcessingChangesetCallCount = 1,
                    ProcessedChangesetCallCount = 1
                };

                // Can't get the payload from the service since we sometimes don't allow read rights
                XDocument existingItemAtom = XDocument.Parse("<entry xmlns:d='http://docs.oasis-open.org/odata/ns/data' xmlns:m='http://docs.oasis-open.org/odata/ns/metadata' xmlns='http://www.w3.org/2005/Atom'>" +
                    "<id>http://host/Items(0)</id>" +
                    "<title type='text'></title>" +
                    "<updated>2010-07-19T14:20:32Z</updated>" +
                    "<author><name /></author>" +
                    "<category term='TestNS.Item' scheme='http://docs.oasis-open.org/odata/ns/scheme' />" +
                    "<content type='application/xml'><m:properties>" +
                        "<d:ID m:type='Edm.Int32'>0</d:ID>" +
                        "<d:ETagProperty m:type='Edm.Int32'>1</d:ETagProperty>" +
                    "</m:properties></content></entry>");

                TestUtil.RunCombinations(
                    UnitTestsUtil.BooleanValues,
                    UnitTestsUtil.BooleanValues,
                    (includeRelationshipLinks, allowReadAccess) =>
                {
                    service.DataServiceBehavior.IncludeRelationshipLinksInResponse = includeRelationshipLinks;
                    service.EntitySetAccessRule = new Dictionary<string,EntitySetRights>() {
                        {"Items", EntitySetRights.AllWrite | (allowReadAccess ? EntitySetRights.AllRead : EntitySetRights.None)}
                    };

                    using (TestWebRequest request = service.CreateForInProcess())
                    {
                        request.RegisterForDispose(PreferHeader_InterceptorsService.InterceptItems.Restore());

                        TestUtil.RunCombinations(
                            new string[] { "POST", "PUT", "PATCH" },
                            new string[] { null, "return=representation", "return=minimal" },
                            new string[] { UnitTestsUtil.AtomFormat },
                            UnitTestsUtil.BooleanValues,
                            UnitTestsUtil.BooleanValues,
                            (httpMethod, preferHeader, format, batch, interceptItems) =>
                        {
                            PreferHeader_InterceptorsService.InterceptItems.Value = interceptItems;
                            PreferHeader_InterceptorsService.LastItemsUpdateOperation = UpdateOperations.None;
                            PreferHeader_InterceptorsService.ItemsQueryInterceptorInvoked = false;
                            service.ClearChanges();
                            callCount.Clear();

                            TestWebRequest r = request;
                            if (batch)
                            {
                                r = new InMemoryWebRequest();
                            }

                            r.RequestVersion = "4.0;";
                            r.RequestMaxVersion = "4.0;";
                            r.RequestHeaders["Prefer"] = preferHeader;

                            PreferHeader_SetupRequest(r, httpMethod, format, existingItemAtom, existingItem, null);

                            if (batch)
                            {
                                var batchRequest = new BatchWebRequest();
                                var changeset = new BatchWebRequest.Changeset();
                                changeset.Parts.Add((InMemoryWebRequest)r);
                                batchRequest.Changesets.Add(changeset);
                                batchRequest.SendRequest(request);
                            }
                            else
                            {
                                TestUtil.RunCatching(request.SendRequest);
                            }

                            Assert.AreEqual(httpMethod != "POST", PreferHeader_InterceptorsService.ItemsQueryInterceptorInvoked, "The query interceptor fire or didn't fire when it should have.");

                            if (!allowReadAccess && httpMethod != "POST")
                            {
                                Assert.AreEqual(403, r.ResponseStatusCode, "The request should have failed due to access rights.");
                            }
                            else if (interceptItems && httpMethod != "POST")
                            {
                                Assert.AreEqual(404, r.ResponseStatusCode, "The request should not have found any resource.");
                            }
                            else
                            {
                                PreferHeader_VerifyResponse(r, request.ServiceRoot.ToString(), true, (response) =>
                                    {
                                        var relationshipLinks = response.Root.Elements(UnitTestsUtil.AtomNamespace + "link")
                                            .Where(e => e.Attribute("rel").Value.Contains("http://docs.oasis-open.org/odata/ns/relatedlinks/"));

                                        if (includeRelationshipLinks)
                                        {
                                            Assert.AreEqual(1, relationshipLinks.Count(), "The response should contain a relationship link.");
                                        }
                                        else
                                        {
                                            Assert.AreEqual(0, relationshipLinks.Count(), "The resounrce should not contain any relationship links.");
                                        }
                                    });
                                callCount.AssertEquals(expectedCallCount);

                                Assert.AreEqual(httpMethod == "POST" ? UpdateOperations.Add : UpdateOperations.Change, PreferHeader_InterceptorsService.LastItemsUpdateOperation,
                                    "The change interceptor didn't fire correctly.");
                            }
                        });
                    }
                });
            }
Example #4
0
            public void PreferHeader_Server()
            {
                DSPMetadata metadata = PreferHeader_CreateMetadata();

                TestUtil.RunCombinations(
                    new[] { typeof(IDataServiceHost), typeof(IDataServiceHost2) },
                    new[] { ODataProtocolVersion.V4 },
                    (hostInterfaceType, maxProtocolVersion) =>
                {
                    DSPSelfmodifyingResource existingItem = new DSPSelfmodifyingResource(metadata.GetResourceType("Item"));
                    existingItem.SetRawValue("ID", 0);
                    existingItem.SetRawValue("ETagProperty", 1);
                    DSPSelfmodifyingResource existingStream = new DSPSelfmodifyingResource(metadata.GetResourceType("Stream"));
                    existingStream.SetRawValue("ID", 0);
                    existingStream.SetRawValue("ETagProperty", 1);

                    bool supportsMR = hostInterfaceType != typeof(IDataServiceHost);
                    DSPServiceDefinition service = this.PreferHeader_CreateService(metadata, existingItem, null, existingStream, null);
                    service.HostInterfaceType = hostInterfaceType;
                    service.DataServiceBehavior.MaxProtocolVersion = maxProtocolVersion;

                    using (TestWebRequest request = service.CreateForInProcess())
                    {
                        XDocument existingItemAtom = UnitTestsUtil.GetResponseAsAtomXLinq(request, "/Items(0)", "application/atom+xml,application/xml");
                        XDocument existingStreamAtom = !supportsMR ? null : UnitTestsUtil.GetResponseAsAtomXLinq(request, "/Streams(0)", "application/atom+xml,application/xml");

                        IEnumerable<string> httpMethods = new string[] { "POST", "POSTMR", "PUT", "PATCH" };

                        TestUtil.RunCombinations(
                            new string[] { null, "return=representation", "return=minimal", "ReTURN=RePrESenTaTioN", "foo" },
                            httpMethods,
                            new string[] { UnitTestsUtil.AtomFormat }, (preferHeader, httpMethod, format) =>
                            {
                                // Skip MR verification since we use MRs in that entity and as such the request would not work without support on the server
                                if (httpMethod == "POSTMR" && !supportsMR)
                                {
                                    return;
                                }

                                service.ClearChanges();

                                request.RequestVersion = "4.0;";
                                request.RequestMaxVersion = "4.0;";
                                request.Accept = "application/atom+xml,application/xml";
                                request.RequestHeaders["Prefer"] = preferHeader;

                                XDocument existingAtom = httpMethod == "POSTMR" ? existingStreamAtom : existingItemAtom;
                                DSPSelfmodifyingResource existingResource = httpMethod == "POSTMR" ? existingStream : existingItem;

                                this.PreferHeader_SetupRequest(request, httpMethod, format, existingAtom, existingResource, (inputAtom) =>
                                {
                                    var triggerModification = inputAtom.Root.Descendants(UnitTestsUtil.MetadataNamespace + "properties").First().Element(UnitTestsUtil.DataNamespace + "TriggerModification");
                                    triggerModification.Attributes(UnitTestsUtil.MetadataNamespace + "null").Remove();
                                    triggerModification.Value = "trigger" + existingItem.GetETag().Replace('"', '_');
                                });

                                bool serviceAllowsPreferHeader = hostInterfaceType == typeof(IDataServiceHost2);

                                bool? effectiveResponsePreference;
                                this.PreferHeader_ShouldContainResponseBody(request, serviceAllowsPreferHeader, out effectiveResponsePreference);

                                TestUtil.RunCatching(request.SendRequest);

                                DSPSelfmodifyingResource returnedItem;
                                if (httpMethod == "POST" || httpMethod == "POSTMR")
                                {
                                    returnedItem = service.CurrentDataSource.GetResourceSetEntities(httpMethod == "POSTMR" ? "Streams" : "Items").OfType<DSPSelfmodifyingResource>().First(r => (int)r.GetValue("ID") == 1);
                                }
                                else
                                {
                                    returnedItem = existingResource;
                                }

                                this.PreferHeader_VerifyResponse(request, request.ServiceRoot.ToString(), serviceAllowsPreferHeader, (response) =>
                                {
                                    if (httpMethod != "POSTMR") // with POST MR the ETagProperty will not be updated since the payload didn't set any properties (it's just the stream)
                                    {
                                        string etagPropertyValue = returnedItem.GetValue("ETagProperty").ToString();
                                        XElement etagPropertyElement = response.Root.Descendants(UnitTestsUtil.MetadataNamespace + "properties").First().Element(UnitTestsUtil.DataNamespace + "ETagProperty");
                                        Assert.AreEqual(etagPropertyValue, etagPropertyElement.Value, "The updated value was not included in the response.");
                                    }
                                });

                                Assert.AreEqual(returnedItem.GetETag(), request.ResponseETag, "The response ETag does not match the current ETag value on the server.");

                            });
                    }
                });
            }