/// <summary>
        /// Compares EntityType elements from CSDL to IEdmEntityTypes in the model.
        /// </summary>
        /// <param name="schemaElements">The CSDL schema elements to extract EntityType elements from.</param>
        /// <param name="model">The Edm model to extract the IEdmEntityTypes from.</param>
        private static void CompareEntityTypes(IEnumerable <XElement> schemaElements, IEdmModel model)
        {
            // Index all types in the CSDL by full name to facilitate derived type verification
            var typeIndex = BuildNamedElementIndex(schemaElements, "EntityType");

            ExceptionUtilities.Assert(typeIndex.Count == model.EntityTypes().Count(), "Unexpected type count in model");

            foreach (var entityType in typeIndex)
            {
                var modelType = model.EntityTypes().SingleOrDefault(t => t.FullName() == entityType.Key);
                ExceptionUtilities.Assert(modelType != null, "Failed to find entity type " + entityType.Key);
                CompareEntityTypeProperties(entityType.Value, modelType, typeIndex);
            }
        }
示例#2
0
 public static void LoadODataAnnotations(this IEdmModel model, int maxEntityPropertyMappingsPerType)
 {
     ExceptionUtils.CheckArgumentNotNull <IEdmModel>(model, "model");
     foreach (IEdmEntityType type in model.EntityTypes())
     {
         model.LoadODataAnnotations(type, maxEntityPropertyMappingsPerType);
     }
 }
示例#3
0
 /// <summary>
 /// Gets the collection navigation property of a model which was created via CreateModelWithNavProps().
 /// </summary>
 /// <param name="edmModel">The model to search.</param>
 /// <returns>The collection navigation property in the model.</returns>
 private static IEdmNavigationProperty GetCollectionNavProp(IEdmModel edmModel)
 {
     return(edmModel
            .EntityTypes()
            .Single(et => et.Name == "Customer")
            .DeclaredProperties
            .OfType <IEdmNavigationProperty>()
            .Single(p => p.Name == "Orders"));
 }
示例#4
0
        /// <summary>
        /// Gets the <see cref="EntityType"/> of the specified entry or feed payload element.
        /// </summary>
        /// <param name="payloadElement">The payload element to get the entity type for.</param>
        /// <param name="model">The model to find the entity type in.</param>
        /// <returns>The <see cref="EntityType"/> of the <paramref name="payloadElement"/>.</returns>
        public static IEdmEntityType GetPayloadElementEntityType(ODataPayloadElement payloadElement, IEdmModel model)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            ExceptionUtilities.CheckArgumentNotNull(model, "model");

            ODataPayloadKind payloadKind = payloadElement.GetPayloadKindFromPayloadElement();

            ExceptionUtilities.Assert(
                payloadKind == ODataPayloadKind.Resource || payloadKind == ODataPayloadKind.ResourceSet,
                "Can only determine entity type for entry or feed payloads.");

            EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation <EntityModelTypeAnnotation>();

            if (typeAnnotation != null)
            {
                var entityDataType = typeAnnotation.EdmModelType;
                Debug.Assert(entityDataType != null, "entityDataType != null");
                return(model.EntityTypes().Single(et => et.FullName() == entityDataType.FullName()));
            }

            string entityTypeName;

            if (payloadKind == ODataPayloadKind.Resource)
            {
                EntityInstance entity = payloadElement as EntityInstance;
                Debug.Assert(entity != null, "entity != null");
                entityTypeName = entity.FullTypeName;
                return(model.EntityTypes().Single(et => et.TestFullName() == entityTypeName));
            }
            else
            {
                //if feed has entries figure out type otherwise use first entity type
                EntitySetInstance feed = payloadElement as EntitySetInstance;
                Debug.Assert(feed != null, "feed != null");
                if (feed.Count > 0)
                {
                    return(model.EntityTypes().Single(et => et.TestFullName() == ((TypedValue)feed.First()).FullTypeName));
                }
                else
                {
                    return(model.EntityTypes().First());
                }
            }
        }
