internal static Func<string, string> GetComparer(BatchWriterTestDescriptor.BatchWriterOperationTestDescriptor operationDescriptor, WriterTestConfiguration testConfiguration) { string expectedContent = null; bool indent = testConfiguration.MessageWriterSettings.Indent; var variables = TestWriterUtils.GetPayloadVariablesForTestConfiguration(testConfiguration); Func<string, string> normalizer = null; Func<string, string> comparer = null; var queryOperation = operationDescriptor as BatchWriterTestDescriptor.BatchWriterQueryOperationTestDescriptor; if (queryOperation != null) { // query operations don't specify content expectedContent = null; } else { var changeSetOperation = operationDescriptor as BatchWriterTestDescriptor.BatchWriterChangeSetOperationTestDescriptor; if (changeSetOperation != null) { if (changeSetOperation.Payload != null) { Debug.Assert(changeSetOperation.ODataPayload == null, "changeSetOperation.ODataPayload == null"); expectedContent = changeSetOperation.Payload; expectedContent = StringUtils.ResolveVariables(expectedContent, variables); } else if (changeSetOperation.ODataPayload != null) { Debug.Assert(changeSetOperation.Payload == null, "changeSetOperation.Payload == null"); if (changeSetOperation.ODataPayload.WriterTestExpectedResults != null) { comparer = GetComparerForWriterTestExpectedResults(changeSetOperation.ODataPayload); } else { expectedContent = changeSetOperation.ODataPayload.ExpectedResult; if (changeSetOperation.ODataPayload.TestConfiguration.Format == ODataFormat.Atom) { expectedContent = XmlUtils.GetComparableXmlString(expectedContent, variables, indent); normalizer = (observed) => XmlUtils.GetComparableXmlString(observed, null, indent); } else if (changeSetOperation.ODataPayload.TestConfiguration.Format == ODataFormat.Json) { expectedContent = JsonUtils.GetComparableJsonString(expectedContent, variables); } else { throw new NotSupportedException("Only ATOM and JSON formats are supported for batch payloads."); } } } } else { var responseOperation = operationDescriptor as BatchWriterTestDescriptor.BatchWriterResponseOperationTestDescriptor; if (responseOperation != null) { if (responseOperation.Payload != null) { Debug.Assert(responseOperation.ODataPayload == null, "responsePart.ODataPayload == null"); expectedContent = responseOperation.Payload; expectedContent = StringUtils.ResolveVariables(expectedContent, variables); } else if (responseOperation.ODataPayload != null) { Debug.Assert(responseOperation.Payload == null, "responsePart.Payload == null"); if (responseOperation.ODataPayload.WriterTestExpectedResults != null) { comparer = GetComparerForWriterTestExpectedResults(responseOperation.ODataPayload); } else { expectedContent = responseOperation.ODataPayload.ExpectedResult; if (responseOperation.ODataPayload.TestConfiguration.Format == ODataFormat.Atom) { expectedContent = XmlUtils.GetComparableXmlString(expectedContent, variables, indent); normalizer = (observed) => XmlUtils.GetComparableXmlString(observed, null, indent); } else if (responseOperation.ODataPayload.TestConfiguration.Format == ODataFormat.Json) { expectedContent = JsonUtils.GetComparableJsonString(expectedContent, variables); } else { throw new NotSupportedException("Only ATOM and JSON formats are supported for batch payloads."); } } } } else { throw new InvalidOperationException("Found unsupported operation descriptor of type " + operationDescriptor.GetType().FullName + "."); } } } return (observedContent) => { if (comparer != null) { return comparer(observedContent); } if (normalizer != null) { observedContent = normalizer(observedContent); } if (string.CompareOrdinal(expectedContent, observedContent) != 0) { return string.Format( "Different operation content.{0}Expected:{0}-->{1}<--{0}Actual:{0}-->{2}<--{0}", Environment.NewLine, expectedContent, observedContent); } return null; }; }
private static WriterTestConfiguration ModifyBatchTestConfig(WriterTestConfiguration testConfig, BatchWriterTestDescriptor testDescriptor) { ODataMessageWriterSettings newSettings = null; if (testDescriptor.BaseUri != null) { // clone the message writer settings with a new base Uri newSettings = testConfig.MessageWriterSettings.Clone(); newSettings.PayloadBaseUri = testDescriptor.BaseUri; } if (testDescriptor.MaxPartsPerBatch.HasValue || testDescriptor.MaxOperationsPerChangeset.HasValue) { if (newSettings == null) { newSettings = testConfig.MessageWriterSettings.Clone(); } if (testDescriptor.MaxPartsPerBatch.HasValue) { newSettings.MessageQuotas.MaxPartsPerBatch = testDescriptor.MaxPartsPerBatch.Value; } if (testDescriptor.MaxOperationsPerChangeset.HasValue) { newSettings.MessageQuotas.MaxOperationsPerChangeset = testDescriptor.MaxOperationsPerChangeset.Value; } } return newSettings == null ? testConfig : new WriterTestConfiguration(testConfig.Format, newSettings, testConfig.IsRequest, testConfig.Synchronous); }
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); }); }
public void ResolverUriTest() { Uri inputUri = new Uri("inputUri", UriKind.Relative); Uri resultRelativeUri = new Uri("resultRelativeUri", UriKind.Relative); Uri resultAbsoluteUri = new Uri("http://odata.org/absoluteresolve"); var resolvers = new [] { // Resolver which always returns relative URL new { Resolver = new Func<Uri, Uri, Uri>((baseUri, payloadUri) => { if (payloadUri.OriginalString == inputUri.OriginalString) { return resultRelativeUri; } else { return null; }}), ResultUri = resultRelativeUri }, // Resolver which always returns absolute URL new { Resolver = new Func<Uri, Uri, Uri>((baseUri, payloadUri) => { if (payloadUri.OriginalString == inputUri.OriginalString) { return resultAbsoluteUri; } else { return null; }}), ResultUri = resultAbsoluteUri } }; var testDescriptors = uriTestCases.SelectMany(testCase => resolvers.Select(resolver => { return new { TestCase = testCase, Descriptor = new PayloadWriterTestDescriptor<ODataItem>( this.Settings, testCase.ItemFunc(inputUri), CreateUriTestCaseExpectedResultCallback(/*baseUri*/ null, resolver.ResultUri, testCase)) { UrlResolver = new TestUrlResolver() { ResolutionCallback = resolver.Resolver } } }; })); // ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight this.CombinatorialEngineProvider.RunCombinations( testDescriptors, new bool[] { false, true }, this.WriterTestConfigurationProvider.ExplicitFormatConfigurations.Where(c => c.Format == ODataFormat.Atom), (testDescriptor, runInBatch, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); if ((!testConfiguration.IsRequest || !testDescriptor.TestCase.ResponseOnly) && (testConfiguration.Format == ODataFormat.Json && testDescriptor.TestCase.JsonExtractor != null || testConfiguration.Format == ODataFormat.Atom && testDescriptor.TestCase.AtomExtractor != null)) { var td = testDescriptor.Descriptor.DeferredLinksToEntityReferenceLinksInRequest(testConfiguration); if (!runInBatch) { TestWriterUtils.WriteAndVerifyODataPayload(td, testConfiguration, this.Assert, this.Logger); } else { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.DisableMessageStreamDisposal = false; var batchDescriptor = new List<BatchWriterTestDescriptor.InvocationAndOperationDescriptor>(); if (testConfiguration.IsRequest) { batchDescriptor.Add(BatchWriterUtils.StartBatch()); batchDescriptor.Add(BatchWriterUtils.StartChangeSet()); batchDescriptor.Add(BatchWriterUtils.ChangeSetRequest( "PUT", new Uri("http://odata.org"), null, null, new BatchWriterUtils.ODataPayload() { Items = td.PayloadItems.ToArray(), WriterTestExpectedResults = td.ExpectedResultCallback(testConfiguration), TestConfiguration = testConfiguration })); batchDescriptor.Add(BatchWriterUtils.EndChangeSet()); batchDescriptor.Add(BatchWriterUtils.EndBatch()); } else { batchDescriptor.Add(BatchWriterUtils.StartBatch()); batchDescriptor.Add(BatchWriterUtils.QueryOperationResponse( 200, new BatchWriterUtils.ODataPayload() { Items = td.PayloadItems.ToArray(), WriterTestExpectedResults = td.ExpectedResultCallback(testConfiguration), TestConfiguration = testConfiguration })); batchDescriptor.Add(BatchWriterUtils.EndBatch()); } var batchTd = new BatchWriterTestDescriptor( this.BatchSettings, batchDescriptor.ToArray(), (Dictionary<string, string>)null, new Uri("http://odata.org/service"), td.UrlResolver); ODataMessageWriterSettings batchWriterSettings = new ODataMessageWriterSettings(testConfiguration.MessageWriterSettings); batchWriterSettings.SetContentType(null); WriterTestConfiguration batchTestConfiguration = new WriterTestConfiguration( null, batchWriterSettings, testConfiguration.IsRequest, testConfiguration.Synchronous); BatchWriterUtils.WriteAndVerifyBatchPayload(batchTd, batchTestConfiguration, testConfiguration, this.Assert); } } }); }