public void ServiceDocumentReaderWithAtomMetadataTest()
        {
            IEnumerable<PayloadReaderTestDescriptor> testDescriptors = new PayloadReaderTestDescriptor[]
            {
                #region tests related to atom:title
                
                // Verify that a title inside a collection is read into the Name property and (if ATOM metadata reading is enabled) the Title property of the metadata annotation.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace().ResourceCollection("Products", baseUri + "Products"))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                            xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                            <workspace>
                                                <collection href='" + baseUri + @"Products'>
                                                    <atom:title>Products</atom:title>
                                                </collection>
                                            </workspace>
                                            </service>"),
                },

                // Title inside a workspace should be read when ATOM metadata reading is on, but ignored otherwise.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace()
                            .AtomTitle("Default", TestAtomConstants.AtomTextConstructTextKind)
                            .ResourceCollection("Products", baseUri + "Products"))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                <workspace>
                                                    <atom:title>Default</atom:title>
                                                    <collection href='" + baseUri + @"Products'>
                                                        <atom:title>Products</atom:title>
                                                    </collection>
                                                </workspace>
                                             </service>"),
                },

                // Multiple atom:title elements inside the collection element should throw when metadata reading is both on and off.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace().ResourceCollection(null, baseUri + "Products"))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                    xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                    <workspace>
                                                        <collection href='" + baseUri + @"Products'>
                                                            <atom:title>Products</atom:title>
                                                            <atom:title>Products</atom:title>   
                                                        </collection>
                                                    </workspace>
                                                 </service>"),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomServiceDocumentMetadataDeserializer_MultipleTitleElementsFound", "collection"),
                },
                
                #endregion tests related to atom:title

                #region app:collection element

                // Collection element with no children.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace().ResourceCollection(null, baseUri + "Products"))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                <workspace>
                                                    <collection href='" + baseUri + @"Products'>
                                                    </collection>
                                                </workspace>
                                                </service>"),
                },
                
                // Empty collection element.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace().ResourceCollection(null, baseUri + "Products"))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                <workspace>
                                                    <collection href='" + baseUri + @"Products' />
                                                </workspace>
                                                </service>"),
                },

                // Multiple collections
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace()
                            .AtomTitle("Default", TestAtomConstants.AtomTextConstructTextKind)
                            .ResourceCollection(
                                PayloadBuilder.ResourceCollection("Collection1", baseUri + "Collection1")
                                    .AppAccept("image/png")
                                    .AppOutOfLineCategories("http://somecategories.com"))
                            .ResourceCollection(
                                PayloadBuilder.ResourceCollection("Collection2", baseUri + "Collection2")
                                    .AppAccept("image/gif")
                                    .AppOutOfLineCategories("http://othercategories.com")))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                <workspace>
                                                    <atom:title>Default</atom:title>
                                                    <collection href='" + baseUri + @"Collection1'>
                                                        <atom:title>Collection1</atom:title>
                                                        <accept>image/png</accept>
                                                        <categories href='http://somecategories.com'/>
                                                    </collection>
                                                    <collection href='" + baseUri + @"Collection2'>
                                                        <atom:title>Collection2</atom:title>
                                                        <accept>image/gif</accept>
                                                        <categories href='http://othercategories.com'/>
                                                    </collection>
                                                </workspace>
                                             </service>"),
                },

                #endregion app:collection element

                #region app:accept and app:categories element 

                // app:accept and app:categories element inside the collection element.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace()
                            .ResourceCollection(
                                PayloadBuilder.ResourceCollection("Products", baseUri + "Products")
                                    .AppAccept("application/atom+xml;type=entry")
                                    .AppInlineCategories("yes", null,
                                        AtomMetadataBuilder.AtomCategory("SomeTerm", "http://someschema.org/", null))))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                <workspace>
                                                    <collection href='" + baseUri + @"Products'>
                                                        <atom:title>Products</atom:title>
                                                        <accept>application/atom+xml;type=entry</accept>
                                                        <categories fixed='yes'>
                                                            <atom:category scheme='http://someschema.org/' term='SomeTerm'/>
                                                        </categories>
                                                    </collection>
                                                </workspace>
                                              </service>"),
                },

                // Out of line app:categories element.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace()
                            .AtomTitle("Default", TestAtomConstants.AtomTextConstructTextKind)
                            .ResourceCollection(
                                PayloadBuilder.ResourceCollection("Products", baseUri + "Products")
                                    .AppOutOfLineCategories("http://example.com/categories")))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                <workspace>
                                                    <atom:title>Default</atom:title>
                                                    <collection href='" + baseUri + @"Products'>
                                                        <atom:title>Products</atom:title>
                                                        <categories href='http://example.com/categories' />
                                                    </collection>
                                                </workspace>
                                              </service>"),
                },

                // Attributes of the "categories" element in a non-empty namespace should be ignored.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace()
                            .ResourceCollection(
                                PayloadBuilder.ResourceCollection("Products", baseUri + "Products")
                                    .AppInlineCategories(null, null,
                                        AtomMetadataBuilder.AtomCategory("SomeTerm", "http://someschema.org", "SomeLabel"))))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'
                                                xmlns:foo='http://foo.org'>
                                                <workspace>
                                                    <collection href='" + baseUri + @"Products'>
                                                        <atom:title>Products</atom:title>
                                                        <categories foo:fixed='yes' atom:scheme='http://baseschema.org'>
                                                            <atom:category term='SomeTerm' scheme='http://someschema.org' label='SomeLabel'/>
                                                        </categories>
                                                    </collection>
                                                </workspace>
                                              </service>"),
                },
                
                #endregion app:accept and app:categories element

                #region atom:category element

                // Attributes of the "category" element in a non-empty namespace should be ignored.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace()
                            .ResourceCollection(
                                PayloadBuilder.ResourceCollection("Products", baseUri + "Products")
                                    .AppInlineCategories("yes", "http://baseschema.org", 
                                        AtomMetadataBuilder.AtomCategory(null, null, null))))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'
                                                xmlns:foo='http://foo.org'>
                                                <workspace>
                                                    <collection href='" + baseUri + @"Products'>
                                                        <atom:title>Products</atom:title>
                                                        <categories fixed='yes' scheme='http://baseschema.org'>
                                                            <atom:category foo:term='SomeTerm' app:scheme='http://someschema.org' atom:label='SomeLabel'/>
                                                        </categories>
                                                    </collection>
                                                </workspace>
                                              </service>"),
                },

                // Multiple atom:category elements.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace()
                            .AtomTitle("Default", TestAtomConstants.AtomTextConstructTextKind)
                            .ResourceCollection(
                                PayloadBuilder.ResourceCollection("Products", baseUri + "Products")
                                    .AppInlineCategories("no", "http://baseschema.org", 
                                        AtomMetadataBuilder.AtomCategory("FirstCategory", null, null),
                                        AtomMetadataBuilder.AtomCategory("SecondCategory", null, "SomeLabel"))))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                <workspace>
                                                    <atom:title>Default</atom:title>
                                                    <collection href='" + baseUri + @"Products'>
                                                        <atom:title>Products</atom:title>
                                                        <categories fixed='no' scheme='http://baseschema.org'>
                                                            <atom:category term='FirstCategory'/>
                                                            <atom:category term='SecondCategory' label='SomeLabel'/>
                                                        </categories>
                                                    </collection>
                                                </workspace>
                                              </service>"),
                },

                #endregion atom:category element

                #region extra nodes

                // comments at different places in the service document.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace().ResourceCollection(null, baseUri + "Products"))
                        .XmlRepresentation(@"<service xmlns:cn='http://customnamespace' xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                <!-- some comments -->
                                                <workspace>
                                                    <!-- more comments -->
                                                    <collection href='" + baseUri + @"Products'>
                                                       <!-- more comments -->                                                    
                                                    </collection>
                                                    <!-- more comments -->
                                                </workspace>
                                                <!-- more comments -->            
                                              </service>"),
                },

                // elements having additional irrelevant attributes 
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace().ResourceCollection(null, baseUri + "Products"))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom' foo2='bar2'>
                                                <workspace foo='bar'>
                                                    <collection href='" + baseUri + @"Products' foo1='bar1'>
                                                    </collection>
                                                </workspace>
                                              </service>"),
                },

                // irrelevant child elements inside a workspace or collection element.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace()
                            .ResourceCollection(null, baseUri + "Products")
                            .ResourceCollection(null, baseUri + "Orders"))
                        .XmlRepresentation(@"<service xmlns:cn='http://customnamespace' xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                <workspace>
                                                    <cn:foo foo1='bar1' />
                                                    <collection href='" + baseUri + @"Products'>
                                                        <cn:foo href='" + baseUri + @"Products'>
                                                        </cn:foo>
                                                    </collection>
                                                    <cn:foo2 foo3='bar3' />
                                                    <cn:foo2 foo3='bar3' />
                                                    <collection href='" + baseUri + @"Orders'>
                                                        <atom:foo href='" + baseUri + @"Orders'>
                                                        </atom:foo>
                                                    </collection>
                                                </workspace>
                                             </service>"),
                },

                // irrelevant element before and after the workspace 
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace().ResourceCollection(null, baseUri + "Products"))
                       .XmlRepresentation(@"<service xmlns:cn='http://customnamespace' xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                <cn:some_element>some text</cn:some_element>
                                                <workspace>
                                                    <collection href='" + baseUri + @"Products'>
                                                    </collection>
                                                </workspace>
                                                <cn:some_element>some text</cn:some_element>
                                             </service>"),
                },

                #endregion extra elements
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations.Where(tc => !tc.IsRequest),
                new bool[] { true, false },
                (testDescriptor, testConfiguration, enableAtomMetadataReading) =>
                {
                    testConfiguration = new ReaderTestConfiguration(testConfiguration);
                    testConfiguration.MessageReaderSettings.EnableAtomMetadataReading = enableAtomMetadataReading;

                    testDescriptor = new PayloadReaderTestDescriptor(testDescriptor);

                    if (!enableAtomMetadataReading)
                    {
                        // If we are running with ATOM metadata reading turned off, strip off all ATOM metadata annotations and 
                        // properties from the expected result.
                        testDescriptor.ExpectedResultNormalizers.Add(tc => RemoveAtomMetadataFromPayloadElementVisitor.Visit);
                    }

                    // Normalize the payload elements so that if an ATOM metadata property is set, the corresponding ATOM metadata 
                    // annotation is created, and vice versa.
                    testDescriptor.ExpectedResultNormalizers.Add(tc => ODataPayloadElementAtomMetadataNormalizer.GenerateNormalizer(testConfiguration));

                    testDescriptor.RunTest(testConfiguration);
                });
        }
        private void RunMessageSizeLimitTests(
            IEnumerable<ReaderTestConfiguration> testConfigurations,
            EdmModel model,
            ODataPayloadElement payload,
            MessageSizeLimitTestCase[] testCases,
            Func<ReaderTestConfiguration, bool> skipTestConfigurationFunc = null)
        {
            var transformScope = this.Settings.PayloadTransformFactory.EmptyScope();
            using (transformScope.Apply())
            {
                this.CombinatorialEngineProvider.RunCombinations(
                    testCases,
                    testConfigurations,
                    (testCase, testConfiguration) =>
                    {
                        int size = -1;
                        if (testConfiguration.Format == ODataFormat.Atom && testCase.AtomSizes != null)
                        {
                            size = testConfiguration.IsRequest ? testCase.AtomSizes.RequestSize : testCase.AtomSizes.ResponseSize;
                        }
                        else if (testConfiguration.Format == ODataFormat.Json && testCase.JsonLightSizes != null)
                        {
                            size = testConfiguration.IsRequest ? testCase.JsonLightSizes.RequestSize : testCase.JsonLightSizes.ResponseSize;
                        }
                        else if (testCase.RawSizes != null)
                        {
                            size = testConfiguration.IsRequest ? testCase.RawSizes.RequestSize : testCase.RawSizes.ResponseSize;
                        }

                        int maxSize = testCase.MaxMessageSize >= 0 ? testCase.MaxMessageSize : 1024 * 1024;
                        ExpectedException expectedException = size < 0
                            ? null
                            : ODataExpectedExceptions.ODataException("MessageStreamWrappingStream_ByteLimitExceeded", size.ToString(), maxSize.ToString());

                        var testDescriptor = new PayloadReaderTestDescriptor(this.Settings)
                        {
                            PayloadEdmModel = model,
                            PayloadElement = payload.DeepCopy(),
                            ExpectedException = expectedException,
                            SkipTestConfiguration = skipTestConfigurationFunc,
                            ApplyPayloadTransformations = false,
                        };

                        testDescriptor.ExpectedResultNormalizers.Add(
                            tc => (Func<ODataPayloadElement, ODataPayloadElement>)null);

                        if (testCase.MaxMessageSize > 0)
                        {
                            testConfiguration = new ReaderTestConfiguration(testConfiguration);
                            testConfiguration.MessageReaderSettings.MessageQuotas.MaxReceivedMessageSize = testCase.MaxMessageSize;
                        }

                        testDescriptor.RunTest(testConfiguration);
                    });
            }
        }
