public ODataJsonLightParameterReaderTests()
 {
     referencedModel = new EdmModel();
     referencedModel.Fixup();
     this.action = new EdmAction("FQ.NS", "ActionImport", null);
     referencedModel.AddElement(this.action);
     this.model = TestUtils.WrapReferencedModelsToMainModel("TestModel", "DefaultContainer", referencedModel);
 }
 public void Init()
 {
     referencedModel = new EdmModel();
     referencedModel.Fixup();
     this.action = new EdmAction("FQ.NS", "ActionImport", null);
     referencedModel.AddElement(this.action);
     this.model = TestUtils.WrapReferencedModelsToMainModel("TestModel", "DefaultContainer", referencedModel);
 }
        public void ComplexValueTest()
        {
            EdmModel model = new EdmModel();

            var emptyComplexType = new EdmComplexType(DefaultNamespaceName, "EmptyComplexType");
            model.AddElement(emptyComplexType);

            var complexTypeWithStringProperty = new EdmComplexType(DefaultNamespaceName, "ComplexTypeWithStringProperty");
            complexTypeWithStringProperty.AddStructuralProperty("stringProperty", EdmCoreModel.Instance.GetString(isNullable: true));
            complexTypeWithStringProperty.AddStructuralProperty("numberProperty", EdmCoreModel.Instance.GetInt32(isNullable: false));
            model.AddElement(complexTypeWithStringProperty);

            model.Fixup();
            

            IEnumerable<PayloadReaderTestDescriptor> testDescriptors = new[]
            {
                // Empty element is a valid complex value
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexValue("TestModel.EmptyComplexType")
                        .XmlValueRepresentation(new XNode[0])
                        .WithTypeAnnotation(emptyComplexType),
                    PayloadEdmModel = model
                },
            };

            testDescriptors = testDescriptors.Concat(
                PropertiesElementAtomValues.CreatePropertiesElementPaddingPayloads<ComplexInstance>(
                    new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.ComplexValue("TestModel.ComplexTypeWithStringProperty")
                            .WithTypeAnnotation(complexTypeWithStringProperty),
                        PayloadEdmModel = model
                    },
                    (complexInstance, xmlValue) => complexInstance.XmlValueRepresentation(xmlValue)));

            testDescriptors = testDescriptors.Select(td => td.InProperty());

            testDescriptors = testDescriptors.Concat(new []
            {
                // Top-level property without expected type and no type name - this is read as primitive string!
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.Property(null, PayloadBuilder.PrimitiveValue(string.Empty))
                        .XmlRepresentation("<m:value/>"),
                    PayloadEdmModel = model,
                },
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations,
                (testDescriptor, testConfiguration) =>
                {
                    testDescriptor.RunTest(testConfiguration);
                });
        }
 static ODataJsonLightReaderIntegrationTests()
 {
     EdmModel tmp = new EdmModel();
     EntityType = new EdmEntityType("Namespace", "EntityType");
     EdmEntityContainer edmEntityContainer = new EdmEntityContainer("Namespace", "Container_sub");
     EntitySet = edmEntityContainer.AddEntitySet("EntitySet", EntityType);
     tmp.AddElement(edmEntityContainer);
     tmp.Fixup();
     Model = TestUtils.WrapReferencedModelsToMainModel("Namespace", "Container", tmp);
 }
        static ODataAtomWriterIntegrationTests()
        {
            Model = new EdmModel();
            EntityType = new EdmEntityType("Namespace", "EntityType");

            Model.AddElement(EntityType);
            var entityContainer = new EdmEntityContainer("Namespace", "Container");
            EntitySet = entityContainer.AddEntitySet("EntitySet", EntityType);
            Model.AddElement(entityContainer);
            Model.Fixup();
        }
        public void HeterogeneousCollectionReaderTest()
        {
            EdmModel model = new EdmModel();
            var cityType = new EdmComplexType("TestModel", "CityType");
            cityType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(true));
            model.AddElement(cityType);

            var addressType = new EdmComplexType("TestModel", "AddressType");
            addressType.AddStructuralProperty("Street", EdmCoreModel.Instance.GetString(true));
            model.AddElement(addressType);

            var testContainer = new EdmEntityContainer("TestModel", "TestContainer");
            model.AddElement(testContainer);
            EdmFunction citiesFunction = new EdmFunction("TestModel", "Cities", EdmCoreModel.GetCollection(cityType.ToTypeReference()));
            model.AddElement(citiesFunction);
            EdmOperationImport citiesFunctionImport = testContainer.AddFunctionImport("Cities", citiesFunction);
            model.Fixup();
            
            // Add some hand-crafted payloads
            IEnumerable<PayloadReaderTestDescriptor> testDescriptors = new PayloadReaderTestDescriptor[]
            {
                // expected type without type names in the payload and heterogeneous items
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue().Property("Name", PayloadBuilder.PrimitiveValue("Vienna")),
                        PayloadBuilder.ComplexValue().Property("Street", PayloadBuilder.PrimitiveValue("Am Euro Platz")))
                        .ExpectedFunctionImport(citiesFunctionImport)
                        .CollectionName(null),
                    PayloadEdmModel = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_PropertyDoesNotExistOnType", "Street", "TestModel.CityType"),
                },
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations,
                (testDescriptor, testConfiguration) =>
                {
                    testDescriptor.RunTest(testConfiguration);
                });
        }
        public void NavigationPropertiesProjectionTest()
        {
            EdmModel model = new EdmModel();

            EdmEntityType townType = model.EntityType("TownType");
            townType.KeyProperty("Id", EdmCoreModel.Instance.GetInt32(false) as EdmTypeReference);
            townType.NavigationProperty("NavProp1", townType);
            EdmEntitySet townsSet = model.EntitySet("Towns", townType);

            EdmEntityType cityType = new EdmEntityType("TestModel", "CityType", townType);
            model.AddElement(cityType);
            cityType.NavigationProperty("NavProp2", townType);
            model.EntitySet("Cities", cityType);

            EdmEntityType cityType2 = new EdmEntityType("TestModel", "DuplicateCityType", townType);
            model.AddElement(cityType2);
            cityType2.NavigationProperty("NavProp2", townType);
            model.EntitySet("DuplicateCities", cityType2);

            model.Fixup();

            var testCases = new ProjectionTestCase[]
            {
                #region No $select
                new ProjectionTestCase
                {
                    DebugDescription = "No $select => two templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1)
                        .NavigationProperty("NavProp1", /*url*/null).NavigationProperty("NavProp2", /*url*/null),
                    ProjectionString = null,
                },
                new ProjectionTestCase
                {
                    DebugDescription = "No $select + one property in the payload => one templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1)
                        .NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", /*url*/null),
                    ProjectionString = null,
                },
                new ProjectionTestCase
                {
                    DebugDescription = "No $select + two properties in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1)
                        .NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ProjectionString = null,
                },
                #endregion No $select
                #region Empty $select
                new ProjectionTestCase
                {
                    DebugDescription = "Empty $select => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ProjectionString = string.Empty,
                },
                new ProjectionTestCase
                {
                    DebugDescription = "Empty $select + one property in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1"),
                    ProjectionString = string.Empty,
                },
                new ProjectionTestCase
                {
                    DebugDescription = "Empty $select + two properties in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ProjectionString = string.Empty,
                },
                #endregion Empty $select
                #region $select=*
                new ProjectionTestCase
                {
                    DebugDescription = "$select=* => two templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", /*url*/null).NavigationProperty("NavProp2", /*url*/null),
                    ProjectionString = "*",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=* + one property in the payload => one templatized property.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp2", "http://odata.org/nav2").NavigationProperty("NavProp1", /*url*/null),
                    ProjectionString = "*",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=* + two properties in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ProjectionString = "*",
                },
                #endregion $select=*
                #region $select=NavProp2,*
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp2,* => two templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", /*url*/null).NavigationProperty("NavProp2", /*url*/null),
                    ProjectionString = "NavProp2,*",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp2,* + NavProp2 property in the payload => one templatized property.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp2", "http://odata.org/nav2").NavigationProperty("NavProp1", /*url*/null),
                    ProjectionString = "NavProp2,*",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp2,* + NavProp1 property in the payload => one templatized property.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", /*url*/null),
                    ProjectionString = "NavProp2,*",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp2,* + two properties in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ProjectionString = "NavProp2,*",
                },
                #endregion $select=NavProp2,*
                #region $select=NavProp1,NavProp2
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp1,NavProp2 => two templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", /*url*/null).NavigationProperty("NavProp2", /*url*/null),
                    ProjectionString = "NavProp1,NavProp2",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp1,NavProp2 + NavProp2 property in the payload => one templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp2", "http://odata.org/nav2").NavigationProperty("NavProp1", /*url*/null),
                    ProjectionString = "NavProp1,NavProp2",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp1,NavProp2 + two properties in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ProjectionString = "NavProp1,NavProp2",
                },
                #endregion $select=NavProp1,NavProp2
                #region $select=NavProp2
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp2 => one templatized property.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp2", /*url*/null),
                    ProjectionString = "NavProp2",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp2 + NavProp2 property in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ProjectionString = "NavProp2",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp2 + NavProp1 property in the payload => one templatized property.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", /*url*/null),
                    ProjectionString = "NavProp2",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp2 + two properties in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", "http://odata.org/nav1").NavigationProperty("NavProp2", "http://odata.org/nav2"),
                    ProjectionString = "NavProp2",
                },
                #endregion $select=NavProp2
                #region $select=NavProp1/*
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp1/* => three templatized stream properties and and one templatized navigation.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2)),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).NavigationProperty("NavProp1", /*url*/null).NavigationProperty("NavProp2", /*url*/null)),
                    ProjectionString = "NavProp1/*",
                },
                #endregion $select=NavProp/*
                #region $select=NavProp1/NavProp1
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp1/NavProp1 => one templatized navigation property.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2)),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).NavigationProperty("NavProp1", /*url*/null)),
                    ProjectionString = "NavProp1/NavProp1",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp1/NavProp1 with expand => two templatized navigation properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 3))),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 3).NavigationProperty("NavProp1", /*url*/null).NavigationProperty("NavProp2", /*url*/null))),
                    ProjectionString = "NavProp1/NavProp1",
                },
                #endregion $select=NavProp1/NavProp1
                #region $select=TestModel.CityType/NavProp2
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.CityType/NavProp2 on base type => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1),
                    ProjectionString = "TestModel.CityType/NavProp2",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.CityType/NavProp2 on derived type => specific property templatized.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp2", /*url*/null),
                    ProjectionString = "TestModel.CityType/NavProp2",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.CityType/NavProp2 on different derived type => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.DuplicateCityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.DuplicateCityType").PrimitiveProperty("Id", 1),
                    ProjectionString = "TestModel.CityType/NavProp2",
                },
                #endregion $select=TestModel.CityType/NavProp2
                #region $select=TestModel.CityType/NavProp1
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.CityType/NavProp1 on base type => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1),
                    ProjectionString = "TestModel.CityType/NavProp1",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.CityType/NavProp1 on derived type => specific property templatized.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", /*url*/null),
                    ProjectionString = "TestModel.CityType/NavProp1",
                },
                #endregion $select=TestModel.CityType/NavProp1
                #region $select=TestModel.TownType/NavProp1
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.TownType/NavProp1 on base type => specific property templatized..",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", /*url*/null),
                    ProjectionString = "TestModel.TownType/NavProp1",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.TownType/NavProp1 on derived type => specific property templatized.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).NavigationProperty("NavProp1", /*url*/null),
                    ProjectionString = "TestModel.TownType/NavProp1",
                },
                #endregion $select=TestModel.TownType/NavProp1
                #region $select=NavProp1/TestModel.City/NavProp2
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp1/TestModel.TownType/NavProp2 on expanded base type => no templatized property.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 2)),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 2)),
                    ProjectionString = "NavProp1/TestModel.TownType/NavProp2",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp1/TestModel.TownType/NavProp2 on expanded derived type type => specific templatized property.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2)),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).NavigationProperty("NavProp2", /*url*/null)),
                    ProjectionString = "NavProp1/TestModel.TownType/NavProp2",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.CityType/* on different derived type => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.DuplicateCityType").PrimitiveProperty("Id", 2)),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp1", PayloadBuilder.Entity("TestModel.DuplicateCityType").PrimitiveProperty("Id", 2)),
                    ProjectionString = "TestModel.CityType/*",
                },
                #endregion $select=NavProp1/TestModel.City/NavProp2
            };

            IEnumerable<PayloadReaderTestDescriptor> testDescriptors = testCases.Select(testCase =>
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = testCase.DebugDescription,
                    PayloadEdmModel = model,
                    PayloadElement = testCase.PayloadEntity
                        .WithContextUriProjection(testCase.ProjectionString)
                        .ExpectedEntityType(townType, townsSet),
                    ExpectedResultPayloadElement = tc => testCase.ExpectedEntity,
                    ExpectedException = testCase.ExpectedException,
                });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations.Where(tc => !tc.IsRequest),
                (testDescriptor, testConfiguration) =>
                {
                    // These descriptors are already tailored specifically for Json Light and 
                    // do not require normalization.
                    testDescriptor.TestDescriptorNormalizers.Clear();
                    testDescriptor.RunTest(testConfiguration);
                });
        }
        public void ComplexValueWithMetadataTest()
        {
            // Use some standard complex value payloads first
            IEnumerable<PayloadReaderTestDescriptor> testDescriptors = PayloadReaderTestDescriptorGenerator.CreateComplexValueTestDescriptors(this.Settings, true);

            // Add metadata validation tests
            EdmModel model = new EdmModel();
            var innerComplexType = model.ComplexType("InnerComplexType");
            innerComplexType.AddStructuralProperty("name", EdmCoreModel.Instance.GetString(true));

            var complexType = model.ComplexType("ComplexType");
            complexType.AddStructuralProperty("number", EdmPrimitiveTypeKind.Int32);
            complexType.AddStructuralProperty("string", EdmCoreModel.Instance.GetString(true));
            complexType.AddStructuralProperty("complex", MetadataUtils.ToTypeReference(innerComplexType, true));

            var entityType = model.EntityType("EntityType");
            entityType.KeyProperty("Id", EdmCoreModel.Instance.GetInt32(false));
            model.Fixup();

            // Test that different types of properties not present in the metadata all fail
            IEnumerable<PropertyInstance> undeclaredPropertyTestCases = new PropertyInstance[]
            {
                PayloadBuilder.PrimitiveProperty("undeclared", 42),
                PayloadBuilder.Property("undeclared", PayloadBuilder.ComplexValue(innerComplexType.FullName())),
                PayloadBuilder.Property("undeclared", PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.Int32"))),
                PayloadBuilder.Property("undeclared", PayloadBuilder.ComplexMultiValue(EntityModelUtils.GetCollectionTypeName("TestModel.InnerComplexType"))),
            };

            testDescriptors = testDescriptors.Concat(
                undeclaredPropertyTestCases.Select(tc =>
                {
                    return new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.ComplexValue(complexType.FullName()).WithTypeAnnotation(complexType)
                            .Property(tc),
                        PayloadEdmModel = model,
                        ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_PropertyDoesNotExistOnType", "undeclared", "TestModel.ComplexType"),
                    };
                }));

            testDescriptors = testDescriptors.Concat(new[]
            {
                // Property which should take typename not from value but from the parent metadata
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexValue(complexType.FullName()).WithTypeAnnotation(complexType)
                        .Property("complex", PayloadBuilder.ComplexValue(innerComplexType.FullName()).PrimitiveProperty("name", null)
                            .JsonRepresentation("{ \"name\" : null }").XmlRepresentation("<d:name m:null=\"true\" />")
                            .AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null })),
                    PayloadEdmModel = model,
                },
                // Property which is declared in the metadata but with a different type
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexValue(complexType.FullName()).WithTypeAnnotation(complexType)
                        .Property("complex", PayloadBuilder.ComplexValue(complexType.FullName())),
                    PayloadEdmModel = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncompatibleType", "TestModel.ComplexType", "TestModel.InnerComplexType"),
                },
                // Property which is declared in the metadata but with a wrong kind
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexValue(complexType.FullName()).WithTypeAnnotation(complexType)
                        .Property("complex", PayloadBuilder.ComplexValue(entityType.FullName())),
                    PayloadEdmModel = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "TestModel.EntityType", "Complex", "Entity"),
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexValue("").WithTypeAnnotation(complexType),
                    PayloadEdmModel = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_UnrecognizedTypeName", string.Empty)
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.ComplexValue("TestModel.NonExistant").WithTypeAnnotation(complexType),
                    PayloadEdmModel = model,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_UnrecognizedTypeName", "TestModel.NonExistant"),
                },
            });

            // Wrap the complex type in a property
            testDescriptors = testDescriptors
                .Select((td, index) => new PayloadReaderTestDescriptor(td) { PayloadDescriptor = td.PayloadDescriptor.InProperty("propertyName" + index)})
                .SelectMany(td => this.PayloadGenerator.GenerateReaderPayloads(td));

            // Handcrafted cases
            testDescriptors = testDescriptors.Concat(new[]
            {
                // Top-level complex property without expected type
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = PayloadBuilder.Property("property", PayloadBuilder.ComplexValue(complexType.FullName()).PrimitiveProperty("number", 42)),
                    PayloadEdmModel = model
                },
            });

            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);
                });
        }
Exemple #9
0
        /// <summary>
        /// Creates a feed containing entities of types that derive from the same base 
        /// </summary>
        /// <param name="model">The entity model schema. The method will modify the model and call Fixup().</param>
        /// <param name="withTypeNames">True if the payloads should specify type names.</param>
        /// <returns>The feed containing derived typed entities.</returns>
        public static IEnumerable<Taupo.OData.Common.PayloadTestDescriptor> GetFeeds(EdmModel model, bool withTypeNames)
        {
            ExceptionUtilities.CheckArgumentNotNull(model, "model");
            List<Taupo.OData.Common.PayloadTestDescriptor> payloads = new List<Taupo.OData.Common.PayloadTestDescriptor>();

            EdmEntityType baseType = model.EntityType("MyBaseType").KeyProperty("Id", (EdmPrimitiveTypeReference) EdmCoreModel.Instance.GetGuid(false));
            model.Fixup();

            EntityInstance instance = PayloadBuilder.Entity(withTypeNames ? "TestModel." + baseType.Name : null).Property("Id", PayloadBuilder.PrimitiveValue(Guid.NewGuid()));
            instance.Id = "urn:id";

            EntitySetInstance emptySet = PayloadBuilder.EntitySet().WithTypeAnnotation(baseType);

            payloads.Add(new Taupo.OData.Common.PayloadTestDescriptor() 
            { 
                PayloadEdmModel = model, 
                PayloadElement = emptySet
            });

            var emptySetWithInlineCount = emptySet.DeepCopy();
            emptySetWithInlineCount.InlineCount = 0;

            // Inline count (note we skip for v1 and request because inline count is valid on response only on V2 and above.
            payloads.Add(new Taupo.OData.Common.PayloadTestDescriptor()
            {
                PayloadEdmModel = model,
                PayloadElement = emptySetWithInlineCount,
                SkipTestConfiguration = (tc => tc.IsRequest)
            });

            var emptySetWithNextLinkAndCount = emptySet.DeepCopy();
            emptySetWithNextLinkAndCount.InlineCount = 0;
            emptySetWithNextLinkAndCount.NextLink = "http://www.odata.org/Feed";
            
            // inline count + next link
            payloads.Add(new Taupo.OData.Common.PayloadTestDescriptor()
            {
                PayloadEdmModel = model,
                PayloadElement = emptySetWithNextLinkAndCount,
                SkipTestConfiguration = (tc => tc.IsRequest)
            });

            var emptySetWithNextLink = emptySet.DeepCopy();
            emptySetWithNextLink.NextLink = "http://www.odata.org/Feed";

            // next link
            payloads.Add(new Taupo.OData.Common.PayloadTestDescriptor()
            {
                PayloadEdmModel = model,
                PayloadElement = emptySetWithNextLink,
                SkipTestConfiguration = (tc => tc.IsRequest)
            });

            EntitySetInstance singleEntity = PayloadBuilder.EntitySet().Append(instance).WithTypeAnnotation(baseType);

            payloads.Add(new Taupo.OData.Common.PayloadTestDescriptor()
            {
                PayloadEdmModel = model,
                PayloadElement = singleEntity.DeepCopy()
            });

            var singleEntityWithInlineCount = singleEntity.DeepCopy();
            singleEntityWithInlineCount.InlineCount = 1;

            // inline count
            payloads.Add(new Taupo.OData.Common.PayloadTestDescriptor()
            {
                PayloadEdmModel = model,
                PayloadElement = singleEntityWithInlineCount,
                SkipTestConfiguration = (tc => tc.IsRequest)
            });

            var singleEntityWithNextLinkAndCount = singleEntity.DeepCopy();
            singleEntityWithInlineCount.InlineCount = 1;
            singleEntityWithNextLinkAndCount.NextLink = "http://www.odata.org/Feed";

            // inline count + next link
            payloads.Add(new Taupo.OData.Common.PayloadTestDescriptor()
            {
                PayloadEdmModel = model,
                PayloadElement = singleEntityWithNextLinkAndCount,
                SkipTestConfiguration = (tc => tc.IsRequest)
            });

            var singleEntityWithNextLink = singleEntity.DeepCopy();
            singleEntityWithNextLink.NextLink = "http://www.odata.org/Feed";

            // next link 
            payloads.Add(new Taupo.OData.Common.PayloadTestDescriptor()
            {
                PayloadEdmModel = model,
                PayloadElement = singleEntityWithNextLink,
                SkipTestConfiguration = (tc => tc.IsRequest)
            });

            EntitySetInstance multipleEntity = PayloadBuilder.EntitySet().Append(instance.GenerateSimilarEntries(3)).WithTypeAnnotation(baseType);

            payloads.Add(new Taupo.OData.Common.PayloadTestDescriptor()
            {
                PayloadEdmModel = model,
                PayloadElement = multipleEntity
            });

            var multipleEntityWithInlineCount = multipleEntity.DeepCopy();
            multipleEntityWithInlineCount.InlineCount = 3;

            // inline count
            payloads.Add(new Taupo.OData.Common.PayloadTestDescriptor()
            {
                PayloadEdmModel = model,
                PayloadElement = multipleEntityWithInlineCount,
                SkipTestConfiguration = (tc => tc.IsRequest)
            });

            var multipleEntityWithNextLinkAndCount = multipleEntity.DeepCopy();
            multipleEntityWithNextLinkAndCount.InlineCount = 3;
            multipleEntityWithNextLinkAndCount.NextLink = "http://www.odata.org/Feed";

            // inline count + next link
            payloads.Add(new Taupo.OData.Common.PayloadTestDescriptor()
            {
                PayloadEdmModel = model,
                PayloadElement = multipleEntityWithNextLinkAndCount,
                SkipTestConfiguration = (tc => tc.IsRequest)
            });

            var multipleEntityWithNextLink = multipleEntity.DeepCopy();
            multipleEntityWithNextLink.NextLink = "http://www.odata.org/Feed";

            // next link
            payloads.Add(new Taupo.OData.Common.PayloadTestDescriptor()
            {
                PayloadEdmModel = model,
                PayloadElement = multipleEntityWithNextLink,
                SkipTestConfiguration = (tc => tc.IsRequest)
            });

            return payloads;
        }
        public void HomogeneousCollectionReaderAtomTest()
        {
            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 PayloadReaderTestDescriptor[]
            {
                // complex collection with primitive expected type
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue("TestModel.CityType").Property("Name", PayloadBuilder.PrimitiveValue("Vienna")),
                        PayloadBuilder.ComplexValue("TestModel.CityType").Property("Name", PayloadBuilder.PrimitiveValue("Prague"))
                        ).ExpectedCollectionItemType(EdmDataTypes.Int32).CollectionName(null),
                    PayloadEdmModel = edmModel,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "TestModel.CityType", "Primitive", "Complex"),
                },
                
                // primitive collection in XMLRepresentation with complex expected type. 
                new PayloadReaderTestDescriptor(this.PayloadTestDescriptorSettings)
                {
                    PayloadElement = new ComplexInstanceCollection(
                        PayloadBuilder.ComplexValue("TestModel.CityType"),
                        PayloadBuilder.ComplexValue("TestModel.CityType")
                        ).ExpectedCollectionItemType(edmComplexTypeCity).CollectionName(null)
                        .XmlRepresentation(@"
                                            <m:value>
                                                <m:element m:type='Edm.Int32'>1</m:element>
                                                <m:element m:type='Edm.Int32'>2</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);
                });
        }
        public void OpenPropertiesTest()
        {
            // Interesting values to test as open properties.
            // Only test complex and collection values here, since open primitive properties rely on format specific primitive type support.
            // The open primitive properties tests are thus format specific and are here:
            //   JSON - PrimitiveValueReaderJsonTests.UntypedPrimitiveValueTest
            //   ATOM - PrimitiveValueReaderAtomTests.PrimitiveValueWithoutType
            IEnumerable<PayloadReaderTestDescriptor> testDescriptors = PayloadReaderTestDescriptorGenerator.CreateComplexValueTestDescriptors(this.Settings, true, false);

            // Add spatial open property tests
            testDescriptors = testDescriptors.Concat(new[]
                {
                    new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.PrimitiveValue(GeographyFactory.Point(10, 20, 30, 40).Build())
                    },
                    new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.PrimitiveValue(GeometryFactory.Point(10, 20, 30, 40).Build())
                    }
                });

            // Add couple of hand-crafted payloads
            testDescriptors = testDescriptors.Concat(new[]
                {
                    // Open complex value with undeclared type - must fail
                    new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.ComplexValue("TestModel.NonExistantType"),
                        ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_UnrecognizedTypeName", "TestModel.NonExistantType"),
                    },
                    // Open complex null value
                    new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.ComplexValue("TestModel.NonEmptyComplexType", true),
                    },
                });

            testDescriptors = testDescriptors
                // Wrap the property in an open entity
                .Select(td =>
                {
                    EdmModel model = (EdmModel)td.PayloadEdmModel;
                    model = model == null ? new EdmModel() : (EdmModel)Test.OData.Utils.Metadata.MetadataUtils.Clone(model);
                    var entityType = model.EntityType("OpenEntityType", "TestModel", null, false, true);
                    entityType.AddKeys(entityType.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32));
                    entityType.AddStructuralProperty("DateTimeProperty", EdmPrimitiveTypeKind.DateTimeOffset);

                    var complexType = model.ComplexType("NonEmptyComplexType");
                    complexType.AddStructuralProperty("P1", EdmPrimitiveTypeKind.Int32);
                    complexType.AddStructuralProperty("P2", EdmCoreModel.Instance.GetString(true));
                    model = model.Fixup();

                    return new PayloadReaderTestDescriptor(td)
                    {
                        PayloadElement = PayloadBuilder.Entity("TestModel.OpenEntityType")
                            .PrimitiveProperty("ID", 42)
                            .Property("OpenProperty", td.PayloadElement),
                        PayloadEdmModel = model
                    };
                });

            // Add a couple of hand crafted payloads
            {
                EdmModel model = new EdmModel();
                var entityType = model.EntityType("OpenEntityType", null, null, false, true);
                entityType.KeyProperty("ID", EdmCoreModel.Instance.GetInt32(false));
                model = model.Fixup();

                testDescriptors = testDescriptors.Concat(new PayloadReaderTestDescriptor[]
                {
                    // Open stream property is not allowed.
                    new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.Entity("TestModel.OpenEntityType").PrimitiveProperty("ID", 42)
                            .StreamProperty("OpenProperty", "http://odata.org/readlink"),
                        PayloadEdmModel = model,
                        ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_OpenStreamProperty", "OpenProperty"),
                        // TODO: In JSON we recognize this as a complex property - once we make a decision about the bug enable the test for JSON.
                        SkipTestConfiguration = tc => tc.Format != ODataFormat.Atom || tc.IsRequest
                    },
                    // Open deferred navigation property is not allowed.
                    new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.Entity("TestModel.OpenEntityType").PrimitiveProperty("ID", 42)
                            .NavigationProperty("OpenProperty", "http://odata.org/navprop"),
                        PayloadEdmModel = model,
                        ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_OpenNavigationProperty", "OpenProperty", "TestModel.OpenEntityType"),
                        // TODO: In JSON we recognize this as a complex property - once we make a decision about the bug enable the test for JSON.
                        SkipTestConfiguration = tc => tc.Format != ODataFormat.Atom
                    },
                    // Open expanded navigation property (entry) is not allowed.
                    new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.Entity("TestModel.OpenEntityType").PrimitiveProperty("ID", 42)
                            .ExpandedNavigationProperty("OpenProperty", PayloadBuilder.Entity("TestModel.OpenEntityType")),
                        PayloadEdmModel = model,
                        ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_OpenNavigationProperty", "OpenProperty", "TestModel.OpenEntityType"),
                        // This can't work in JSON as it is recognized as a complex value - and will fail for different reasons
                        SkipTestConfiguration = tc => tc.Format != ODataFormat.Atom
                    },
                    // Open expanded navigation property (feed) is not allowed.
                    new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.Entity("TestModel.OpenEntityType").PrimitiveProperty("ID", 42)
                            .ExpandedNavigationProperty("OpenProperty", PayloadBuilder.EntitySet()),
                        PayloadEdmModel = model,
                        ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_OpenNavigationProperty", "OpenProperty", "TestModel.OpenEntityType"),
                        // This can't work in JSON as it may be recognized as a complex value - and will fail for different reasons
                        SkipTestConfiguration = tc => tc.Format != ODataFormat.Atom
                    },
                    // Open property with same name as non-open property
                    new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.Entity("TestModel.OpenEntityType").PrimitiveProperty("ID", 42).PrimitiveProperty("DateTimeProperty", new DateTimeOffset(DateTime.Now))
                            .PrimitiveProperty("DateTimeProperty", new DateTimeOffset(DateTime.Now.AddDays(1.0))),
                        PayloadEdmModel = model,
                        ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "DateTimeProperty"),
                        // In JSON Light this fails for different reasons, related to missing/multiple type annotations (depending on how it is serialised)
                        SkipTestConfiguration = tc => tc.Format == ODataFormat.Json,
                    },
                });
            }

            testDescriptors = testDescriptors.SelectMany(td => this.PayloadGenerator.GenerateReaderPayloads(td));

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations,
                (testDescriptor, testConfiguration) =>
                {
                    testDescriptor.RunTest(testConfiguration);
                });
        }
        public void ComplexValuePropertyOrderingTest()
        {
            EdmModel model = new EdmModel();

            var complexType = new EdmComplexType(DefaultNamespaceName, "ComplexType");
            complexType.AddStructuralProperty("stringProperty", EdmCoreModel.Instance.GetString(isNullable: false));
            complexType.AddStructuralProperty("numberProperty", EdmCoreModel.Instance.GetInt32(isNullable: false));
            complexType.AddStructuralProperty("nullProperty", EdmCoreModel.Instance.GetString(isNullable: true));
            model.AddElement(complexType);

            model.Fixup();

            IEnumerable<PayloadReaderTestDescriptor> testDescriptors =
                PropertiesElementAtomValues.CreatePropertiesElementOrderingPayloads<ComplexInstance>(
                    new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = PayloadBuilder.ComplexValue("TestModel.ComplexType"),
                        PayloadEdmModel = model
                    },
                    (complexInstance, xmlNodes) => complexInstance.XmlValueRepresentation(xmlNodes)).Select(td =>
                    new PayloadReaderTestDescriptor(td)
                    {
                        PayloadElement = PayloadBuilder.Property(null, td.PayloadElement).ExpectedPropertyType(new EdmComplexTypeReference(complexType, isNullable: false)),
                    });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations,
                (testDescriptor, testConfiguration) =>
                {
                    testDescriptor.RunTest(testConfiguration);
                });
        }
        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);
                });
        }
        public void BatchReaderMixedEncodingTest()
        {
            EdmModel model = new EdmModel();
            EdmEntityType personType = model.EntityType("Person")
                .KeyProperty("Id", EdmCoreModel.Instance.GetInt32(false) as EdmTypeReference)
                .Property("Name", EdmPrimitiveTypeKind.String, isNullable: true);
            model.Fixup();

            EdmEntitySet personSet = model.EntitySet("Person", personType);

            EntityInstance personInstance = PayloadBuilder.Entity("TestModel.Person")
                .Property("Id", PayloadBuilder.PrimitiveValue(1))
                .Property("Name", PayloadBuilder.PrimitiveValue("Mr Foo Baz"));

            ODataUriSegment root = ODataUriBuilder.Root(new Uri("http://www.odata.org"));
            ODataUri testUri = new ODataUri(root, ODataUriBuilder.EntitySet(personSet));


            Encoding[] encodings = new Encoding[] 
            { 
                Encoding.UTF8, 
                Encoding.BigEndianUnicode, 
                Encoding.Unicode 
            };

            IEnumerable<BatchReaderMixedEncodingTestCase> testCases =
                encodings.SelectMany(batchEncoding =>
                    encodings.Select(changesetEncoding =>
                        new BatchReaderMixedEncodingTestCase
                        {
                            BatchEncoding = batchEncoding,
                            Changesets = new[]
                            {
                                new BatchReaderMixedEncodingChangeset
                                {
                                    ChangesetEncoding = changesetEncoding,
                                    Operations = new[]
                                    {
                                       new BatchReaderMixedEncodingOperation
                                       {
                                           OperationEncoding = Encoding.Unicode,
                                           PayloadFormat = ODataFormat.Atom,
                                       },
                                       new BatchReaderMixedEncodingOperation
                                       {
                                           // Uses changeset's encoding
                                           PayloadFormat = ODataFormat.Atom,
                                       },
                                    },
                                },
                                new BatchReaderMixedEncodingChangeset
                                {
                                    Operations = new[]
                                    {
                                        new BatchReaderMixedEncodingOperation
                                        {
                                            // Uses batch's encoding
                                            OperationEncoding = batchEncoding,
                                            PayloadFormat = ODataFormat.Atom,
                                        },
                                    },
                                },
                            },
                        }
                    ));

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                this.ReaderTestConfigurationProvider.DefaultFormatConfigurations,
                (testCase, testConfiguration) =>
                {
                    var testPayload = personInstance.DeepCopy();
                    if (!testConfiguration.IsRequest)
                    {
                        testPayload.AddAnnotation(new PayloadFormatVersionAnnotation() { Response = true, ResponseWrapper = true });
                    }

                    var testDescriptor = this.CreateTestDescriptor(testCase, testPayload, testUri, testConfiguration.IsRequest);
                    testDescriptor.PayloadEdmModel = model;
                    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);
                });
        }
        private IEnumerable<PayloadWriterTestDescriptor<ODataProperty>> CreateComplexPropertyDescriptors()
        {
            EdmModel model = new EdmModel();
            ODataProperty[] properties = ObjectModelUtils.CreateDefaultComplexProperties(model);
            model.Fixup();

            var owningType = MetadataUtils.EntityTypes(model).Single(et => et.Name == "EntryWithComplexProperties");

            string[] propertiesAtomResults = new string[]
            {
                string.Join("$(NL)",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""My.AddressType"" xmlns:{2}=""{3}"">",
                @"$(Indent)<{2}:Street>One Redmond Way</{2}:Street>",
                @"$(Indent)<{2}:City xml:space=""preserve""> Redmond</{2}:City>",
                @"</{5}>"),
                string.Join("$(NL)",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""My.NestedAddressType"">",
                @"$(Indent)<Street {0}:{4}=""My.StreetType"" xmlns=""{3}"">",
                @"$(Indent)$(Indent)<StreetName>One Redmond Way</StreetName>",
                @"$(Indent)$(Indent)<Number {0}:{4}=""Int32"">1234</Number>",
                @"$(Indent)</Street>",
                @"$(Indent)<{2}:City xml:space=""preserve"" xmlns:{2}=""{3}"">Redmond </{2}:City>",
                @"</{5}>")
            };
            propertiesAtomResults = propertiesAtomResults
                .Select(r =>
                    string.Format(r,
                        TestAtomConstants.ODataMetadataNamespacePrefix,
                        TestAtomConstants.ODataMetadataNamespace,
                        TestAtomConstants.ODataNamespacePrefix,
                        TestAtomConstants.ODataNamespace,
                        TestAtomConstants.AtomTypeAttributeName,
                        TestAtomConstants.ODataValueElementName))
                .ToArray();


            Func<bool, string[][]> propertiesJsonLightResultsFunc = isRequest => new string[][]
            {
                StringUtils.Flatten(
                    "{",
                    "$(Indent)" + 
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"" + JsonLightConstants.DefaultMetadataDocumentUri + "#My.AddressType\"," +
                        "\"Street\":\"One Redmond Way\",\"City\":\" Redmond\"",
                    "}"
                ),
                StringUtils.Flatten(
                    "{",
                    "$(Indent)" + 
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"" + JsonLightConstants.DefaultMetadataDocumentUri + "#My.NestedAddressType\"," + 
                        "\"Street\":{",
                    "$(Indent)$(Indent)\"StreetName\":\"One Redmond Way\",\"Number\":1234",
                    "$(Indent)},\"City\":\"Redmond \"",
                    "}"
                )
            };
            string[][] propertiesJsonLightRequestResults = propertiesJsonLightResultsFunc(true);
            string[][] propertiesJsonLightResponseResults = propertiesJsonLightResultsFunc(false);

            for (int i = 0; i < properties.Length; ++i)
            {
                ODataProperty property = properties[i];
                string atomResult = propertiesAtomResults[i];
                string[] jsonLightRequestResult = propertiesJsonLightRequestResults[i];
                string[] jsonLightResponseResult = propertiesJsonLightResponseResults[i];

                yield return new PayloadWriterTestDescriptor<ODataProperty>(
                    this.Settings,
                    property,
                    (testConfiguration) =>
                    {
                        if (testConfiguration.Format == ODataFormat.Atom)
                        {
                            return new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                Xml = atomResult
                            };
                        }
                        else if (testConfiguration.Format == ODataFormat.Json)
                        {
                            if (((ODataComplexValue)property.Value).TypeName == null)
                            {
                                return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                                {
                                    // TODO: Need to localize error messages that missed string freeze deadline.
                                    ExpectedException = new ODataException("A type name was not provided for an instance of ODataComplexValue.")
                                };
                            }

                            return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                Json = JsonLightWriterUtils.CombineLines(testConfiguration.IsRequest ? jsonLightRequestResult : jsonLightResponseResult),
                                FragmentExtractor = null
                            };
                        }
                        else
                        {
                            string formatName = testConfiguration.Format == null ? "null" : testConfiguration.Format.GetType().Name;
                            throw new NotSupportedException("Format " + formatName + " + is not supported.");
                        }
                    })
                    {
                        Model = model,
                        PayloadEdmElementContainer = owningType
                    };
            }
        }
        private IEnumerable<PayloadWriterTestDescriptor<ODataProperty>> CreateCollectionPropertyDescriptors()
        {
            EdmModel model = new EdmModel();
            var properties = ObjectModelUtils.CreateDefaultCollectionProperties(model);
            model.Fixup();

            var owningType = MetadataUtils.EntityTypes(model).Single(et => et.Name == "EntryWithCollectionProperties");

            string[] propertiesAtomResults = new string[]
            {
                @"<{6} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{5}=""" + EntityModelUtils.GetCollectionTypeName("Edm.String") + @""" />",
                string.Join(
                    "$(NL)",
                    @"<{6} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{5}=""" + EntityModelUtils.GetCollectionTypeName("Edm.Int32") + @""">",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">0</{0}:{4}>",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">1</{0}:{4}>",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">2</{0}:{4}>",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">3</{0}:{4}>",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">4</{0}:{4}>",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">5</{0}:{4}>",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">6</{0}:{4}>",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">7</{0}:{4}>",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">8</{0}:{4}>",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">9</{0}:{4}>",
                    @"</{6}>"),
                string.Join(
                    "$(NL)",
                    @"<{6} xmlns=""{1}"" xmlns:{0}=""{1}"">",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"" {0}:{5}=""Edm.Int32"">0</{0}:{4} >",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"" {0}:{5}=""Edm.Int32"">1</{0}:{4} >",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"" {0}:{5}=""Edm.Int32"">2</{0}:{4} >",
                    @"</{6}>"),
                string.Join(
                    "$(NL)",
                    @"<{6} xmlns=""{1}"" xmlns:{0}=""{1}"">",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">One</{0}:{4} >",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">Two</{0}:{4} >",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">Three</{0}:{4} >",
                    @"</{6}>"),
                string.Join(
                    "$(NL)",
                    @"$(Indent)<{6} xmlns=""{1}"" xmlns:{0}=""{1}"">",
                    @"$(Indent)$(Indent)<{0}:{4} xmlns:{2}=""{3}"" {0}:{5}=""Edm.GeographyCollection"">" + SpatialUtils.GetSpatialStringValue(ODataFormat.Atom, ObjectModelUtils.GeographyCollectionValue) + "</{0}:{4}>",
                    @"$(Indent)$(Indent)<{0}:{4} xmlns:{2}=""{3}"" {0}:{5}=""Edm.GeographyLineString"">" + SpatialUtils.GetSpatialStringValue(ODataFormat.Atom, ObjectModelUtils.GeographyLineStringValue) + "</{0}:{4}>",
                    @"$(Indent)$(Indent)<{0}:{4} xmlns:{2}=""{3}"" {0}:{5}=""Edm.GeographyMultiLineString"">" + SpatialUtils.GetSpatialStringValue(ODataFormat.Atom, ObjectModelUtils.GeographyMultiLineStringValue) + "</{0}:{4}>",
                    @"$(Indent)$(Indent)<{0}:{4} xmlns:{2}=""{3}"" {0}:{5}=""Edm.GeographyMultiPoint"">" + SpatialUtils.GetSpatialStringValue(ODataFormat.Atom, ObjectModelUtils.GeographyMultiPointValue) + "</{0}:{4}>",
                    @"$(Indent)$(Indent)<{0}:{4} xmlns:{2}=""{3}"" {0}:{5}=""Edm.GeographyMultiPolygon"">" + SpatialUtils.GetSpatialStringValue(ODataFormat.Atom, ObjectModelUtils.GeographyMultiPolygonValue) + "</{0}:{4}>",
                    @"$(Indent)$(Indent)<{0}:{4} xmlns:{2}=""{3}"" {0}:{5}=""Edm.GeographyPoint"">" + SpatialUtils.GetSpatialStringValue(ODataFormat.Atom, ObjectModelUtils.GeographyPointValue) + "</{0}:{4}>",
                    @"$(Indent)$(Indent)<{0}:{4} xmlns:{2}=""{3}"" {0}:{5}=""Edm.GeographyPolygon"">" + SpatialUtils.GetSpatialStringValue(ODataFormat.Atom, ObjectModelUtils.GeographyPolygonValue) + "</{0}:{4}>",
                    @"$(Indent)$(Indent)<{0}:{4} xmlns:{2}=""{3}"" {0}:{5}=""Edm.GeographyPoint"">" + SpatialUtils.GetSpatialStringValue(ODataFormat.Atom, ObjectModelUtils.GeographyValue) + "</{0}:{4}>",
                    @"$(Indent)</{6}>"),
                string.Join(
                    "$(NL)",
                    @"<{6} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{5}=""" + EntityModelUtils.GetCollectionTypeName("My.AddressType") + @""">",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">",
                    @"$(Indent)$(Indent)<{2}:Street xmlns:{2}=""{3}"">One Redmond Way</{2}:Street>",
                    @"$(Indent)$(Indent)<{2}:City xml:space=""preserve"" > Redmond</{2}:City>",
                    @"$(Indent)</{0}:{4}>",
                    @"$(Indent)<{0}:{4} xmlns:{2}=""{3}"">",
                    @"$(Indent)$(Indent)<{2}:Street>Am Euro Platz 3</{2}:Street>",
                    @"$(Indent)$(Indent)<{2}:City xml:space=""preserve"">Vienna </{2}:City>",
                    @"$(Indent)</{0}:{4}>",
                    @"</{6}>"),
                    string.Empty,
                    string.Empty
            };
            propertiesAtomResults = propertiesAtomResults
                .Select(r =>
                    string.Format(r,
                        TestAtomConstants.ODataMetadataNamespacePrefix,
                        TestAtomConstants.ODataMetadataNamespace,
                        TestAtomConstants.ODataNamespacePrefix,
                        TestAtomConstants.ODataNamespace,
                        TestAtomConstants.ODataCollectionItemElementName,
                        TestAtomConstants.AtomTypeAttributeName,
                        TestAtomConstants.ODataValueElementName))
                .ToArray();

            Func<bool, string[][]> propertiesJsonLightResultsFunc = isRequest => new string[][]
            {
                StringUtils.Flatten(
                    "{",
                    "$(Indent)" + 
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"" + JsonLightConstants.DefaultMetadataDocumentUri + "#Collection(Edm.String)\"," +
                        "\"" + JsonLightConstants.ODataValuePropertyName + "\":[",
                    "$(Indent)$(Indent)",
                    "$(Indent)]",
                    "}"
                ),
                StringUtils.Flatten(
                    "{",
                    "$(Indent)" + 
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"" + JsonLightConstants.DefaultMetadataDocumentUri + "#Collection(Edm.Int32)\"," +
                        "\"" + JsonLightConstants.ODataValuePropertyName + "\":[",
                    "$(Indent)$(Indent)0,1,2,3,4,5,6,7,8,9",
                    "$(Indent)]",
                    "}"
                ),
                StringUtils.Flatten(
                    "{",
                    "$(Indent)" + 
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"" + JsonLightConstants.DefaultMetadataDocumentUri + "#Collection(Edm.Int32)\"," +
                        "\"" + JsonLightConstants.ODataValuePropertyName + "\":[",
                    "$(Indent)$(Indent)0,1,2",
                    "$(Indent)]",
                    "}"
                ),
                StringUtils.Flatten(
                    "{",
                    "$(Indent)" + 
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"" + JsonLightConstants.DefaultMetadataDocumentUri + "#Collection(Edm.String)\"," +
                        "\"" + JsonLightConstants.ODataValuePropertyName + "\":[",
                    "$(Indent)$(Indent)\"One\",\"Two\",\"Three\"",
                    "$(Indent)]",
                    "}"
                ),
                StringUtils.Flatten(
                    "{",
                    "$(Indent)" + 
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"" + JsonLightConstants.DefaultMetadataDocumentUri + "#Collection(Edm.Geography)\"," +
                        "\"" + JsonLightConstants.ODataValuePropertyName + "\":[",
                    JsonUtils.GetJsonLines(
                        "$(Indent)$(Indent)" +
                        SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyCollectionValue) + "," +
                        SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyLineStringValue) + "," +
                        SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyMultiLineStringValue) + "," +
                        SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyMultiPointValue) + "," +
                        SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyMultiPolygonValue) + "," +
                        SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyPointValue) + "," +
                        SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyPolygonValue) + "," +
                        SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyValue), indentDepth: 2),
                    "$(Indent)]",
                    "}"
                ),
                StringUtils.Flatten(
                    "{",
                    "$(Indent)" + 
                        "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"" + JsonLightConstants.DefaultMetadataDocumentUri + "#Collection(My.AddressType)\"," +
                        "\"" + JsonLightConstants.ODataValuePropertyName + "\":[",
                    "$(Indent)$(Indent){",
                    "$(Indent)$(Indent)$(Indent)\"Street\":\"One Redmond Way\",\"City\":\" Redmond\"",
                    "$(Indent)$(Indent)},{",
                    "$(Indent)$(Indent)$(Indent)\"Street\":\"Am Euro Platz 3\",\"City\":\"Vienna \"",
                    "$(Indent)$(Indent)}",
                    "$(Indent)]",
                    "}"
                ),
                new string[0], 
                new string[0],
            };

            string[][] propertiesJsonLightRequestResults = propertiesJsonLightResultsFunc(true);
            string[][] propertiesJsonLightResponseResults = propertiesJsonLightResultsFunc(false);

            for (int i = 0; i < properties.Length; ++i)
            {
                ODataProperty property = properties[i];
                string atomResult = propertiesAtomResults[i];
                string[] jsonLightRequestResultLines = propertiesJsonLightRequestResults[i];
                string[] jsonLightResponseResultLines = propertiesJsonLightResponseResults[i];

                yield return new PayloadWriterTestDescriptor<ODataProperty>(
                    this.Settings,
                    property,
                    (testConfiguration) =>
                    {
                        if (testConfiguration.Format == ODataFormat.Atom)
                        {
                            return new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                Xml = atomResult,
                            };
                        }
                        else if (testConfiguration.Format == ODataFormat.Json)
                        {
                            ODataCollectionValue collectionValue = ((ODataCollectionValue)property.Value);
                            if (string.IsNullOrEmpty(collectionValue.TypeName) && (collectionValue.GetAnnotation<SerializationTypeNameAnnotation>() == null || string.IsNullOrEmpty(collectionValue.GetAnnotation<SerializationTypeNameAnnotation>().TypeName)))
                            {
                                return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException2 = ODataExpectedExceptions.ODataException("WriterValidationUtils_MissingTypeNameWithMetadata")
                                };
                            }

                            return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                Json = JsonLightWriterUtils.CombineLines(testConfiguration.IsRequest ? jsonLightRequestResultLines : jsonLightResponseResultLines),
                                FragmentExtractor = testConfiguration.IsRequest
                                    ? (Func<JsonValue, JsonValue>)null
                                    : (result) => result
                            };
                        }
                        else
                        {
                            string formatName = testConfiguration.Format == null ? "null" : testConfiguration.Format.GetType().Name;
                            throw new NotSupportedException("Format " + formatName + " + is not supported.");
                        }
                    })
                    {
                        Model = model,
                        PayloadEdmElementContainer = owningType
                    };
            }
        }
        private IEnumerable<PayloadWriterTestDescriptor<ODataProperty>> CreatePrimitiveTopLevelPropertyDescriptors()
        {
            var model = new EdmModel();
            ODataProperty[] properties = ObjectModelUtils.CreateDefaultPrimitiveProperties(model);
            model.Fixup();
            var owningType = MetadataUtils.EntityTypes(model).Single(et => et.Name == "EntryWithPrimitiveProperties");

            string[] propertiesAtomResults = new string[]
            {
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true""/>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Double"" >1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Binary"">AAEAAQ==</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Single"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Boolean"">true</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Byte"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""DateTimeOffset"">2010-10-10T10:10:10Z</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""DateTimeOffset"">2010-10-10T10:10:10+01:00</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""DateTimeOffset"">2010-10-10T10:10:10-08:00</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Decimal"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Guid"">11111111-2222-3333-4444-555555555555</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""SByte"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Int16"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Int32"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Int64"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Duration"">PT12M20.4S</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeographyPoint"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeographyValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeographyPoint"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeographyPointValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeographyLineString"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeographyLineStringValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeographyPolygon"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeographyPolygonValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeographyCollection"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeographyCollectionValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeographyMultiPoint"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeographyMultiPointValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeographyMultiLineString"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeographyMultiLineStringValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeographyMultiPolygon"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeographyMultiPolygonValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeometryPoint"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeometryValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeometryPoint"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeometryPointValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeometryLineString"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeometryLineStringValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeometryPolygon"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeometryPolygonValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeometryCollection"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeometryCollectionValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeometryMultiPoint"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeometryMultiPointValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeometryMultiLineString"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeometryMultiLineStringValue) + "</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""GeometryMultiPolygon"">" + GmlFormatter.Create().Write(ObjectModelUtils.GeometryMultiPolygonValue) + "</{5}>",

                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Double"" >1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Single"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Boolean"">true</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Byte"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""DateTimeOffset"">2010-10-10T10:10:10Z</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""DateTimeOffset"">2010-10-10T10:10:10+01:00</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""DateTimeOffset"">2010-10-10T10:10:10-08:00</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Decimal"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Guid"">11111111-2222-3333-4444-555555555555</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""SByte"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Int16"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Int32"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Int64"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"">1</{5}>",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:{4}=""Duration"">PT12M20.4S</{5}>",

                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
                @"<{5} xmlns=""{1}"" xmlns:{0}=""{1}"" {0}:null=""true"" />",
            };
            propertiesAtomResults = propertiesAtomResults
                .Select(r =>
                    string.Format(r,
                        TestAtomConstants.ODataMetadataNamespacePrefix,
                        TestAtomConstants.ODataMetadataNamespace,
                        TestAtomConstants.ODataNamespacePrefix,
                        TestAtomConstants.ODataNamespace,
                        TestAtomConstants.AtomTypeAttributeName,
                        TestAtomConstants.ODataValueElementName))
                .ToArray();

            string[] propertiesJsonLightResults = new string[]
            {
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":1.0",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"AAEAAQ==\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":1",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":true",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":1",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"2010-10-10T10:10:10Z\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"2010-10-10T10:10:10+01:00\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"2010-10-10T10:10:10-08:00\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"1\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"11111111-2222-3333-4444-555555555555\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":1",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":1",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":1",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"1\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"1\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"PT12M20.4S\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyPointValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyLineStringValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyPolygonValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyCollectionValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyMultiPointValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyMultiLineStringValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeographyMultiPolygonValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeometryValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeometryPointValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeometryLineStringValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeometryPolygonValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeometryCollectionValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeometryMultiPointValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeometryMultiLineStringValue),
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, ObjectModelUtils.GeometryMultiPolygonValue),

                "\"" + JsonLightConstants.ODataValuePropertyName + "\":1.0",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":1",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":true",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":1",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"2010-10-10T10:10:10Z\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"2010-10-10T10:10:10+01:00\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"2010-10-10T10:10:10-08:00\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"1\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"11111111-2222-3333-4444-555555555555\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":1",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":1",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":1",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"1\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"1\"",
                "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"PT12M20.4S\"",

                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
                "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true",
            };

            string[][] propertiesJsonLightRequestResultLines = new string[propertiesJsonLightResults.Length][];
            string[][] propertiesJsonLightResponseResultLines = new string[propertiesJsonLightResults.Length][];
            for (int i = 0; i < propertiesJsonLightResults.Length; ++i)
            {
                string propertyJsonLightResult = propertiesJsonLightResults[i];

                var property = owningType.FindProperty(properties[i].Name);
                var typeName = property.Type.TestFullName();
                if (properties[i].Value == null)
                {
                    typeName = "Edm.Null";
                }
                else if(properties[i].Value is ISpatial)
                {
                    typeName = "Edm." + properties[i].Value.GetType().BaseType.Name;
                }

                string contextUri = JsonLightConstants.DefaultMetadataDocumentUri.AbsoluteUri + "#" + typeName;
                string propertyJsonLightWithMetadataAnnotationResult = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"" + contextUri + "\"," + propertyJsonLightResult;

                propertiesJsonLightRequestResultLines[i] = JsonUtils.WrapTopLevelObject(JsonUtils.GetJsonLines(propertyJsonLightWithMetadataAnnotationResult));
                propertiesJsonLightResponseResultLines[i] = JsonUtils.WrapTopLevelObject(JsonUtils.GetJsonLines(propertyJsonLightWithMetadataAnnotationResult));
            }

            for (int i = 0; i < properties.Length; ++i)
            {
                ODataProperty property = properties[i];
                string atomResult = propertiesAtomResults[i];
                string[] jsonLightRequestResult = propertiesJsonLightRequestResultLines[i];
                string[] jsonLightResponseResult = propertiesJsonLightResponseResultLines[i];

                yield return new PayloadWriterTestDescriptor<ODataProperty>(
                    this.Settings,
                    property,
                    (testConfiguration) =>
                    {
                        if (testConfiguration.Format == ODataFormat.Atom)
                        {
                            return new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                Xml = atomResult,
                            };
                        }
                        else if (testConfiguration.Format == ODataFormat.Json)
                        {
                            return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                Json = JsonLightWriterUtils.CombineLines(testConfiguration.IsRequest ? jsonLightRequestResult : jsonLightResponseResult),
                                FragmentExtractor = null,
                            };
                        }
                        else
                        {
                            string formatName = testConfiguration.Format == null ? "null" : testConfiguration.Format.GetType().Name;
                            throw new NotSupportedException("Format " + formatName + " + is not supported.");
                        }
                    })
                    {
                        Model = model,
                        PayloadEdmElementContainer = owningType
                    };
            }
        }
Exemple #19
0
        /// <summary>
        /// Build a test model shared across several tests.
        /// </summary>
        /// <returns>Returns the test model.</returns>
        public static EdmModel BuildTestModel()
        {
            // The metadata model
            var model = new EdmModel();

            var addressType = new EdmComplexType(DefaultNamespaceName, "Address");
            addressType.AddStructuralProperty("Street", StringNullableTypeRef);
            addressType.AddStructuralProperty("Zip", Int32TypeRef);
            addressType.AddStructuralProperty("SubAddress", new EdmComplexTypeReference(addressType, isNullable: false));
            model.AddElement(addressType);

            var officeType = new EdmEntityType(DefaultNamespaceName, "OfficeType");
            officeType.AddKeys(officeType.AddStructuralProperty("Id", Int32TypeRef));
            officeType.AddStructuralProperty("Address", new EdmComplexTypeReference(addressType, isNullable: false));
            model.AddElement(officeType);

            var officeWithNumberType = new EdmEntityType(DefaultNamespaceName, "OfficeWithNumberType", officeType);
            officeWithNumberType.AddStructuralProperty("Number", Int32TypeRef);
            model.AddElement(officeWithNumberType);

            var cityType = new EdmEntityType(DefaultNamespaceName, "CityType");
            cityType.AddKeys(cityType.AddStructuralProperty("Id", Int32TypeRef));
            cityType.AddStructuralProperty("Name", StringNullableTypeRef);
            cityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo { Name = "CityHall", Target = officeType, TargetMultiplicity = EdmMultiplicity.Many });
            cityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo { Name = "DOL", Target = officeType, TargetMultiplicity = EdmMultiplicity.Many });
            cityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo { Name = "PoliceStation", Target = officeType, TargetMultiplicity = EdmMultiplicity.One });
            cityType.AddStructuralProperty("Skyline", EdmPrimitiveTypeKind.Stream, isNullable: false);
            cityType.AddStructuralProperty("MetroLanes", EdmCoreModel.GetCollection(StringNullableTypeRef));
            model.AddElement(cityType);

            var metropolitanCityType = new EdmEntityType(DefaultNamespaceName, "MetropolitanCityType", cityType);
            metropolitanCityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo { Name = "ContainedOffice", Target = officeType, TargetMultiplicity = EdmMultiplicity.Many, ContainsTarget = true });
            officeType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo { Name = "ContainedCity", Target = metropolitanCityType, TargetMultiplicity = EdmMultiplicity.One, ContainsTarget = true });
            model.AddElement(metropolitanCityType);

            var cityWithMapType = new EdmEntityType(DefaultNamespaceName, "CityWithMapType", cityType, false, false, true);
            model.AddElement(cityWithMapType);

            var cityOpenType = new EdmEntityType(DefaultNamespaceName, "CityOpenType", cityType, isAbstract: false, isOpen: true);
            model.AddElement(cityOpenType);

            var personType = new EdmEntityType(DefaultNamespaceName, "Person");
            personType.AddKeys(personType.AddStructuralProperty("Id", Int32TypeRef));
            personType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo { Name = "Friend", Target = personType, TargetMultiplicity = EdmMultiplicity.Many });
            model.AddElement(personType);

            var employeeType = new EdmEntityType(DefaultNamespaceName, "Employee", personType);
            employeeType.AddStructuralProperty("CompanyName", StringNullableTypeRef);
            model.AddElement(employeeType);

            var managerType = new EdmEntityType(DefaultNamespaceName, "Manager", employeeType);
            managerType.AddStructuralProperty("Level", Int32TypeRef);
            model.AddElement(managerType);

            var container = new EdmEntityContainer(DefaultNamespaceName, "DefaultContainer");
            model.AddElement(container);

            container.AddEntitySet("Offices", officeType);
            container.AddEntitySet("Cities", cityType);
            container.AddEntitySet("MetropolitanCities", metropolitanCityType);
            container.AddEntitySet("Persons", personType);
            container.AddEntitySet("Employee", employeeType);
            container.AddEntitySet("Manager", managerType);
            container.AddSingleton("Boss", personType);

            // Fixup will set DefaultContainer\TopLevelEntitySet\AssociationSet
            model.Fixup();

            // NOTE: Function import parameters and return types must be nullable as per current CSDL spec
            var serviceOp = container.AddFunctionAndFunctionImport(model, "ServiceOperation1", Int32NullableTypeRef, null, false /*isComposable*/, false /*isBound*/);
            serviceOp.Function.AsEdmFunction().AddParameter("a", Int32NullableTypeRef);
            serviceOp.Function.AsEdmFunction().AddParameter("b", StringNullableTypeRef);

            container.AddFunctionAndFunctionImport(model, "PrimitiveResultOperation", Int32NullableTypeRef, null, false /*isComposable*/, false /*isBound*/);
            container.AddFunctionAndFunctionImport(model, "ComplexResultOperation", new EdmComplexTypeReference(addressType, isNullable: true), null, false /*isComposable*/, false /*isBound*/);
            container.AddFunctionAndFunctionImport(model, "PrimitiveCollectionResultOperation", EdmCoreModel.GetCollection(Int32NullableTypeRef), null, false /*isComposable*/, false /*isBound*/);
            container.AddFunctionAndFunctionImport(model, "ComplexCollectionResultOperation", EdmCoreModel.GetCollection(new EdmComplexTypeReference(addressType, isNullable: true)), null, false /*isComposable*/, false /*isBound*/);

            // Overload with 0 Param
            container.AddFunctionAndFunctionImport(model, "FunctionImportWithOverload", Int32NullableTypeRef, null, false /*isComposable*/, false /*isBound*/);

            // Overload with 1 Param
            var overloadWithOneParam = container.AddFunctionAndFunctionImport(model, "FunctionImportWithOverload", Int32NullableTypeRef, null, false /*isComposable*/, false /*isBound*/);
            overloadWithOneParam.Function.AsEdmFunction().AddParameter("p1", new EdmEntityTypeReference(cityWithMapType, isNullable: true));

            // Overload with 2 Params
            var overloadWithTwoParams = container.AddFunctionAndFunctionImport(model, "FunctionImportWithOverload", Int32NullableTypeRef, null, false /*isComposable*/, false /*isBound*/);
            overloadWithTwoParams.Function.AsEdmFunction().AddParameter("p1", new EdmEntityTypeReference(cityType, isNullable: true));
            overloadWithTwoParams.Function.AsEdmFunction().AddParameter("p2", StringNullableTypeRef);

            // Overload with 5 Params
            var overloadWithFiveParams = container.AddFunctionAndFunctionImport(model, "FunctionImportWithOverload", Int32NullableTypeRef, null, false /*isComposable*/, false /*isBound*/);
            overloadWithFiveParams.Function.AsEdmFunction().AddParameter("p1", EdmCoreModel.GetCollection(new EdmEntityTypeReference(cityType, isNullable: true)));
            overloadWithFiveParams.Function.AsEdmFunction().AddParameter("p2", EdmCoreModel.GetCollection(StringNullableTypeRef));
            overloadWithFiveParams.Function.AsEdmFunction().AddParameter("p3", StringNullableTypeRef);
            overloadWithFiveParams.Function.AsEdmFunction().AddParameter("p4", new EdmComplexTypeReference(addressType, isNullable: true));
            overloadWithFiveParams.Function.AsEdmFunction().AddParameter("p5", EdmCoreModel.GetCollection(new EdmComplexTypeReference(addressType, isNullable: true)));

            return model;
        }
