Пример #1
0
        public void CollectionReaderAtomTest()
        {
            EdmModel       edmModel           = new EdmModel();
            EdmComplexType edmComplexTypeCity = edmModel.ComplexType("CityType", ModelNamespace);

            edmComplexTypeCity.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(true));
            edmModel.Fixup();

            IEnumerable <PayloadReaderTestDescriptor> testDescriptors = new[]
            {
                #region primitive collection

                // Empty primitive collection.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection().CollectionName(null),
                },

                // Yet another empty collection with extra elements not in the d namespace.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection().CollectionName(null)
                                     .XmlRepresentation("<m:value><c:foo xmlns:c='customns'>bar</c:foo></m:value>"),
                },

                // Empty collection with text inside the collection element.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection().CollectionName(null)
                                     .XmlRepresentation("<m:value>foo</m:value>"),
                },

                // Empty collection with insignificant nodes inside the collection element.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection().CollectionName(null)
                                     .XmlRepresentation("<m:value><!-- some comment -->  </m:value>"),
                },

                // TODO:: Currently the test infrastructure drops any top level node other than the root element.
                // Once the test infrstructure is fixed, we should add some test to verify that insignificant nodes
                // before the collection start are discarded.

                // Verify that anything which is not in the d namespace, after the collection start, is discarded.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection(
                        new PrimitiveValue[]
                    {
                        PayloadBuilder.PrimitiveValue("vineet"),
                    }
                        ).CollectionName(null)
                                     .XmlRepresentation(@"<m:value>
                                            <!-- some comment -->                    
                                            <c:foo xmlns:c='customns'>bar</c:foo>
                                            <m:element>vineet</m:element>
                                            <c:foo xmlns:c='customns'>bar</c:foo>
                                           </m:value>"),
                },

                // Verify that insignificant nodes after the collection end are discarded.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection().CollectionName(null)
                                     .XmlRepresentation(@"
                                            <m:value>
                                            </m:value>
                                            <!-- some comment -->                    
                                             some text
                                          "),
                },

                // Primitive collection with 'element' as collection name.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection(
                        new PrimitiveValue[]
                    {
                        PayloadBuilder.PrimitiveValue("vineet"),
                    }
                        ).CollectionName(null),
                },

                // Collection with 'element' as collection name.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection(
                        new PrimitiveValue[]
                    {
                        PayloadBuilder.PrimitiveValue("redmond"),
                        PayloadBuilder.PrimitiveValue(""),
                        PayloadBuilder.PrimitiveValue("seattle"),
                    }
                        ).XmlRepresentation(@"<m:value>            
                                             <m:element>redmond</m:element>
                                             <m:element/>
                                             <m:element>seattle</m:element>
                                            </m:value>")
                                     .CollectionName(null),
                },

                #endregion

                #region complex collection


                // yet another empty complex collection
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue("TestModel.CityType").PrimitiveProperty("Name", null)
                        ).CollectionName(null),
                },

                // Verify that anything which is not in the d namespace, after the collection start, is discarded.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue("TestModel.CityType").Property("City", PayloadBuilder.PrimitiveValue("Vienna"))
                        ).CollectionName(null)
                                     .XmlRepresentation(@"<m:value>
                                            <!-- some comment -->                    
                                            <c:foo xmlns:c='customns'>bar</c:foo>
                                            <m:element m:type='TestModel.CityType'>
                                                <c:foo xmlns:c='customns'>bar</c:foo>
                                                <d:City>Vienna</d:City>
                                                <!-- some more comments -->                            
                                            </m:element>
                                            <c:foo xmlns:c='customns'>bar</c:foo>
                                           </m:value>"),
                },

                // Verify that insignificant nodes after the collection end are discarded.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue("TestModel.CityType").Property("City", PayloadBuilder.PrimitiveValue("Vienna")))
                                     .CollectionName(null)
                                     .XmlRepresentation(@"
                                            <m:value>
                                               <m:element m:type='TestModel.CityType'>
                                                <d:City>Vienna</d:City>
                                               </m:element>
                                            </m:value>
                                            <!-- some comment -->                    
                                             some text
                                         "),
                },

                #endregion

                #region no metadata

                // primitive collection with no expected type and no metadata.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection(
                        PayloadBuilder.PrimitiveValue(1),
                        PayloadBuilder.PrimitiveValue(2)
                        ).CollectionName(null),
                },

                // complex collection with no expected type and no metadata.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue("TestModel.CityType").Property("Name", PayloadBuilder.PrimitiveValue("Vienna")),
                        PayloadBuilder.ComplexValue("TestModel.CityType").Property("Name", PayloadBuilder.PrimitiveValue("Am Euro Platz"))
                        ).CollectionName(null),
                },

                #endregion
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                testDescriptor.RunTest(testConfiguration);
            });
        }
Пример #2
0
        public void HomogeneousCollectionReaderWithoutMetadataAtomTest()
        {
            IEnumerable <PayloadReaderTestDescriptor> testDescriptors = new[]
            {
                // Primitive collection with only nulls
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection(
                        PayloadBuilder.PrimitiveValue(null),
                        PayloadBuilder.PrimitiveValue(null)
                        ).CollectionName(null),
                },

                // Primitive collection with type names on string values
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection(
                        PayloadBuilder.PrimitiveValue("foo"),
                        PayloadBuilder.PrimitiveValue("bar")
                        ).CollectionName(null),
                },

                // Primitive collection with type names on Int32 values
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection(
                        PayloadBuilder.PrimitiveValue(1),
                        PayloadBuilder.PrimitiveValue(2)
                        ).CollectionName(null),
                },

                // Primitive collection without type names on some string values
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection(
                        new PrimitiveValue("Edm.String", "foo"),
                        new PrimitiveValue(/*fullTypeName*/ null, "bar")
                        ).CollectionName(null),
                },

                // Primitive collection without type names on string values
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection(
                        new PrimitiveValue(/*fullTypeName*/ null, "foo"),
                        new PrimitiveValue(/*fullTypeName*/ null, "bar")
                        ).CollectionName(null),
                },

                // Primitive collection with type names on Int32 values and null values
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection(
                        PayloadBuilder.PrimitiveValue(1),
                        PayloadBuilder.PrimitiveValue(null),
                        PayloadBuilder.PrimitiveValue(2),
                        PayloadBuilder.PrimitiveValue(null)
                        ).CollectionName(null),
                },

                // Complex collection with type names on complex values
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue("TestModel.ComplexType").PrimitiveProperty("StringProperty", "abc"),
                        PayloadBuilder.ComplexValue("TestModel.ComplexType").PrimitiveProperty("StringProperty", "123")
                        ).CollectionName(null),
                },

                // Complex collection with type names on complex values and null values
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue("TestModel.ComplexType").PrimitiveProperty("StringProperty", "abc"),
                        PayloadBuilder.ComplexValue(null, /*isNull*/ true),
                        PayloadBuilder.ComplexValue("TestModel.ComplexType").PrimitiveProperty("StringProperty", "123")
                        ).CollectionName(null),
                },

                // Complex collection without type names on complex values
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue().PrimitiveProperty("Name", "Clemens"),
                        PayloadBuilder.ComplexValue().PrimitiveProperty("Name", "Vitek")
                        ).CollectionName(null),
                },

                // Complex collection without type names on complex values and null values
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue().PrimitiveProperty("FirstName", "Clemens"),
                        PayloadBuilder.ComplexValue(null, /*isNull*/ true),
                        PayloadBuilder.ComplexValue().PrimitiveProperty("LastName", "Kerer")
                        ).CollectionName(null),
                },
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                testDescriptor.RunTest(testConfiguration);
            });
        }