Exemplo n.º 3
0
        public void InvalidXmlBaseUriHandlingTest()
        {
            string absoluteUri = "http://odata.org/relative";

            var testCases = new[]
            {
                new
                {
                    BaseUriString = "relativeUri",
                    SettingsBaseUri = (string)null,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomDeserializer_RelativeUriUsedWithoutBaseUriSpecified", "relativeUri")
                },
                new
                {
                    BaseUriString = string.Empty,
                    SettingsBaseUri = (string)null,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomDeserializer_RelativeUriUsedWithoutBaseUriSpecified", string.Empty)
                },
                new
                {
                    BaseUriString = "http://invalid:uri:value",
                    SettingsBaseUri = (string)null,
                    ExpectedException = new ExpectedException(typeof(UriFormatException))
                }
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                new TestODataBehaviorKind[] { TestODataBehaviorKind.Default, TestODataBehaviorKind.WcfDataServicesServer },
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations,
                (testCase, behaviorKind, testConfiguration) =>
                {
                    var td = new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.Entity().AsMediaLinkEntry().StreamSourceLink(absoluteUri)
                            .XmlRepresentation("<entry xml:base='" + testCase.BaseUriString + "'><content src='" + absoluteUri + "'/></entry>"),
                        ExpectedException = testCase.ExpectedException
                    };

                    // [Astoria-ODataLib-Integration] Parsing of URLs on OData recognized places may fail, but Astoria server doesn't
                    // In server mode we need to normalize payload to not expect information that the server does not read
                    if(behaviorKind == TestODataBehaviorKind.WcfDataServicesServer)
                    {
                        td.ExpectedResultNormalizers.Add((tc) => (payloadElement => WcfDsServerPayloadElementNormalizer.Normalize(payloadElement, tc.Format, (EdmModel)null)));
                    }


                    testConfiguration = testConfiguration.CloneAndApplyBehavior(behaviorKind);
                    testConfiguration.MessageReaderSettings.BaseUri = testCase.SettingsBaseUri == null ? null : new Uri(testCase.SettingsBaseUri);

                    td.RunTest(testConfiguration);
                });
        }
        public void ServiceDocumentReaderInvalidAtomMetadataTest()
        {
            // The ExpectedExceptions in the following test descriptors only apply when ATOM metadata reading is on.
            // When ATOM metadata reading is off, invalid ATOM metadata should cause no failures, and ExpectedException is ignored.
            IEnumerable<PayloadReaderTestDescriptor> testDescriptors = new PayloadReaderTestDescriptor[]
            {
                // Multiple atom:title elements inside the workspace element.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace().ResourceCollection("Products", baseUri + "Products"))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                    xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                    <workspace>
                                                        <atom:title>Default</atom:title>
                                                        <atom:title>Default</atom:title>
                                                        <collection href='" + baseUri + @"Products'>
                                                            <atom:title>Products</atom:title>   
                                                        </collection>
                                                    </workspace>
                                                 </service>"),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomServiceDocumentMetadataDeserializer_MultipleTitleElementsFound", "workspace"),
                },

                // Invalid value for "fixed" attribute on a categories element
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace().ResourceCollection("Products", baseUri + "Products"))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                    xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                    <workspace>
                                                        <collection href='" + baseUri + @"Products'>
                                                            <atom:title>Products</atom:title>
                                                            <categories fixed='foo' scheme='http://baseschema.org'>
                                                                <atom:category term='Some Term'/>
                                                            </categories> 
                                                        </collection>
                                                    </workspace>
                                                 </service>"),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomServiceDocumentMetadataDeserializer_InvalidFixedAttributeValue", "foo"),
                },

                // Multiple app:accept attributes inside a collection
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ServiceDocument().Workspace(
                        PayloadBuilder.Workspace()
                            .ResourceCollection(
                                PayloadBuilder.ResourceCollection("Products", baseUri + "Products")
                                    .AppAccept("application/atom+xml;type=entry")
                                    .AppInlineCategories("yes", null,
                                        AtomMetadataBuilder.AtomCategory("SomeTerm", "http://someschema.org/", null))))
                        .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' 
                                                xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'>
                                                <workspace>
                                                    <collection href='" + baseUri + @"Products'>
                                                        <atom:title>Products</atom:title>
                                                        <accept>application/atom+xml;type=entry</accept>
                                                        <categories fixed='yes'>
                                                            <atom:category scheme='http://someschema.org/' term='SomeTerm'/>
                                                        </categories>
                                                        <accept>application/atom+xml;type=entry</accept>
                                                    </collection>
                                                </workspace>
                                              </service>"),
                       ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomServiceDocumentMetadataDeserializer_MultipleAcceptElementsFoundInCollection"),
                },
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations.Where(tc => !tc.IsRequest),
                new bool[] { true, false },
                (testDescriptor, testConfiguration, enableAtomMetadataReading) =>
                {
                    testConfiguration = new ReaderTestConfiguration(testConfiguration);
                    testConfiguration.MessageReaderSettings.EnableAtomMetadataReading = enableAtomMetadataReading;

                    testDescriptor = new PayloadReaderTestDescriptor(testDescriptor);

                    if (!enableAtomMetadataReading)
                    {
                        testDescriptor.ExpectedResultNormalizers.Add(tc => RemoveAtomMetadataFromPayloadElementVisitor.Visit);
                        testDescriptor.ExpectedException = null;
                    }

                    testDescriptor.RunTest(testConfiguration);
                });
        }