示例#5
0
        /// <summary>
        /// Loads the supported, OData-specific serializable annotations into their in-memory representations.
        /// </summary>
        /// <param name="model">The <see cref="IEdmModel"/> to process.</param>
        /// <param name="maxEntityPropertyMappingsPerType">The maximum number of entity mapping attributes to be found
        /// for an entity type (on the type itself and all its base types).</param>
        public static void LoadODataAnnotations(this IEdmModel model, int maxEntityPropertyMappingsPerType)
        {
            ExceptionUtils.CheckArgumentNotNull(model, "model");

            // NOTE: right now we only support annotations on entity types so we only iterate through them.
            foreach (IEdmEntityType entityType in model.EntityTypes())
            {
                LoadODataAnnotations(model, entityType, maxEntityPropertyMappingsPerType);
            }
        }
示例#6
0
 public static void SaveODataAnnotations(this IEdmModel model)
 {
     ExceptionUtils.CheckArgumentNotNull <IEdmModel>(model, "model");
     if (!model.IsUserModel())
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ODataUtils_CannotSaveAnnotationsToBuiltInModel);
     }
     foreach (IEdmEntityType type in model.EntityTypes())
     {
         SaveODataAnnotationsImplementation(model, type);
     }
 }
        /// <summary>
        /// Compare EntityContainer elements from CSDL against those in an Edm model.
        /// </summary>
        /// <param name="schemaElements">The CSDL schema elements containing the EntityContainer elements.</param>
        /// <param name="model">The Edm model to compare against.</param>
        private static void CompareEntityContainers(IEnumerable <XElement> schemaElements, IEdmModel model)
        {
            // Index by qualified name to facilitate lookups for extended containers
            var containerIndex = BuildNamedElementIndex(schemaElements, "EntityContainer");

            var modelContainers = model.SchemaElements.OfType <IEdmEntityContainer>();

            ExceptionUtilities.Assert(containerIndex.Count() == modelContainers.Count(), "Unexpected number of entity containers");

            foreach (var containerIndice in containerIndex)
            {
                var    containerElement = containerIndice.Value;
                string containerName    = containerElement.GetAttributeValue("Name");
                var    modelContainer   = modelContainers.SingleOrDefault(c => c.Name == containerName);
                ExceptionUtilities.Assert(modelContainer != null, "Failed to find container " + containerName);

                var containerElements = new List <XElement> {
                    containerElement
                };

                string extendsContainer;
                var    extendingContainerElement = containerElement;
                while (extendingContainerElement.TryGetAttributeValue("Extends", out extendsContainer))
                {
                    ExceptionUtilities.Assert(containerIndex.ContainsKey(extendsContainer), "Failed to find extended entity container " + extendsContainer);
                    extendingContainerElement = containerIndex[extendsContainer];
                    containerElements.Add(extendingContainerElement);

                    // TODO: remove this after container extension is supported.
                    break;
                }

                CompareEntitySets(containerElements, modelContainer, model.EntityTypes());
                CompareActionAndFunctionImports(containerElements, modelContainer, model);
            }
        }
        private static ODataPayloadElement CreatePayloadElement(IEdmModel model, ODataPayloadKind payloadKind, ReaderTestConfiguration testConfig)
        {
            IEdmEntitySet citySet = model.EntityContainer.FindEntitySet("Cities");
            IEdmEntityType cityType = model.EntityTypes().Single(e => e.Name == "CityType");
            IEdmProperty cityNameProperty = cityType.Properties().Single(e => e.Name == "Name");
            IEdmNavigationProperty policeStationNavProp = cityType.NavigationProperties().Single(e => e.Name == "PoliceStation");
            IEdmOperationImport primitiveCollectionResultOperation = model.EntityContainer.FindOperationImports("PrimitiveCollectionResultOperation").Single();
            IEdmOperationImport serviceOp1 = model.EntityContainer.FindOperationImports("ServiceOperation1").Single();

            bool isRequest = testConfig.IsRequest;
            bool isJsonLightRequest = isRequest && testConfig.Format == ODataFormat.Json;
            switch (payloadKind)
            {
                case ODataPayloadKind.Feed:
                    {
                        return PayloadBuilder.EntitySet().WithTypeAnnotation(cityType).ExpectedEntityType(cityType, citySet);
                    }
                case ODataPayloadKind.Entry:
                    {
                        return PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).WithTypeAnnotation(cityType).ExpectedEntityType(cityType, citySet);
                    }
                case ODataPayloadKind.Property:
                    return PayloadBuilder.PrimitiveProperty(isJsonLightRequest ? string.Empty : null, "SomeCityValue").ExpectedProperty(cityType, "Name");
                case ODataPayloadKind.EntityReferenceLink:
                    return PayloadBuilder.DeferredLink("http://odata.org/entityreferencelink").ExpectedNavigationProperty(citySet, cityType, "PoliceStation");

                case ODataPayloadKind.EntityReferenceLinks:
                    return PayloadBuilder.LinkCollection().Item(PayloadBuilder.DeferredLink("http://odata.org/entityreferencelink")).ExpectedNavigationProperty((EdmEntitySet)citySet, (EdmEntityType)cityType, "CityHall");

                case ODataPayloadKind.Value:
                    return PayloadBuilder.PrimitiveValue("PrimitiveValue");
                case ODataPayloadKind.BinaryValue:
                    return PayloadBuilder.PrimitiveValue(new byte[] { 0, 0, 1, 1 });
                case ODataPayloadKind.Collection:
                    return PayloadBuilder.PrimitiveCollection().CollectionName(null).ExpectedFunctionImport((EdmOperationImport)primitiveCollectionResultOperation);

                case ODataPayloadKind.ServiceDocument:
                    Debug.Assert(!isRequest, "Not supported in requests.");
                    return new ServiceDocumentInstance().Workspace(PayloadBuilder.Workspace());

                case ODataPayloadKind.MetadataDocument:
                    Debug.Assert(!isRequest, "Not supported in requests.");
                    throw new NotImplementedException();
                case ODataPayloadKind.Error:
                    Debug.Assert(!isRequest, "Not supported in requests.");
                    return PayloadBuilder.Error("ErrorCode");

                case ODataPayloadKind.Parameter:
                    // build parameter payload based on model definition
                    var parameterPayload = new ComplexInstance(null, false);
                    ODataPayloadElement a = PayloadBuilder.PrimitiveValue(123).WithTypeAnnotation(EdmCoreModel.Instance.GetInt32(false));
                    ODataPayloadElement b = PayloadBuilder.PrimitiveValue("stringvalue").WithTypeAnnotation(EdmCoreModel.Instance.GetString(false));
                    PrimitiveProperty parametera = new PrimitiveProperty("a", "Edm.Integer", ((PrimitiveValue)a).ClrValue);
                    PrimitiveProperty parameterb = new PrimitiveProperty("b", "Edm.String", ((PrimitiveValue)b).ClrValue);
                    parameterPayload.Add(parametera);
                    parameterPayload.Add(parameterb);
                    parameterPayload.ExpectedFunctionImport((EdmOperationImport)serviceOp1);
                    return parameterPayload;

                case ODataPayloadKind.Unsupported:  // fall through
                default:
                    throw new NotSupportedException();
            }
        }
        /// <summary>
        /// Adds or modifies a property's ExpectedTypeODataPayloadElementAnnotation, to aid generation of the context uri.
        /// </summary>
        /// <param name="property">The property to annotate.</param>
        /// <param name="propertyValueType">The type of the property's value.</param>
        /// <param name="matchesProperty">Delegate for matching the property instance to a MemberProperty.</param>
        /// <remarks>
        /// If the method cannot resolve the parent type of the property, one will be created and added to the test descriptor's
        /// PayloadModel. The descriptor's cached model will be reset.
        /// </remarks>
        private void AddExpectedTypeToProperty(PropertyInstance property, IEdmTypeReference propertyValueType, Func <IEdmProperty, bool> matchesProperty)
        {
            if (property.Annotations.OfType <JsonLightContextUriAnnotation>().Any())
            {
                return;
            }

            var typeAnnotation = property.Annotations.OfType <ExpectedTypeODataPayloadElementAnnotation>().SingleOrDefault();

            if (typeAnnotation == null || (typeAnnotation.MemberProperty == null && string.IsNullOrEmpty(typeAnnotation.OpenMemberPropertyName)))
            {
                ExpectedTypeODataPayloadElementAnnotation annotation = typeAnnotation ?? new ExpectedTypeODataPayloadElementAnnotation();

                IEdmModel model = this.testDescriptor.PayloadEdmModel;

                var entityType = model.EntityTypes().SingleOrDefault(t => t.Properties().Any(matchesProperty));
                if (entityType != null)
                {
                    annotation.EdmEntitySet  = FindEntitySet(model, entityType);
                    annotation.EdmOwningType = entityType;
                    annotation.EdmProperty   = entityType.Properties().FirstOrDefault(matchesProperty);
                }
                else
                {
                    var complexType = model.SchemaElements.OfType <IEdmComplexType>().SingleOrDefault(t => t.Properties().Any(matchesProperty));
                    if (complexType != null)
                    {
                        var complexProperty = complexType.Properties().Single(p => p.Name == property.Name);

                        annotation.EdmOwningType   = complexType;
                        annotation.EdmProperty     = complexProperty;
                        annotation.EdmExpectedType = complexProperty.Type;
                    }
                    else
                    {
                        // Add new entity type to the model and use that
                        IEdmTypeReference propertyType = annotation.EdmExpectedType ?? propertyValueType;

                        EdmEntityType newEntityType   = model.FindDeclaredType("TestModel.NewType") as EdmEntityType;
                        IEdmEntitySet newEntitySet    = null;
                        IEdmProperty  newProperty     = null;
                        string        newPorpertyName = property.Name ?? propertyType.FullName() ?? "EmptyName";

                        if (newEntityType == null)
                        {
                            newEntityType = new EdmEntityType("TestModel", "NewType");
                            newProperty   = newEntityType.AddStructuralProperty(newPorpertyName, propertyType);
                            ((EdmModel)model).AddElement(newEntityType);
                            var container = model.EntityContainersAcrossModels().Single() as EdmEntityContainer;
                            newEntitySet = container.AddEntitySet("NewTypes", newEntityType);
                        }
                        else
                        {
                            newProperty  = newEntityType.AddStructuralProperty(newPorpertyName, propertyType);
                            newEntitySet = FindEntitySet(model, newEntityType);
                        }

                        annotation.EdmEntitySet    = newEntitySet;
                        annotation.EdmOwningType   = newEntityType;
                        annotation.EdmProperty     = newProperty;
                        annotation.EdmExpectedType = propertyType;

                        this.testDescriptor.PayloadEdmModel = model;
                        this.testDescriptor.ResetCachedModel();
                    }
                }

                property.SetAnnotation(annotation);
            }
        }
        private static ODataPayloadElement CreatePayloadElement(IEdmModel model, ODataPayloadKind payloadKind, ReaderTestConfiguration testConfig)
        {
            IEdmEntitySet          citySet              = model.EntityContainer.FindEntitySet("Cities");
            IEdmEntityType         cityType             = model.EntityTypes().Single(e => e.Name == "CityType");
            IEdmProperty           cityNameProperty     = cityType.Properties().Single(e => e.Name == "Name");
            IEdmNavigationProperty policeStationNavProp = cityType.NavigationProperties().Single(e => e.Name == "PoliceStation");
            IEdmOperationImport    primitiveCollectionResultOperation = model.EntityContainer.FindOperationImports("PrimitiveCollectionResultOperation").Single();
            IEdmOperationImport    serviceOp1 = model.EntityContainer.FindOperationImports("ServiceOperation1").Single();

            bool isRequest          = testConfig.IsRequest;
            bool isJsonLightRequest = isRequest && testConfig.Format == ODataFormat.Json;

            switch (payloadKind)
            {
            case ODataPayloadKind.Feed:
            {
                return(PayloadBuilder.EntitySet().WithTypeAnnotation(cityType).ExpectedEntityType(cityType, citySet));
            }

            case ODataPayloadKind.Entry:
            {
                return(PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1).WithTypeAnnotation(cityType).ExpectedEntityType(cityType, citySet));
            }

            case ODataPayloadKind.Property:
                return(PayloadBuilder.PrimitiveProperty(isJsonLightRequest ? string.Empty : null, "SomeCityValue").ExpectedProperty(cityType, "Name"));

            case ODataPayloadKind.EntityReferenceLink:
                return(PayloadBuilder.DeferredLink("http://odata.org/entityreferencelink").ExpectedNavigationProperty(citySet, cityType, "PoliceStation"));

            case ODataPayloadKind.EntityReferenceLinks:
                return(PayloadBuilder.LinkCollection().Item(PayloadBuilder.DeferredLink("http://odata.org/entityreferencelink")).ExpectedNavigationProperty((EdmEntitySet)citySet, (EdmEntityType)cityType, "CityHall"));

            case ODataPayloadKind.Value:
                return(PayloadBuilder.PrimitiveValue("PrimitiveValue"));

            case ODataPayloadKind.BinaryValue:
                return(PayloadBuilder.PrimitiveValue(new byte[] { 0, 0, 1, 1 }));

            case ODataPayloadKind.Collection:
                return(PayloadBuilder.PrimitiveCollection().CollectionName(null).ExpectedFunctionImport((EdmOperationImport)primitiveCollectionResultOperation));

            case ODataPayloadKind.ServiceDocument:
                Debug.Assert(!isRequest, "Not supported in requests.");
                return(new ServiceDocumentInstance().Workspace(PayloadBuilder.Workspace()));

            case ODataPayloadKind.MetadataDocument:
                Debug.Assert(!isRequest, "Not supported in requests.");
                throw new NotImplementedException();

            case ODataPayloadKind.Error:
                Debug.Assert(!isRequest, "Not supported in requests.");
                return(PayloadBuilder.Error("ErrorCode"));

            case ODataPayloadKind.Parameter:
                // build parameter payload based on model definition
                var parameterPayload           = new ComplexInstance(null, false);
                ODataPayloadElement a          = PayloadBuilder.PrimitiveValue(123).WithTypeAnnotation(EdmCoreModel.Instance.GetInt32(false));
                ODataPayloadElement b          = PayloadBuilder.PrimitiveValue("stringvalue").WithTypeAnnotation(EdmCoreModel.Instance.GetString(false));
                PrimitiveProperty   parametera = new PrimitiveProperty("a", "Edm.Integer", ((PrimitiveValue)a).ClrValue);
                PrimitiveProperty   parameterb = new PrimitiveProperty("b", "Edm.String", ((PrimitiveValue)b).ClrValue);
                parameterPayload.Add(parametera);
                parameterPayload.Add(parameterb);
                parameterPayload.ExpectedFunctionImport((EdmOperationImport)serviceOp1);
                return(parameterPayload);

            case ODataPayloadKind.Unsupported:      // fall through
            default:
                throw new NotSupportedException();
            }
        }
