Ejemplo n.º 1
0
        /// <summary>
        /// Returns all interesting payloads for a property.
        /// </summary>
        /// <param name="testDescriptor">Test descriptor which will end up writing a single entry with a single property.
        /// The entry is not going to be used, but the property from it will.</param>
        /// <returns>Enumeration of test descriptors which will include the original property in some interesting scenarios.</returns>
        public static IEnumerable <PayloadWriterTestDescriptor <ODataItem> > PropertyPayloads(PayloadWriterTestDescriptor <ODataItem> testDescriptor)
        {
            ODataResource tempEntry = testDescriptor.PayloadItems[0] as ODataResource;

            Debug.Assert(tempEntry != null, "A single entry payload is expected.");
            ODataProperty property = tempEntry.Properties.First();

            // Note - the property can be null - it is a valid test case !!!!

            var payloadCases = new WriterPayloadCase <ODataItem>[] {
                new WriterPayloadCase <ODataItem>()  // Single property on an entry
                {
                    GetPayloadItems = () => {
                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        entry.Properties = new ODataProperty[] { property };
                        return(new ODataItem[] { entry });
                    },
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(TestAtomUtils.ExtractPropertiesFromEntry(result).Element(TestAtomConstants.ODataXNamespace + property.Name));
                    },
                    //ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
                },

                // TODO: Add other interesting payloads for properties - more properties in an entry, inside a complex property, inside a collection of complex and so on
            };

            return(ApplyPayloadCases <ODataItem>(testDescriptor, payloadCases));
        }
Ejemplo n.º 2
0
        private void InvokeWriterAction(ODataMessageWriterTestWrapper messageWriter, ODataWriter writer, WriterAction writerAction)
        {
            switch (writerAction)
            {
            case WriterAction.StartResource:
                writer.WriteStart(ObjectModelUtils.CreateDefaultEntry());
                break;

            case WriterAction.StartFeed:
                writer.WriteStart(ObjectModelUtils.CreateDefaultFeed());
                break;

            case WriterAction.StartLink:
                writer.WriteStart(ObjectModelUtils.CreateDefaultCollectionLink());
                break;

            case WriterAction.End:
                writer.WriteEnd();
                break;

            case WriterAction.Error:
                messageWriter.WriteError(new ODataError(), false);
                break;
            }
        }
        public void EntryValidationTest()
        {
            var testCases = new[] {
                new { // type name must not be empty
                    InvalidateEntry   = new Action <ODataResource>(entry => entry.TypeName = string.Empty),
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_TypeNameMustNotBeEmpty")
                },
            };

            // Convert test cases to test descriptions
            var testDescriptors = testCases.Select(testCase =>
            {
                ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                testCase.InvalidateEntry(entry);
                return(new PayloadWriterTestDescriptor <ODataItem>(this.Settings, entry, testConfiguration =>
                                                                   new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                {
                    ExpectedException2 = testCase.ExpectedException
                }));
            });

            // TODO: Fix places where we've lost JsonVerbose coverage to add JsonLight
            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors.PayloadCases(WriterPayloads.EntryPayloads),
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurations.Where(tc => false),
                (testDescriptor, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger);
            });
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Returns all interesting payloads for a navigation link itself. That is the ODataNestedResourceInfo without any subsequent events.
        /// </summary>
        /// <param name="testDescriptor">Test descriptor which will end up writing a single navigation link.</param>
        /// <returns>Enumeration of test descriptors which will include the original navigation link in some interesting scenarios.</returns>
        public static IEnumerable <PayloadWriterTestDescriptor <ODataItem> > NavigationLinkOnlyPayloads(PayloadWriterTestDescriptor <ODataItem> testDescriptor)
        {
            ODataNestedResourceInfo navigationLink = testDescriptor.PayloadItems[0] as ODataNestedResourceInfo;

            Debug.Assert(navigationLink != null, "Navigation link payload expected.");
            Debug.Assert(navigationLink.IsCollection.HasValue, "ODataNestedResourceInfo.IsCollection required.");

            var payloadCases = new WriterPayloadCase <ODataItem>[] {
                new WriterPayloadCase <ODataItem>()  // Just the link as non-expanded
                {
                    GetPayloadItems = () => new ODataItem[] { navigationLink }
                },
                new WriterPayloadCase <ODataItem>()  // The link with expanded entry
                {
                    GetPayloadItems = () => {
                        if (navigationLink.IsCollection.Value)
                        {
                            return(new ODataItem[] { navigationLink, ObjectModelUtils.CreateDefaultFeed() });
                        }
                        else
                        {
                            return(new ODataItem[] { navigationLink, ObjectModelUtils.CreateDefaultEntry() });
                        }
                    }
                }
            };

            // Apply the cases here and then wrap the link in some entry/feed cases
            return(ApplyPayloadCases <ODataItem>(testDescriptor, payloadCases).PayloadCases(NavigationLinkPayloads));
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Returns all interesting payloads for a value.
        /// </summary>
        /// <param name="testDescriptor">Test descriptor which will end up writing a single entry with a single property.
        /// The entry is not going to be used, the property is not going to be used, but the property value from it will.</param>
        /// <returns>Enumeration of test descriptors which will include the original value in some interesting scenarios.</returns>
        public static IEnumerable <PayloadWriterTestDescriptor <ODataItem> > ValuePayloads(PayloadWriterTestDescriptor <ODataItem> testDescriptor)
        {
            ODataResource tempEntry = testDescriptor.PayloadItems[0] as ODataResource;

            Debug.Assert(tempEntry != null, "A single entry payload is expected.");
            ODataProperty property = tempEntry.Properties.First();

            Debug.Assert(property != null, "A single property is expected.");
            object propertyValue = property.Value;

            var payloadCases = new WriterPayloadCase <ODataItem>[] {
                new WriterPayloadCase <ODataItem>()  // Value of a property
                {
                    GetPayloadItems = () => {
                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        entry.Properties = new ODataProperty[] { new ODataProperty()
                                                                 {
                                                                     Name = "TestProperty", Value = propertyValue
                                                                 } };
                        return(new ODataItem[] { entry });
                    },
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(TestAtomUtils.ExtractPropertiesFromEntry(result).Element(TestAtomConstants.ODataXNamespace + property.Name));
                    },
                    //ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
                },
                new WriterPayloadCase <ODataItem>()  // Value as item in a collection
                {
                    ShouldSkip      = testConfiguration => propertyValue is ODataCollectionValue,
                    GetPayloadItems = () => {
                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        entry.Properties = new ODataProperty[] { new ODataProperty()
                                                                 {
                                                                     Name = "TestProperty", Value = new ODataCollectionValue()
                                                                     {
                                                                         Items = new object[] { propertyValue }
                                                                     }
                                                                 } };
                        return(new ODataItem[] { entry });
                    },
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(TestAtomUtils.ExtractPropertiesFromEntry(result).Element(TestAtomConstants.ODataXNamespace + property.Name));
                    },
                    //ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
                },

                // TODO: Add other interesting payloads for property values
            };

            // Combine with property payloads to get interesting places where the property itself is used.
            return(ApplyPayloadCases <ODataItem>(testDescriptor, payloadCases).PayloadCases(PropertyPayloads));
        }
Ejemplo n.º 6
0
        public void FatalExceptionTest()
        {
            ODataResource entry = ObjectModelUtils.CreateDefaultEntry();

            this.CombinatorialEngineProvider.RunCombinations(
                new ODataItem[] { entry },
                new bool[] { true, false }, // flush
                // TODO: also enable this test for the sync scenarios
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurations.Where(tc => !tc.Synchronous),
                (payload, flush, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                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);

                        // close the memory stream so that any attempt to flush will cause a fatal error
                        memoryStream.CloseInner();

                        // write the payload and call FlushAsync() to trigger a fatal exception
                        Exception ex = TestExceptionUtils.RunCatching(() => TestWriterUtils.WritePayload(messageWriter, writer, true, entry));
                        this.Assert.IsNotNull(ex, "Expected exception but none was thrown.");
                        NotSupportedException notSupported = null;
#if SILVERLIGHT || WINDOWS_PHONE
                        var baseEx = ex.GetBaseException();
                        this.Assert.IsNotNull(baseEx, "BaseException of exception:" + ex.ToString() + " should not be null");
                        notSupported = baseEx as NotSupportedException;
                        this.Assert.IsNotNull(notSupported, "Expected NotSupportedException but " + baseEx.GetType().FullName + " was reported.");
#else
                        notSupported = TestExceptionUtils.UnwrapAggregateException(ex, this.Assert) as NotSupportedException;
                        this.Assert.IsNotNull(notSupported, "Expected NotSupportedException but " + ex.ToString() + " was reported.");
#endif

                        this.Assert.AreEqual("Stream does not support writing.", notSupported.Message, "Did not find expected error message.");
                        this.Assert.IsTrue(inspector.IsInErrorState, "Writer is not in expected 'Error' state.");

                        if (flush)
                        {
                            // Flush should work in error state.
                            writer.Flush();
                        }

                        // in all cases we have to be able to dispose the writer without problems.
                    }
            });
        }
Ejemplo n.º 7
0
 private Action <WriterTestConfiguration> WriteEntry(Func <XElement, XElement> fragmentExtractor, Func <ODataVersion, string> expectedXml)
 {
     return((testConfiguration) => TestWriterUtils.WriteAndVerifyODataPayload(
                new PayloadWriterTestDescriptor <ODataItem>(
                    this.Settings,
                    ObjectModelUtils.CreateDefaultEntry(),
                    expectedXml(testConfiguration.Version),
                    null,
                    fragmentExtractor,
                    null,
                    /*disableXmlNamespaceNormalization*/ true),
                testConfiguration,
                this.Assert,
                this.Logger));
 }
        public void DefaultStreamValidationTest()
        {
            var testCases = new[] {
                new { // empty content type is invalid
                    InvalidateDefaultStream = new Action <ODataStreamReferenceValue>(mediaResource => mediaResource.ContentType = string.Empty),
                    ExpectedException       = ODataExpectedExceptions.ODataException("WriterValidationUtils_StreamReferenceValueEmptyContentType"),
                },
                new { // null read link and non-empty content type is invalid
                    InvalidateDefaultStream = new Action <ODataStreamReferenceValue>(mediaResource => { mediaResource.ReadLink = null; mediaResource.ContentType = "mime/type"; }),
                    ExpectedException       = ODataExpectedExceptions.ODataException("WriterValidationUtils_DefaultStreamWithContentTypeWithoutReadLink"),
                },
                new { // non-null read link and null content type is invalid
                    InvalidateDefaultStream = new Action <ODataStreamReferenceValue>(mediaResource => { mediaResource.ReadLink = new Uri("http://odata.org"); mediaResource.ContentType = null; }),
                    ExpectedException       = ODataExpectedExceptions.ODataException("WriterValidationUtils_DefaultStreamWithReadLinkWithoutContentType"),
                },
                new { // etag without an edit link is invalid
                    InvalidateDefaultStream = new Action <ODataStreamReferenceValue>(mediaResource => { mediaResource.ETag = "someetag"; mediaResource.EditLink = null; }),
                    ExpectedException       = ODataExpectedExceptions.ODataException("WriterValidationUtils_StreamReferenceValueMustHaveEditLinkToHaveETag"),
                },
            };

            var testDescriptors = testCases.Select(testCase =>
            {
                ODataStreamReferenceValue mediaResource = ObjectModelUtils.CreateDefaultStream();
                testCase.InvalidateDefaultStream(mediaResource);
                ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                entry.MediaResource = mediaResource;
                return(new PayloadWriterTestDescriptor <ODataItem>(
                           this.Settings,
                           entry,
                           testConfiguration => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                {
                    ExpectedException2 = testCase.ExpectedException
                }));
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors.PayloadCases(WriterPayloads.EntryPayloads),
                this.WriterTestConfigurationProvider.AtomFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger);
            });
        }
Ejemplo n.º 9
0
        public void WriteAfterExceptionTest()
        {
            // create a default entry and then set both read and edit links to null to provoke an exception during writing
            ODataResource faultyEntry = ObjectModelUtils.CreateDefaultEntry();

            this.Assert.IsNull(faultyEntry.EditLink, "entry.EditLink == null");

            ODataResource    defaultEntry = ObjectModelUtils.CreateDefaultEntry();
            ODataResourceSet defaultFeed  = ObjectModelUtils.CreateDefaultFeed();

            this.CombinatorialEngineProvider.RunCombinations(
                new ODataItem[] { faultyEntry },
                new ODataItem[] { defaultFeed, defaultEntry },
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurations,
                (faultyPayload, contentPayload, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                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);

                        // write the invalid entry and expect an exception
                        this.Assert.ExpectedException(
                            () => TestWriterUtils.WritePayload(messageWriter, writer, false, faultyEntry),
                            ODataExpectedExceptions.ODataException("WriterValidationUtils_EntriesMustHaveNonEmptyId"),
                            this.ExceptionVerifier);
                        this.Assert.IsTrue(inspector.IsInErrorState, "Writer is not in expected 'error' state.");

                        // now write some non-error content which is invalid to do
                        Exception ex = TestExceptionUtils.RunCatching(() => TestWriterUtils.WritePayload(messageWriter, writer, false, contentPayload));
                        ex           = TestExceptionUtils.UnwrapAggregateException(ex, this.Assert);
                        this.Assert.IsNotNull(ex, "Expected exception but none was thrown");
                        this.Assert.IsTrue(ex is ODataException, "Expected an ODataException instance but got a " + ex.GetType().FullName + ".");
                        this.Assert.IsTrue(ex.Message.Contains("Cannot transition from state 'Error' to state "), "Did not find expected start of error message.");
                        this.Assert.IsTrue(ex.Message.Contains("Nothing can be written once the writer entered the error state."), "Did not find expected end of error message in '" + ex.Message + "'.");
                        this.Assert.IsTrue(inspector.IsInErrorState, "Writer is not in expected 'error' state.");
                        writer.Flush();
                    }
            });
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Returns all interesting payloads for a navigation link.
        /// </summary>
        /// <param name="testDescriptor">Test descriptor which will end up writing a single navigation link.</param>
        /// <returns>Enumeration of test descriptors which will include the original navigation link in some interesting scenarios.</returns>
        public static IEnumerable <PayloadWriterTestDescriptor <ODataItem> > NavigationLinkPayloads(PayloadWriterTestDescriptor <ODataItem> testDescriptor)
        {
            ODataNestedResourceInfo navigationLink = testDescriptor.PayloadItems[0] as ODataNestedResourceInfo;

            Debug.Assert(navigationLink != null, "Link payload expected.");

            var payloadCases = new WriterPayloadCase <ODataItem>[] {
                new WriterPayloadCase <ODataItem>()  // Single link on top-level entry
                {
                    GetPayloadItems       = () => new ODataItem[] { ObjectModelUtils.CreateDefaultEntry() }.Concat(testDescriptor.PayloadItems),
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                               .Where(linkElement => linkElement.Attribute(TestAtomConstants.AtomLinkRelationAttributeName).Value.StartsWith(TestAtomConstants.ODataNavigationPropertiesRelatedLinkRelationPrefix))
                               .First());
                    },
                },

                // TODO: Add other interesting payloads for links - in expanded entry, in expanded feed
            };

            return(ApplyPayloadCases <ODataItem>(testDescriptor, payloadCases));
        }
        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.BaseUri is invalid; it must either be null or an absolute URI.";

            ODataResource 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.BaseUri = testDescriptor.BaseUri;

                WriterTestConfiguration config =
                    new WriterTestConfiguration(testConfiguration.Format, settings, testConfiguration.IsRequest, testConfiguration.Synchronous);

                TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor.TestDescriptor, config, this.Assert, this.Logger);
            });
        }