Exemplo n.º 5
0
        public void DuplicatePropertyNamesTest()
        {
            EdmModel model = new EdmModel();
            var entityType = new EdmEntityType("TestModel", "DuplicateEntityType");
            entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
            model.AddElement(entityType);
            var complexType = new EdmComplexType("TestModel", "DuplicateComplexType");
            complexType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(true));
            model.AddElement(complexType);
            var container = new EdmEntityContainer("TestModel", "DefaultContainer");
            container.AddEntitySet("ClosedEntitySet", entityType);
            model.AddElement(container);

            PropertyInstance primitiveProperty = PayloadBuilder.PrimitiveProperty("DuplicateProperty", 42);
            PropertyInstance complexProperty = PayloadBuilder.Property("DuplicateProperty",
                PayloadBuilder.ComplexValue("TestModel.DuplicateComplexType").PrimitiveProperty("Name", "foo"));
            PropertyInstance collectionProperty = PayloadBuilder.Property("DuplicateProperty",
                PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.String")).WithTypeAnnotation(EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetString(false))));
            PropertyInstance streamProperty = PayloadBuilder.StreamProperty("DuplicateProperty", "http://odata.org/readlink", "http://odata.org/editlink");
            PropertyInstance navigationProperty = PayloadBuilder.NavigationProperty("DuplicateProperty", "http://odata.org/navlink")
                .IsCollection(true)
                .WithTypeAnnotation(entityType);
            PropertyInstance expandedFeedProperty = PayloadBuilder.ExpandedNavigationProperty("DuplicateProperty",
                PayloadBuilder.EntitySet(new EntityInstance[] { PayloadBuilder.Entity("TestModel.DuplicateEntityType").PrimitiveProperty("Id", 1) }))
                .IsCollection(true)
                .WithTypeAnnotation(entityType);
            PropertyInstance associationLinkProperty = PayloadBuilder.NavigationProperty("DuplicateProperty", null, "http://odata.org/assoclink");

            PropertyInstance[] allProperties = new[] { primitiveProperty, complexProperty, collectionProperty, streamProperty, navigationProperty, expandedFeedProperty, associationLinkProperty };
            PropertyInstance[] propertiesWithPossibleDuplication = new[] { primitiveProperty, complexProperty, navigationProperty, expandedFeedProperty };
            PropertyInstance[] propertiesWithNoDuplication = new[] { collectionProperty, streamProperty, associationLinkProperty };

            IEnumerable<DuplicatePropertySet> duplicatePropertySets;

            // Those which may allow duplication
            duplicatePropertySets = propertiesWithPossibleDuplication
                .Variations(2).Select(properties => new DuplicatePropertySet { Properties = properties, DuplicationPotentiallyAllowed = true });

            // Then for each in those which don't allow duplication try it against all the others
            duplicatePropertySets = duplicatePropertySets.Concat(propertiesWithNoDuplication.SelectMany(
                propertyWithNoDuplication => allProperties.SelectMany(otherProperty =>
                    new[]
                    {
                        new DuplicatePropertySet { Properties = new [] { propertyWithNoDuplication, otherProperty }, DuplicationPotentiallyAllowed = false },
                        new DuplicatePropertySet { Properties = new [] { otherProperty, propertyWithNoDuplication }, DuplicationPotentiallyAllowed = false },
                    })));

            this.CombinatorialEngineProvider.RunCombinations(
                duplicatePropertySets,
                new bool[] { false, true },
                new bool[] { true, false },
                this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations,
                (duplicatePropertySet, useServerBehavior, useMetadata, testConfiguration) =>
                {
                    PropertyInstance firstProperty = duplicatePropertySet.Properties.ElementAt(0);
                    PropertyInstance secondProperty = duplicatePropertySet.Properties.ElementAt(1);

                    // Non-metadata parsing is not supported in JSON.
                    if (!useMetadata && (testConfiguration.Format != ODataFormat.Atom))
                    {
                        return;
                    }

                    // If we will have metadata then we can only allow combinations of the same kind
                    if (useMetadata)
                    {
                        if (firstProperty.ElementType != secondProperty.ElementType)
                        {
                            return;
                        }
                    }

                    // Association links are only recognized in response payloads and MPV >= V3
                    if ((testConfiguration.IsRequest) &&
                        duplicatePropertySet.Properties.Any(p => object.ReferenceEquals(p, associationLinkProperty)))
                    {
                        return;
                    }

                    // Steam properties are only recognized in response >=V3 payloads
                    if ((testConfiguration.IsRequest) &&
                        duplicatePropertySet.Properties.Any(p => object.ReferenceEquals(p, streamProperty)))
                    {
                        return;
                    }

                    // Copy the test config
                    testConfiguration = new ReaderTestConfiguration(testConfiguration);
                    if (useServerBehavior)
                    {
                        testConfiguration.MessageReaderSettings.EnableODataServerBehavior();
                    }

                    // Create a descriptor with the first property
                    PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = firstProperty,
                        PayloadEdmModel = useMetadata ? (EdmModel)Test.OData.Utils.Metadata.MetadataUtils.Clone(model) : null,
                    };

                    // Now generate entity around it
                    testDescriptor = testDescriptor.InEntity(2, 2);

                    // Now add the second property to it
                    ((EntityInstance)testDescriptor.PayloadElement).Add(secondProperty);

                    // [Astoria-ODataLib-Integration] Parsing of URLs on OData recognized places may fail, but Astoria server doesn't
                    // Server does not read named stream links for Atom payload therefore the expected payload needs to be normalized
                    if (testConfiguration.Format == ODataFormat.Atom && useServerBehavior)
                    {
                        testDescriptor.ExpectedResultNormalizers.Add(config => (payloadElement => WcfDsServerPayloadElementNormalizer.Normalize(payloadElement, ODataFormat.Atom, testDescriptor.PayloadEdmModel as EdmModel)));
                    }

                    // We expect failure only if we don't allow duplicates or if the property kind doesn't allow duplicates ever.
                    // In JSON with WCF DS Service behavior where duplicates are removed very soon and thus we never fail on them.
                    if ((!duplicatePropertySet.DuplicationPotentiallyAllowed || !useServerBehavior))
                    {
                        testDescriptor.ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "DuplicateProperty");
                    }

                    if (firstProperty.ElementType == ODataPayloadElementType.NavigationPropertyInstance && secondProperty.ElementType == ODataPayloadElementType.NavigationPropertyInstance)
                    {
                        NavigationPropertyInstance navigationFirstProperty = (NavigationPropertyInstance)firstProperty;
                        NavigationPropertyInstance navigationSecondProperty = (NavigationPropertyInstance)secondProperty;

                        // If one of the properties is an association link and the other is a navigation link, that combination is allowed and it's not an error.
                        // Just skip that combination.
                        if ((navigationFirstProperty.Value != null && navigationFirstProperty.AssociationLink == null && navigationSecondProperty.Value == null && navigationSecondProperty.AssociationLink != null) ||
                            (navigationFirstProperty.Value == null && navigationFirstProperty.AssociationLink != null && navigationSecondProperty.Value != null && navigationSecondProperty.AssociationLink == null))
                        {
                            return;
                        }

                        if (testConfiguration.Format == ODataFormat.Json)
                        {
                            if ((navigationFirstProperty.Value is DeferredLink || navigationSecondProperty.Value is DeferredLink) &&
                                (navigationFirstProperty.Value is ExpandedLink || navigationSecondProperty.Value is ExpandedLink))
                            {
                                testDescriptor.ExpectedException = null;
                                testDescriptor.ExpectedResultNormalizers.Add(
                                    (tc) => (tc.IsRequest)
                                        ? (Func<ODataPayloadElement, ODataPayloadElement>)((payload) => EnsureAnnotationsBeforeProperties(DuplicateNavigationPropertiesToLinkCollection(payload)))
                                        : (payload) => EnsureAnnotationsBeforeProperties(DuplicateNavigationPropertiesToExpandedLink(payload)));
                            }
                            else if (navigationFirstProperty.AssociationLink != null && navigationSecondProperty.AssociationLink != null)
                            {
                                testDescriptor.ExpectedException = ODataExpectedExceptions.ODataException(
                                    "DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed",
                                    JsonLightConstants.ODataAssociationLinkUrlAnnotationName,
                                    "DuplicateProperty");
                            }
                        }

                        // In requests if both are navigation properties (not association links)
                        // If both are expanded, then fail (that's not allowed), but if one is not expanded, that is allowed (binding in POST scenario)
                        // Note that this only works because we use expanded feed, if we would add expanded entry, then the expanded entry can't be allowed along with a deferred link.
                        else if (navigationFirstProperty.AssociationLink == null && navigationSecondProperty.AssociationLink == null &&
                            testConfiguration.IsRequest &&
                            (navigationFirstProperty.Value is DeferredLink || navigationSecondProperty.Value is DeferredLink))
                        {
                            testDescriptor.ExpectedException = null;
                        }
                    }

                    if (firstProperty.ElementType == ODataPayloadElementType.NamedStreamInstance && secondProperty.ElementType == ODataPayloadElementType.NamedStreamInstance)
                    {
                        if (testConfiguration.Format == ODataFormat.Atom)
                        {
                            // In ATOM stream properties are represented as pair of links and thus we first match the links together.
                            // Thus the code finds the duplicate stream property before we get to the duplicate check
                            // (since it actually finds a stream property which already has a link which it's trying to read)
                            // As a result we get a different error message, which is OK.
                            testDescriptor.ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomEntryAndFeedDeserializer_StreamPropertyWithMultipleReadLinks", "DuplicateProperty");
                        }
                        else if (testConfiguration.Format == ODataFormat.Json)
                        {
                            testDescriptor.ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataMediaEditLinkAnnotationName, "DuplicateProperty");
                        }
                    }

                    if (testConfiguration.Format == ODataFormat.Json)
                    {
                        testDescriptor.PayloadElement = EnsureAnnotationsBeforeProperties(testDescriptor.PayloadElement);
                    }

                    testDescriptor.RunTest(testConfiguration);
                });
        }
