public void CanOverloadUpdateRequestWithHeader() { foreach (var serviceType in Services) { using (CustomDataContext.CreateChangeScope()) { using (TestWebRequest webRequest = TestWebRequest.CreateForInProcessWcf()) { // get an existing customer before sending PUT requests webRequest.HttpMethod = "GET"; webRequest.ServiceType = serviceType; webRequest.RequestUriString = "/Customers(1)"; webRequest.Accept = UnitTestsUtil.JsonLightMimeType; TestUtil.RunCatching(webRequest.SendRequest); Assert.IsTrue(webRequest.ResponseContentType.ToLower().Contains(UnitTestsUtil.JsonLightMimeType.ToLower())); // all the subsequent requests are PUT requests with specified Accept and Content-Type headers webRequest.HttpMethod = "PUT"; webRequest.Accept = UnitTestsUtil.JsonLightMimeType; webRequest.RequestContentType = "application/json"; // update the customer and send the correct ETag in query string header - should succeed webRequest.RequestUriString = "/Customers(1)/Name?Override-If-Match=" + webRequest.ResponseETag; webRequest.IfMatch = "SomeBadValue"; webRequest.SetRequestStreamAsText("{\"value\": \"Name1\"}"); TestUtil.RunCatching(webRequest.SendRequest); Assert.AreEqual(204, webRequest.ResponseStatusCode); string eTag = webRequest.ResponseETag; // update the customer and send ETag with reversed guid in query string header - should fail // Length of a GUID is 36 string correctGuid = webRequest.ResponseETag.Substring(webRequest.ResponseETag.IndexOf('"') + 1, 36); string reversedGuid = string.Concat(correctGuid.ToArray().Reverse()); webRequest.RequestUriString = "/Customers(1)/Name?Override-If-Match=" + webRequest.ResponseETag.Replace(correctGuid, reversedGuid); webRequest.IfMatch = eTag; webRequest.SetRequestStreamAsText("{\"value\": \"Name2\"}"); TestUtil.RunCatching(webRequest.SendRequest); Assert.AreEqual(412, webRequest.ResponseStatusCode); // update the customer and send prefer header return=representation in query string - expect 200 webRequest.RequestUriString = "/Customers(1)/Name?Override-Prefer=return=representation"; webRequest.IfMatch = eTag; webRequest.SetRequestStreamAsText("{\"value\": \"Name3\"}"); TestUtil.RunCatching(webRequest.SendRequest); Assert.AreEqual(200, webRequest.ResponseStatusCode); Assert.IsTrue(webRequest.GetResponseStreamAsText().Contains("TheTest/$metadata#Customers(1)/Name\",\"value\":\"Name3\"")); } } } }
public void HttpContextServiceHostTunnelingTest() { CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("Method", new string[] { "GET", "POST", "PUT", "DELETE" }), new Dimension("XMethod", new string[] { "GET", "POST", "PATCH", "DELETE", "DELETE,DELETE" })); TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { using (TestWebRequest request = TestWebRequest.CreateForLocal()) { request.DataServiceType = typeof(CustomDataContext); request.RequestUriString = "/Orders(100)"; string method = (string)values["Method"]; string xmethod = (string)values["XMethod"]; request.HttpMethod = method; if (xmethod == "PATCH") { request.RequestContentType = UnitTestsUtil.JsonLightMimeType; request.SetRequestStreamAsText( "{ @odata.type:\"#AstoriaUnitTests.Stubs.Order\"" + " , DollarAmount: 10 }"); } request.RequestHeaders["X-HTTP-Method"] = xmethod; Exception exception = TestUtil.RunCatching(request.SendRequest); TestUtil.AssertExceptionExpected(exception, method != "POST", xmethod != "PATCH"); } }); }
public void NonNullableComplexPropertyTest() { test.TestUtil.RunCombinations( new DSPUnitTestServiceDefinition[] { service }, new string[] { UnitTestsUtil.AtomFormat }, ServiceVersion.ValidVersions, // requestDSV ServiceVersion.ValidVersions, // requestMDSV ServiceVersion.ValidVersions, // maxProtocolVersion (localService, format, requestDSV, requestMDSV, maxProtocolVersion) => { if (maxProtocolVersion == null) { return; } localService.DataServiceBehavior.MaxProtocolVersion = maxProtocolVersion.ToProtocolVersion(); using (TestWebRequest request = localService.CreateForInProcess()) { if (requestDSV != null && maxProtocolVersion.ToProtocolVersion() < requestDSV.ToProtocolVersion()) { return; } request.StartService(); request.HttpMethod = "POST"; request.RequestUriString = "/People"; request.Accept = format; if (requestDSV != null) { request.RequestVersion = requestDSV.ToString(); } if (requestMDSV != null) { request.RequestMaxVersion = requestMDSV.ToString(); } request.RequestContentType = format; request.SetRequestStreamAsText(@"<entry xml:base='http://host/' 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'> <category term='#AstoriaUnitTests.Tests.PeopleType' scheme='http://docs.oasis-open.org/odata/ns/scheme' /> <content type='application/xml'> <m:properties> <d:ID m:type='Edm.Int32'>1</d:ID> <d:Name>bar</d:Name> <d:Body></d:Body> <d:Age>6</d:Age> <d:Office m:type='#AstoriaUnitTests.Tests.OfficeType' m:null='true'/> </m:properties> </content> </entry>"); request.HttpMethod = "POST"; var exception = test.TestUtil.RunCatching(request.SendRequest); Assert.IsNotNull(exception, "Exception is always expected."); Assert.IsNotNull(exception.InnerException, "InnerException is always expected."); // For v1 and v2, provider should throw. Assert.AreEqual("EntityFramework", exception.InnerException.Source, "Source expected: EntityFramework, actual: " + exception.InnerException.Source); Assert.AreEqual(500, request.ResponseStatusCode, "Status code expected: 500" + ", actual: " + request.ResponseStatusCode); } }); }
[Ignore] // Remove Atom // [TestMethod, TestCategory("Partition1")] public void CanOverrideAcceptHeaderToBatchRequestWithQueryItem() { StringBuilder batchQueryOperation = new StringBuilder(); batchQueryOperation.AppendLine("GET Customers(1)/Address?Override-Accept=" + UnitTestsUtil.JsonLightMimeType + " HTTP/1.1"); batchQueryOperation.AppendLine("Host: host"); batchQueryOperation.AppendLine("Accept: " + UnitTestsUtil.MimeApplicationXml); var test = new SimpleBatchTestCase { RequestPayload = new BatchInfo(new BatchQuery(new Operation(batchQueryOperation.ToString()))), ResponseStatusCode = 202, ResponseETag = default(string), ResponseVersion = V4, RequestDataServiceVersion = V4, RequestMaxDataServiceVersion = V4, }; foreach (var serviceType in Services) { using (TestWebRequest request = TestWebRequest.CreateForInProcessWcf()) { request.HttpMethod = "POST"; request.RequestUriString = "/$batch?Override-Batch-Accept=" + UnitTestsUtil.JsonLightMimeType; request.DataServiceType = serviceType; request.Accept = UnitTestsUtil.MimeMultipartMixed; request.RequestVersion = test.RequestDataServiceVersion.ToString(); request.RequestMaxVersion = test.RequestMaxDataServiceVersion.ToString(); request.ForceVerboseErrors = true; if (test.RequestPayload == null) { request.RequestContentLength = 0; } else { const string boundary = "batch-set"; request.RequestContentType = String.Format("{0}; boundary={1}", UnitTestsUtil.MimeMultipartMixed, boundary); request.SetRequestStreamAsText(BatchRequestWritingUtils.GetBatchText(test.RequestPayload, boundary)); } TestUtil.RunCatching(request.SendRequest); // expect 202 as $batch request does not honor query string Accept header Assert.AreEqual(test.ResponseStatusCode, request.ResponseStatusCode); // The following response header is written in ProcessingRequest/OnStartProcessingRequest Assert.AreEqual(UnitTestsUtil.JsonLightMimeType, request.ResponseHeaders["Override-Batch-Accept"]); string response = request.GetResponseStreamAsText(); if (serviceType == typeof(ModifyHeaderOnStartProcessingRequestTestService)) { Assert.IsTrue(response.Contains("Content-Type: application/json;odata.metadata=minimal;")); } else { // ProcessingRequest which sets the Aceept header is not called for inner requests Assert.IsTrue(response.Contains("Content-Type: application/xml;charset=utf-8")); } } } }
public void SpatialOpenProperty_AtomWrongTypeDeserialize() { var testCases = testData.Select(kvp => new { Type = SpatialTestUtil.GeographyTypeFor(kvp.Key), WktData = new String[] { kvp.Value.Last() } }); String[] edmCases = { "Edm.Double", "Edm.String" }; TestUtil.RunCombinations(testCases, edmCases, (tcase, edmName) => { using (TestWebRequest request = CreateSpatialPropertyService(new Geography[tcase.WktData.Length], tcase.Type, true, true).CreateForInProcess()) { request.RequestUriString = "/Entities"; request.HttpMethod = "POST"; request.RequestContentType = UnitTestsUtil.AtomFormat; request.SetRequestStreamAsText(AggregateAtomPayloadFromWkt(tcase.Type.Name, tcase.WktData, edmName)); Exception ex = TestUtil.RunCatching(request.SendRequest); Assert.IsNotNull(ex); while (ex.InnerException != null) { ex = ex.InnerException; } Assert.AreEqual(ODataLibResourceUtil.GetString("XmlReaderExtension_InvalidNodeInStringValue", "Element"), ex.Message); } }); }
public void GeometryAsOpenProperty_AtomWithTypeDeserialize() { // tests atom deserialization with m:type information var testCases = testData.Select(kvp => new { Type = SpatialTestUtil.GeometryTypeFor(kvp.Key), EdmName = SpatialTestUtil.GeometryEdmNameFor(kvp.Key), WktData = kvp.Value }); TestUtil.RunCombinations(testCases, (tcase) => { using (TestWebRequest request = CreateSpatialPropertyService(new Geometry[tcase.WktData.Length], tcase.Type, true, true).CreateForInProcessWcf()) { request.RequestUriString = "/Entities"; request.HttpMethod = "POST"; request.Accept = "application/atom+xml,application/xml"; request.RequestContentType = UnitTestsUtil.AtomFormat; request.SetRequestStreamAsText(AggregateAtomPayloadFromWkt(tcase.Type.Name, tcase.WktData, tcase.EdmName)); request.SendRequest(); var response = request.GetResponseStreamAsXDocument(); string rootXpath = "atom:entry/atom:content/adsm:properties/ads:" + tcase.Type.Name; UnitTestsUtil.VerifyXPaths(response, tcase.WktData.Select((v, i) => rootXpath + i + "[@adsm:type = '" + tcase.EdmName + "' and namespace-uri(*) = 'http://www.opengis.net/gml']").ToArray()); } }); }
public void CallBackInBatchRequestTest() { StringBuilder batchQueryOperation = new StringBuilder(); batchQueryOperation.AppendLine("GET Customers(1)/Address?$callback=foo HTTP/1.1"); batchQueryOperation.AppendLine("Host: host"); batchQueryOperation.AppendLine("Accept: " + UnitTestsUtil.JsonMimeType); batchQueryOperation.AppendLine("Override-Accept: " + UnitTestsUtil.JsonLightMimeType); var testCase = new SimpleBatchTestCase { RequestPayload = new BatchInfo(new BatchQuery(new Operation(batchQueryOperation.ToString()))), ExpectedResponsePayloadContains = new[] { "Content-Type: text/javascript;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8", "foo({\"@odata.context\":", "\"StreetAddress\":\"Line1\",\"City\":\"Redmond\",\"State\":\"WA\",\"PostalCode\":\"98052\"})", }, ResponseStatusCode = 202, ResponseETag = default(string), }; using (TestWebRequest request = TestWebRequest.CreateForInProcessWcf()) { request.HttpMethod = "POST"; request.RequestUriString = "/$batch"; request.DataServiceType = typeof(CustomDataContext); request.Accept = UnitTestsUtil.MimeMultipartMixed; request.ForceVerboseErrors = true; const string boundary = "batch-set"; request.RequestContentType = String.Format("{0}; boundary={1}", UnitTestsUtil.MimeMultipartMixed, boundary); request.SetRequestStreamAsText(BatchRequestWritingUtils.GetBatchText(testCase.RequestPayload, boundary)); // callback in inner GET request should succeed request.SendRequest(); string response = request.GetResponseStreamAsText(); Assert.AreEqual(testCase.ResponseStatusCode, request.ResponseStatusCode); Assert.IsTrue(request.ResponseContentType.StartsWith("multipart/mixed; boundary=batchresponse_")); foreach (string str in testCase.ExpectedResponsePayloadContains) { Assert.IsTrue(response.Contains(str), String.Format("The response:\r\n{0}\r\nDoes not contain the string:\r\n{1}.", response, str)); } // callback with $batch should fail try { request.RequestUriString = "/$batch?$callback=bar"; request.SendRequest(); Assert.Fail("Request should have failed because it was not a GET request."); } catch (WebException) { Assert.IsTrue(request.GetResponseStreamAsText().Contains("$callback can only be specified on GET requests.")); Assert.IsTrue(request.ResponseHeaders["content-type"].StartsWith("application/xml")); Assert.AreEqual(400, request.ResponseStatusCode); } } }
public void BadCustomAnnotationOnErrorWithBatchRequestCausesInStreamErrorInErrorPayload() { StringBuilder batchQueryOperation = new StringBuilder(); batchQueryOperation.AppendLine("GET Customers(1)/Addresssss?Override-Accept=" + UnitTestsUtil.JsonLightMimeType + " HTTP/1.1"); batchQueryOperation.AppendLine("Host: host"); batchQueryOperation.AppendLine("Accept: " + "application/json;odata.metadata=minimal"); var test = new SimpleBatchTestCase { RequestPayload = new BatchInfo(new BatchQuery(new Operation(batchQueryOperation.ToString()))), ResponseStatusCode = 202, ResponseETag = default(string), ResponseVersion = V4, RequestDataServiceVersion = V4, RequestMaxDataServiceVersion = V4, }; using (TestWebRequest webRequest = this.SetupRequest()) { webRequest.HttpMethod = "POST"; webRequest.RequestUriString = "/$batch"; webRequest.Accept = UnitTestsUtil.MimeMultipartMixed; webRequest.RequestVersion = "4.0;"; webRequest.RequestMaxVersion = "4.0;"; webRequest.ForceVerboseErrors = true; const string boundary = "batch-set"; webRequest.RequestContentType = String.Format("{0}; boundary={1}", UnitTestsUtil.MimeMultipartMixed, boundary); webRequest.SetRequestStreamAsText(BatchRequestWritingUtils.GetBatchText(test.RequestPayload, boundary)); AnnotationValue = new ODataComplexValue { TypeName = "AstoriaUnitTests.Stubs.Address", Properties = new[] { new ODataProperty { Name = "CityCity", Value = "404" }, new ODataProperty { Name = "State", Value = (new DateTimeOffset(2012, 10, 10, 1, 2, 3, new TimeSpan())).ToString() }, new ODataProperty { Name = "Foo", Value = new ODataCollectionValue { Items = new Object[] { 123, new Object() } } } // collection value is wrong so error payload fails to write } }; TestUtil.RunCatching(webRequest.SendRequest); // For batch request if ODL fails when writing error, HandleException is called twice and ODataError annotation cannot be be written correctly webRequest.ResponseStatusCode.Should().Be(202); webRequest.GetResponseStreamAsText().Should().Contain("{\"error\":{\"code\":\"\",\"message\":\"Resource not found for the segment 'Addresssss'.\",\"@location.error\":{\"@odata.type\":\"#AstoriaUnitTests.Stubs.Address\",\"CityCity\":\"404\",\"State\":\"10/10/2012 1:02:03 AM +00:00\",\"Foo\":[123<?xml"); HandleExceptionCalls.Should().Be(2); } }
public void GeometryCollection_Deserialize() { StringBuilder payload = new StringBuilder(); payload.Append("{ \"__metadata\":{ \"uri\": \"http://host/Entities(0)\" }, \"ID\": 0"); foreach (var kvp in testData) { payload.AppendLine(","); payload.Append(JsonCollectionPropertyFromWkt(SpatialTestUtil.GeometryTypeFor(kvp.Key).Name, kvp.Value, SpatialTestUtil.GeometryEdmNameFor(kvp.Key))); } payload.AppendLine("}"); var svc = CreateCollectionWriteService(testData.Keys.Select(t => SpatialTestUtil.GeometryTypeFor(t)).ToList()); using (TestWebRequest request = svc.CreateForInProcess()) { System.Data.Test.Astoria.TestUtil.RunCombinations(UnitTestsUtil.ResponseFormats, (format) => { request.RequestUriString = "/Entities"; request.HttpMethod = "POST"; request.Accept = "application/atom+xml,application/xml"; request.RequestContentType = format; if (format == UnitTestsUtil.JsonLightMimeType) { request.SetRequestStreamAsText(payload.ToString()); } else { var xDoc = JsonValidator.ConvertToXDocument(payload.ToString()); var atomPayload = UnitTestsUtil.Json2AtomXLinq(xDoc, true).ToString(); request.SetRequestStreamAsText(atomPayload); } request.SendRequest(); var response = request.GetResponseStreamAsXDocument(); UnitTestsUtil.VerifyXPaths(response, testData.Select(d => String.Format("count(atom:entry/atom:content/adsm:properties/ads:Collection{0}/adsm:element) = {1}", SpatialTestUtil.GeometryTypeFor(d.Key).Name, d.Value.Length)).ToArray()); }); } }
public void GeometryAsOpenProperty_Deserialize() { var testCases = testData.Select(kvp => new { Type = SpatialTestUtil.GeometryTypeFor(kvp.Key), EdmName = SpatialTestUtil.GeometryEdmNameFor(kvp.Key), Data = new Geometry[kvp.Value.Length], Payload = AggregateJsonPayloadFromWkt(SpatialTestUtil.GeometryTypeFor(kvp.Key).Name, kvp.Value, SpatialTestUtil.GeometryEdmNameFor(kvp.Key)) }); TestUtil.RunCombinations(testCases, UnitTestsUtil.ResponseFormats, (tcase, format) => { using (TestWebRequest request = CreateSpatialPropertyService(tcase.Data, tcase.Type, true, true).CreateForInProcessWcf()) { request.RequestUriString = "/Entities"; request.HttpMethod = "POST"; request.Accept = "application/atom+xml,application/xml"; request.RequestContentType = format; if (format == UnitTestsUtil.JsonLightMimeType) { request.SetRequestStreamAsText(tcase.Payload); } else { // atom from Json - this payload has no m:type var xDoc = JsonValidator.ConvertToXDocument(tcase.Payload.ToString()); var atomPayload = UnitTestsUtil.Json2AtomXLinq(xDoc, true).ToString(); request.SetRequestStreamAsText(atomPayload); } request.SendRequest(); var response = request.GetResponseStreamAsXDocument(); string rootXpath = "atom:entry/atom:content/adsm:properties/ads:" + tcase.Type.Name; string[] xpaths = tcase.Data.Select((v, i) => rootXpath + i + "[@adsm:type = '" + tcase.EdmName + "' and namespace-uri(*) = 'http://www.opengis.net/gml']").ToArray(); UnitTestsUtil.VerifyXPaths(response, xpaths); } }); }
[Ignore] // Remove Atom // [TestMethod, TestCategory("Partition1")] public void OverloadUpdateRequestWithContentTypeContentLengthHeader() { using (CustomDataContext.CreateChangeScope()) { using (TestWebRequest webRequest = TestWebRequest.CreateForInProcessWcf()) { // get an existing customer before the PUT requests webRequest.HttpMethod = "GET"; webRequest.ServiceType = typeof(ModifyHeaderOnStartProcessingRequestTestService); webRequest.RequestUriString = "/Customers(1)"; webRequest.Accept = UnitTestsUtil.JsonLightMimeType; TestUtil.RunCatching(webRequest.SendRequest); Assert.IsTrue(webRequest.ResponseContentType.ToLower().Contains(UnitTestsUtil.JsonLightMimeType.ToLower())); // all the subsequent requests are PUT requests with specified Accept If-Match, and Content-Type headers webRequest.HttpMethod = "PUT"; webRequest.Accept = UnitTestsUtil.JsonLightMimeType; webRequest.IfMatch = "*"; webRequest.RequestContentType = "application/json"; // override Content-Type header webRequest.RequestUriString = "/Customers(1)/Name?Override-Content-Type=application/xml"; webRequest.SetRequestStreamAsText("{\"value\": \"Name1\"}"); TestUtil.RunCatching(webRequest.SendRequest); Assert.AreEqual(400, webRequest.ResponseStatusCode); // The following response header is written in ProcessingRequest/OnStartProcessingRequest Assert.IsTrue(webRequest.GetResponseStreamAsText().Contains("Data at the root level is invalid.")); // override Content-Length header webRequest.RequestUriString = "/Customers(1)/Name?Override-Content-Length=10000"; webRequest.SetRequestStreamAsText("{\"value\": \"Name1\"}"); TestUtil.RunCatching(webRequest.SendRequest); Assert.AreEqual(204, webRequest.ResponseStatusCode); // The following response header is written in ProcessingRequest/OnStartProcessingRequest Assert.AreEqual("10000", webRequest.ResponseHeaders["Request-Content-Length"]); } } }
public void BatchCustomAnnotationOnInnerRequestErrorShouldGetWrittenInJsonLight() { StringBuilder batchQueryOperation = new StringBuilder(); batchQueryOperation.AppendLine("GET Customers(1)/Addresssss?Override-Accept=" + UnitTestsUtil.JsonLightMimeType + " HTTP/1.1"); batchQueryOperation.AppendLine("Host: host"); batchQueryOperation.AppendLine("Accept: " + "application/json;odata.metadata=minimal"); var test = new SimpleBatchTestCase { RequestPayload = new BatchInfo(new BatchQuery(new Operation(batchQueryOperation.ToString()))), ResponseStatusCode = 202, ResponseETag = default(string), ResponseVersion = V4, RequestDataServiceVersion = V4, RequestMaxDataServiceVersion = V4, }; using (TestWebRequest webRequest = this.SetupRequest()) { webRequest.HttpMethod = "POST"; webRequest.RequestUriString = "/$batch"; webRequest.Accept = UnitTestsUtil.MimeMultipartMixed; webRequest.RequestVersion = "4.0;"; webRequest.RequestMaxVersion = "4.0;"; webRequest.ForceVerboseErrors = true; const string boundary = "batch-set"; webRequest.RequestContentType = String.Format("{0}; boundary={1}", UnitTestsUtil.MimeMultipartMixed, boundary); webRequest.SetRequestStreamAsText(BatchRequestWritingUtils.GetBatchText(test.RequestPayload, boundary)); AnnotationValue = new ODataCollectionValue { TypeName = "Collection(Edm.String)", Items = new [] { "404", new DateTimeOffset(2012, 10, 10, 1, 2, 3, new TimeSpan()).ToString() } }; TestUtil.RunCatching(webRequest.SendRequest); webRequest.ResponseStatusCode.Should().Be(202); webRequest.GetResponseStreamAsText().Should().Contain("{\"error\":{\"code\":\"\",\"message\":\"Resource not found for the segment 'Addresssss'.\",\"[email protected]\":\"#Collection(String)\",\"@location.error\":[\"404\",\"10/10/2012 1:02:03 AM +00:00\"]}}"); HandleExceptionCalls.Should().Be(1); } }
public void UpdateWithDowncast() { string requestUriString = "/Entities('Derived')/" + EntitySetBaseTypeName + "/" + DerivedTypeName; using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(SimpleInheritanceService); request.RequestUriString = requestUriString; request.HttpMethod = "PATCH"; request.RequestContentType = "application/json"; request.SetRequestStreamAsText(@"{""@odata.type"":""" + DerivedTypeName + @"""}"); TestUtil.RunCatching(request.SendRequest); Assert.AreEqual(204, request.ResponseStatusCode); } }
public void ETag_PUTPATCHResourceWithNoContent() { CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("Type", new Type[] { typeof(Customer) }), new Dimension("Method", new string[] { "PUT", "PATCH" }), new Dimension("ProcessResponse", new bool[] { true, false })); using (CustomDataContext.CreateChangeScope()) using (TestUtil.RestoreStaticValueOnDispose(typeof(BaseTestWebRequest), "HostInterfaceType")) using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(CustomDataContext); BaseTestWebRequest.HostInterfaceType = typeof(Microsoft.OData.Service.IDataServiceHost2); TestUtil.RunCombinatorialEngineFail(engine, values => { Type type = (Type)values["Type"]; string method = (string)values["Method"]; bool processResponse = (bool)values["ProcessResponse"]; string atomPayload = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" + "<entry xml:base=\"/\" " + TestUtil.CommonPayloadNamespaces + ">" + AtomUpdatePayloadBuilder.GetCategoryXml(type.FullName) + "</entry>"; request.RequestUriString = "/Customers(0)"; request.HttpMethod = method; request.IfMatch = "W/\"sdfght\""; // Wrong ETag request.RequestVersion = "4.0;"; if (processResponse) { request.RequestHeaders["Prefer"] = "return=representation"; } else { request.RequestHeaders["Prefer"] = "return=minimal"; } request.SetRequestStreamAsText(atomPayload); request.RequestContentType = UnitTestsUtil.AtomFormat; Exception e = TestUtil.RunCatching(request.SendRequest); Assert.IsNotNull(e, "The request should have failed."); Assert.AreEqual(412, request.ResponseStatusCode, "The request should have failed due to mismatch in ETags"); }); } }
public void InsertWithUpcastInUriShouldStillCreateInstanceOfPayloadType() { string requestUriString = "/Entities/" + VeryDerivedTypeName + "/" + EntitySetBaseTypeName; using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(SimpleInheritanceService); request.RequestUriString = requestUriString; request.HttpMethod = "POST"; request.RequestContentType = "application/json"; request.SetRequestStreamAsText(@"{""@odata.type"":""" + DerivedTypeName + @""",""ID"": ""Inserted""}"); TestUtil.RunCatching(request.SendRequest); Assert.AreEqual(201, request.ResponseStatusCode); Assert.AreEqual("http://host/Entities('Inserted')/AstoriaUnitTests.Tests.MultipleTypeSegmentsIntegrationTests_DerivedType", request.ResponseLocation); } }
private static void ExecuteUpdate(DSPResource resource, int id, TestWebRequest baseRequest, string httpMethod, string preferHeader, bool useBatch, DSPResourceSerializerFormat payloadFormat) { string payload = DSPResourceSerializer.WriteEntity(resource, payloadFormat); bool isPost = httpMethod == "POST"; bool expectedReturnContent = preferHeader == "return=representation" || isPost && preferHeader == null; string uriSuffix = isPost ? String.Empty : String.Format("({0})", id); TestWebRequest request = useBatch ? new InMemoryWebRequest() : baseRequest; request.RequestUriString = String.Format("/{0}s{1}", resource.ResourceType.Name, uriSuffix); request.HttpMethod = httpMethod; request.RequestVersion = "4.0;"; request.RequestMaxVersion = "4.0;"; request.RequestHeaders["Prefer"] = preferHeader; request.Accept = payloadFormat == DSPResourceSerializerFormat.Atom ? "application/atom+xml,application/xml" : UnitTestsUtil.JsonLightMimeType; request.RequestContentType = "application/atom+xml"; request.SetRequestStreamAsText(payload); if (useBatch) { var batchRequest = new BatchWebRequest(); var changeset = new BatchWebRequest.Changeset(); changeset.Parts.Add((InMemoryWebRequest)request); batchRequest.Changesets.Add(changeset); batchRequest.SendRequest(baseRequest); Assert.IsTrue(UnitTestsUtil.IsSuccessStatusCode(baseRequest.ResponseStatusCode), "Unexpected error occurred on batch."); } else { request.SendRequest(); } Assert.IsTrue(UnitTestsUtil.IsSuccessStatusCode(request.ResponseStatusCode), "Unexpected error occurred when sending the request."); if (expectedReturnContent) { // If the request is expected to return content, verify there were no instream errors Exception e = request.ParseResponseInStreamError(); string errorMessage = e != null ? e.Message : string.Empty; Assert.IsNull(e, "Expected no exception, but got the following error", errorMessage); } }
public void FailedTopLevelBatchRequestShouldBeXmlRegardlessOfCustomAnnotation() { StringBuilder batchQueryOperation = new StringBuilder(); batchQueryOperation.AppendLine("GET Customers(1)/Address?Override-Accept=" + UnitTestsUtil.JsonLightMimeType + " HTTP/1.1"); batchQueryOperation.AppendLine("Host: host"); batchQueryOperation.AppendLine("Accept: " + "application/json;odata.metadata=minimal"); var test = new SimpleBatchTestCase { RequestPayload = new BatchInfo(new BatchQuery(new Operation(batchQueryOperation.ToString()))), ResponseStatusCode = 400, }; using (TestWebRequest webRequest = this.SetupRequest()) { webRequest.HttpMethod = "POST"; webRequest.RequestUriString = "/$batch"; webRequest.Accept = UnitTestsUtil.MimeMultipartMixed; webRequest.RequestVersion = "4.0;"; webRequest.RequestMaxVersion = "4.0;"; webRequest.ForceVerboseErrors = true; const string boundary = "batch-set"; // set content type to json so the batch request fails with 400 webRequest.RequestContentType = String.Format("{0}; boundary={1}", "application/json;odata.metadata=minimal", boundary); webRequest.SetRequestStreamAsText(BatchRequestWritingUtils.GetBatchText(test.RequestPayload, boundary)); AnnotationValue = new ODataPrimitiveValue("This is a custom value message"); TestUtil.RunCatching(webRequest.SendRequest); // Since the error response of top level batch request is xml, the custom error annotation will be ignored webRequest.ResponseStatusCode.Should().Be(test.ResponseStatusCode); webRequest.GetResponseStreamAsText().Should().NotContain("custom value message"); HandleExceptionCalls.Should().Be(1); } }
[Ignore] // Remove Atom // [TestCategory("Partition2"), TestMethod, Variation] public void BatchContentTypeTest() { var testCases = new BatchContentTypeTestCase[] { // Completely wrong content type new BatchContentTypeTestCase { ContentType = "text/plain", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = DataServicesClientResourceUtil.GetString("Batch_ExpectedContentType", "text/plain") }, // Just type is correct, subtype is wrong new BatchContentTypeTestCase { ContentType = "multipart/text", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = DataServicesClientResourceUtil.GetString("Batch_ExpectedContentType", "multipart/text") }, // No boundary - still wrong new BatchContentTypeTestCase { ContentType = "multipart/mixed", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed", "boundary") }, // Some other parameter but no boundary new BatchContentTypeTestCase { ContentType = "multipart/mixed;param=value", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed;param=value", "boundary") }, // Empty boundary - fails new BatchContentTypeTestCase { ContentType = "multipart/mixed;boundary=", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("ValidationUtils_InvalidBatchBoundaryDelimiterLength", string.Empty, "70") }, new BatchContentTypeTestCase { ContentType = "multipart/mixed;boundary=;param=value", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("ValidationUtils_InvalidBatchBoundaryDelimiterLength", string.Empty, "70") }, // Two boundary parameters - wrong new BatchContentTypeTestCase { ContentType = "multipart/mixed;boundary=one;boundary=two", ExpectedErrorStatusCode = 400, ExpectedClientErrorMessage = ODataLibResourceUtil.GetString("MediaTypeUtils_BoundaryMustBeSpecifiedForBatchPayloads", "multipart/mixed;boundary=one;boundary=two", "boundary") }, // Valid simple boundary new BatchContentTypeTestCase { ContentType = "multipart/mixed;boundary=batchboundary", PayloadBatchBoundary = "batchboundary" }, // Valid simple boundary - mimetype using different casing new BatchContentTypeTestCase { ContentType = "MultiPart/mIxed;boundary=batchboundary", PayloadBatchBoundary = "batchboundary" }, // Valid simple boundary - boundary parameter name different casing new BatchContentTypeTestCase { ContentType = "multipart/mixed;BounDary=batchboundary", PayloadBatchBoundary = "batchboundary" }, }; OpenWebDataServiceDefinition serverService = new OpenWebDataServiceDefinition() { DataServiceType = typeof(CustomDataContext) }; PlaybackServiceDefinition clientService = new PlaybackServiceDefinition(); TestUtil.RunCombinations( testCases, (testCase) => { using (TestWebRequest request = serverService.CreateForInProcess()) { request.RequestContentType = testCase.ContentType; request.SetRequestStreamAsText(string.Format( "--{0}\r\n" + "Content-Type: multipart/mixed; boundary=changesetresponse_00000001-0000-0000-0000-000000000000\r\n\r\n" + "--changesetresponse_00000001-0000-0000-0000-000000000000\r\n" + "--changesetresponse_00000001-0000-0000-0000-000000000000--\r\n" + "--{0}--\r\n", testCase.PayloadBatchBoundary)); request.RequestUriString = "/$batch"; request.HttpMethod = "POST"; Exception exception = TestUtil.RunCatching(request.SendRequest); int actualStatusCode = 0; if (exception != null) { actualStatusCode = request.ResponseStatusCode; } else { Assert.AreEqual(202, request.ResponseStatusCode, "Wrong response code for no-exception request."); BatchWebRequest batchResponse = BatchWebRequest.FromResponse(InMemoryWebRequest.FromResponse(request)); if (batchResponse.Parts.Count > 0) { actualStatusCode = batchResponse.Parts[0].ResponseStatusCode; if (actualStatusCode == 200) { actualStatusCode = 0; } } } Assert.AreEqual(testCase.ExpectedErrorStatusCode, actualStatusCode, "Wrong status code."); } using (TestWebRequest request = clientService.CreateForInProcessWcf()) { request.StartService(); clientService.ProcessRequestOverride = clientRequest => { var clientResponse = new InMemoryWebRequest(); clientResponse.SetResponseStatusCode(202); clientResponse.ResponseHeaders["Content-Type"] = testCase.ContentType; clientResponse.SetResponseStreamAsText(string.Format( "--{0}\r\n" + "Content-Type: application/http\r\n" + "Content-Transfer-Encoding: binary\r\n" + "\r\n" + "200 OK\r\n" + "<feed xmlns='http://www.w3.org/2005/Atom'/>\r\n" + "--{0}--\r\n", testCase.PayloadBatchBoundary)); return(clientResponse); }; DataServiceContext ctx = new DataServiceContext(request.ServiceRoot); Exception exception = TestUtil.RunCatching(() => ctx.ExecuteBatch(ctx.CreateQuery <Customer>("/Customers"))); if (exception != null) { exception = ((DataServiceRequestException)exception).InnerException; Assert.AreEqual(testCase.ExpectedClientErrorMessage, exception.Message, "Unexpected error message."); } else { Assert.IsNull(testCase.ExpectedClientErrorMessage, "Expected exception, but none was thrown."); } } }); }
private void PreferHeader_SetupRequest(TestWebRequest request, string httpMethod, string format, XDocument existingItemAtom, DSPResource existingItem, Action<XDocument> modifyInputAtom) { string realHttpMethod = httpMethod; if (realHttpMethod == "POSTMR") { realHttpMethod = "POST"; } request.HttpMethod = realHttpMethod; request.RequestContentType = httpMethod == "POSTMR" ? UnitTestsUtil.MimeTextPlain : format; request.Accept = format; XDocument inputAtom = new XDocument(existingItemAtom); // Remove all nav property links as those are not supported on some operations inputAtom.Root.Elements(UnitTestsUtil.AtomNamespace + "link").Where(e => e.Attribute("rel").Value.Contains("http://docs.oasis-open.org/odata/ns/related/") || e.Attribute("rel").Value.Contains("http://docs.oasis-open.org/odata/ns/relatedlinks/")).Remove(); request.RequestHeaders["Slug"] = null; if (httpMethod == "POST") { inputAtom.Root.Element(UnitTestsUtil.AtomNamespace + "content").Element(UnitTestsUtil.MetadataNamespace + "properties") .Element(UnitTestsUtil.DataNamespace + "ID").Value = "1"; request.IfMatch = null; request.RequestUriString = "/Items"; } else if (httpMethod == "POSTMR") { request.RequestHeaders["Slug"] = "1"; request.IfMatch = null; request.RequestUriString = "/Streams"; } else { request.IfMatch = existingItem.GetETag(); request.RequestUriString = "/Items(0)"; } if (httpMethod == "POSTMR") { request.SetRequestStreamAsText("some text content"); } else { if (modifyInputAtom != null) { modifyInputAtom(inputAtom); } request.SetRequestStreamAsText(inputAtom.ToString()); } }
/// <summary> /// Runs a batch test. For the purposes of exact baselining, this will strip off the guids from the boundary markers /// in the batch response. Also replaces the string BASE_URI with the service's base URI in any expected response text, /// so metadata in the response can be properly compared. Ignore the action-specific fields on the SimpleBatchTestCase. /// </summary> /// <param name="testCase">Description of the test.</param> /// <param name="serviceType">The DataServiceType to use.</param> private static void RunBatchTest(SimpleBatchTestCase testCase, Type serviceType, string requestUriString, Func <string> exceptionMessageFunc) { using (TestWebRequest request = TestWebRequest.CreateForInProcessWcf()) { request.HttpMethod = "POST"; request.RequestUriString = requestUriString; request.DataServiceType = serviceType; request.Accept = UnitTestsUtil.MimeMultipartMixed; request.RequestVersion = testCase.RequestDataServiceVersion.ToString(); request.RequestMaxVersion = testCase.RequestMaxDataServiceVersion.ToString(); request.ForceVerboseErrors = true; if (testCase.RequestPayload == null) { request.RequestContentLength = 0; } else { const string boundary = "batch-set"; request.RequestContentType = String.Format("{0}; boundary={1}", UnitTestsUtil.MimeMultipartMixed, boundary); request.SetRequestStreamAsText(BatchRequestWritingUtils.GetBatchText(testCase.RequestPayload, boundary)); } Exception e = TestUtil.RunCatching(request.SendRequest); string response = request.GetResponseStreamAsText(); // Top level status code / response version / etag comparisons Assert.AreEqual(testCase.ResponseStatusCode, request.ResponseStatusCode); Assert.AreEqual(testCase.ResponseVersion.ToString(), request.ResponseVersion); Assert.AreEqual(testCase.ResponseETag, request.ResponseETag); // strip off the guid from the boundries and etag for comparison purposes Regex regex1 = new Regex(@"batchresponse_\w{8}-\w{4}-\w{4}-\w{4}-\w{12}"); response = regex1.Replace(response, "batchresponse"); Regex regex2 = new Regex(@"changesetresponse_\w{8}-\w{4}-\w{4}-\w{4}-\w{12}"); response = regex2.Replace(response, "changesetresponse"); Regex regex3 = new Regex(@"ETag: W/""\w{8}-\w{4}-\w{4}-\w{4}-\w{12}"""); response = regex3.Replace(response, "ETag"); var expectedMessage = exceptionMessageFunc(); if (expectedMessage != null) { Assert.IsNotNull(expectedMessage, "Expected an exception"); Assert.IsTrue(response.Contains(expectedMessage)); } else { // Make exact comparision if given that, or otherwise do a series of str contains if (testCase.ExpectedResponsePayloadExact != null) { Assert.AreEqual(testCase.ExpectedResponsePayloadExact.Replace("BASE_URI", request.BaseUri + "/"), response); } else { foreach (string str in testCase.ExpectedResponsePayloadContains) { Assert.IsTrue(response.Contains(str.Replace("BASE_URI", request.BaseUri + "/")), String.Format("The response:\r\n{0}\r\nDoes not contain the string:\r\n{1}.", response, str)); } } Assert.IsNull(e, "No exception expected but received one."); } } }
public void SetupOverflowRequest(TestWebRequest request, bool useCollections) { TestUtil.CheckArgumentNotNull(request, "request"); StringBuilder builder; int entryId = 100; request.DataServiceType = typeof(CustomDataContext); request.RequestUriString = "/Customers"; switch (this.feature) { case StackConsumingFeature.AtomDeserializer: // ATOM deserializer shares limits with JSON deserialized. int atomDeserializerDepth = 105; request.HttpMethod = "POST"; request.RequestContentType = SerializationFormatData.Atom.MimeTypes[0]; builder = new StringBuilder(); string entryTail = "xml:base=\"/\" " + TestUtil.CommonPayloadNamespaces + ">" + AtomUpdatePayloadBuilder.GetCategoryXml(typeof(Customer).FullName); // "<category term=\"" + typeof(Customer).FullName + "\" scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" />"; for (int i = 0; i < atomDeserializerDepth; i++) { if (i != 0) { builder.Append("<adsm:inline>"); } if (i == 1) { entryTail = "> " + AtomUpdatePayloadBuilder.GetCategoryXml(typeof(Customer).FullName); } builder.Append("<entry " + entryTail); builder.Append("<content type=\"application/xml\"><adsm:properties>"); builder.Append("<ads:ID>" + (entryId++).ToString() + "</ads:ID></adsm:properties></content>"); builder.Append("<link rel='http://docs.oasis-open.org/odata/ns/related/BestFriend' title='BestFriend'>"); } for (int i = 0; i < atomDeserializerDepth; i++) { if (i != 0) { builder.Append("</adsm:inline>"); } builder.Append("</link></entry>"); } request.SetRequestStreamAsText(builder.ToString()); break; case StackConsumingFeature.JsonDeserializer: // JSON deserializer survives 1000 nested objects but not 2000 on Vista Ultimate x86 chk under debugger. We hard-code to 100. int jsonDeserializerDepth = 200; request.HttpMethod = "POST"; request.RequestContentType = UnitTestsUtil.JsonLightMimeType; builder = new StringBuilder(); for (int i = 0; i < jsonDeserializerDepth; i++) { builder.Append("{ @odata.type: \"" + typeof(Customer).FullName + "\" , ID: " + (entryId++).ToString() + ", BestFriend : "); } // builder.Append("null"); // null not supported builder.Append(" { ID : 110000 } "); builder.Append('}', jsonDeserializerDepth); request.SetRequestStreamAsText(builder.ToString()); break; case StackConsumingFeature.JsonReader: // JSON reader is not recursive in ODL, so we pick a large depth here to verify that it doesn't break. int jsonReaderDepth = 3000; request.HttpMethod = "POST"; request.RequestContentType = UnitTestsUtil.JsonLightMimeType; request.SetRequestStreamAsText(new string('[', jsonReaderDepth) + " abc "); break; case StackConsumingFeature.RequestQueryParser: // Query parser survives 1000 nested expressions but not 5000 on Vista Ultimate x86 chk under the debugger. We hard-code to 100 nested expressions. int queryParserDepth = 115; request.RequestUriString += "?$filter=" + new string('(', queryParserDepth) + "true" + new string(')', queryParserDepth); break; case StackConsumingFeature.RequestUriProcessor: // The Uri constructor already restricts to 65520 characters. // Request processor is hard-coded to reject more than 100 segments of querying. int processorDepth = 101; builder = new StringBuilder(request.RequestUriString + "(1)"); for (int i = 0; i < processorDepth; i++) { builder.Append("/a"); } request.RequestUriString = builder.ToString(); break; case StackConsumingFeature.JsonSerializer: request.DataServiceType = useCollections ? typeof(StackOverflowCollectionCustomDataContext) : typeof(StackOverflowCustomDataContext); request.Accept = AstoriaUnitTests.Data.SerializationFormatData.JsonLight.MimeTypes[0]; break; case StackConsumingFeature.AtomSerializer: request.DataServiceType = useCollections ? typeof(StackOverflowCollectionCustomDataContext) : typeof(StackOverflowCustomDataContext); request.Accept = AstoriaUnitTests.Data.SerializationFormatData.Atom.MimeTypes[0]; break; case StackConsumingFeature.XmlSerializer: request.DataServiceType = useCollections ? typeof(StackOverflowCollectionCustomDataContext) : typeof(StackOverflowCustomDataContext); request.RequestUriString = "/Customers(1)/Address"; break; default: Debug.Fail("Unknown feature."); break; } }
public void SetupOverflowRequest(TestWebRequest request, bool useCollections) { TestUtil.CheckArgumentNotNull(request, "request"); StringBuilder builder; int entryId = 100; request.DataServiceType = typeof(CustomDataContext); request.RequestUriString = "/Customers"; switch (this.feature) { case StackConsumingFeature.AtomDeserializer: // ATOM deserializer shares limits with JSON deserialized. int atomDeserializerDepth = 105; request.HttpMethod = "POST"; request.RequestContentType = SerializationFormatData.Atom.MimeTypes[0]; builder = new StringBuilder(); string entryTail = "xml:base=\"/\" " + TestUtil.CommonPayloadNamespaces + ">" + AtomUpdatePayloadBuilder.GetCategoryXml(typeof(Customer).FullName); // "<category term=\"" + typeof(Customer).FullName + "\" scheme=\"http://docs.oasis-open.org/odata/ns/scheme\" />"; for (int i = 0; i < atomDeserializerDepth; i++) { if (i != 0) { builder.Append("<adsm:inline>"); } if (i == 1) { entryTail = "> " + AtomUpdatePayloadBuilder.GetCategoryXml(typeof(Customer).FullName); } builder.Append("<entry " + entryTail); builder.Append("<content type=\"application/xml\"><adsm:properties>"); builder.Append("<ads:ID>" + (entryId++).ToString() + "</ads:ID></adsm:properties></content>"); builder.Append("<link rel='http://docs.oasis-open.org/odata/ns/related/BestFriend' title='BestFriend'>"); } for (int i = 0; i < atomDeserializerDepth; i++) { if (i != 0) { builder.Append("</adsm:inline>"); } builder.Append("</link></entry>"); } request.SetRequestStreamAsText(builder.ToString()); break; case StackConsumingFeature.JsonDeserializer: // JSON deserializer survives 1000 nested objects but not 2000 on Vista Ultimate x86 chk under debugger. We hard-code to 100. int jsonDeserializerDepth = 200; request.HttpMethod = "POST"; request.RequestContentType = UnitTestsUtil.JsonLightMimeType; builder = new StringBuilder(); for (int i = 0; i < jsonDeserializerDepth; i++) { builder.Append("{ @odata.type: \"" + typeof(Customer).FullName + "\" , ID: " + (entryId++).ToString() + ", BestFriend : "); } // builder.Append("null"); // null not supported builder.Append(" { ID : 110000 } "); builder.Append('}', jsonDeserializerDepth); request.SetRequestStreamAsText(builder.ToString()); break; case StackConsumingFeature.JsonReader: // JSON reader is not recursive in ODL, so we pick a large depth here to verify that it doesn't break. int jsonReaderDepth = 3000; request.HttpMethod = "POST"; request.RequestContentType = UnitTestsUtil.JsonLightMimeType; request.SetRequestStreamAsText(new string('[', jsonReaderDepth) + " abc "); break; case StackConsumingFeature.RequestQueryParser: // Query parser survives 1000 nested expressions but not 5000 on Vista Ultimate x86 chk under the debugger. We hard-code to 100 nested expressions. int queryParserDepth = 115; request.RequestUriString += "?$filter=" + new string('(', queryParserDepth) + "true" + new string(')', queryParserDepth); break; case StackConsumingFeature.RequestUriProcessor: // The Uri constructor already restricts to 65520 characters. // Request processor is hard-coded to reject more than 100 segments of querying. int processorDepth = 101; builder = new StringBuilder(request.RequestUriString + "(1)"); for (int i = 0; i < processorDepth; i++) { builder.Append("/a"); } request.RequestUriString = builder.ToString(); break; case StackConsumingFeature.JsonSerializer: request.DataServiceType = useCollections ? typeof(StackOverflowCollectionCustomDataContext) : typeof(StackOverflowCustomDataContext); request.Accept = AstoriaUnitTests.Data.SerializationFormatData.JsonLight.MimeTypes[0]; break; case StackConsumingFeature.AtomSerializer: request.DataServiceType = useCollections ? typeof(StackOverflowCollectionCustomDataContext) : typeof(StackOverflowCustomDataContext); request.Accept = AstoriaUnitTests.Data.SerializationFormatData.Atom.MimeTypes[0]; break; case StackConsumingFeature.XmlSerializer: request.DataServiceType = useCollections ? typeof(StackOverflowCollectionCustomDataContext) : typeof(StackOverflowCustomDataContext); request.RequestUriString = "/Customers(1)/Address"; break; default: Debug.Fail("Unknown feature."); break; } }
public void NonNullableTopLevelPropertiesTest() { // Create a Test case var testCase = new NonNullablePropertiesTestCase() { RequestUris = new string[] { "/People(1)/Name", "/People(1)/Body", "/People(1)/Age" }, HttpMethods = new string[] { "PUT" }, }; // Run the variations test.TestUtil.RunCombinations( new DSPUnitTestServiceDefinition[] { service }, testCase.HttpMethods, testCase.RequestUris, new string[] { UnitTestsUtil.JsonLightMimeType }, ServiceVersion.ValidVersions, // requestDSV ServiceVersion.ValidVersions, // requestMDSV ServiceVersion.ValidVersions, // maxProtocolVersion (localService, httpMethod, requestUri, format, requestDSV, requestMDSV, maxProtocolVersion) => { if (maxProtocolVersion == null) { return; } localService.DataServiceBehavior.MaxProtocolVersion = maxProtocolVersion.ToProtocolVersion(); using (TestWebRequest request = localService.CreateForInProcess()) { if (requestDSV != null && maxProtocolVersion.ToProtocolVersion() < requestDSV.ToProtocolVersion()) { return; } request.StartService(); request.HttpMethod = httpMethod; request.RequestUriString = requestUri; request.Accept = format; if (requestDSV != null) { request.RequestVersion = requestDSV.ToString(); } if (requestMDSV != null) { request.RequestMaxVersion = requestMDSV.ToString(); } request.RequestContentType = format; // TODO: Change the payload of null top-level properties #645 request.SetRequestStreamAsText(@"{ ""value"" : null }"); IDisposable dispose = null; if (httpMethod != "GET") { dispose = service.CreateChangeScope(GetDefaultData(service.Metadata)); } var exception = test.TestUtil.RunCatching(request.SendRequest); Assert.IsNotNull(exception, "Exception is always expected."); Assert.IsNotNull(exception.InnerException, "InnerException is always expected."); if (requestUri.Substring(requestUri.LastIndexOf("/") + 1) == "Office") { Assert.AreEqual("System.Data.Entity", exception.InnerException.Source, "Source expected: System.Data.Entity, actual: " + exception.InnerException.Source); Assert.AreEqual(500, request.ResponseStatusCode, "Status code expected: 500" + ", actual: " + request.ResponseStatusCode); } else { // For primitive properties provider decides what to do. For EF, we get an exception with response code of 500. Assert.AreEqual(500, request.ResponseStatusCode, "Status code expected: 500" + ", actual: " + request.ResponseStatusCode); } dispose.Dispose(); } }); }
public void EncodingFromAcceptCharsetTest() { // It takes over a minute to run all combinations. CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("EncodingData", EncodingData.Values), new Dimension("StringData", StringData.Values), new Dimension("SerializationFormatData", SerializationFormatData.StructuredValues), new Dimension("WebServerLocation", new object[] { WebServerLocation.InProcess })); engine.Mode = CombinatorialEngineMode.EveryElement; TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable table) { EncodingData encodingData = (EncodingData)table["EncodingData"]; StringData stringData = (StringData)table["StringData"]; WebServerLocation location = (WebServerLocation)table["WebServerLocation"]; SerializationFormatData format = (SerializationFormatData)table["SerializationFormatData"]; if (encodingData.Encoding == null) { return; } if (!EncodingHandlesString(encodingData.Encoding, "<>#&;\r\n")) { return; } // Transliteration of ISCII characters and Unicode is possible, but round-tripping from // Unicode will not work because all phonetic sounds share an ISCII value, but have // distinct Unicode points depending on the language. if (encodingData.Name.StartsWith("x-iscii") && stringData.TextScript != null && stringData.TextScript.SupportsIscii) { return; } using (CustomDataContext.CreateChangeScope()) using (TestWebRequest request = TestWebRequest.CreateForLocation(location)) { request.DataServiceType = typeof(CustomDataContext); request.HttpMethod = "POST"; request.RequestUriString = "/Customers"; request.RequestContentType = UnitTestsUtil.JsonLightMimeType; request.SetRequestStreamAsText("{ " + "@odata.type : \"AstoriaUnitTests.Stubs.Customer\" ," + "ID: 100," + "Name: " + System.Data.Test.Astoria.Util.JsonPrimitiveTypesUtil.PrimitiveToString(stringData.Value, typeof(string)) + " }"); request.SendRequest(); request.HttpMethod = "GET"; request.AcceptCharset = encodingData.Name; request.Accept = format.MimeTypes[0]; request.RequestUriString = "/Customers(100)"; bool encoderCanHandleData = EncodingHandlesString(encodingData.Encoding, stringData.Value); Trace.WriteLine("Encoding handles string: " + encoderCanHandleData); Exception exception = TestUtil.RunCatching(request.SendRequest); XmlDocument document = null; Stream byteStream = new MemoryStream(); if (exception == null) { using (Stream stream = request.GetResponseStream()) { IOUtil.CopyStream(stream, byteStream); } byteStream.Position = 0; Trace.WriteLine(TestUtil.BuildHexDump(byteStream)); byteStream.Position = 0; if (format == SerializationFormatData.Atom) { document = new XmlDocument(TestUtil.TestNameTable); using (StreamReader reader = new StreamReader(byteStream, encodingData.Encoding)) { document.Load(reader); } TestUtil.TraceXml(document); XmlElement nameElement = TestUtil.AssertSelectSingleElement(document, "//ads:Name"); if (stringData.Value == null) { Assert.IsTrue(UnitTestsUtil.HasElementNullValue(nameElement, new System.Net.Mime.ContentType(request.ResponseContentType).MediaType)); } else { Assert.AreEqual(stringData.Value, nameElement.InnerText); } } } else { TestUtil.AssertExceptionExpected(exception, !encoderCanHandleData); } } }); }
[Ignore] // Remove Atom // [TestCategory("Partition2"), TestMethod, Variation] public void TestExceedMaxBatchCount() { // Astoria Server: Assert on Batch Request after configuring MaxBatchCount TestUtil.ClearConfiguration(); try { using (CustomDataContext.CreateChangeScope()) using (TestWebRequest request = TestWebRequest.CreateForInProcess()) using (StaticCallbackManager <InitializeServiceArgs> .RegisterStatic((sender, args) => { args.Config.SetEntitySetAccessRule("*", EntitySetRights.All); args.Config.MaxBatchCount = 1; args.Config.UseVerboseErrors = true; })) { request.ServiceType = typeof(TypedDataService <CustomDataContext>); request.HttpMethod = "POST"; request.RequestUriString = "/$batch"; request.RequestContentType = "multipart/mixed;boundary=boundary1"; request.SetRequestStreamAsText( "--boundary1\r\n" + "Content-Type: multipart/mixed; boundary=cs\r\n" + "\r\n" + "--cs\r\n" + "Content-Type: application/http\r\n" + "Content-Transfer-Encoding: binary\r\n" + "\r\n" + "POST /Customers HTTP/1.1\r\n" + "Content-Type: application/atom+xml\r\n" + "Accept: application/atom+xml\r\n" + "Content-ID : 2\r\n" + "\r\n" + "<entry xmlns:ads='http://docs.oasis-open.org/odata/ns/data' xmlns:adsm='http://docs.oasis-open.org/odata/ns/metadata' xmlns='http://www.w3.org/2005/Atom' adsm:type='#AstoriaUnitTests.Stubs.Customer'>\r\n" + "<content type='application/xml'>\r\n" + "<adsm:properties>\r\n" + "<ads:ID ads:type='Edm.Int32'>10</ads:ID>\r\n" + "</adsm:properties>\r\n" + "</content></entry>\r\n" + "--cs--\r\n" + "--boundary1\r\n" + "Content-Type: multipart/mixed; boundary=cs\r\n" + "\r\n" + "--cs\r\n" + "Content-Type: application/http\r\n" + "Content-Transfer-Encoding: binary\r\n" + "\r\n" + "POST /Customers HTTP/1.1\r\n" + "Content-Type: application/atom+xml\r\n" + "Accept: application/atom+xml\r\n" + "Content-ID : 2\r\n" + "\r\n" + "<entry xmlns:ads='http://docs.oasis-open.org/odata/ns/data' xmlns:adsm='http://docs.oasis-open.org/odata/ns/metadata' xmlns='http://www.w3.org/2005/Atom' adsm:type='#AstoriaUnitTests.Stubs.Customer'>\r\n" + "<content type='application/xml'>\r\n" + "<adsm:properties>\r\n" + "<ads:ID ads:type='Edm.Int32'>10</ads:ID>\r\n" + "</adsm:properties>\r\n" + "</content></entry>\r\n" + "--cs--\r\n" + "--boundary1--"); Exception exception = TestUtil.RunCatching(request.SendRequest); TestUtil.AssertExceptionExpected(exception, false); string response = request.GetResponseStreamAsText(); TestUtil.AssertContains(response, "exceeds"); } } finally { TestUtil.ClearMetadataCache(); } }
[Ignore] // Remove Atom // [TestCategory("Partition2"), TestMethod, Variation] public void ConfigurationBatchTest() { CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("MaxBatchCount", new int[] { -1, 0, 1, 2, 10 }), new Dimension("MaxChangeSetCount", new int[] { -1, 0, 1, 2, 10 }), new Dimension("BatchCount", new int[] { 0, 1, 2 }), new Dimension("ChangeSetCount", new int[] { 0, 1, 2 }) ); TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { int maxBatchCount = (int)values["MaxBatchCount"]; int maxChangeSetCount = (int)values["MaxChangeSetCount"]; int batchCount = (int)values["BatchCount"]; int changeSetCount = (int)values["ChangeSetCount"]; TestUtil.ClearConfiguration(); using (CustomDataContext.CreateChangeScope()) using (TestWebRequest request = TestWebRequest.CreateForInProcess()) using (StaticCallbackManager <InitializeServiceArgs> .RegisterStatic((sender, args) => { args.Config.SetEntitySetAccessRule("*", EntitySetRights.All); args.Config.MaxBatchCount = maxBatchCount; args.Config.MaxChangesetCount = maxChangeSetCount; args.Config.UseVerboseErrors = true; })) { request.ServiceType = typeof(TypedDataService <CustomDataContext>); request.RequestUriString = "/$batch"; request.HttpMethod = "POST"; request.Accept = "*/*"; string boundary = "boundary"; request.RequestContentType = String.Format("{0}; boundary={1}", UnitTestsUtil.MimeMultipartMixed, boundary); int customerId = 1000; int contentId = 0; StringBuilder payload = new StringBuilder(); for (int i = 0; i < batchCount; i++) { StringBuilder batchElement = new StringBuilder(); if (i % 2 == 0) { string changesetBoundary = "cs"; for (int j = 0; j < changeSetCount; j++) { StringBuilder changeSetElement = new StringBuilder(); changeSetElement.AppendLine("<entry " + TestUtil.CommonPayloadNamespaces + ">"); changeSetElement.AppendLine(AtomUpdatePayloadBuilder.GetCategoryXml("AstoriaUnitTests.Stubs.Customer")); changeSetElement.AppendLine(" <content type='application/xml'><adsm:properties>"); changeSetElement.AppendLine(" <ads:Name>A New Customer</ads:Name>"); changeSetElement.AppendLine(" <ads:ID>" + customerId++ + "</ads:ID>"); changeSetElement.AppendLine(" </adsm:properties></content></entry>"); int length = changeSetElement.Length; changeSetElement.Insert(0, "--" + changesetBoundary + "\r\n" + "Content-Type: application/http\r\n" + "Content-Transfer-Encoding: binary\r\n" + "Content-ID: " + (++contentId).ToString() + "\r\n" + "\r\n" + "POST /Customers HTTP/1.1\r\n" + "Content-Type: application/atom+xml;type=entry\r\n" + "Content-Length: " + length + "\r\n" + "\r\n"); batchElement.Append(changeSetElement.ToString()); } batchElement.AppendLine("--" + changesetBoundary + "--"); int batchLength = batchElement.Length; batchElement.Insert(0, "--" + boundary + "\r\n" + "Content-Type: multipart/mixed; boundary=" + changesetBoundary + "\r\n" + "Content-Length: " + batchLength + "\r\n" + "\r\n"); } else { // Do a GET request. batchElement.AppendLine("--" + boundary); batchElement.AppendLine("Content-Type: application/http"); batchElement.AppendLine("Content-Transfer-Encoding: binary"); batchElement.AppendLine(); batchElement.AppendLine("GET /Customers HTTP/1.1"); batchElement.AppendLine("Content-Length: 0"); batchElement.AppendLine(); } payload.Append(batchElement.ToString()); } payload.AppendLine("--" + boundary + "--"); string payloadText = payload.ToString(); Trace.WriteLine("Payload text:"); Trace.WriteLine(payloadText); request.SetRequestStreamAsText(payloadText); // Build a payload. Exception exception = TestUtil.RunCatching(request.SendRequest); TestUtil.AssertExceptionExpected(exception, maxBatchCount < 0, maxChangeSetCount < 0); if (exception == null) { string text = request.GetResponseStreamAsText(); if (maxBatchCount < batchCount || (batchCount > 0 && maxChangeSetCount < changeSetCount)) { TestUtil.AssertContains(text, "error"); } else { TestUtil.AssertContainsFalse(text, "error"); } } } }); }