Example #1
0
    void RecursiveTraverseTree(Node node, Vector3 point, Action <T> action)
    {
        bool side = SpatialUtils.SideToPlane(node.plane, point);
        Node a = node.right, b = node.left;

        if (!side)
        {
            a = node.left; b = node.right;
        }

        if (a != null)
        {
            RecursiveTraverseTree(a, point, action);
        }

        if (action != null)
        {
            foreach (var obj in node.objs)
            {
                action(obj);
            }
        }

        if (b != null)
        {
            RecursiveTraverseTree(b, point, action);
        }
    }
Example #2
0
 static bool SplitTriangle(Plane plane, Vector3 v0, Vector3 v1, Vector3 v2, ref float t1, ref float t2)
 {
     t1 = SpatialUtils.SplitSegment(plane, v0, v1);
     t2 = SpatialUtils.SplitSegment(plane, v0, v2);
     if (t1 < 0f || t1 > 1f)
     {
         return(false);
     }
     if (t2 < 0f || t2 > 1f)
     {
         return(false);
     }
     return(true);
 }
Example #3
0
    void RecursiveBuildTree(Node node)
    {
        if (node.objs.Count <= 1)
        {
            return;
        }

        Plane splitPlane = PickSplittingPlane(node.objs);

        List <T> nodeObjs  = new List <T>();
        List <T> frontObjs = new List <T>();
        List <T> backObjs  = new List <T>();

        foreach (var obj in node.objs)
        {
            if (SpatialUtils.PlaneCoincide(splitPlane, obj.plane))
            {
                nodeObjs.Add(obj);
            }
            else
            {
                obj.Split(splitPlane, ref frontObjs, ref backObjs);
            }
        }

        node.plane = splitPlane;
        node.objs  = nodeObjs;

        if (frontObjs.Count > 0)
        {
            node.left      = new Node();
            node.left.objs = frontObjs;
            RecursiveBuildTree(node.left);
        }

        if (backObjs.Count > 0)
        {
            node.right      = new Node();
            node.right.objs = backObjs;
            RecursiveBuildTree(node.right);
        }
    }
Example #4
0
    void Start()
    {
        var meshList = meshRoot.GetComponentsInChildren <MeshFilter>();

        if (meshList.Length <= 0)
        {
            return;
        }

        objBounds = meshList[0].mesh.bounds;
        foreach (var meshF in meshList)
        {
            var boundsList = SpatialUtils.GetMeshTriangleBoundsList(meshF.mesh);
            objBoundsList.AddRange(boundsList);
            objBounds.Encapsulate(meshF.mesh.bounds);
        }

        bvhtree.BuildTree(objBoundsList);
        octree.BuildTree(objBoundsList, objBounds);
    }
Example #5
0
    bool RecursiveIntersectPoint(Node node, Vector3 point)
    {
        bool side = SpatialUtils.SideToPlane(node.plane, point);

        if (side)
        {
            if (node.left != null)
            {
                return(RecursiveIntersectPoint(node.left, point));
            }
            return(false);
        }
        else
        {
            if (node.right != null)
            {
                return(RecursiveIntersectPoint(node.right, point));
            }
            return(true);
        }
    }
Example #6
0
    public void Split <T>(Plane plane, ref List <T> front, ref List <T> back) where T : BSPtreeObject
    {
        bool s0 = SpatialUtils.SideToPlane(plane, vertices[0]);
        bool s1 = SpatialUtils.SideToPlane(plane, vertices[1]);
        bool s2 = SpatialUtils.SideToPlane(plane, vertices[2]);

        if (s0 && s1 && s2)
        {
            front.Add(this as T);
        }
        else if (!(s0 || s1 || s2))
        {
            back.Add(this as T);
        }
        else if (s0 && !(s1 || s2))
        {
            SplitObject(plane, 0, 1, 2, ref front, ref back);
        }
        else if (s1 && !(s2 || s0))
        {
            SplitObject(plane, 1, 2, 0, ref front, ref back);
        }
        else if (s2 && !(s0 || s1))
        {
            SplitObject(plane, 2, 0, 1, ref front, ref back);
        }
        else if (s0 && s1 && !s2)
        {
            SplitObject(plane, 2, 0, 1, ref back, ref front);
        }
        else if (s2 && s0 && !s1)
        {
            SplitObject(plane, 1, 2, 0, ref back, ref front);
        }
        else if (s1 && s2 && !s0)
        {
            SplitObject(plane, 0, 1, 2, ref back, ref front);
        }
    }
