public void BaseUriValidationTest() { string relativeUriString = "abc/pqr/"; Uri absoluteUri = new Uri("http://odata.org"); Uri relativeUri = absoluteUri.MakeRelativeUri(new Uri(absoluteUri, relativeUriString)); string expectedError = "The base URI '" + relativeUriString + "' specified in ODataMessageWriterSettings.PayloadBaseUri is invalid; it must either be null or an absolute URI."; ODataEntry entry = ObjectModelUtils.CreateDefaultEntry(); var testDescriptors = new [] { new { BaseUri = relativeUri, TestDescriptor = new PayloadWriterTestDescriptor<ODataItem>(this.Settings, entry, testConfiguration => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings) { ExpectedODataExceptionMessage = expectedError }) } }; this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.WriterTestConfigurationProvider.ExplicitFormatConfigurations, (testDescriptor, testConfiguration) => { // clone the test configuration and set an invalid base Uri ODataMessageWriterSettings settings = testConfiguration.MessageWriterSettings.Clone(); settings.PayloadBaseUri = testDescriptor.BaseUri; WriterTestConfiguration config = new WriterTestConfiguration(testConfiguration.Format, settings, testConfiguration.IsRequest, testConfiguration.Synchronous); TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor.TestDescriptor, config, this.Assert, this.Logger); }); }
/// <summary> /// Gets the JSON array holding the entries of the given feed. /// </summary> /// <param name="testConfiguration">The test configuration to consider.</param> /// <param name="feed">The JSON value representing the feed.</param> /// <returns>A JSON array with the items in a feed.</returns> public static JsonArray GetTopLevelFeedItemsArray(WriterTestConfiguration testConfiguration, JsonValue feed) { feed = feed.Object().PropertyValue("value"); ExceptionUtilities.CheckObjectNotNull(feed, "The specified JSON Lite payload is not wrapped in the expected \"value\": wrapper."); ExceptionUtilities.Assert(feed.JsonType == JsonValueType.JsonArray, "Feed contents must be an array."); return (JsonArray)feed; }
/// <summary> /// Constructor. /// </summary> /// <param name="writer">The writer to wrap.</param> /// <param name="testConfiguration">The test configuration to use.</param> public ODataWriterTestWrapper(ODataWriter writer, WriterTestConfiguration testConfiguration) { ExceptionUtilities.CheckArgumentNotNull(writer, "writer"); ExceptionUtilities.CheckArgumentNotNull(testConfiguration, "testConfiguration"); this.writer = writer; this.testConfiguration = testConfiguration; }
/// <summary> /// Constructor. /// </summary> /// <param name="parameterWriter">The writer to wrap.</param> /// <param name="testConfiguration">The test configuration to use.</param> public ODataParameterWriterTestWrapper(ODataParameterWriter parameterWriter, WriterTestConfiguration testConfiguration) { ExceptionUtilities.CheckArgumentNotNull(parameterWriter, "parameterWriter"); ExceptionUtilities.CheckArgumentNotNull(testConfiguration, "testConfiguration"); this.parameterWriter = parameterWriter; this.testConfiguration = testConfiguration; }
/// <summary> /// Constructor. /// </summary> /// <param name="collectionWriter">The writer to wrap.</param> /// <param name="testConfiguration">The test configuration to use.</param> public ODataCollectionWriterTestWrapper(ODataCollectionWriter collectionWriter, WriterTestConfiguration testConfiguration) { ExceptionUtilities.CheckArgumentNotNull(collectionWriter, "collectionWriter"); ExceptionUtilities.CheckArgumentNotNull(testConfiguration, "testConfiguration"); this.collectionWriter = collectionWriter; this.testConfiguration = testConfiguration; }
/// <summary> /// Constructor. /// </summary> /// <param name="writer">The writer to wrap.</param> /// <param name="testConfiguration">The test configuration to use.</param> public ODataWriterTestWrapper(ODataWriter writer, WriterTestConfiguration testConfiguration) { ExceptionUtilities.CheckArgumentNotNull(writer, "writer"); ExceptionUtilities.CheckArgumentNotNull(testConfiguration, "testConfiguration"); this.writer = writer; this.testConfiguration = testConfiguration; }
/// <summary> /// Constructor. /// </summary> /// <param name="parameterWriter">The writer to wrap.</param> /// <param name="testConfiguration">The test configuration to use.</param> public ODataParameterWriterTestWrapper(ODataParameterWriter parameterWriter, WriterTestConfiguration testConfiguration) { ExceptionUtilities.CheckArgumentNotNull(parameterWriter, "parameterWriter"); ExceptionUtilities.CheckArgumentNotNull(testConfiguration, "testConfiguration"); this.parameterWriter = parameterWriter; this.testConfiguration = testConfiguration; }
/// <summary> /// Constructor. /// </summary> /// <param name="collectionWriter">The writer to wrap.</param> /// <param name="testConfiguration">The test configuration to use.</param> public ODataCollectionWriterTestWrapper(ODataCollectionWriter collectionWriter, WriterTestConfiguration testConfiguration) { ExceptionUtilities.CheckArgumentNotNull(collectionWriter, "collectionWriter"); ExceptionUtilities.CheckArgumentNotNull(testConfiguration, "testConfiguration"); this.collectionWriter = collectionWriter; this.testConfiguration = testConfiguration; }
/// <summary> /// Constructor. /// </summary> /// <param name="batchWriter">The writer to wrap.</param> /// <param name="testConfiguration">The test configuration to use.</param> public ODataBatchWriterTestWrapper(ODataBatchWriter batchWriter, WriterTestConfiguration testConfiguration) { ExceptionUtilities.CheckArgumentNotNull(batchWriter, "batchWriter"); ExceptionUtilities.CheckArgumentNotNull(testConfiguration, "testConfiguration"); this.batchWriter = batchWriter; this.testConfiguration = testConfiguration; this.contentId = 100; }
/// <summary> /// Constructor. /// </summary> /// <param name="batchWriter">The writer to wrap.</param> /// <param name="testConfiguration">The test configuration to use.</param> public ODataBatchWriterTestWrapper(ODataBatchWriter batchWriter, WriterTestConfiguration testConfiguration) { ExceptionUtilities.CheckArgumentNotNull(batchWriter, "batchWriter"); ExceptionUtilities.CheckArgumentNotNull(testConfiguration, "testConfiguration"); this.batchWriter = batchWriter; this.testConfiguration = testConfiguration; this.contentId = 100; }
/// <summary> /// Verifies that the result of the test (the message reader) is what the test expected. /// </summary> /// <param name="stream">Stream which contains the results of the write.</param> /// <param name="payloadKind">The payload kind specified in the test descriptor.</param> /// <param name="testConfiguration">The test configuration to use.</param> public virtual void VerifyResult( TestMessage message, ODataPayloadKind payloadKind, WriterTestConfiguration testConfiguration, BaselineLogger logger) { // throw if not implemented; eventually we can make this method abstract when the WriterTestExpectedResults // are not used directly anymore throw new NotImplementedException("Subclasses must implement their own validation logic."); }
/// <summary> /// Called to get the expected result of the test. /// </summary> /// <param name="testConfiguration">The test configuration to use.</param> /// <returns>The expected result.</returns> protected virtual WriterTestExpectedResults GetExpectedResult(WriterTestConfiguration testConfiguration) { if (this.ExpectedResultCallback != null) { return(this.ExpectedResultCallback(testConfiguration)); } else { return(null); } }
/// <summary> /// Called before the test is actually executed for the specified test configuration to determine if the test should be skipped. /// </summary> /// <param name="testConfiguration">The test configuration to use.</param> /// <returns>true if the test should be skipped for the <paramref name="testConfiguration"/> or false to run the test.</returns> /// <remarks>Derived classes should always call the base class and return true if the base class returned true.</remarks> protected virtual bool ShouldSkipForTestConfiguration(WriterTestConfiguration testConfiguration) { if (this.SkipTestConfiguration != null) { return(this.SkipTestConfiguration(testConfiguration)); } else { return(false); } }
public static bool IsSupported(this ODataPayloadKind payloadKind, WriterTestConfiguration testConfiguration) { if (payloadKind == ODataPayloadKind.Unsupported) { return false; } if (testConfiguration.IsRequest) { // some payloads are not supported in requests if (payloadKind == ODataPayloadKind.Collection || payloadKind == ODataPayloadKind.Error || payloadKind == ODataPayloadKind.ServiceDocument || payloadKind == ODataPayloadKind.MetadataDocument || // Top-level EntityReferenceLinks payload write requests are not allowed. payloadKind == ODataPayloadKind.EntityReferenceLinks) { return false; } } else { // Parameter payload is not supported in responses. if (payloadKind == ODataPayloadKind.Parameter) { return false; } } if (payloadKind == ODataPayloadKind.MetadataDocument && !testConfiguration.Synchronous) { // Metadata writing is only supported in synchronous scenarios return false; } if (payloadKind == ODataPayloadKind.Batch || payloadKind == ODataPayloadKind.Value || payloadKind == ODataPayloadKind.BinaryValue || payloadKind == ODataPayloadKind.MetadataDocument) { if (testConfiguration.Format != null) { return false; } } if (payloadKind == ODataPayloadKind.Parameter && (testConfiguration.Format != ODataFormat.Json)) { return false; } return true; }
public static bool IsSupported(this ODataPayloadKind payloadKind, WriterTestConfiguration testConfiguration) { if (payloadKind == ODataPayloadKind.Unsupported) { return(false); } if (testConfiguration.IsRequest) { // some payloads are not supported in requests if (payloadKind == ODataPayloadKind.Collection || payloadKind == ODataPayloadKind.Error || payloadKind == ODataPayloadKind.ServiceDocument || payloadKind == ODataPayloadKind.MetadataDocument || // Top-level EntityReferenceLinks payload write requests are not allowed. payloadKind == ODataPayloadKind.EntityReferenceLinks) { return(false); } } else { // Parameter payload is not supported in responses. if (payloadKind == ODataPayloadKind.Parameter) { return(false); } } if (payloadKind == ODataPayloadKind.MetadataDocument && !testConfiguration.Synchronous) { // Metadata writing is only supported in synchronous scenarios return(false); } if (payloadKind == ODataPayloadKind.Batch || payloadKind == ODataPayloadKind.Value || payloadKind == ODataPayloadKind.BinaryValue || payloadKind == ODataPayloadKind.MetadataDocument) { if (testConfiguration.Format != null) { return(false); } } if (payloadKind == ODataPayloadKind.Parameter && (testConfiguration.Format != ODataFormat.Json)) { return(false); } return(true); }
/// <summary> /// Called to get the expected result of the test. /// </summary> /// <param name="testConfiguration">The test configuration to use.</param> /// <returns>The expected result.</returns> protected override WriterTestExpectedResults GetExpectedResult(WriterTestConfiguration testConfiguration) { WriterTestExpectedResults expectedResult = base.GetExpectedResult(testConfiguration); if (expectedResult == null) { throw new NotImplementedException(); } else { return(expectedResult); } }
/// <summary> /// Verifies that the result of the test is what the test expected. /// </summary> /// <param name="stream">The stream after writing the message content. This method should use it /// to read the message content and verify it.</param> /// <param name="payloadKind">The payload kind specified in the test descriptor.</param> /// <param name="testConfiguration">The test configuration to use.</param> public override void VerifyResult( TestMessage message, ODataPayloadKind payloadKind, WriterTestConfiguration testConfiguration, BaselineLogger logger) { // Get observed payload var observed = TestWriterUtils.ReadToString(message); if (logger != null) { logger.LogPayload(TestWriterUtils.BaseLineFixup(observed)); } }
/// <summary> /// If overriden dumps the content of an output message which would be created for the specified test configuration /// into a string and returns it. This is used only for debugging purposes. /// </summary> /// <param name="messageStream">The stream for the message content.</param> /// <param name="testConfiguration">The test configuration to use.</param> /// <returns>The string content of the output message.</returns> protected virtual string DumpOutputMessageContent(Stream messageStream, WriterTestConfiguration testConfiguration) { Debug.Assert(messageStream != null, "Require a message stream."); if (!messageStream.CanSeek) { return("<Cannot dump message content since underlying stream does not support seek.>"); } messageStream.Seek(0, SeekOrigin.Begin); byte[] payload = new byte[messageStream.Length]; messageStream.Read(payload, 0, (int)messageStream.Length); return(Encoding.UTF8.GetString(payload, 0, payload.Length)); }
/// <summary> /// Called before the test is actually executed for the specified test configuration to determine if the test should be skipped. /// </summary> /// <param name="testConfiguration">The test configuration to use.</param> /// <returns>true if the test should be skipped for the <paramref name="testConfiguration"/> or false to run the test.</returns> /// <remarks>Derived classes should always call the base class and return true if the base class returned true.</remarks> protected override bool ShouldSkipForTestConfiguration(WriterTestConfiguration testConfiguration) { if (this.PayloadDescriptor.SkipTestConfiguration != null && this.PayloadDescriptor.SkipTestConfiguration(testConfiguration)) { return(true); } else if (this.SkipTestConfiguration != null) { return(this.SkipTestConfiguration(testConfiguration)); } else { return(false); } }
/// <summary> /// Verifies that the result of the test is what the test expected. /// </summary> /// <param name="stream">The stream after writing the message content. This method should use it /// to read the message content and verify it.</param> /// <param name="payloadKind">The payload kind specified in the test descriptor.</param> /// <param name="testConfiguration">The test configuration to use.</param> public override void VerifyResult( TestMessage message, ODataPayloadKind payloadKind, WriterTestConfiguration testConfiguration, BaselineLogger logger) { // Get observed payload #if !SILVERLIGHT var observed = TestWriterUtils.ReadToString(message); if (logger != null) logger.LogPayload(TestWriterUtils.BaseLineFixup(observed)); #endif // TODO: Handle SILVERLIGHT }
/// <summary> /// Constructor. /// </summary> /// <param name="messageWriter">The message writer to wrap.</param> /// <param name="testConfiguration">The test configuration to use.</param> /// <param name="messageStream">the stream of the message.</param> /// <param name="message">The message to write to.</param> /// <param name="assert">The assertion handler for the test.</param> public ODataMessageWriterTestWrapper(ODataMessageWriter messageWriter, WriterTestConfiguration testConfiguration, TestMessage message, AssertionHandler assert) { ExceptionUtilities.CheckArgumentNotNull(messageWriter, "messageWriter"); ExceptionUtilities.CheckArgumentNotNull(testConfiguration, "testConfiguration"); this.messageWriter = messageWriter; this.testConfiguration = testConfiguration; this.message = message; this.assert = assert; if (message != null && message.TestStream != null && assert != null) { this.assert.AreEqual(0, message.TestStream.DisposeCount, "If the underlying message stream is a TestStream, its dispose count must be 0."); this.assert.AreEqual(false, message.StreamRetrieved, "GetMessage and GetMessageAsync must not be called privously on the given message."); } }
/// <summary> /// Verifies the result of the write-read. /// </summary> /// <param name="message">The test message is not used but is required to keep the method signature the same.</param> /// <param name="payloadKind">The payload kind is not used but is required to keep the method signature the same.</param> /// <param name="testConfiguration">The test configuration is used for some fixups.</param> public override void VerifyResult(TestMessage message, ODataPayloadKind payloadKind, WriterTestConfiguration testConfiguration, BaselineLogger logger=null) { //TODO: Use Logger to verify result, right now this change is only to unblock writer testcase checkin Debug.Assert(ObservedElement != null, "ObservedElement not provided"); // Fixup the expected and get the content type ODataPayloadElement expected = this.ExpectedPayload.DeepCopy(); ODataPayloadElement observed = this.ObservedElement.DeepCopy(); observed.Accept(new RemoveTypeNameAnnotationFromComplexInCollection()); expected.Accept(new ReorderProperties()); expected.Accept(new RemoveComplexWithNoProperties()); // Compare this.settings.PayloadElementComparer.Compare(expected, observed); }
/// <summary> /// Constructor. /// </summary> /// <param name="messageWriter">The message writer to wrap.</param> /// <param name="testConfiguration">The test configuration to use.</param> /// <param name="messageStream">the stream of the message.</param> /// <param name="message">The message to write to.</param> /// <param name="assert">The assertion handler for the test.</param> public ODataMessageWriterTestWrapper(ODataMessageWriter messageWriter, WriterTestConfiguration testConfiguration, TestMessage message, AssertionHandler assert) { ExceptionUtilities.CheckArgumentNotNull(messageWriter, "messageWriter"); ExceptionUtilities.CheckArgumentNotNull(testConfiguration, "testConfiguration"); this.messageWriter = messageWriter; this.testConfiguration = testConfiguration; this.message = message; this.assert = assert; if (message != null && message.TestStream != null && assert != null) { this.assert.AreEqual(0, message.TestStream.DisposeCount, "If the underlying message stream is a TestStream, its dispose count must be 0."); this.assert.AreEqual(false, message.StreamRetrieved, "GetMessage and GetMessageAsync must not be called privously on the given message."); } }
/// <summary> /// Called to create the output message for the writer test. /// </summary> /// <param name="innerStream">The <see cref="Stream"/> instance to be used as inner stream of the <see cref="TestStream"/>.</param> /// <param name="testConfiguration">The test configuration.</param> /// <returns>The newly created test message to use.</returns> protected virtual TestMessage CreateOutputMessage(Stream innerStream, WriterTestConfiguration testConfiguration) { TestStream messageStream = new TestStream(innerStream); if (testConfiguration.Synchronous) { messageStream.FailAsynchronousCalls = true; } else { messageStream.FailSynchronousCalls = true; } TestMessage testMessage = TestWriterUtils.CreateOutputMessageFromStream(messageStream, testConfiguration, this.PayloadKind, this.ContentType, this.UrlResolver); return(testMessage); }
/// <summary> /// Verifies that the result of the test is what the test expected. /// </summary> /// <param name="stream">The stream after writing the message content. This method should use it /// to read the message content and verify it.</param> /// <param name="payloadKind">The payload kind specified in the test descriptor.</param> /// <param name="testConfiguration">The test configuration to use.</param> public override void VerifyResult( TestMessage message, ODataPayloadKind payloadKind, WriterTestConfiguration testConfiguration, BaselineLogger logger) { this.settings.Assert.IsTrue(payloadKind == ODataPayloadKind.MetadataDocument, "Only metadata payload kind is supported."); // read the message content using the Taupo infrastructure ExceptionUtilities.CheckArgumentNotNull(message.TestStream, "stream != null"); #if !SILVERLIGHT var observed = TestWriterUtils.ReadToString(message); if (logger != null) logger.LogPayload(TestWriterUtils.BaseLineFixup(observed)); #endif // TODO: Handle SILVERLIGHT }
/// <summary> /// Applies the specified behavior with default settings. /// For detailed settings the caller should use Clone and direct application of behavior to the settings. /// </summary> /// <param name="behaviorKind">The behavior kind to apply.</param> /// <returns>A copy of this configuration with the new behavior applied.</returns> public WriterTestConfiguration CloneAndApplyBehavior(TestODataBehaviorKind behaviorKind) { WriterTestConfiguration testConfiguration = this.Clone(); switch (behaviorKind) { case TestODataBehaviorKind.Default: break; case TestODataBehaviorKind.WcfDataServicesClient: break; case TestODataBehaviorKind.WcfDataServicesServer: testConfiguration.MessageWriterSettings.Validations &= ~ValidationKinds.ThrowOnDuplicatePropertyNames; break; } return(testConfiguration); }
/// <summary> /// Applies the specified behavior with default settings. /// For detailed settings the caller should use Clone and direct application of behavior to the settings. /// </summary> /// <param name="behaviorKind">The behavior kind to apply.</param> /// <returns>A copy of this configuration with the new behavior applied.</returns> public WriterTestConfiguration CloneAndApplyBehavior(TestODataBehaviorKind behaviorKind) { WriterTestConfiguration testConfiguration = this.Clone(); switch (behaviorKind) { case TestODataBehaviorKind.Default: break; case TestODataBehaviorKind.WcfDataServicesClient: testConfiguration.MessageWriterSettings.EnableWcfDataServicesClientBehavior(); break; case TestODataBehaviorKind.WcfDataServicesServer: testConfiguration.MessageWriterSettings.EnableODataServerBehavior(false); break; } return(testConfiguration); }
public void RawPrimitiveValueTests() { var testCases = new PayloadWriterTestDescriptor<object> [] { new PayloadWriterTestDescriptor<object>(this.Settings, (object)(double)1, "1", null, TextPlainContentType), // double new PayloadWriterTestDescriptor<object>(this.Settings, (object)new byte[] { 0, 1, 0, 1}, (string)null, new byte[] { 0, 1, 0, 1}, ApplicationOctetStreamContentType), // binary new PayloadWriterTestDescriptor<object>(this.Settings, (object)(Single)1, "1", (byte[])null, TextPlainContentType), // single new PayloadWriterTestDescriptor<object>(this.Settings, (object)true, "true", (byte[])null, TextPlainContentType), // boolean new PayloadWriterTestDescriptor<object>(this.Settings, (object)(byte)1, "1", (byte[])null, TextPlainContentType), // byte new PayloadWriterTestDescriptor<object>(this.Settings, (object)DateTimeOffset.Parse("2010-10-10T10:10:10Z"), "2010-10-10T10:10:10Z", (byte[])null, TextPlainContentType), // DateTimeOffset new PayloadWriterTestDescriptor<object>(this.Settings, (object)DateTimeOffset.Parse("2010-10-10T10:10:10+01:00"), "2010-10-10T10:10:10+01:00", (byte[])null, TextPlainContentType), // DateTimeOffset (2) new PayloadWriterTestDescriptor<object>(this.Settings, (object)DateTimeOffset.Parse("2010-10-10T10:10:10-08:00"), "2010-10-10T10:10:10-08:00", (byte[])null, TextPlainContentType), // DateTimeOffset (3) new PayloadWriterTestDescriptor<object>(this.Settings, (object)(decimal)1, "1", (byte[])null, TextPlainContentType), // Decimal new PayloadWriterTestDescriptor<object>(this.Settings, (object)new Guid("11111111-2222-3333-4444-555555555555"), "11111111-2222-3333-4444-555555555555", (byte[])null, TextPlainContentType), // Guid new PayloadWriterTestDescriptor<object>(this.Settings, (object)(sbyte)1, "1", (byte[])null, TextPlainContentType), // SByte new PayloadWriterTestDescriptor<object>(this.Settings, (object)(Int16)1, "1", (byte[])null, TextPlainContentType), // Int16 new PayloadWriterTestDescriptor<object>(this.Settings, (object)(Int32)1, "1", (byte[])null, TextPlainContentType), // Int32 new PayloadWriterTestDescriptor<object>(this.Settings, (object)(Int64)1, "1", (byte[])null, TextPlainContentType), // Int64 new PayloadWriterTestDescriptor<object>(this.Settings, (object)"1", "1", (byte[])null, TextPlainContentType), // string new PayloadWriterTestDescriptor<object>(this.Settings, (object)TimeSpan.FromMinutes(12.34), "PT12M20.4S", (byte[])null, TextPlainContentType), // Duration new PayloadWriterTestDescriptor<object>(this.Settings, (object)string.Empty, string.Empty, (byte[])null, TextPlainContentType), // empty }; this.CombinatorialEngineProvider.RunCombinations( testCases, this.WriterTestConfigurationProvider.DefaultFormatConfigurationsWithIndent, (testCase, testConfiguration) => { // fix up the accept header for binary content bool binaryPayload = testCase.PayloadItems.Single() is byte[]; if (binaryPayload) { ODataMessageWriterSettings settings = testConfiguration.MessageWriterSettings.Clone(); settings.SetContentType("application/octet-stream", null); testConfiguration = new WriterTestConfiguration(testConfiguration.Format, settings, testConfiguration.IsRequest, testConfiguration.Synchronous); } TestWriterUtils.WriteAndVerifyRawContent(testCase, testConfiguration, this.Assert, this.Logger); }); }
public void StreamMessage(ODataMessageReaderTestWrapper reader, ODataMessageWriterTestWrapper writer, ODataPayloadKind payloadKind, WriterTestConfiguration config) { ExceptionUtilities.CheckArgumentNotNull(reader, "reader is required"); ExceptionUtilities.CheckArgumentNotNull(writer, "writer is required"); ExceptionUtilities.CheckArgumentNotNull(payloadKind, "payloadKind is required"); ExceptionUtilities.CheckArgumentNotNull(config, "config is required"); this.testConfiguration = config; switch(payloadKind) { case ODataPayloadKind.Entry: this.StartRead(reader.CreateODataEntryReader(), writer.CreateODataEntryWriter()); break; case ODataPayloadKind.Feed: this.StartRead(reader.CreateODataFeedReader(), writer.CreateODataFeedWriter()); break; default: throw new NotSupportedException("ObjectModelReadWriteStreamer currently supports only feed and entry"); }; }
/// <summary> /// Runs the test specified by this test descriptor. /// </summary> /// <param name="testConfiguration">The test configuration to use for running the test.</param> public virtual void RunTest(WriterTestConfiguration testConfiguration, BaselineLogger logger) { if (this.ShouldSkipForTestConfiguration(testConfiguration)) { return; } // Wrap the memory stream in a non-disposing stream so we can dump the message content // even in the case of a failure where the message stream normally would get disposed. logger.LogConfiguration(testConfiguration); logger.LogModelPresence(this.Model); this.messageStream = new NonDisposingStream(new MemoryStream()); TestMessage message = this.CreateOutputMessage(this.messageStream, testConfiguration); IEdmModel model = this.GetMetadataProvider(); WriterTestExpectedResults expectedResult = this.GetExpectedResult(testConfiguration); ExceptionUtilities.Assert(expectedResult != null, "The expected result could not be determined for the test. Did you specify it?"); Exception exception = TestExceptionUtils.RunCatching(() => { using (ODataMessageWriterTestWrapper messageWriterWrapper = TestWriterUtils.CreateMessageWriter(message, model, testConfiguration, this.settings.Assert)) { this.WritePayload(messageWriterWrapper, testConfiguration); expectedResult.VerifyResult(message, this.PayloadKind, testConfiguration, logger); } }); try { expectedResult.VerifyException(exception); } catch (Exception failureException) { this.TraceFailureInformation(message, this.messageStream, testConfiguration); throw failureException; } }
/// <summary> /// Constructor. /// </summary> /// <param name="messageWriter">The message writer to wrap.</param> /// <param name="testConfiguration">The test configuration to use.</param> public ODataMessageWriterTestWrapper(ODataMessageWriter messageWriter, WriterTestConfiguration testConfiguration) : this(messageWriter, testConfiguration, null, null) { }
/// <summary> /// Constructor. /// </summary> /// <param name="messageWriter">The message writer to wrap.</param> /// <param name="testConfiguration">The test configuration to use.</param> public ODataMessageWriterTestWrapper(ODataMessageWriter messageWriter, WriterTestConfiguration testConfiguration) : this(messageWriter, testConfiguration, null, null) { }
/// <summary> /// If overridden dumps additional description of the test descriptor for the specified testConfiguration. /// This is used only for debugging purposes. /// </summary> /// <param name="testConfiguration">The test configuration to use.</param> /// <returns>String description of the test.</returns> protected virtual string DumpAdditionalTestDescriptions(WriterTestConfiguration testConfiguration) { return(string.Empty); }
/// <summary> /// Called to write the payload to the specified <paramref name="messageWriter"/>. /// </summary> /// <param name="messageWriter">The <see cref="ODataMessageWriterTestWrapper"/> to use for writing the payload.</param> /// <param name="testConfiguration">The test configuration to generate the payload for.</param> protected override void WritePayload(ODataMessageWriterTestWrapper messageWriter, WriterTestConfiguration testConfiguration) { ODataPayloadElement payload = this.PayloadElement.DeepCopy(); if (testConfiguration.Format == ODataFormat.Json) { payload.Accept(new ODataPayloadJsonNormalizer()); //Fixup added as odatalib requires ids on feeds even though it can't be represented in json payload.Accept(new AddFeedIDFixup()); } else if (testConfiguration.Format == ODataFormat.Atom) { // TODO: Remove visitor payload.Accept(new ODataPayloadElementNullIDVisitor()); } ODataPayloadElementToObjectModelConverter converter = new ODataPayloadElementToObjectModelConverter(!testConfiguration.IsRequest); if (this.PayloadKind != ODataPayloadKind.Batch) { this.settings.ObjectModelToMessageWriter.WriteMessage(messageWriter, this.PayloadKind, converter.Convert(payload)); } else { TestWriterUtils.WriteBatchPayload(messageWriter, payload, converter, this.settings.ObjectModelToMessageWriter, this.Model, this.settings.Assert, testConfiguration, true); } }
/// <summary> /// Called to create the input message for the reader test. /// </summary> /// <param name="innerStream">The <see cref="Stream"/> instance to be used as inner stream of the <see cref="TestStream"/>.</param> /// <param name="testConfiguration">The test configuration.</param> /// <returns>The newly created test message to use.</returns> protected override TestMessage CreateOutputMessage(Stream innerStream, WriterTestConfiguration testConfiguration) { TestStream messageStream = new TestStream(innerStream); if (testConfiguration.Synchronous) { messageStream.FailAsynchronousCalls = true; } else { messageStream.FailSynchronousCalls = true; } TestMessage testMessage = TestWriterUtils.CreateOutputMessageFromStream( messageStream, testConfiguration, this.PayloadKind, this.PayloadElement.GetCustomContentTypeHeader(), this.UrlResolver); return testMessage; }
public void LogConfiguration(WriterTestConfiguration config) { this.config = config; }
/// <summary> /// Creates an <see cref="ODataCollectionWriter"/> for the specified format and the specified version and /// invokes the specified methods on it. It then parses /// the written Xml/JSON and compares it to the expected result as specified in the descriptor. /// </summary> /// <param name="descriptor">The test descriptor to process.</param> /// <param name="testConfiguration">The configuration of the test.</param> /// <param name="assert">The assertion handler to report errors to.</param> /// <param name="baselineLogger">Logger to log baseline.</param> internal static void WriteAndVerifyCollectionPayload(CollectionWriterTestDescriptor descriptor, WriterTestConfiguration testConfiguration, AssertionHandler assert, BaselineLogger baselineLogger) { baselineLogger.LogConfiguration(testConfiguration); baselineLogger.LogModelPresence(descriptor.Model); // serialize to a memory stream using (var memoryStream = new MemoryStream()) using (var testMemoryStream = new TestStream(memoryStream, ignoreDispose: true)) { TestMessage testMessage = null; Exception exception = TestExceptionUtils.RunCatching(() => { using (var messageWriter = TestWriterUtils.CreateMessageWriter(testMemoryStream, testConfiguration, assert, out testMessage, null, descriptor.Model)) { IEdmTypeReference itemTypeReference = descriptor.ItemTypeParameter; ODataCollectionWriter writer = itemTypeReference == null ? messageWriter.CreateODataCollectionWriter() : messageWriter.CreateODataCollectionWriter(itemTypeReference); WriteCollectionPayload(messageWriter, writer, true, descriptor); } }); exception = TestExceptionUtils.UnwrapAggregateException(exception, assert); WriterTestExpectedResults expectedResults = descriptor.ExpectedResultCallback(testConfiguration); TestWriterUtils.ValidateExceptionOrLogResult(testMessage, testConfiguration, expectedResults, exception, assert, descriptor.TestDescriptorSettings.ExpectedResultSettings.ExceptionVerifier, baselineLogger); TestWriterUtils.ValidateContentType(testMessage, expectedResults, true, assert); } }
/// <summary> /// Creates an ODataWriter for the specified format and the specified version and /// writes the property in the descriptor to an in-memory stream. It then parses /// the written Xml and compares it to the expected result as specified in the descriptor. /// </summary> /// <param name="originalPayload">The payload to first clone and then write.</param> /// <param name="testConfiguration">Configuration for the test</param> /// <param name="model">The model to use.</param> protected void WriteAndVerifyODataProperty(ODataPayloadElement originalPayload, WriterTestConfiguration testConfiguration, IEdmModel model) { this.Logger.LogConfiguration(testConfiguration); this.Logger.LogModelPresence(model); using (var memoryStream = new TestStream()) { TestMessage testMessage; using (ODataMessageWriterTestWrapper writer = TestWriterUtils.CreateMessageWriter(memoryStream, testConfiguration, this.Assert, out testMessage, null, model)) { Action<ODataPayloadElement> writeElementToStream = payload => this.PropertyPayloadElementWriter.WriteProperty(writer.MessageWriter, payload); #if !SILVERLIGHT this.WriteAndLogODataPayload(originalPayload, writer.Message, testConfiguration.Version, testConfiguration.Format, writeElementToStream); #else //TODO: Add roundtrip for silverlight #endif } } }
/// <summary> /// Creates an ODataWriter for the specified format and the specified version and /// writes the payload in the descriptor to an in-memory stream. It then parses /// the written Xml and compares it to the expected result as specified in the descriptor. /// </summary> /// <param name="originalPayload">expectedPayload to write and</param> /// <param name="testConfiguration">Configuration for the test</param> protected void WriteAndVerifyODataPayloadElement(ODataPayloadElement originalPayload, WriterTestConfiguration testConfiguration) { this.Logger.LogConfiguration(testConfiguration); bool feedWriter = originalPayload.ElementType == ODataPayloadElementType.EntitySetInstance; using (var memoryStream = new TestStream()) { using (var messageWriter = TestWriterUtils.CreateMessageWriter(memoryStream, testConfiguration, this.Assert)) { ODataWriter writer = messageWriter.CreateODataWriter(feedWriter); Action<ODataPayloadElement> writeToStream = payload => this.PayloadElementWriter.WritePayload(writer, payload); #if !SILVERLIGHT this.WriteAndLogODataPayload(originalPayload, messageWriter.Message, testConfiguration.Version, testConfiguration.Format, writeToStream); #else //TODO: Add roundtrip for silverlight #endif } } }
/// <summary> /// Called to get the expected result of the test. /// </summary> /// <param name="testConfiguration">The test configuration to use.</param> /// <returns>The expected result.</returns> protected override WriterTestExpectedResults GetExpectedResult(WriterTestConfiguration testConfiguration) { WriterTestExpectedResults expectedResult = base.GetExpectedResult(testConfiguration); if (expectedResult == null) { throw new NotImplementedException(); } else { return expectedResult; } }
/// <summary> /// Called to write the payload to the specified <paramref name="messageWriter"/>. /// </summary> /// <param name="messageWriter">The <see cref="ODataMessageWriterTestWrapper"/> to use for writing the payload.</param> protected abstract void WritePayload(ODataMessageWriterTestWrapper messageWriter, WriterTestConfiguration config);
/// <summary> /// Called before the test is actually executed for the specified test configuration to determine if the test should be skipped. /// </summary> /// <param name="testConfiguration">The test configuration to use.</param> /// <returns>true if the test should be skipped for the <paramref name="testConfiguration"/> or false to run the test.</returns> /// <remarks>Derived classes should always call the base class and return true if the base class returned true.</remarks> protected override bool ShouldSkipForTestConfiguration(WriterTestConfiguration testConfiguration) { if (this.PayloadDescriptor.SkipTestConfiguration != null && this.PayloadDescriptor.SkipTestConfiguration(testConfiguration)) { return true; } else if (this.SkipTestConfiguration != null) { return this.SkipTestConfiguration(testConfiguration); } else { return false; } }
/// <summary> /// Called to write the payload to the specified <paramref name="messageWriter"/>. /// </summary> /// <param name="messageWriter">The <see cref="ODataMessageWriterTestWrapper"/> to use for writing the payload.</param> /// <param name="testConfiguration">The test configuration to generate the payload for.</param> protected override void WritePayload(ODataMessageWriterTestWrapper messageWriter, WriterTestConfiguration testConfiguration) { ODataPayloadElement payload = this.PayloadElement.DeepCopy(); if (testConfiguration.Format == ODataFormat.Json) { payload.Accept(new ODataPayloadJsonNormalizer()); //Fixup added as odatalib requires ids on feeds even though it can't be represented in json payload.Accept(new AddFeedIDFixup()); } else if (testConfiguration.Format == ODataFormat.Atom) { // TODO: Remove visitor payload.Accept(new ODataPayloadElementNullIDVisitor()); } ODataPayloadElementToObjectModelConverter converter = new ODataPayloadElementToObjectModelConverter(!testConfiguration.IsRequest); if (this.PayloadKind != ODataPayloadKind.Batch) { this.settings.ObjectModelToMessageWriter.WriteMessage(messageWriter, this.PayloadKind, converter.Convert(payload)); } else { TestWriterUtils.WriteBatchPayload(messageWriter, payload, converter, this.settings.ObjectModelToMessageWriter, this.Model, this.settings.Assert, testConfiguration, true); } }
private static Stream GetMessageStream(ODataBatchOperationResponseMessage responseMessage, WriterTestConfiguration testConfiguration) { if (testConfiguration.Synchronous) { return responseMessage.GetStream(); } else { var t = responseMessage.GetStreamAsync(); t.Wait(); return t.Result; } }
private WriterTestExpectedResults CreateExpectedResults(WriterTestConfiguration testConfiguration, ProjectedPropertiesTestCase testCase, bool withModel) { if (testCase.ExpectedException != null) { ExpectedException expectedException = testCase.ExpectedException(withModel); if (expectedException != null) { return new WriterTestExpectedResults(this.Settings.ExpectedResultSettings) { ExpectedException2 = expectedException }; } } if (testConfiguration.Format == ODataFormat.Atom) { #region Atom expected result var atomExpectedResults = new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Xml = new XElement("properties", testCase.ExpectedProperties.OrderBy(p => p).Select(p => new XElement(p))).ToString(), FragmentExtractor = (result) => { // Navigation links IEnumerable<string> actualProperties; if (result == null) { actualProperties = new string[0]; } else { actualProperties = result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName) .Where(link => link.Attribute(TestAtomConstants.AtomLinkRelationAttributeName).Value.StartsWith(TestAtomConstants.ODataNavigationPropertiesRelatedLinkRelationPrefix)) .Select(link => link.Attribute(TestAtomConstants.AtomLinkTitleAttributeName).Value); // Named stream links actualProperties = actualProperties.Concat(result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName) .Where(link => link.Attribute(TestAtomConstants.AtomLinkRelationAttributeName).Value.StartsWith(TestAtomConstants.ODataStreamPropertyEditMediaRelatedLinkRelationPrefix)) .Select(link => link.Attribute(TestAtomConstants.AtomLinkTitleAttributeName).Value)); // Association links actualProperties = actualProperties.Concat(result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName) .Where(link => link.Attribute(TestAtomConstants.AtomLinkRelationAttributeName).Value.StartsWith(TestAtomConstants.ODataNavigationPropertiesAssociationLinkRelationPrefix)) .Select(link => link.Attribute(TestAtomConstants.AtomLinkTitleAttributeName).Value)); // Properties actualProperties = actualProperties.Concat(result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomContentElementName) .Elements(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.AtomPropertiesElementName) .Elements().Where(e => e.Name.Namespace == TestAtomConstants.ODataXNamespace) .Select(pe => pe.Name.LocalName)); } return new XElement("properties", actualProperties.OrderBy(p => p).Select(p => new XElement(p))); } }; if (testCase.NestedPayload) { var originalFragmentExtractor = atomExpectedResults.FragmentExtractor; atomExpectedResults.FragmentExtractor = (result) => { // Verify that the Wrapping_ID property is not written this.Assert.IsNull(result .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomContentElementName) .Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.AtomPropertiesElementName), "There should be no other property but the nav link and thus no m:properties in the content."); XElement expandedNavLinkElement = result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName) .Where(link => link.Attribute(TestAtomConstants.AtomLinkRelationAttributeName).Value .StartsWith(TestAtomConstants.ODataNavigationPropertiesRelatedLinkRelationPrefix + "Wrapping_ExpandedEntry")) .SingleOrDefault(); return originalFragmentExtractor( expandedNavLinkElement == null ? null : expandedNavLinkElement .Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName) .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomEntryElementName)); }; } return atomExpectedResults; #endregion Atom expected result } else if (testConfiguration.Format == ODataFormat.Json) { #region JSON Light expected result JsonArray expectedJson = new JsonArray(); foreach (var p in testCase.ExpectedProperties.Distinct().OrderBy(p => p)) { expectedJson.Add(new JsonPrimitiveValue(p)); } var jsonExpectedResults = new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Json = expectedJson.ToText(/*writingJsonLight*/ true, testConfiguration.MessageWriterSettings.Indent), FragmentExtractor = (result) => { // Everything except association links IEnumerable<string> actualProperties; if (result == null) { actualProperties = new string[0]; } else { List<string> propertyNames = new List<string>(); foreach (JsonProperty jsonProperty in result.Object().Properties) { string propertyName = jsonProperty.Name; int atIndex = propertyName.IndexOf('@'); int dotIndex = propertyName.IndexOf('.'); if (dotIndex < 0) { propertyNames.Add(propertyName); } else if (atIndex >= 0) { propertyNames.Add(propertyName.Substring(0, atIndex)); } } actualProperties = propertyNames.Distinct(); } JsonArray r = new JsonArray(); foreach (var p in actualProperties.OrderBy(p => p)) { r.Add(new JsonPrimitiveValue(p)); } return r; } }; if (testCase.NestedPayload) { var originalFragmentExtractor = jsonExpectedResults.FragmentExtractor; jsonExpectedResults.FragmentExtractor = (result) => { // Verify that the Wrapping_ID property is not written JsonObject resultObject = result.Object(); this.Assert.IsNull(resultObject.Property("Wrapping_ID"), "No other property but the nav. link should be written."); return originalFragmentExtractor( resultObject.Property("Wrapping_ExpandedEntry") == null ? null : resultObject.PropertyObject("Wrapping_ExpandedEntry")); }; } return jsonExpectedResults; #endregion JSON Light expected result } else { throw new TaupoInvalidOperationException("The format " + testConfiguration.Format.GetType().FullName + " is not supported."); } }
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; }; }
/// <summary> /// Traces interesting information if on test failure. /// </summary> /// <param name="message">The message to dump the failure information for.</param> /// <param name="messageStream">The message stream to get the message content from.</param> /// <param name="testConfiguration">The test configuration to use.</param> protected void TraceFailureInformation(TestMessage message, Stream messageStream, WriterTestConfiguration testConfiguration) { try { Trace.WriteLine("----- HTTP Message start ------------------------------------------"); TestRequestMessage requestMessage = message as TestRequestMessage; if (requestMessage != null) { Trace.WriteLine(requestMessage.Method.ToString() + " " + requestMessage.Url + " HTTP/1.1"); } TestResponseMessage responseMessage = message as TestResponseMessage; if (responseMessage != null) { Trace.WriteLine(responseMessage.StatusCode.ToString()); } foreach (var header in message.Headers) { Trace.WriteLine(header.Key + ": " + header.Value); } Trace.WriteLine(""); Trace.WriteLine(this.DumpOutputMessageContent(messageStream, testConfiguration)); Trace.WriteLine("----- HTTP Message end --------------------------------------------"); string additionalDescription = this.DumpAdditionalTestDescriptions(testConfiguration); if (!string.IsNullOrEmpty(additionalDescription)) { Trace.WriteLine(""); Trace.WriteLine("----- Additional test description ---------------------------------"); Trace.WriteLine(additionalDescription); } } catch (Exception innerException) { // Ignore all exceptions here since we want to fail with the original test exception. Trace.WriteLine("Failed to dump the test message."); Trace.WriteLine(innerException); } }
public override void RunTest(ReaderTestConfiguration testConfiguration) { //TODO: Use Logger to verify result, right now this change is only to unblock writer testcase checkin BaselineLogger logger = null; if (this.ShouldSkipForTestConfiguration(testConfiguration)) { return; } var originalPayload = this.PayloadElement; this.PayloadElement = this.PayloadElement.DeepCopy(); if (testConfiguration.Format == ODataFormat.Atom) { this.PayloadElement.Accept(new AddFeedIDFixup()); this.PayloadElement.Accept(new WriteFeedIDFirstFixup()); } // Create messages (payload gets serialized in createInputMessage) TestMessage readerMessage = this.CreateInputMessage(testConfiguration); var settings = new ODataMessageWriterSettings() { Version = testConfiguration.Version, PayloadBaseUri = testConfiguration.MessageReaderSettings.BaseUri, DisableMessageStreamDisposal = testConfiguration.MessageReaderSettings.DisableMessageStreamDisposal, }; settings.SetContentType(testConfiguration.Format); WriterTestConfiguration writerConfig = new WriterTestConfiguration(testConfiguration.Format, settings, testConfiguration.IsRequest, testConfiguration.Synchronous); TestMessage writerMessage = TestWriterUtils.CreateOutputMessageFromStream(new TestStream(new MemoryStream()), writerConfig, this.PayloadKind, String.Empty, this.UrlResolver); IEdmModel model = this.GetMetadataProvider(testConfiguration); WriterTestExpectedResults expectedResult = this.GetExpectedResult(writerConfig); ExceptionUtilities.Assert(expectedResult != null, "The expected result could not be determined for the test. Did you specify it?"); Exception exception = TestExceptionUtils.RunCatching(() => { using (ODataMessageReaderTestWrapper messageReaderWrapper = TestReaderUtils.CreateMessageReader(readerMessage, model, testConfiguration)) using (ODataMessageWriterTestWrapper messageWriterWrapper = TestWriterUtils.CreateMessageWriter(writerMessage, model, writerConfig, this.settings.Assert)) { var streamer = new ObjectModelReadWriteStreamer(); streamer.StreamMessage(messageReaderWrapper, messageWriterWrapper, this.PayloadKind, writerConfig); expectedResult.VerifyResult(writerMessage, this.PayloadKind, writerConfig, logger); } }); this.PayloadElement = originalPayload; try { expectedResult.VerifyException(exception); } catch (Exception) { this.TraceFailureInformation(testConfiguration); throw; } }
/// <summary> /// Verifies that the result of the test (the message reader) is what the test expected. /// </summary> /// <param name="stream">Stream which contains the results of the write.</param> /// <param name="payloadKind">The payload kind specified in the test descriptor.</param> /// <param name="testConfiguration">The test configuration to use.</param> public virtual void VerifyResult( TestMessage message, ODataPayloadKind payloadKind, WriterTestConfiguration testConfiguration, BaselineLogger logger) { // throw if not implemented; eventually we can make this method abstract when the WriterTestExpectedResults // are not used directly anymore throw new NotImplementedException("Subclasses must implement their own validation logic."); }
protected WriterTestExpectedResults GetExpectedResult(WriterTestConfiguration testConfiguration) { if (this.ExpectedResultCallback != null) { return this.ExpectedResultCallback(testConfiguration); } else { return null; } }
public void WriterStreamPropertiesTests() { Uri baseUri = new Uri("http://www.odata.org/", UriKind.Absolute); Uri relativeReadLinkUri = new Uri("readlink", UriKind.RelativeOrAbsolute); Uri relativeEditLinkUri = new Uri("editlink", UriKind.RelativeOrAbsolute); Uri absoluteReadLinkUri = new Uri(baseUri, relativeReadLinkUri.OriginalString); Uri absoluteEditLinkUri = new Uri(baseUri, relativeEditLinkUri.OriginalString); string contentType = "application/binary"; string etag = "\"myetagvalue\""; string streamPropertyName = "stream1"; var namedStreamProperties = new[] { // with only read link new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { ReadLink = relativeReadLinkUri }}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { ReadLink = relativeReadLinkUri, ContentType = contentType}}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { ReadLink = absoluteReadLinkUri }}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { ReadLink = absoluteReadLinkUri, ContentType = contentType}}, // with only edit link new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { EditLink = relativeEditLinkUri }}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { EditLink = relativeEditLinkUri, ContentType = contentType }}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { EditLink = relativeEditLinkUri, ContentType = contentType, ETag = etag }}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { EditLink = absoluteEditLinkUri }}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { EditLink = absoluteEditLinkUri, ContentType = contentType }}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { EditLink = absoluteEditLinkUri, ContentType = contentType, ETag = etag }}, // with both edit and read link new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { ReadLink = relativeReadLinkUri, EditLink = relativeEditLinkUri }}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { ReadLink = relativeReadLinkUri, EditLink = relativeEditLinkUri, ContentType = contentType}}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { ReadLink = relativeReadLinkUri, EditLink = relativeEditLinkUri, ContentType = contentType, ETag = etag }}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { ReadLink = absoluteReadLinkUri, EditLink = relativeEditLinkUri }}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { ReadLink = absoluteReadLinkUri, EditLink = relativeEditLinkUri, ContentType = contentType}}, new ODataProperty { Name = streamPropertyName, Value = new ODataStreamReferenceValue { ReadLink = absoluteReadLinkUri, EditLink = relativeEditLinkUri, ContentType = contentType, ETag = etag }}, }; var testCases = namedStreamProperties.Select(property => { var propertyName = property.Name; var streamReferenceValue = (ODataStreamReferenceValue)property.Value; return new StreamPropertyTestCase { NamedStreamProperty = property, GetExpectedAtomPayload = (testConfiguration) => { return (streamReferenceValue.ReadLink == null ? string.Empty : ( "<link rel=\"http://docs.oasis-open.org/odata/ns/mediaresource/" + property.Name + "\" " + (streamReferenceValue.ContentType == null ? string.Empty : "type=\"" + streamReferenceValue.ContentType + "\" ") + "title=\"" + property.Name + "\" " + "href=\"" + (((ODataStreamReferenceValue)property.Value).ReadLink.IsAbsoluteUri ? absoluteReadLinkUri.OriginalString : relativeReadLinkUri.OriginalString) + "\" " + "xmlns=\"" + TestAtomConstants.AtomNamespace + "\" />")) + (streamReferenceValue.EditLink == null ? string.Empty : ( "<link rel=\"http://docs.oasis-open.org/odata/ns/edit-media/" + property.Name + "\" " + (streamReferenceValue.ContentType == null ? string.Empty : "type=\"" + streamReferenceValue.ContentType + "\" ") + "title=\"" + property.Name + "\" " + "href=\"" + (((ODataStreamReferenceValue)property.Value).EditLink.IsAbsoluteUri ? absoluteEditLinkUri.OriginalString : relativeEditLinkUri.OriginalString) + "\" " + (streamReferenceValue.ETag == null ? string.Empty : "m:etag=\"" + streamReferenceValue.ETag.Replace("\"", """) + "\" xmlns:m=\"" + TestAtomConstants.ODataMetadataNamespace + "\" ") + "xmlns=\"" + TestAtomConstants.AtomNamespace + "\" />")); }, GetExpectedJsonLightPayload = (testConfiguration) => { return JsonLightWriterUtils.CombineProperties( (streamReferenceValue.EditLink == null ? string.Empty : ("\"" + JsonLightUtils.GetPropertyAnnotationName(propertyName, JsonLightConstants.ODataMediaEditLinkAnnotationName) + "\":\"" + absoluteEditLinkUri.OriginalString + "\"")), (streamReferenceValue.ReadLink == null ? string.Empty : ("\"" + JsonLightUtils.GetPropertyAnnotationName(propertyName, JsonLightConstants.ODataMediaReadLinkAnnotationName) + "\":\"" + absoluteReadLinkUri.OriginalString + "\"")), (streamReferenceValue.ContentType == null ? string.Empty : ("\"" + JsonLightUtils.GetPropertyAnnotationName(propertyName, JsonLightConstants.ODataMediaContentTypeAnnotationName) + "\":\"" + streamReferenceValue.ContentType + "\"")), (streamReferenceValue.ETag == null ? string.Empty : ("\"" + JsonLightUtils.GetPropertyAnnotationName(propertyName, JsonLightConstants.ODataMediaETagAnnotationName) + "\":\"" + streamReferenceValue.ETag.Replace("\"", "\\\"") + "\""))); }, }; }); var testDescriptors = testCases.SelectMany(testCase => { EdmModel model = new EdmModel(); EdmEntityType edmEntityType = new EdmEntityType("TestModel", "StreamPropertyEntityType"); EdmStructuralProperty edmStructuralProperty= edmEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, false); edmEntityType.AddKeys(new IEdmStructuralProperty[]{edmStructuralProperty}); model.AddElement(edmEntityType); EdmEntityContainer edmEntityContainer = new EdmEntityContainer("TestModel", "DefaultContainer"); model.AddElement(edmEntityContainer); EdmEntitySet edmEntitySet = new EdmEntitySet(edmEntityContainer, "StreamPropertyEntitySet", edmEntityType); edmEntityContainer.AddElement(edmEntitySet); ODataEntry entry = new ODataEntry() { Id = ObjectModelUtils.DefaultEntryId, ReadLink = ObjectModelUtils.DefaultEntryReadLink, TypeName = edmEntityType.FullName() }; var streamReference = (ODataStreamReferenceValue)testCase.NamedStreamProperty.Value; bool needBaseUri = (streamReference.ReadLink != null && !streamReference.ReadLink.IsAbsoluteUri) || (streamReference.EditLink != null && !streamReference.EditLink.IsAbsoluteUri); entry.Properties = new ODataProperty[] { testCase.NamedStreamProperty }; var resultDescriptor = new PayloadWriterTestDescriptor<ODataItem>( this.Settings, entry, (testConfiguration) => { if (testConfiguration.Format == ODataFormat.Atom) { return new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Xml = "<NamedStream>" + testCase.GetExpectedAtomPayload(testConfiguration) + "</NamedStream>", FragmentExtractor = result => result, }; } else if (testConfiguration.Format == ODataFormat.Json) { return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Json = string.Join( "$(NL)", "{", testCase.GetExpectedJsonLightPayload(testConfiguration), "}"), FragmentExtractor = result => result.RemoveAllAnnotations(true), }; } else { throw new NotSupportedException("Unsupported ODataFormat found: " + testConfiguration.Format.ToString()); } }) { Model = model, PayloadEdmElementContainer = edmEntityContainer, PayloadEdmElementType = edmEntityType, }; var resultTestCases = new List<StreamPropertyTestDescriptor>(); if (needBaseUri) { resultTestCases.Add(new StreamPropertyTestDescriptor { BaseUri = baseUri, TestDescriptor = resultDescriptor }); } else { resultTestCases.Add(new StreamPropertyTestDescriptor { BaseUri = null, TestDescriptor = resultDescriptor }); resultTestCases.Add(new StreamPropertyTestDescriptor { BaseUri = baseUri, TestDescriptor = resultDescriptor }); resultTestCases.Add(new StreamPropertyTestDescriptor { BaseUri = new Uri("http://mybaseuri/", UriKind.Absolute), TestDescriptor = resultDescriptor }); } return resultTestCases; }); var testDescriptorBaseUriPairSet = testDescriptors.SelectMany(descriptor => WriterPayloads.NamedStreamPayloads(descriptor.TestDescriptor).Select(namedStreamPayload => new Tuple<PayloadWriterTestDescriptor<ODataItem>, Uri>(namedStreamPayload, descriptor.BaseUri))); this.CombinatorialEngineProvider.RunCombinations( testDescriptorBaseUriPairSet, this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent, (testDescriptorBaseUriPair, testConfiguration) => { var testDescriptor = testDescriptorBaseUriPair.Item1; if (testDescriptor.IsGeneratedPayload && testConfiguration.Format == ODataFormat.Json) { return; } ODataMessageWriterSettings settings = testConfiguration.MessageWriterSettings.Clone(); settings.PayloadBaseUri = testDescriptorBaseUriPair.Item2; settings.SetServiceDocumentUri(ServiceDocumentUri); WriterTestConfiguration config = new WriterTestConfiguration(testConfiguration.Format, settings, testConfiguration.IsRequest, testConfiguration.Synchronous); if (testConfiguration.IsRequest) { ODataEntry payloadEntry = (ODataEntry)testDescriptor.PayloadItems[0]; ODataProperty firstStreamProperty = payloadEntry.Properties.Where(p => p.Value is ODataStreamReferenceValue).FirstOrDefault(); this.Assert.IsNotNull(firstStreamProperty, "firstStreamProperty != null"); testDescriptor = new PayloadWriterTestDescriptor<ODataItem>(testDescriptor) { ExpectedResultCallback = tc => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings) { ExpectedException2 = ODataExpectedExceptions.ODataException("WriterValidationUtils_StreamPropertyInRequest", firstStreamProperty.Name) } }; } TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, config, this.Assert, this.Logger); }); }
public void SetContentTypeInMessageHeaderTest() { IEdmModel model = Microsoft.Test.OData.Utils.Metadata.TestModels.BuildTestModel(); var testDescriptors = writerActionsForPayloadKinds.SelectMany( writerAction => CreateContentTypeHeaderTestCases(writerAction.PayloadKind).Select( testCase => new { WriterInvocation = writerAction, TestCase = testCase })); // ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight this.CombinatorialEngineProvider.RunCombinations( testDescriptors.Where(td => td.TestCase.ExpectedFormat == ODataFormat.Atom), this.WriterTestConfigurationProvider.AllFormatsConfigurations.Where(tc => tc.Format == ODataFormat.Atom), (testDescriptor, testConfiguration) => { ODataPayloadKind payloadKind = testDescriptor.WriterInvocation.PayloadKind; if (!payloadKind.IsSupported(testConfiguration)) { return; } // Clone the test configuration and make sure no content type is set on the message writer settings ODataMessageWriterSettings settings = testConfiguration.MessageWriterSettings; ODataMessageWriterSettings clonedSettings = new ODataMessageWriterSettings() { // NOTE intentionally not copying acceptable media types, acceptable char sets, format and useFormat PayloadBaseUri = settings.PayloadBaseUri, CheckCharacters = settings.CheckCharacters, DisableMessageStreamDisposal = settings.DisableMessageStreamDisposal, Indent = settings.Indent, MessageQuotas = new ODataMessageQuotas(settings.MessageQuotas), Version = settings.Version, EnableAtom = true }; clonedSettings.SetServiceDocumentUri(ServiceDocumentUri); WriterTestConfiguration clonedTestConfiguration = new WriterTestConfiguration( testConfiguration.Format, clonedSettings, testConfiguration.IsRequest, testConfiguration.Synchronous); using (var memoryStream = new TestStream()) { TestMessage testMessage; using (ODataMessageWriterTestWrapper messageWriter = TestWriterUtils.CreateMessageWriter(memoryStream, clonedTestConfiguration, this.Assert, out testMessage, null, model)) { // Set the content type header in the test message testMessage.SetHeader(ODataConstants.ContentTypeHeader, testDescriptor.TestCase.ContentTypeHeaderValue); Func<WriterTestConfiguration, ExpectedException> expectedExceptionFunc = testDescriptor.TestCase.ExpectedException; ExpectedException expectedException = expectedExceptionFunc == null ? null : expectedExceptionFunc(testConfiguration); TestExceptionUtils.ExpectedException( this.Assert, () => testDescriptor.WriterInvocation.WriterAction(messageWriter), expectedException, this.ExceptionVerifier); if (expectedException != null) { // nothing more to do if we expected an exception return; } // Check that the format and encoding was properly set ODataFormat actualFormat = messageWriter.PrivateFormat; Encoding actualEncoding = messageWriter.PrivateEncoding; string actualEncodingName = actualEncoding != null ? actualEncoding.WebName : null; string expectedEncodingName = testDescriptor.TestCase.ExpectedEncoding != null ? testDescriptor.TestCase.ExpectedEncoding.WebName : null; this.Assert.AreEqual(expectedEncodingName, actualEncodingName, "Encodings do not match!"); this.Assert.AreEqual(testDescriptor.TestCase.ExpectedFormat, actualFormat, "Formats do not match!"); // For batch payloads we need to validate the boundary string as well. if (payloadKind == ODataPayloadKind.Batch) { string batchBoundary = messageWriter.PrivateBatchBoundary; this.Assert.IsNotNull(batchBoundary, "Boundary string must not be null."); this.Assert.IsTrue(testDescriptor.TestCase.ContentTypeHeaderValue.Contains("boundary=" + batchBoundary), "Boundary strings don't match."); } } } }); }