public void EntityReferenceLinkValidationTest() { var testCases = new[] { new { InvalidateEntityReferenceLink = new Action <ODataEntityReferenceLink>(entityReferenceLink => entityReferenceLink.Url = null), ExpectedException = ODataExpectedExceptions.ODataException("WriterValidationUtils_EntityReferenceLinkUrlMustNotBeNull"), }, }; var testDescriptors = testCases.SelectMany(testCase => { ODataEntityReferenceLink entityReferenceLink = ObjectModelUtils.CreateDefaultEntityReferenceLink(); testCase.InvalidateEntityReferenceLink(entityReferenceLink); ODataEntityReferenceLinks entityReferenceLinks = ObjectModelUtils.CreateDefaultEntityReferenceLinks(); testCase.InvalidateEntityReferenceLink(entityReferenceLinks.Links.First()); return(new PayloadWriterTestDescriptor[] { // Top level entity reference link new PayloadWriterTestDescriptor <ODataEntityReferenceLink>( this.Settings, entityReferenceLink, testConfiguration => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings) { ExpectedException2 = testCase.ExpectedException }), // Entity reference link in entity reference links new PayloadWriterTestDescriptor <ODataEntityReferenceLinks>( this.Settings, entityReferenceLinks, testConfiguration => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings) { // Top-level EntityReferenceLinks payload write requests are not allowed. ExpectedException2 = testConfiguration.IsRequest ? ODataExpectedExceptions.ODataException("ODataMessageWriter_EntityReferenceLinksInRequestNotAllowed") : testCase.ExpectedException }), new PayloadWriterTestDescriptor <ODataItem>( this.Settings, new ODataItem[] { ObjectModelUtils.CreateDefaultEntry(), ObjectModelUtils.CreateDefaultSingletonLink(), entityReferenceLink, null, null }, testConfiguration => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings) { ExpectedException2 = testConfiguration.IsRequest ? testCase.ExpectedException : ODataExpectedExceptions.ODataException("ODataWriterCore_EntityReferenceLinkInResponse") }), }); }); this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.WriterTestConfigurationProvider.AtomFormatConfigurations, (testDescriptor, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); PayloadWriterTestDescriptor <ODataEntityReferenceLink> entityReferenceLinkTestDescriptor = testDescriptor as PayloadWriterTestDescriptor <ODataEntityReferenceLink>; if (entityReferenceLinkTestDescriptor != null) { TestWriterUtils.WriteAndVerifyTopLevelContent( entityReferenceLinkTestDescriptor, testConfiguration, (messageWriter) => messageWriter.WriteEntityReferenceLink(entityReferenceLinkTestDescriptor.PayloadItems.Single()), this.Assert, baselineLogger: this.Logger); return; } PayloadWriterTestDescriptor <ODataEntityReferenceLinks> entityReferenceLinksTestDescriptor = testDescriptor as PayloadWriterTestDescriptor <ODataEntityReferenceLinks>; if (entityReferenceLinksTestDescriptor != null) { TestWriterUtils.WriteAndVerifyTopLevelContent( entityReferenceLinksTestDescriptor, testConfiguration, (messageWriter) => messageWriter.WriteEntityReferenceLinks(entityReferenceLinksTestDescriptor.PayloadItems.Single()), this.Assert, baselineLogger: this.Logger); return; } TestWriterUtils.WriteAndVerifyODataPayload((PayloadWriterTestDescriptor <ODataItem>)testDescriptor, testConfiguration, this.Assert, this.Logger); }); }
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); } }); }