Ejemplo n.º 12
0
        public void WriteAfterDisposeTest()
        {
            this.CombinatorialEngineProvider.RunCombinations(
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurations,
                (testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                using (var stream = new TestStream())
                {
                    ODataWriter writer;
                    using (var messageWriter = TestWriterUtils.CreateMessageWriter(stream, testConfiguration, this.Assert))
                    {
                        writer = messageWriter.CreateODataWriter(isFeed: true);
                        // Message writer is disposed outside of this scope.
                    }

                    this.VerifyWriterAlreadyDisposed(() => writer.WriteStart(ObjectModelUtils.CreateDefaultFeed()));
                    this.VerifyWriterAlreadyDisposed(() => writer.WriteStart(ObjectModelUtils.CreateDefaultEntry()));
                    this.VerifyWriterAlreadyDisposed(() => writer.WriteStart(ObjectModelUtils.CreateDefaultCollectionLink()));
                }
            });
        }
        public void AssociationLinkOnNavigationLinkTest()
        {
            EdmModel model = new EdmModel();

            var container = new EdmEntityContainer("TestModel", "Default");

            model.AddElement(container);

            var edmEntityTypeOrderType = new EdmEntityType("TestModel", "OrderType");

            model.AddElement(edmEntityTypeOrderType);

            var edmEntityTypeCustomerType = new EdmEntityType("TestModel", "CustomerType");
            var edmNavigationPropertyAssociationLinkOne = edmEntityTypeCustomerType.AddUnidirectionalNavigation(
                new EdmNavigationPropertyInfo {
                Name = "NavProp1", Target = edmEntityTypeOrderType, TargetMultiplicity = EdmMultiplicity.One
            });
            var edmNavigationPropertyAssociationLinkTwo = edmEntityTypeCustomerType.AddUnidirectionalNavigation(
                new EdmNavigationPropertyInfo {
                Name = "NavProp2", Target = edmEntityTypeOrderType, TargetMultiplicity = EdmMultiplicity.Many
            });

            model.AddElement(edmEntityTypeCustomerType);

            var customerSet = container.AddEntitySet("Customers", edmEntityTypeCustomerType);
            var orderSet    = container.AddEntitySet("Orders", edmEntityTypeOrderType);

            customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkOne, orderSet);
            customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkTwo, orderSet);

            var testCases = new[]
            {
                // Both nav link URL and association link URL
                new {
                    NavigationLink = new ODataNestedResourceInfo()
                    {
                        Name = "NavProp1", IsCollection = false, Url = new Uri("http://odata.org/navlink"), AssociationLinkUrl = new Uri("http://odata.org/assoclink")
                    },
                    PropertyName = "NavProp1",
                    Atom         = BuildXmlNavigationLink("NavProp1", "application/atom+xml;type=entry", "http://odata.org/navlink"),
                    JsonLight    =
                        "\"" + JsonLightUtils.GetPropertyAnnotationName("NavProp1", JsonLightConstants.ODataNavigationLinkUrlAnnotationName) + "\":\"http://odata.org/navlink\"," +
                        "\"" + JsonLightUtils.GetPropertyAnnotationName("NavProp1", JsonLightConstants.ODataAssociationLinkUrlAnnotationName) + "\":\"http://odata.org/assoclink\""
                },
                // Just nav link URL
                new {
                    NavigationLink = new ODataNestedResourceInfo()
                    {
                        Name = "NavProp1", IsCollection = false, Url = new Uri("http://odata.org/navlink"), AssociationLinkUrl = null
                    },
                    PropertyName = "NavProp1",
                    Atom         = BuildXmlNavigationLink("NavProp1", "application/atom+xml;type=entry", "http://odata.org/navlink"),
                    JsonLight    = "\"" + JsonLightUtils.GetPropertyAnnotationName("NavProp1", JsonLightConstants.ODataNavigationLinkUrlAnnotationName) + "\":\"http://odata.org/navlink\""
                },
                // Just association link URL
                new {
                    NavigationLink = new ODataNestedResourceInfo()
                    {
                        Name = "NavProp1", IsCollection = false, Url = null, AssociationLinkUrl = new Uri("http://odata.org/assoclink")
                    },
                    PropertyName = "NavProp1",
                    Atom         = (string)null,
                    JsonLight    = "\"" + JsonLightUtils.GetPropertyAnnotationName("NavProp1", JsonLightConstants.ODataAssociationLinkUrlAnnotationName) + "\":\"http://odata.org/assoclink\""
                },
                // Navigation link with both URLs null
                new {
                    NavigationLink = new ODataNestedResourceInfo()
                    {
                        Name = "NavProp1", IsCollection = false, Url = null, AssociationLinkUrl = null
                    },
                    PropertyName = "NavProp1",
                    Atom         = (string)null,
                    JsonLight    = string.Empty
                }
            };

            IEnumerable <PayloadWriterTestDescriptor <ODataItem> > testDescriptors = testCases.Select(testCase =>
            {
                ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                entry.TypeName      = "TestModel.CustomerType";
                return(new PayloadWriterTestDescriptor <ODataItem>(
                           this.Settings,
                           new ODataItem[] { entry, testCase.NavigationLink, null },
                           (testConfiguration) =>
                {
                    if (testConfiguration.Format == ODataFormat.Json)
                    {
                        return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                        {
                            Json = string.Join(
                                "$(NL)",
                                "{",
                                testCase.JsonLight,
                                "}"),
                            FragmentExtractor = (result) =>
                            {
                                var links = result.Object().GetPropertyAnnotations(testCase.PropertyName).ToList();
                                var jsonResult = new JsonObject();
                                links.ForEach(l =>
                                {
                                    // NOTE we remove all annoatations here and in particular the text annotations to be able to easily compare
                                    //      against the expected results. This however means that we do not distinguish between the indented and non-indented case here.
                                    l.RemoveAllAnnotations(true);
                                    jsonResult.Add(l);
                                });
                                return jsonResult;
                            }
                        };
                    }
                    else
                    {
                        this.Settings.Assert.Fail("Unknown format '{0}'.", testConfiguration.Format);
                        return null;
                    }
                })
                {
                    Model = model,
                    PayloadEdmElementContainer = customerSet
                });
            });

            // With and without model
            testDescriptors = testDescriptors.SelectMany(td =>
                                                         new[]
            {
                td,
                new PayloadWriterTestDescriptor <ODataItem>(td)
                {
                    Model = null,
                    PayloadEdmElementContainer = null
                }
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors.PayloadCases(WriterPayloads.EntryPayloads),
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent.Where(testConfiguration => !testConfiguration.IsRequest),
                (testDescriptor, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                if (testDescriptor.Model == null && testConfiguration.Format == ODataFormat.Json)
                {
                    return;
                }

                if (testDescriptor.IsGeneratedPayload && testDescriptor.Model != null)
                {
                    return;
                }

                TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger);
            });
        }
Ejemplo n.º 14
0
        public void DisposeAfterExceptionTest()
        {
            // create a default entry and then set both read and edit links to null to provoke an exception during writing
            ODataResource 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 + ".");
                            }
                        }
                    }
            });
        }