Exemplo n.º 6
0
        public void DuplicateNavigationLinkTest()
        {
            IEdmModel model = TestModels.BuildTestModel();

            IEnumerable<DuplicateNavigationLinkTestCase> testCases = new[]
            {
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Two expanded links, both collection",
                    Properties = new PropertyInstance[] { 
                        PayloadBuilder.ExpandedNavigationProperty(
                            "CityHall",
                            PayloadBuilder.EntitySet().InsertAt(0, PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 1), PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 2))),
                        PayloadBuilder.ExpandedNavigationProperty(
                            "CityHall",
                            PayloadBuilder.EntitySet()) },
                    ExpectedResultCallback = 
                        (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = (tc.Format == ODataFormat.Json)
                                        ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall")
                                        : (tc.IsRequest) 
                                            ? null
                                            : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"),
                                },
                },
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Two expanded links, both singletons",
                    Properties = new PropertyInstance[] { 
                        PayloadBuilder.ExpandedNavigationProperty(
                            "PoliceStation",
                            PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 1)),
                        PayloadBuilder.ExpandedNavigationProperty(
                            "PoliceStation",
                            null) },
                    ExpectedResultCallback = 
                        (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = (tc.Format == ODataFormat.Json)
                                        ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "PoliceStation")
                                        : (tc.IsRequest) 
                                            ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_MultipleLinksForSingleton", "PoliceStation")
                                            : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "PoliceStation"),
                                },
                },
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Two expanded links, one collection one singleton",
                    Properties = new PropertyInstance[] { 
                        PayloadBuilder.ExpandedNavigationProperty(
                            "PoliceStation",
                            PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 1)),
                        PayloadBuilder.ExpandedNavigationProperty(
                            "PoliceStation",
                            PayloadBuilder.EntitySet()) },
                    ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_MultipleLinksForSingleton", "PoliceStation"),
                    NoMetadataOnly = true
                },
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Expanded singleton, deferred without type",
                    Properties = new PropertyInstance[] { 
                        PayloadBuilder.ExpandedNavigationProperty(
                            "PoliceStation",
                            PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 1)),
                        PayloadBuilder.DeferredNavigationProperty(
                            "PoliceStation",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred")) },
                    ExpectedResultCallback = 
                        (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = (tc.Format == ODataFormat.Json)
                                        ? tc.IsRequest
                                            ? ODataExpectedExceptions.ODataException("ODataJsonLightEntryAndFeedDeserializer_SingletonNavigationPropertyWithBindingAndValue", "PoliceStation", JsonLightConstants.ODataBindAnnotationName) 
                                            : null
                                        : tc.IsRequest
                                            ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_MultipleLinksForSingleton", "PoliceStation")
                                            : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "PoliceStation"),
                                }
                },
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Expanded singleton, deferred singleton",
                    Properties = new PropertyInstance[] { 
                        PayloadBuilder.ExpandedNavigationProperty(
                            "PoliceStation",
                            PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 1)),
                        PayloadBuilder.DeferredNavigationProperty(
                            "PoliceStation",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(false)) },
                    ExpectedResultCallback = 
                        (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = (tc.Format == ODataFormat.Json)
                                        ? tc.IsRequest 
                                            ? ODataExpectedExceptions.ODataException("ODataJsonLightEntryAndFeedDeserializer_SingletonNavigationPropertyWithBindingAndValue", "PoliceStation", JsonLightConstants.ODataBindAnnotationName) 
                                            : null
                                        : tc.IsRequest
                                            ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_MultipleLinksForSingleton", "PoliceStation")
                                            : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "PoliceStation"),
                                }
                },
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Expanded singleton, deferred collection (no metadata), we will fail on this since we don't allow multiple links for singletons",
                    Properties = new PropertyInstance[] { 
                        PayloadBuilder.ExpandedNavigationProperty(
                            "PoliceStation",
                            PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 1)),
                        PayloadBuilder.DeferredNavigationProperty(
                            "PoliceStation",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(true)) },
                    ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_MultipleLinksForSingleton", "PoliceStation"),
                    NoMetadataOnly = true
                },
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Expanded collection, deferred without type - no failures",
                    Properties = new PropertyInstance[] { 
                        PayloadBuilder.ExpandedNavigationProperty(
                            "CityHall",
                            PayloadBuilder.EntitySet()),
                        PayloadBuilder.DeferredNavigationProperty(
                            "CityHall",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred")).IsCollection(true) },
                    ExpectedResultNormalizer = 
                        (tc) =>
                        {
                            if (tc.Format == ODataFormat.Json)
                            {
                                return (tc.IsRequest) ? (Func<ODataPayloadElement, ODataPayloadElement>)DuplicateNavigationPropertiesToLinkCollection : DuplicateNavigationPropertiesToExpandedLink;
                            }

                            return null;
                        },
                    ExpectedResultCallback = 
                        (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = (tc.Format == ODataFormat.Json || tc.IsRequest)
                                        ? null
                                        : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"),
                                }
                },
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Expanded collection, deferred singleton - no failures (binding scenario) (the metadata mismatch is specifically allowed)",
                    Properties = new PropertyInstance[] { 
                        PayloadBuilder.ExpandedNavigationProperty(
                            "CityHall",
                            PayloadBuilder.EntitySet()),
                        PayloadBuilder.DeferredNavigationProperty(
                            "CityHall",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(false)) },
                    // Doesn't work for JSON since the metadata mismatch will cause the parsing to fail
                    // Does not work for deferred link in responses.
                    SkipForConfiguration = tc => tc.IsRequest == false,
                    ExpectedResultNormalizer = 
                        (tc) => (tc.Format == ODataFormat.Json) ? DuplicateNavigationPropertiesToLinkCollection : (Func<ODataPayloadElement, ODataPayloadElement>)null,
                    ExpectedResultCallback = 
                        (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = (tc.Format == ODataFormat.Json)
                                            ? ODataExpectedExceptions.ODataException("ODataJsonLightEntryAndFeedDeserializer_StringValueForCollectionBindPropertyAnnotation", "CityHall", JsonLightConstants.ODataBindAnnotationName)
                                            : null,
                                },
                },
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Expanded collection, deferred collection - no failures (binding scenario)",
                    Properties = new PropertyInstance[] { 
                        PayloadBuilder.ExpandedNavigationProperty(
                            "CityHall",
                            PayloadBuilder.EntitySet()),
                        PayloadBuilder.DeferredNavigationProperty(
                            "CityHall",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(true)) },
                    // Doesn't work for JSON since the metadata mismatch will cause the parsing to fail
                    ExpectedResultCallback = 
                        (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = (tc.Format == ODataFormat.Json)
                                        ? tc.IsRequest 
                                            ? ODataExpectedExceptions.ODataException("ODataJsonLightEntryAndFeedDeserializer_StringValueForCollectionBindPropertyAnnotation", "CityHall", JsonLightConstants.ODataBindAnnotationName) 
                                            : null
                                        : tc.IsRequest 
                                            ? null 
                                            : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"),
                                },
                },
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Two deferred singletons on a collection property - no failures (binding scenario) (the metadata mismatch is specifically allowed)",
                    Properties = new PropertyInstance[] { 
                        PayloadBuilder.DeferredNavigationProperty(
                            "CityHall",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(false)),
                        PayloadBuilder.DeferredNavigationProperty(
                            "CityHall",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(false)) },
                    // Doesn't work for JSON since the metadata mismatch will cause the parsing to fail
                    // Does not work for deferred link in responses.
                    SkipForConfiguration = tc => tc.IsRequest == false,
                    ExpectedResultCallback = 
                        (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = (tc.Format == ODataFormat.Json) 
                                        ? (tc.IsRequest) 
                                            ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataBindAnnotationName, "CityHall") 
                                            : null
                                        : (tc.IsRequest) 
                                            ? null 
                                            : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"),
                                },
                },
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Two deferred collections on a collection property - no failures (binding scenario)",
                    Properties = new PropertyInstance[] { 
                        PayloadBuilder.DeferredNavigationProperty(
                            "CityHall",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(true)).IsCollection(true),
                        PayloadBuilder.DeferredNavigationProperty(
                            "CityHall",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(true)).IsCollection(true) },
                    ExpectedResultCallback = 
                        (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = 
                                        (tc.Format == ODataFormat.Json) 
                                            ? (tc.IsRequest) 
                                                ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataBindAnnotationName, "CityHall") 
                                                : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataNavigationLinkUrlAnnotationName, "CityHall") 
                                            : (tc.IsRequest) 
                                                ? null 
                                                : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"),
                                },
                },
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Deferred collection and deferred singleton - no failures (binding scenario) (the metadata mismatch is specifically allowed)",
                    Properties = new PropertyInstance[] { 
                        PayloadBuilder.DeferredNavigationProperty(
                            "CityHall",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(true)),
                        PayloadBuilder.DeferredNavigationProperty(
                            "CityHall",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(false)) },
                    // Doesn't work for JSON since the metadata mismatch will cause the parsing to fail
                    // Does not work for deferred link in responses.
                    SkipForConfiguration = tc => tc.IsRequest == false,
                    ExpectedResultCallback = 
                        (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = 
                                        (tc.Format == ODataFormat.Json) 
                                            ? (tc.IsRequest) 
                                                ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataBindAnnotationName, "CityHall") 
                                                : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataNavigationLinkUrlAnnotationName, "CityHall") 
                                            : (tc.IsRequest) 
                                                ? null 
                                                : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"),
                                },
                },
                new DuplicateNavigationLinkTestCase
                {
                    DebugDescription = "Expanded collection, deferred collection and deferred singleton - no failures (binding scenario) (the metadata mismatch is specifically allowed)",
                    Properties = new PropertyInstance[] {
                        PayloadBuilder.ExpandedNavigationProperty(
                            "CityHall",
                            PayloadBuilder.EntitySet()),
                        PayloadBuilder.DeferredNavigationProperty(
                            "CityHall",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(true)),
                        PayloadBuilder.DeferredNavigationProperty(
                            "CityHall",
                            PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(false)) },
                    // Doesn't work for JSON since the metadata mismatch will cause the parsing to fail
                    // Does not work for deferred link in responses.
                    SkipForConfiguration = tc => tc.IsRequest == false,
                    ExpectedResultCallback = 
                        (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = 
                                        (tc.Format == ODataFormat.Json) 
                                            ? (tc.IsRequest) 
                                                ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataBindAnnotationName, "CityHall") 
                                                : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataNavigationLinkUrlAnnotationName, "CityHall") 
                                            : (tc.IsRequest) 
                                                ? null 
                                                : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"),
                                },
                },
            };

            // Add association link cases (this should have no effect on the result, since single association link is always allowed)
            testCases = testCases.SelectMany(testCase =>
                new[]
                {
                    testCase,
                    new DuplicateNavigationLinkTestCase(testCase)
                    {
                        DebugDescription = testCase.DebugDescription + " [With association link]",
                        Properties = testCase.Properties.ConcatSingle(PayloadBuilder.NavigationProperty(testCase.Properties[0].Name, null, "http://odata.org/associationlink")).ToArray(),
                        // No association links in requests.
                        SkipForConfiguration = tc => testCase.SkipForConfiguration == null ? tc.IsRequest : testCase.SkipForConfiguration(tc) || tc.IsRequest
                    }
                });

            // Add all permutations since order should not have any effect on the outcome
            testCases = testCases.SelectMany(testCase => testCase.Properties.Permutations().Select(properties =>
                new DuplicateNavigationLinkTestCase(testCase) { Properties = properties }));

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                new bool[] { true, false },
                this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations,
                (testCase, withMetadata, testConfiguration) =>
                {
                    // JSON reading requires metadata
                    if (!withMetadata && (testConfiguration.Format == ODataFormat.Json))
                    {
                        return;
                    }

                    if (withMetadata && testCase.NoMetadataOnly)
                    {
                        return;
                    }

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

                    EntityInstance entityInstance = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1);
                    foreach (PropertyInstance propertyInstance in testCase.Properties)
                    {
                        entityInstance.Add(propertyInstance);
                    }

                    ExpectedException expectedException = testCase.ExpectedException;
                    if (!testConfiguration.IsRequest && testCase.ExpectedResultCallback == null)
                    {
                        // In responses all duplicates will fail with the same error message since we don't allow any duplicates there.
                        expectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", testCase.Properties[0].Name);
                    }

                    PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings)
                    {
                        DebugDescription = testCase.DebugDescription,
                        PayloadElement = entityInstance,
                        ExpectedException = expectedException,
                        ExpectedResultCallback = testCase.ExpectedResultCallback,
                        PayloadEdmModel = withMetadata ? model : null,
                    };

                    testDescriptor.ExpectedResultNormalizers.Add(
                        tc => (Func<ODataPayloadElement, ODataPayloadElement>)null);
                    testDescriptor.ExpectedResultNormalizers.Add(tc => RemoveContentTypeAnnotationNormalizer.Normalize);

                    if (testCase.ExpectedResultNormalizer != null)
                    {
                        testDescriptor.ExpectedResultNormalizers.Add(testCase.ExpectedResultNormalizer);
                    }

                    if (testConfiguration.Format == ODataFormat.Json)
                    {
                        testDescriptor.PayloadElement = EnsureAnnotationsBeforeProperties(testDescriptor.PayloadElement);
                    }

                    testDescriptor.RunTest(testConfiguration);
                });
        }