示例#11
0
        private IEnumerable <PayloadWriterTestDescriptor <ODataPayloadElement> > CreateFeedValidatorDescriptors(IEdmModel model)
        {
            var cityType     = model.EntityTypes().Single(type => type.FullName() == "TestModel.CityType");
            var personType   = model.EntityTypes().Single(type => type.FullName() == "TestModel.Person");
            var employeeType = model.EntityTypes().Single(type => type.FullName() == "TestModel.Employee");

            var testCases = new[]
            {
                new
                {
                    Description = "Homogenous collection (no inheritance)",
                    Feed        = (ODataPayloadElement)PayloadBuilder.EntitySet().WithDefaultAtomIDAnnotation().WithTypeAnnotation(personType)
                                  .Append(PayloadBuilder.Entity("TestModel.Person")
                                          .PrimitiveProperty("Id", 1).WithTypeAnnotation(personType))
                                  .Append(PayloadBuilder.Entity("TestModel.Person")
                                          .PrimitiveProperty("Id", 2).WithTypeAnnotation(personType)),
                    ExpectedException = (ExpectedException)null,
                    Model             = model
                },
                new
                {
                    Description = "Homogenous collection (inheritance, base type first)",
                    Feed        = (ODataPayloadElement)PayloadBuilder.EntitySet().WithDefaultAtomIDAnnotation().WithTypeAnnotation(personType)
                                  .Append(PayloadBuilder.Entity("TestModel.Person")
                                          .PrimitiveProperty("Id", 1).WithTypeAnnotation(personType))
                                  .Append(PayloadBuilder.Entity("TestModel.Employee")
                                          .PrimitiveProperty("Id", 2).WithTypeAnnotation(employeeType)),
                    ExpectedException = (ExpectedException)null,
                    Model             = model
                },
                new
                {
                    Description = "Homogenous collection (inheritance, derived type first)",
                    Feed        = (ODataPayloadElement)PayloadBuilder.EntitySet().WithDefaultAtomIDAnnotation().WithTypeAnnotation(personType)
                                  .Append(PayloadBuilder.Entity("TestModel.Employee")
                                          .PrimitiveProperty("Id", 1).WithTypeAnnotation(employeeType))
                                  .Append(PayloadBuilder.Entity("TestModel.Person")
                                          .PrimitiveProperty("Id", 2).WithTypeAnnotation(personType)),
                    ExpectedException = (ExpectedException)null,
                    Model             = model
                },
                new
                {
                    Description = "Heterogeneous collection",
                    Feed        = (ODataPayloadElement)PayloadBuilder.EntitySet().WithDefaultAtomIDAnnotation().WithTypeAnnotation(personType)
                                  .Append(PayloadBuilder.Entity("TestModel.Person")
                                          .PrimitiveProperty("Id", 1).WithTypeAnnotation(personType))
                                  .Append(PayloadBuilder.Entity("TestModel.CityType")
                                          .PrimitiveProperty("Id", 2).WithTypeAnnotation(cityType)),
                    ExpectedException = ODataExpectedExceptions.ODataException("FeedWithoutExpectedTypeValidator_IncompatibleTypes", "TestModel.CityType", "TestModel.Person"),
                    Model             = model
                },
                new
                {
                    Description = "Heterogeneous collection (no model)",
                    Feed        = (ODataPayloadElement)PayloadBuilder.EntitySet().WithDefaultAtomIDAnnotation()
                                  .Append(PayloadBuilder.Entity("TestModel.Person")
                                          .PrimitiveProperty("Id", 1))
                                  .Append(PayloadBuilder.Entity("TestModel.CityType")
                                          .PrimitiveProperty("Id", 2)),
                    ExpectedException = (ExpectedException)null,
                    Model             = (IEdmModel)null
                },
            };

            // Create the tests for a top-level feed
            return(testCases.Select(testCase =>
                                    new PayloadWriterTestDescriptor <ODataPayloadElement>(this.Settings, testCase.Feed)
            {
                DebugDescription = testCase.Description,
                Model = testCase.Model,
                PayloadDescriptor = new PayloadTestDescriptor()
                {
                    DebugDescription = testCase.Description,
                    PayloadElement = testCase.Feed,
                    PayloadEdmModel = testCase.Model,
                    SkipTestConfiguration = tc => testCase.Model == null && tc.Format == ODataFormat.Json,
                },
                ExpectedResultCallback = (tc) =>
                {
                    return new PayloadWriterTestExpectedResults(this.ExpectedResultSettings)
                    {
                        ExpectedPayload = testCase.Feed,
                        ExpectedException2 = testCase.ExpectedException,
                    };
                }
            }));
        }
