public void ETag_VerifyETagInPayloadInTopLevelPost() { string jsonPayload = "{ " + "@odata.type : \"AstoriaUnitTests.Stubs.Customer\" ," + "Name: \"Bar\"," + "ID: 125" + "}"; string[] jsonXPath = new string[] { String.Format("count(/{0}/odata.etag)=1", JsonValidator.ObjectString) }; string atomPayload = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" + "<entry xml:base=\"/\" " + TestUtil.CommonPayloadNamespaces + ">" + AtomUpdatePayloadBuilder.GetCategoryXml(typeof(Customer).FullName) + "<content type=\"application/xml\">" + "<adsm:properties>" + "<ads:Name>Foo</ads:Name>" + "<ads:ID>125</ads:ID>" + "</adsm:properties>" + "</content>" + "</entry>"; string[] atomXPaths = new string[] { "count(/atom:entry/@adsm:etag)=1" }; using (CustomDataContext.CreateChangeScope()) { GetResponse("/Customers", UnitTestsUtil.JsonLightMimeType, typeof(CustomDataContext), jsonXPath, null, "POST", jsonPayload); } using (CustomDataContext.CreateChangeScope()) { GetResponse("/Customers", UnitTestsUtil.AtomFormat, typeof(CustomDataContext), atomXPaths, null, "POST", atomPayload); } }
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 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; } }
[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"); } } } }); }