Ejemplo n.º 15
0
        private void WriterStatesTestImplementation(bool feedWriter)
        {
            var testCases = new WriterStatesTestDescriptor[]
            {
                // Start
                new WriterStatesTestDescriptor {
                    Setup           = null,
                    ExpectedResults = new Dictionary <WriterAction, ExpectedException> {
                        { WriterAction.StartResource, feedWriter ? ODataExpectedExceptions.ODataException("ODataWriterCore_CannotWriteTopLevelResourceWithResourceSetWriter") : (ExpectedException)null },
                        { WriterAction.StartFeed, feedWriter ? (ExpectedException)null : ODataExpectedExceptions.ODataException("ODataWriterCore_CannotWriteTopLevelResourceSetWithResourceWriter") },
                        { WriterAction.StartLink, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromStart", "Start", "NavigationLink") },
                        { WriterAction.End, ODataExpectedExceptions.ODataException("ODataWriterCore_WriteEndCalledInInvalidState", "Start") },
                        { WriterAction.Error, null },
                    }
                },

                // Entry
                new WriterStatesTestDescriptor {
                    Setup = (mw, w, s) => {
                        if (feedWriter)
                        {
                            w.WriteStart(ObjectModelUtils.CreateDefaultFeed());
                        }
                        w.WriteStart(ObjectModelUtils.CreateDefaultEntry());
                    },
                    ExpectedResults = new Dictionary <WriterAction, ExpectedException> {
                        { WriterAction.StartResource, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromResource", "Entry", "Entry") },
                        { WriterAction.StartFeed, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromResource", "Entry", "Feed") },
                        { WriterAction.StartLink, null },
                        { WriterAction.End, null },
                        { WriterAction.Error, null },
                    }
                },

                // Feed
                new WriterStatesTestDescriptor {
                    Setup = (mw, w, s) => {
                        if (feedWriter)
                        {
                            w.WriteStart(ObjectModelUtils.CreateDefaultFeed());
                        }
                        else
                        {
                            w.WriteStart(ObjectModelUtils.CreateDefaultEntry()); w.WriteStart(ObjectModelUtils.CreateDefaultCollectionLink()); w.WriteStart(ObjectModelUtils.CreateDefaultFeed());
                        }
                    },
                    ExpectedResults = new Dictionary <WriterAction, ExpectedException> {
                        { WriterAction.StartResource, null },
                        { WriterAction.StartFeed, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromResourceSet", "Feed", "Feed") },
                        { WriterAction.StartLink, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromResourceSet", "Feed", "NavigationLink") },
                        { WriterAction.End, null },
                        { WriterAction.Error, null },
                    }
                },

                // Link - single
                new WriterStatesTestDescriptor {
                    Setup = (mw, w, s) => {
                        if (feedWriter)
                        {
                            w.WriteStart(ObjectModelUtils.CreateDefaultFeed());
                        }
                        w.WriteStart(ObjectModelUtils.CreateDefaultEntry());
                        w.WriteStart(new ODataNestedResourceInfo {
                            Name = ObjectModelUtils.DefaultLinkName, Url = ObjectModelUtils.DefaultLinkUrl, IsCollection = false
                        });
                    },
                    ExpectedResults = new Dictionary <WriterAction, ExpectedException> {
                        { WriterAction.StartResource, null },
                        { WriterAction.StartFeed, ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionFalseWithResourceSetContent", "http://odata.org/link") },
                        { WriterAction.StartLink, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidStateTransition", "NavigationLink", "NavigationLink") },
                        { WriterAction.End, null },
                        { WriterAction.Error, null },
                    },
                    SkipForTestConfiguration = tc => tc.IsRequest
                },

                // Link - collection
                new WriterStatesTestDescriptor {
                    Setup = (mw, w, s) => {
                        if (feedWriter)
                        {
                            w.WriteStart(ObjectModelUtils.CreateDefaultFeed());
                        }
                        w.WriteStart(ObjectModelUtils.CreateDefaultEntry());
                        w.WriteStart(ObjectModelUtils.CreateDefaultCollectionLink());
                    },
                    ExpectedResults = new Dictionary <WriterAction, ExpectedException> {
                        { WriterAction.StartResource, ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionTrueWithResourceContent", "http://odata.org/link") },
                        { WriterAction.StartFeed, null },
                        { WriterAction.StartLink, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidStateTransition", "NavigationLink", "NavigationLink") },
                        { WriterAction.End, null },
                        { WriterAction.Error, null },
                    },
                    SkipForTestConfiguration = tc => tc.IsRequest
                },

                // Expanded link - there's no way to get to the expanded link state alone since the writer will always
                //   immediately transition to either entry or feed state instead.

                // Completed
                new WriterStatesTestDescriptor {
                    Setup = (mw, w, s) => {
                        if (feedWriter)
                        {
                            w.WriteStart(ObjectModelUtils.CreateDefaultFeed()); w.WriteEnd();
                        }
                        else
                        {
                            w.WriteStart(ObjectModelUtils.CreateDefaultEntry()); w.WriteEnd();
                        }
                    },
                    ExpectedResults = new Dictionary <WriterAction, ExpectedException> {
                        { WriterAction.StartResource, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromCompleted", "Completed", "Entry") },
                        { WriterAction.StartFeed, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromCompleted", "Completed", "Feed") },
                        { WriterAction.StartLink, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromCompleted", "Completed", "NavigationLink") },
                        { WriterAction.End, ODataExpectedExceptions.ODataException("ODataWriterCore_WriteEndCalledInInvalidState", "Completed") },
                        { WriterAction.Error, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromCompleted", "Completed", "Error") },
                    }
                },

                // ODataExceptionThrown
                new WriterStatesTestDescriptor {
                    Setup = (mw, w, s) => {
                        TestExceptionUtils.RunCatching(() => w.WriteStart(ObjectModelUtils.CreateDefaultCollectionLink()));
                    },
                    ExpectedResults = new Dictionary <WriterAction, ExpectedException> {
                        { WriterAction.StartResource, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromError", "Error", "Entry") },
                        { WriterAction.StartFeed, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromError", "Error", "Feed") },
                        { WriterAction.StartLink, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromError", "Error", "NavigationLink") },
                        { WriterAction.End, ODataExpectedExceptions.ODataException("ODataWriterCore_WriteEndCalledInInvalidState", "Error") },
                        { WriterAction.Error, null },
                    },
                    SkipForTestConfiguration = tc => tc.IsRequest,
                },

                // Error
                new WriterStatesTestDescriptor {
                    Setup = (mw, w, s) => {
                        mw.WriteError(new ODataError(), false);
                    },
                    ExpectedResults = new Dictionary <WriterAction, ExpectedException> {
                        { WriterAction.StartResource, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromError", "Error", "Entry") },
                        { WriterAction.StartFeed, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromError", "Error", "Feed") },
                        { WriterAction.StartLink, ODataExpectedExceptions.ODataException("ODataWriterCore_InvalidTransitionFromError", "Error", "NavigationLink") },
                        { WriterAction.End, ODataExpectedExceptions.ODataException("ODataWriterCore_WriteEndCalledInInvalidState", "Error") },
                        { WriterAction.Error, ODataExpectedExceptions.ODataException("ODataMessageWriter_WriteErrorAlreadyCalled") },
                    },
                    SkipForTestConfiguration = tc => tc.IsRequest,
                },
            };

            ExpectedException errorNotAllowedException = ODataExpectedExceptions.ODataException("ODataMessageWriter_ErrorPayloadInRequest");

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                EnumExtensionMethods.GetValues <WriterAction>().Cast <WriterAction>(),
                this.WriterTestConfigurationProvider.AtomFormatConfigurations,
                (testCase, writerAction, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                if (testCase.SkipForTestConfiguration != null && testCase.SkipForTestConfiguration(testConfiguration))
                {
                    return;
                }

                ExpectedException expectedExceptionOnError;
                if (testCase.ExpectedResults.TryGetValue(WriterAction.Error, out expectedExceptionOnError))
                {
                    if (testConfiguration.IsRequest)
                    {
                        testCase = new WriterStatesTestDescriptor(testCase);
                        testCase.ExpectedResults[WriterAction.Error] = errorNotAllowedException;
                    }
                }

                using (TestStream stream = new TestStream())
                {
                    // We purposely don't use the using pattern around the messageWriter here. Disposing the message writer will
                    // fail here because the writer is not left in a valid state.
                    var messageWriter  = TestWriterUtils.CreateMessageWriter(stream, testConfiguration, this.Assert);
                    ODataWriter writer = messageWriter.CreateODataWriter(feedWriter);

                    TestExceptionUtils.ExpectedException(
                        this.Assert,
                        () =>
                    {
                        if (testCase.Setup != null)
                        {
                            testCase.Setup(messageWriter, writer, stream);
                        }
                        this.InvokeWriterAction(messageWriter, writer, writerAction);
                    },
                        testCase.ExpectedResults[writerAction],
                        this.ExceptionVerifier);
                }
            });
        }
        public void EntryDefaultStreamTest()
        {
            string readLink               = "http://odata.org/read";
            Uri    readLinkUri            = new Uri(readLink);
            string editLink               = "http://odata.org/edit";
            Uri    editLinkUri            = new Uri(editLink);
            string contentType            = "application/binary";
            string etag                   = "\"myetagvalue\"";
            string atomEscapedEtag        = "&quot;myetagvalue&quot;";
            string outOfContentProperties = "<m:properties xmlns:m=\"" + TestAtomConstants.ODataMetadataNamespace + "\"><d:ID xmlns:d=\"" + TestAtomConstants.ODataNamespace + "\">foo</d:ID></m:properties>";

            var testCases = new[]
            {
                new {  // Completely empty default stream is valid and should not produce any MLE/MR related values in the payload
                    DefaultStream = new ODataStreamReferenceValue(),
                    Atom          = outOfContentProperties,
                },
                new {  // Bare minimum for valid default stream
                    DefaultStream = new ODataStreamReferenceValue()
                    {
                        ReadLink = readLinkUri, EditLink = null, ContentType = contentType, ETag = null
                    },
                    Atom = "<content type=\"" + contentType + "\" src=\"" + readLinkUri + "\" xmlns=\"" + TestAtomConstants.AtomNamespace + "\" />" +
                           outOfContentProperties
                },
                new {  // with edit link
                    DefaultStream = new ODataStreamReferenceValue()
                    {
                        ReadLink = readLinkUri, EditLink = editLinkUri, ContentType = contentType, ETag = null
                    },
                    Atom = "<content type=\"" + contentType + "\" src=\"" + readLinkUri + "\" xmlns=\"" + TestAtomConstants.AtomNamespace + "\" />" +
                           "<link rel=\"edit-media\" href=\"" + editLink + "\" xmlns=\"" + TestAtomConstants.AtomNamespace + "\" />" +
                           outOfContentProperties
                },
                new {  // just edit link
                    DefaultStream = new ODataStreamReferenceValue()
                    {
                        ReadLink = null, EditLink = editLinkUri, ContentType = null, ETag = null
                    },
                    Atom = "<link rel=\"edit-media\" href=\"" + editLink + "\" xmlns=\"" + TestAtomConstants.AtomNamespace + "\" />" +
                           outOfContentProperties
                },
                // etag without edit link is invalid and is covered in input validation tests
                new {  // with edit link and etag
                    DefaultStream = new ODataStreamReferenceValue()
                    {
                        ReadLink = readLinkUri, EditLink = editLinkUri, ContentType = contentType, ETag = etag
                    },
                    Atom = "<content type=\"" + contentType + "\" src=\"" + readLinkUri + "\" xmlns=\"" + TestAtomConstants.AtomNamespace + "\" />" +
                           "<link rel=\"edit-media\" href=\"" + editLink + "\" p2:etag=\"" + atomEscapedEtag + "\" xmlns:p2=\"" + TestAtomConstants.ODataMetadataNamespace + "\" " +
                           "xmlns=\"" + TestAtomConstants.AtomNamespace + "\" />" +
                           outOfContentProperties
                }
            };

            var testDescriptors = testCases.Select(testCase =>
            {
                ODataEntry entry = ObjectModelUtils.CreateDefaultEntry();
                entry.Properties = new ODataProperty[] { new ODataProperty {
                                                             Name = "ID", Value = "foo"
                                                         } };
                entry.MediaResource = testCase.DefaultStream;
                return(new PayloadWriterTestDescriptor <ODataItem>(
                           this.Settings,
                           entry,
                           (testConfiguration) =>
                {
                    return new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        Xml = "<DefaultStream>" + testCase.Atom + "</DefaultStream>",
                        FragmentExtractor = (result) =>
                        {
                            var content = result.Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomContentElementName);
                            content = content == null ? null : new XElement(content.Name, content.Attributes());
                            var mediaEditLink = result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                                .Where(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.ODataStreamPropertyEditMediaSegmentName);
                            var properties = result.Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.AtomPropertiesElementName);
                            return new XElement("DefaultStream", content, mediaEditLink, properties);
                        }
                    };
                }));
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors.PayloadCases(WriterPayloads.EntryPayloads),
                this.WriterTestConfigurationProvider.AtomFormatConfigurationsWithIndent,
                (testDescriptor, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger);
            });
        }
Ejemplo n.º 17
0
        public void FeedUserExceptionTests()
        {
            IEdmModel edmModel = Microsoft.Test.OData.Utils.Metadata.TestModels.BuildTestModel();

            ODataFeed           cityFeed  = ObjectModelUtils.CreateDefaultFeed();
            ODataEntry          cityEntry = ObjectModelUtils.CreateDefaultEntry("TestModel.CityType");
            ODataNavigationLink cityHallCollectionLink     = ObjectModelUtils.CreateDefaultCollectionLink("CityHall");
            ODataNavigationLink policeStationSingletonLink = ObjectModelUtils.CreateDefaultSingletonLink("PoliceStation");
            ODataFeed           officeFeed  = ObjectModelUtils.CreateDefaultFeed();
            ODataEntry          officeEntry = ObjectModelUtils.CreateDefaultEntry("TestModel.OfficeType");

            var container = edmModel.FindEntityContainer("DefaultContainer");
            var citySet   = container.FindEntitySet("Cities") as EdmEntitySet;
            var cityType  = edmModel.FindType("TestModel.CityType") as EdmEntityType;

            ODataItem[] writerPayload = new ODataItem[]
            {
                cityFeed,
                cityEntry,
                null,
                cityEntry,
                cityHallCollectionLink,
                officeFeed,
                officeEntry,
                null,
                null,
                null,
                null,
                cityEntry,
                null,
                cityEntry,
                policeStationSingletonLink,
                officeEntry,
                null,
                null,
                null,
            };

            IEnumerable <PayloadWriterTestDescriptor <ODataItem> > testDescriptors = new PayloadWriterTestDescriptor <ODataItem>[]
            {
                new PayloadWriterTestDescriptor <ODataItem>(
                    this.Settings,
                    writerPayload,
                    tc => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                {
                    ExpectedException = new Exception("User code triggered an exception."),
                }
                    )
                {
                    Model = edmModel,
                    PayloadEdmElementContainer = citySet,
                    PayloadEdmElementType      = cityType,
                }
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors.PayloadCases(WriterPayloads.FeedPayloads),
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent,
                (testDescriptor, testConfiguration) =>
            {
                if (testDescriptor.IsGeneratedPayload && (testConfiguration.Format == ODataFormat.Json || testDescriptor.Model != null))
                {
                    return;
                }

                foreach (int throwUserExceptionAt in Enumerable.Range(0, testDescriptor.PayloadItems.Count + 1))
                {
                    var configuredTestDescriptor = new PayloadWriterTestDescriptor <ODataItem>(this.Settings, testDescriptor.PayloadItems, testDescriptor.ExpectedResultCallback)
                    {
                        Model = testDescriptor.Model,
                        PayloadEdmElementContainer = testDescriptor.PayloadEdmElementContainer,
                        PayloadEdmElementType      = testDescriptor.PayloadEdmElementType,
                        ThrowUserExceptionAt       = throwUserExceptionAt,
                    };

                    TestWriterUtils.WriteAndVerifyODataEdmPayload(configuredTestDescriptor, testConfiguration, this.Assert, this.Logger);
                }
            });
        }
Ejemplo n.º 18
0
        public void FeedMetadataWriterTest()
        {
            AtomTextConstruct testRights = new AtomTextConstruct {
                Text = "Copyright Data Fx team."
            };
            AtomTextConstruct testTitle = new AtomTextConstruct {
                Text = "Test title"
            };
            AtomTextConstruct testSubtitle = new AtomTextConstruct {
                Text = "Test subtitle"
            };
            const string testUpdated = "2010-11-01T00:04:00Z";
            const string testIcon    = "http://odata.org/icon";
            const string testLogo    = "http://odata.org/logo";

            const string testAuthorName  = "Test Author 1";
            const string testAuthorEmail = "*****@*****.**";
            const string testAuthorUri   = "http://odata.org/authors/1";

            var testAuthors = new AtomPersonMetadata[]
            {
                new AtomPersonMetadata()
                {
                    Email = testAuthorEmail,
                    Name  = testAuthorName,
                    Uri   = new Uri(testAuthorUri)
                }
            };

            const string testCategoryTerm   = "Test category 1 term";
            const string testCategoryLabel  = "Test category 1 label";
            const string testCategoryScheme = "http://odata.org/categories/1";

            var testCategories = new AtomCategoryMetadata[]
            {
                new AtomCategoryMetadata()
                {
                    Term   = testCategoryTerm,
                    Label  = testCategoryLabel,
                    Scheme = testCategoryScheme
                }
            };

            const string testContributorName  = "Test Contributor 1";
            const string testContributorEmail = "*****@*****.**";
            const string testContributorUri   = "http://odata.org/contributors/1";

            var testContributors = new AtomPersonMetadata[]
            {
                new AtomPersonMetadata()
                {
                    Email = testContributorEmail,
                    Name  = testContributorName,
                    Uri   = new Uri(testContributorUri)
                }
            };

            const string testGeneratorName    = "Test generator";
            const string testGeneratorUri     = "http://odata.org/generator";
            const string testGeneratorVersion = "3.0";

            var testGenerator = new AtomGeneratorMetadata()
            {
                Name    = testGeneratorName,
                Uri     = new Uri(testGeneratorUri),
                Version = testGeneratorVersion
            };

            const string testLinkRelation  = "http://odata.org/links/1";
            const string testLinkTitle     = "Test link 1";
            const string testLinkHref      = "http://odata.org/links/1";
            const string testLinkHrefLang  = "de-AT";
            int?         testLinkLength    = 999;
            const string testLinkMediaType = "image/png";

            var testLinks = new AtomLinkMetadata[]
            {
                new AtomLinkMetadata()
                {
                    Relation  = testLinkRelation,
                    Title     = testLinkTitle,
                    Href      = new Uri(testLinkHref),
                    HrefLang  = testLinkHrefLang,
                    Length    = testLinkLength,
                    MediaType = testLinkMediaType
                }
            };

            var selfLink = new AtomLinkMetadata()
            {
                Relation  = TestAtomConstants.AtomSelfRelationAttributeValue,
                Title     = testLinkTitle,
                Href      = new Uri(testLinkHref),
                HrefLang  = testLinkHrefLang,
                Length    = testLinkLength,
                MediaType = testLinkMediaType
            };

            Func <string, Func <XElement, XElement> > fragmentExtractor = (localName) => (e) => e.Element(TestAtomConstants.AtomXNamespace + localName);

            // TODO, ckerer: specify an Id via metadata if the entry does not specify one; we first have to decide what rules
            //               we want to apply to merging of metadata and ODataLib OM data.
            var testCases = new FeedMetadataTestCase[] {
                new FeedMetadataTestCase { // specify an icon via metadata
                    CustomizeMetadata = metadata => metadata.Icon = new Uri(testIcon),
                    Xml       = @"<icon xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testIcon + @"</icon>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomIconElementName)
                },
                new FeedMetadataTestCase { // specify a logo via metadata
                    CustomizeMetadata = metadata => metadata.Logo = new Uri(testLogo),
                    Xml       = @"<logo xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testLogo + @"</logo>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomLogoElementName)
                },
                new FeedMetadataTestCase { // specify rights via metadata
                    CustomizeMetadata = metadata => metadata.Rights = testRights,
                    Xml       = @"<rights type=""text"" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testRights.Text + @"</rights>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomRightsElementName)
                },
                new FeedMetadataTestCase { // specify a subtitle via metadata
                    CustomizeMetadata = metadata => metadata.Subtitle = testSubtitle,
                    Xml       = @"<subtitle type=""text"" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testSubtitle.Text + @"</subtitle>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomSubtitleElementName)
                },
                new FeedMetadataTestCase { // specify a title via metadata
                    CustomizeMetadata = metadata => metadata.Title = testTitle,
                    Xml       = @"<title type=""text"" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testTitle.Text + @"</title>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomTitleElementName)
                },
                new FeedMetadataTestCase { // specify an updated date via metadata
                    CustomizeMetadata = metadata => metadata.Updated = DateTimeOffset.Parse(testUpdated),
                    Xml       = @"<updated xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testUpdated + @"</updated>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomUpdatedElementName)
                },
                new FeedMetadataTestCase { // no author specified, the default author with empty name is written
                    CustomizeMetadata = metadata => metadata.Authors = null,
                    Xml = string.Join(
                        "$(NL)",
                        @"<author xmlns=""" + TestAtomConstants.AtomNamespace + @""">",
                        @"  <name />",
                        @"</author>"),
                    Extractor = fragmentExtractor(TestAtomConstants.AtomAuthorElementName)
                },
                new FeedMetadataTestCase { // specify an author via metadata
                    CustomizeMetadata = metadata => metadata.Authors = testAuthors,
                    Xml = string.Join(
                        "$(NL)",
                        @"<author xmlns=""" + TestAtomConstants.AtomNamespace + @""">",
                        @"  <name>" + testAuthorName + @"</name>",
                        @"  <uri>" + testAuthorUri + @"</uri>",
                        @"  <email>" + testAuthorEmail + @"</email>",
                        @"</author>"),
                    Extractor = fragmentExtractor(TestAtomConstants.AtomAuthorElementName)
                },
                new FeedMetadataTestCase { // no author specified but some entries written, no author should be written
                    CustomizeMetadata = metadata => metadata.Authors = null,
                    CustomizePayload  = feed => new ODataItem[] { feed, ObjectModelUtils.CreateDefaultEntry() },
                    Xml       = "<authors />",
                    Extractor = result => new XElement("authors", fragmentExtractor(TestAtomConstants.AtomAuthorElementName)(result))
                },
                new FeedMetadataTestCase { // specify an author via metadata and some entries (the author should be written anyway)
                    CustomizeMetadata = metadata => metadata.Authors = testAuthors,
                    CustomizePayload  = feed => new ODataItem[] { feed, ObjectModelUtils.CreateDefaultEntry() },
                    Xml = string.Join(
                        "$(NL)",
                        @"<author xmlns=""" + TestAtomConstants.AtomNamespace + @""">",
                        @"  <name>" + testAuthorName + @"</name>",
                        @"  <uri>" + testAuthorUri + @"</uri>",
                        @"  <email>" + testAuthorEmail + @"</email>",
                        @"</author>"),
                    Extractor = fragmentExtractor(TestAtomConstants.AtomAuthorElementName)
                },
                new FeedMetadataTestCase { // specify a category via metadata
                    CustomizeMetadata = metadata => metadata.Categories = testCategories,
                    Xml       = @"<category term=""" + testCategoryTerm + @""" scheme=""" + testCategoryScheme + @""" label=""" + testCategoryLabel + @""" xmlns=""" + TestAtomConstants.AtomNamespace + @""" />",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomCategoryElementName)
                },
                new FeedMetadataTestCase { // specify a contributor via metadata
                    CustomizeMetadata = metadata => metadata.Contributors = testContributors,
                    Xml = string.Join(
                        "$(NL)",
                        @"<contributor xmlns=""" + TestAtomConstants.AtomNamespace + @""">",
                        @"  <name>" + testContributorName + @"</name>",
                        @"  <uri>" + testContributorUri + @"</uri>",
                        @"  <email>" + testContributorEmail + @"</email>",
                        @"</contributor>"),
                    Extractor = fragmentExtractor(TestAtomConstants.AtomContributorElementName)
                },
                new FeedMetadataTestCase { // specify a generator via metadata
                    CustomizeMetadata = metadata => metadata.Generator = testGenerator,
                    Xml       = @"<generator uri=""" + testGeneratorUri + @""" version=""" + testGeneratorVersion + @""" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testGeneratorName + @"</generator>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomGeneratorElementName)
                },
                new FeedMetadataTestCase { // specify a link via metadata
                    CustomizeMetadata = metadata => metadata.Links = testLinks,
                    Xml       = @"<link rel=""" + testLinkRelation + @""" type = """ + testLinkMediaType + @""" title=""" + testLinkTitle + @""" href=""" + testLinkHref + @""" hreflang=""" + testLinkHrefLang + @""" length=""" + testLinkLength + @"""  xmlns=""" + TestAtomConstants.AtomNamespace + @"""/>",
                    Extractor = (e) => e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                .Single()
                },
                new FeedMetadataTestCase { // no self link specified
                    CustomizeMetadata = metadata => metadata.SelfLink = null,
                    Xml       = @"<selflink/>",
                    Extractor = (e) => new XElement("selflink",
                                                    e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                                    .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomSelfRelationAttributeValue))
                },
                new FeedMetadataTestCase { // Some self link specified
                    CustomizeMetadata = metadata => metadata.SelfLink = selfLink,
                    Xml       = @"<link rel=""" + TestAtomConstants.AtomSelfRelationAttributeValue + @""" type = """ + testLinkMediaType + @""" title=""" + testLinkTitle + @""" href=""" + testLinkHref + @""" hreflang=""" + testLinkHrefLang + @""" length=""" + testLinkLength + @"""  xmlns=""" + TestAtomConstants.AtomNamespace + @"""/>",
                    Extractor = (e) => e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomSelfRelationAttributeValue)
                },
                new FeedMetadataTestCase { // Non-self relation
                    CustomizeMetadata = metadata => metadata.SelfLink = new AtomLinkMetadata {
                        Relation = "SelF", Href = new Uri(testLinkHref)
                    },
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomWriterMetadataUtils_LinkRelationsMustMatch", "self", "SelF"),
                },
                new FeedMetadataTestCase { // no next link on either OM or metadata specified
                    CustomizeMetadata = metadata => metadata.NextPageLink = null,
                    Xml       = @"<nextlink/>",
                    Extractor = (e) => new XElement("nextlink",
                                                    e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                                    .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomNextRelationAttributeValue)),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
                new FeedMetadataTestCase { // the next link is only specified on metadata - nothing is written
                    CustomizeMetadata = metadata => metadata.NextPageLink = new AtomLinkMetadata {
                        Relation = "next", Href = new Uri(testLinkHref)
                    },
                    Xml       = @"<nextlink/>",
                    Extractor = (e) => new XElement("nextlink",
                                                    e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                                    .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomNextRelationAttributeValue)),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
                new FeedMetadataTestCase { // Next link specified only on the OM
                    CustomizeMetadata = metadata => metadata.NextPageLink = null,
                    CustomizePayload  = feed => { feed.NextPageLink = new Uri(testLinkHref); return(new ODataItem[] { feed }); },
                    Xml       = @"<link rel=""" + TestAtomConstants.AtomNextRelationAttributeValue + @""" href=""" + testLinkHref + @""" xmlns=""" + TestAtomConstants.AtomNamespace + @"""/>",
                    Extractor = (e) => e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomNextRelationAttributeValue),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
                new FeedMetadataTestCase { // Next link specified both on OM and on metadata - no conflicts
                    CustomizeMetadata = metadata => metadata.NextPageLink = new AtomLinkMetadata {
                        Title = testLinkTitle, HrefLang = testLinkHrefLang, Length = testLinkLength, MediaType = testLinkMediaType
                    },
                    CustomizePayload = feed => { feed.NextPageLink = new Uri(testLinkHref); return(new ODataItem[] { feed }); },
                    Xml       = @"<link rel=""" + TestAtomConstants.AtomNextRelationAttributeValue + @""" type = """ + testLinkMediaType + @""" title=""" + testLinkTitle + @""" href=""" + testLinkHref + @""" hreflang=""" + testLinkHrefLang + @""" length=""" + testLinkLength + @"""  xmlns=""" + TestAtomConstants.AtomNamespace + @"""/>",
                    Extractor = (e) => e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomNextRelationAttributeValue),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
                new FeedMetadataTestCase { // Next link specified both on OM and on metadata - no conflicts cause values are identical
                    CustomizeMetadata = metadata => metadata.NextPageLink = new AtomLinkMetadata {
                        Relation = TestAtomConstants.AtomNextRelationAttributeValue, Href = new Uri(testLinkHref), Title = testLinkTitle, HrefLang = testLinkHrefLang, Length = testLinkLength, MediaType = testLinkMediaType
                    },
                    CustomizePayload = feed => { feed.NextPageLink = new Uri(testLinkHref); return(new ODataItem[] { feed }); },
                    Xml       = @"<link rel=""" + TestAtomConstants.AtomNextRelationAttributeValue + @""" type = """ + testLinkMediaType + @""" title=""" + testLinkTitle + @""" href=""" + testLinkHref + @""" hreflang=""" + testLinkHrefLang + @""" length=""" + testLinkLength + @"""  xmlns=""" + TestAtomConstants.AtomNamespace + @"""/>",
                    Extractor = (e) => e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomNextRelationAttributeValue),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
                new FeedMetadataTestCase { // Next link specified both on OM and on metadata - conflict on relation
                    CustomizeMetadata = metadata => metadata.NextPageLink = new AtomLinkMetadata {
                        Relation = "Next", Title = testLinkTitle, HrefLang = testLinkHrefLang, Length = testLinkLength, MediaType = testLinkMediaType
                    },
                    CustomizePayload      = feed => { feed.NextPageLink = new Uri(testLinkHref); return(new ODataItem[] { feed }); },
                    ExpectedException     = ODataExpectedExceptions.ODataException("ODataAtomWriterMetadataUtils_LinkRelationsMustMatch", "next", "Next"),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
                new FeedMetadataTestCase { // Next link specified both on OM and on metadata - conflict on href
                    CustomizeMetadata = metadata => metadata.NextPageLink = new AtomLinkMetadata {
                        Href = new Uri("http://odata.org/different"), Title = testLinkTitle, HrefLang = testLinkHrefLang, Length = testLinkLength, MediaType = testLinkMediaType
                    },
                    CustomizePayload      = feed => { feed.NextPageLink = new Uri(testLinkHref); return(new ODataItem[] { feed }); },
                    ExpectedException     = ODataExpectedExceptions.ODataException("ODataAtomWriterMetadataUtils_LinkHrefsMustMatch", testLinkHref, "http://odata.org/different"),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
            };

            this.CreateTestDescriptorsAndRunTests(testCases, WriterPayloads.FeedPayloads);
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Returns all interesting payloads for a feed.
        /// </summary>
        /// <param name="testDescriptor">The test descriptor which will end up writing a single feed.</param>
        /// <returns>Enumeration of test descriptors which will include the original feed in some interesting scenarios.</returns>
        public static IEnumerable <PayloadWriterTestDescriptor <ODataItem> > FeedPayloads(PayloadWriterTestDescriptor <ODataItem> testDescriptor)
        {
            Debug.Assert(testDescriptor.PayloadItems[0] is ODataResourceSet, "The payload does not specify a feed.");

            var payloadCases = new WriterPayloadCase <ODataItem>[]
            {
                // Top-level feed with an entry that has an expanded link containing the feed
                new WriterPayloadCase <ODataItem>()
                {
                    GetPayloadItems = () => new ODataItem[]
                    {
                        ObjectModelUtils.CreateDefaultFeed(),
                ObjectModelUtils.CreateDefaultEntry(),
                ObjectModelUtils.CreateDefaultCollectionLink(),
                    }.Concat(testDescriptor.PayloadItems),
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(result.Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomEntryElementName)
                               .Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                               .First(e => e.Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName) != null)
                               .Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomFeedElementName));
                    },
                    //ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
                },

                // Top-level entry with an expanded link containing the feed
                new WriterPayloadCase <ODataItem>()
                {
                    GetPayloadItems = () => new ODataItem[]
                    {
                        ObjectModelUtils.CreateDefaultEntry(),
                            ObjectModelUtils.CreateDefaultCollectionLink(),
                    }.Concat(testDescriptor.PayloadItems),
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                               .First(e => e.Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName) != null)
                               .Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomFeedElementName));
                    },
                    //ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
                },

                // Top-level entry with an expanded link containing a feed with a single entry;
                // that entry has another expanded link containing the payload feed
                new WriterPayloadCase <ODataItem>()
                {
                    GetPayloadItems = () => new ODataItem[]
                    {
                        ObjectModelUtils.CreateDefaultEntry(),
                            ObjectModelUtils.CreateDefaultCollectionLink(),
                            ObjectModelUtils.CreateDefaultFeed(),
                            ObjectModelUtils.CreateDefaultEntry(),
                            ObjectModelUtils.CreateDefaultCollectionLink(),
                    }.Concat(testDescriptor.PayloadItems),
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                               .First(e => e.Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName) != null)
                               .Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomFeedElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomEntryElementName)
                               .Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                               .First(e => e.Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName) != null)
                               .Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomFeedElementName));
                    },
                    //ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
                },
            };

            return(ApplyPayloadCases <ODataItem>(testDescriptor, payloadCases));
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Returns all interesting payloads for a named stream.
        /// </summary>
        /// <param name="testDescriptor">Test descriptor which will end up writing a single entry with a single named stream.
        /// The entry is not going to be used, but the named stream from it will.</param>
        /// <returns>Enumeration of test descriptors which will include the original named stream in some interesting scenarios.</returns>
        public static IEnumerable <PayloadWriterTestDescriptor <ODataItem> > NamedStreamPayloads(PayloadWriterTestDescriptor <ODataItem> testDescriptor)
        {
            ODataResource tempEntry = testDescriptor.PayloadItems[0] as ODataResource;

            Debug.Assert(tempEntry != null, "A single entry payload is expected.");
            ODataProperty namedStreamProperty = tempEntry.Properties.FirstOrDefault(p => p != null && p.Value is ODataStreamReferenceValue);

            // Note - the named stream can be null - it is a valid test case !!!!

            var payloadCases = new WriterPayloadCase <ODataItem>[] {
                new WriterPayloadCase <ODataItem>()  // Single named stream on an entry
                {
                    GetPayloadItems = () => {
                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        entry.TypeName   = "TestModel.EntityWithStreamProperty";
                        entry.Properties = new ODataProperty[] { namedStreamProperty };
                        return(new ODataItem[] { entry });
                    },
                    ModelBuilder = (model) =>
                    {
                        model = model.Clone();
                        model.EntityType("EntityWithStreamProperty", "TestModel")
                        .StreamProperty(namedStreamProperty.Name);
                        return(model);
                    },
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(TestAtomUtils.ExtractNamedStreamLinksFromEntry(result, namedStreamProperty.Name));
                    },
                    JsonLightFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(new JsonObject().AddProperties(result.Object().GetPropertyAnnotationsAndProperty(namedStreamProperty.Name)));
                    },
                },

                new WriterPayloadCase <ODataItem>()  // Single named stream on an entry with other properties before/after it
                {
                    GetPayloadItems = () => {
                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        entry.TypeName   = "TestModel.EntityWithStreamPropertyAndOtherProperties";
                        entry.Properties = new ODataProperty[]
                        {
                            new ODataProperty {
                                Name = "Id", Value = 1
                            },
                            new ODataProperty {
                                Name = "Name", Value = "Clemens"
                            },
                            namedStreamProperty,
                            new ODataProperty {
                                Name  = "Address",
                                Value = new ODataComplexValue
                                {
                                    TypeName   = "TestModel.AddressType",
                                    Properties = new ODataProperty[]
                                    {
                                        new ODataProperty {
                                            Name = "Street", Value = "Am Euro Platz"
                                        },
                                        new ODataProperty {
                                            Name = "City", Value = "Vienna"
                                        }
                                    }
                                }
                            }
                        };
                        return(new ODataItem[] { entry });
                    },
                    ModelBuilder = (model) =>
                    {
                        model = model.Clone();
                        var addressType = model.ComplexType("AddressType", "TestModel")
                                          .Property("Street", EdmPrimitiveTypeKind.String)
                                          .Property("City", EdmPrimitiveTypeKind.String);
                        model.EntityType("EntityWithStreamPropertyAndOtherProperties", "TestModel")
                        .KeyProperty("Id", (EdmTypeReference)EdmCoreModel.Instance.GetInt32(false))
                        .Property("Name", EdmPrimitiveTypeKind.String)
                        .StreamProperty(namedStreamProperty.Name)
                        .Property("Address", new EdmComplexTypeReference(addressType, false));
                        return(model);
                    },
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(TestAtomUtils.ExtractNamedStreamLinksFromEntry(result, namedStreamProperty.Name));
                    },
                    JsonLightFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(new JsonObject().AddProperties(result.Object().GetPropertyAnnotationsAndProperty(namedStreamProperty.Name)));
                    },
                },

                new WriterPayloadCase <ODataItem>()  // Multiple named stream properties on an entry
                {
                    GetPayloadItems = () => {
                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        entry.TypeName   = "TestModel.EntityWithSeveralStreamProperties";
                        entry.Properties = new ODataProperty[]
                        {
                            new ODataProperty {
                                Name = "Id", Value = 1
                            },
                            new ODataProperty {
                                Name = "__Stream1", Value = new ODataStreamReferenceValue {
                                    ReadLink = new Uri("http://odata.org/stream1/readlink")
                                }
                            },
                            new ODataProperty {
                                Name = "__Stream2", Value = new ODataStreamReferenceValue {
                                    EditLink = new Uri("http://odata.org/stream2/editlink")
                                }
                            },
                            namedStreamProperty,
                            new ODataProperty {
                                Name = "__Stream3", Value = new ODataStreamReferenceValue {
                                    ReadLink = new Uri("http://odata.org/stream3/readlink"), ContentType = "stream3:contenttype"
                                }
                            },
                        };
                        return(new ODataItem[] { entry });
                    },
                    ModelBuilder = (model) =>
                    {
                        model = model.Clone();
                        model.EntityType("EntityWithSeveralStreamProperties", "TestModel")
                        .KeyProperty("Id", (EdmTypeReference)EdmCoreModel.Instance.GetInt32(false))
                        .StreamProperty("__Stream1")
                        .StreamProperty("__Stream2")
                        .StreamProperty(namedStreamProperty.Name)
                        .StreamProperty("__Stream3");
                        return(model);
                    },
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(TestAtomUtils.ExtractNamedStreamLinksFromEntry(result, namedStreamProperty.Name));
                    },
                    JsonLightFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(new JsonObject().AddProperties(result.Object().GetPropertyAnnotationsAndProperty(namedStreamProperty.Name)));
                    },
                },
            };

            return(ApplyPayloadCases <ODataItem>(testDescriptor, payloadCases));
        }
Ejemplo n.º 21
0
        public void ActionAndFunctionTest()
        {
            // <m:action Metadata=URI title?="title" target=URI />

            Uri    actionMetadata  = new Uri("http://odata.org/test/$metadata#defaultAction");
            Uri    actionMetadata2 = new Uri("#action escaped relative metadata", UriKind.Relative);
            Uri    actionMetadata3 = new Uri("../#action escaped relative metadata", UriKind.Relative);
            string actionTitle     = "Default Action";
            Uri    actionTarget    = new Uri("http://odata.org/defaultActionTarget");
            Uri    actionTarget2   = new Uri("http://odata.org/defaultActionTarget2");

            ODataAction action_r1_t1 = new ODataAction()
            {
                Metadata = actionMetadata, Title = actionTitle, Target = actionTarget
            };
            ODataAction action_r1_t2 = new ODataAction()
            {
                Metadata = actionMetadata, Title = actionTitle, Target = actionTarget2
            };
            ODataAction action_r2_t1 = new ODataAction()
            {
                Metadata = actionMetadata2, Title = actionTitle, Target = actionTarget
            };
            ODataAction action_r3_t1 = new ODataAction()
            {
                Metadata = actionMetadata3, Title = actionTitle, Target = actionTarget
            };

            Uri    functionMetadata  = new Uri("http://odata.org/test/$metadata#defaultFunction");
            Uri    functionMetadata2 = new Uri("#function escaped relative metadata", UriKind.Relative);
            Uri    functionMetadata3 = new Uri("\\#function escaped relative metadata", UriKind.Relative);
            string functionTitle     = "Default Function";
            Uri    functionTarget    = new Uri("http://odata.org/defaultFunctionTarget");
            Uri    functionTarget2   = new Uri("http://odata.org/defaultFunctionTarget2");

            ODataFunction function_r1_t1 = new ODataFunction()
            {
                Metadata = functionMetadata, Title = functionTitle, Target = functionTarget
            };
            ODataFunction function_r1_t2 = new ODataFunction()
            {
                Metadata = functionMetadata, Title = functionTitle, Target = functionTarget2
            };
            ODataFunction function_r2_t1 = new ODataFunction()
            {
                Metadata = functionMetadata2, Title = functionTitle, Target = functionTarget
            };
            ODataFunction function_r3_t1 = new ODataFunction()
            {
                Metadata = functionMetadata3, Title = functionTitle, Target = functionTarget
            };

            var actionCases = new[]
            {
                new {
                    ODataActions = new ODataAction[] { action_r1_t1 },
                    Atom         = GetAtom(action_r1_t1),
                    JsonLight    = GetJsonLightForRelGroup(action_r1_t1),
                },
                new {
                    ODataActions = new ODataAction[] { action_r1_t1, action_r1_t2 },
                    Atom         = GetAtom(action_r1_t1) + GetAtom(action_r1_t2),
                    JsonLight    = GetJsonLightForRelGroup(action_r1_t1, action_r1_t2),
                },
                new {
                    ODataActions = new ODataAction[] { action_r1_t1, action_r2_t1 },
                    Atom         = GetAtom(action_r1_t1) + GetAtom(action_r2_t1),
                    JsonLight    = GetJsonLightForRelGroup(action_r1_t1) + "," + GetJsonLightForRelGroup(action_r2_t1),
                },
                new {
                    ODataActions = new ODataAction[] { action_r1_t1, action_r2_t1, action_r1_t2 },
                    Atom         = GetAtom(action_r1_t1) + GetAtom(action_r2_t1) + GetAtom(action_r1_t2),
                    JsonLight    = GetJsonLightForRelGroup(action_r1_t1, action_r1_t2) + "," + GetJsonLightForRelGroup(action_r2_t1),
                },
                new {
                    ODataActions = new ODataAction[] { action_r3_t1 },
                    Atom         = GetAtom(action_r3_t1),
                    JsonLight    = GetJsonLightForRelGroup(action_r3_t1),
                },
            };

            var functionCases = new[]
            {
                new {
                    ODataFunctions = new ODataFunction[] { function_r1_t1 },
                    Atom           = GetAtom(function_r1_t1),
                    JsonLight      = GetJsonLightForRelGroup(function_r1_t1),
                },
                new {
                    ODataFunctions = new ODataFunction[] { function_r1_t1, function_r1_t2 },
                    Atom           = GetAtom(function_r1_t1) + GetAtom(function_r1_t2),
                    JsonLight      = GetJsonLightForRelGroup(function_r1_t1, function_r1_t2),
                },
                new {
                    ODataFunctions = new ODataFunction[] { function_r1_t1, function_r2_t1 },
                    Atom           = GetAtom(function_r1_t1) + GetAtom(function_r2_t1),
                    JsonLight      = GetJsonLightForRelGroup(function_r1_t1) + "," + GetJsonLightForRelGroup(function_r2_t1),
                },
                new {
                    ODataFunctions = new ODataFunction[] { function_r1_t1, function_r2_t1, function_r1_t2 },
                    Atom           = GetAtom(function_r1_t1) + GetAtom(function_r2_t1) + GetAtom(function_r1_t2),
                    JsonLight      = GetJsonLightForRelGroup(function_r1_t1, function_r1_t2) + "," + GetJsonLightForRelGroup(function_r2_t1),
                },
                new {
                    ODataFunctions = new ODataFunction[] { function_r3_t1 },
                    Atom           = GetAtom(function_r3_t1),
                    JsonLight      = GetJsonLightForRelGroup(function_r3_t1),
                },
            };

            var queryResults =
                from actionCase in actionCases
                from functionCase in functionCases
                select new
            {
                actionCase.ODataActions,
                functionCase.ODataFunctions,
                Atom      = string.Concat(actionCase.Atom, functionCase.Atom),
                JsonLight = string.Join(",", new[] { actionCase.JsonLight, functionCase.JsonLight }.Where(x => x != null))
            };

            EdmModel           model = new EdmModel();
            EdmEntityType      edmEntityTypeCustomer  = model.EntityType("Customer", "TestModel");
            EdmEntityContainer edmEntityContainer     = model.EntityContainer("DefaultContainer", "TestModel");
            EdmEntitySet       edmEntitySetCustermors = model.EntitySet("Customers", edmEntityTypeCustomer);

            var testDescriptors = queryResults.Select(testCase =>
            {
                ODataResource entry = ObjectModelUtils.CreateDefaultEntry("TestModel.Customer");

                if (testCase.ODataActions != null)
                {
                    foreach (var action in testCase.ODataActions)
                    {
                        entry.AddAction(action);
                    }
                }

                if (testCase.ODataFunctions != null)
                {
                    foreach (var function in testCase.ODataFunctions)
                    {
                        entry.AddFunction(function);
                    }
                }

                return(new PayloadWriterTestDescriptor <ODataItem>(
                           this.Settings,
                           entry,
                           (testConfiguration) =>
                {
                    if (testConfiguration.Format == ODataFormat.Json)
                    {
                        return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                        {
                            Json = string.Join(
                                "$(NL)",
                                "{",
                                testCase.JsonLight,
                                "}"),
                            ExpectedException2 =
                                entry.Actions != null && entry.Actions.Contains(null)
                                        ? ODataExpectedExceptions.ODataException("ValidationUtils_EnumerableContainsANullItem", "ODataResource.Actions")
                                        : testConfiguration.IsRequest && entry.Actions != null && entry.Actions.Any()
                                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_OperationInRequest", GetFirstOperationMetadata(entry))
                                            : entry.Actions != null && entry.Actions.Any(a => !a.Metadata.IsAbsoluteUri && !a.Metadata.OriginalString.StartsWith("#"))
                                                ? ODataExpectedExceptions.ODataException("ValidationUtils_InvalidMetadataReferenceProperty", entry.Actions.First(a => a.Metadata.OriginalString.Contains(" ")).Metadata.OriginalString)
                                            : entry.Functions != null && entry.Functions.Contains(null)
                                                ? ODataExpectedExceptions.ODataException("ValidationUtils_EnumerableContainsANullItem", "ODataResource.Functions")
                                                : testConfiguration.IsRequest && entry.Functions != null && entry.Functions.Any()
                                                    ? ODataExpectedExceptions.ODataException("WriterValidationUtils_OperationInRequest", GetFirstOperationMetadata(entry))
                                                        : entry.Functions != null && entry.Functions.Any(f => !f.Metadata.IsAbsoluteUri && !f.Metadata.OriginalString.StartsWith("#"))
                                                            ? ODataExpectedExceptions.ODataException("ValidationUtils_InvalidMetadataReferenceProperty", entry.Functions.First(f => f.Metadata.OriginalString.Contains(" ")).Metadata.OriginalString)
                                                    : null,
                            FragmentExtractor = (result) =>
                            {
                                var actionsAndFunctions = result.Object().Properties.Where(p => p.Name.Contains("#")).ToList();

                                var jsonResult = new JsonObject();
                                actionsAndFunctions.ForEach(p =>
                                {
                                    // NOTE we remove all annotations here and in particular the text annotations to be able to easily compare
                                    //      against the expected results. This however means that we do not distinguish between the indented and non-indented case here.
                                    p.RemoveAllAnnotations(true);
                                    jsonResult.Add(p);
                                });
                                return jsonResult;
                            }
                        };
                    }
                    else
                    {
                        string formatName = testConfiguration.Format == null ? "null" : testConfiguration.Format.GetType().Name;
                        throw new NotSupportedException("Invalid format detected: " + formatName);
                    }
                }));
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors.PayloadCases(WriterPayloads.EntryPayloads),
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent,
                (testDescriptor, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                if (testConfiguration.Format == ODataFormat.Json)
                {
                    if (testDescriptor.IsGeneratedPayload)
                    {
                        return;
                    }

                    // We need a model, entity set and entity type for JSON Light
                    testDescriptor = new PayloadWriterTestDescriptor <ODataItem>(testDescriptor)
                    {
                        Model = model,
                        PayloadEdmElementContainer = edmEntitySetCustermors,
                        PayloadEdmElementType      = edmEntityTypeCustomer,
                    };
                }

                TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger);
            });
        }
        public void AssociationLinkMetadataValidationTest()
        {
            EdmModel model = new EdmModel();

            var container = new EdmEntityContainer("TestModel", "Default");

            model.AddElement(container);

            var edmEntityTypeOrderType = new EdmEntityType("TestModel", "OrderType");

            model.AddElement(edmEntityTypeOrderType);

            var edmEntityTypeCustomerType = new EdmEntityType("TestModel", "CustomerType");

            edmEntityTypeCustomerType.AddKeys(new EdmStructuralProperty(edmEntityTypeCustomerType, "ID", EdmCoreModel.Instance.GetInt32(false)));
            edmEntityTypeCustomerType.AddStructuralProperty("PrimitiveProperty", EdmCoreModel.Instance.GetString(true));
            var edmNavigationPropertyAssociationLinkOne = edmEntityTypeCustomerType.AddUnidirectionalNavigation(
                new EdmNavigationPropertyInfo {
                Name = "Orders", Target = edmEntityTypeOrderType, TargetMultiplicity = EdmMultiplicity.Many
            });
            var edmNavigationPropertyAssociationLinkTwo = edmEntityTypeCustomerType.AddUnidirectionalNavigation(
                new EdmNavigationPropertyInfo {
                Name = "BestFriend", Target = edmEntityTypeCustomerType, TargetMultiplicity = EdmMultiplicity.One
            });

            model.AddElement(edmEntityTypeCustomerType);

            var edmEntityTypeOpenCustomerType = new EdmEntityType("TestModel", "OpenCustomerType", edmEntityTypeCustomerType, isAbstract: false, isOpen: true);

            model.AddElement(edmEntityTypeOpenCustomerType);

            var customerSet = container.AddEntitySet("Customers", edmEntityTypeCustomerType);
            var orderSet    = container.AddEntitySet("Orders", edmEntityTypeOrderType);

            customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkOne, orderSet);
            customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkTwo, customerSet);

            Uri associationLinkUrl = new Uri("http://odata.org/associationlink");

            var testCases = new[]
            {
                // Valid collection
                new
                {
                    TypeName          = "TestModel.CustomerType",
                    NavigationLink    = ObjectModelUtils.CreateDefaultCollectionLink("Orders"),
                    ExpectedException = (ExpectedException)null,
                },
                // Valid singleton
                new
                {
                    TypeName          = "TestModel.CustomerType",
                    NavigationLink    = ObjectModelUtils.CreateDefaultSingletonLink("BestFriend"),
                    ExpectedException = (ExpectedException)null,
                },
                // Undeclared on closed type
                new
                {
                    TypeName          = "TestModel.CustomerType",
                    NavigationLink    = ObjectModelUtils.CreateDefaultCollectionLink("NonExistant"),
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_PropertyDoesNotExistOnType", "NonExistant", "TestModel.CustomerType"),
                },
                // Undeclared on open type
                new
                {
                    TypeName          = "TestModel.OpenCustomerType",
                    NavigationLink    = ObjectModelUtils.CreateDefaultCollectionLink("NonExistant"),
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_OpenNavigationProperty", "NonExistant", "TestModel.OpenCustomerType"),
                },
                // Declared but of wrong kind
                new
                {
                    TypeName          = "TestModel.CustomerType",
                    NavigationLink    = ObjectModelUtils.CreateDefaultSingletonLink("PrimitiveProperty"),
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_NavigationPropertyExpected", "PrimitiveProperty", "TestModel.CustomerType", "Structural"),
                },
            };

            var testDescriptors = testCases.Select(testCase =>
            {
                ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                entry.TypeName      = testCase.TypeName;
                ODataNestedResourceInfo navigationLink = testCase.NavigationLink;
                navigationLink.AssociationLinkUrl      = associationLinkUrl;

                return(new PayloadWriterTestDescriptor <ODataItem>(
                           this.Settings,
                           new ODataItem[] { entry, navigationLink },
                           tc => (WriterTestExpectedResults) new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                {
                    ExpectedException2 = testCase.ExpectedException
                })
                {
                    Model = model,
                    PayloadEdmElementContainer = customerSet
                });
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.WriterTestConfigurationProvider.AtomFormatConfigurations
                .Where(testConfiguration => !testConfiguration.IsRequest),
                (testDescriptor, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger);
            });
        }
        public void AssociationLinkTest()
        {
            string associationLinkName1 = "AssociationLinkOne";
            string linkUrl1             = "http://odata.org/associationlink";
            Uri    linkUrlUri1          = new Uri(linkUrl1);
            string associationLinkName2 = "AssociationLinkTwo";
            string linkUrl2             = "http://odata.org/associationlink2";
            Uri    linkUrlUri2          = new Uri(linkUrl2);

            EdmModel model = new EdmModel();

            var edmEntityTypeOrderType = new EdmEntityType("TestModel", "OrderType");

            model.AddElement(edmEntityTypeOrderType);

            var edmEntityTypeCustomerType = new EdmEntityType("TestModel", "CustomerType");
            var edmNavigationPropertyAssociationLinkOne = edmEntityTypeCustomerType.AddUnidirectionalNavigation(
                new EdmNavigationPropertyInfo {
                Name = associationLinkName1, Target = edmEntityTypeOrderType, TargetMultiplicity = EdmMultiplicity.One
            });
            var edmNavigationPropertyAssociationLinkTwo = edmEntityTypeCustomerType.AddUnidirectionalNavigation(
                new EdmNavigationPropertyInfo {
                Name = associationLinkName2, Target = edmEntityTypeOrderType, TargetMultiplicity = EdmMultiplicity.Many
            });

            model.AddElement(edmEntityTypeCustomerType);

            var container = new EdmEntityContainer("TestModel", "Default");

            model.AddElement(container);

            var customerSet = container.AddEntitySet("Customers", edmEntityTypeCustomerType);
            var orderSet    = container.AddEntitySet("Orders", edmEntityTypeOrderType);

            customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkOne, orderSet);
            customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkTwo, orderSet);

            var testCases = new[]
            {
                new {
                    NavigationLink = ObjectModelUtils.CreateDefaultNavigationLink(associationLinkName1, linkUrlUri1),
                    Atom           = BuildXmlAssociationLink(associationLinkName1, "application/xml", linkUrl1),
                    JsonLight      = (string)null,
                },
                new {
                    NavigationLink = ObjectModelUtils.CreateDefaultNavigationLink(associationLinkName2, linkUrlUri2),
                    Atom           = BuildXmlAssociationLink(associationLinkName2, "application/xml", linkUrl2),
                    JsonLight      = (string)null
                },
            };

            var testCasesWithMultipleLinks = testCases.Variations()
                                             .Select(tcs =>
                                                     new
            {
                NavigationLinks = tcs.Select(tc => tc.NavigationLink),
                Atom            = string.Concat(tcs.Select(tc => tc.Atom)),
                JsonLight       = string.Join(",", tcs.Where(tc => tc.JsonLight != null).Select(tc => tc.JsonLight))
            });

            var testDescriptors = testCasesWithMultipleLinks.Select(testCase =>
            {
                ODataResource entry    = ObjectModelUtils.CreateDefaultEntry();
                entry.TypeName         = "TestModel.CustomerType";
                List <ODataItem> items = new ODataItem[] { entry }.ToList();
                foreach (var navLink in testCase.NavigationLinks)
                {
                    items.Add(navLink);
                    items.Add(null);
                }

                return(new PayloadWriterTestDescriptor <ODataItem>(
                           this.Settings,
                           items,
                           (testConfiguration) =>
                {
                    var firstAssocLink = testCase.NavigationLinks == null ? null : testCase.NavigationLinks.FirstOrDefault();
                    if (testConfiguration.Format == ODataFormat.Json)
                    {
                        return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                        {
                            Json = string.Join(
                                "$(NL)",
                                "{",
                                testCase.JsonLight,
                                "}"),
                            FragmentExtractor = (result) =>
                            {
                                var associationLinks = result.Object().GetAnnotationsWithName("@" + JsonLightConstants.ODataAssociationLinkUrlAnnotationName).ToList();
                                var jsonResult = new JsonObject();
                                associationLinks.ForEach(l =>
                                {
                                    // NOTE we remove all annoatations here and in particular the text annotations to be able to easily compare
                                    //      against the expected results. This however means that we do not distinguish between the indented and non-indented case here.
                                    l.RemoveAllAnnotations(true);
                                    jsonResult.Add(l);
                                });
                                return jsonResult;
                            },
                        };
                    }
                    else
                    {
                        this.Settings.Assert.Fail("Unknown format '{0}'.", testConfiguration.Format);
                        return null;
                    }
                })
                {
                    Model = model,
                    PayloadEdmElementContainer = customerSet
                });
            });

            // With and without model
            testDescriptors = testDescriptors.SelectMany(td =>
                                                         new[]
            {
                td,
                new PayloadWriterTestDescriptor <ODataItem>(td)
                {
                    Model = null,
                    PayloadEdmElementContainer = null
                }
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors.PayloadCases(WriterPayloads.EntryPayloads),
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent,
                (testDescriptor, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                if (testDescriptor.Model == null && testConfiguration.Format == ODataFormat.Json)
                {
                    return;
                }

                if (testDescriptor.IsGeneratedPayload && testDescriptor.Model != null)
                {
                    return;
                }

                TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger);
            });
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Returns all interesting payloads for an entry.
        /// </summary>
        /// <param name="testDescriptor">The test descriptor which will end up writing a single entry.</param>
        /// <returns>Enumeration of test descriptors which will include the original entry in some interesting scenarios.</returns>
        public static IEnumerable <PayloadWriterTestDescriptor <ODataItem> > EntryPayloads(PayloadWriterTestDescriptor <ODataItem> testDescriptor)
        {
            Debug.Assert(testDescriptor.PayloadItems[0] is ODataResource, "The payload does not specify an entry.");

            var payloadCases = new WriterPayloadCase <ODataItem>[]
            {
                // Feed with a single entry
                new WriterPayloadCase <ODataItem>()
                {
                    GetPayloadItems       = () => new ODataItem[] { ObjectModelUtils.CreateDefaultFeed() }.Concat(testDescriptor.PayloadItems),
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomEntryElementName).First());
                    },
                    //ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
                },

                // Feed with three (identical) entries, picking the second one
                new WriterPayloadCase <ODataItem>()
                {
                    GetPayloadItems = () => new ODataItem[]
                    {
                        ObjectModelUtils.CreateDefaultFeed()
                    }
                    .Concat(testDescriptor.PayloadItems)
                    .Concat(LinqExtensions.FromSingle((ODataItem)null))
                    .Concat(testDescriptor.PayloadItems)
                    .Concat(LinqExtensions.FromSingle((ODataItem)null))
                    .Concat(testDescriptor.PayloadItems)
                    .Concat(LinqExtensions.FromSingle((ODataItem)null)),
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        var entries = result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomEntryElementName);
                        Debug.Assert(entries.Count() == 3, "Expected three entries in the feed.");
                        return(entries.ElementAt(2));
                    },
                    //ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
                },

                // Top-level entry with an expanded link containing a single entry
                new WriterPayloadCase <ODataItem>()
                {
                    GetPayloadItems = () => new ODataItem[]
                    {
                        ObjectModelUtils.CreateDefaultEntry(),
                            ObjectModelUtils.CreateDefaultSingletonLink(),
                    }.Concat(testDescriptor.PayloadItems),
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                               .First(e => e.Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName) != null)
                               .Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomEntryElementName));
                    },
                    //ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
                },

                // Top-level entry with an expanded link containing a feed with a single entry
                new WriterPayloadCase <ODataItem>()
                {
                    GetPayloadItems = () => new ODataItem[]
                    {
                        ObjectModelUtils.CreateDefaultEntry(),
                            ObjectModelUtils.CreateDefaultCollectionLink(),
                            ObjectModelUtils.CreateDefaultFeed()
                    }.Concat(testDescriptor.PayloadItems),
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                               .First(e => e.Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName) != null)
                               .Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomFeedElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomEntryElementName));
                    },
                    //ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
                },

                // Top-level entry with an expanded link containing a feed with three entries; picking the second one
                new WriterPayloadCase <ODataItem>()
                {
                    GetPayloadItems = () => new ODataItem[]
                    {
                        ObjectModelUtils.CreateDefaultEntry(),
                            ObjectModelUtils.CreateDefaultCollectionLink(),
                            ObjectModelUtils.CreateDefaultFeed()
                    }
                    .Concat(testDescriptor.PayloadItems)
                    .Concat(LinqExtensions.FromSingle((ODataItem)null))
                    .Concat(testDescriptor.PayloadItems)
                    .Concat(LinqExtensions.FromSingle((ODataItem)null))
                    .Concat(testDescriptor.PayloadItems)
                    .Concat(LinqExtensions.FromSingle((ODataItem)null)),
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                               .First(e => e.Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName) != null)
                               .Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomFeedElementName)
                               .Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomEntryElementName)
                               .ElementAt(2));
                    },
                    //ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
                },

                // Top-level entry with an expanded link containing a feed with a single entry;
                // that entry has another expanded link containing a feed with the payload entry
                new WriterPayloadCase <ODataItem>()
                {
                    GetPayloadItems = () => new ODataItem[]
                    {
                        ObjectModelUtils.CreateDefaultEntry(),
                            ObjectModelUtils.CreateDefaultCollectionLink(),
                            ObjectModelUtils.CreateDefaultFeed(),
                            ObjectModelUtils.CreateDefaultEntry(),
                            ObjectModelUtils.CreateDefaultCollectionLink(),
                            ObjectModelUtils.CreateDefaultFeed(),
                    }.Concat(testDescriptor.PayloadItems),
                    AtomFragmentExtractor = (testConfiguration, result) =>
                    {
                        return(result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                               .First(e => e.Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName) != null)
                               .Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomFeedElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomEntryElementName)
                               .Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                               .First(e => e.Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName) != null)
                               .Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomFeedElementName)
                               .Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomEntryElementName));
                    },
                    //ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
                },
            };

            return(ApplyPayloadCases <ODataItem>(testDescriptor, payloadCases));
        }
Ejemplo n.º 25
0
        public void EntryMetadataWriterTest()
        {
            const string      testPublished = "2010-10-20T20:10:00Z";
            AtomTextConstruct testRights    = new AtomTextConstruct {
                Text = "Copyright Data Fx team."
            };
            AtomTextConstruct testSummary = new AtomTextConstruct {
                Text = "Test summary."
            };
            AtomTextConstruct testTitle = new AtomTextConstruct {
                Text = "Test title"
            };
            const string      testUpdated  = "2010-11-01T00:04:00Z";
            const string      testIcon     = "http://odata.org/icon";
            const string      testSourceId = "http://odata.org/id/random";
            const string      testLogo     = "http://odata.org/logo";
            AtomTextConstruct testSubtitle = new AtomTextConstruct {
                Text = "Test subtitle."
            };

            const string testAuthorName  = "Test Author 1";
            const string testAuthorEmail = "*****@*****.**";
            const string testAuthorUri   = "http://odata.org/authors/1";

            var testAuthors = new AtomPersonMetadata[]
            {
                new AtomPersonMetadata()
                {
                    Email = testAuthorEmail,
                    Name  = testAuthorName,
                    Uri   = new Uri(testAuthorUri)
                }
            };

            var testAuthors2 = new AtomPersonMetadata[0];

            const string testCategoryTerm   = "Test category 1 term";
            const string testCategoryLabel  = "Test category 1 label";
            const string testCategoryScheme = "http://odata.org/categories/1";

            var testCategories = new AtomCategoryMetadata[]
            {
                new AtomCategoryMetadata()
                {
                    Term   = testCategoryTerm,
                    Label  = testCategoryLabel,
                    Scheme = testCategoryScheme
                }
            };

            const string testContributorName  = "Test Contributor 1";
            const string testContributorEmail = "*****@*****.**";
            const string testContributorUri   = "http://odata.org/contributors/1";

            var testContributors = new AtomPersonMetadata[]
            {
                new AtomPersonMetadata()
                {
                    Email = testContributorEmail,
                    Name  = testContributorName,
                    Uri   = new Uri(testContributorUri)
                }
            };

            const string testGeneratorName    = "Test generator";
            const string testGeneratorUri     = "http://odata.org/generator";
            const string testGeneratorVersion = "3.0";

            var testGenerator = new AtomGeneratorMetadata()
            {
                Name    = testGeneratorName,
                Uri     = new Uri(testGeneratorUri),
                Version = testGeneratorVersion
            };

            const string testLinkRelation  = "http://odata.org/links/1";
            const string testLinkTitle     = "Test link 1";
            const string testLinkHref      = "http://odata.org/links/1";
            const string testLinkHrefLang  = "de-AT";
            int?         testLinkLength    = 999;
            const string testLinkMediaType = "image/png";

            var testLinks = new AtomLinkMetadata[]
            {
                new AtomLinkMetadata()
                {
                    Relation  = testLinkRelation,
                    Title     = testLinkTitle,
                    Href      = new Uri(testLinkHref),
                    HrefLang  = testLinkHrefLang,
                    Length    = testLinkLength,
                    MediaType = testLinkMediaType
                }
            };

            AtomFeedMetadata testSource = new AtomFeedMetadata()
            {
                Authors      = testAuthors,
                Categories   = testCategories,
                Contributors = testContributors,
                Generator    = testGenerator,
                Icon         = new Uri(testIcon),
                SourceId     = new Uri(testSourceId),
                Links        = testLinks,
                Logo         = new Uri(testLogo),
                Rights       = testRights,
                Subtitle     = testSubtitle,
                Title        = testTitle,
                Updated      = DateTimeOffset.Parse(testUpdated)
            };

            Func <string, Func <XElement, XElement> > fragmentExtractor = (localName) => (e) => e.Element(TestAtomConstants.AtomXNamespace + localName);

            // TODO, ckerer: specify an Id via metadata if the entry does not specify one; we first have to decide what rules
            //               we want to apply to merging of metadata and ODataLib OM data.
            var testCases = new[] {
                new { // specify an author via metadata
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Authors = testAuthors),
                    Xml = string.Join(
                        "$(NL)",
                        @"<author xmlns=""" + TestAtomConstants.AtomNamespace + @""">",
                        @"  <name>" + testAuthorName + @"</name>",
                        @"  <uri>" + testAuthorUri + @"</uri>",
                        @"  <email>" + testAuthorEmail + @"</email>",
                        @"</author>"),
                    Extractor = fragmentExtractor(TestAtomConstants.AtomAuthorElementName)
                },
                new { // specify an empty author array via metadata
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Authors = testAuthors2),
                    Xml = string.Join(
                        "$(NL)",
                        @"<author xmlns=""" + TestAtomConstants.AtomNamespace + @""">",
                        @"  <name />",
                        @"</author>"),
                    Extractor = fragmentExtractor(TestAtomConstants.AtomAuthorElementName)
                },
                new { // specify no authors via metadata
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Authors = null),
                    Xml = string.Join(
                        "$(NL)",
                        @"<author xmlns=""" + TestAtomConstants.AtomNamespace + @""">",
                        @"$(Indent)<name />",
                        @"</author>"),
                    Extractor = fragmentExtractor(TestAtomConstants.AtomAuthorElementName)
                },
                new { // specify a category via metadata
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Categories = testCategories),
                    Xml       = @"<category term=""" + testCategoryTerm + @""" scheme=""" + testCategoryScheme + @""" label=""" + testCategoryLabel + @""" xmlns=""" + TestAtomConstants.AtomNamespace + @""" />",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomCategoryElementName)
                },
                new { // specify a contributor via metadata
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Contributors = testContributors),
                    Xml = string.Join(
                        "$(NL)",
                        @"<contributor xmlns=""" + TestAtomConstants.AtomNamespace + @""">",
                        @"  <name>" + testContributorName + @"</name>",
                        @"  <uri>" + testContributorUri + @"</uri>",
                        @"  <email>" + testContributorEmail + @"</email>",
                        @"</contributor>"),
                    Extractor = fragmentExtractor(TestAtomConstants.AtomContributorElementName)
                },
                new { // specify a link via metadata
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Links = testLinks),
                    Xml       = @"<link rel=""" + testLinkRelation + @""" type = """ + testLinkMediaType + @""" title=""" + testLinkTitle + @""" href=""" + testLinkHref + @""" hreflang=""" + testLinkHrefLang + @""" length=""" + testLinkLength + @"""  xmlns=""" + TestAtomConstants.AtomNamespace + @"""/>",
                    Extractor = new Func <XElement, XElement>(
                        (e) => e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                        .Where(l => l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName).Value != TestAtomConstants.AtomSelfRelationAttributeValue)
                        .Single())
                },
                new { // specify a published date via metadata
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Published = DateTimeOffset.Parse(testPublished)),
                    Xml       = @"<published xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testPublished + @"</published>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomPublishedElementName)
                },
                new { // specify rights via metadata
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Rights = testRights),
                    Xml       = @"<rights type=""text"" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testRights.Text + @"</rights>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomRightsElementName)
                },
                new { // specify a source via metadata
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Source = testSource),
                    Xml = string.Join(
                        "$(NL)",
                        @"<source xmlns=""" + TestAtomConstants.AtomNamespace + @""">",
                        @"  <id>" + testSourceId + "</id>",
                        @"  <title type=""text"">" + testTitle.Text + @"</title>",
                        @"  <subtitle type=""text"">" + testSubtitle.Text + @"</subtitle>",
                        @"  <updated>" + testUpdated + @"</updated>",
                        @"  <link rel=""" + testLinkRelation + @""" type = """ + testLinkMediaType + @""" title=""" + testLinkTitle + @""" href=""" + testLinkHref + @""" hreflang=""" + testLinkHrefLang + @""" length=""" + testLinkLength + @"""/>",
                        @"  <category term=""" + testCategoryTerm + @""" scheme=""" + testCategoryScheme + @""" label=""" + testCategoryLabel + @""" />",
                        @"  <logo>" + testLogo + @"</logo>",
                        @"  <rights type=""text"">" + testRights.Text + @"</rights>",
                        @"  <contributor>",
                        @"    <name>" + testContributorName + @"</name>",
                        @"    <uri>" + testContributorUri + @"</uri>",
                        @"    <email>" + testContributorEmail + @"</email>",
                        @"  </contributor>",
                        @"  <generator uri=""" + testGeneratorUri + @""" version=""" + testGeneratorVersion + @""">" + testGeneratorName + @"</generator>",
                        @"  <icon>" + testIcon + @"</icon>",
                        @"  <author>",
                        @"    <name>" + testAuthorName + @"</name>",
                        @"    <uri>" + testAuthorUri + @"</uri>",
                        @"    <email>" + testAuthorEmail + @"</email>",
                        @"  </author>",
                        @"</source>"),
                    Extractor = fragmentExtractor(TestAtomConstants.AtomSourceElementName)
                },
                new { // specify default feed metadata as source
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Source = new AtomFeedMetadata()),
                    Xml = string.Join(
                        "$(NL)",
                        @"<source xmlns=""" + TestAtomConstants.AtomNamespace + @""">",
                        @"  <id />",
                        @"  <title />",
                        @"  <updated />",
                        @"</source>"),
                    Extractor = new Func <XElement, XElement>(result => {
                        var source = fragmentExtractor(TestAtomConstants.AtomSourceElementName)(result);
                        // Remove the value of updates as it can't be reliably predicted
                        source.Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomUpdatedElementName).Nodes().Remove();
                        return(source);
                    })
                },
                new { // specify a summary via metadata
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Summary = testSummary),
                    Xml       = @"<summary type=""text"" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testSummary.Text + @"</summary>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomSummaryElementName)
                },
                new { // specify a title via metadata
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Title = testTitle),
                    Xml       = @"<title type=""text"" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testTitle.Text + @"</title>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomTitleElementName)
                },
                new { // specify an updated date via metadata
                    CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Updated = DateTimeOffset.Parse(testUpdated)),
                    Xml       = @"<updated xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testUpdated + @"</updated>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomUpdatedElementName)
                },
            };

            // Convert test cases to test descriptions
            IEnumerable <Func <ODataEntry> > entryCreators = new Func <ODataEntry>[]
            {
                () => ObjectModelUtils.CreateDefaultEntry(),
                () => ObjectModelUtils.CreateDefaultEntryWithAtomMetadata(),
            };
            var testDescriptors = testCases.SelectMany(testCase =>
                                                       entryCreators.Select(entryCreator =>
            {
                ODataEntry entry           = entryCreator();
                AtomEntryMetadata metadata = entry.Atom();
                this.Assert.IsNotNull(metadata, "Expected default entry metadata on a default entry.");
                testCase.CustomizeMetadata(metadata);
                return(new PayloadWriterTestDescriptor <ODataItem>(this.Settings, entry, testConfiguration =>
                                                                   new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                {
                    Xml = testCase.Xml, FragmentExtractor = testCase.Extractor
                }));
            }));

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors.PayloadCases(WriterPayloads.EntryPayloads),
                this.WriterTestConfigurationProvider.AtomFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger);
            });
        }
Ejemplo n.º 26
0
        public void ExpandedLinkWithNullNavigationTests()
        {
            ODataNavigationLink expandedEntryLink = ObjectModelUtils.CreateDefaultCollectionLink();

            expandedEntryLink.IsCollection = false;

            ODataNavigationLink expandedEntryLink2 = ObjectModelUtils.CreateDefaultCollectionLink();

            expandedEntryLink2.IsCollection = false;
            expandedEntryLink2.Name         = expandedEntryLink2.Name + "2";

            ODataEntry defaultEntry = ObjectModelUtils.CreateDefaultEntry();
            ODataFeed  defaultFeed  = ObjectModelUtils.CreateDefaultFeed();
            ODataEntry nullEntry    = ObjectModelUtils.ODataNullEntry;

            PayloadWriterTestDescriptor.WriterTestExpectedResultCallback successCallback = (testConfiguration) =>
            {
                if (testConfiguration.Format == ODataFormat.Atom)
                {
                    return(new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        Xml = new XElement(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName).ToString(),
                        FragmentExtractor = (result) =>
                        {
                            return result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                            .First(e => e.Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName) != null)
                            .Element(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.ODataInlineElementName);
                        }
                    });
                }
                else
                {
                    return(new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        Json = "null", //new JsonPrimitiveValue(null).ToText(testConfiguration.MessageWriterSettings.Indent),
                        FragmentExtractor = (result) =>
                        {
                            return JsonUtils.UnwrapTopLevelValue(testConfiguration, result).Object().Properties.First(p => p.Name == ObjectModelUtils.DefaultLinkName).Value;
                        }
                    });
                }
            };

            Func <ExpectedException, PayloadWriterTestDescriptor.WriterTestExpectedResultCallback> errorCallback = (expectedException) =>
            {
                return((testConfiguration) =>
                {
                    return new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException2 = expectedException,
                    };
                });
            };

            var testCases = new PayloadWriterTestDescriptor <ODataItem>[]
            {
                // navigation to a null entry
                new PayloadWriterTestDescriptor <ODataItem>(
                    this.Settings,
                    new ODataItem[] { defaultEntry, expandedEntryLink, nullEntry },
                    successCallback),

                // navigation to a null entry twice
                new PayloadWriterTestDescriptor <ODataItem>(
                    this.Settings,
                    new ODataItem[] { defaultEntry, expandedEntryLink, nullEntry, null, null, expandedEntryLink2, nullEntry, null },
                    successCallback),

                // top level null entry.
                new PayloadWriterTestDescriptor <ODataItem>(
                    this.Settings,
                    new ODataItem[] { nullEntry },
                    errorCallback(new ExpectedException(typeof(ArgumentNullException)))),

                // navigation to a null entry twice in expanded link
                // this actually throws ArgumentNullException when WriteStart() for the second nullEntry is called since
                // the state has been changed from NavigationLink to ExpandedLink after the first one.
                // TODO: check if ArgumentNullException needs to change the WriterState.
                new PayloadWriterTestDescriptor <ODataItem>(
                    this.Settings,
                    new ODataItem[] { defaultEntry, expandedEntryLink, nullEntry, null, nullEntry },
                    errorCallback(new ExpectedException(typeof(ArgumentNullException)))),

                // Null entry inside a feed, same as above this throws ArgumentNullException but state is not put to error state.
                new PayloadWriterTestDescriptor <ODataItem>(
                    this.Settings,
                    new ODataItem[] { defaultFeed, nullEntry },
                    errorCallback(new ExpectedException(typeof(ArgumentNullException)))),
            };

            // TODO: Fix places where we've lost JsonVerbose coverage to add JsonLight
            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent.Where(tc => tc.Format == ODataFormat.Atom),
                (testCase, testConfig) =>
            {
                testConfig = testConfig.Clone();
                testConfig.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                TestWriterUtils.WriteAndVerifyODataPayload(testCase, testConfig, this.Assert, this.Logger);
            });
        }
        public void EntityReferenceLinkValidationTest()
        {
            var testCases = new[] {
                new {
                    InvalidateEntityReferenceLink = new Action <ODataEntityReferenceLink>(entityReferenceLink => entityReferenceLink.Url = null),
                    ExpectedException             = ODataExpectedExceptions.ODataException("WriterValidationUtils_EntityReferenceLinkUrlMustNotBeNull"),
                },
            };

            var testDescriptors = testCases.SelectMany(testCase =>
            {
                ODataEntityReferenceLink entityReferenceLink = ObjectModelUtils.CreateDefaultEntityReferenceLink();
                testCase.InvalidateEntityReferenceLink(entityReferenceLink);
                ODataEntityReferenceLinks entityReferenceLinks = ObjectModelUtils.CreateDefaultEntityReferenceLinks();
                testCase.InvalidateEntityReferenceLink(entityReferenceLinks.Links.First());

                return(new PayloadWriterTestDescriptor[]
                {
                    // Top level entity reference link
                    new PayloadWriterTestDescriptor <ODataEntityReferenceLink>(
                        this.Settings,
                        entityReferenceLink,
                        testConfiguration => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException2 = testCase.ExpectedException
                    }),
                    // Entity reference link in entity reference links
                    new PayloadWriterTestDescriptor <ODataEntityReferenceLinks>(
                        this.Settings,
                        entityReferenceLinks,
                        testConfiguration => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        // Top-level EntityReferenceLinks payload write requests are not allowed.
                        ExpectedException2 = testConfiguration.IsRequest ?
                                             ODataExpectedExceptions.ODataException("ODataMessageWriter_EntityReferenceLinksInRequestNotAllowed") : testCase.ExpectedException
                    }),
                    new PayloadWriterTestDescriptor <ODataItem>(
                        this.Settings,
                        new ODataItem[] { ObjectModelUtils.CreateDefaultEntry(), ObjectModelUtils.CreateDefaultSingletonLink(), entityReferenceLink, null, null },
                        testConfiguration => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException2 = testConfiguration.IsRequest ? testCase.ExpectedException : ODataExpectedExceptions.ODataException("ODataWriterCore_EntityReferenceLinkInResponse")
                    }),
                });
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.WriterTestConfigurationProvider.AtomFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                PayloadWriterTestDescriptor <ODataEntityReferenceLink> entityReferenceLinkTestDescriptor = testDescriptor as PayloadWriterTestDescriptor <ODataEntityReferenceLink>;
                if (entityReferenceLinkTestDescriptor != null)
                {
                    TestWriterUtils.WriteAndVerifyTopLevelContent(
                        entityReferenceLinkTestDescriptor,
                        testConfiguration,
                        (messageWriter) => messageWriter.WriteEntityReferenceLink(entityReferenceLinkTestDescriptor.PayloadItems.Single()),
                        this.Assert,
                        baselineLogger: this.Logger);
                    return;
                }

                PayloadWriterTestDescriptor <ODataEntityReferenceLinks> entityReferenceLinksTestDescriptor = testDescriptor as PayloadWriterTestDescriptor <ODataEntityReferenceLinks>;
                if (entityReferenceLinksTestDescriptor != null)
                {
                    TestWriterUtils.WriteAndVerifyTopLevelContent(
                        entityReferenceLinksTestDescriptor,
                        testConfiguration,
                        (messageWriter) => messageWriter.WriteEntityReferenceLinks(entityReferenceLinksTestDescriptor.PayloadItems.Single()),
                        this.Assert,
                        baselineLogger: this.Logger);
                    return;
                }

                TestWriterUtils.WriteAndVerifyODataPayload((PayloadWriterTestDescriptor <ODataItem>)testDescriptor, testConfiguration, this.Assert, this.Logger);
            });
        }
Ejemplo n.º 28
0
        public void ExpandedLinkWithMultiplicityTests()
        {
            ODataNavigationLink expandedEntryLink = ObjectModelUtils.CreateDefaultCollectionLink();

            expandedEntryLink.IsCollection = false;

            ODataNavigationLink expandedFeedLink = ObjectModelUtils.CreateDefaultCollectionLink();

            expandedFeedLink.IsCollection = true;

            ODataEntry defaultEntry = ObjectModelUtils.CreateDefaultEntry();
            ODataFeed  defaultFeed  = ObjectModelUtils.CreateDefaultFeed();
            ODataEntityReferenceLink defaultEntityReferenceLink = ObjectModelUtils.CreateDefaultEntityReferenceLink();

            ODataEntry officeEntry           = ObjectModelUtils.CreateDefaultEntry("TestModel.OfficeType");
            ODataEntry officeWithNumberEntry = ObjectModelUtils.CreateDefaultEntry("TestModel.OfficeWithNumberType");
            ODataEntry cityEntry             = ObjectModelUtils.CreateDefaultEntry("TestModel.CityType");

            // CityHall is a nav prop with multiplicity '*' of type 'TestModel.OfficeType'
            ODataNavigationLink cityHallLinkIsCollectionNull  = ObjectModelUtils.CreateDefaultCollectionLink("CityHall", /*isCollection*/ null);
            ODataNavigationLink cityHallLinkIsCollectionTrue  = ObjectModelUtils.CreateDefaultCollectionLink("CityHall", /*isCollection*/ true);
            ODataNavigationLink cityHallLinkIsCollectionFalse = ObjectModelUtils.CreateDefaultCollectionLink("CityHall", /*isCollection*/ false);

            // PoliceStation is a nav prop with multiplicity '1' of type 'TestModel.OfficeType'
            ODataNavigationLink policeStationLinkIsCollectionNull  = ObjectModelUtils.CreateDefaultCollectionLink("PoliceStation", /*isCollection*/ null);
            ODataNavigationLink policeStationLinkIsCollectionTrue  = ObjectModelUtils.CreateDefaultCollectionLink("PoliceStation", /*isCollection*/ true);
            ODataNavigationLink policeStationLinkIsCollectionFalse = ObjectModelUtils.CreateDefaultCollectionLink("PoliceStation", /*isCollection*/ false);

            ExpectedException expandedEntryLinkWithFeedContentError  = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedContent", "http://odata.org/link");
            ExpectedException expandedFeedLinkWithEntryContentError  = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryContent", "http://odata.org/link");
            ExpectedException expandedFeedLinkWithEntryMetadataError = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryMetadata", "http://odata.org/link");

            ExpectedException expandedEntryLinkWithFeedMetadataErrorResponse        = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedMetadata", "http://odata.org/link");
            ExpectedException expandedFeedLinkPayloadWithEntryMetadataErrorRequest  = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkWithFeedPayloadAndEntryMetadata", "http://odata.org/link");
            ExpectedException expandedFeedLinkPayloadWithEntryMetadataErrorResponse = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryMetadata", "http://odata.org/link");
            ExpectedException expandedEntryLinkPayloadWithFeedMetadataErrorResponse = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedMetadata", "http://odata.org/link");
            ExpectedException expandedEntryLinkPayloadWithFeedMetadataError         = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkWithEntryPayloadAndFeedMetadata", "http://odata.org/link");
            ExpectedException multipleItemsInExpandedLinkError   = ODataExpectedExceptions.ODataException("ODataWriterCore_MultipleItemsInNavigationLinkContent", "http://odata.org/link");
            ExpectedException entityReferenceLinkInResponseError = ODataExpectedExceptions.ODataException("ODataWriterCore_EntityReferenceLinkInResponse");

            IEdmModel model = Microsoft.Test.OData.Utils.Metadata.TestModels.BuildTestModel();

            var testCases = new ExpandedLinkMultiplicityTestCase[]
            {
                #region IsCollection flag does not match payload
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link with IsCollection is 'false' and feed payload
                    Items         = new ODataItem[] { defaultEntry, expandedEntryLink, defaultFeed },
                    ExpectedError = tc => expandedEntryLinkWithFeedContentError,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link with IsCollection is 'true' and entry payload
                    Items         = new ODataItem[] { defaultEntry, expandedFeedLink, defaultEntry },
                    ExpectedError = tc => expandedFeedLinkWithEntryContentError,
                },
                #endregion IsCollection flag does not match payload
                #region IsCollection == null; check compatibility of entity types of navigation property and entity in expanded link
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link of singleton type without IsCollection value and an entry of a non-matching entity type;
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, cityEntry },
                    ExpectedError = tc => tc.Format == ODataFormat.Atom || !tc.IsRequest
                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_EntryTypeInExpandedLinkNotCompatibleWithNavigationPropertyType", "TestModel.CityType", "TestModel.OfficeType")
                            : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "PoliceStation"),
                    Model = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link of singleton type without IsCollection value and an entry of a matching entity type; no error expected.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, officeEntry },
                    ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest ? null : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "PoliceStation"),
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link of singleton type without IsCollection and an entry of a derived entity type; no error expected.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, officeWithNumberEntry },
                    ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest ? null : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "PoliceStation"),
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link of collection type without IsCollection value and an entry of a non-matching entity type;
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, defaultFeed, cityEntry },
                    ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest
                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_EntryTypeInExpandedLinkNotCompatibleWithNavigationPropertyType", "TestModel.CityType", "TestModel.OfficeType")
                            : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "CityHall"),
                    Model = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link of collection type without IsCollection value and an entry of a matching entity type; no error expected.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, defaultFeed, officeEntry },
                    ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest
                            ? null
                            : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "CityHall"),
                    Model = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link of collection type without IsCollection and an entry of a derived entity type; no error expected.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, defaultFeed, officeWithNumberEntry },
                    ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest
                            ? null
                            : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "CityHall"),
                    Model = model,
                },
                #endregion IsCollection == null; check compatibility of entity types of navigation property and entity in expanded link
                #region Expanded link with entry content
                new ExpandedLinkMultiplicityTestCase
                {
                    // Entry content, IsCollection == false, singleton nav prop; should not fail.
                    Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionFalse, officeEntry },
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Entry content, IsCollection == true, singleton nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionTrue, officeEntry },
                    ExpectedError = tc => expandedFeedLinkWithEntryContentError,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Entry content, IsCollection == false, collection nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionFalse, officeEntry },
                    ExpectedError = tc => tc.IsRequest ? expandedEntryLinkPayloadWithFeedMetadataError : expandedEntryLinkPayloadWithFeedMetadataErrorResponse,
                    Model         = model
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Entry content, IsCollection == true, collection nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionTrue, officeEntry },
                    ExpectedError = tc => expandedFeedLinkWithEntryContentError,
                    Model         = model
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Entry content, IsCollection == null, singleton nav prop; should not fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, officeEntry },
                    ExpectedError = tc => tc.IsRequest || tc.Format == ODataFormat.Atom
                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "PoliceStation")
                            : null,
                    Model = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Entry content, IsCollection == null, collection nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, officeEntry },
                    ExpectedError = tc => expandedEntryLinkPayloadWithFeedMetadataError,
                    Model         = model,
                },
                #endregion Expanded collection link with entry content
                #region Expanded link with feed content
                new ExpandedLinkMultiplicityTestCase
                {
                    // Feed content, IsCollection == false, singleton nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionFalse, defaultFeed, officeEntry },
                    ExpectedError = tc => expandedEntryLinkWithFeedContentError,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Feed content, IsCollection == true, singleton nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionTrue, defaultFeed, officeEntry },
                    ExpectedError = tc => tc.IsRequest ? expandedFeedLinkPayloadWithEntryMetadataErrorRequest : expandedFeedLinkPayloadWithEntryMetadataErrorResponse,
                    Model         = model
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Feed content, IsCollection == false, collection nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionFalse, defaultFeed, officeEntry },
                    ExpectedError = tc => tc.IsRequest ? expandedEntryLinkWithFeedContentError : expandedEntryLinkWithFeedMetadataErrorResponse,
                    Model         = model
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Feed content, IsCollection == true, collection nav prop; should not fail.
                    Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionTrue, defaultFeed, officeEntry },
                    Model = model
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Feed content, IsCollection == null, singleton nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, defaultFeed, officeEntry },
                    ExpectedError = tc => expandedFeedLinkPayloadWithEntryMetadataErrorRequest,
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Feed content, IsCollection == null, collection nav prop; should not fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, defaultFeed, officeEntry },
                    ExpectedError = tc => tc.IsRequest || tc.Format == ODataFormat.Atom
                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "CityHall")
                            : null,
                    Model = model,
                },
                #endregion Expanded collection link with entry content
                #region Expanded link with entity reference link content
                new ExpandedLinkMultiplicityTestCase
                {
                    // Single ERL (entity reference link) content, IsCollection == false, singleton nav prop; should not fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionFalse, defaultEntityReferenceLink },
                    ExpectedError = tc => tc.IsRequest ? null : entityReferenceLinkInResponseError
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Multiple ERL (entity reference link) content, IsCollection == false, singleton nav prop; should not fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionFalse, defaultEntityReferenceLink, defaultEntityReferenceLink },
                    ExpectedError = tc => tc.IsRequest ? multipleItemsInExpandedLinkError : entityReferenceLinkInResponseError,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Single ERL content, IsCollection == true, singleton nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionTrue, defaultEntityReferenceLink },
                    ExpectedError = tc => expandedFeedLinkWithEntryMetadataError,
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Multiple ERL content, IsCollection == true, singleton nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionTrue, defaultEntityReferenceLink, defaultEntityReferenceLink },
                    ExpectedError = tc => expandedFeedLinkWithEntryMetadataError,
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Single ERL content, IsCollection == false, collection nav prop; should not fail (metadata mismatch explicitly allowed).
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionFalse, defaultEntityReferenceLink },
                    ExpectedError = tc => tc.IsRequest ? null : expandedEntryLinkWithFeedMetadataErrorResponse,
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Multiple ERL content, IsCollection == false, collection nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionFalse, defaultEntityReferenceLink, defaultEntityReferenceLink },
                    ExpectedError = tc => tc.IsRequest ? multipleItemsInExpandedLinkError : expandedEntryLinkWithFeedMetadataErrorResponse,
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Single ERL content, IsCollection == true, collection nav prop; should not fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionTrue, defaultEntityReferenceLink },
                    ExpectedError = tc => tc.IsRequest ? null : entityReferenceLinkInResponseError,
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Multiple ERL content, IsCollection == true, collection nav prop; should not fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionTrue, defaultEntityReferenceLink, defaultEntityReferenceLink },
                    ExpectedError = tc => tc.IsRequest ? null : entityReferenceLinkInResponseError,
                    Model         = model,
                },

                //// NOTE: Not testing the cases where IsCollection == null here since ERL payloads are only allowed in
                ////       requests where IsCollection is required (in ATOM and JSON)
                #endregion Expanded link with entity reference link content
            };

            // TODO: Fix places where we've lost JsonVerbose coverage to add JsonLight
            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurations.Where(tc => tc.Format == ODataFormat.Atom),
                (testCase, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                using (var memoryStream = new TestStream())
                    using (var messageWriter = TestWriterUtils.CreateMessageWriter(memoryStream, testConfiguration, this.Assert, null, testCase.Model))
                    {
                        ODataWriter writer = messageWriter.CreateODataWriter(isFeed: false);
                        TestExceptionUtils.ExpectedException(
                            this.Assert,
                            () => TestWriterUtils.WritePayload(messageWriter, writer, true, testCase.Items),
                            testCase.ExpectedError == null ? null : testCase.ExpectedError(testConfiguration),
                            this.ExceptionVerifier);
                    }
            });
        }
Ejemplo n.º 29
0
        public void BaseUriErrorTest()
        {
            Uri baseUri = new Uri("http://odata.org");
            Uri testUri = new Uri("http://odata.org/relative");
            IEnumerable <Func <Uri, BaseUriErrorTestCase> > testCaseFuncs = new Func <Uri, BaseUriErrorTestCase>[]
            {
                relativeUri => new BaseUriErrorTestCase
                {   // next page link
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataResourceSet feed = ObjectModelUtils.CreateDefaultFeed();
                        feed.NextPageLink     = relativeUri;
                        return(new [] { feed });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // entry read link
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        entry.ReadLink      = relativeUri;
                        return(new [] { entry });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // entry edit link
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        entry.EditLink      = relativeUri;
                        return(new [] { entry });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // media resource (default stream) read link
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataStreamReferenceValue mediaResource = new ODataStreamReferenceValue();
                        mediaResource.ContentType = "image/jpg";
                        mediaResource.ReadLink    = relativeUri;
                        ODataResource entry       = ObjectModelUtils.CreateDefaultEntry();
                        entry.MediaResource       = mediaResource;
                        return(new [] { entry });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // media resource (default stream) edit link
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataStreamReferenceValue mediaResource = new ODataStreamReferenceValue();
                        mediaResource.ContentType = "image/jpg";    // required
                        mediaResource.ReadLink    = testUri;        // required
                        mediaResource.EditLink    = relativeUri;
                        ODataResource entry       = ObjectModelUtils.CreateDefaultEntry();
                        entry.MediaResource       = mediaResource;
                        return(new [] { entry });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // link Url
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataNestedResourceInfo link = ObjectModelUtils.CreateDefaultCollectionLink();
                        link.Url = relativeUri;

                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        return(new ODataItem[] { entry, link });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // association link Url
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataNestedResourceInfo link = ObjectModelUtils.CreateDefaultSingletonLink();
                        link.AssociationLinkUrl      = relativeUri;

                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        return(new ODataItem[] { entry, link });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // named stream read link
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataStreamReferenceValue namedStream = new ODataStreamReferenceValue()
                        {
                            ContentType = "image/jpg",
                            ReadLink    = relativeUri,
                        };
                        ODataResource entry    = ObjectModelUtils.CreateDefaultEntry();
                        ODataProperty property = new ODataProperty()
                        {
                            Name  = "NamedStream",
                            Value = namedStream
                        };

                        entry.Properties = new[] { property };
                        return(new [] { entry });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // named stream edit link
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataStreamReferenceValue namedStream = new ODataStreamReferenceValue()
                        {
                            ContentType = "image/jpg",
                            ReadLink    = testUri,
                            EditLink    = relativeUri
                        };
                        ODataResource entry    = ObjectModelUtils.CreateDefaultEntry();
                        ODataProperty property = new ODataProperty()
                        {
                            Name  = "NamedStream",
                            Value = namedStream
                        };

                        entry.Properties = new[] { property };
                        return(new [] { entry });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // Atom metadata: feed generator Uri
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataResourceSet feed = ObjectModelUtils.CreateDefaultFeed();
                        return(new [] { feed });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // Atom metadata: feed logo
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataResourceSet feed = ObjectModelUtils.CreateDefaultFeed();
                        return(new [] { feed });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // Atom metadata: feed icon
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataResourceSet feed = ObjectModelUtils.CreateDefaultFeed();
                        return(new [] { feed });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // Atom metadata: feed author
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataResourceSet feed = ObjectModelUtils.CreateDefaultFeed();
                        return(new [] { feed });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // Atom metadata: feed contributor
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataResourceSet feed = ObjectModelUtils.CreateDefaultFeed();
                        return(new [] { feed });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // Atom metadata: feed link
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataResourceSet feed = ObjectModelUtils.CreateDefaultFeed();
                        return(new [] { feed });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // Atom metadata: entry author
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        return(new [] { entry });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // Atom metadata: entry contributor
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        return(new [] { entry });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
                relativeUri => new BaseUriErrorTestCase
                {   // Atom metadata: entry link
                    ItemFunc = new Func <IEnumerable <ODataItem> >(() =>
                    {
                        ODataResource entry = ObjectModelUtils.CreateDefaultEntry();
                        return(new [] { entry });
                    }),
                    Formats = new [] { ODataFormat.Json }
                },
            };

            // ToDo: Fix places where we've lost JsonVerbose coverage to add JsonLight
            Uri testRelativeUri    = baseUri.MakeRelativeUri(testUri);
            Uri invalidRelativeUri = new Uri("../invalid/relative/uri", UriKind.Relative);

            this.CombinatorialEngineProvider.RunCombinations(
                testCaseFuncs,
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurations.Where(c => false),
                new Uri[] { testRelativeUri, invalidRelativeUri },
                new bool[] { false, true },
                (testCaseFunc, testConfiguration, uri, implementUrlResolver) =>
            {
                var testCase       = testCaseFunc(uri);
                var testDescriptor = new
                {
                    Descriptor = new PayloadWriterTestDescriptor <ODataItem>(
                        this.Settings,
                        testCase.ItemFunc(),
                        testConfig => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException2 = ODataExpectedExceptions.ODataException("ODataWriter_RelativeUriUsedWithoutBaseUriSpecified", uri.OriginalString)
                    }),
                    Formats = testCase.Formats
                };

                if (testDescriptor.Formats.Contains(testConfiguration.Format))
                {
                    PayloadWriterTestDescriptor <ODataItem> payloadTestDescriptor = testDescriptor.Descriptor;
                    TestUrlResolver urlResolver = null;
                    if (implementUrlResolver)
                    {
                        payloadTestDescriptor             = new PayloadWriterTestDescriptor <ODataItem>(payloadTestDescriptor);
                        urlResolver                       = new TestUrlResolver();
                        payloadTestDescriptor.UrlResolver = urlResolver;
                    }

                    testConfiguration = testConfiguration.Clone();
                    testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                    TestWriterUtils.WriteAndVerifyODataPayload(payloadTestDescriptor, testConfiguration, this.Assert, this.Logger);

                    if (implementUrlResolver)
                    {
                        this.Assert.AreEqual(1, urlResolver.Calls.Where(call => call.Value.OriginalString == uri.OriginalString).Count(), "The resolver should be called exactly once for each URL.");
                    }
                }
            });
        }
Ejemplo n.º 30
0
        public void FeedAndEntryUpdatedTimeTests()
        {
            ODataFeed defaultFeedWithEmptyMetadata = ObjectModelUtils.CreateDefaultFeed();

            defaultFeedWithEmptyMetadata.SetAnnotation <AtomFeedMetadata>(new AtomFeedMetadata());
            ODataEntry defaultEntryWithEmptyMetadata = ObjectModelUtils.CreateDefaultEntry();

            defaultEntryWithEmptyMetadata.SetAnnotation <AtomEntryMetadata>(new AtomEntryMetadata());

            IEnumerable <PayloadWriterTestDescriptor <ODataItem> > testPayloads =
                new[]
            {
                new PayloadWriterTestDescriptor <ODataItem>(this.Settings, ObjectModelUtils.CreateDefaultFeed()),
                new PayloadWriterTestDescriptor <ODataItem>(this.Settings, defaultFeedWithEmptyMetadata),
                new PayloadWriterTestDescriptor <ODataItem>(this.Settings, ObjectModelUtils.CreateDefaultFeedWithAtomMetadata()),
            }.PayloadCases(WriterPayloads.FeedPayloads)
            .Concat((new[]
            {
                new PayloadWriterTestDescriptor <ODataItem>(this.Settings, ObjectModelUtils.CreateDefaultEntry()),
                new PayloadWriterTestDescriptor <ODataItem>(this.Settings, defaultEntryWithEmptyMetadata),
                new PayloadWriterTestDescriptor <ODataItem>(this.Settings, ObjectModelUtils.CreateDefaultEntryWithAtomMetadata()),
            }.PayloadCases(WriterPayloads.EntryPayloads)));

            this.CombinatorialEngineProvider.RunCombinations(
                testPayloads,
                this.WriterTestConfigurationProvider.AtomFormatConfigurationsWithIndent.Where(tc => !tc.IsRequest),
                (testPayload, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                string lastUpdatedTimeStr = null;
                using (var memoryStream = new MemoryStream())
                {
                    using (var testMemoryStream = TestWriterUtils.CreateTestStream(testConfiguration, memoryStream, ignoreDispose: true))
                    {
                        bool feedWriter         = testPayload.PayloadItems[0] is ODataFeed;
                        TestMessage testMessage = null;
                        Exception exception     = TestExceptionUtils.RunCatching(() =>
                        {
                            using (var messageWriter = TestWriterUtils.CreateMessageWriter(testMemoryStream, testConfiguration, this.Assert, out testMessage, null, testPayload.Model))
                            {
                                ODataWriter writer = messageWriter.CreateODataWriter(feedWriter);
                                TestWriterUtils.WritePayload(messageWriter, writer, true, testPayload.PayloadItems, testPayload.ThrowUserExceptionAt);
                            }
                        });
                        this.Assert.IsNull(exception, "Received exception but expected none.");
                    }

                    memoryStream.Position = 0;
                    XElement result       = XElement.Load(memoryStream);
                    foreach (XElement updated in result.Descendants(((XNamespace)TestAtomConstants.AtomNamespace) + "updated"))
                    {
                        if (updated.Value != ObjectModelUtils.DefaultFeedUpdated && updated.Value != ObjectModelUtils.DefaultEntryUpdated)
                        {
                            if (lastUpdatedTimeStr == null)
                            {
                                lastUpdatedTimeStr = updated.Value;
                            }
                            else
                            {
                                this.Assert.AreEqual(lastUpdatedTimeStr, updated.Value, "<atom:updated> should contain the same value.");
                            }
                        }
                    }
                }
            });
        }