Exemplo n.º 7
0
        public void BatchReaderBatchSizeTests()
        {
            var testCases = new[]
            {
                new
                {
                    MaxPartsPerBatch = (int?)null,
                    QueryCount = 0,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxPartsPerBatch = (int?)null,
                    QueryCount = 1,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxPartsPerBatch = (int?)null,
                    QueryCount = 4,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxPartsPerBatch = (int?)0,
                    QueryCount = 0,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxPartsPerBatch = (int?)1,
                    QueryCount = 1,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxPartsPerBatch = (int?)2,
                    QueryCount = 2,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxPartsPerBatch = (int?)5,
                    QueryCount = 0,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxPartsPerBatch = (int?)5,
                    QueryCount = 1,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxPartsPerBatch = (int?)5,
                    QueryCount = 2,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxPartsPerBatch = (int?)0,
                    QueryCount = 1,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataBatchReader_MaxBatchSizeExceeded", "0")
                },
                new
                {
                    MaxPartsPerBatch = (int?)1,
                    QueryCount = 2,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataBatchReader_MaxBatchSizeExceeded", "1")
                },
                new
                {
                    MaxPartsPerBatch = (int?)2,
                    QueryCount = 5,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataBatchReader_MaxBatchSizeExceeded", "2")

                },
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                this.ReaderTestConfigurationProvider.DefaultFormatConfigurations,
                (testCase, testConfig) =>
                {
                    PayloadTestDescriptor ptd = TestBatches.CreateDefaultQueryBatch(
                        this.RequestManager,
                        testCase.QueryCount,
                        testConfig.IsRequest);
                    PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.PayloadReaderSettings)
                    {
                        DebugDescription = "Batch with " + testCase.QueryCount + " queries.",
                        PayloadDescriptor = ptd,
                        ExpectedException = testCase.ExpectedException,
                    };

                    testConfig = ModifyBatchTestConfig(testConfig, testCase.MaxPartsPerBatch, /*maxOperationsPerChangeset*/ null);
                    testDescriptor.RunTest(testConfig);
                });
        }
