Пример #1
0
        public void ExpandedLinkWithMultiplicityTests()
        {
            ODataNavigationLink expandedEntryLink = ObjectModelUtils.CreateDefaultCollectionLink();

            expandedEntryLink.IsCollection = false;

            ODataNavigationLink expandedFeedLink = ObjectModelUtils.CreateDefaultCollectionLink();

            expandedFeedLink.IsCollection = true;

            ODataEntry defaultEntry = ObjectModelUtils.CreateDefaultEntry();
            ODataFeed  defaultFeed  = ObjectModelUtils.CreateDefaultFeed();
            ODataEntityReferenceLink defaultEntityReferenceLink = ObjectModelUtils.CreateDefaultEntityReferenceLink();

            ODataEntry officeEntry           = ObjectModelUtils.CreateDefaultEntry("TestModel.OfficeType");
            ODataEntry officeWithNumberEntry = ObjectModelUtils.CreateDefaultEntry("TestModel.OfficeWithNumberType");
            ODataEntry cityEntry             = ObjectModelUtils.CreateDefaultEntry("TestModel.CityType");

            // CityHall is a nav prop with multiplicity '*' of type 'TestModel.OfficeType'
            ODataNavigationLink cityHallLinkIsCollectionNull  = ObjectModelUtils.CreateDefaultCollectionLink("CityHall", /*isCollection*/ null);
            ODataNavigationLink cityHallLinkIsCollectionTrue  = ObjectModelUtils.CreateDefaultCollectionLink("CityHall", /*isCollection*/ true);
            ODataNavigationLink cityHallLinkIsCollectionFalse = ObjectModelUtils.CreateDefaultCollectionLink("CityHall", /*isCollection*/ false);

            // PoliceStation is a nav prop with multiplicity '1' of type 'TestModel.OfficeType'
            ODataNavigationLink policeStationLinkIsCollectionNull  = ObjectModelUtils.CreateDefaultCollectionLink("PoliceStation", /*isCollection*/ null);
            ODataNavigationLink policeStationLinkIsCollectionTrue  = ObjectModelUtils.CreateDefaultCollectionLink("PoliceStation", /*isCollection*/ true);
            ODataNavigationLink policeStationLinkIsCollectionFalse = ObjectModelUtils.CreateDefaultCollectionLink("PoliceStation", /*isCollection*/ false);

            ExpectedException expandedEntryLinkWithFeedContentError  = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedContent", "http://odata.org/link");
            ExpectedException expandedFeedLinkWithEntryContentError  = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryContent", "http://odata.org/link");
            ExpectedException expandedFeedLinkWithEntryMetadataError = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryMetadata", "http://odata.org/link");

            ExpectedException expandedEntryLinkWithFeedMetadataErrorResponse        = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedMetadata", "http://odata.org/link");
            ExpectedException expandedFeedLinkPayloadWithEntryMetadataErrorRequest  = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkWithFeedPayloadAndEntryMetadata", "http://odata.org/link");
            ExpectedException expandedFeedLinkPayloadWithEntryMetadataErrorResponse = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryMetadata", "http://odata.org/link");
            ExpectedException expandedEntryLinkPayloadWithFeedMetadataErrorResponse = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedMetadata", "http://odata.org/link");
            ExpectedException expandedEntryLinkPayloadWithFeedMetadataError         = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkWithEntryPayloadAndFeedMetadata", "http://odata.org/link");
            ExpectedException multipleItemsInExpandedLinkError   = ODataExpectedExceptions.ODataException("ODataWriterCore_MultipleItemsInNavigationLinkContent", "http://odata.org/link");
            ExpectedException entityReferenceLinkInResponseError = ODataExpectedExceptions.ODataException("ODataWriterCore_EntityReferenceLinkInResponse");

            IEdmModel model = Microsoft.Test.OData.Utils.Metadata.TestModels.BuildTestModel();

            var testCases = new ExpandedLinkMultiplicityTestCase[]
            {
                #region IsCollection flag does not match payload
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link with IsCollection is 'false' and feed payload
                    Items         = new ODataItem[] { defaultEntry, expandedEntryLink, defaultFeed },
                    ExpectedError = tc => expandedEntryLinkWithFeedContentError,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link with IsCollection is 'true' and entry payload
                    Items         = new ODataItem[] { defaultEntry, expandedFeedLink, defaultEntry },
                    ExpectedError = tc => expandedFeedLinkWithEntryContentError,
                },
                #endregion IsCollection flag does not match payload
                #region IsCollection == null; check compatibility of entity types of navigation property and entity in expanded link
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link of singleton type without IsCollection value and an entry of a non-matching entity type;
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, cityEntry },
                    ExpectedError = tc => tc.Format == ODataFormat.Atom || !tc.IsRequest
                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_EntryTypeInExpandedLinkNotCompatibleWithNavigationPropertyType", "TestModel.CityType", "TestModel.OfficeType")
                            : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "PoliceStation"),
                    Model = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link of singleton type without IsCollection value and an entry of a matching entity type; no error expected.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, officeEntry },
                    ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest ? null : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "PoliceStation"),
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link of singleton type without IsCollection and an entry of a derived entity type; no error expected.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, officeWithNumberEntry },
                    ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest ? null : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "PoliceStation"),
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link of collection type without IsCollection value and an entry of a non-matching entity type;
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, defaultFeed, cityEntry },
                    ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest
                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_EntryTypeInExpandedLinkNotCompatibleWithNavigationPropertyType", "TestModel.CityType", "TestModel.OfficeType")
                            : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "CityHall"),
                    Model = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link of collection type without IsCollection value and an entry of a matching entity type; no error expected.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, defaultFeed, officeEntry },
                    ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest
                            ? null
                            : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "CityHall"),
                    Model = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Expanded link of collection type without IsCollection and an entry of a derived entity type; no error expected.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, defaultFeed, officeWithNumberEntry },
                    ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest
                            ? null
                            : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "CityHall"),
                    Model = model,
                },
                #endregion IsCollection == null; check compatibility of entity types of navigation property and entity in expanded link
                #region Expanded link with entry content
                new ExpandedLinkMultiplicityTestCase
                {
                    // Entry content, IsCollection == false, singleton nav prop; should not fail.
                    Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionFalse, officeEntry },
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Entry content, IsCollection == true, singleton nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionTrue, officeEntry },
                    ExpectedError = tc => expandedFeedLinkWithEntryContentError,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Entry content, IsCollection == false, collection nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionFalse, officeEntry },
                    ExpectedError = tc => tc.IsRequest ? expandedEntryLinkPayloadWithFeedMetadataError : expandedEntryLinkPayloadWithFeedMetadataErrorResponse,
                    Model         = model
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Entry content, IsCollection == true, collection nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionTrue, officeEntry },
                    ExpectedError = tc => expandedFeedLinkWithEntryContentError,
                    Model         = model
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Entry content, IsCollection == null, singleton nav prop; should not fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, officeEntry },
                    ExpectedError = tc => tc.IsRequest || tc.Format == ODataFormat.Atom
                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "PoliceStation")
                            : null,
                    Model = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Entry content, IsCollection == null, collection nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, officeEntry },
                    ExpectedError = tc => expandedEntryLinkPayloadWithFeedMetadataError,
                    Model         = model,
                },
                #endregion Expanded collection link with entry content
                #region Expanded link with feed content
                new ExpandedLinkMultiplicityTestCase
                {
                    // Feed content, IsCollection == false, singleton nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionFalse, defaultFeed, officeEntry },
                    ExpectedError = tc => expandedEntryLinkWithFeedContentError,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Feed content, IsCollection == true, singleton nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionTrue, defaultFeed, officeEntry },
                    ExpectedError = tc => tc.IsRequest ? expandedFeedLinkPayloadWithEntryMetadataErrorRequest : expandedFeedLinkPayloadWithEntryMetadataErrorResponse,
                    Model         = model
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Feed content, IsCollection == false, collection nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionFalse, defaultFeed, officeEntry },
                    ExpectedError = tc => tc.IsRequest ? expandedEntryLinkWithFeedContentError : expandedEntryLinkWithFeedMetadataErrorResponse,
                    Model         = model
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Feed content, IsCollection == true, collection nav prop; should not fail.
                    Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionTrue, defaultFeed, officeEntry },
                    Model = model
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Feed content, IsCollection == null, singleton nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, defaultFeed, officeEntry },
                    ExpectedError = tc => expandedFeedLinkPayloadWithEntryMetadataErrorRequest,
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Feed content, IsCollection == null, collection nav prop; should not fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, defaultFeed, officeEntry },
                    ExpectedError = tc => tc.IsRequest || tc.Format == ODataFormat.Atom
                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "CityHall")
                            : null,
                    Model = model,
                },
                #endregion Expanded collection link with entry content
                #region Expanded link with entity reference link content
                new ExpandedLinkMultiplicityTestCase
                {
                    // Single ERL (entity reference link) content, IsCollection == false, singleton nav prop; should not fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionFalse, defaultEntityReferenceLink },
                    ExpectedError = tc => tc.IsRequest ? null : entityReferenceLinkInResponseError
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Multiple ERL (entity reference link) content, IsCollection == false, singleton nav prop; should not fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionFalse, defaultEntityReferenceLink, defaultEntityReferenceLink },
                    ExpectedError = tc => tc.IsRequest ? multipleItemsInExpandedLinkError : entityReferenceLinkInResponseError,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Single ERL content, IsCollection == true, singleton nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionTrue, defaultEntityReferenceLink },
                    ExpectedError = tc => expandedFeedLinkWithEntryMetadataError,
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Multiple ERL content, IsCollection == true, singleton nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, policeStationLinkIsCollectionTrue, defaultEntityReferenceLink, defaultEntityReferenceLink },
                    ExpectedError = tc => expandedFeedLinkWithEntryMetadataError,
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Single ERL content, IsCollection == false, collection nav prop; should not fail (metadata mismatch explicitly allowed).
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionFalse, defaultEntityReferenceLink },
                    ExpectedError = tc => tc.IsRequest ? null : expandedEntryLinkWithFeedMetadataErrorResponse,
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Multiple ERL content, IsCollection == false, collection nav prop; should fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionFalse, defaultEntityReferenceLink, defaultEntityReferenceLink },
                    ExpectedError = tc => tc.IsRequest ? multipleItemsInExpandedLinkError : expandedEntryLinkWithFeedMetadataErrorResponse,
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Single ERL content, IsCollection == true, collection nav prop; should not fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionTrue, defaultEntityReferenceLink },
                    ExpectedError = tc => tc.IsRequest ? null : entityReferenceLinkInResponseError,
                    Model         = model,
                },
                new ExpandedLinkMultiplicityTestCase
                {
                    // Multiple ERL content, IsCollection == true, collection nav prop; should not fail.
                    Items         = new ODataItem[] { cityEntry, cityHallLinkIsCollectionTrue, defaultEntityReferenceLink, defaultEntityReferenceLink },
                    ExpectedError = tc => tc.IsRequest ? null : entityReferenceLinkInResponseError,
                    Model         = model,
                },

                //// NOTE: Not testing the cases where IsCollection == null here since ERL payloads are only allowed in
                ////       requests where IsCollection is required (in ATOM and JSON)
                #endregion Expanded link with entity reference link content
            };

            // TODO: Fix places where we've lost JsonVerbose coverage to add JsonLight
            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurations.Where(tc => tc.Format == ODataFormat.Atom),
                (testCase, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                using (var memoryStream = new TestStream())
                    using (var messageWriter = TestWriterUtils.CreateMessageWriter(memoryStream, testConfiguration, this.Assert, null, testCase.Model))
                    {
                        ODataWriter writer = messageWriter.CreateODataWriter(isFeed: false);
                        TestExceptionUtils.ExpectedException(
                            this.Assert,
                            () => TestWriterUtils.WritePayload(messageWriter, writer, true, testCase.Items),
                            testCase.ExpectedError == null ? null : testCase.ExpectedError(testConfiguration),
                            this.ExceptionVerifier);
                    }
            });
        }