示例#12
0
        private IEnumerable<PayloadWriterTestDescriptor<ODataPayloadElement>> CreateFeedValidatorDescriptors(IEdmModel model)
        {
            var cityType = model.EntityTypes().Single(type => type.FullName() == "TestModel.CityType");
            var personType = model.EntityTypes().Single(type => type.FullName() == "TestModel.Person");
            var employeeType = model.EntityTypes().Single(type => type.FullName() == "TestModel.Employee");

            var testCases = new[]
                {
                    new
                    {
                        Description = "Homogenous collection (no inheritance)",
                        Feed = (ODataPayloadElement)PayloadBuilder.EntitySet().WithDefaultAtomIDAnnotation().WithTypeAnnotation(personType)
                            .Append(PayloadBuilder.Entity("TestModel.Person")
                                .PrimitiveProperty("Id", 1).WithTypeAnnotation(personType))
                            .Append(PayloadBuilder.Entity("TestModel.Person")
                                .PrimitiveProperty("Id", 2).WithTypeAnnotation(personType)),
                        ExpectedException = (ExpectedException)null,
                        Model = model
                    },
                    new
                    {
                        Description = "Homogenous collection (inheritance, base type first)",
                        Feed = (ODataPayloadElement)PayloadBuilder.EntitySet().WithDefaultAtomIDAnnotation().WithTypeAnnotation(personType)
                            .Append(PayloadBuilder.Entity("TestModel.Person")
                                .PrimitiveProperty("Id", 1).WithTypeAnnotation(personType))
                            .Append(PayloadBuilder.Entity("TestModel.Employee")
                                .PrimitiveProperty("Id", 2).WithTypeAnnotation(employeeType)),
                        ExpectedException = (ExpectedException)null,
                        Model = model
                    },
                    new
                    {
                        Description = "Homogenous collection (inheritance, derived type first)",
                        Feed = (ODataPayloadElement)PayloadBuilder.EntitySet().WithDefaultAtomIDAnnotation().WithTypeAnnotation(personType)
                            .Append(PayloadBuilder.Entity("TestModel.Employee")
                                .PrimitiveProperty("Id", 1).WithTypeAnnotation(employeeType))
                            .Append(PayloadBuilder.Entity("TestModel.Person")
                                .PrimitiveProperty("Id", 2).WithTypeAnnotation(personType)),
                        ExpectedException = (ExpectedException)null,
                        Model = model
                    },
                    new
                    {
                        Description = "Heterogeneous collection",
                        Feed = (ODataPayloadElement)PayloadBuilder.EntitySet().WithDefaultAtomIDAnnotation().WithTypeAnnotation(personType)
                            .Append(PayloadBuilder.Entity("TestModel.Person")
                                .PrimitiveProperty("Id", 1).WithTypeAnnotation(personType))
                            .Append(PayloadBuilder.Entity("TestModel.CityType")
                                .PrimitiveProperty("Id", 2).WithTypeAnnotation(cityType)),
                        ExpectedException = ODataExpectedExceptions.ODataException("FeedWithoutExpectedTypeValidator_IncompatibleTypes", "TestModel.CityType", "TestModel.Person"),
                        Model = model
                    },
                    new
                    {
                        Description = "Heterogeneous collection (no model)",
                        Feed = (ODataPayloadElement)PayloadBuilder.EntitySet().WithDefaultAtomIDAnnotation()
                            .Append(PayloadBuilder.Entity("TestModel.Person")
                                .PrimitiveProperty("Id", 1))
                            .Append(PayloadBuilder.Entity("TestModel.CityType")
                                .PrimitiveProperty("Id", 2)),
                        ExpectedException = (ExpectedException)null,
                        Model = (IEdmModel)null
                    },
                };

            // Create the tests for a top-level feed
            return testCases.Select(testCase =>
                new PayloadWriterTestDescriptor<ODataPayloadElement>(this.Settings, testCase.Feed)
                {
                    DebugDescription = testCase.Description,
                    Model = testCase.Model,
                    PayloadDescriptor = new PayloadTestDescriptor()
                    {
                        DebugDescription = testCase.Description,
                        PayloadElement = testCase.Feed,
                        PayloadEdmModel = testCase.Model,
                        SkipTestConfiguration = tc => testCase.Model == null && tc.Format == ODataFormat.Json,
                    },
                    ExpectedResultCallback = (tc) =>
                    {
                        return new PayloadWriterTestExpectedResults(this.ExpectedResultSettings)
                        {
                            ExpectedPayload = testCase.Feed,
                            ExpectedException2 = testCase.ExpectedException,
                        };
                    }
                });
        }