Пример #3
0
        public void CollectionReaderAtomErrorTest()
        {
            EdmModel edmModel = new EdmModel();

            EdmComplexType edmComplexTypeEmpty = new EdmComplexType(ModelNamespace, "EmptyComplexType");

            edmModel.AddElement(edmComplexTypeEmpty);

            EdmComplexType edmComplexTypeCity = new EdmComplexType(ModelNamespace, "CityType");

            edmComplexTypeCity.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(true));
            edmModel.AddElement(edmComplexTypeCity);

            EdmComplexType edmComplexTypeAddress = new EdmComplexType(ModelNamespace, "AddressType");

            edmComplexTypeAddress.AddStructuralProperty("Street", EdmCoreModel.Instance.GetString(true));
            edmModel.AddElement(edmComplexTypeAddress);

            edmModel.Fixup();

            IEnumerable <PayloadReaderTestDescriptor> testDescriptors = new[]
            {
                // Verify that collections do not support top level collection type.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection().CollectionName(null)
                                     .XmlRepresentation(@"<m:value>
                                           <m:element m:type='" + EntityModelUtils.GetCollectionTypeName("Edm.Int32") + @"'>
                                                <m:element>42</m:element>
                                           </m:element>
                                           </m:value>"),
                    PayloadEdmModel       = edmModel,
                    ExpectedException     = ODataExpectedExceptions.ODataException("CollectionWithoutExpectedTypeValidator_InvalidItemTypeKind", "Collection"),
                    SkipTestConfiguration = tc => tc.Version < Microsoft.OData.Core.ODataVersion.V4,
                },

                // Verify that collection inside complex type is not supported.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new  ComplexInstanceCollection().CollectionName(null)
                                     .XmlRepresentation(@"<m:value>
                                               <m:element>
                                                <m:element m:type='" + EntityModelUtils.GetCollectionTypeName("Edm.Int32") + @"'>
                                                 <m:element>42</m:element>
                                                </m:element>
                                               </m:element>
                                             </m:value>"),
                    PayloadEdmModel       = null, // No model, since otherwise we would fail to read the top-level item as it has no type information
                    ExpectedException     = ODataExpectedExceptions.ODataException("CollectionWithoutExpectedTypeValidator_InvalidItemTypeKind", "Collection"),
                    SkipTestConfiguration = tc => tc.Version < Microsoft.OData.Core.ODataVersion.V4,
                },

                // Collection with m:type attribute in the root collection element.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection().CollectionName(null)
                                     .XmlRepresentation("<m:value m:type='Edm.Int32'></m:value>"),
                    PayloadEdmModel   = edmModel,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomCollectionDeserializer_TypeOrNullAttributeNotAllowed"),
                },

                // Collection with m:null attribute in the Collection element.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection().CollectionName(null)
                                     .XmlRepresentation("<m:value m:null='true'></m:value>"),
                    PayloadEdmModel   = edmModel,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomCollectionDeserializer_TypeOrNullAttributeNotAllowed"),
                },

                // Collection with both m:type and m:null attribute in the Collection element.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection().CollectionName(null)
                                     .XmlRepresentation("<m:value m:null='true' m:type='Edm.Int32'></m:value>"),
                    PayloadEdmModel   = edmModel,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomCollectionDeserializer_TypeOrNullAttributeNotAllowed"),
                },

                // root collection element not in the d namespace.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection().CollectionName("PrimitiveCollection")
                                     .XmlRepresentation("<d:PrimitiveCollection></d:PrimitiveCollection>"),
                    PayloadEdmModel   = edmModel,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomCollectionDeserializer_TopLevelCollectionElementWrongNamespace", "http://docs.oasis-open.org/odata/ns/data", "http://docs.oasis-open.org/odata/ns/metadata"),
                },

                // complex value instead of collection.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection().CollectionName(null)
                                     .XmlRepresentation(@"<m:value>
                                              <m:city>Seattle</m:city>
                                             </m:value>"),
                    PayloadEdmModel   = edmModel,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomCollectionDeserializer_WrongCollectionItemElementName", "city", "http://docs.oasis-open.org/odata/ns/data", "http://docs.oasis-open.org/odata/ns/data"),
                },

                // complex collection with expected type and no metadata.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue("TestModel.CityType").Property("Name", PayloadBuilder.PrimitiveValue("Vienna")),
                        PayloadBuilder.ComplexValue("TestModel.CityType").Property("Name", PayloadBuilder.PrimitiveValue("Am Euro Platz"))
                        ).ExpectedCollectionItemType(edmComplexTypeCity).CollectionName(null),

                    ExpectedResultCallback = tc =>
                                             new PayloadReaderTestExpectedResult(this.PayloadExpectedResultSettings)
                    {
                        // There was no simple way to specify the complex type as the expected type, so specifying a primitive type as the
                        // expected type. Since the expected type is only used to trigger the exception any expected type works.
                        ReaderMetadata    = new PayloadReaderTestDescriptor.ReaderMetadata(EdmCoreModel.Instance.GetInt32(false)),
                        ExpectedException = ODataExpectedExceptions.ArgumentException("ODataMessageReader_ExpectedTypeSpecifiedWithoutMetadata", "expectedItemTypeReference"),
                    }
                },

                // primitive collection with expected type and no metadata.
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new PrimitiveCollection(
                        PayloadBuilder.PrimitiveValue(1),
                        PayloadBuilder.PrimitiveValue(2)
                        ).ExpectedCollectionItemType(EdmDataTypes.Int32).CollectionName(null),
                    ExpectedException = ODataExpectedExceptions.ArgumentException("ODataMessageReader_ExpectedTypeSpecifiedWithoutMetadata", "expectedItemTypeReference"),
                },
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                testDescriptor.RunTest(testConfiguration);
            });
        }
Пример #4
0
        public void HeterogeneousCollectionReaderAtomTest()
        {
            EdmModel edmModel = new EdmModel();

            EdmComplexType edmComplexTypeEmpty = new EdmComplexType(ModelNamespace, "EmptyComplexType");

            edmModel.AddElement(edmComplexTypeEmpty);

            EdmComplexType edmComplexTypeCity = new EdmComplexType(ModelNamespace, "CityType");

            edmComplexTypeCity.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(true));
            edmModel.AddElement(edmComplexTypeCity);

            EdmComplexType edmComplexTypeAddress = new EdmComplexType(ModelNamespace, "AddressType");

            edmComplexTypeAddress.AddStructuralProperty("Street", EdmCoreModel.Instance.GetString(true));
            edmModel.AddElement(edmComplexTypeAddress);

            edmModel.Fixup();

            IEnumerable <PayloadReaderTestDescriptor> testDescriptors = new[]
            {
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue("TestModel.CityType").Property("Name", PayloadBuilder.PrimitiveValue("Vienna")),
                        PayloadBuilder.ComplexValue("TestModel.AddressType").Property("Street", PayloadBuilder.PrimitiveValue("Am Euro Platz"))
                        ).ExpectedCollectionItemType(edmComplexTypeCity).CollectionName(null),
                    PayloadEdmModel   = edmModel,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncompatibleType", "TestModel.AddressType", "TestModel.CityType"),
                },

                // primitive collection with primitive and complex elements (with metadata, with expected types)
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveCollection()
                                     .ExpectedCollectionItemType(EdmDataTypes.String())
                                     .XmlRepresentation(@"<m:value>
                                                <m:element m:type='Edm.String'>Foo</m:element>
                                                <m:element m:type='TestModel.CityType'>
                                                    <d:Name m:type='Edm.String'>Perth</d:Name>
                                                </m:element>
                                             </m:value>"),
                    PayloadEdmModel   = edmModel,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "TestModel.CityType", "Primitive", "Complex"),
                },

                // complex collection with complex and primitive elements (with metadata, with expected types)
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = PayloadBuilder.ComplexCollection()
                                     .ExpectedCollectionItemType(edmComplexTypeCity)
                                     .XmlRepresentation(@"<m:value>
                                                <m:element m:type='TestModel.CityType'>
                                                    <d:Name m:type='Edm.String'>Perth</d:Name>
                                                </m:element>
                                                <m:element m:type='Edm.Int32'>123</m:element>
                                             </m:value>"),
                    PayloadEdmModel   = edmModel,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "Edm.Int32", "Complex", "Primitive"),
                },
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                testDescriptor.RunTest(testConfiguration);
            });
        }