Exemplo n.º 8
0
        public void TypeCheckingOnCollectionPropertyWithModel()
        {
            EdmModel model = new EdmModel();
            var entity = new EdmEntityType("TestNS", "EntityWithCollection");
            entity.AddKeys(entity.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
            entity.AddStructuralProperty("Collection", EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false)));
            model.AddElement(entity);

            var container = new EdmEntityContainer("TestNS", "DefaultContainer");
            container.AddEntitySet("EntitySet", entity);
            model.AddElement(container);

            EntityInstance entityWithCollection = new EntityInstance("TestNS.EntityWithCollection", false /*isnull*/);
            entityWithCollection.PrimitiveProperty("Id", 1).Property(new PrimitiveMultiValueProperty("Collection",
                new PrimitiveMultiValue("Collection(Edm.String)", false /*isnull*/,
                    new PrimitiveValue[]
                    {
                        new PrimitiveValue(null, "5"),
                        new PrimitiveValue(null, "-32"),
                        new PrimitiveValue(null, "+16"),
                        new PrimitiveValue(null, "0")
                    })));
            entityWithCollection.WithTypeAnnotation(entity);

            EntityInstance expectedCollection = new EntityInstance("TestNS.EntityWithCollection", false /*isnull*/);
            expectedCollection.PrimitiveProperty("Id", 1).Property(new PrimitiveMultiValueProperty("Collection",
                new PrimitiveMultiValue("Collection(Edm.Int32)", false /*isnull*/,
                    new PrimitiveValue[]
                    {
                        new PrimitiveValue(null, 5),
                        new PrimitiveValue(null, -32),
                        new PrimitiveValue(null, 16),
                        new PrimitiveValue(null, 0)
                    }).WithAnnotations(new SerializationTypeNameTestAnnotation() { TypeName = "Collection(Edm.String)" })));
            expectedCollection.WithTypeAnnotation(entity);

            PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings)
            {
                PayloadEdmModel = model,
                PayloadElement = entityWithCollection,
                SkipTestConfiguration = tc => tc.Version < ODataVersion.V4,
                ExpectedResultCallback = tc => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                {
                    ExpectedPayloadElement = expectedCollection
                }
            };

            this.CombinatorialEngineProvider.RunCombinations(
                this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations,
                new[] { true, false },
                (testConfiguration, laxMode) =>
                {
                    var descriptor = new PayloadReaderTestDescriptor(testDescriptor);

                    if (testConfiguration.Format == ODataFormat.Json)
                    {
                        var testEntityInstance = descriptor.PayloadElement.DeepCopy() as EntityInstance;
                        PropertyInstance testProperty = testEntityInstance.Properties.Single(p => p.Name == "Collection");
                        testProperty.WithPropertyAnnotation(JsonLightConstants.ODataTypeAnnotationName, "Collection(Edm.String)");
                        descriptor.PayloadElement = testEntityInstance;
                    }

                    if (laxMode)
                    {
                        // Run test in Lax mode - type will be inferred from the model and will pass.
                        descriptor.RunTest(testConfiguration.CloneAndApplyBehavior(TestODataBehaviorKind.WcfDataServicesServer));
                    }
                    else
                    {
                        // Run test in Strict mode - type comparison will fail and an exception will be thrown.
                        descriptor.ExpectedResultCallback =
                            (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                            {
                                ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncompatibleType", "Collection(Edm.String)", "Collection(Edm.Int32)")
                            };

                        descriptor.RunTest(testConfiguration);
                    }
                });
        }