Exemple #20
0
        /// <summary>
        /// Creates a set of models.
        /// </summary>
        /// <returns>List of interesting models.</returns>
        public static IEnumerable<IEdmModel> CreateModels()
        {
            //
            // NOTE: we only create a few models here since we mostly rely on EdmLib to test 
            //       model serialization/deserialization for us
            //
            // Empty model
            EdmModel emptyModel = new EdmModel();
            emptyModel.AddElement(new EdmEntityContainer("DefaultNamespace", "DefaultContainer"));
            yield return emptyModel.Fixup();

            // Model with a single entity type
            EdmModel modelWithSingleEntityType = new EdmModel();
            var singletonEntityType = new EdmEntityType(DefaultNamespaceName, "SingletonEntityType");
            singletonEntityType.AddKeys(singletonEntityType.AddStructuralProperty("Id", Int32TypeRef));
            singletonEntityType.AddStructuralProperty("Name", StringNullableTypeRef);
            modelWithSingleEntityType.AddElement(singletonEntityType);
            modelWithSingleEntityType.Fixup();
            yield return modelWithSingleEntityType;

            // Model with a single complex type
            EdmModel modelWithSingleComplexType = new EdmModel();
            var singletonComplexType = new EdmComplexType(DefaultNamespaceName, "SingletonComplexType");
            singletonComplexType.AddStructuralProperty("City", StringNullableTypeRef);
            modelWithSingleComplexType.AddElement(singletonComplexType);
            modelWithSingleComplexType.Fixup();
            yield return modelWithSingleComplexType;

            // Model with a collection property
            EdmModel modelWithCollectionProperty = new EdmModel();
            var complexTypeWithCollection = new EdmComplexType(DefaultNamespaceName, "ComplexTypeWithCollection");
            complexTypeWithCollection.AddStructuralProperty("Cities", EdmCoreModel.GetCollection(StringNullableTypeRef));
            modelWithCollectionProperty.AddElement(complexTypeWithCollection);
            modelWithCollectionProperty.Fixup();
            yield return modelWithCollectionProperty;

            // Model with an open type
            EdmModel modelWithOpenType = new EdmModel();
            var openType = new EdmEntityType(DefaultNamespaceName, "OpenEntityType", baseType: null, isAbstract: false, isOpen: true);
            openType.AddKeys(openType.AddStructuralProperty("Id", Int32TypeRef));
            modelWithOpenType.AddElement(openType);

            var containerForModelWithOpenType = new EdmEntityContainer(DefaultNamespaceName, "DefaultContainer");
            containerForModelWithOpenType.AddEntitySet("OpenEntityType", openType);
            modelWithOpenType.AddElement(containerForModelWithOpenType);
            yield return modelWithOpenType;

            // Model with a named stream
            EdmModel modelWithNamedStream = new EdmModel();
            var namedStreamEntityType = new EdmEntityType(DefaultNamespaceName, "NamedStreamEntityType");
            namedStreamEntityType.AddKeys(namedStreamEntityType.AddStructuralProperty("Id", Int32TypeRef));
            namedStreamEntityType.AddStructuralProperty("NamedStream", EdmPrimitiveTypeKind.Stream, isNullable: false);
            modelWithNamedStream.AddElement(namedStreamEntityType);

            var containerForModelWithNamedStream = new EdmEntityContainer(DefaultNamespaceName, "DefaultContainer");
            containerForModelWithNamedStream.AddEntitySet("NamedStreamEntityType", namedStreamEntityType);
            modelWithNamedStream.AddElement(containerForModelWithNamedStream);
            yield return modelWithNamedStream;

            // OData Shared Test Model
            yield return BuildTestModel();

            // Model with OData-specific attribute annotations
            yield return BuildODataAnnotationTestModel(true);

            // Astoria Default Test Model
            yield return BuildDefaultAstoriaTestModel();
        }
        public void StreamPropertiesProjectionTest()
        {
            EdmModel model = new EdmModel();
            var container = new EdmEntityContainer("TestModel", "DefaultContainer");
            model.AddElement(container);
            EdmEntityType townType = model.EntityType("TownType");
            townType.KeyProperty("Id", EdmCoreModel.Instance.GetInt32(false));
            townType.StreamProperty("MapSmall");
            townType.StreamProperty("MapMedium");
            townType.NavigationProperty("NavProp", townType);

            EdmEntityType cityType = model.EntityType("CityType", null, townType);
            cityType.StreamProperty("CityLogo");

            EdmEntitySet townsSet = model.EntitySet("Towns", townType);
            model.Fixup();

            var testCases = new ProjectionTestCase[]
            {
                #region No $select
                new ProjectionTestCase
                {
                    DebugDescription = "No $select => three templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall").StreamProperty("MapMedium").StreamProperty("CityLogo").NavigationProperty("NavProp", /*url*/null),
                    ProjectionString = null,
                },
                new ProjectionTestCase
                {
                    DebugDescription = "No $select + one property in the payload => two templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium").StreamProperty("CityLogo").NavigationProperty("NavProp", /*url*/null),
                    ProjectionString = null,
                },
                new ProjectionTestCase
                {
                    DebugDescription = "No $select + three properties in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium", "http://odata.org/stream/read").StreamProperty("CityLogo", "http://odata.org/stream/read"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium", "http://odata.org/stream/read").StreamProperty("CityLogo", "http://odata.org/stream/read").NavigationProperty("NavProp", /*url*/null),
                    ProjectionString = null,
                },
                #endregion No $select
                #region Empty $select
                new ProjectionTestCase
                {
                    DebugDescription = "Empty $select => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ProjectionString = string.Empty,
                },
                new ProjectionTestCase
                {
                    DebugDescription = "Empty $select + one property in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read"),
                    ProjectionString = string.Empty,
                },
                new ProjectionTestCase
                {
                    DebugDescription = "Empty $select + three properties in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium", "http://odata.org/stream/read").StreamProperty("CityLogo", "http://odata.org/stream/read"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium", "http://odata.org/stream/read").StreamProperty("CityLogo", "http://odata.org/stream/read"),
                    ProjectionString = string.Empty,
                },
                #endregion Empty $select
                #region $select=*
                new ProjectionTestCase
                {
                    DebugDescription = "$select=* => three templatized stream properties and and one templatized navigation.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall").StreamProperty("MapMedium").StreamProperty("CityLogo").NavigationProperty("NavProp", /*url*/null),
                    ProjectionString = "*",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=* + one property in the payload => two templatized stream properties and one templatized navigation.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium").StreamProperty("CityLogo").NavigationProperty("NavProp", /*url*/null),
                    ProjectionString = "*",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=* + three properties in the payload => no templatized stream properties, one templatized navigation.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium", "http://odata.org/stream/read").StreamProperty("CityLogo", "http://odata.org/stream/read"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium", "http://odata.org/stream/read").StreamProperty("CityLogo", "http://odata.org/stream/read").NavigationProperty("NavProp", /*url*/null),
                    ProjectionString = "*",
                },
                #endregion $select=*
                #region $select=MapMedium
                new ProjectionTestCase
                {
                    DebugDescription = "$select=MapMedium => one templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapMedium"),
                    ProjectionString = "MapMedium",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=MapMedium + MapMedium property in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapMedium", "http://odata.org/stream/read"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapMedium", "http://odata.org/stream/read"),
                    ProjectionString = "MapMedium",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=MapMedium + MapSmall property in the payload => one templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium"),
                    ProjectionString = "MapMedium",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=MapMedium + three properties in the payload => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium", "http://odata.org/stream/read").StreamProperty("CityLogo", "http://odata.org/stream/read"),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium", "http://odata.org/stream/read").StreamProperty("CityLogo", "http://odata.org/stream/read"),
                    ProjectionString = "MapMedium",
                },
                #endregion $select=MapMedium
                #region $select=NavProp/*
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp/* => three templatized stream properties and and one templatized navigation.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2)),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).StreamProperty("MapSmall").StreamProperty("MapMedium").StreamProperty("CityLogo").NavigationProperty("NavProp", /*url*/null)),
                    ProjectionString = "NavProp/*",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp/* + one property in the payload => two templatized stream properties and one templatized navigation.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).StreamProperty("MapSmall", "http://odata.org/stream/read")),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium").StreamProperty("CityLogo").NavigationProperty("NavProp", /*url*/null)),
                    ProjectionString = "NavProp/*",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp/* + three properties in the payload => no templatized stream properties, one templatized navigation.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium", "http://odata.org/stream/read").StreamProperty("CityLogo", "http://odata.org/stream/read")),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).StreamProperty("MapSmall", "http://odata.org/stream/read").StreamProperty("MapMedium", "http://odata.org/stream/read").StreamProperty("CityLogo", "http://odata.org/stream/read").NavigationProperty("NavProp", /*url*/null)),
                    ProjectionString = "NavProp/*",
                },
                #endregion $select=NavProp/*
                #region $select=NavProp/NavProp/MapMedium
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp/NavProp/MapMedium => one templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 3))),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 3).StreamProperty("MapMedium"))),
                    ProjectionString = "NavProp/NavProp/MapMedium",
                },
                #endregion $select=NavProp/NavProp/MapMedium
                #region $select=NavProp/NavProp
                new ProjectionTestCase
                {
                    DebugDescription = "$select=NavProp/NavProp => three templatized stream properties and one navigation property.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 3))),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 2).ExpandedNavigationProperty("NavProp", PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 3).StreamProperty("MapSmall").StreamProperty("MapMedium").StreamProperty("CityLogo").NavigationProperty("NavProp", /*url*/null))),
                    ProjectionString = "NavProp/NavProp",
                },
                #endregion $select=NavProp/NavProp
                #region $select=TestModel.CityType/CityLogo
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.CityType/CityLogo on base type => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1),
                    ProjectionString = "TestModel.CityType/CityLogo",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.CityType/CityLogo on derived type => specific property templatized.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("CityLogo"),
                    ProjectionString = "TestModel.CityType/CityLogo",
                },
                #endregion $select=TestModel.CityType/CityLogo
                #region $select=TestModel.CityType/MapSmall
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.CityType/MapSmall on base type => no templatized properties.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1),
                    ProjectionString = "TestModel.CityType/MapSmall",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.CityType/MapSmall on derived type => specific property templatized.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall"),
                    ProjectionString = "TestModel.CityType/MapSmall",
                },
                #endregion $select=TestModel.CityType/MapSmall
                #region $select=TestModel.TownType/MapSmall
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.TownType/MapSmall on base type => specific property templatized..",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.TownType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall"),
                    ProjectionString = "TestModel.TownType/MapSmall",
                },
                new ProjectionTestCase
                {
                    DebugDescription = "$select=TestModel.TownType/MapSmall on derived type => specific property templatized.",
                    PayloadEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1),
                    ExpectedEntity = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).StreamProperty("MapSmall"),
                    ProjectionString = "TestModel.TownType/MapSmall",
                },
                #endregion $select=TestModel.TownType/MapSmall
            };

            IEnumerable<PayloadReaderTestDescriptor> testDescriptors = testCases.Select(testCase =>
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = testCase.DebugDescription,
                    PayloadEdmModel = model,
                    PayloadElement = testCase.PayloadEntity
                        .WithContextUriProjection(testCase.ProjectionString)
                        .ExpectedEntityType(townType, townsSet),
                    ExpectedResultPayloadElement = tc => testCase.ExpectedEntity,
                    ExpectedException = testCase.ExpectedException,
                });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations.Where(tc => !tc.IsRequest),
                (testDescriptor, testConfiguration) =>
                {
                    // These descriptors are already tailored specifically for Json Light and 
                    // do not require normalization.
                    testDescriptor.TestDescriptorNormalizers.Clear();
                    testDescriptor.RunTest(testConfiguration);
                });
        }
        public void CollectionValueTest()
        {
            EdmModel model = new EdmModel();
            var complexType = new EdmComplexType("TestModel", "ComplexType").Property("Name", EdmPrimitiveTypeKind.String, true);
            model.AddElement(complexType);
            var owningType = new EdmEntityType("TestModel", "OwningType");
            owningType.AddKeys(owningType.AddStructuralProperty("ID", EdmCoreModel.Instance.GetInt32(false)));
            owningType.AddStructuralProperty("PrimitiveCollection", EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false)));
            owningType.AddStructuralProperty("ComplexCollection", EdmCoreModel.GetCollection(complexType.ToTypeReference()));
            model.AddElement(owningType);
            model.Fixup();
            
            var primitiveMultiValue = PayloadBuilder.PrimitiveMultiValue("Collection(Edm.Int32)").Item(42).Item(43);
            var complexMultiValue = PayloadBuilder.ComplexMultiValue("Collection(TestModel.ComplexType)").Item(
                PayloadBuilder.ComplexValue("TestModel.ComplexType")
                    .PrimitiveProperty("Name", "Value")
                    .AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null }))
                .JsonRepresentation("[{\"Name\":\"Value\"}]")
                .AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null });

            IEnumerable<PayloadReaderTestDescriptor> testDescriptors = new[]
            {
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "null collection in request - should fail.",
                    PayloadEdmModel = model,
                    PayloadElement = PayloadBuilder.Property("PrimitiveCollection",
                        PayloadBuilder.PrimitiveMultiValue("Collection(Edm.Int32)"))
                        .JsonRepresentation("{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true }")
                        .ExpectedProperty(owningType, "PrimitiveCollection"),
                    SkipTestConfiguration = tc => !tc.IsRequest,
                    ExpectedException = ODataExpectedExceptions.ODataException("ReaderValidationUtils_NullValueForNonNullableType", "Collection(Edm.Int32)")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "null collection in response - should fail.",
                    PayloadEdmModel = model,
                    PayloadElement = PayloadBuilder.Property("PrimitiveCollection",
                        PayloadBuilder.PrimitiveMultiValue("Collection(Edm.Int32)"))
                        .JsonRepresentation(
                            "{" + 
                            "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Collection(Edm.Int32)\"," +
                            "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true" +
                            "}")
                        .ExpectedProperty(owningType, "PrimitiveCollection"),
                    SkipTestConfiguration = tc => tc.IsRequest,
                    ExpectedException = ODataExpectedExceptions.ODataException("ReaderValidationUtils_NullValueForNonNullableType", "Collection(Edm.Int32)")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Primitive value for collection - should fail.",
                    PayloadEdmModel = model,
                    PayloadElement = PayloadBuilder.Property("PrimitiveCollection",
                        PayloadBuilder.PrimitiveMultiValue("Collection(Edm.Int32)")
                            .JsonRepresentation("42"))
                        .ExpectedProperty(owningType, "PrimitiveCollection"),
                    ExpectedException = ODataExpectedExceptions.ODataException("JsonReaderExtensions_UnexpectedNodeDetected", "StartArray", "PrimitiveValue")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Object value for collection - should fail.",
                    PayloadEdmModel = model,
                    PayloadElement = PayloadBuilder.Property("PrimitiveCollection",
                        PayloadBuilder.PrimitiveMultiValue("Collection(Edm.Int32)")
                            .JsonRepresentation("{}"))
                        .ExpectedProperty(owningType, "PrimitiveCollection"),
                    ExpectedException = ODataExpectedExceptions.ODataException("JsonReaderExtensions_UnexpectedNodeDetectedWithPropertyName", "StartArray", "StartObject", "value")
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Simple primitive collection.",
                    PayloadEdmModel = model,
                    PayloadElement = PayloadBuilder.Property("PrimitiveCollection",
                        primitiveMultiValue
                            .JsonRepresentation("[42,43]")
                            .AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null }))
                        .ExpectedProperty(owningType, "PrimitiveCollection"),
                    ExpectedResultPayloadElement = tc => tc.IsRequest
                        ? PayloadBuilder.Property(string.Empty, primitiveMultiValue)
                        : PayloadBuilder.Property("PrimitiveCollection", primitiveMultiValue)
                },
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = "Simple complex collection.",
                    PayloadEdmModel = model,
                    PayloadElement = PayloadBuilder.Property("ComplexCollection", complexMultiValue)
                        .ExpectedProperty(owningType, "ComplexCollection"),
                    ExpectedResultPayloadElement = tc => tc.IsRequest
                        ? PayloadBuilder.Property(string.Empty, complexMultiValue)
                        : PayloadBuilder.Property("ComplexCollection", complexMultiValue)
                },
            };

            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 ParameterReaderJsonLightTest()
        {
            EdmModel model = new EdmModel();
            model.Fixup();

            EdmEntityContainer container = model.EntityContainer as EdmEntityContainer;

            EdmFunction function = new EdmFunction(container.Namespace, "f1", EdmCoreModel.Instance.GetInt32(true));
            function.AddParameter("p1", EdmCoreModel.Instance.GetInt32(false) as EdmTypeReference);
            function.AddParameter("p2", EdmCoreModel.Instance.GetString(false) as EdmTypeReference);
            model.AddElement(function);
            EdmOperationImport f1 = container.FunctionImport(function);
                
            ComplexInstance f1Params = PayloadBuilder.ComplexValue().PrimitiveProperty("p1", 42).PrimitiveProperty("p2", "Vienna")
                .ExpectedFunctionImport(f1);

            var testCases = new[]
            {
                new
                {
                    DebugDescription = "Custom property annotation for a valid parameter property (before property) - should work.",
                    Json = "{\"" + JsonLightUtils.GetPropertyAnnotationName("p1", "my.custom") + "\":42, \"p1\":42, \"p2\":\"Vienna\"}",
                    ExpectedException = (ExpectedException)null,
                },
                new
                {
                    DebugDescription = "Custom property annotation for a valid parameter property (after property) - should fail.",
                    Json = "{\"p1\":42, \"" + JsonLightUtils.GetPropertyAnnotationName("p1", "my.custom") + "\":42, \"p2\":\"Vienna\"}",
                    ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_PropertyAnnotationAfterTheProperty", "my.custom", "p1"),
                },
                new
                {
                    DebugDescription = "OData property annotation for a valid parameter property (before property) - should work.",
                    Json = "{\"" + JsonLightUtils.GetPropertyAnnotationName("p1", JsonLightConstants.ODataTypeAnnotationName) + "\":42, \"p1\":42, \"p2\":\"Vienna\"}",
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightParameterDeserializer_PropertyAnnotationForParameters"),
                },
                new
                {
                    DebugDescription = "OData property annotation for a valid parameter property (after property) - should fail.",
                    Json = "{\"p1\":42, \"" + JsonLightUtils.GetPropertyAnnotationName("p1", JsonLightConstants.ODataTypeAnnotationName) + "\":42, \"p2\":\"Vienna\"}",
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightParameterDeserializer_PropertyAnnotationForParameters"),
                },
                new
                {
                    DebugDescription = "Custom property annotation for an invalid parameter property - should fail.",
                    Json = "{\"" + JsonLightUtils.GetPropertyAnnotationName("p0", "my.custom") + "\":42, \"p1\":42, \"p2\":\"Vienna\"}",
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightParameterDeserializer_PropertyAnnotationWithoutPropertyForParameters", "p0"),
                },
                new
                {
                    DebugDescription = "Custom instance annotation - should work.",
                    Json = "{\"@my.custom\":42, \"p1\":42, \"p2\":\"Vienna\"}",
                    ExpectedException = (ExpectedException)null,
                },
                new
                {
                    DebugDescription = "OData instance annotation - should fail.",
                    Json = "{\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.Int32\", \"p1\":42, \"p2\":\"Vienna\"}",
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties", JsonLightConstants.ODataTypeAnnotationName),
                },
            };

            var testDescriptors = testCases.Select(testCase =>
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = testCase.DebugDescription,
                    PayloadElement = f1Params.DeepCopy().JsonRepresentation(testCase.Json),
                    PayloadEdmModel = model,
                    PayloadKind = ODataPayloadKind.Parameter,
                    ExpectedException = testCase.ExpectedException,
                });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations.Where(c => c.IsRequest),
                (testDescriptor, testConfiguration) =>
                {
                    testDescriptor.ExpectedResultNormalizers.Add(tc => ParameterReaderTests.FixupExpectedCollectionParameterPayloadElement);

                    // 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 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 DuplicatePropertyNamesTest()
        {
            PropertyInstance primitiveProperty = PayloadBuilder.PrimitiveProperty("DuplicateProperty", 42);
            PropertyInstance complexProperty = PayloadBuilder.Property("DuplicateProperty", 
                PayloadBuilder.ComplexValue("TestModel.DuplicateComplexType").PrimitiveProperty("Name", "foo"));
            PropertyInstance collectionProperty = PayloadBuilder.Property("DuplicateProperty",
                PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.String")).WithTypeAnnotation(EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetString(false))));

            PropertyInstance[] allProperties = new[] { primitiveProperty, complexProperty, collectionProperty };
            PropertyInstance[] propertiesWithPossibleDuplication = new[] { primitiveProperty, complexProperty };
            PropertyInstance[] propertiesWithNoDuplication = new[] { collectionProperty };

            IEnumerable<DuplicatePropertySet> duplicatePropertySets;

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

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

            this.CombinatorialEngineProvider.RunCombinations(
                duplicatePropertySets,
                new bool[] { false, true },
                new bool[] { true, false },
                this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations,
                (duplicatePropertySet, allowDuplicateProperties, useMetadata, testConfiguration) =>
                {
                    EdmModel model = new EdmModel();
                    var complexType = model.ComplexType("DuplicateComplexType");
                    complexType.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);
                    model.Fixup();

                    PropertyInstance firstProperty = duplicatePropertySet.Properties.ElementAt(0);
                    PropertyInstance secondProperty = duplicatePropertySet.Properties.ElementAt(1);

                    // Non-metadata reading is not possible in JSON
                    if (!useMetadata && (testConfiguration.Format == ODataFormat.Json))
                    {
                        return;
                    }

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

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

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

                    // Now generate entity around it
                    testDescriptor = testDescriptor.InComplexValue(5, 5);

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

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

                    // We expect failure only if we don't allow duplicates or if the property kind doesn't allow duplicates ever
                    if ((!duplicatePropertySet.DuplicationPotentiallyAllowed || !allowDuplicateProperties))
                    {
                        testDescriptor.ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "DuplicateProperty");
                    }

                    IEnumerable<PayloadReaderTestDescriptor> testDescriptors = new PayloadReaderTestDescriptor[]
                    {
                        testDescriptor.InProperty("TopLevelProperty"),
                        testDescriptor.InProperty("ComplexProperty").InEntity(2, 2),
                        testDescriptor.InCollection(5, 5).InProperty("TopLevelCollection"),
                    };

                    this.CombinatorialEngineProvider.RunCombinations(
                        testDescriptors, 
                        td =>
                        {
                            var property = td.PayloadElement as PropertyInstance;
                            if (property != null && testConfiguration.Format == ODataFormat.Atom)
                            {
                                property.Name = null;
                            }
                            td.RunTest(testConfiguration);
                        });
                });
        }
        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);
                });
        }
        public void ComplexValueIgnorePropertyNullValuesTest()
        {
            var versions = new Version[] {
                    null,
                    new Version(4, 0),
                };

            EdmModel edmModel = new EdmModel();
            IEdmComplexType countryRegionType = edmModel.ComplexType("CountryRegion")
                .Property("Name", EdmPrimitiveTypeKind.String)
                .Property("CountryRegionCode", EdmPrimitiveTypeKind.String);
            IEdmComplexType countryRegionNullType = edmModel.ComplexType("CountryRegionNull")
                .Property("Name", EdmPrimitiveTypeKind.String)
                .Property("CountryRegionCode", EdmPrimitiveTypeKind.String);
            IEdmComplexType addressType = edmModel.ComplexType("Address")
                .Property("Street", EdmPrimitiveTypeKind.String)
                .Property("StreetNull", EdmCoreModel.Instance.GetString(true) as EdmTypeReference)
                .Property("Numbers", EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false)) as EdmTypeReference)
                .Property("CountryRegion", new EdmComplexTypeReference(countryRegionType, false))
                .Property("CountryRegionNull", new EdmComplexTypeReference(countryRegionNullType, true));
            edmModel.EntityType("Customer")
                .KeyProperty("ID", EdmCoreModel.Instance.GetInt32(false) as EdmTypeReference)
                .Property("Address", new EdmComplexTypeReference(addressType, false));
            edmModel.Fixup();

            this.CombinatorialEngineProvider.RunCombinations(
                new ODataNullValueBehaviorKind[] { ODataNullValueBehaviorKind.Default, ODataNullValueBehaviorKind.DisableValidation, ODataNullValueBehaviorKind.IgnoreValue },
                versions,
                versions,
                TestReaderUtils.ODataBehaviorKinds,
                (nullPropertyValueReaderBehavior, dataServiceVersion, edmVersion, behaviorKind) =>
                {
                    edmModel.SetEdmVersion(edmVersion);

                    // Now we set the 'IgnoreNullValues' annotation on all properties
                    IEdmComplexType edmAddressType = (IEdmComplexType)edmModel.FindType("TestModel.Address");
                    foreach (IEdmStructuralProperty edmProperty in edmAddressType.StructuralProperties())
                    {
                        edmModel.SetNullValueReaderBehavior(edmProperty, nullPropertyValueReaderBehavior);
                    }

                    EntityInstance customerPayload = PayloadBuilder.Entity("TestModel.Customer")
                        .PrimitiveProperty("ID", 1)
                        .Property("Address", PayloadBuilder.ComplexValue("TestModel.Address")
                            .PrimitiveProperty("Street", "One Microsoft Way")
                            .PrimitiveProperty("StreetNull", "One Microsoft Way")
                            .Property("Numbers", PayloadBuilder.PrimitiveMultiValue("Collection(Edm.Int32)").Item(1).Item(2))
                            .Property("CountryRegion", PayloadBuilder.ComplexValue("TestModel.CountryRegion")
                                .PrimitiveProperty("Name", "Austria")
                                .PrimitiveProperty("CountryRegionCode", "AUT"))
                            .Property("CountryRegionNull", PayloadBuilder.ComplexValue("TestModel.CountryRegionNull")
                                .PrimitiveProperty("Name", "Austria")
                                .PrimitiveProperty("CountryRegionCode", "AUT")));

                    var testCases = new[]
                    {
                        // Complex types that are not nullable should not allow null values.
                        // Null primitive property in the payload and non-nullable property in the model
                        new IgnoreNullValueTestCase
                        {
                            PropertyName = "Street",
                            ExpectedResponseException = ODataExpectedExceptions.ODataException("ReaderValidationUtils_NullNamedValueForNonNullableType", "Street", "Edm.String"),
                        },
                         // Null complex property in the payload and non-nullable property in the model
                        new IgnoreNullValueTestCase
                        {
                            PropertyName = "CountryRegion",
                            ExpectedResponseException = ODataExpectedExceptions.ODataException("ReaderValidationUtils_NullNamedValueForNonNullableType", "CountryRegion", "TestModel.CountryRegion"),
                        },
                        // Null collection property in the payload and non-nullable property in the model
                        new IgnoreNullValueTestCase
                        {
                            PropertyName = "Numbers",
                            ExpectedResponseException = ODataExpectedExceptions.ODataException("ReaderValidationUtils_NullNamedValueForNonNullableType", "Numbers", "Collection(Edm.Int32)"),
                        },
                        // Complex types that are nullable should allow null values.
                        // Null primitive property in the payload and nullable property in the model
                        new IgnoreNullValueTestCase
                        {
                            PropertyName = "StreetNull",
                        },
                        // Null complex property in the payload and nullable property in the model
                        new IgnoreNullValueTestCase
                        {
                            PropertyName = "CountryRegionNull",
                        },
                    };

                    Func<IgnoreNullValueTestCase, ReaderTestConfiguration, PayloadReaderTestDescriptor> createTestDescriptor =
                        (testCase, testConfig) =>
                        {
                            EntityInstance payloadValue = customerPayload.DeepCopy();
                            ComplexInstance payloadAddressValue = ((ComplexProperty)payloadValue.GetProperty("Address")).Value;
                            SetToNull(payloadAddressValue, testCase.PropertyName);

                            ComplexInstance resultValue = payloadValue;
                            if (testConfig.IsRequest && nullPropertyValueReaderBehavior == ODataNullValueBehaviorKind.IgnoreValue)
                            {
                                resultValue = customerPayload.DeepCopy();
                                ComplexInstance resultAddressValue = ((ComplexProperty)resultValue.GetProperty("Address")).Value;
                                resultAddressValue.Remove(resultAddressValue.GetProperty(testCase.PropertyName));
                            }

                            return new PayloadReaderTestDescriptor(this.Settings)
                            {
                                PayloadElement = payloadValue,
                                PayloadEdmModel = edmModel,
                                ExpectedResultPayloadElement = 
                                    tc =>
                                    {
                                        if (tc.Format == ODataFormat.Json)
                                        {
                                            // under the client knob ODL will compute edit links, ids, etc
                                            // so we need to update the expected payload
                                            if (tc.RunBehaviorKind == TestODataBehaviorKind.WcfDataServicesClient)
                                            {
                                                var entity = resultValue as EntityInstance;
                                                if (entity != null)
                                                {
                                                    if (!tc.IsRequest)
                                                    {
                                                        entity.Id = "http://odata.org/test/Customer(1)";
                                                        entity.EditLink = "http://odata.org/test/Customer(1)";
                                                        entity.WithSelfLink("http://odata.org/test/Customer(1)");
                                                    }
                                                }
                                            } 
                                            
                                            var tempDescriptor = new PayloadReaderTestDescriptor(this.Settings)
                                            {
                                                PayloadElement = resultValue,
                                                PayloadEdmModel = edmModel,
                                            };

                                            JsonLightPayloadElementFixup.Fixup(tempDescriptor);
                                            return tempDescriptor.PayloadElement;
                                        }

                                        return resultValue;
                                    },
                                ExpectedException = (testConfig.IsRequest && nullPropertyValueReaderBehavior != ODataNullValueBehaviorKind.Default) ? null : testCase.ExpectedResponseException
                            };
                        };

                    this.CombinatorialEngineProvider.RunCombinations(
                        testCases,
                        this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations,
                        (testCase, testConfiguration) =>
                        {
                            testConfiguration = testConfiguration.CloneAndApplyBehavior(behaviorKind);
                            testConfiguration.MessageReaderSettings.BaseUri = null;

                            PayloadReaderTestDescriptor testDescriptor = createTestDescriptor(testCase, testConfiguration);
                            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;

        }
        private void RunCombinationsForUndeclaredPropertyBehavior(IEnumerable<PayloadReaderTestDescriptor> testCases, ODataUndeclaredPropertyBehaviorKinds behavior, Func<ReaderTestConfiguration, bool> additionalConfigurationFilter = null)
        {
            EdmModel model = new EdmModel();
            var entity = new EdmEntityType("TestModel", "EntityType", null, false, true);
            entity.AddKeys(entity.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
            model.AddElement(entity);
            var complexType = new EdmComplexType("TestModel", "ComplexType");
            model.AddElement(complexType);

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

            var testCaseList = testCases.ToList();
            testCaseList.ForEach(t => t.PayloadEdmModel = model);

            this.CombinatorialEngineProvider.RunCombinations(
                testCaseList,
                this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations.Where(tc => !tc.IsRequest && (additionalConfigurationFilter == null || additionalConfigurationFilter(tc))),
                (testDescriptor, testConfiguration) =>
                {
                    testConfiguration = new ReaderTestConfiguration(testConfiguration);
                    testConfiguration.MessageReaderSettings.UndeclaredPropertyBehaviorKinds = behavior;

                    testDescriptor.RunTest(testConfiguration);
                });
        }