Пример #2
0
        public void ExpandedLinkWithMultiplicityTests()
        {
            ODataNavigationLink expandedEntryLink = ObjectModelUtils.CreateDefaultCollectionLink();
            expandedEntryLink.IsCollection = false;

            ODataNavigationLink expandedFeedLink = ObjectModelUtils.CreateDefaultCollectionLink();
            expandedFeedLink.IsCollection = true;

            ODataEntry defaultEntry = ObjectModelUtils.CreateDefaultEntry();
            ODataFeed defaultFeed = ObjectModelUtils.CreateDefaultFeed();
            ODataEntityReferenceLink defaultEntityReferenceLink = ObjectModelUtils.CreateDefaultEntityReferenceLink();

            ODataEntry officeEntry = ObjectModelUtils.CreateDefaultEntry("TestModel.OfficeType");
            ODataEntry officeWithNumberEntry = ObjectModelUtils.CreateDefaultEntry("TestModel.OfficeWithNumberType");
            ODataEntry cityEntry = ObjectModelUtils.CreateDefaultEntry("TestModel.CityType");

            // CityHall is a nav prop with multiplicity '*' of type 'TestModel.OfficeType'
            ODataNavigationLink cityHallLinkIsCollectionNull = ObjectModelUtils.CreateDefaultCollectionLink("CityHall", /*isCollection*/ null);
            ODataNavigationLink cityHallLinkIsCollectionTrue = ObjectModelUtils.CreateDefaultCollectionLink("CityHall", /*isCollection*/ true);
            ODataNavigationLink cityHallLinkIsCollectionFalse = ObjectModelUtils.CreateDefaultCollectionLink("CityHall", /*isCollection*/ false);

            // PoliceStation is a nav prop with multiplicity '1' of type 'TestModel.OfficeType'
            ODataNavigationLink policeStationLinkIsCollectionNull = ObjectModelUtils.CreateDefaultCollectionLink("PoliceStation", /*isCollection*/ null);
            ODataNavigationLink policeStationLinkIsCollectionTrue = ObjectModelUtils.CreateDefaultCollectionLink("PoliceStation", /*isCollection*/ true);
            ODataNavigationLink policeStationLinkIsCollectionFalse = ObjectModelUtils.CreateDefaultCollectionLink("PoliceStation", /*isCollection*/ false);

            ExpectedException expandedEntryLinkWithFeedContentError = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedContent", "http://odata.org/link");
            ExpectedException expandedFeedLinkWithEntryContentError = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryContent", "http://odata.org/link");
            ExpectedException expandedFeedLinkWithEntryMetadataError = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryMetadata", "http://odata.org/link");

            ExpectedException expandedEntryLinkWithFeedMetadataErrorResponse = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedMetadata", "http://odata.org/link");
            ExpectedException expandedFeedLinkPayloadWithEntryMetadataErrorRequest = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkWithFeedPayloadAndEntryMetadata", "http://odata.org/link");
            ExpectedException expandedFeedLinkPayloadWithEntryMetadataErrorResponse = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionTrueWithEntryMetadata", "http://odata.org/link");
            ExpectedException expandedEntryLinkPayloadWithFeedMetadataErrorResponse = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkIsCollectionFalseWithFeedMetadata", "http://odata.org/link");
            ExpectedException expandedEntryLinkPayloadWithFeedMetadataError = ODataExpectedExceptions.ODataException("WriterValidationUtils_ExpandedLinkWithEntryPayloadAndFeedMetadata", "http://odata.org/link");
            ExpectedException multipleItemsInExpandedLinkError = ODataExpectedExceptions.ODataException("ODataWriterCore_MultipleItemsInNavigationLinkContent", "http://odata.org/link");
            ExpectedException entityReferenceLinkInResponseError = ODataExpectedExceptions.ODataException("ODataWriterCore_EntityReferenceLinkInResponse");

            IEdmModel model = Microsoft.Test.OData.Utils.Metadata.TestModels.BuildTestModel();

            var testCases = new ExpandedLinkMultiplicityTestCase[]
                {
                    #region IsCollection flag does not match payload
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Expanded link with IsCollection is 'false' and feed payload
                        Items = new ODataItem[] { defaultEntry, expandedEntryLink, defaultFeed },
                        ExpectedError = tc => expandedEntryLinkWithFeedContentError,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Expanded link with IsCollection is 'true' and entry payload
                        Items = new ODataItem[] { defaultEntry, expandedFeedLink, defaultEntry },
                        ExpectedError = tc => expandedFeedLinkWithEntryContentError,
                    },
                    #endregion IsCollection flag does not match payload
                    #region IsCollection == null; check compatibility of entity types of navigation property and entity in expanded link
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Expanded link of singleton type without IsCollection value and an entry of a non-matching entity type;
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, cityEntry },
                        ExpectedError = tc => tc.Format == ODataFormat.Atom || !tc.IsRequest
                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_EntryTypeInExpandedLinkNotCompatibleWithNavigationPropertyType", "TestModel.CityType", "TestModel.OfficeType")
                            : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "PoliceStation"),
                        Model = model,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Expanded link of singleton type without IsCollection value and an entry of a matching entity type; no error expected.
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, officeEntry },
                        ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest ? null : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "PoliceStation"),
                        Model = model,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Expanded link of singleton type without IsCollection and an entry of a derived entity type; no error expected.
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, officeWithNumberEntry },
                        ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest ? null : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "PoliceStation"),
                        Model = model,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Expanded link of collection type without IsCollection value and an entry of a non-matching entity type;
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, defaultFeed, cityEntry },
                        ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest 
                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_EntryTypeInExpandedLinkNotCompatibleWithNavigationPropertyType", "TestModel.CityType", "TestModel.OfficeType")
                            : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "CityHall"),
                        Model = model,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Expanded link of collection type without IsCollection value and an entry of a matching entity type; no error expected.
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, defaultFeed, officeEntry },
                        ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest 
                            ? null 
                            : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "CityHall"),
                        Model = model,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Expanded link of collection type without IsCollection and an entry of a derived entity type; no error expected.
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, defaultFeed, officeWithNumberEntry },
                        ExpectedError = tc => tc.Format == ODataFormat.Json && !tc.IsRequest 
                            ? null 
                            : ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "CityHall"),
                        Model = model,
                    },
                    #endregion IsCollection == null; check compatibility of entity types of navigation property and entity in expanded link
                    #region Expanded link with entry content
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Entry content, IsCollection == false, singleton nav prop; should not fail.
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionFalse, officeEntry },
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Entry content, IsCollection == true, singleton nav prop; should fail.
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionTrue, officeEntry },
                        ExpectedError = tc => expandedFeedLinkWithEntryContentError,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Entry content, IsCollection == false, collection nav prop; should fail.
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionFalse, officeEntry },
                        ExpectedError = tc => tc.IsRequest ? expandedEntryLinkPayloadWithFeedMetadataError : expandedEntryLinkPayloadWithFeedMetadataErrorResponse,
                        Model = model
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Entry content, IsCollection == true, collection nav prop; should fail.
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionTrue, officeEntry },
                        ExpectedError = tc => expandedFeedLinkWithEntryContentError,
                        Model = model
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Entry content, IsCollection == null, singleton nav prop; should not fail.
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, officeEntry },
                        ExpectedError = tc => tc.IsRequest || tc.Format == ODataFormat.Atom
                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "PoliceStation")
                            : null,
                        Model = model,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Entry content, IsCollection == null, collection nav prop; should fail.
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, officeEntry },
                        ExpectedError = tc => expandedEntryLinkPayloadWithFeedMetadataError,
                        Model = model,
                    },
                    #endregion Expanded collection link with entry content
                    #region Expanded link with feed content
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Feed content, IsCollection == false, singleton nav prop; should fail.
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionFalse, defaultFeed, officeEntry },
                        ExpectedError = tc => expandedEntryLinkWithFeedContentError,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Feed content, IsCollection == true, singleton nav prop; should fail.
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionTrue, defaultFeed, officeEntry },
                        ExpectedError = tc => tc.IsRequest ? expandedFeedLinkPayloadWithEntryMetadataErrorRequest : expandedFeedLinkPayloadWithEntryMetadataErrorResponse,
                        Model = model
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Feed content, IsCollection == false, collection nav prop; should fail.
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionFalse, defaultFeed, officeEntry },
                        ExpectedError = tc => tc.IsRequest ? expandedEntryLinkWithFeedContentError : expandedEntryLinkWithFeedMetadataErrorResponse,
                        Model = model
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Feed content, IsCollection == true, collection nav prop; should not fail.
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionTrue, defaultFeed, officeEntry },
                        Model = model
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Feed content, IsCollection == null, singleton nav prop; should fail.
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionNull, defaultFeed, officeEntry },
                        ExpectedError = tc => expandedFeedLinkPayloadWithEntryMetadataErrorRequest,
                        Model = model,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Feed content, IsCollection == null, collection nav prop; should not fail.
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionNull, defaultFeed, officeEntry },
                        ExpectedError = tc => tc.IsRequest || tc.Format == ODataFormat.Atom
                            ? ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyIsCollection", "CityHall")
                            : null,
                        Model = model,
                    },
                    #endregion Expanded collection link with entry content
                    #region Expanded link with entity reference link content
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Single ERL (entity reference link) content, IsCollection == false, singleton nav prop; should not fail.
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionFalse, defaultEntityReferenceLink },
                        ExpectedError = tc => tc.IsRequest ? null : entityReferenceLinkInResponseError
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Multiple ERL (entity reference link) content, IsCollection == false, singleton nav prop; should not fail.
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionFalse, defaultEntityReferenceLink, defaultEntityReferenceLink },
                        ExpectedError = tc => tc.IsRequest ? multipleItemsInExpandedLinkError : entityReferenceLinkInResponseError,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Single ERL content, IsCollection == true, singleton nav prop; should fail.
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionTrue, defaultEntityReferenceLink },
                        ExpectedError = tc => expandedFeedLinkWithEntryMetadataError,
                        Model = model,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Multiple ERL content, IsCollection == true, singleton nav prop; should fail.
                        Items = new ODataItem[] { cityEntry, policeStationLinkIsCollectionTrue, defaultEntityReferenceLink, defaultEntityReferenceLink },
                        ExpectedError = tc => expandedFeedLinkWithEntryMetadataError,
                        Model = model,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Single ERL content, IsCollection == false, collection nav prop; should not fail (metadata mismatch explicitly allowed).
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionFalse, defaultEntityReferenceLink },
                        ExpectedError = tc => tc.IsRequest ? null : expandedEntryLinkWithFeedMetadataErrorResponse,
                        Model = model,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Multiple ERL content, IsCollection == false, collection nav prop; should fail.
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionFalse, defaultEntityReferenceLink, defaultEntityReferenceLink },
                        ExpectedError = tc => tc.IsRequest ? multipleItemsInExpandedLinkError : expandedEntryLinkWithFeedMetadataErrorResponse,
                        Model = model,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Single ERL content, IsCollection == true, collection nav prop; should not fail.
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionTrue, defaultEntityReferenceLink },
                        ExpectedError = tc => tc.IsRequest ? null : entityReferenceLinkInResponseError,
                        Model = model,
                    },
                    new ExpandedLinkMultiplicityTestCase
                    {
                        // Multiple ERL content, IsCollection == true, collection nav prop; should not fail.
                        Items = new ODataItem[] { cityEntry, cityHallLinkIsCollectionTrue, defaultEntityReferenceLink, defaultEntityReferenceLink },
                        ExpectedError = tc => tc.IsRequest ? null : entityReferenceLinkInResponseError,
                        Model = model,
                    },

                    //// NOTE: Not testing the cases where IsCollection == null here since ERL payloads are only allowed in
                    ////       requests where IsCollection is required (in ATOM and JSON)
                    #endregion Expanded link with entity reference link content
                };

            // TODO: Fix places where we've lost JsonVerbose coverage to add JsonLight
            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurations.Where(tc => tc.Format == ODataFormat.Atom),
                (testCase, testConfiguration) =>
                {
                    testConfiguration = testConfiguration.Clone();
                    testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                    using (var memoryStream = new TestStream())
                    using (var messageWriter = TestWriterUtils.CreateMessageWriter(memoryStream, testConfiguration, this.Assert, null, testCase.Model))
                    {
                        ODataWriter writer = messageWriter.CreateODataWriter(isFeed: false);
                        TestExceptionUtils.ExpectedException(
                            this.Assert,
                            () => TestWriterUtils.WritePayload(messageWriter, writer, true, testCase.Items),
                            testCase.ExpectedError == null ? null : testCase.ExpectedError(testConfiguration),
                            this.ExceptionVerifier);
                    }
                });
        }