Пример #5
0
        public void TopLevelPropertiesWithMetadataTest()
        {
            IEnumerable <PayloadReaderTestDescriptor> testDescriptors = PayloadReaderTestDescriptorGenerator.CreatePrimitiveValueTestDescriptors(this.Settings);

            testDescriptors = testDescriptors.Concat(PayloadReaderTestDescriptorGenerator.CreateComplexValueTestDescriptors(this.Settings, true));
            testDescriptors = testDescriptors.Concat(PayloadReaderTestDescriptorGenerator.CreateCollectionTestDescriptors(this.Settings, true));

            testDescriptors = testDescriptors.Select(collectionTestDescriptor => collectionTestDescriptor.InProperty("propertyName"));
            testDescriptors = testDescriptors.SelectMany(td => this.PayloadGenerator.GenerateReaderPayloads(td));

            // Limit to only top-level property payloads
            testDescriptors = testDescriptors.Where(td => td.PayloadElement is PropertyInstance);

            // Add a couple of invalid cases which use a standard model
            EdmModel model = new EdmModel();

            model.ComplexType("UnusedComplexType");

            EdmEntityType unusedEntityType = model.EntityType("UnusedEntityType");

            unusedEntityType.AddKeys(unusedEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, isNullable: false));
            unusedEntityType.Property("Name", EdmPrimitiveTypeKind.String, isNullable: false);

            EdmEntityType streamPropertyEntityType = model.EntityType("EntityTypeWithStreamProperty");

            streamPropertyEntityType.AddKeys(streamPropertyEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, isNullable: false));
            streamPropertyEntityType.AddStructuralProperty("Video", EdmPrimitiveTypeKind.Stream, isNullable: false);
            streamPropertyEntityType.Property("NonStreamProperty", EdmPrimitiveTypeKind.Boolean, isNullable: false);

            EdmEntityType navigationPropertyEntityType = model.EntityType("EntityTypeWithNavigationProperty");

            navigationPropertyEntityType.AddKeys(navigationPropertyEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32, isNullable: false));
            navigationPropertyEntityType.NavigationProperty("Navigation", streamPropertyEntityType);

            model.Fixup();

            EdmEntityContainer container = model.EntityContainer as EdmEntityContainer;

            EdmFunction nameFunction = new EdmFunction(container.Namespace, "NameFunctionImport", EdmCoreModel.Instance.GetInt32(false), false /*isBound*/, null, false /*isComposable*/);

            model.AddElement(nameFunction);
            container.AddFunctionImport("NameFunctionImport", nameFunction);
            model.Fixup();

            var videoPropertyType = model.GetEntityType("TestModel.EntityTypeWithStreamProperty").Properties().Single(p => p.Name == "Video").Type;

            var explicitTestDescriptors = new[]
            {
                // Non existant type name
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement    = PayloadBuilder.Property("propertyName", PayloadBuilder.ComplexValue("TestModel.NonExistantType")),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_UnrecognizedTypeName", "TestModel.NonExistantType"),
                    // This test has different meaning in JSON-L (no expected type + non-existent typename)
                    SkipTestConfiguration = (tc) => tc.Format == ODataFormat.Json,
                },
                // Existing type name without namespace
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement    = PayloadBuilder.Property("propertyName", PayloadBuilder.ComplexValue("UnusedComplexType")),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_UnrecognizedTypeName", "UnusedComplexType"),
                    // This test has different meaning in JSON-L (no expected type + non-existent typename)
                    SkipTestConfiguration = (tc) => tc.Format == ODataFormat.Json,
                },
                // Existing type of wrong kind
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement    = PayloadBuilder.Property("propertyName", PayloadBuilder.ComplexValue("TestModel.UnusedEntityType")),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectValueTypeKind", "TestModel.UnusedEntityType", "Entity"),
                    // This test has different meaning in JSON-L
                    SkipTestConfiguration = (tc) => tc.Format == ODataFormat.Json,
                },
                // A stream is not allowed in a property with a non-stream property kind.
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement         = PayloadBuilder.Entity("TestModel.EntityTypeWithStreamProperty").StreamProperty("NonStreamProperty", "http://readlink", "http://editlink"),
                    PayloadEdmModel        = model,
                    ExpectedResultCallback = tc =>
                                             new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException = tc.Format == ODataFormat.Atom
                                    ? tc.IsRequest
                                        ? null
                                        : ODataExpectedExceptions.ODataException("ValidationUtils_MismatchPropertyKindForStreamProperty", "NonStreamProperty")
                                    : tc.Format == ODataFormat.Json
                                        ? ODataExpectedExceptions.ODataException("ODataJsonLightEntryAndFeedDeserializer_PropertyWithoutValueWithWrongType", "NonStreamProperty", "Edm.Boolean")
                                        : ODataExpectedExceptions.ODataException("JsonReaderExtensions_UnexpectedNodeDetected", "PrimitiveValue", "StartObject")
                    },
                },
                // Top-level property of stream type is not allowed
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement    = PayloadBuilder.PrimitiveProperty("Video", 42).ExpectedPropertyType(videoPropertyType),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ArgumentException("ODataMessageReader_ExpectedPropertyTypeStream"),
                },
                // Top-level deferred navigation property is not allowed
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement    = PayloadBuilder.PrimitiveProperty("Video", 42).ExpectedPropertyType(streamPropertyEntityType),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ArgumentException("ODataMessageReader_ExpectedPropertyTypeEntityKind"),
                },
                // Top-level expanded navigation property is not allowed
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement    = PayloadBuilder.PrimitiveProperty("Video", 42).ExpectedPropertyType(streamPropertyEntityType),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ArgumentException("ODataMessageReader_ExpectedPropertyTypeEntityKind"),
                },
            };

            testDescriptors = testDescriptors.Concat(explicitTestDescriptors);

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                var property = testDescriptor.PayloadElement as PropertyInstance;
                if (property != null && testConfiguration.Format == ODataFormat.Atom)
                {
                    property.Name = null;
                }
                testDescriptor.RunTest(testConfiguration);
            });
        }
        public void ComplexValueTest()
        {
            var injectedProperties = new[]
            {
                new
                {
                    InjectedJSON      = string.Empty,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    InjectedJSON      = "\"@custom.annotation\": null",
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    InjectedJSON      = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataAnnotationNamespacePrefix + "unknown\": { }",
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    InjectedJSON      = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\": { }",
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties", JsonLightConstants.ODataContextAnnotationName)
                },
                new
                {
                    InjectedJSON      = "\"@custom.annotation\": null, \"@custom.annotation\": 42",
                    ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationNotAllowed", "custom.annotation")
                },
            };

            var payloads = new[]
            {
                new
                {
                    Json          = "{{{0}}}",
                    ExpectedValue = (ComplexInstance)PayloadBuilder.ComplexValue("TestModel.ComplexType")
                },
                new
                {
                    Json          = "{{{0}{1} \"Name\": \"Value\"}}",
                    ExpectedValue = (ComplexInstance)PayloadBuilder.ComplexValue("TestModel.ComplexType")
                                    .PrimitiveProperty("Name", "Value")
                },
                new
                {
                    Json          = "{{\"Name\": \"Value\"{1}{0}}}",
                    ExpectedValue = (ComplexInstance)PayloadBuilder.ComplexValue("TestModel.ComplexType")
                                    .PrimitiveProperty("Name", "Value")
                },
                new
                {
                    Json          = "{{\"Name\":\"Value\",{0}{1}\"City\":\"Redmond\"}}",
                    ExpectedValue = (ComplexInstance)PayloadBuilder.ComplexValue("TestModel.ComplexType")
                                    .PrimitiveProperty("Name", "Value")
                                    .PrimitiveProperty("City", "Redmond")
                },
            };

            EdmModel model = new EdmModel();

            var addressType = new EdmComplexType("TestModel", "Address");

            addressType.AddStructuralProperty("Street", EdmCoreModel.Instance.GetString(isNullable: false));

            var complexType = new EdmComplexType("TestModel", "ComplexType");

            complexType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(isNullable: false));
            complexType.AddStructuralProperty("City", EdmCoreModel.Instance.GetString(isNullable: false));
            complexType.AddStructuralProperty("Address", new EdmComplexTypeReference(addressType, isNullable: false));
            complexType.AddStructuralProperty("Location", EdmPrimitiveTypeKind.GeographyPoint);

            var owningType = new EdmEntityType("TestModel", "OwningType");

            owningType.AddKeys(owningType.AddStructuralProperty("ID", EdmCoreModel.Instance.GetInt32(isNullable: false)));
            owningType.AddStructuralProperty("TopLevelProperty", new EdmComplexTypeReference(complexType, isNullable: true));
            model.AddElement(owningType);
            model.AddElement(addressType);
            model.AddElement(complexType);

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

            container.AddEntitySet("OwningType", owningType);
            model.AddElement(container);

            IEnumerable <PayloadReaderTestDescriptor> testDescriptors = payloads.SelectMany(payload => injectedProperties.Select(injectedProperty =>
            {
                return(new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.Property("TopLevelProperty", payload.ExpectedValue.DeepCopy()
                                                             .JsonRepresentation(string.Format(payload.Json, injectedProperty.InjectedJSON, string.IsNullOrEmpty(injectedProperty.InjectedJSON) ? string.Empty : ","))
                                                             // JSON Light payloads don't store complex type names since the type can be inferred from the context URI and or API.
                                                             .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    }))
                                     .ExpectedProperty(owningType, "TopLevelProperty"),
                    PayloadEdmModel = model,
                    ExpectedException = injectedProperty.ExpectedException,
                    ExpectedResultPayloadElement = tc => tc.IsRequest
                        ? PayloadBuilder.Property(string.Empty, payload.ExpectedValue.DeepCopy()
                                                  .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    }))
                        : PayloadBuilder.Property("TopLevelProperty", payload.ExpectedValue.DeepCopy()
                                                  .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    }))
                });
            }));

            var explicitPayloads = new[]
            {
                new
                {
                    Description       = "Primitive value as complex - should fail.",
                    Json              = "42",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("JsonReaderExtensions_UnexpectedNodeDetected", "StartObject", "PrimitiveValue")
                },
                new
                {
                    Description       = "Array value as complex - should fail.",
                    Json              = "[]",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("JsonReaderExtensions_UnexpectedNodeDetected", "StartObject", "StartArray")
                },
                new
                {
                    Description = "Type annotation preceded by custom annotation - should fail",
                    Json        = "{" +
                                  "\"@custom.annotation\": null," +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\": \"TestModel.ComplexType\"," +
                                  "\"Name\": \"Value\"" +
                                  "}",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_ComplexTypeAnnotationNotFirst")
                },
                new
                {
                    Description = "Custom property annotation - should be ignored.",
                    Json        = "{" +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Name", "custom.annotation") + "\": null," +
                                  "\"Name\": \"Value\"" +
                                  "}",
                    ExpectedPayload = PayloadBuilder.ComplexValue("TestModel.ComplexType")
                                      .PrimitiveProperty("Name", "Value"),
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    Description = "Duplicate custom property annotation - should fail.",
                    Json        = "{" +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Name", "custom.annotation") + "\": null," +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Name", "custom.annotation") + "\": 42," +
                                  "\"Name\": \"Value\"" +
                                  "}",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", "custom.annotation", "Name")
                },
                new
                {
                    Description = "Unrecognized odata property annotation - should fail.",
                    Json        = "{" +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Name", JsonLightConstants.ODataAnnotationNamespacePrefix + "unknown") + "\": null," +
                                  "\"Name\": \"Value\"" +
                                  "}",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType").PrimitiveProperty("Name", "Value"),
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    Description = "Custom property annotation after the property - should fail.",
                    Json        = "{" +
                                  "\"Name\": \"Value\"," +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Name", "custom.annotation") + "\": null" +
                                  "}",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_PropertyAnnotationAfterTheProperty", "custom.annotation", "Name")
                },
                new
                {
                    Description = "OData property annotation.",
                    Json        = "{" +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Name", JsonLightConstants.ODataTypeAnnotationName) + "\": \"Edm.String\"," +
                                  "\"Name\": \"Value\"" +
                                  "}",
                    ExpectedPayload = PayloadBuilder.ComplexValue("TestModel.ComplexType")
                                      .PrimitiveProperty("Name", "Value"),
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    Description = "Duplicate odata property annotation.",
                    Json        = "{" +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Name", JsonLightConstants.ODataTypeAnnotationName) + "\": \"Edm.Int32\"," +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Name", JsonLightConstants.ODataTypeAnnotationName) + "\": \"Edm.String\"," +
                                  "\"Name\": \"Value\"" +
                                  "}",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataTypeAnnotationName, "Name")
                },
                new
                {
                    Description = "Property with object value and type name annotation - should fail.",
                    Json        = "{" +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Address", JsonLightConstants.ODataTypeAnnotationName) + "\":\"TestModel.Address\"," +
                                  "\"Address\":{}" +
                                  "}",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_ComplexValueWithPropertyTypeAnnotation", JsonLightConstants.ODataTypeAnnotationName)
                },
                new
                {
                    Description = "String property with type annotation after the property - should fail.",
                    Json        = "{" +
                                  "\"Name\":\"value\"," +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Name", JsonLightConstants.ODataTypeAnnotationName) + "\":\"Edm.String\"" +
                                  "}",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_PropertyAnnotationAfterTheProperty", JsonLightConstants.ODataTypeAnnotationName, "Name")
                },
                new
                {
                    Description = "String property with null type annotation - should fail.",
                    Json        = "{" +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Name", JsonLightConstants.ODataTypeAnnotationName) + "\":null," +
                                  "\"Name\":\"value\"" +
                                  "}",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_InvalidTypeName", string.Empty)
                },
                new
                {
                    Description = "null property with unknown type annotation - should fail.",
                    Json        = "{" +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Name", JsonLightConstants.ODataTypeAnnotationName) + "\":\"Unknown\"," +
                                  "\"Name\":null" +
                                  "}",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "Unknown", "Primitive", "Complex"),
                },
                new
                {
                    Description = "Spatial property with odata.type annotation inside the GeoJson object - should fail.",
                    Json        = "{" +
                                  "\"Location\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, GeographyFactory.Point(33.1, -110.0).Build(), "Edm.GeographyPoint") +
                                  "}",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_ODataTypeAnnotationInPrimitiveValue", JsonLightConstants.ODataTypeAnnotationName),
                },
                new
                {
                    Description = "Spatial property with odata.type annotation inside and outside the GeoJson object - should fail.",
                    Json        = "{" +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("Location", JsonLightConstants.ODataTypeAnnotationName) + "\":\"Edm.GeographyPoint\"," +
                                  "\"Location\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, GeographyFactory.Point(33.1, -110.0).Build(), "Edm.GeographyPoint") +
                                  "}",
                    ExpectedPayload   = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_ODataTypeAnnotationInPrimitiveValue", JsonLightConstants.ODataTypeAnnotationName),
                },
            };

            testDescriptors = testDescriptors.Concat(explicitPayloads.Select(payload =>
            {
                return(new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.Property("TopLevelProperty", payload.ExpectedPayload.DeepCopy()
                                                             .JsonRepresentation(payload.Json)
                                                             // JSON Light payloads don't store complex type names since the type can be inferred from the context URI and or API.
                                                             .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    }))
                                     // Don't reorder the properties on serialization
                                     .SetAnnotation(new JsonLightMaintainPropertyOrderAnnotation())
                                     .ExpectedProperty(owningType, "TopLevelProperty"),
                    PayloadEdmModel = model,
                    ExpectedException = payload.ExpectedException,
                    DebugDescription = payload.Description,
                    ExpectedResultPayloadElement = tc => tc.IsRequest
                        ? PayloadBuilder.Property(string.Empty, payload.ExpectedPayload.DeepCopy()
                                                  .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    }))
                        : PayloadBuilder.Property("TopLevelProperty", payload.ExpectedPayload.DeepCopy()
                                                  .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    }))
                });
            }));

            // Manual test descriptors
            testDescriptors = testDescriptors.Concat(new PayloadReaderTestDescriptor[]
            {
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "null complex value in request.",
                    PayloadElement   = PayloadBuilder.Property("TopLevelProperty", PayloadBuilder.ComplexValue("TestModel.ComplexType", true)
                                                               // JSON Light payloads don't store complex type names since the type can be inferred from the context URI and or API.
                                                               .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    }))
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true}")
                                       .ExpectedProperty(owningType, "TopLevelProperty"),
                    //PayloadModel = model,
                    PayloadEdmModel = model,
                    ExpectedResultPayloadElement = tc => PayloadBuilder.Property(string.Empty, PayloadBuilder.ComplexValue("TestModel.ComplexType", true)
                                                                                 .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    })),
                    SkipTestConfiguration = tc => !tc.IsRequest
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "null complex value in response.",
                    PayloadElement   = PayloadBuilder.Property("TopLevelProperty", PayloadBuilder.ComplexValue("TestModel.ComplexType", true)
                                                               // JSON Light payloads don't store complex type names since the type can be inferred from the context URI and or API.
                                                               .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    }))
                                       .JsonRepresentation(
                        "{" +
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#TestModel.ComplexType\"," +
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true" +
                        "}")
                                       .ExpectedProperty(owningType, "TopLevelProperty"),
                    //PayloadModel = model,
                    PayloadEdmModel = model,
                    ExpectedResultPayloadElement = tc => PayloadBuilder.Property("TopLevelProperty", PayloadBuilder.ComplexValue("TestModel.ComplexType", true)
                                                                                 .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    })),
                    SkipTestConfiguration = tc => tc.IsRequest
                }
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                // These descriptors are already tailored specifically for Json Light and
                // do not require normalization.
                testDescriptor.TestDescriptorNormalizers.Clear();
                testDescriptor.RunTest(testConfiguration);
            });
        }
        public void CollectionReaderTest()
        {
            IEdmModel           model     = Test.OData.Utils.Metadata.TestModels.BuildTestModel();
            IEdmEntityContainer container = model.FindEntityContainer("DefaultContainer");
            EdmOperationImport  primitiveCollectionResultOperation = container.FindOperationImports("PrimitiveCollectionResultOperation").Single() as EdmOperationImport;
            EdmOperationImport  complexCollectionResultOperation   = container.FindOperationImports("ComplexCollectionResultOperation").Single() as EdmOperationImport;

            var primitiveCollection = PayloadBuilder.PrimitiveCollection("PrimitiveCollectionResultOperation");

            primitiveCollection.Add(PayloadBuilder.PrimitiveValue(1));
            primitiveCollection.Add(PayloadBuilder.PrimitiveValue(2));
            primitiveCollection.Add(PayloadBuilder.PrimitiveValue(3));

            var complexCollection = PayloadBuilder.ComplexCollection("ComplexCollectionResultOperation");
            var complexValue1     = PayloadBuilder.ComplexValue("TestModel.Address")
                                    .PrimitiveProperty("Street", "Am Euro Platz")
                                    .AddAnnotation(new SerializationTypeNameTestAnnotation()
            {
                TypeName = null
            });

            complexCollection.Add(complexValue1);

            IEnumerable <PayloadReaderTestDescriptor> testDescriptors = new[]
            {
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Primitive collection - should work.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", \"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ] }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Complex collection - should work.",
                    PayloadEdmModel  = model,
                    PayloadElement   = complexCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(TestModel.Address)\", \"" + JsonLightConstants.ODataValuePropertyName + "\":[ { \"Street\":\"Am Euro Platz\" } ] }")
                                       .ExpectedFunctionImport(complexCollectionResultOperation),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "null collection - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy().JsonRepresentation("null")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("JsonReaderExtensions_UnexpectedNodeDetected", "StartObject", "PrimitiveValue")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Primitive value for collection - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy().JsonRepresentation("42")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("JsonReaderExtensions_UnexpectedNodeDetected", "StartObject", "PrimitiveValue")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Array value for collection - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy().JsonRepresentation("[]")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("JsonReaderExtensions_UnexpectedNodeDetected", "StartObject", "StartArray")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Extra property before collection property - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", \"extra\": null, \"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ] }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyName", "extra", "value")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Extra property after collection property - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", \"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ], \"extra\": null }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightCollectionDeserializer_CannotReadCollectionEnd", "extra")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Custom instance annotation before collection property - should work.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", \"@my.extra\": null, \"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ] }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Custom instance annotation after collection property - should work.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", \"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ], \"@my.extra\": null }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "OData instance annotations before collection property - should work.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\"," +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataCountAnnotationName + "\":3," +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNextLinkAnnotationName + "\":\"http://next-link\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ] }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "OData instance annotations after collection property - should work.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ]," +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNextLinkAnnotationName + "\":\"http://next-link\"," +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataCountAnnotationName + "\":3}")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Custom property annotation before collection property - should work.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", \"[email protected]\": null, \"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ] }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Custom property annotation on 'value' after collection property - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", \"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ], \"[email protected]\": null }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightCollectionDeserializer_CannotReadCollectionEnd", "value")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Custom property annotation on 'extra' before collection property - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", \"[email protected]\": null, \"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ] }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_TopLevelPropertyAnnotationWithoutProperty", "extra")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Custom property annotation on 'extra' after collection property - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", \"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ], \"[email protected]\": null }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightCollectionDeserializer_CannotReadCollectionEnd", "extra")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Invalid collection property name - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", \"invalid\":[ 1, 2, 3 ] }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyName", "invalid", JsonLightConstants.ODataValuePropertyName)
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Missing collection property - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\" }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightCollectionDeserializer_ExpectedCollectionPropertyNotFound", JsonLightConstants.ODataValuePropertyName)
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Invalid collection property value - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", \"" + JsonLightConstants.ODataValuePropertyName + "\":{} }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightCollectionDeserializer_CannotReadCollectionContentStart", "StartObject")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Invalid OData instance annotation before collection property - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", " +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataEditLinkAnnotationName + "\":null, " +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[] }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties", JsonLightConstants.ODataEditLinkAnnotationName)
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Invalid OData instance annotation after collection property - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", " +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[], " +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataEditLinkAnnotationName + "\":null }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightCollectionDeserializer_CannotReadCollectionEnd", JsonLightConstants.ODataEditLinkAnnotationName)
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Invalid OData instance annotation after collection property - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", " +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[], " +

                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataEditLinkAnnotationName + "\":null }")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightCollectionDeserializer_CannotReadCollectionEnd", JsonLightConstants.ODataEditLinkAnnotationName)
                },
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                // 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\"",
                },

                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 = ODataExpectedExceptions.ODataException("ReaderValidationUtils_ResourceWithoutType");
                }

                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 CollectionWithODataTypeReaderTest()
        {
            IEdmModel           model     = Test.OData.Utils.Metadata.TestModels.BuildTestModel();
            IEdmEntityContainer container = model.FindEntityContainer("DefaultContainer");
            EdmOperationImport  primitiveCollectionResultOperation = container.FindOperationImports("PrimitiveCollectionResultOperation").Single() as EdmOperationImport;
            EdmOperationImport  complexCollectionResultOperation   = container.FindOperationImports("ComplexCollectionResultOperation").Single() as EdmOperationImport;

            var primitiveCollection = PayloadBuilder.PrimitiveCollection("PrimitiveCollectionResultOperation");

            primitiveCollection.Add(PayloadBuilder.PrimitiveValue(1));
            primitiveCollection.Add(PayloadBuilder.PrimitiveValue(2));
            primitiveCollection.Add(PayloadBuilder.PrimitiveValue(3));

            var complexCollection = PayloadBuilder.ComplexCollection("ComplexCollectionResultOperation");
            var complexValue1     = PayloadBuilder.ComplexValue("TestModel.Address")
                                    .PrimitiveProperty("Street", "Am Euro Platz")
                                    .AddAnnotation(new SerializationTypeNameTestAnnotation()
            {
                TypeName = null
            });

            complexCollection.Add(complexValue1);

            // NOTE: tests to cover consistency between the expected function import and the function import
            //       in the payload exist in the ContextUriValidationJsonLightTests.
            IEnumerable <PayloadReaderTestDescriptor> testDescriptors = new[]
            {
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Non-collection type specified in odata.type - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", " +
                                                           "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"TestModel.Address\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ]" +
                                                           "}")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightCollectionDeserializer_InvalidCollectionTypeName", "TestModel.Address"),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Expected primitive item type and odata.type consistent - should work.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", " +
                                                           "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"Collection(Edm.Int32)\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ]" +
                                                           "}")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Expected complex item type and odata.type consistent - should work.",
                    PayloadEdmModel  = model,
                    PayloadElement   = complexCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(TestModel.Address)\", " +
                                                           "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"Collection(TestModel.Address)\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ { \"Street\": \"Am Euro Platz\"} ]" +
                                                           "}")
                                       .ExpectedFunctionImport(complexCollectionResultOperation),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Context URI (primitive collection) and odata.type consistent - should work.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", " +
                                                           "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"Collection(Edm.Int32)\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ]" +
                                                           "}")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation)
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Context URI (complex collection) and odata.type consistent - should work.",
                    PayloadEdmModel  = model,
                    PayloadElement   = complexCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(TestModel.Address)\", " +
                                                           "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"Collection(TestModel.Address)\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ { \"Street\": \"Am Euro Platz\"} ]" +
                                                           "}")
                                       .ExpectedFunctionImport(complexCollectionResultOperation),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Expected primitive item type and odata.type NOT consistent - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", " +
                                                           "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"Collection(Edm.Single)\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ]" +
                                                           "}")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncompatibleType", "Edm.Single", "Edm.Int32")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Expected primitive item type and odata.type NOT consistent (2) - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = primitiveCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(TestModel.Address)\", " +
                                                           "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"Collection(Edm.Int32)\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ 1, 2, 3 ]" +
                                                           "}")
                                       .ExpectedFunctionImport(complexCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "Edm.Int32", "Complex", "Primitive")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Expected complex item type and odata.type NOT consistent - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = complexCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(TestModel.Address)\", " +
                                                           "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"Collection(TestModel.OfficeType)\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ { \"Street\": \"Am Euro Platz\"} ]" +
                                                           "}")
                                       .ExpectedFunctionImport(complexCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "TestModel.OfficeType", "Complex", "Entity")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Expected primitive item type and odata.type NOT consistent (2) - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = complexCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", " +
                                                           "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"Collection(TestModel.Address)\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ { \"Street\": \"Am Euro Platz\"} ]" +
                                                           "}")
                                       .ExpectedFunctionImport(primitiveCollectionResultOperation),
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "TestModel.Address", "Primitive", "Complex")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Complex item type in context URI and odata.type NOT consistent - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = complexCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(TestModel.Address)\", " +
                                                           "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"Collection(TestModel.OfficeType)\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ { \"Street\": \"Am Euro Platz\"} ]" +
                                                           "}"),
                    SkipTestConfiguration = tc => tc.IsRequest,
                    ExpectedException     = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "TestModel.OfficeType", "Complex", "Entity")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Primitive item type in context URI and odata.type NOT consistent - should fail.",
                    PayloadEdmModel  = model,
                    PayloadElement   = complexCollection.DeepCopy()
                                       .JsonRepresentation("{" +
                                                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\", " +
                                                           "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"Collection(TestModel.Address)\"," +
                                                           "\"" + JsonLightConstants.ODataValuePropertyName + "\":[ { \"Street\": \"Am Euro Platz\"} ]" +
                                                           "}"),
                    SkipTestConfiguration = tc => tc.IsRequest,
                    ExpectedException     = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "TestModel.Address", "Primitive", "Complex")
                },
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                // These descriptors are already tailored specifically for Json Light and
                // do not require normalization.
                testDescriptor.TestDescriptorNormalizers.Clear();
                testDescriptor.RunTest(testConfiguration);
            });
        }
        public void CollectionWithoutExpectedTypeAndWithMetadataTest()
        {
            // For now only top-level property can do this.
            // TODO: Once we have open properties, these test cases apply to those as well, then probably move these to the top-level property
            // tests and share them from the open properties test, or possible keep both here.

            IEnumerable <PayloadReaderTestDescriptor> testDescriptors = this.CreateCollectionPayloadsWithMetadata(true);

            testDescriptors = testDescriptors.Concat(this.CreateInvalidCollectionsWithTypeNames(false));

            EdmModel       model           = new EdmModel();
            EdmComplexType itemComplexType = model.ComplexType("ItemComplexType").Property("stringProperty", EdmPrimitiveTypeKind.String);

            model = model.Fixup();

            testDescriptors = testDescriptors.Concat(new[]
            {
                // No expected type specified, the one in the payload should be enough
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement  = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.String")),
                    PayloadEdmModel = model,
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement  = PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName("TestModel.ItemComplexType")),
                    PayloadEdmModel = model,
                },

                // Verify that the item type is inherited from the collection to its items if the item doesn't specify the type
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName("TestModel.ItemComplexType"))
                                     .Item(PayloadBuilder
                                           .ComplexValue()
                                           .PrimitiveProperty("stringProperty", "test")
                                           .WithTypeAnnotation(itemComplexType)
                                           .AddAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    })),                                                                                             // Add item which does not have the type name
                    PayloadEdmModel = model
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName("TestModel.ItemComplexType"))
                                     .Item(PayloadBuilder
                                           .ComplexValue("TestModel.ItemComplexType")
                                           .PrimitiveProperty("stringProperty", "test")
                                           .WithTypeAnnotation(itemComplexType)) // Add an item which does have the type name
                                     .Item(PayloadBuilder
                                           .ComplexValue()
                                           .PrimitiveProperty("stringProperty", "test")
                                           .WithTypeAnnotation(itemComplexType)
                                           .AddAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    })),                                                                                             // Add item which does not have the type name
                    PayloadEdmModel = model
                }
            });

            // Wrap the value in a top-level property without expected type (can't use the .InProperty here, since that would put the expected type on it)
            testDescriptors = testDescriptors.Select(td =>
                                                     new PayloadReaderTestDescriptor(td)
            {
                PayloadElement = PayloadBuilder.Property("propertyName", td.PayloadElement)
            });

            // Fill in type names for expected result from the type annotations
            testDescriptors = testDescriptors.Select(td =>
            {
                td.ExpectedResultNormalizers.Add(tc => FillTypeNamesFromTypeAnnotationsPayloadElementVisitor.Visit);
                return(td);
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                // The version dependent behavior tests are implemented in the format specific tests.
                this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                testDescriptor.PayloadNormalizers.Add((tc) => tc.Format == ODataFormat.Json ? ReplaceExpectedTypeWithContextUriVisitor.VisitPayload : (Func <ODataPayloadElement, ODataPayloadElement>)null);

                var property = testDescriptor.PayloadElement as PropertyInstance;
                if (property != null && testConfiguration.Format == ODataFormat.Atom)
                {
                    property.Name = null;
                }

                testDescriptor.RunTest(testConfiguration);
            });
        }
        public IEnumerable <PayloadReaderTestDescriptor> CreateInvalidCollectionsWithTypeNames(bool expectedTypeWillBeUsed)
        {
            EdmModel       model           = new EdmModel();
            EdmComplexType itemComplexType = model.ComplexType("ItemComplexType");

            model.ComplexType("ExtraComplexType");
            model = model.Fixup();

            // Add invalid cases
            var testDescriptors = new[]
            {
                // Invalid collection type name
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue("")
                                     .WithTypeAnnotation(EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false))),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_UnrecognizedTypeName", string.Empty),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName(""))
                                     .WithTypeAnnotation(EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false))),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_UnrecognizedTypeName", EntityModelUtils.GetCollectionTypeName("")),
                },
                // Invalid collection type name
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue("collection(Edm.Int32)")
                                     .WithTypeAnnotation(EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false))),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_UnrecognizedTypeName", "collection(Edm.Int32)"),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue("foo")
                                     .WithTypeAnnotation(EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false))),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_UnrecognizedTypeName", "foo"),
                },

                // Non existant type name
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("TestModel.NonExistant"))
                                     .WithTypeAnnotation(EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false))),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_UnrecognizedTypeName", EntityModelUtils.GetCollectionTypeName("TestModel.NonExistant")),
                },

                // Type of the item differs from the type of the collection
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.String"))
                                     .Item(-42)
                                     .WithTypeAnnotation(EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetString(true))),
                    PayloadEdmModel        = model,
                    ExpectedResultCallback = tc =>
                                             new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException = tc.Format == ODataFormat.Atom ?
                                            ODataExpectedExceptions.ODataException("ValidationUtils_IncompatibleType", "Edm.Int32", "Edm.String") :
                                            ODataExpectedExceptions.ODataException("ReaderValidationUtils_CannotConvertPrimitiveValue", "-42", "Edm.String")
                    },
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName("TestModel.ItemComplexType"))
                                     .Item(PayloadBuilder.ComplexValue("TestModel.ExtraComplexType"))
                                     .WithTypeAnnotation(EdmCoreModel.GetCollection(itemComplexType.ToTypeReference())),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncompatibleType", "TestModel.ExtraComplexType", "TestModel.ItemComplexType"),
                }
            };

            if (expectedTypeWillBeUsed)
            {
                testDescriptors = testDescriptors.Concat(new[]
                {
                    // Type differs from the declared/expected type
                    new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.String"))
                                         .WithTypeAnnotation(EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false))),
                        PayloadEdmModel   = model,
                        ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncompatibleType", EntityModelUtils.GetCollectionTypeName("Edm.String"), EntityModelUtils.GetCollectionTypeName("Edm.Int32")),
                    },
                }).ToArray();
            }

            foreach (var testDescriptor in testDescriptors)
            {
                testDescriptor.PayloadNormalizers.Add((tc) => tc.Format == ODataFormat.Json ? AddJsonLightTypeAnnotationToCollectionsVisitor.Normalize : (Func <ODataPayloadElement, ODataPayloadElement>)null);
            }

            return(testDescriptors);
        }
        public void CollectionWithoutExpectedTypeAndWithoutMetadataTest()
        {
            const string complexType1Name = "TestModel.TestComplexType1";
            const string complexType2Name = "TestModel.TestComplexType2";

            #region Test cases where the collection does not specify a type name
            IEnumerable <PayloadReaderTestDescriptor> noCollectionTypeNameTestDescriptors = new[]
            {
                // Primitive collection containing items of the same primitive type
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue().Item(1).Item(2).Item(3)
                },
                // Primitive collection containing string items where some don't specify the type name
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue().Item("One").Item(new PrimitiveValue(/*fullTypeName*/ null, "Two")).Item("Three")
                },
                // Primitive collection containing string items where the first doesn't specify the type name
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue().Item(new PrimitiveValue(/*fullTypeName*/ null, "One")).Item("Two").Item("Three")
                },

                // Primitive collection containing items of different primitive types
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement         = PayloadBuilder.PrimitiveMultiValue().Item(1).Item(true).Item(2),
                    ExpectedResultCallback = tc => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException = ODataExpectedExceptions.ODataException("CollectionWithoutExpectedTypeValidator_IncompatibleItemTypeName", "Edm.Boolean", "Edm.Int32")
                    }
                },
                // Complex collection containing items of different complex type (correct type attribute value)
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexMultiValue()
                                     .Item(PayloadBuilder.ComplexValue(complexType1Name).PrimitiveProperty("Property1", "Foo"))
                                     .Item(PayloadBuilder.ComplexValue(complexType2Name).PrimitiveProperty("Property1", "Foo")),
                    ExpectedException = ODataExpectedExceptions.ODataException("CollectionWithoutExpectedTypeValidator_IncompatibleItemTypeName", complexType2Name, complexType1Name),
                },
                // Primitive collection containing items of different primitive types (including one not specifying the type name)
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement         = PayloadBuilder.PrimitiveMultiValue().Item(new PrimitiveValue(/*fullTypeName*/ null, "One")).Item("Two").Item(3),
                    ExpectedResultCallback = tc => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException = ODataExpectedExceptions.ODataException("CollectionWithoutExpectedTypeValidator_IncompatibleItemTypeName", "Edm.Int32", "Edm.String")
                    }
                },
                // Complex collection containing complex items without type names
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexMultiValue()
                                     .Item(PayloadBuilder.ComplexValue().PrimitiveProperty("Property1", "Foo"))
                                     .Item(PayloadBuilder.ComplexValue().PrimitiveProperty("Property2", "Bar")),
                },
            };
            #endregion Test cases where the collection does not specify a type name

            #region Test cases where the collection does specify a type name
            IEnumerable <PayloadReaderTestDescriptor> collectionTypeNameTestDescriptors = new[]
            {
                // Primitive collection containing items of the same primitive type and the items have type names as well
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.Int32")).Item(1).Item(2).Item(3)
                },
                // Primitive collection containing string items where some don't specify the type name
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.String")).Item("One").Item(new PrimitiveValue(/*fullTypeName*/ null, "Two")).Item("Three")
                },
                // Primitive collection containing string items where the first doesn't specify the type name
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.String")).Item(new PrimitiveValue(/*fullTypeName*/ null, "One")).Item("Two").Item("Three")
                },

                // Primitive collection containing some items of a different primitive type
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement         = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.String")).Item(new PrimitiveValue(/*fullTypeName*/ null, "One")).Item("Two").Item(3),
                    ExpectedResultCallback = tc => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException = ODataExpectedExceptions.ODataException("CollectionWithoutExpectedTypeValidator_IncompatibleItemTypeName", "Edm.Int32", "Edm.String")
                    }
                },
                // Primitive collection containing items of the same primitive type where some specify type names
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.Int32")).Item(1).Item(new PrimitiveValue(/*fullTypeName*/ null, 2)).Item(3),
                },
                // Primitive collection containing items of different primitive types
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement         = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.String")).Item(1).Item(true).Item(2),
                    ExpectedResultCallback = tc => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException = ODataExpectedExceptions.ODataException("CollectionWithoutExpectedTypeValidator_IncompatibleItemTypeName", "Edm.Int32", "Edm.String")
                    }
                },
                // Complex collection containing items of different complex type
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName(complexType1Name))
                                     .Item(PayloadBuilder.ComplexValue(complexType2Name).PrimitiveProperty("Property1", "Foo")),
                    ExpectedException = ODataExpectedExceptions.ODataException("CollectionWithoutExpectedTypeValidator_IncompatibleItemTypeName", complexType2Name, complexType1Name),
                },
                // Complex collection containing items of different complex type
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName(complexType1Name))
                                     .Item(PayloadBuilder.ComplexValue(complexType1Name).PrimitiveProperty("Property1", "Foo"))
                                     .Item(PayloadBuilder.ComplexValue(complexType2Name).PrimitiveProperty("Property1", "Foo")),
                    ExpectedException = ODataExpectedExceptions.ODataException("CollectionWithoutExpectedTypeValidator_IncompatibleItemTypeName", complexType2Name, complexType1Name),
                },
            };
            #endregion

            noCollectionTypeNameTestDescriptors = noCollectionTypeNameTestDescriptors.Select(td => td.InProperty());
            collectionTypeNameTestDescriptors   = collectionTypeNameTestDescriptors.Select(td => td.InProperty());

            this.CombinatorialEngineProvider.RunCombinations(
                noCollectionTypeNameTestDescriptors.Concat(collectionTypeNameTestDescriptors),
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations,  // only in ATOM since we don't support reading JSON without metadata yet
                (testDescriptor, testConfiguration) =>
            {
                testDescriptor.RunTest(testConfiguration);
            });
        }
        public void CollectionWithHeterogenousItemsErrorTest()
        {
            EdmModel model = new EdmModel();

            var complexType1 = model.ComplexType("ComplexTypeWithStringAndInteger32")
                               .Property("Property1", EdmCoreModel.Instance.GetString(true) as EdmTypeReference)
                               .Property("Property2", EdmCoreModel.Instance.GetInt32(false) as EdmTypeReference);

            var complexType2 = model.ComplexType("ComplexTypeWithStringAndDateTime")
                               .Property("Property1", EdmCoreModel.Instance.GetString(true) as EdmTypeReference)
                               .Property("Property2", EdmPrimitiveTypeKind.DateTimeOffset);

            model.Fixup();

            IEnumerable <PayloadReaderTestDescriptor> testDescriptors = new[]
            {
                // Primitive collection containing items of different primitive types
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement         = PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.Int32")).Item(1).Item(true).Item(2).WithTypeAnnotation(EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false))),
                    PayloadEdmModel        = model,
                    ExpectedResultCallback = tc => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException = tc.Format == ODataFormat.Atom ?
                                            ODataExpectedExceptions.ODataException("ValidationUtils_IncompatibleType", "Edm.Boolean", "Edm.Int32") :
                                            ODataExpectedExceptions.ODataException("ReaderValidationUtils_CannotConvertPrimitiveValue", "True", "Edm.Int32")
                    }
                },
                // Complex collection containing items of different complex type (correct type attribute value)
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName(complexType1.FullName()))
                                     .Item(PayloadBuilder.ComplexValue(complexType1.FullName()).PrimitiveProperty("Property1", "Foo").PrimitiveProperty("Property2", -1))
                                     .Item(PayloadBuilder.ComplexValue(complexType2.FullName()).PrimitiveProperty("Property1", "Foo").PrimitiveProperty("Property2", DateTimeOffset.Now))
                                     .WithTypeAnnotation(EdmCoreModel.GetCollection(complexType1.ToTypeReference())),
                    PayloadEdmModel   = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncompatibleType", "TestModel.ComplexTypeWithStringAndDateTime", "TestModel.ComplexTypeWithStringAndInteger32"),
                },
                // Complex collection containing items of different complex type (incorrect type attribute value)
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName(complexType2.FullName()))
                                     .Item(PayloadBuilder.ComplexValue(complexType2.FullName()).PrimitiveProperty("Property1", "Foo").PrimitiveProperty("Property2", -1))
                                     .Item(PayloadBuilder.ComplexValue(complexType2.FullName()).PrimitiveProperty("Property1", "Foo").PrimitiveProperty("Property2", DateTimeOffset.Now))
                                     .WithTypeAnnotation(EdmCoreModel.GetCollection(complexType2.ToTypeReference())),
                    PayloadEdmModel        = model,
                    ExpectedResultCallback = tc => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                    {
                        ExpectedException = tc.Format == ODataFormat.Atom ?
                                            ODataExpectedExceptions.ODataException("ValidationUtils_IncompatibleType", "Edm.Int32", "Edm.DateTimeOffset") :
                                            ODataExpectedExceptions.ODataException("ReaderValidationUtils_CannotConvertPrimitiveValue", "-1", "Edm.DateTimeOffset")
                    }
                },
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                if (testConfiguration.Format == ODataFormat.Atom)
                {
                    testDescriptor = testDescriptor.InProperty();
                }
                else
                {
                    testDescriptor = testDescriptor.InProperty("RootProperty");
                }

                testDescriptor.RunTest(testConfiguration);
            });
        }