Exemplo n.º 9
0
        public void BatchReaderChangeSetSizeTests()
        {
            var testCases = new[]
            {
                new
                {
                    MaxOperationsPerChangeset = (int?)null,
                    ChangeSetCount = 0,
                    ChangeSetSizes = new int[0],
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxOperationsPerChangeset = (int?)null,
                    ChangeSetCount = 1,
                    ChangeSetSizes = new int[] { 1 },
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxOperationsPerChangeset = (int?)null,
                    ChangeSetCount = 1,
                    ChangeSetSizes = new int[] { 3 },
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxOperationsPerChangeset = (int?)null,
                    ChangeSetCount = 2,
                    ChangeSetSizes = new int[] { 0, 0 },
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxOperationsPerChangeset = (int?)null,
                    ChangeSetCount = 2,
                    ChangeSetSizes = new int[] { 1, 2 },
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxOperationsPerChangeset = (int?)1,
                    ChangeSetCount = 1,
                    ChangeSetSizes = new int[] { 2 },
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataBatchReader_MaxChangeSetSizeExceeded", "1")
                },
                new
                {
                    MaxOperationsPerChangeset = (int?)0,
                    ChangeSetCount = 1,
                    ChangeSetSizes = new int[] { 1 },
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataBatchReader_MaxChangeSetSizeExceeded", "0")
                },
                new
                {
                    MaxOperationsPerChangeset = (int?)2,
                    ChangeSetCount = 1,
                    ChangeSetSizes = new int[] { 2 },
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    MaxOperationsPerChangeset = (int?)0,
                    ChangeSetCount = 0,
                    ChangeSetSizes = new int[0],
                    ExpectedException = (ExpectedException)null
                },
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                this.ReaderTestConfigurationProvider.DefaultFormatConfigurations,
                (testCase, testConfig) =>
                {
                    PayloadTestDescriptor ptd = TestBatches.CreateDefaultChangeSetBatch(
                        this.RequestManager,
                        testCase.ChangeSetCount, 
                        testCase.ChangeSetSizes,
                        testConfig.IsRequest);
                    PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.PayloadReaderSettings)
                    {
                        DebugDescription = "Batch with " + testCase.ChangeSetCount + " changesets of varying sizes.",
                        PayloadDescriptor = ptd,
                        ExpectedException = testCase.ExpectedException,
                    };

                    testConfig = ModifyBatchTestConfig(testConfig, /*maxPartsPerBatch*/ null, testCase.MaxOperationsPerChangeset);
                    testDescriptor.RunTest(testConfig);
                });
        }
