public void OpenComplexTopLevelPropertiesTest()
        {
            IEdmModel model = TestModels.BuildTestModel();

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

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

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

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

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

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

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

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

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

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

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

                    // An open property without expected and payload type cannot be read; expect an exception.
                    expectedException = ODataExpectedExceptions.ODataException("ReaderValidationUtils_ResourceWithoutType");
                }

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

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

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

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

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

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

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

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

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

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

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

                bool typeGiven = withExpectedType || withPayloadType || withContextUri;

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

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

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

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

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

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

                // These descriptors are already tailored specifically for Json Light and
                // do not require normalization.
                testDescriptor.TestDescriptorNormalizers.Clear();
                testDescriptor.RunTest(testConfiguration);
            });
        }
        public void OpenPropertiesTest()
        {
            IEdmModel model = Test.OData.Utils.Metadata.TestModels.BuildTestModel();
            IEdmEntityContainer container = model.FindEntityContainer("DefaultContainer");
            IEdmEntitySet citiesEntitySet = container.FindEntitySet("Cities");
            IEdmType cityType = model.FindType("TestModel.CityType");

            var testCases = new OpenPropertyTestCase[]
            {
                new OpenPropertyTestCase
                {
                    DebugDescription = "Simple integer open property without type information.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", 42),
                    Json = "\"OpenProperty\":42",
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "null open property without type information.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", null),
                    Json = "\"OpenProperty\":null",
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "String open property with string type information.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value"),
                    Json = 
                        "\"" + JsonLightUtils.GetPropertyAnnotationName("OpenProperty", JsonLightConstants.ODataTypeAnnotationName) + "\":\"Edm.String\"," +
                        "\"OpenProperty\":\"value\"",
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "String open property with date time value without type information.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "2012-04-13T02:43:10.215Z"),
                    Json = "\"OpenProperty\":\"2012-04-13T02:43:10.215Z\"",
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "DateTimeOffset open property with type information.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", new DateTimeOffset(2012, 4, 13, 2, 43, 10, 215, TimeSpan.Zero)),
                    Json = 
                        "\"" + JsonLightUtils.GetPropertyAnnotationName("OpenProperty", JsonLightConstants.ODataTypeAnnotationName) + "\":\"Edm.DateTimeOffset\"," +
                        "\"OpenProperty\":\"2012-04-13T02:43:10.215Z\"",
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "Spatial open property with type information - should work.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", GeographyFactory.Point(25.0, 23.2).Build()),
                    Json = "\"" + JsonLightUtils.GetPropertyAnnotationName("OpenProperty", JsonLightConstants.ODataTypeAnnotationName) + "\":\"Edm.GeographyPoint\"," + 
                           "\"OpenProperty\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, GeographyFactory.Point(25.0, 23.2).Build()),
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "Empty complex open property with type information.",
                    ExpectedProperty = PayloadBuilder.Property("OpenProperty", PayloadBuilder.ComplexValue("TestModel.Address")),
                    Json = "\"OpenProperty\":{ \"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"TestModel.Address\"}",
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "Complex property with data with type information.",
                    ExpectedProperty = PayloadBuilder.Property("OpenProperty", PayloadBuilder.ComplexValue("TestModel.Address").PrimitiveProperty("Street", "First")),
                    Json = "\"OpenProperty\":{ \"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"TestModel.Address\", \"Street\":\"First\"}",
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "String open property with complex type information - should fail.",
                    ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value"),
                    Json = 
                        "\"" + JsonLightUtils.GetPropertyAnnotationName("OpenProperty", JsonLightConstants.ODataTypeAnnotationName) + "\":\"TestModel.Address\"," +
                        "\"OpenProperty\":\"value\"",
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_ComplexValueWithPropertyTypeAnnotation")
                },
                new OpenPropertyTestCase
                {
                    DebugDescription = "Open collection property - should pass.",
                    ExpectedProperty = PayloadBuilder.Property("OpenProperty", PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.Int32")).Item(1)),
                    Json = 
                        "\"" + JsonLightUtils.GetPropertyAnnotationName("OpenProperty", JsonLightConstants.ODataTypeAnnotationName) + "\":\"Collection(Edm.Int32)\"," +
                        "\"OpenProperty\":[1]",
                },
            };

            IEnumerable<PayloadReaderTestDescriptor> testDescriptors = testCases.Select(testCase =>
                new PayloadReaderTestDescriptor(this.Settings)
                {
                    DebugDescription = testCase.DebugDescription,
                    PayloadElement = PayloadBuilder.Entity("TestModel.CityOpenType").PrimitiveProperty("Id", 1)
                        .Property(testCase.ExpectedProperty)
                        .JsonRepresentation("{" +
                            "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#TestModel.DefaultContainer.Cities/TestModel.CityOpenType()/$entity\"," +
                            "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"TestModel.CityOpenType\"," +
                            "\"Id\":1," +
                            testCase.Json +
                            "}")
                        .ExpectedEntityType(cityType, citiesEntitySet),
                    PayloadEdmModel = model,
                    ExpectedException = testCase.ExpectedException
                });

            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 OpenTopLevelPropertiesErrorTest()
        {
            IEdmModel model = TestModels.BuildTestModel();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    bool typeGiven = withExpectedType || withPayloadType || withContextUri;

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

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

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

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

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

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

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