public void DisposeAfterExceptionTest() { // create a default entry and then set both read and edit links to null to provoke an exception during writing ODataEntry entry = ObjectModelUtils.CreateDefaultEntry(); this.Assert.IsNull(entry.EditLink, "entry.EditLink == null"); this.CombinatorialEngineProvider.RunCombinations( new ODataItem[] { entry }, new bool[] { true, false }, // writeError new bool[] { true, false }, // flush this.WriterTestConfigurationProvider.ExplicitFormatConfigurations.Where(c => c.IsRequest == false), (payload, writeError, flush, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); // try writing to a memory stream using (var memoryStream = new TestStream()) using (var messageWriter = TestWriterUtils.CreateMessageWriter(memoryStream, testConfiguration, this.Assert)) { ODataWriter writer = messageWriter.CreateODataWriter(isFeed: false); ODataWriterCoreInspector inspector = new ODataWriterCoreInspector(writer); try { // write the invalid entry and expect an exception TestExceptionUtils.ExpectedException( this.Assert, () => TestWriterUtils.WritePayload(messageWriter, writer, false, entry), ODataExpectedExceptions.ODataException("WriterValidationUtils_EntriesMustHaveNonEmptyId"), this.ExceptionVerifier); this.Assert.IsTrue(inspector.IsInErrorState, "Writer is not in expected 'error' state."); if (writeError) { // now write an error which is the only valid thing to do ODataAnnotatedError error = new ODataAnnotatedError { Error = new ODataError() { Message = "DisposeAfterExceptionTest error message." } }; Exception ex = TestExceptionUtils.RunCatching(() => TestWriterUtils.WritePayload(messageWriter, writer, false, error)); this.Assert.IsNull(ex, "Unexpected error '" + (ex == null ? "<none>" : ex.Message) + "' while writing an error."); this.Assert.IsTrue(inspector.IsInErrorState, "Writer is not in expected 'error' state."); } if (flush) { writer.Flush(); } } catch (ODataException oe) { if (writeError && !flush) { this.Assert.AreEqual("A writer or stream has been disposed with data still in the buffer. You must call Flush or FlushAsync before calling Dispose when some data has already been written.", oe.Message, "Did not find expected error message"); this.Assert.IsTrue(inspector.IsInErrorState, "Writer is not in expected 'error' state."); } else { this.Assert.Fail("Caught an unexpected ODataException: " + oe.Message + "."); } } } }); }
public void ODataBatchWriterODataPayloadSmokeTests() { // Create OData payloads ODataEntry sampleEntry = ObjectModelUtils.CreateDefaultEntryWithAtomMetadata(); ODataFeed sampleFeed = ObjectModelUtils.CreateDefaultFeedWithAtomMetadata(); ODataAnnotatedError sampleError = ObjectModelUtils.CreateDefaultError(true); ODataItem[] entryPayload = new ODataItem[] { sampleEntry }; ODataItem[] feedPayload = new ODataItem[] { sampleFeed, sampleEntry }; ODataAnnotatedError[] errorPayload = new ODataAnnotatedError[] { sampleError }; // the expected entry result (ATOM and JSON) Func<ODataVersion, string> entryPayloadExpectedAtomResult = version => string.Join( "$(NL)", @"<entry xmlns=""" + TestAtomConstants.AtomNamespace + @""" xmlns:d=""" + TestAtomConstants.ODataNamespace + @""" xmlns:m=""" + TestAtomConstants.ODataMetadataNamespace + @""" xmlns:georss=""" + TestAtomConstants.GeoRssNamespace + @""" xmlns:gml=""" + TestAtomConstants.GmlNamespace + @""">" + @" <id>" + ObjectModelUtils.DefaultEntryId + "</id>", @" <link rel=""self"" href=""" + ObjectModelUtils.DefaultEntryReadLink + @""" />", @" <title />", @" <updated>" + ObjectModelUtils.DefaultEntryUpdated + "</updated>", @" <author>", @" <name />", @" </author>", @" <content type=""application/xml"" />", @"</entry>"); string[] entryPayloadExpectedJsonResult = new string[] { "{", "$(Indent)\"__metadata\":{", "$(Indent)$(Indent)\"id\":\"http://www.odata.org/entryid\",\"uri\":\"http://www.odata.org/entry/readlink\"", "$(Indent)}", "}" }; // create the expected feed result (ATOM and JSON) Func<ODataVersion, string> feedPayloadExpectedAtomResult = version => string.Join( "$(NL)", @"<feed xmlns=""" + TestAtomConstants.AtomNamespace + @""" xmlns:d=""" + TestAtomConstants.ODataNamespace + @""" xmlns:m=""" + TestAtomConstants.ODataMetadataNamespace + @""" xmlns:georss=""" + TestAtomConstants.GeoRssNamespace + @""" xmlns:gml=""" + TestAtomConstants.GmlNamespace + @""">" + @" <id>http://www.odata.org/feedid</id>", @" <title />", @" <updated>2010-10-10T10:10:10Z</updated>", @" <entry>", @" <id>" + ObjectModelUtils.DefaultEntryId + "</id>", @" <link rel=""self"" href=""" + ObjectModelUtils.DefaultEntryReadLink + @""" />", @" <title />", @" <updated>" + ObjectModelUtils.DefaultEntryUpdated + "</updated>", @" <author>", @" <name />", @" </author>", @" <content type=""application/xml"" />", @" </entry>", @"</feed>"); string[] feedPayloadExpectedJsonResult = new string[] { "[", "$(Indent){", "$(Indent)$(Indent)\"__metadata\":{", "$(Indent)$(Indent)$(Indent)\"id\":\"http://www.odata.org/entryid\",\"uri\":\"http://www.odata.org/entry/readlink\"", "$(Indent)$(Indent)}", "$(Indent)}", "]" }; // create the expected error result (ATOM and JSON) string errorPayloadExpectedAtomResult = string.Join( "$(NL)", @"<m:error xmlns:m=""" + TestAtomConstants.ODataMetadataNamespace + @""">", @" <m:code>Default error code</m:code>", @" <m:message xml:lang=""Default error message language."">Default error message.</m:message>", @" <m:innererror>", @" <m:message>Default inner error.</m:message>", @" <m:type></m:type>", @" <m:stacktrace></m:stacktrace>", @" </m:innererror>", @"</m:error>"); string[] errorPayloadExpectedJsonResult = new string[] { "{", "$(Indent)\"error\":{", "$(Indent)$(Indent)\"code\":\"Default error code\",\"message\":{", "$(Indent)$(Indent)$(Indent)\"lang\":\"Default error message language.\",\"value\":\"Default error message.\"", "$(Indent)$(Indent)},\"innererror\":{", "$(Indent)$(Indent)$(Indent)\"message\":\"Default inner error.\",\"type\":\"\",\"stacktrace\":\"\"", "$(Indent)$(Indent)}", "$(Indent)}", "}", }; // create the various query and changeset batches var testCases = new Func<WriterTestConfiguration, BatchTestWithDirection>[] { testConfig => { // entry payload of query operation response with 200 response code string expectedResult = testConfig.Format == ODataFormat.Atom ? entryPayloadExpectedAtomResult(testConfig.Version) : JsonUtils.WrapTopLevelValue(testConfig, entryPayloadExpectedJsonResult); testConfig = SetAcceptableHeaders(testConfig); return new BatchTestWithDirection { Batch = BatchWriterUtils.CreateQueryResponseBatch( 200, new BatchWriterUtils.ODataPayload() { Items = entryPayload, TestConfiguration = testConfig, ExpectedResult = expectedResult }, GetExpectedHeadersForFormat(testConfig.Format, ODataPayloadKind.Entry)), ForRequests = false }; }, testConfig => { // feed payload of query operation response with 200 response code string expectedResult = testConfig.Format == ODataFormat.Atom ? feedPayloadExpectedAtomResult(testConfig.Version) : JsonUtils.WrapTopLevelResults(testConfig, feedPayloadExpectedJsonResult); testConfig = SetAcceptableHeaders(testConfig); return new BatchTestWithDirection { Batch = BatchWriterUtils.CreateQueryResponseBatch( 200, new BatchWriterUtils.ODataPayload() { Items = feedPayload, TestConfiguration = testConfig, ExpectedResult = expectedResult }, GetExpectedHeadersForFormat(testConfig.Format, ODataPayloadKind.Feed)), ForRequests = false }; }, testConfig => { // error payload of query operation response with 200 response code string expectedResult = testConfig.Format == ODataFormat.Atom ? errorPayloadExpectedAtomResult : string.Join("$(NL)", errorPayloadExpectedJsonResult); testConfig = SetAcceptableHeaders(testConfig); return new BatchTestWithDirection { Batch = BatchWriterUtils.CreateQueryResponseBatch( 200, new BatchWriterUtils.ODataPayload() { Items = errorPayload, TestConfiguration = testConfig, ExpectedResult = expectedResult }, GetExpectedHeadersForFormat(testConfig.Format, ODataPayloadKind.Error)), ForRequests = false }; }, testConfig => { // changeset request with entry payload string expectedResult = testConfig.Format == ODataFormat.Atom ? entryPayloadExpectedAtomResult(testConfig.Version) : JsonUtils.WrapTopLevelValue(testConfig, entryPayloadExpectedJsonResult); testConfig = SetAcceptableHeaders(testConfig); return new BatchTestWithDirection { Batch = BatchWriterUtils.CreateChangeSetRequestBatch( "POST", new Uri("http://services.odata.org/OData/OData.svc/Products"), new BatchWriterUtils.ODataPayload() { Items = entryPayload, TestConfiguration = testConfig, ExpectedResult = expectedResult }, GetExpectedHeadersForFormat(testConfig.Format, ODataPayloadKind.Entry) ), ForRequests = true }; }, testConfig => { // changeset response with entry payload string expectedResult = testConfig.Format == ODataFormat.Atom ? entryPayloadExpectedAtomResult(testConfig.Version) : JsonUtils.WrapTopLevelValue(testConfig, entryPayloadExpectedJsonResult); testConfig = SetAcceptableHeaders(testConfig); return new BatchTestWithDirection { Batch = BatchWriterUtils.CreateChangeSetResponseBatch( 200, new BatchWriterUtils.ODataPayload() { Items = entryPayload, TestConfiguration = testConfig, ExpectedResult = expectedResult }, GetExpectedHeadersForFormat(testConfig.Format, ODataPayloadKind.Entry) ), ForRequests = false }; }, testConfig => { // changeset response with error payload string expectedResult = testConfig.Format == ODataFormat.Atom ? errorPayloadExpectedAtomResult : string.Join("$(NL)", errorPayloadExpectedJsonResult); testConfig = SetAcceptableHeaders(testConfig); return new BatchTestWithDirection { Batch = BatchWriterUtils.CreateChangeSetResponseBatch( 200, new BatchWriterUtils.ODataPayload() { Items = errorPayload, TestConfiguration = testConfig, ExpectedResult = expectedResult }, GetExpectedHeadersForFormat(testConfig.Format, ODataPayloadKind.Error)), ForRequests = false }; }, }; // TODO: Fix places where we've lost JsonVerbose coverage to add JsonLight // Write everything to the batch (ATOM + JSON) this.CombinatorialEngineProvider.RunCombinations( testCases, this.WriterTestConfigurationProvider.DefaultFormatConfigurationsWithIndent, this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent.Where(tc => !tc.MessageWriterSettings.DisableMessageStreamDisposal && tc.Format == ODataFormat.Atom), (testCase, batchTestConfig, payloadTestConfig) => { if (batchTestConfig.IsRequest != payloadTestConfig.IsRequest) { return; } BatchTestWithDirection testWithDirection = testCase(payloadTestConfig); if (batchTestConfig.IsRequest != testWithDirection.ForRequests) { return; } var testDescriptor = new BatchWriterTestDescriptor(this.Settings, testWithDirection.Batch, (Dictionary<string, string>)null); BatchWriterUtils.WriteAndVerifyBatchPayload(testDescriptor, batchTestConfig, payloadTestConfig, this.Assert); }); }