public void SpatialPropertyErrorTest()
        {
            EdmModel model     = new EdmModel();
            var      container = new EdmEntityContainer("TestModel", "DefaultContainer");

            model.AddElement(container);

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

            owningType.AddKeys(owningType.AddStructuralProperty("ID", EdmCoreModel.Instance.GetInt32(false)));
            owningType.AddStructuralProperty("TopLevelProperty", EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPoint, true));
            model.AddElement(owningType);

            IEdmEntityType         edmOwningType       = (IEdmEntityType)model.FindDeclaredType("TestModel.OwningType");
            IEdmStructuralProperty edmTopLevelProperty = (IEdmStructuralProperty)edmOwningType.FindProperty("TopLevelProperty");

            PayloadReaderTestDescriptor.ReaderMetadata readerMetadata = new PayloadReaderTestDescriptor.ReaderMetadata(edmTopLevelProperty);
            string pointValue = SpatialUtils.GetSpatialStringValue(ODataFormat.Json, GeographyFactory.Point(33.1, -110.0).Build(), "Edm.GeographyPoint");

            var explicitPayloads = new[]
            {
                new
                {
                    Description = "Spatial value with type information and odata.type annotation - should fail.",
                    Json        = "{ " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.GeographyPoint\", " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.GeographyPoint\"," +
                                  "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + pointValue +
                                  "}",
                    ReaderMetadata    = readerMetadata,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_ODataTypeAnnotationInPrimitiveValue", JsonLightConstants.ODataTypeAnnotationName)
                },
                new
                {
                    Description = "Spatial value with odata.type annotation - should fail.",
                    Json        = "{ " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.GeographyPoint\", " +
                                  "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + pointValue +
                                  "}",
                    ReaderMetadata    = readerMetadata,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_ODataTypeAnnotationInPrimitiveValue", JsonLightConstants.ODataTypeAnnotationName)
                },
            };

            var testDescriptors = explicitPayloads.Select(payload =>
            {
                return(new NativeInputReaderTestDescriptor()
                {
                    DebugDescription = payload.Description,
                    PayloadKind = ODataPayloadKind.Property,
                    InputCreator = (tc) =>
                    {
                        return payload.Json;
                    },
                    PayloadEdmModel = model,

                    // We use payload expected result just as a convenient way to run the reader for the Property payload kind
                    // since the reading should always fail, we don't need anything to compare the results to.
                    ExpectedResultCallback = (tc) =>
                                             new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                    {
                        ReaderMetadata = payload.ReaderMetadata,
                        ExpectedException = payload.ExpectedException,
                    },
                });
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                testDescriptor.RunTest(testConfiguration);
            });
        }
        public void TopLevelPropertyTest()
        {
            var injectedProperties = new[]
            {
                new
                {
                    InjectedJSON      = string.Empty,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    InjectedJSON      = "\"@custom.annotation\": null",
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    InjectedJSON      = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataAnnotationNamespacePrefix + "unknown\": { }",
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    InjectedJSON      = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\": { }",
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties", JsonLightConstants.ODataContextAnnotationName)
                },
                new
                {
                    InjectedJSON      = "\"@custom.annotation\": null, \"@custom.annotation\": 42",
                    ExpectedException = (ExpectedException)null
                },
            };

            var payloads = new[]
            {
                new
                {
                    Json = "{{ " +
                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                           "\"value\": null" +
                           "{1}{0}" +
                           "}}",
                },
                new
                {
                    Json = "{{ " +
                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                           "{0}{1}" +
                           "\"" + JsonLightConstants.ODataValuePropertyName + "\": 42" +
                           "}}",
                },
                new
                {
                    Json = "{{ " +
                           "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                           "\"" + JsonLightConstants.ODataValuePropertyName + "\": 42" +
                           "{1}{0}" +
                           "}}",
                },
            };

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

            model.AddElement(container);

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

            owningType.AddKeys(owningType.AddStructuralProperty("ID", EdmCoreModel.Instance.GetInt32(false)));
            owningType.AddStructuralProperty("TopLevelProperty", EdmCoreModel.Instance.GetInt32(true));
            owningType.AddStructuralProperty("TopLevelSpatialProperty", EdmCoreModel.Instance.GetSpatial(EdmPrimitiveTypeKind.GeographyPoint, false));
            owningType.AddStructuralProperty("TopLevelCollectionProperty", EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false)));
            model.AddElement(owningType);

            IEdmEntityType         edmOwningType                 = (IEdmEntityType)model.FindDeclaredType("TestModel.OwningType");
            IEdmStructuralProperty edmTopLevelProperty           = (IEdmStructuralProperty)edmOwningType.FindProperty("TopLevelProperty");
            IEdmStructuralProperty edmTopLevelSpatialProperty    = (IEdmStructuralProperty)edmOwningType.FindProperty("TopLevelSpatialProperty");
            IEdmStructuralProperty edmTopLevelCollectionProperty = (IEdmStructuralProperty)edmOwningType.FindProperty("TopLevelCollectionProperty");

            PayloadReaderTestDescriptor.ReaderMetadata readerMetadata           = new PayloadReaderTestDescriptor.ReaderMetadata(edmTopLevelProperty);
            PayloadReaderTestDescriptor.ReaderMetadata spatialReaderMetadata    = new PayloadReaderTestDescriptor.ReaderMetadata(edmTopLevelSpatialProperty);
            PayloadReaderTestDescriptor.ReaderMetadata collectionReaderMetadata = new PayloadReaderTestDescriptor.ReaderMetadata(edmTopLevelCollectionProperty);

            var testDescriptors = payloads.SelectMany(payload => injectedProperties.Select(injectedProperty =>
            {
                return(new NativeInputReaderTestDescriptor()
                {
                    PayloadKind = ODataPayloadKind.Property,
                    InputCreator = (tc) =>
                    {
                        string input = string.Format(payload.Json, injectedProperty.InjectedJSON, string.IsNullOrEmpty(injectedProperty.InjectedJSON) ? string.Empty : ",");
                        return input;
                    },
                    PayloadEdmModel = model,

                    // We use payload expected result just as a convenient way to run the reader for the Property payload kind.
                    // We validate whether the reading succeeds or fails, but not the actual read values (at least not here).
                    ExpectedResultCallback = (tc) =>
                                             new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                    {
                        ReaderMetadata = readerMetadata,
                        ExpectedException = injectedProperty.ExpectedException,
                    }
                });
            }));

            var explicitPayloads = new[]
            {
                new
                {
                    Description = "Custom property annotation - should be ignored.",
                    Json        = "{ " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("value", "custom.annotation") + "\": null," +
                                  "\"" + JsonLightConstants.ODataValuePropertyName + "\": 42" +
                                  "}",
                    ReaderMetadata    = readerMetadata,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    Description = "Duplicate custom property annotation - should not fail.",
                    Json        = "{ " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("value", "custom.annotation") + "\": null," +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("value", "custom.annotation") + "\": 42," +
                                  "\"" + JsonLightConstants.ODataValuePropertyName + "\": 42" +
                                  "}",
                    ReaderMetadata    = readerMetadata,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    Description = "Unrecognized odata property annotation - should be ignored.",
                    Json        = "{ " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("value", JsonLightConstants.ODataAnnotationNamespacePrefix + "unknown") + "\": null," +
                                  "\"" + JsonLightConstants.ODataValuePropertyName + "\": 42" +
                                  "}",
                    ReaderMetadata    = readerMetadata,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    Description = "Custom property annotation after the property - should fail.",
                    Json        = "{ " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                                  "\"" + JsonLightConstants.ODataValuePropertyName + "\": 42," +
                                  "\"" + JsonLightUtils.GetPropertyAnnotationName("value", "custom.annotation") + "\": null" +
                                  "}",
                    ReaderMetadata    = readerMetadata,
                    ExpectedException = ODataExpectedExceptions.ODataException("PropertyAnnotationAfterTheProperty", "custom.annotation", "value")
                },
                new
                {
                    Description = "OData property annotation.",
                    Json        = "{ " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\": \"Edm.Int32\"," +
                                  "\"" + JsonLightConstants.ODataValuePropertyName + "\": 42" +
                                  "}",
                    ReaderMetadata    = readerMetadata,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    Description = "Duplicate odata.type property should fail.",
                    Json        = "{ " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\": \"Edm.Int32\"," +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\": \"Edm.String\"," +
                                  "\"" + JsonLightConstants.ODataValuePropertyName + "\": 42" +
                                  "}",
                    ReaderMetadata    = readerMetadata,
                    ExpectedException = ODataExpectedExceptions.ODataException("DuplicateAnnotationNotAllowed", JsonLightConstants.ODataTypeAnnotationName)
                },
                new
                {
                    Description = "Type information for top-level property - correct.",
                    Json        = "{ " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\": \"Edm.Int32\"," +
                                  "\"" + JsonLightConstants.ODataValuePropertyName + "\": 42" +
                                  "}",
                    ReaderMetadata    = readerMetadata,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    Description = "Type information for top-level property - different kind - should fail.",
                    Json        = "{ " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\": \"Collection(Edm.Int32)\"," +
                                  "\"" + JsonLightConstants.ODataValuePropertyName + "\": 42" +
                                  "}",
                    ReaderMetadata    = readerMetadata,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "Collection(Edm.Int32)", "Primitive", "Collection")
                },
                new
                {
                    Description = "Unknown type information for top-level null - should fail.",
                    Json        = "{ " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\": \"Unknown\"," +
                                  "\"" + JsonLightConstants.ODataValuePropertyName + "\": null" +
                                  "}",
                    ReaderMetadata    = readerMetadata,
                    ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "Unknown", "Primitive", "Complex")
                },
                new
                {
                    Description = "Type information for top-level spatial - should work.",
                    Json        = "{ " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.GeographyPoint\", " +
                                  "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\": \"Edm.GeographyPoint\"," +
                                  "\"" + JsonLightConstants.ODataValuePropertyName + "\":" + SpatialUtils.GetSpatialStringValue(ODataFormat.Json, GeographyFactory.Point(33.1, -110.0).Build()) +
                                  "}",
                    ReaderMetadata    = spatialReaderMetadata,
                    ExpectedException = (ExpectedException)null
                },
            };

            testDescriptors = testDescriptors.Concat(explicitPayloads.Select(payload =>
            {
                return(new NativeInputReaderTestDescriptor()
                {
                    PayloadKind = ODataPayloadKind.Property,
                    InputCreator = (tc) =>
                    {
                        return payload.Json;
                    },
                    PayloadEdmModel = model,

                    // We use payload expected result just as a convenient way to run the reader for the Property payload kind
                    // since the reading should always fail, we don't need anything to compare the results to.
                    ExpectedResultCallback = (tc) =>
                                             new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                    {
                        ReaderMetadata = payload.ReaderMetadata,
                        ExpectedException = payload.ExpectedException,
                    },
                    DebugDescription = payload.Description
                });
            }));

            // Add a test descriptor to verify that we ignore odata.context in requests
            testDescriptors = testDescriptors.Concat(
                new NativeInputReaderTestDescriptor[]
            {
                new NativeInputReaderTestDescriptor()
                {
                    DebugDescription = "Top-level property with invalid name.",
                    PayloadKind      = ODataPayloadKind.Property,
                    InputCreator     = tc =>
                    {
                        return("{ " +
                               "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.Int32\", " +
                               "\"TopLevelProperty\": 42" +
                               "}");
                    },
                    PayloadEdmModel        = model,
                    ExpectedResultCallback = tc =>
                                             new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings)
                    {
                        ReaderMetadata    = readerMetadata,
                        ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyName", "TopLevelProperty", "value")
                    },
                    SkipTestConfiguration = tc => !tc.IsRequest
                }
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                testDescriptor.RunTest(testConfiguration);
            });
        }