public void TopBatchReturingODataError() { const string payload = @"<?xml version=""1.0"" encoding=""utf-8"" standalone=""yes""?> <error xmlns=""http://docs.oasis-open.org/odata/ns/metadata""> <code></code> <message xml:lang=""en-US"">This error must show up in the error returned below</message> </error>"; IODataRequestMessage requestMessage = new ODataTestMessage(); var responseMessage = new ODataTestMessage(); responseMessage.SetHeader("Content-Type", "application\atom+xml"); responseMessage.SetHeader("OData-Version", "4.0"); responseMessage.StatusCode = 400; responseMessage.WriteToStream(payload); responseMessage.SetHeader("Content-Length", "0"); var context = new DataServiceContextWithCustomTransportLayer(ODataProtocolVersion.V4, requestMessage, responseMessage); context.AddObject("Products", new SimpleNorthwind.Product() { ID = 1 }); Action test = () => context.SaveChanges(SaveChangesOptions.BatchWithSingleChangeset); // we should be returning an ODataErrorException instead of the full contents test.ShouldThrow<DataServiceRequestException>() .WithInnerException<DataServiceClientException>() .And.InnerException.Message.Should().Be("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\r\n<error xmlns=\"http://docs.oasis-open.org/odata/ns/metadata\">\r\n <code></code>\r\n <message xml:lang=\"en-US\">This error must show up in the error returned below</message>\r\n</error>"); }
public void WebExceptionShouldNotBeSurfacedWhenGetResponseThrowsOnBatch() { IODataRequestMessage requestMessage = new ODataTestMessage(); var context = new DataServiceContextWithCustomTransportLayer(ODataProtocolVersion.V4, () => requestMessage, () => { throw new WebException("web exception on getting response"); }); Action test = () => context.ExecuteBatch(context.CreateQuery<NorthwindModel.Products>("Products")); test.ShouldThrow<WebException>().WithMessage("web exception on getting response"); }
public void WebExceptionShouldNotBeSurfacedWhenSaveChangesWithBatch() { IODataRequestMessage requestMessage = new ODataTestMessage(); var context = new DataServiceContextWithCustomTransportLayer(ODataProtocolVersion.V4, () => requestMessage, () => { throw new WebException("web exception on getting response"); }); context.AddObject("Products", new SimpleNorthwind.Product() { ID = 1 }); Action test = () => context.SaveChanges(SaveChangesOptions.BatchWithSingleChangeset); test.ShouldThrow<WebException>().WithMessage("web exception on getting response"); }
public void WebExceptionShouldNotBeSurfacedWhenSaveChangesWithNonBatch() { IODataRequestMessage requestMessage = new ODataTestMessage(); var context = new DataServiceContextWithCustomTransportLayer(ODataProtocolVersion.V4, () => requestMessage, () => { throw new WebException("web exception on getting response"); }); context.AddObject("Products", new SimpleNorthwind.Product() { ID = 1 }); Action test = () => context.SaveChanges(SaveChangesOptions.None); var innerInnerException = test.ShouldThrow<DataServiceRequestException>().WithInnerException<DataServiceClientException>().And.InnerException.InnerException; innerInnerException.Should().BeOfType<WebException>(); innerInnerException.Message.Should().Be("web exception on getting response"); }
public void AttachEntityAddEntityAndBindSaveChanges() { var odataRequestMessage = new ODataTestMessage(); var odataResponseMessage = new ODataTestMessage() { StatusCode = 202, MemoryStream = new MemoryStream(Encoding.UTF8.GetBytes(@"<?xml version=""1.0"" encoding=""utf-8"" standalone=""yes""?> <entry xml:base=""http://services.odata.org/OData/OData.svc/"" xmlns:d=""http://schemas.microsoft.com/ado/2007/08/dataservices"" xmlns:m=""http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"" xmlns=""http://www.w3.org/2005/Atom""> <id>http://services.odata.org/OData/OData.svc/Suppliers(2)</id> <category term=""ODataDemo.Product"" scheme=""http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"" /> <link rel=""edit"" title=""AnnotationTests_Product"" href=""Products(2)"" /> <title /> <updated>2012-11-15T19:29:45Z</updated> <author> <name /> </author> <content type=""application/xml""> <m:properties> <d:ID m:type=""Edm.Int32"">1</d:ID> </m:properties> </content> </entry>")) }; odataResponseMessage.SetHeader("DataServiceId", "http://service/foo/Products(2)"); odataResponseMessage.SetHeader("Location", "http://service/foo/Products(2)"); odataResponseMessage.SetHeader("Content-Type", "application/atom+xml"); DataServiceContextWithCustomTransportLayer context = new DataServiceContextWithCustomTransportLayer(DataServiceProtocolVersion.V3, () => odataRequestMessage, () => odataResponseMessage); WritingNavigationLinkArgs startingNavigLinkArgs = null; WritingNavigationLinkArgs endingNavigLinkArgs = null; WritingEntityReferenceLinkArgs args = null; context.Configurations.RequestPipeline.OnNavigationLinkStarting((r => startingNavigLinkArgs = r)); context.Configurations.RequestPipeline.OnNavigationLinkEnding((r => endingNavigLinkArgs = r)); context.Configurations.RequestPipeline.OnEntityReferenceLink((r => args = r)); SimpleNorthwind.Product product = new SimpleNorthwind.Product() { ID = 1 }; SimpleNorthwind.Supplier supplier = new SimpleNorthwind.Supplier() { ID = 2 }; context.AddObject("Products", product); context.AttachTo("Suppliers", supplier); context.SetLink(product, "Supplier", supplier); context.SaveChanges(); VerifyWritingNavigationLinkArgs(startingNavigLinkArgs, null, product, supplier, "Supplier"); VerifyWritingNavigationLinkArgs(endingNavigLinkArgs, null, product, supplier, "Supplier"); args.Should().NotBeNull(); args.EntityReferenceLink.Url.AbsoluteUri.Should().Be("http://somedummyuri/myService.svc/Suppliers(2)"); }
public void BindTwoEntitiesSaveChanges() { var odataRequestMessage = new ODataTestMessage(); var odataResponseMessage = new ODataTestMessage(){StatusCode = 204}; DataServiceContextWithCustomTransportLayer context = new DataServiceContextWithCustomTransportLayer(DataServiceProtocolVersion.V3, () => odataRequestMessage, () => odataResponseMessage); WritingEntityReferenceLinkArgs args = null; context.Configurations.RequestPipeline.OnEntityReferenceLink((r => args = r)); SimpleNorthwind.Product product = new SimpleNorthwind.Product() {ID = 1}; SimpleNorthwind.Supplier supplier = new SimpleNorthwind.Supplier() {ID = 2}; context.AttachTo("Products", product); context.AttachTo("Suppliers", supplier); context.SetLink(product, "Supplier", supplier); context.SaveChanges(); // Note writing entity links is not triggered here as its not in the payload args.Should().BeNull(); odataRequestMessage.Method.Should().Be("PUT"); odataRequestMessage.Url.AbsoluteUri.Should().Be("http://somedummyuri/myService.svc/Products(1)/$links/Supplier"); }
private static void RunClientRequest(Action<DataServiceContext> runTest, string expectedRequestPayload = null, string responsePayload = null, Action<IODataResponseMessage> setupResponse = null) { using (var requestStream = new MemoryStream()) using (var responseStream = responsePayload == null ? new MemoryStream() : new MemoryStream(Encoding.UTF8.GetBytes(responsePayload))) { responseStream.Position = 0; var requestMessage = new InMemoryMessage {Stream = requestStream}; var responseMessage = new InMemoryMessage {Stream = responseStream}; if (setupResponse != null) { setupResponse(responseMessage); } DataServiceContext ctx = new DataServiceContextWithCustomTransportLayer(ODataProtocolVersion.V4, requestMessage, responseMessage); runTest(ctx); if (expectedRequestPayload != null) { var actualRequestPayload = Encoding.UTF8.GetString(requestStream.ToArray()); Assert.AreEqual(expectedRequestPayload, actualRequestPayload); } } }
private DataServiceContextWithCustomTransportLayer CreateTransportLayerContext(string payload, string odataVersion) { IODataRequestMessage requestMessage = new ODataTestMessage(); var responseMessage = new ODataTestMessage(); responseMessage.SetHeader("Content-Type", "application/json"); responseMessage.SetHeader("OData-Version", odataVersion); responseMessage.StatusCode = 200; responseMessage.WriteToStream(payload); responseMessage.SetHeader("Content-Length", responseMessage.MemoryStream.Length.ToString()); var context = new DataServiceContextWithCustomTransportLayer(ODataProtocolVersion.V4, requestMessage, responseMessage); context.ResolveName = ResolveName; context.ResolveType = ResolveType; context.Format.UseJson(Model); return context; }
public void NotModifiedTest() { var odataRequestMessage = new ODataTestMessage(); var odataResponseMessage = new ODataTestMessage() { StatusCode = 304, MemoryStream = new MemoryStream(Encoding.UTF8.GetBytes(@"")) }; odataResponseMessage.SetHeader("Content-Type", "0"); DataServiceContextWithCustomTransportLayer context = new DataServiceContextWithCustomTransportLayer(ODataProtocolVersion.V4, () => odataRequestMessage, () => odataResponseMessage); Action test = () => context.CreateQuery<SimpleNorthwind.Product>("Products").ToList(); test.ShouldThrow<DataServiceQueryException>().WithInnerMessage("NotModified"); }
private static void SendRequestAndVerifyUriAndContext(DSPServiceDefinition service, Func<IEnumerable<Tuple<Func<DataServiceContext, IQueryable>[], Func<DataServiceContext, string>, Action<DataServiceContext, IQueryable, List<object>>>>> queryUrisAndValidations) { using (InProcessWebRequest request = (InProcessWebRequest)service.CreateForInProcess()) { request.StartService(); ODataProtocolVersion[] versions = new ODataProtocolVersion[] { ODataProtocolVersion.V4 }; t.TestUtil.RunCombinations(queryUrisAndValidations(), versions, (testCase, version) => { var getQueries = testCase.Item1; var getExpectedUri = testCase.Item2; var validate = testCase.Item3; foreach (var getQuery in getQueries) { var host = new t.TestServiceHost2(); var requestMessage = new DataServiceHostRequestMessage(host); var ctx = new DataServiceContextWithCustomTransportLayer(request.ServiceRoot, version, () => requestMessage, () => { request.SendRequest(host); return new DataServiceHostResponseMessage(host); }); ctx.EnableAtom = true; ctx.Format.UseAtom(); if (version < ODataProtocolVersion.V4) { var query = getQuery(ctx); try { foreach (var p in query) { } Assert.Fail("Exception expected but received none."); } catch (NotSupportedException e) { Assert.IsTrue( "The expression 'TypeAs' is not supported when MaxProtocolVersion is less than '4.0'." == e.Message || "The method 'OfType' is not supported when MaxProtocolVersion is less than '4.0'." == e.Message); } } else { #region Setup resolvers and events ctx.ResolveType = (typeName) => { if (typeName == typeof(Employee).FullName) { return typeof(Employee); } if (typeName == typeof(PeopleManager).FullName) { return typeof(PeopleManager); } return null; }; ctx.SendingRequest2 += (sender, e) => { Assert.AreEqual("4.0", e.RequestMessage.GetHeader("OData-Version"), "OData-Version mismatch."); Assert.AreEqual("4.0", e.RequestMessage.GetHeader("OData-MaxVersion"), "OData-MaxVersion mismatch."); }; #endregion Setup resolvers and events // Validate Uri var query = getQuery(ctx); string clientGeneratedUri = query.ToString(); Assert.AreEqual(getExpectedUri(ctx), clientGeneratedUri); #region Validate entities List<object> materializedObjects = new List<object>(); // Materialize and validate LinkInfos foreach (var e in query) { EntityDescriptor descriptor = ctx.GetEntityDescriptor(e); if (descriptor != null) { foreach (var link in descriptor.LinkInfos) { switch (link.Name) { case "Aquaintances": case "DirectReports": case "Manager": case "Colleagues": case "BestFriend": case "Friends": // If the entity is not of the base type (Person), then expect navigation links to have a type segment. if (descriptor.ServerTypeName != "AstoriaUnitTests.Tests.DerivedProperty.Person") { t.TestUtil.AssertContains(link.NavigationLink.OriginalString, descriptor.ServerTypeName); if (link.AssociationLink != null) { t.TestUtil.AssertContains(link.AssociationLink.OriginalString, descriptor.ServerTypeName); } } break; default: Assert.Fail("Unexpected link: " + link.Name); return; } } } materializedObjects.Add(e); } #endregion Validate entities #region Validate Links // Validate LinkDescriptors foreach (LinkDescriptor link in ctx.Links) { string identity = ctx.GetEntityDescriptor(link.Source).Identity.AbsoluteUri; int startIdx = identity.IndexOf('(') + 1; int endIdx = identity.IndexOf(')'); int sourceId = int.Parse(identity.Substring(startIdx, endIdx - startIdx)); identity = ctx.GetEntityDescriptor(link.Target).Identity.AbsoluteUri; startIdx = identity.IndexOf('(') + 1; endIdx = identity.IndexOf(')'); int targetId = int.Parse(identity.Substring(startIdx, endIdx - startIdx)); switch (link.SourceProperty) { case "DirectReports": switch (sourceId) { case 1: //"Foo": Assert.Fail("DirectReports link not expected for Foo"); break; case 2: //"Andy": //Assert.IsTrue(targetName == "Pratik" || targetName == "Jimmy"); Assert.IsTrue(targetId == 3 || targetId == 4); break; case 3: //"Pratik": Assert.Fail("DirectReports link not expected for Pratik"); break; case 4: //"Jimmy": Assert.Fail("DirectReports link not expected for Jimmy"); break; case 5: //"Shyam": //Assert.IsTrue(targetName == "Andy" || targetName == "Marcelo"); Assert.IsTrue(targetId == 2 || targetId == 6); break; case 6: //"Marcelo": Assert.Fail("DirectReports link not expected for Marcelo"); break; default: Assert.Fail("Unrecognized id: " + sourceId); break; } break; case "Manager": switch (sourceId) { case 1: //"Foo": Assert.Fail("Manager link not expected for Foo"); break; case 2: //"Andy": //Assert.AreEqual("Shyam", targetName); Assert.AreEqual(5, targetId); break; case 3: //"Pratik": //Assert.AreEqual("Andy", targetName); Assert.AreEqual(2, targetId); break; case 4: //"Jimmy": //Assert.AreEqual("Andy", targetName); Assert.AreEqual(2, targetId); break; case 5: //"Shyam": //Assert.AreEqual("Shyam", targetName); Assert.AreEqual(5, targetId); break; case 6: //"Marcelo": //Assert.AreEqual("Shyam", targetName); Assert.AreEqual(5, targetId); break; default: Assert.Fail("Unrecognized id: " + sourceId); break; } break; case "Colleagues": switch (sourceId) { case 1: //"Foo": Assert.Fail("Colleagues link not expected for Foo"); break; case 2: //"Andy": //Assert.AreEqual("Marcelo", targetName); Assert.AreEqual(6, targetId); break; case 3: //"Pratik": //Assert.AreEqual("Jimmy", targetName); Assert.AreEqual(4, targetId); break; case 4: //"Jimmy": //Assert.AreEqual("Pratik", targetName); Assert.AreEqual(3, targetId); break; case 5: //"Shyam": Assert.Fail("Colleagues link not expected for Shyam"); break; case 6: //"Marcelo": //Assert.AreEqual("Andy", targetName); Assert.AreEqual(2, targetId); break; default: Assert.Fail("Unrecognized id: " + sourceId); break; } break; case "BestFriend": switch (sourceId) { case 1: //"Foo": //Assert.AreEqual("Pratik", targetName); Assert.AreEqual(3, targetId); break; case 2: //"Andy": //Assert.AreEqual("Shyam", targetName); Assert.AreEqual(5, targetId); break; case 3: //"Pratik": //Assert.AreEqual("Andy", targetName); Assert.AreEqual(2, targetId); break; case 4: //"Jimmy": //Assert.AreEqual("Foo", targetName); Assert.AreEqual(1, targetId); break; case 5: //"Shyam": //Assert.AreEqual("Marcelo", targetName); Assert.AreEqual(6, targetId); break; case 6: //"Marcelo": //Assert.AreEqual("Jimmy", targetName); Assert.AreEqual(4, targetId); break; default: Assert.Fail("Unrecognized id: " + sourceId); break; } break; case "Friends": break; default: Assert.Fail("Unexpected link descriptor: " + link.SourceProperty); return; } } #endregion Validate Links // Validation specific to the test case. validate(ctx, query, materializedObjects); } } }); } }
public void WebExceptionShouldeSurfacedWhenGetResponseThrowsOnNonBatch() { IODataRequestMessage requestMessage = new ODataTestMessage(); var context = new DataServiceContextWithCustomTransportLayer(ODataProtocolVersion.V4, () => requestMessage, () => { throw new WebException("web exception on getting response"); }); Action test = () => context.CreateQuery<NorthwindModel.Products>("Products").ToList(); var exception = test.ShouldThrow<Exception>().And; // Should not be surfacing an internal exception exception.Should().BeOfType<WebException>(); exception.Message.Should().Be("web exception on getting response"); }
private static Action GetQueryWithInjectedObjectDisposedOnGetStream(bool useExecuteBatch) { IODataRequestMessage requestMessage = new ODataTestMessage(); var responseMessage = CreateResponseMessageWithGetStreamThrowingObjectDisposeException(); var context = new DataServiceContextWithCustomTransportLayer(ODataProtocolVersion.V4, requestMessage, responseMessage); if (useExecuteBatch) { return () => context.ExecuteBatch(context.CreateQuery<NorthwindModel.Products>("Products")); } else { return () => context.CreateQuery<NorthwindModel.Products>("Products").ToList(); } }
private static Action AddObjectWithInjectedObjectDisposedOnGetStreamO(SaveChangesOptions saveChangesOptions) { IODataRequestMessage requestMessage = new ODataTestMessage(); var responseMessage = CreateResponseMessageWithGetStreamThrowingObjectDisposeException(); var context = new DataServiceContextWithCustomTransportLayer(ODataProtocolVersion.V4, requestMessage, responseMessage); context.AddObject("Products", new SimpleNorthwind.Product() { ID = 1 }); return () => context.SaveChanges(saveChangesOptions); }
private static DataServiceQueryException TopLevelErrorPayloadWithTransportException(int statusCode, Action<DataServiceContextWithCustomTransportLayer> contextAction) { IODataRequestMessage requestMessage = new ODataTestMessage(); TopLevelBatchResponseMessage topLevelResponse = new TopLevelBatchResponseMessage(); byte[] payload = Encoding.UTF8.GetBytes("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\r\n<error xmlns=\"http://docs.oasis-open.org/odata/ns/metadata\">\r\n <code></code>\r\n <message xml:lang=\"en-US\">This error must show up in the error returned below</message>\r\n</error>"); topLevelResponse.SetHeader("OData-Version", "4.0"); topLevelResponse.SetHeader("Content-Type", "application/xml"); topLevelResponse.SetHeader("Content-Length", payload.Length.ToString()); topLevelResponse.StatusCode = statusCode; topLevelResponse.GetStreamFunc = () => { return new MemoryStream(payload); }; var context = new DataServiceContextWithCustomTransportLayer(ODataProtocolVersion.V4, () => requestMessage, () => { throw new DataServiceTransportException(topLevelResponse, new WebException()); }); context.EnableAtom = true; Action test = () => contextAction(context); var exception = test.ShouldThrow<DataServiceQueryException>().And; return exception; }