Exemplo n.º 10
0
        public void TopLevelPropertyNamespaceTest()
        {
            var testCases = new[]
            {
                new
                {
                    // Support custom data namespace for compatibility with WCF DS client.
                    NamespaceUri = TestAtomConstants.ODataMetadataNamespace + "/custom",
                    ExpectedException = new System.Func<TestODataBehaviorKind, ODataVersion, ExpectedException>((TestODataBehaviorKind behavior,ODataVersion odataVersion) => 
                    {
                        if (behavior == TestODataBehaviorKind.WcfDataServicesServer)
                        {
                            return null;
                        }
                        else
                        {
                            return ODataExpectedExceptions.ODataException("ODataAtomPropertyAndValueDeserializer_TopLevelPropertyElementWrongNamespace", TestAtomConstants.ODataMetadataNamespace + "/custom", TestAtomConstants.ODataMetadataNamespace);
                        }
                    })
                },
                new
                {
                    NamespaceUri = TestAtomConstants.ODataMetadataNamespace,
                    ExpectedException = new System.Func<TestODataBehaviorKind, ODataVersion, ExpectedException>((TestODataBehaviorKind behavior, ODataVersion odataVersion) => 
                    {
                        return null;
                    })
                },
                new
                {
                    NamespaceUri = TestAtomConstants.ODataNamespace,
                    ExpectedException = new System.Func<TestODataBehaviorKind, ODataVersion, ExpectedException>((TestODataBehaviorKind behavior, ODataVersion odataVersion) => 
                    {
                        if (behavior == TestODataBehaviorKind.WcfDataServicesServer)
                        {
                            return null;
                        }
                        else
                        {
                            return ODataExpectedExceptions.ODataException("ODataAtomPropertyAndValueDeserializer_TopLevelPropertyElementWrongNamespace", TestAtomConstants.ODataNamespace, TestAtomConstants.ODataMetadataNamespace);
                        }
                    })
                },
                new
                {
                    NamespaceUri = "http://odata.org/customUri",
                    ExpectedException = new System.Func<TestODataBehaviorKind, ODataVersion, ExpectedException>((TestODataBehaviorKind behavior,ODataVersion odataVersion) => 
                    {
                        if (behavior == TestODataBehaviorKind.WcfDataServicesServer)
                        {
                            return null;
                        }
                        else
                        {
                            return ODataExpectedExceptions.ODataException("ODataAtomPropertyAndValueDeserializer_TopLevelPropertyElementWrongNamespace", "http://odata.org/customUri", TestAtomConstants.ODataMetadataNamespace);
                        }
                    })
                }
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                TestReaderUtils.ODataBehaviorKinds,
                new[] { ODataVersion.V4 },
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations,
                (testCase, behavior, odataVersion, testConfiguration) =>
                {
                    var td = new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.PrimitiveProperty(null, string.Empty)
                            .XmlRepresentation("<p:value xmlns:p='" + testCase.NamespaceUri + "'/>"),
                        ExpectedException = testCase.ExpectedException(behavior, odataVersion)
                    };

                    testConfiguration = testConfiguration.CloneAndApplyBehavior(behavior);

                    td.RunTest(testConfiguration);
                });
        }
        public void OpenTopLevelPropertiesErrorTest()
        {
            IEdmModel model = TestModels.BuildTestModel();

            var testCases = new OpenPropertyTestCase[]
            {
                new OpenPropertyTestCase
                {
                    DebugDescription = "String open property with property annotation type information - should fail.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)),
                    Json = 
                        "{0}" +
                        "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"Edm.String\"," +
                        "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"",
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_UnexpectedODataPropertyAnnotation", JsonLightConstants.ODataTypeAnnotationName)
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "String open property with complex type information - should fail.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)),
                    Json = 
                        "{0}" +
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"TestModel.Address\"," +
                        "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"",
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "TestModel.Address", "Primitive", "Complex")
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "Type property after the data property - should fail.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)),
                    Json = 
                        "{0}" +
                        "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"," +
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\"" ,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_TypePropertyAfterValueProperty", JsonLightConstants.ODataTypeAnnotationName, JsonLightConstants.ODataValuePropertyName)
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "Duplicate data property - should fail.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)),
                    Json = 
                        "{0}" +
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\"," +
                        "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"," +
                        "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"",
                    ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", JsonLightConstants.ODataValuePropertyName)
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "Duplicate type property - should fail.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)),
                    Json = 
                        "{0}" +
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\"," +
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\"," +
                        "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"",
                    ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationNotAllowed", JsonLightConstants.ODataTypeAnnotationName)
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "No data property - should fail.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)),
                    Json = 
                        "{0}" +
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\"",
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyPayload")
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "No data property (only type property) - should fail.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)),
                    Json = 
                        "{0}" +
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\"",
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyPayload")
                },
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations,
                (testCase, testConfiguration) =>
                {
                    string json = string.Format(
                        CultureInfo.InvariantCulture,
                        testCase.Json,
                        testConfiguration.IsRequest
                            ? string.Empty
                            : "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.String\",");

                    PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings)
                    {
                        DebugDescription = testCase.DebugDescription,
                        PayloadElement = testCase.ExpectedProperty
                            .JsonRepresentation("{" + json + "}"),
                        PayloadEdmModel = model,
                        ExpectedException = testCase.ExpectedException,
                    };

                    // These descriptors are already tailored specifically for Json Light and 
                    // do not require normalization.
                    testDescriptor.TestDescriptorNormalizers.Clear();
                    testDescriptor.RunTest(testConfiguration);
                });
        }
        public void OpenComplexTopLevelPropertiesTest()
        {
            IEdmModel model = TestModels.BuildTestModel();

            var addressType = model.FindDeclaredType("TestModel.Address");

            var testCases = new OpenPropertyTestCase[]
            {
                new OpenPropertyTestCase
                {
                    DebugDescription = "Empty complex open property with type information.",
                    ExpectedProperty = PayloadBuilder.Property("OpenProperty", PayloadBuilder.ComplexValue("TestModel.Address")),
                    ExpectedPropertyType = addressType.ToTypeReference(),
                    JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"TestModel.Address\"",
                    Json = "{0}{1}",
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "Complex property with data.",
                    ExpectedProperty = PayloadBuilder.Property("OpenProperty", PayloadBuilder.ComplexValue("TestModel.Address").PrimitiveProperty("Street", "First")),
                    ExpectedPropertyType = addressType.ToTypeReference(),
                    JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"TestModel.Address\",",
                    Json = "{0}{1}\"Street\":\"First\"",
                },
            };

            bool[] withExpectedTypes = new bool[] { true, false };
            bool[] withPayloadTypes = new bool[] { true, false };
            bool[] includeContextUri = new bool[] { true, false };

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                withExpectedTypes,
                withPayloadTypes,
                includeContextUri,
                this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations,
                (testCase, withExpectedType, withPayloadType, withContextUri, testConfiguration) =>
                {
                    if (withContextUri && testConfiguration.IsRequest)
                    {
                        return;
                    }

                    PropertyInstance property = testCase.ExpectedProperty.DeepCopy();
                    ComplexProperty complexProperty = (ComplexProperty)property;
                    ComplexInstance complexValue = complexProperty.Value;
                    bool isEmpty = !complexValue.Properties.Any();

                    string contextUri = withContextUri ? "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#TestModel.Address\"," : string.Empty;
                    string json = string.Format(
                        CultureInfo.InvariantCulture,
                        testCase.Json,
                        contextUri,
                        withPayloadType ? testCase.JsonTypeInformation : string.Empty);

                    if (isEmpty && json.EndsWith(","))
                    {
                        json = json.Substring(0, json.Length - 1);
                    }

                    if (withExpectedType)
                    {
                        property = property.ExpectedPropertyType(testCase.ExpectedPropertyType);
                    }

                    if (!withPayloadType)
                    {
                        complexProperty.Value.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null });
                    }

                    ExpectedException expectedException = testCase.ExpectedException;
                    if (!withContextUri && !testConfiguration.IsRequest)
                    {
                        expectedException = ODataExpectedExceptions.ODataException("ODataJsonLightDeserializer_ContextLinkNotFoundAsFirstProperty");
                    }
                    else if (!withExpectedType && !withPayloadType && !withContextUri)
                    {
                        string firstPropertyName = isEmpty ? null : complexValue.Properties.First().Name;

                        // An open property without expected and payload type cannot be read; expect an exception.
                        expectedException = isEmpty
                            ? ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyPayload")
                            : ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyName", firstPropertyName, JsonLightConstants.ODataValuePropertyName);
                    }

                    PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings)
                    {
                        DebugDescription = testCase.DebugDescription + "[Expected type: " + withExpectedType + ", payload type: " + withPayloadType + "]",
                        PayloadElement = property
                            .JsonRepresentation("{" + json + "}"),
                        PayloadEdmModel = model,
                        ExpectedException = expectedException,
                    };

                    // These descriptors are already tailored specifically for Json Light and 
                    // do not require normalization.
                    testDescriptor.TestDescriptorNormalizers.Clear();

                    testDescriptor.RunTest(testConfiguration);
                });
        }
        public void OpenTopLevelPropertiesTest()
        {
            IEdmModel model = TestModels.BuildTestModel();

            var testCases = new OpenPropertyTestCase[]
            {   
                new OpenPropertyTestCase
                {
                    DebugDescription = "Integer open property.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", 42),
                    ExpectedPropertyWhenTypeUnavailable = PayloadBuilder.PrimitiveProperty("OpenProperty", 42),
                    ExpectedPropertyType = EdmCoreModel.Instance.GetInt32(false),
                    JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.Int32\",",
                    Json = "{0}{1}\"" + JsonLightConstants.ODataValuePropertyName + "\":42",
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "Null open property.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", null),
                    ExpectedPropertyWhenTypeUnavailable = PayloadBuilder.PrimitiveProperty("OpenProperty", null),
                    ExpectedPropertyType = EdmCoreModel.Instance.GetString(true),
                    JsonTypeInformation = string.Empty,
                    Json = "{0}{1}\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "String open property.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value"),
                    ExpectedPropertyWhenTypeUnavailable = PayloadBuilder.PrimitiveProperty("OpenProperty", "value"),
                    ExpectedPropertyType = EdmCoreModel.Instance.GetString(true),
                    JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\",",
                    Json = "{0}{1}\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"",
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "DateTimeOffset open property with type information.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", new DateTimeOffset(2012, 4, 13, 2, 43, 10, 215, TimeSpan.Zero)),
                    ExpectedPropertyWhenTypeUnavailable = PayloadBuilder.PrimitiveProperty("OpenProperty", "2012-04-13T02:43:10.215Z"),
                    ExpectedPropertyType = EdmCoreModel.Instance.GetDateTimeOffset(false),
                    JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.DateTimeOffset\",",
                    Json = "{0}{1}\"" + JsonLightConstants.ODataValuePropertyName + "\":\"2012-04-13T02:43:10.215Z\"",
                },
            };

            bool[] withExpectedTypes = new bool[] { true, false };
            bool[] withPayloadTypes = new bool[] { true, false };
            bool[] includeContextUri = new bool[] { true, false };

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                withExpectedTypes,
                withPayloadTypes,
                includeContextUri,
                this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations,
                (testCase, withExpectedType, withPayloadType, withContextUri, testConfiguration) =>
                {
                    if (withContextUri && testConfiguration.IsRequest)
                    {
                        return;
                    }

                    string expectedTypeName = testCase.ExpectedPropertyType is IEdmCollectionTypeReference ? "Collection(" + ((IEdmCollectionType)testCase.ExpectedPropertyType.Definition).ElementType.FullName() + ")" : testCase.ExpectedPropertyType.TestFullName();
                    string contextUri = withContextUri ? "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + string.Format("\":\"http://odata.org/test/$metadata#{0}\",", expectedTypeName) : string.Empty;
                    string json = string.Format(
                        CultureInfo.InvariantCulture,
                        testCase.Json,
                        contextUri,
                        withPayloadType ? testCase.JsonTypeInformation : string.Empty);

                    bool typeGiven = withExpectedType || withPayloadType || withContextUri;

                    if (!typeGiven && testCase.ExpectedPropertyWhenTypeUnavailable == null)
                    {
                        testCase.ExpectedException = ODataExpectedExceptions.ODataException("ReaderValidationUtils_ValueWithoutType");
                    }

                    PropertyInstance property = typeGiven || testCase.ExpectedPropertyWhenTypeUnavailable == null ? testCase.ExpectedProperty : testCase.ExpectedPropertyWhenTypeUnavailable;
                    property = property.DeepCopy();

                    if (withExpectedType)
                    {
                        property = property.ExpectedPropertyType(testCase.ExpectedPropertyType);
                    }

                    if (!withPayloadType)
                    {
                        ComplexProperty complexProperty = property as ComplexProperty;
                        if (complexProperty != null)
                        {
                            complexProperty.Value.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null });
                        }
                        else
                        {
                            PrimitiveMultiValueProperty primitiveCollectionProperty = property as PrimitiveMultiValueProperty;
                            if (primitiveCollectionProperty != null)
                            {
                                primitiveCollectionProperty.Value.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null });
                            }
                            else
                            {
                                ComplexMultiValueProperty complexCollectionProperty = property as ComplexMultiValueProperty;
                                if (complexCollectionProperty != null)
                                {
                                    complexCollectionProperty.Value.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null });
                                }
                            }
                        }
                    }

                    ExpectedException expectedException = testCase.ExpectedException;
                    if (!withContextUri && !testConfiguration.IsRequest)
                    {
                        expectedException = ODataExpectedExceptions.ODataException("ODataJsonLightDeserializer_ContextLinkNotFoundAsFirstProperty");
                    }

                    PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings)
                    {
                        DebugDescription = testCase.DebugDescription + "[Expected type: " + withExpectedType + ", payload type: " + withPayloadType + "]",
                        PayloadElement = property
                            .JsonRepresentation("{" + json + "}"),
                        PayloadEdmModel = model,
                        ExpectedException = expectedException,
                    };

                    // These descriptors are already tailored specifically for Json Light and 
                    // do not require normalization.
                    testDescriptor.TestDescriptorNormalizers.Clear();
                    testDescriptor.RunTest(testConfiguration);
                });
        }