Example #7
0
    public UbietyResult UbietyToPlane(Plane plane)
    {
        if (SpatialUtils.PlaneCoincide(plane, this.plane))
        {
            return(UbietyResult.Coincident);
        }

        bool s0 = SpatialUtils.SideToPlane(plane, vertices[0]);
        bool s1 = SpatialUtils.SideToPlane(plane, vertices[1]);
        bool s2 = SpatialUtils.SideToPlane(plane, vertices[2]);

        if (s0 && s1 && s2)
        {
            return(UbietyResult.Front);
        }
        else if (!(s0 || s1 || s2))
        {
            return(UbietyResult.Back);
        }
        else
        {
            return(UbietyResult.Cross);
        }
    }
        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);
            });
        }
Example #10
0
        public void ComplexValueTest()
        {
            var injectedProperties = new[]
            {
                new
                {
                    InjectedJSON      = string.Empty,
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    InjectedJSON      = "\"@custom.annotation\": null",
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    InjectedJSON      = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataAnnotationNamespacePrefix + "unknown\": { }",
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    InjectedJSON      = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\": { }",
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_UnexpectedAnnotationProperties", JsonLightConstants.ODataContextAnnotationName)
                },
                new
                {
                    InjectedJSON      = "\"@custom.annotation\": null, \"@custom.annotation\": 42",
                    ExpectedException = (ExpectedException)null
                },
            };

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

            EdmModel model = new EdmModel();

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

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

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

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

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

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

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

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

            IEnumerable <PayloadReaderTestDescriptor> testDescriptors = payloads.SelectMany(payload => injectedProperties.Select(injectedProperty =>
            {
                var json = string.Format(payload.Json, injectedProperty.InjectedJSON, string.IsNullOrEmpty(injectedProperty.InjectedJSON) ? string.Empty : ",");
                json     = string.Format("{{{0}{1}{2}}}",
                                         "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#TestModel.ComplexType\"",
                                         string.IsNullOrEmpty(json) ? string.Empty : ",", json);
                return(new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadKind = ODataPayloadKind.Resource,
                    PayloadElement = payload.ExpectedValue.DeepCopy()
                                     .JsonRepresentation(json)
                                     // JSON Light payloads don't store complex type names since the type can be inferred from the context URI and or API.
                                     .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    })
                                     .ExpectedEntityType(complexType),
                    PayloadEdmModel = model,
                    ExpectedException = injectedProperty.ExpectedException,
                    ExpectedResultPayloadElement = tc => tc.IsRequest
                        ? payload.ExpectedValue
                                                   .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    }).IsComplex(true)
                        : payload.ExpectedValue
                                                   .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    }).IsComplex(true)
                });
            }));

            var explicitPayloadsForPrimitiveAndArray = new[]
            {
                new
                {
                    Description       = "Primitive value as complex - should fail.",
                    Json              = "42",
                    ExpectedPayload   = PayloadBuilder.Entity("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("JsonReaderExtensions_UnexpectedNodeDetected", "StartObject", "PrimitiveValue")
                },
                new
                {
                    Description       = "Array value as complex - should fail.",
                    Json              = "[]",
                    ExpectedPayload   = PayloadBuilder.Entity("TestModel.ComplexType"),
                    ExpectedException = ODataExpectedExceptions.ODataException("JsonReaderExtensions_UnexpectedNodeDetected", "StartObject", "StartArray")
                },
            };

            testDescriptors = testDescriptors.Concat(explicitPayloadsForPrimitiveAndArray.Select(payload =>
            {
                return(new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = payload.ExpectedPayload.DeepCopy()
                                     .JsonRepresentation(payload.Json)
                                     // JSON Light payloads don't store complex type names since the type can be inferred from the context URI and or API.
                                     .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    })
                                     .ExpectedEntityType(complexType),
                    PayloadEdmModel = model,
                    ExpectedException = payload.ExpectedException,
                    DebugDescription = payload.Description,
                    ExpectedResultPayloadElement = tc => payload.ExpectedPayload.DeepCopy()
                                                   .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    })
                });
            }));

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

            testDescriptors = testDescriptors.Concat(explicitPayloads.Select(payload =>
            {
                var json = string.Format("{{{0}{1}{2}}}",
                                         "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#TestModel.ComplexType\"",
                                         string.IsNullOrEmpty(payload.Json) ? string.Empty : ",", payload.Json);
                return(new PayloadReaderTestDescriptor(this.Settings)
                {
                    PayloadElement = payload.ExpectedPayload.DeepCopy()
                                     .JsonRepresentation(json)
                                     // JSON Light payloads don't store complex type names since the type can be inferred from the context URI and or API.
                                     .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    })
                                     .ExpectedEntityType(complexType),
                    PayloadEdmModel = model,
                    ExpectedException = payload.ExpectedException,
                    DebugDescription = payload.Description,
                    ExpectedResultPayloadElement = tc => payload.ExpectedPayload.DeepCopy()
                                                   .SetAnnotation(new SerializationTypeNameTestAnnotation()
                    {
                        TypeName = null
                    })
                });
            }));

            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);
            });
        }