public void CallbackSuccessQueryKeywordTest() { using (TestWebRequest request = TestWebRequest.CreateForInProcessWcf()) { request.DataServiceType = typeof(CallbackQueryOptionTestService); request.StartService(); request.RequestUriString = "/ReturnNullServiceOperation?$callback=foo"; request.SendRequest(); Assert.AreEqual(204, request.ResponseStatusCode); request.RequestUriString = "/Customers(1)/ID/$value?$callback=foo"; request.SendRequest(); Assert.AreEqual(200, request.ResponseStatusCode); Assert.AreEqual("foo(1)", request.GetResponseStreamAsText()); Assert.AreEqual("text/javascript;charset=utf-8", request.ResponseHeaders["content-type"]); request.RequestUriString = "/Customers/$count?$callback=foo"; request.SendRequest(); Assert.AreEqual(200, request.ResponseStatusCode); var actualText = request.GetResponseStreamAsText(); Assert.IsTrue(actualText.StartsWith("foo(")); Assert.IsTrue(actualText.EndsWith(")")); Assert.AreEqual("text/javascript;charset=utf-8", request.ResponseHeaders["content-type"]); } }
public void CheckRelationshipLinkForDeleteOperationForEntityCollection() { // CreateChangeScope will make sure that changes are preserved after every SendRequest. // By default the data source is created for every request using (UnitTestsUtil.CreateChangeScope(typeof(CustomDataContext))) { using (TestWebRequest request = TestWebRequest.CreateForInProcessWcf()) { request.ServiceType = typeof(RelationshipLinksService); request.RequestUriString = "/Customers(1)/Orders/$ref"; request.HttpMethod = "GET"; request.SendRequest(); var response1 = request.GetResponseStreamAsText(); request.RequestUriString = "/Customers(1)/Orders/$ref?$id=Orders(1)"; request.HttpMethod = "DELETE"; request.SendRequest(); var response = request.GetResponseStreamAsText(); Assert.IsTrue(response != null); Assert.IsTrue(request.ResponseStatusCode == 204); request.RequestUriString = "/Customers(1)/Orders/$ref"; request.HttpMethod = "GET"; request.SendRequest(); var response2 = request.GetResponseStreamAsText(); Assert.IsTrue(response1 != response2); } } }
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 CallbackSuccessQueryTest() { using (TestWebRequest request = TestWebRequest.CreateForInProcessWcf()) { request.DataServiceType = typeof(CustomDataContext); List <string> requestUris = new List <string>() { "/Customers(1)/ID?$format=json&$callback=foo", "/Customers(1)/Orders/$ref?$format=json&$callback=foo", "/Customers/?$expand=Orders&$select=ID,Name,Orders&$top=3&$skip=1&$orderby=ID&$filter=Orders/any(p:p/ID%20ne%200)&$format=json&$callback=foo", "/Customers/?$format=json&$callback=foo&$filter=Orders/all(p:p/ID%20ge%200)&inlinecount=allpages", }; foreach (var requestUri in requestUris) { request.RequestUriString = requestUri; request.SendRequest(); var actualText = request.GetResponseStreamAsText(); Assert.IsTrue(actualText.StartsWith("foo(")); Assert.IsTrue(actualText.EndsWith(")")); Assert.IsTrue(request.ResponseHeaders["content-type"].StartsWith("text/javascript;odata.metadata=minimal;")); Assert.AreEqual(200, request.ResponseStatusCode); } } }
private static void ResponsesShouldBeTheSame(string baselineUri, string testUri, int statusCode, Func <string, string> prepareExpected, Type serviceType) { using (TestServiceHost.AllowServerToSerializeException.Restore()) using (TestWebRequest baselineRequest = TestWebRequest.CreateForInProcess()) using (TestWebRequest testRequest = TestWebRequest.CreateForInProcess()) { TestServiceHost.AllowServerToSerializeException.Value = true; baselineRequest.DataServiceType = serviceType; testRequest.DataServiceType = serviceType; baselineRequest.RequestUriString = baselineUri; testRequest.RequestUriString = testUri; TestUtil.RunCatching(baselineRequest.SendRequest); TestUtil.RunCatching(testRequest.SendRequest); Assert.AreEqual(statusCode, testRequest.ResponseStatusCode); Assert.AreEqual(testRequest.ResponseStatusCode, baselineRequest.ResponseStatusCode); var baselinePayload = prepareExpected(testRequest.GetResponseStreamAsText()); string actualPayload = baselineRequest.GetResponseStreamAsText(); Assert.AreEqual(baselinePayload, actualPayload); } }
[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 CallbackFailOnCUDRequest() { using (TestWebRequest request = TestWebRequest.CreateForInProcessWcf()) { request.DataServiceType = typeof(CustomDataContext); request.RequestUriString = "/Customers(1)?$format=json&$callback=foo"; List <string> methods = new List <string>() { "POST", "PUT", "DELETE" }; request.RequestStream = new MemoryStream(new byte[] { 1, 2, 3, }); foreach (string method in methods) { try { request.HttpMethod = method; request.SendRequest(); Assert.Fail("Request should have failed because it was not a GET request."); } catch (WebException) { var actualText = request.GetResponseStreamAsText(); Assert.IsFalse(actualText.StartsWith("foo(")); Assert.IsTrue(actualText.Contains("$callback can only be specified on GET requests.")); Assert.IsTrue(request.ResponseHeaders["content-type"].StartsWith("application/json")); Assert.AreEqual(400, request.ResponseStatusCode); } } } }
public void PrimitiveCustomAnnotationOnInStreamError() { using (TestWebRequest webRequest = this.SetupRequest()) { webRequest.RequestUriString = "/InStreamErrorGetCustomers"; webRequest.Accept = "application/json;odata.metadata=minimal"; AnnotationValue = new ODataPrimitiveValue(88); TestUtil.RunCatching(webRequest.SendRequest); webRequest.ErrorResponseContent.Should().BeEmpty(); string responseBody = webRequest.GetResponseStreamAsText(); responseBody.Should().StartWith("{\"@odata.context\":\"http://"); responseBody.Should().Contain(string.Concat( "\"ID\":1,", "\"Name\":\"Customer 1\",", "\"NameAsHtml\":\"<html><body>Customer 1</body></html>\",", "\"Birthday\":\"" )); responseBody.Should().EndWith(string.Concat( "},", "{", "\"error\":", "{", "\"code\":\"\",", "\"message\":\"InStreamErrorGetCustomers ThrowForCustomer2 error\",", "\"@location.error\":88", "}", "}" )); HandleExceptionCalls.Should().Be(1); } }
public void RequestUriCaseInsensitive() { // Repro: Path to the .svc file shoud not be case sensitive. WebServerLocation[] locations = new WebServerLocation[] { WebServerLocation.InProcessWcf, WebServerLocation.Local }; CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("location", locations)); TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { WebServerLocation location = (WebServerLocation)values["location"]; using (TestWebRequest request = TestWebRequest.CreateForLocation(location)) { request.DataServiceType = typeof(CustomDataContext); request.RequestUriString = "/Customers"; request.FullRequestUriString = request.FullRequestUriString .Replace(".svc", ".SvC") .Replace("Test", "test"); request.SendRequest(); string response = request.GetResponseStreamAsText(); Trace.WriteLine(response); } }); }
public void HttpProcessUtilityJsonEncodingTest() { CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("Test", TestUtil.CreateDictionary <string, Encoding>( new string[] { UnitTestsUtil.JsonLightMimeType, UnitTestsUtil.JsonLightMimeType + ";charset=utf-16", UnitTestsUtil.JsonLightMimeType + ";charset=GB18030" }, new Encoding[] { Encoding.UTF8, Encoding.Unicode, Encoding.GetEncoding("GB18030") }))); using (CustomDataContext.CreateChangeScope()) using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(CustomDataContext); request.Accept = UnitTestsUtil.JsonLightMimeType; request.HttpMethod = "POST"; int index = 100; TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { KeyValuePair <string, Encoding> test = (KeyValuePair <string, Encoding>)values["Test"]; Encoding encoding = test.Value; request.RequestContentType = test.Key; request.RequestStream = new MemoryStream(); byte[] bytes = encoding.GetBytes("{ @odata.type: 'AstoriaUnitTests.Stubs.Customer', ID : " + index++.ToString() + ", Name : \"P\\\\B \\/K\\\"n\\u00e4c\\f\\tke\\r\\n\\br\\u00f6d AB\" }"); request.RequestStream.Write(bytes, 0, bytes.Length); request.RequestStream.Position = 0; request.RequestUriString = "/Customers"; request.SendRequest(); string responseText = request.GetResponseStreamAsText(); Assert.IsTrue(responseText.Contains(@"P\\B /K\" + "\"" + @"n\u00e4c\f\tke\r\n\br\u00f6d AB"), "Response [" + responseText + "] contains the expected escape sequences."); }); } }
public void CallbackFailOnAtomXml() { using (TestWebRequest request = TestWebRequest.CreateForInProcessWcf()) { request.DataServiceType = typeof(CustomDataContext); List <string> requestUriStrings = new List <string>() { "/Customers(1)?$callback=foo", "/Customers(1)/Address?$callback=foo", }; foreach (string requestUriString in requestUriStrings) { try { request.RequestUriString = requestUriString; request.Accept = "application/atom+xml,application/xml"; request.SendRequest(); Assert.Fail("Request should have failed because our server defaults to ATOM/XML, which does not support $callback."); } catch (WebException) { var actualText = request.GetResponseStreamAsText(); Assert.IsFalse(actualText.StartsWith("foo(")); Assert.IsTrue(actualText.Contains("is not compatible with the $callback query option.")); 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 RequestUriProcessorKeySpecialRealTest() { double[] doubleValues = new double[] { double.PositiveInfinity, double.NegativeInfinity, double.NaN }; string[] findText = new string[] { "INF", "-INF", "NaN" }; int textIndex = 0; // Index corresponds to the findText array CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("doubleValue", doubleValues)); using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(TypedCustomDataContext <TypedEntity <double, string> >); TypedCustomDataContext <TypedEntity <double, string> > .ClearHandlers(); TypedCustomDataContext <TypedEntity <double, string> > .ClearValues(); TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { double doubleValue = (double)values["doubleValue"]; TypedCustomDataContext <TypedEntity <double, string> > .ValuesRequested += (sender, args) => { TypedCustomDataContext <TypedEntity <double, string> > s = (TypedCustomDataContext <TypedEntity <double, string> >)sender; TypedEntity <double, string> entity = new TypedEntity <double, string>(); entity.ID = doubleValue; s.SetValues(new object[] { entity }); }; try { Assert.IsTrue(textIndex < 3, "Out of bounds for test data array. Please check the doubleValues variable."); string searchValue = findText[textIndex]; // Increment textIndex for next test case ++textIndex; request.RequestUriString = "/Values"; request.Accept = "application/json"; request.SendRequest(); string responseText = request.GetResponseStreamAsText(); Assert.IsTrue(responseText.IndexOf(searchValue) > 0, String.Format("ID \"{0}\" expected in response.", searchValue)); Trace.WriteLine(String.Format("Found ID: {0}", searchValue)); // Finish the test suite after we've ran through all the strings. If we continue, the test suite continues and fails. // Researching into that is a expensive at this time. if (textIndex == 3) { return; } } finally { TypedCustomDataContext <TypedEntity <double, string> > .ClearHandlers(); TypedCustomDataContext <TypedEntity <double, string> > .ClearValues(); } }); } }
public void RequestUriResourceKeyTest() { CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("TypeData", TypeData.Values), new Dimension("UseSmallCasing", new bool[] { true, false }), new Dimension("UseDoublePostfix", new bool[] { true, false })); TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { TypeData typeData = (TypeData)values["TypeData"]; if (!typeData.IsTypeSupportedAsKey) { return; } // TODO: when System.Uri handles '/' correctly, re-enable. if (typeData.ClrType == typeof(System.Xml.Linq.XElement)) { return; } Type entityType = typeof(TypedEntity <,>).MakeGenericType(typeData.ClrType, typeof(int)); CustomDataContextSetup setup = new CustomDataContextSetup(entityType); object idValue = typeData.NonNullValue; if (idValue is byte[]) { // idValue = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; return; } bool useSmallCasing = (bool)values["UseSmallCasing"]; bool useDoublePostFix = (bool)values["UseDoublePostfix"]; if (!(idValue is double) && useDoublePostFix) { return; } string valueAsString = TypeData.FormatForKey(idValue, useSmallCasing, useDoublePostFix); using (TestWebRequest request = TestWebRequest.CreateForLocation(WebServerLocation.InProcess)) { Trace.WriteLine("Running with value: [" + valueAsString + "] for [" + typeData.ToString() + "]"); setup.Id = idValue; setup.MemberValue = 1; request.DataServiceType = setup.DataServiceType; request.Accept = "application/json"; request.RequestUriString = "/Values(" + valueAsString + ")"; Trace.WriteLine("RequestUriString: " + request.RequestUriString); request.SendRequest(); request.GetResponseStreamAsText(); } setup.Cleanup(); }); }
public void OpenTypeUrlTest() { string[] queries = new string[] { "/Values", "/Values('100')/sampleValue2", "/Values('100')/sampleValue4", // no () after sample value 4, it's an array, gets rejected "/Values('100')/notfound", // This should be bad query since we expect to return 404 for open-properties not found }; string[] badQueries = new string[] { "/Values/sampleValue1", // no () after Values "/Values('100')/sampleValue4()", "/Values('100')/sampleValue4('101')", "/Values('100')/sampleValue4('101')/ID", "/Values('100')/sampleValue4(101)", // Since we don't detect types during runtime, this queries will fail "/Values('100')/sampleValue3/Identity/Name", "/Values('100')/sampleValue3/Identity", }; using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(OpenTypeContextWithReflection <OpenElement>); int i = 0; using (StaticCallbackManager <PopulatingValuesEventArgs <OpenElement> > .RegisterStatic((sender, args) => { var o = new OpenElement(); o.ID = "100"; o.Properties.Add("sampleValue1", "abc"); o.Properties.Add("sampleValue2", 12345); args.Values.Add(o); })) { foreach (string query in queries) { i++; Trace.WriteLine(query); request.RequestUriString = query; request.SendRequest(); Trace.WriteLine(request.GetResponseStreamAsText()); } foreach (string query in badQueries) { i++; Trace.WriteLine(query); request.RequestUriString = query; Exception exception = TestUtil.RunCatching(request.SendRequest); TestUtil.AssertExceptionExpected(exception, true); } } } }
public void OpenTypeOrderByTest() { string[][] queries = new string[][] { new string[] { "/Values?$orderby=sampleValue1", "abc", "ABC" }, new string[] { "/Values?$orderby=sampleValue1 desc", "ABC", "abc" }, new string[] { "/Values?$orderby=sampleValue1,sampleValue2", "abc", "ABC" }, new string[] { "/Values('101')/sampleValue4()?$orderby=ID", "101", "102" }, }; using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(OpenTypeContextWithReflection <OpenElement>); using (StaticCallbackManager <PopulatingValuesEventArgs <OpenElement> > .RegisterStatic((sender, args) => { var o = new OpenElement(); o.ID = "101"; o.Properties.Add("sampleValue1", "abc"); o.Properties.Add("sampleValue2", 12345); o.Properties.Add("sampleValue3", true); args.Values.Add(o); o = new OpenElement(); o.Properties.Add("sampleValue1", "ABC"); o.Properties.Add("sampleValue2", 1); o.Properties.Add("sampleValue3", false); args.Values.Add(o); })) { int i = 0; foreach (string[] queryParts in queries) { string query = queryParts[0]; Trace.WriteLine("Running " + query); request.RequestUriString = query; Exception exception = TestUtil.RunCatching(request.SendRequest); TestUtil.AssertExceptionExpected(exception, i == queries.Length - 1); if (exception == null) { string response = request.GetResponseStreamAsText(); int firstOffset = response.IndexOf(queryParts[1]); int secondOffset = response.IndexOf(queryParts[2]); if (firstOffset >= secondOffset) { Assert.Fail( "For '" + query + "' the offset for " + queryParts[1] + " (" + firstOffset + ") should be less than " + "the offset for " + queryParts[2] + " (" + secondOffset + ") in '" + response + "'"); } } i++; } } } }
private static void GetResponseAndVerify(TestWebRequest request, int expectedStatusCode, string[] verificationStrings) { TestUtil.RunCatching(request.SendRequest); Assert.AreEqual(expectedStatusCode, request.ResponseStatusCode); string responsePayload = request.GetResponseStreamAsText(); foreach (string verifyString in verificationStrings) { Assert.IsTrue(responsePayload.Contains(verifyString)); } }
public void WebDataServiceReflectionNoLinqToSql() { // Verifies that no Linq to SQL-specific types appear in metadata. // Incorrect namespace always being defined as System.Data.Linq when you generated a ClientClassGeneration for a LinqToWorkspace uri using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(TypedCustomDataContext <AllTypes>); request.RequestUriString = "/$metadata"; request.SendRequest(); string text = request.GetResponseStreamAsText(); TestUtil.AssertContainsFalse(text, "System.Data"); } }
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 RequestUriProcessorKeySpecialRealTest() { double[] doubleValues = new double[] { double.PositiveInfinity, double.NegativeInfinity, double.NaN }; CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("doubleValue", doubleValues)); using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(TypedCustomDataContext <TypedEntity <double, string> >); TypedCustomDataContext <TypedEntity <double, string> > .ClearHandlers(); TypedCustomDataContext <TypedEntity <double, string> > .ClearValues(); TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { double doubleValue = (double)values["doubleValue"]; TypedCustomDataContext <TypedEntity <double, string> > .ValuesRequested += (sender, args) => { TypedCustomDataContext <TypedEntity <double, string> > s = (TypedCustomDataContext <TypedEntity <double, string> >)sender; TypedEntity <double, string> entity = new TypedEntity <double, string>(); entity.ID = doubleValue; s.SetValues(new object[] { entity }); }; try { request.RequestUriString = "/Values"; request.Accept = "application/atom+xml,application/xml"; request.SendRequest(); XmlDocument document = request.GetResponseStreamAsXmlDocument(); XmlElement element = TestUtil.AssertSelectSingleElement(document, "/atom:feed/atom:entry/atom:id"); Trace.WriteLine("Found ID: " + element.InnerText); request.FullRequestUriString = element.InnerText; Exception exception = TestUtil.RunCatching(request.SendRequest); // One NaN value won't match another except throug the use of the .IsNaN // method. It's probably OK to not support this. TestUtil.AssertExceptionExpected(exception, double.IsNaN(doubleValue)); string responseText = request.GetResponseStreamAsText(); Trace.WriteLine(responseText); } finally { TypedCustomDataContext <TypedEntity <double, string> > .ClearHandlers(); TypedCustomDataContext <TypedEntity <double, string> > .ClearValues(); } }); } }
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 AnnotationBuilderShouldNotBeCalledOutsideMetadataUri() { NumAnnotationBuilderCalls = 0; var testServiceDef = new TestServiceDefinition { DataServiceType = typeof(AnnotationsBuilderDataService) }; using (TestWebRequest request = (testServiceDef).CreateForInProcessWcf()) { request.RequestUriString = request.BaseUri + "/Customers"; request.Accept = "application/atom+xml"; request.RequestMaxVersion = "4.0"; request.SendRequest(); request.GetResponseStreamAsText(); Assert.AreEqual(0, NumAnnotationBuilderCalls); } }
public void VerifyODataLibIsUsedForWritingTopLevelErrors() { // Only ODL knows about json lite serialization, so we know ODL is being used if the json lite error was serialized correctly. const string expectedJsonLitePayload = @"{""error"":{""code"":"""",""message"":""Resource not found for the segment 'Customers'.""}}"; using (TestWebRequest r = TestWebRequest.CreateForInProcessWcf()) { r.DataServiceType = typeof(CustomDataContext); r.RequestUriString = "/Customers(-2345354)"; r.HttpMethod = "GET"; r.Accept = "application/json;odata.metadata=minimal"; TestUtil.RunCatching(() => r.SendRequest()); string responsePayload = r.GetResponseStreamAsText(); Assert.AreEqual(404, r.ResponseStatusCode); Assert.AreEqual(expectedJsonLitePayload, responsePayload); } }
public void CallbackOptionValueTest() { using (TestWebRequest request = TestWebRequest.CreateForInProcessWcf()) { request.DataServiceType = typeof(CustomDataContext); Dictionary <string, string> testCases = new Dictionary <string, string>() { // empty callback option { "?$format=json&$callback=", string.Empty }, // example callback option values from JQuery and DataJS { "?$callback=parent.handleJSONP_0&$format=json", "parent.handleJSONP_0" }, { "?$callback=jQuery18209805240577502099_1348783118115&$format=json&_=1348783118119", "jQuery18209805240577502099_1348783118115" }, // callback option values in special character/format { "?$format=json&$callback=null", "null" }, { "?$callback=" + Uri.EscapeDataString("A string with characters :%*+,/.") + "&$format=json", "A string with characters :%*+,/." }, { "?$callback=" + "<script>$.getJSON(\"http://something.com\",function (data) {alert(data.value);});</script>" + "&$format=json", "<script>$.getJSON(\"http://something.com\",function (data) {alert(data.value);});</script>" }, }; foreach (var testCase in testCases) { request.RequestUriString = "/Customers(1)" + testCase.Key; request.SendRequest(); var actualText = request.GetResponseStreamAsText(); if (testCase.Value.Length == 0) { // We don't do JSONP for empty callback value Assert.IsTrue(actualText.StartsWith(testCase.Value + "{")); Assert.IsTrue(actualText.EndsWith("}")); Assert.IsTrue(request.ResponseHeaders["content-type"].StartsWith("application/json;odata.metadata=minimal;")); } else { Assert.IsTrue(actualText.StartsWith(testCase.Value + "({")); Assert.IsTrue(actualText.EndsWith("})")); Assert.IsTrue(request.ResponseHeaders["content-type"].StartsWith("text/javascript;odata.metadata=minimal;")); } Assert.AreEqual(200, request.ResponseStatusCode); } } }
public void EndToEndAnnotationTestEnsuringAnnotationBuilderCalledOnceAndMetadataBumpedToV3() { NumAnnotationBuilderCalls = 0; var testServiceDef = new TestServiceDefinition { DataServiceType = typeof(AnnotationsBuilderDataService) }; using (TestWebRequest request = (testServiceDef).CreateForInProcessWcf()) { request.RequestUriString = request.BaseUri + "/$metadata"; request.Accept = "application/xml"; request.RequestMaxVersion = "4.0"; request.SendRequest(); var results = request.GetResponseStreamAsText(); var returnedModel = EdmxReader.Parse(XmlTextReader.Create(new StringReader(results))); Assert.IsNotNull(returnedModel); Assert.AreEqual(1, NumAnnotationBuilderCalls); } }
public void DollarFormatSmokeTest() { const string expectedJsonLight = @"{""@odata.context"":""BASE_URI$metadata#Customers(1)/Address"",""StreetAddress"":""Line1"",""City"":""Redmond"",""State"":""WA"",""PostalCode"":""98052""}"; // $format should override accept header and give us json light since MDSV is 3 using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(CustomDataContext); request.Accept = "application/xml"; request.RequestMaxVersion = "4.0"; request.RequestVersion = "4.0"; request.RequestUriString = "/Customers(1)/Address?$format=json"; request.SendRequest(); var actualText = request.GetResponseStreamAsText(); Assert.AreEqual(200, request.ResponseStatusCode); Assert.AreEqual(expectedJsonLight.Replace("BASE_URI", request.BaseUri), actualText); } }
public void OpenTypeJsonWithNulls() { using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { using (StaticCallbackManager <PopulatingValuesEventArgs <OpenElement> > .RegisterStatic((sender, args) => { var o = new OpenElement(); o.Properties["Foo"] = null; args.Values.Add(o); })) { request.DataServiceType = typeof(OpenTypeContextWithReflection <OpenElement>); request.RequestUriString = "/Values"; request.Accept = UnitTestsUtil.JsonLightMimeType; Exception exception = TestUtil.RunCatching(request.SendRequest); String response = request.GetResponseStreamAsText(); Assert.AreEqual(exception, null); Assert.IsTrue(response.Contains("\"Foo\":null")); } } }
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); } }
public void PlainSerializersMimeOverrideTest() { using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(CustomDataContext); request.RequestUriString = "/Customers(1)/NameAsHtml/$value"; request.SendRequest(); Assert.AreEqual("text/html", TestUtil.GetMediaType(request.ResponseContentType)); Assert.IsTrue(request.GetResponseStreamAsText().Contains("<html>"), "Payloads contains '<html>'"); } // Make sure an incompatible accept header causes a content negotiation failure. using (TestWebRequest request = TestWebRequest.CreateForInProcess()) { request.DataServiceType = typeof(CustomDataContext); request.RequestUriString = "/Customers(1)/NameAsHtml/$value"; request.Accept = "text/plain"; Exception exception = System.Data.Test.Astoria.TestUtil.RunCatching(request.SendRequest); Assert.AreEqual(415, request.ResponseStatusCode); Assert.AreEqual(DataServicesResourceUtil.GetString("DataServiceException_UnsupportedMediaType"), exception.InnerException.Message); } }
public void SecurityStackOverflowTest() { CombinatorialEngine engine = CombinatorialEngine.FromDimensions( new Dimension("Feature", StackConsumingFeatureData.Values), new Dimension("UseCollections", new bool [] { false, true })); TestUtil.RunCombinatorialEngineFail(engine, delegate(Hashtable values) { StackConsumingFeatureData feature = (StackConsumingFeatureData)values["Feature"]; WebServerLocation location = WebServerLocation.InProcess; bool useCollections = (bool)values["UseCollections"]; using (TestWebRequest request = TestWebRequest.CreateForLocation(location)) { if (useCollections) { // Collection switch only does a collection version of the test for serializers if (feature.Feature != StackConsumingFeature.AtomSerializer && feature.Feature != StackConsumingFeature.JsonSerializer && feature.Feature != StackConsumingFeature.XmlSerializer) { return; } request.RequestVersion = "4.0"; request.RequestMaxVersion = "4.0"; } feature.SetupOverflowRequest(request, useCollections); Exception exception = TestUtil.RunCatching(request.SendRequest); TestUtil.AssertExceptionExpected(exception, true); TestUtil.AssertExceptionStatusCode(exception, feature.ExpectedStatusCode, ""); if (location == WebServerLocation.InProcess) { TestUtil.AssertContains(request.GetResponseStreamAsText(), feature.ErrorMessageKey); } } }); }
private void PreferHeader_VerifyResponse(TestWebRequest request, string serviceRoot, bool considerResponsePreference, Action<XDocument> responsePayloadValidation) { bool? effectiveResponsePreference; bool expectedPayload = PreferHeader_ShouldContainResponseBody(request, considerResponsePreference, out effectiveResponsePreference); ServiceVersion responseVersion = ServiceVersion.FromHeaderValue(request.ResponseVersion); string preferApplied; request.ResponseHeaders.TryGetValue("Preference-Applied", out preferApplied); string odataEntityId; request.ResponseHeaders.TryGetValue("OData-EntityId", out odataEntityId); if (request.HttpMethod == "POST") { // Substring(1) to remove the first slash // For POST we need to add the (1) to identify the entity posted string itemLocation = serviceRoot + request.RequestUriString.Substring(1) + "(1)"; if (effectiveResponsePreference == false) { Assert.AreEqual(204, request.ResponseStatusCode, "POST without response payload should respond with status 204."); Assert.AreEqual(itemLocation, odataEntityId, "Response to POST without payload must include the OData-EntityId header with the value being the URL of the item posted."); } else { Assert.AreEqual(201, request.ResponseStatusCode, "POST with response payload should respond with status 201."); Assert.IsNull(odataEntityId, "Response to POST with payload must NOT include the OData-EntityId header."); } Assert.AreEqual(itemLocation, request.ResponseLocation, "The response to POST should include the Location header and it must have the URL to the item posted."); } else { Assert.AreEqual(expectedPayload ? 200 : 204, request.ResponseStatusCode, "Unexpected response status for PUT/PATCH."); Assert.IsNull(odataEntityId, "Response to anything other than POST must NOT include the OData-EntityId header."); } if (effectiveResponsePreference.HasValue) { Assert.IsTrue(responseVersion.Version >= 40, "Response which was influenced by the Prefer header must have DSV >= 4.0"); Assert.AreEqual(effectiveResponsePreference == false ? "return=minimal" : "return=representation", preferApplied, "The preference was applied and thus Preference-Applied header should have been included with the right value."); } else { Assert.IsNull(preferApplied, "No Prefer was sent or it was ignored thus Preference-Applied must not be sent in the response."); } if (expectedPayload) { XDocument response = UnitTestsUtil.GetResponseAsAtomXLinq(request); if (responsePayloadValidation != null) { responsePayloadValidation(response); } } else { string response = request.GetResponseStreamAsText(); Assert.IsTrue(string.IsNullOrEmpty(response), "No response should have been sent."); } }