public void ServiceDocumentReaderWithAtomMetadataTest() { IEnumerable<PayloadReaderTestDescriptor> testDescriptors = new PayloadReaderTestDescriptor[] { #region tests related to atom:title // Verify that a title inside a collection is read into the Name property and (if ATOM metadata reading is enabled) the Title property of the metadata annotation. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace().ResourceCollection("Products", baseUri + "Products")) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <collection href='" + baseUri + @"Products'> <atom:title>Products</atom:title> </collection> </workspace> </service>"), }, // Title inside a workspace should be read when ATOM metadata reading is on, but ignored otherwise. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace() .AtomTitle("Default", TestAtomConstants.AtomTextConstructTextKind) .ResourceCollection("Products", baseUri + "Products")) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <atom:title>Default</atom:title> <collection href='" + baseUri + @"Products'> <atom:title>Products</atom:title> </collection> </workspace> </service>"), }, // Multiple atom:title elements inside the collection element should throw when metadata reading is both on and off. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace().ResourceCollection(null, baseUri + "Products")) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <collection href='" + baseUri + @"Products'> <atom:title>Products</atom:title> <atom:title>Products</atom:title> </collection> </workspace> </service>"), ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomServiceDocumentMetadataDeserializer_MultipleTitleElementsFound", "collection"), }, #endregion tests related to atom:title #region app:collection element // Collection element with no children. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace().ResourceCollection(null, baseUri + "Products")) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <collection href='" + baseUri + @"Products'> </collection> </workspace> </service>"), }, // Empty collection element. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace().ResourceCollection(null, baseUri + "Products")) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <collection href='" + baseUri + @"Products' /> </workspace> </service>"), }, // Multiple collections new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace() .AtomTitle("Default", TestAtomConstants.AtomTextConstructTextKind) .ResourceCollection( PayloadBuilder.ResourceCollection("Collection1", baseUri + "Collection1") .AppAccept("image/png") .AppOutOfLineCategories("http://somecategories.com")) .ResourceCollection( PayloadBuilder.ResourceCollection("Collection2", baseUri + "Collection2") .AppAccept("image/gif") .AppOutOfLineCategories("http://othercategories.com"))) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <atom:title>Default</atom:title> <collection href='" + baseUri + @"Collection1'> <atom:title>Collection1</atom:title> <accept>image/png</accept> <categories href='http://somecategories.com'/> </collection> <collection href='" + baseUri + @"Collection2'> <atom:title>Collection2</atom:title> <accept>image/gif</accept> <categories href='http://othercategories.com'/> </collection> </workspace> </service>"), }, #endregion app:collection element #region app:accept and app:categories element // app:accept and app:categories element inside the collection element. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace() .ResourceCollection( PayloadBuilder.ResourceCollection("Products", baseUri + "Products") .AppAccept("application/atom+xml;type=entry") .AppInlineCategories("yes", null, AtomMetadataBuilder.AtomCategory("SomeTerm", "http://someschema.org/", null)))) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <collection href='" + baseUri + @"Products'> <atom:title>Products</atom:title> <accept>application/atom+xml;type=entry</accept> <categories fixed='yes'> <atom:category scheme='http://someschema.org/' term='SomeTerm'/> </categories> </collection> </workspace> </service>"), }, // Out of line app:categories element. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace() .AtomTitle("Default", TestAtomConstants.AtomTextConstructTextKind) .ResourceCollection( PayloadBuilder.ResourceCollection("Products", baseUri + "Products") .AppOutOfLineCategories("http://example.com/categories"))) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <atom:title>Default</atom:title> <collection href='" + baseUri + @"Products'> <atom:title>Products</atom:title> <categories href='http://example.com/categories' /> </collection> </workspace> </service>"), }, // Attributes of the "categories" element in a non-empty namespace should be ignored. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace() .ResourceCollection( PayloadBuilder.ResourceCollection("Products", baseUri + "Products") .AppInlineCategories(null, null, AtomMetadataBuilder.AtomCategory("SomeTerm", "http://someschema.org", "SomeLabel")))) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom' xmlns:foo='http://foo.org'> <workspace> <collection href='" + baseUri + @"Products'> <atom:title>Products</atom:title> <categories foo:fixed='yes' atom:scheme='http://baseschema.org'> <atom:category term='SomeTerm' scheme='http://someschema.org' label='SomeLabel'/> </categories> </collection> </workspace> </service>"), }, #endregion app:accept and app:categories element #region atom:category element // Attributes of the "category" element in a non-empty namespace should be ignored. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace() .ResourceCollection( PayloadBuilder.ResourceCollection("Products", baseUri + "Products") .AppInlineCategories("yes", "http://baseschema.org", AtomMetadataBuilder.AtomCategory(null, null, null)))) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom' xmlns:foo='http://foo.org'> <workspace> <collection href='" + baseUri + @"Products'> <atom:title>Products</atom:title> <categories fixed='yes' scheme='http://baseschema.org'> <atom:category foo:term='SomeTerm' app:scheme='http://someschema.org' atom:label='SomeLabel'/> </categories> </collection> </workspace> </service>"), }, // Multiple atom:category elements. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace() .AtomTitle("Default", TestAtomConstants.AtomTextConstructTextKind) .ResourceCollection( PayloadBuilder.ResourceCollection("Products", baseUri + "Products") .AppInlineCategories("no", "http://baseschema.org", AtomMetadataBuilder.AtomCategory("FirstCategory", null, null), AtomMetadataBuilder.AtomCategory("SecondCategory", null, "SomeLabel")))) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <atom:title>Default</atom:title> <collection href='" + baseUri + @"Products'> <atom:title>Products</atom:title> <categories fixed='no' scheme='http://baseschema.org'> <atom:category term='FirstCategory'/> <atom:category term='SecondCategory' label='SomeLabel'/> </categories> </collection> </workspace> </service>"), }, #endregion atom:category element #region extra nodes // comments at different places in the service document. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace().ResourceCollection(null, baseUri + "Products")) .XmlRepresentation(@"<service xmlns:cn='http://customnamespace' xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <!-- some comments --> <workspace> <!-- more comments --> <collection href='" + baseUri + @"Products'> <!-- more comments --> </collection> <!-- more comments --> </workspace> <!-- more comments --> </service>"), }, // elements having additional irrelevant attributes new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace().ResourceCollection(null, baseUri + "Products")) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom' foo2='bar2'> <workspace foo='bar'> <collection href='" + baseUri + @"Products' foo1='bar1'> </collection> </workspace> </service>"), }, // irrelevant child elements inside a workspace or collection element. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace() .ResourceCollection(null, baseUri + "Products") .ResourceCollection(null, baseUri + "Orders")) .XmlRepresentation(@"<service xmlns:cn='http://customnamespace' xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <cn:foo foo1='bar1' /> <collection href='" + baseUri + @"Products'> <cn:foo href='" + baseUri + @"Products'> </cn:foo> </collection> <cn:foo2 foo3='bar3' /> <cn:foo2 foo3='bar3' /> <collection href='" + baseUri + @"Orders'> <atom:foo href='" + baseUri + @"Orders'> </atom:foo> </collection> </workspace> </service>"), }, // irrelevant element before and after the workspace new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace().ResourceCollection(null, baseUri + "Products")) .XmlRepresentation(@"<service xmlns:cn='http://customnamespace' xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <cn:some_element>some text</cn:some_element> <workspace> <collection href='" + baseUri + @"Products'> </collection> </workspace> <cn:some_element>some text</cn:some_element> </service>"), }, #endregion extra elements }; this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.ReaderTestConfigurationProvider.AtomFormatConfigurations.Where(tc => !tc.IsRequest), new bool[] { true, false }, (testDescriptor, testConfiguration, enableAtomMetadataReading) => { testConfiguration = new ReaderTestConfiguration(testConfiguration); testConfiguration.MessageReaderSettings.EnableAtomMetadataReading = enableAtomMetadataReading; testDescriptor = new PayloadReaderTestDescriptor(testDescriptor); if (!enableAtomMetadataReading) { // If we are running with ATOM metadata reading turned off, strip off all ATOM metadata annotations and // properties from the expected result. testDescriptor.ExpectedResultNormalizers.Add(tc => RemoveAtomMetadataFromPayloadElementVisitor.Visit); } // Normalize the payload elements so that if an ATOM metadata property is set, the corresponding ATOM metadata // annotation is created, and vice versa. testDescriptor.ExpectedResultNormalizers.Add(tc => ODataPayloadElementAtomMetadataNormalizer.GenerateNormalizer(testConfiguration)); testDescriptor.RunTest(testConfiguration); }); }
private void RunMessageSizeLimitTests( IEnumerable<ReaderTestConfiguration> testConfigurations, EdmModel model, ODataPayloadElement payload, MessageSizeLimitTestCase[] testCases, Func<ReaderTestConfiguration, bool> skipTestConfigurationFunc = null) { var transformScope = this.Settings.PayloadTransformFactory.EmptyScope(); using (transformScope.Apply()) { this.CombinatorialEngineProvider.RunCombinations( testCases, testConfigurations, (testCase, testConfiguration) => { int size = -1; if (testConfiguration.Format == ODataFormat.Atom && testCase.AtomSizes != null) { size = testConfiguration.IsRequest ? testCase.AtomSizes.RequestSize : testCase.AtomSizes.ResponseSize; } else if (testConfiguration.Format == ODataFormat.Json && testCase.JsonLightSizes != null) { size = testConfiguration.IsRequest ? testCase.JsonLightSizes.RequestSize : testCase.JsonLightSizes.ResponseSize; } else if (testCase.RawSizes != null) { size = testConfiguration.IsRequest ? testCase.RawSizes.RequestSize : testCase.RawSizes.ResponseSize; } int maxSize = testCase.MaxMessageSize >= 0 ? testCase.MaxMessageSize : 1024 * 1024; ExpectedException expectedException = size < 0 ? null : ODataExpectedExceptions.ODataException("MessageStreamWrappingStream_ByteLimitExceeded", size.ToString(), maxSize.ToString()); var testDescriptor = new PayloadReaderTestDescriptor(this.Settings) { PayloadEdmModel = model, PayloadElement = payload.DeepCopy(), ExpectedException = expectedException, SkipTestConfiguration = skipTestConfigurationFunc, ApplyPayloadTransformations = false, }; testDescriptor.ExpectedResultNormalizers.Add( tc => (Func<ODataPayloadElement, ODataPayloadElement>)null); if (testCase.MaxMessageSize > 0) { testConfiguration = new ReaderTestConfiguration(testConfiguration); testConfiguration.MessageReaderSettings.MessageQuotas.MaxReceivedMessageSize = testCase.MaxMessageSize; } testDescriptor.RunTest(testConfiguration); }); } }
public void InvalidXmlBaseUriHandlingTest() { string absoluteUri = "http://odata.org/relative"; var testCases = new[] { new { BaseUriString = "relativeUri", SettingsBaseUri = (string)null, ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomDeserializer_RelativeUriUsedWithoutBaseUriSpecified", "relativeUri") }, new { BaseUriString = string.Empty, SettingsBaseUri = (string)null, ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomDeserializer_RelativeUriUsedWithoutBaseUriSpecified", string.Empty) }, new { BaseUriString = "http://invalid:uri:value", SettingsBaseUri = (string)null, ExpectedException = new ExpectedException(typeof(UriFormatException)) } }; this.CombinatorialEngineProvider.RunCombinations( testCases, new TestODataBehaviorKind[] { TestODataBehaviorKind.Default, TestODataBehaviorKind.WcfDataServicesServer }, this.ReaderTestConfigurationProvider.AtomFormatConfigurations, (testCase, behaviorKind, testConfiguration) => { var td = new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.Entity().AsMediaLinkEntry().StreamSourceLink(absoluteUri) .XmlRepresentation("<entry xml:base='" + testCase.BaseUriString + "'><content src='" + absoluteUri + "'/></entry>"), ExpectedException = testCase.ExpectedException }; // [Astoria-ODataLib-Integration] Parsing of URLs on OData recognized places may fail, but Astoria server doesn't // In server mode we need to normalize payload to not expect information that the server does not read if(behaviorKind == TestODataBehaviorKind.WcfDataServicesServer) { td.ExpectedResultNormalizers.Add((tc) => (payloadElement => WcfDsServerPayloadElementNormalizer.Normalize(payloadElement, tc.Format, (EdmModel)null))); } testConfiguration = testConfiguration.CloneAndApplyBehavior(behaviorKind); testConfiguration.MessageReaderSettings.BaseUri = testCase.SettingsBaseUri == null ? null : new Uri(testCase.SettingsBaseUri); td.RunTest(testConfiguration); }); }
public void ServiceDocumentReaderInvalidAtomMetadataTest() { // The ExpectedExceptions in the following test descriptors only apply when ATOM metadata reading is on. // When ATOM metadata reading is off, invalid ATOM metadata should cause no failures, and ExpectedException is ignored. IEnumerable<PayloadReaderTestDescriptor> testDescriptors = new PayloadReaderTestDescriptor[] { // Multiple atom:title elements inside the workspace element. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace().ResourceCollection("Products", baseUri + "Products")) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <atom:title>Default</atom:title> <atom:title>Default</atom:title> <collection href='" + baseUri + @"Products'> <atom:title>Products</atom:title> </collection> </workspace> </service>"), ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomServiceDocumentMetadataDeserializer_MultipleTitleElementsFound", "workspace"), }, // Invalid value for "fixed" attribute on a categories element new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace().ResourceCollection("Products", baseUri + "Products")) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <collection href='" + baseUri + @"Products'> <atom:title>Products</atom:title> <categories fixed='foo' scheme='http://baseschema.org'> <atom:category term='Some Term'/> </categories> </collection> </workspace> </service>"), ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomServiceDocumentMetadataDeserializer_InvalidFixedAttributeValue", "foo"), }, // Multiple app:accept attributes inside a collection new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.ServiceDocument().Workspace( PayloadBuilder.Workspace() .ResourceCollection( PayloadBuilder.ResourceCollection("Products", baseUri + "Products") .AppAccept("application/atom+xml;type=entry") .AppInlineCategories("yes", null, AtomMetadataBuilder.AtomCategory("SomeTerm", "http://someschema.org/", null)))) .XmlRepresentation(@"<service xmlns:app='http://www.w3.org/2007/app' xmlns='http://www.w3.org/2007/app' xmlns:atom='http://www.w3.org/2005/Atom'> <workspace> <collection href='" + baseUri + @"Products'> <atom:title>Products</atom:title> <accept>application/atom+xml;type=entry</accept> <categories fixed='yes'> <atom:category scheme='http://someschema.org/' term='SomeTerm'/> </categories> <accept>application/atom+xml;type=entry</accept> </collection> </workspace> </service>"), ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomServiceDocumentMetadataDeserializer_MultipleAcceptElementsFoundInCollection"), }, }; this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.ReaderTestConfigurationProvider.AtomFormatConfigurations.Where(tc => !tc.IsRequest), new bool[] { true, false }, (testDescriptor, testConfiguration, enableAtomMetadataReading) => { testConfiguration = new ReaderTestConfiguration(testConfiguration); testConfiguration.MessageReaderSettings.EnableAtomMetadataReading = enableAtomMetadataReading; testDescriptor = new PayloadReaderTestDescriptor(testDescriptor); if (!enableAtomMetadataReading) { testDescriptor.ExpectedResultNormalizers.Add(tc => RemoveAtomMetadataFromPayloadElementVisitor.Visit); testDescriptor.ExpectedException = null; } testDescriptor.RunTest(testConfiguration); }); }
public void DuplicatePropertyNamesTest() { EdmModel model = new EdmModel(); var entityType = new EdmEntityType("TestModel", "DuplicateEntityType"); entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false))); model.AddElement(entityType); var complexType = new EdmComplexType("TestModel", "DuplicateComplexType"); complexType.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(true)); model.AddElement(complexType); var container = new EdmEntityContainer("TestModel", "DefaultContainer"); container.AddEntitySet("ClosedEntitySet", entityType); model.AddElement(container); PropertyInstance primitiveProperty = PayloadBuilder.PrimitiveProperty("DuplicateProperty", 42); PropertyInstance complexProperty = PayloadBuilder.Property("DuplicateProperty", PayloadBuilder.ComplexValue("TestModel.DuplicateComplexType").PrimitiveProperty("Name", "foo")); PropertyInstance collectionProperty = PayloadBuilder.Property("DuplicateProperty", PayloadBuilder.PrimitiveMultiValue(EntityModelUtils.GetCollectionTypeName("Edm.String")).WithTypeAnnotation(EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetString(false)))); PropertyInstance streamProperty = PayloadBuilder.StreamProperty("DuplicateProperty", "http://odata.org/readlink", "http://odata.org/editlink"); PropertyInstance navigationProperty = PayloadBuilder.NavigationProperty("DuplicateProperty", "http://odata.org/navlink") .IsCollection(true) .WithTypeAnnotation(entityType); PropertyInstance expandedFeedProperty = PayloadBuilder.ExpandedNavigationProperty("DuplicateProperty", PayloadBuilder.EntitySet(new EntityInstance[] { PayloadBuilder.Entity("TestModel.DuplicateEntityType").PrimitiveProperty("Id", 1) })) .IsCollection(true) .WithTypeAnnotation(entityType); PropertyInstance associationLinkProperty = PayloadBuilder.NavigationProperty("DuplicateProperty", null, "http://odata.org/assoclink"); PropertyInstance[] allProperties = new[] { primitiveProperty, complexProperty, collectionProperty, streamProperty, navigationProperty, expandedFeedProperty, associationLinkProperty }; PropertyInstance[] propertiesWithPossibleDuplication = new[] { primitiveProperty, complexProperty, navigationProperty, expandedFeedProperty }; PropertyInstance[] propertiesWithNoDuplication = new[] { collectionProperty, streamProperty, associationLinkProperty }; IEnumerable<DuplicatePropertySet> duplicatePropertySets; // Those which may allow duplication duplicatePropertySets = propertiesWithPossibleDuplication .Variations(2).Select(properties => new DuplicatePropertySet { Properties = properties, DuplicationPotentiallyAllowed = true }); // Then for each in those which don't allow duplication try it against all the others duplicatePropertySets = duplicatePropertySets.Concat(propertiesWithNoDuplication.SelectMany( propertyWithNoDuplication => allProperties.SelectMany(otherProperty => new[] { new DuplicatePropertySet { Properties = new [] { propertyWithNoDuplication, otherProperty }, DuplicationPotentiallyAllowed = false }, new DuplicatePropertySet { Properties = new [] { otherProperty, propertyWithNoDuplication }, DuplicationPotentiallyAllowed = false }, }))); this.CombinatorialEngineProvider.RunCombinations( duplicatePropertySets, new bool[] { false, true }, new bool[] { true, false }, this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations, (duplicatePropertySet, useServerBehavior, useMetadata, testConfiguration) => { PropertyInstance firstProperty = duplicatePropertySet.Properties.ElementAt(0); PropertyInstance secondProperty = duplicatePropertySet.Properties.ElementAt(1); // Non-metadata parsing is not supported in JSON. if (!useMetadata && (testConfiguration.Format != ODataFormat.Atom)) { return; } // If we will have metadata then we can only allow combinations of the same kind if (useMetadata) { if (firstProperty.ElementType != secondProperty.ElementType) { return; } } // Association links are only recognized in response payloads and MPV >= V3 if ((testConfiguration.IsRequest) && duplicatePropertySet.Properties.Any(p => object.ReferenceEquals(p, associationLinkProperty))) { return; } // Steam properties are only recognized in response >=V3 payloads if ((testConfiguration.IsRequest) && duplicatePropertySet.Properties.Any(p => object.ReferenceEquals(p, streamProperty))) { return; } // Copy the test config testConfiguration = new ReaderTestConfiguration(testConfiguration); if (useServerBehavior) { testConfiguration.MessageReaderSettings.EnableODataServerBehavior(); } // Create a descriptor with the first property PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = firstProperty, PayloadEdmModel = useMetadata ? (EdmModel)Test.OData.Utils.Metadata.MetadataUtils.Clone(model) : null, }; // Now generate entity around it testDescriptor = testDescriptor.InEntity(2, 2); // Now add the second property to it ((EntityInstance)testDescriptor.PayloadElement).Add(secondProperty); // [Astoria-ODataLib-Integration] Parsing of URLs on OData recognized places may fail, but Astoria server doesn't // Server does not read named stream links for Atom payload therefore the expected payload needs to be normalized if (testConfiguration.Format == ODataFormat.Atom && useServerBehavior) { testDescriptor.ExpectedResultNormalizers.Add(config => (payloadElement => WcfDsServerPayloadElementNormalizer.Normalize(payloadElement, ODataFormat.Atom, testDescriptor.PayloadEdmModel as EdmModel))); } // We expect failure only if we don't allow duplicates or if the property kind doesn't allow duplicates ever. // In JSON with WCF DS Service behavior where duplicates are removed very soon and thus we never fail on them. if ((!duplicatePropertySet.DuplicationPotentiallyAllowed || !useServerBehavior)) { testDescriptor.ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "DuplicateProperty"); } if (firstProperty.ElementType == ODataPayloadElementType.NavigationPropertyInstance && secondProperty.ElementType == ODataPayloadElementType.NavigationPropertyInstance) { NavigationPropertyInstance navigationFirstProperty = (NavigationPropertyInstance)firstProperty; NavigationPropertyInstance navigationSecondProperty = (NavigationPropertyInstance)secondProperty; // If one of the properties is an association link and the other is a navigation link, that combination is allowed and it's not an error. // Just skip that combination. if ((navigationFirstProperty.Value != null && navigationFirstProperty.AssociationLink == null && navigationSecondProperty.Value == null && navigationSecondProperty.AssociationLink != null) || (navigationFirstProperty.Value == null && navigationFirstProperty.AssociationLink != null && navigationSecondProperty.Value != null && navigationSecondProperty.AssociationLink == null)) { return; } if (testConfiguration.Format == ODataFormat.Json) { if ((navigationFirstProperty.Value is DeferredLink || navigationSecondProperty.Value is DeferredLink) && (navigationFirstProperty.Value is ExpandedLink || navigationSecondProperty.Value is ExpandedLink)) { testDescriptor.ExpectedException = null; testDescriptor.ExpectedResultNormalizers.Add( (tc) => (tc.IsRequest) ? (Func<ODataPayloadElement, ODataPayloadElement>)((payload) => EnsureAnnotationsBeforeProperties(DuplicateNavigationPropertiesToLinkCollection(payload))) : (payload) => EnsureAnnotationsBeforeProperties(DuplicateNavigationPropertiesToExpandedLink(payload))); } else if (navigationFirstProperty.AssociationLink != null && navigationSecondProperty.AssociationLink != null) { testDescriptor.ExpectedException = ODataExpectedExceptions.ODataException( "DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataAssociationLinkUrlAnnotationName, "DuplicateProperty"); } } // In requests if both are navigation properties (not association links) // If both are expanded, then fail (that's not allowed), but if one is not expanded, that is allowed (binding in POST scenario) // Note that this only works because we use expanded feed, if we would add expanded entry, then the expanded entry can't be allowed along with a deferred link. else if (navigationFirstProperty.AssociationLink == null && navigationSecondProperty.AssociationLink == null && testConfiguration.IsRequest && (navigationFirstProperty.Value is DeferredLink || navigationSecondProperty.Value is DeferredLink)) { testDescriptor.ExpectedException = null; } } if (firstProperty.ElementType == ODataPayloadElementType.NamedStreamInstance && secondProperty.ElementType == ODataPayloadElementType.NamedStreamInstance) { if (testConfiguration.Format == ODataFormat.Atom) { // In ATOM stream properties are represented as pair of links and thus we first match the links together. // Thus the code finds the duplicate stream property before we get to the duplicate check // (since it actually finds a stream property which already has a link which it's trying to read) // As a result we get a different error message, which is OK. testDescriptor.ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomEntryAndFeedDeserializer_StreamPropertyWithMultipleReadLinks", "DuplicateProperty"); } else if (testConfiguration.Format == ODataFormat.Json) { testDescriptor.ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataMediaEditLinkAnnotationName, "DuplicateProperty"); } } if (testConfiguration.Format == ODataFormat.Json) { testDescriptor.PayloadElement = EnsureAnnotationsBeforeProperties(testDescriptor.PayloadElement); } testDescriptor.RunTest(testConfiguration); }); }
public void DuplicateNavigationLinkTest() { IEdmModel model = TestModels.BuildTestModel(); IEnumerable<DuplicateNavigationLinkTestCase> testCases = new[] { new DuplicateNavigationLinkTestCase { DebugDescription = "Two expanded links, both collection", Properties = new PropertyInstance[] { PayloadBuilder.ExpandedNavigationProperty( "CityHall", PayloadBuilder.EntitySet().InsertAt(0, PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 1), PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 2))), PayloadBuilder.ExpandedNavigationProperty( "CityHall", PayloadBuilder.EntitySet()) }, ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = (tc.Format == ODataFormat.Json) ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall") : (tc.IsRequest) ? null : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"), }, }, new DuplicateNavigationLinkTestCase { DebugDescription = "Two expanded links, both singletons", Properties = new PropertyInstance[] { PayloadBuilder.ExpandedNavigationProperty( "PoliceStation", PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 1)), PayloadBuilder.ExpandedNavigationProperty( "PoliceStation", null) }, ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = (tc.Format == ODataFormat.Json) ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "PoliceStation") : (tc.IsRequest) ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_MultipleLinksForSingleton", "PoliceStation") : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "PoliceStation"), }, }, new DuplicateNavigationLinkTestCase { DebugDescription = "Two expanded links, one collection one singleton", Properties = new PropertyInstance[] { PayloadBuilder.ExpandedNavigationProperty( "PoliceStation", PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 1)), PayloadBuilder.ExpandedNavigationProperty( "PoliceStation", PayloadBuilder.EntitySet()) }, ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_MultipleLinksForSingleton", "PoliceStation"), NoMetadataOnly = true }, new DuplicateNavigationLinkTestCase { DebugDescription = "Expanded singleton, deferred without type", Properties = new PropertyInstance[] { PayloadBuilder.ExpandedNavigationProperty( "PoliceStation", PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 1)), PayloadBuilder.DeferredNavigationProperty( "PoliceStation", PayloadBuilder.DeferredLink("http://odata.org/deferred")) }, ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = (tc.Format == ODataFormat.Json) ? tc.IsRequest ? ODataExpectedExceptions.ODataException("ODataJsonLightEntryAndFeedDeserializer_SingletonNavigationPropertyWithBindingAndValue", "PoliceStation", JsonLightConstants.ODataBindAnnotationName) : null : tc.IsRequest ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_MultipleLinksForSingleton", "PoliceStation") : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "PoliceStation"), } }, new DuplicateNavigationLinkTestCase { DebugDescription = "Expanded singleton, deferred singleton", Properties = new PropertyInstance[] { PayloadBuilder.ExpandedNavigationProperty( "PoliceStation", PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 1)), PayloadBuilder.DeferredNavigationProperty( "PoliceStation", PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(false)) }, ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = (tc.Format == ODataFormat.Json) ? tc.IsRequest ? ODataExpectedExceptions.ODataException("ODataJsonLightEntryAndFeedDeserializer_SingletonNavigationPropertyWithBindingAndValue", "PoliceStation", JsonLightConstants.ODataBindAnnotationName) : null : tc.IsRequest ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_MultipleLinksForSingleton", "PoliceStation") : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "PoliceStation"), } }, new DuplicateNavigationLinkTestCase { DebugDescription = "Expanded singleton, deferred collection (no metadata), we will fail on this since we don't allow multiple links for singletons", Properties = new PropertyInstance[] { PayloadBuilder.ExpandedNavigationProperty( "PoliceStation", PayloadBuilder.Entity("TestModel.OfficeType").PrimitiveProperty("Id", 1)), PayloadBuilder.DeferredNavigationProperty( "PoliceStation", PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(true)) }, ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_MultipleLinksForSingleton", "PoliceStation"), NoMetadataOnly = true }, new DuplicateNavigationLinkTestCase { DebugDescription = "Expanded collection, deferred without type - no failures", Properties = new PropertyInstance[] { PayloadBuilder.ExpandedNavigationProperty( "CityHall", PayloadBuilder.EntitySet()), PayloadBuilder.DeferredNavigationProperty( "CityHall", PayloadBuilder.DeferredLink("http://odata.org/deferred")).IsCollection(true) }, ExpectedResultNormalizer = (tc) => { if (tc.Format == ODataFormat.Json) { return (tc.IsRequest) ? (Func<ODataPayloadElement, ODataPayloadElement>)DuplicateNavigationPropertiesToLinkCollection : DuplicateNavigationPropertiesToExpandedLink; } return null; }, ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = (tc.Format == ODataFormat.Json || tc.IsRequest) ? null : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"), } }, new DuplicateNavigationLinkTestCase { DebugDescription = "Expanded collection, deferred singleton - no failures (binding scenario) (the metadata mismatch is specifically allowed)", Properties = new PropertyInstance[] { PayloadBuilder.ExpandedNavigationProperty( "CityHall", PayloadBuilder.EntitySet()), PayloadBuilder.DeferredNavigationProperty( "CityHall", PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(false)) }, // Doesn't work for JSON since the metadata mismatch will cause the parsing to fail // Does not work for deferred link in responses. SkipForConfiguration = tc => tc.IsRequest == false, ExpectedResultNormalizer = (tc) => (tc.Format == ODataFormat.Json) ? DuplicateNavigationPropertiesToLinkCollection : (Func<ODataPayloadElement, ODataPayloadElement>)null, ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = (tc.Format == ODataFormat.Json) ? ODataExpectedExceptions.ODataException("ODataJsonLightEntryAndFeedDeserializer_StringValueForCollectionBindPropertyAnnotation", "CityHall", JsonLightConstants.ODataBindAnnotationName) : null, }, }, new DuplicateNavigationLinkTestCase { DebugDescription = "Expanded collection, deferred collection - no failures (binding scenario)", Properties = new PropertyInstance[] { PayloadBuilder.ExpandedNavigationProperty( "CityHall", PayloadBuilder.EntitySet()), PayloadBuilder.DeferredNavigationProperty( "CityHall", PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(true)) }, // Doesn't work for JSON since the metadata mismatch will cause the parsing to fail ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = (tc.Format == ODataFormat.Json) ? tc.IsRequest ? ODataExpectedExceptions.ODataException("ODataJsonLightEntryAndFeedDeserializer_StringValueForCollectionBindPropertyAnnotation", "CityHall", JsonLightConstants.ODataBindAnnotationName) : null : tc.IsRequest ? null : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"), }, }, new DuplicateNavigationLinkTestCase { DebugDescription = "Two deferred singletons on a collection property - no failures (binding scenario) (the metadata mismatch is specifically allowed)", Properties = new PropertyInstance[] { PayloadBuilder.DeferredNavigationProperty( "CityHall", PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(false)), PayloadBuilder.DeferredNavigationProperty( "CityHall", PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(false)) }, // Doesn't work for JSON since the metadata mismatch will cause the parsing to fail // Does not work for deferred link in responses. SkipForConfiguration = tc => tc.IsRequest == false, ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = (tc.Format == ODataFormat.Json) ? (tc.IsRequest) ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataBindAnnotationName, "CityHall") : null : (tc.IsRequest) ? null : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"), }, }, new DuplicateNavigationLinkTestCase { DebugDescription = "Two deferred collections on a collection property - no failures (binding scenario)", Properties = new PropertyInstance[] { PayloadBuilder.DeferredNavigationProperty( "CityHall", PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(true)).IsCollection(true), PayloadBuilder.DeferredNavigationProperty( "CityHall", PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(true)).IsCollection(true) }, ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = (tc.Format == ODataFormat.Json) ? (tc.IsRequest) ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataBindAnnotationName, "CityHall") : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataNavigationLinkUrlAnnotationName, "CityHall") : (tc.IsRequest) ? null : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"), }, }, new DuplicateNavigationLinkTestCase { DebugDescription = "Deferred collection and deferred singleton - no failures (binding scenario) (the metadata mismatch is specifically allowed)", Properties = new PropertyInstance[] { PayloadBuilder.DeferredNavigationProperty( "CityHall", PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(true)), PayloadBuilder.DeferredNavigationProperty( "CityHall", PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(false)) }, // Doesn't work for JSON since the metadata mismatch will cause the parsing to fail // Does not work for deferred link in responses. SkipForConfiguration = tc => tc.IsRequest == false, ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = (tc.Format == ODataFormat.Json) ? (tc.IsRequest) ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataBindAnnotationName, "CityHall") : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataNavigationLinkUrlAnnotationName, "CityHall") : (tc.IsRequest) ? null : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"), }, }, new DuplicateNavigationLinkTestCase { DebugDescription = "Expanded collection, deferred collection and deferred singleton - no failures (binding scenario) (the metadata mismatch is specifically allowed)", Properties = new PropertyInstance[] { PayloadBuilder.ExpandedNavigationProperty( "CityHall", PayloadBuilder.EntitySet()), PayloadBuilder.DeferredNavigationProperty( "CityHall", PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(true)), PayloadBuilder.DeferredNavigationProperty( "CityHall", PayloadBuilder.DeferredLink("http://odata.org/deferred").IsCollection(false)) }, // Doesn't work for JSON since the metadata mismatch will cause the parsing to fail // Does not work for deferred link in responses. SkipForConfiguration = tc => tc.IsRequest == false, ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = (tc.Format == ODataFormat.Json) ? (tc.IsRequest) ? ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataBindAnnotationName, "CityHall") : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationForPropertyNotAllowed", JsonLightConstants.ODataNavigationLinkUrlAnnotationName, "CityHall") : (tc.IsRequest) ? null : ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "CityHall"), }, }, }; // Add association link cases (this should have no effect on the result, since single association link is always allowed) testCases = testCases.SelectMany(testCase => new[] { testCase, new DuplicateNavigationLinkTestCase(testCase) { DebugDescription = testCase.DebugDescription + " [With association link]", Properties = testCase.Properties.ConcatSingle(PayloadBuilder.NavigationProperty(testCase.Properties[0].Name, null, "http://odata.org/associationlink")).ToArray(), // No association links in requests. SkipForConfiguration = tc => testCase.SkipForConfiguration == null ? tc.IsRequest : testCase.SkipForConfiguration(tc) || tc.IsRequest } }); // Add all permutations since order should not have any effect on the outcome testCases = testCases.SelectMany(testCase => testCase.Properties.Permutations().Select(properties => new DuplicateNavigationLinkTestCase(testCase) { Properties = properties })); this.CombinatorialEngineProvider.RunCombinations( testCases, new bool[] { true, false }, this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations, (testCase, withMetadata, testConfiguration) => { // JSON reading requires metadata if (!withMetadata && (testConfiguration.Format == ODataFormat.Json)) { return; } if (withMetadata && testCase.NoMetadataOnly) { return; } if (testCase.SkipForConfiguration != null && testCase.SkipForConfiguration(testConfiguration)) { return; } EntityInstance entityInstance = PayloadBuilder.Entity("TestModel.CityType").PrimitiveProperty("Id", 1); foreach (PropertyInstance propertyInstance in testCase.Properties) { entityInstance.Add(propertyInstance); } ExpectedException expectedException = testCase.ExpectedException; if (!testConfiguration.IsRequest && testCase.ExpectedResultCallback == null) { // In responses all duplicates will fail with the same error message since we don't allow any duplicates there. expectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", testCase.Properties[0].Name); } PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings) { DebugDescription = testCase.DebugDescription, PayloadElement = entityInstance, ExpectedException = expectedException, ExpectedResultCallback = testCase.ExpectedResultCallback, PayloadEdmModel = withMetadata ? model : null, }; testDescriptor.ExpectedResultNormalizers.Add( tc => (Func<ODataPayloadElement, ODataPayloadElement>)null); testDescriptor.ExpectedResultNormalizers.Add(tc => RemoveContentTypeAnnotationNormalizer.Normalize); if (testCase.ExpectedResultNormalizer != null) { testDescriptor.ExpectedResultNormalizers.Add(testCase.ExpectedResultNormalizer); } if (testConfiguration.Format == ODataFormat.Json) { testDescriptor.PayloadElement = EnsureAnnotationsBeforeProperties(testDescriptor.PayloadElement); } testDescriptor.RunTest(testConfiguration); }); }
public void BatchReaderBatchSizeTests() { var testCases = new[] { new { MaxPartsPerBatch = (int?)null, QueryCount = 0, ExpectedException = (ExpectedException)null }, new { MaxPartsPerBatch = (int?)null, QueryCount = 1, ExpectedException = (ExpectedException)null }, new { MaxPartsPerBatch = (int?)null, QueryCount = 4, ExpectedException = (ExpectedException)null }, new { MaxPartsPerBatch = (int?)0, QueryCount = 0, ExpectedException = (ExpectedException)null }, new { MaxPartsPerBatch = (int?)1, QueryCount = 1, ExpectedException = (ExpectedException)null }, new { MaxPartsPerBatch = (int?)2, QueryCount = 2, ExpectedException = (ExpectedException)null }, new { MaxPartsPerBatch = (int?)5, QueryCount = 0, ExpectedException = (ExpectedException)null }, new { MaxPartsPerBatch = (int?)5, QueryCount = 1, ExpectedException = (ExpectedException)null }, new { MaxPartsPerBatch = (int?)5, QueryCount = 2, ExpectedException = (ExpectedException)null }, new { MaxPartsPerBatch = (int?)0, QueryCount = 1, ExpectedException = ODataExpectedExceptions.ODataException("ODataBatchReader_MaxBatchSizeExceeded", "0") }, new { MaxPartsPerBatch = (int?)1, QueryCount = 2, ExpectedException = ODataExpectedExceptions.ODataException("ODataBatchReader_MaxBatchSizeExceeded", "1") }, new { MaxPartsPerBatch = (int?)2, QueryCount = 5, ExpectedException = ODataExpectedExceptions.ODataException("ODataBatchReader_MaxBatchSizeExceeded", "2") }, }; this.CombinatorialEngineProvider.RunCombinations( testCases, this.ReaderTestConfigurationProvider.DefaultFormatConfigurations, (testCase, testConfig) => { PayloadTestDescriptor ptd = TestBatches.CreateDefaultQueryBatch( this.RequestManager, testCase.QueryCount, testConfig.IsRequest); PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.PayloadReaderSettings) { DebugDescription = "Batch with " + testCase.QueryCount + " queries.", PayloadDescriptor = ptd, ExpectedException = testCase.ExpectedException, }; testConfig = ModifyBatchTestConfig(testConfig, testCase.MaxPartsPerBatch, /*maxOperationsPerChangeset*/ null); testDescriptor.RunTest(testConfig); }); }
public void TypeCheckingOnCollectionPropertyWithModel() { EdmModel model = new EdmModel(); var entity = new EdmEntityType("TestNS", "EntityWithCollection"); entity.AddKeys(entity.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false))); entity.AddStructuralProperty("Collection", EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(false))); model.AddElement(entity); var container = new EdmEntityContainer("TestNS", "DefaultContainer"); container.AddEntitySet("EntitySet", entity); model.AddElement(container); EntityInstance entityWithCollection = new EntityInstance("TestNS.EntityWithCollection", false /*isnull*/); entityWithCollection.PrimitiveProperty("Id", 1).Property(new PrimitiveMultiValueProperty("Collection", new PrimitiveMultiValue("Collection(Edm.String)", false /*isnull*/, new PrimitiveValue[] { new PrimitiveValue(null, "5"), new PrimitiveValue(null, "-32"), new PrimitiveValue(null, "+16"), new PrimitiveValue(null, "0") }))); entityWithCollection.WithTypeAnnotation(entity); EntityInstance expectedCollection = new EntityInstance("TestNS.EntityWithCollection", false /*isnull*/); expectedCollection.PrimitiveProperty("Id", 1).Property(new PrimitiveMultiValueProperty("Collection", new PrimitiveMultiValue("Collection(Edm.Int32)", false /*isnull*/, new PrimitiveValue[] { new PrimitiveValue(null, 5), new PrimitiveValue(null, -32), new PrimitiveValue(null, 16), new PrimitiveValue(null, 0) }).WithAnnotations(new SerializationTypeNameTestAnnotation() { TypeName = "Collection(Edm.String)" }))); expectedCollection.WithTypeAnnotation(entity); PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings) { PayloadEdmModel = model, PayloadElement = entityWithCollection, SkipTestConfiguration = tc => tc.Version < ODataVersion.V4, ExpectedResultCallback = tc => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedPayloadElement = expectedCollection } }; this.CombinatorialEngineProvider.RunCombinations( this.ReaderTestConfigurationProvider.ExplicitFormatConfigurations, new[] { true, false }, (testConfiguration, laxMode) => { var descriptor = new PayloadReaderTestDescriptor(testDescriptor); if (testConfiguration.Format == ODataFormat.Json) { var testEntityInstance = descriptor.PayloadElement.DeepCopy() as EntityInstance; PropertyInstance testProperty = testEntityInstance.Properties.Single(p => p.Name == "Collection"); testProperty.WithPropertyAnnotation(JsonLightConstants.ODataTypeAnnotationName, "Collection(Edm.String)"); descriptor.PayloadElement = testEntityInstance; } if (laxMode) { // Run test in Lax mode - type will be inferred from the model and will pass. descriptor.RunTest(testConfiguration.CloneAndApplyBehavior(TestODataBehaviorKind.WcfDataServicesServer)); } else { // Run test in Strict mode - type comparison will fail and an exception will be thrown. descriptor.ExpectedResultCallback = (tc) => new PayloadReaderTestExpectedResult(this.Settings.ExpectedResultSettings) { ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncompatibleType", "Collection(Edm.String)", "Collection(Edm.Int32)") }; descriptor.RunTest(testConfiguration); } }); }
public void BatchReaderChangeSetSizeTests() { var testCases = new[] { new { MaxOperationsPerChangeset = (int?)null, ChangeSetCount = 0, ChangeSetSizes = new int[0], ExpectedException = (ExpectedException)null }, new { MaxOperationsPerChangeset = (int?)null, ChangeSetCount = 1, ChangeSetSizes = new int[] { 1 }, ExpectedException = (ExpectedException)null }, new { MaxOperationsPerChangeset = (int?)null, ChangeSetCount = 1, ChangeSetSizes = new int[] { 3 }, ExpectedException = (ExpectedException)null }, new { MaxOperationsPerChangeset = (int?)null, ChangeSetCount = 2, ChangeSetSizes = new int[] { 0, 0 }, ExpectedException = (ExpectedException)null }, new { MaxOperationsPerChangeset = (int?)null, ChangeSetCount = 2, ChangeSetSizes = new int[] { 1, 2 }, ExpectedException = (ExpectedException)null }, new { MaxOperationsPerChangeset = (int?)1, ChangeSetCount = 1, ChangeSetSizes = new int[] { 2 }, ExpectedException = ODataExpectedExceptions.ODataException("ODataBatchReader_MaxChangeSetSizeExceeded", "1") }, new { MaxOperationsPerChangeset = (int?)0, ChangeSetCount = 1, ChangeSetSizes = new int[] { 1 }, ExpectedException = ODataExpectedExceptions.ODataException("ODataBatchReader_MaxChangeSetSizeExceeded", "0") }, new { MaxOperationsPerChangeset = (int?)2, ChangeSetCount = 1, ChangeSetSizes = new int[] { 2 }, ExpectedException = (ExpectedException)null }, new { MaxOperationsPerChangeset = (int?)0, ChangeSetCount = 0, ChangeSetSizes = new int[0], ExpectedException = (ExpectedException)null }, }; this.CombinatorialEngineProvider.RunCombinations( testCases, this.ReaderTestConfigurationProvider.DefaultFormatConfigurations, (testCase, testConfig) => { PayloadTestDescriptor ptd = TestBatches.CreateDefaultChangeSetBatch( this.RequestManager, testCase.ChangeSetCount, testCase.ChangeSetSizes, testConfig.IsRequest); PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.PayloadReaderSettings) { DebugDescription = "Batch with " + testCase.ChangeSetCount + " changesets of varying sizes.", PayloadDescriptor = ptd, ExpectedException = testCase.ExpectedException, }; testConfig = ModifyBatchTestConfig(testConfig, /*maxPartsPerBatch*/ null, testCase.MaxOperationsPerChangeset); testDescriptor.RunTest(testConfig); }); }
public void TopLevelPropertyNamespaceTest() { var testCases = new[] { new { // Support custom data namespace for compatibility with WCF DS client. NamespaceUri = TestAtomConstants.ODataMetadataNamespace + "/custom", ExpectedException = new System.Func<TestODataBehaviorKind, ODataVersion, ExpectedException>((TestODataBehaviorKind behavior,ODataVersion odataVersion) => { if (behavior == TestODataBehaviorKind.WcfDataServicesServer) { return null; } else { return ODataExpectedExceptions.ODataException("ODataAtomPropertyAndValueDeserializer_TopLevelPropertyElementWrongNamespace", TestAtomConstants.ODataMetadataNamespace + "/custom", TestAtomConstants.ODataMetadataNamespace); } }) }, new { NamespaceUri = TestAtomConstants.ODataMetadataNamespace, ExpectedException = new System.Func<TestODataBehaviorKind, ODataVersion, ExpectedException>((TestODataBehaviorKind behavior, ODataVersion odataVersion) => { return null; }) }, new { NamespaceUri = TestAtomConstants.ODataNamespace, ExpectedException = new System.Func<TestODataBehaviorKind, ODataVersion, ExpectedException>((TestODataBehaviorKind behavior, ODataVersion odataVersion) => { if (behavior == TestODataBehaviorKind.WcfDataServicesServer) { return null; } else { return ODataExpectedExceptions.ODataException("ODataAtomPropertyAndValueDeserializer_TopLevelPropertyElementWrongNamespace", TestAtomConstants.ODataNamespace, TestAtomConstants.ODataMetadataNamespace); } }) }, new { NamespaceUri = "http://odata.org/customUri", ExpectedException = new System.Func<TestODataBehaviorKind, ODataVersion, ExpectedException>((TestODataBehaviorKind behavior,ODataVersion odataVersion) => { if (behavior == TestODataBehaviorKind.WcfDataServicesServer) { return null; } else { return ODataExpectedExceptions.ODataException("ODataAtomPropertyAndValueDeserializer_TopLevelPropertyElementWrongNamespace", "http://odata.org/customUri", TestAtomConstants.ODataMetadataNamespace); } }) } }; this.CombinatorialEngineProvider.RunCombinations( testCases, TestReaderUtils.ODataBehaviorKinds, new[] { ODataVersion.V4 }, this.ReaderTestConfigurationProvider.AtomFormatConfigurations, (testCase, behavior, odataVersion, testConfiguration) => { var td = new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.PrimitiveProperty(null, string.Empty) .XmlRepresentation("<p:value xmlns:p='" + testCase.NamespaceUri + "'/>"), ExpectedException = testCase.ExpectedException(behavior, odataVersion) }; testConfiguration = testConfiguration.CloneAndApplyBehavior(behavior); td.RunTest(testConfiguration); }); }
public void OpenTopLevelPropertiesErrorTest() { IEdmModel model = TestModels.BuildTestModel(); var testCases = new OpenPropertyTestCase[] { new OpenPropertyTestCase { DebugDescription = "String open property with property annotation type information - should fail.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)), Json = "{0}" + "\"" + JsonLightUtils.GetPropertyAnnotationName(JsonLightConstants.ODataValuePropertyName, JsonLightConstants.ODataTypeAnnotationName) + "\":\"Edm.String\"," + "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"", ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_UnexpectedODataPropertyAnnotation", JsonLightConstants.ODataTypeAnnotationName) }, new OpenPropertyTestCase { DebugDescription = "String open property with complex type information - should fail.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)), Json = "{0}" + "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"TestModel.Address\"," + "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"", ExpectedException = ODataExpectedExceptions.ODataException("ValidationUtils_IncorrectTypeKind", "TestModel.Address", "Primitive", "Complex") }, new OpenPropertyTestCase { DebugDescription = "Type property after the data property - should fail.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)), Json = "{0}" + "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"," + "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\"" , ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_TypePropertyAfterValueProperty", JsonLightConstants.ODataTypeAnnotationName, JsonLightConstants.ODataValuePropertyName) }, new OpenPropertyTestCase { DebugDescription = "Duplicate data property - should fail.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)), Json = "{0}" + "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\"," + "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"," + "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"", ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", JsonLightConstants.ODataValuePropertyName) }, new OpenPropertyTestCase { DebugDescription = "Duplicate type property - should fail.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)), Json = "{0}" + "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\"," + "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\"," + "\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"", ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicateAnnotationNotAllowed", JsonLightConstants.ODataTypeAnnotationName) }, new OpenPropertyTestCase { DebugDescription = "No data property - should fail.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)), Json = "{0}" + "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\"", ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyPayload") }, new OpenPropertyTestCase { DebugDescription = "No data property (only type property) - should fail.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value").ExpectedPropertyType(EdmCoreModel.Instance.GetString(true)), Json = "{0}" + "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\"", ExpectedException = ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyPayload") }, }; this.CombinatorialEngineProvider.RunCombinations( testCases, this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations, (testCase, testConfiguration) => { string json = string.Format( CultureInfo.InvariantCulture, testCase.Json, testConfiguration.IsRequest ? string.Empty : "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#Edm.String\","); PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings) { DebugDescription = testCase.DebugDescription, PayloadElement = testCase.ExpectedProperty .JsonRepresentation("{" + json + "}"), PayloadEdmModel = model, ExpectedException = testCase.ExpectedException, }; // These descriptors are already tailored specifically for Json Light and // do not require normalization. testDescriptor.TestDescriptorNormalizers.Clear(); testDescriptor.RunTest(testConfiguration); }); }
public void OpenComplexTopLevelPropertiesTest() { IEdmModel model = TestModels.BuildTestModel(); var addressType = model.FindDeclaredType("TestModel.Address"); var testCases = new OpenPropertyTestCase[] { new OpenPropertyTestCase { DebugDescription = "Empty complex open property with type information.", ExpectedProperty = PayloadBuilder.Property("OpenProperty", PayloadBuilder.ComplexValue("TestModel.Address")), ExpectedPropertyType = addressType.ToTypeReference(), JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"TestModel.Address\"", Json = "{0}{1}", }, new OpenPropertyTestCase { DebugDescription = "Complex property with data.", ExpectedProperty = PayloadBuilder.Property("OpenProperty", PayloadBuilder.ComplexValue("TestModel.Address").PrimitiveProperty("Street", "First")), ExpectedPropertyType = addressType.ToTypeReference(), JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"TestModel.Address\",", Json = "{0}{1}\"Street\":\"First\"", }, }; bool[] withExpectedTypes = new bool[] { true, false }; bool[] withPayloadTypes = new bool[] { true, false }; bool[] includeContextUri = new bool[] { true, false }; this.CombinatorialEngineProvider.RunCombinations( testCases, withExpectedTypes, withPayloadTypes, includeContextUri, this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations, (testCase, withExpectedType, withPayloadType, withContextUri, testConfiguration) => { if (withContextUri && testConfiguration.IsRequest) { return; } PropertyInstance property = testCase.ExpectedProperty.DeepCopy(); ComplexProperty complexProperty = (ComplexProperty)property; ComplexInstance complexValue = complexProperty.Value; bool isEmpty = !complexValue.Properties.Any(); string contextUri = withContextUri ? "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + "\":\"http://odata.org/test/$metadata#TestModel.Address\"," : string.Empty; string json = string.Format( CultureInfo.InvariantCulture, testCase.Json, contextUri, withPayloadType ? testCase.JsonTypeInformation : string.Empty); if (isEmpty && json.EndsWith(",")) { json = json.Substring(0, json.Length - 1); } if (withExpectedType) { property = property.ExpectedPropertyType(testCase.ExpectedPropertyType); } if (!withPayloadType) { complexProperty.Value.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null }); } ExpectedException expectedException = testCase.ExpectedException; if (!withContextUri && !testConfiguration.IsRequest) { expectedException = ODataExpectedExceptions.ODataException("ODataJsonLightDeserializer_ContextLinkNotFoundAsFirstProperty"); } else if (!withExpectedType && !withPayloadType && !withContextUri) { string firstPropertyName = isEmpty ? null : complexValue.Properties.First().Name; // An open property without expected and payload type cannot be read; expect an exception. expectedException = isEmpty ? ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyPayload") : ODataExpectedExceptions.ODataException("ODataJsonLightPropertyAndValueDeserializer_InvalidTopLevelPropertyName", firstPropertyName, JsonLightConstants.ODataValuePropertyName); } PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings) { DebugDescription = testCase.DebugDescription + "[Expected type: " + withExpectedType + ", payload type: " + withPayloadType + "]", PayloadElement = property .JsonRepresentation("{" + json + "}"), PayloadEdmModel = model, ExpectedException = expectedException, }; // These descriptors are already tailored specifically for Json Light and // do not require normalization. testDescriptor.TestDescriptorNormalizers.Clear(); testDescriptor.RunTest(testConfiguration); }); }
public void OpenTopLevelPropertiesTest() { IEdmModel model = TestModels.BuildTestModel(); var testCases = new OpenPropertyTestCase[] { new OpenPropertyTestCase { DebugDescription = "Integer open property.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", 42), ExpectedPropertyWhenTypeUnavailable = PayloadBuilder.PrimitiveProperty("OpenProperty", 42), ExpectedPropertyType = EdmCoreModel.Instance.GetInt32(false), JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.Int32\",", Json = "{0}{1}\"" + JsonLightConstants.ODataValuePropertyName + "\":42", }, new OpenPropertyTestCase { DebugDescription = "Null open property.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", null), ExpectedPropertyWhenTypeUnavailable = PayloadBuilder.PrimitiveProperty("OpenProperty", null), ExpectedPropertyType = EdmCoreModel.Instance.GetString(true), JsonTypeInformation = string.Empty, Json = "{0}{1}\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataNullAnnotationName + "\":true", }, new OpenPropertyTestCase { DebugDescription = "String open property.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", "value"), ExpectedPropertyWhenTypeUnavailable = PayloadBuilder.PrimitiveProperty("OpenProperty", "value"), ExpectedPropertyType = EdmCoreModel.Instance.GetString(true), JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.String\",", Json = "{0}{1}\"" + JsonLightConstants.ODataValuePropertyName + "\":\"" + JsonLightConstants.ODataValuePropertyName + "\"", }, new OpenPropertyTestCase { DebugDescription = "DateTimeOffset open property with type information.", ExpectedProperty = PayloadBuilder.PrimitiveProperty("OpenProperty", new DateTimeOffset(2012, 4, 13, 2, 43, 10, 215, TimeSpan.Zero)), ExpectedPropertyWhenTypeUnavailable = PayloadBuilder.PrimitiveProperty("OpenProperty", "2012-04-13T02:43:10.215Z"), ExpectedPropertyType = EdmCoreModel.Instance.GetDateTimeOffset(false), JsonTypeInformation = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"Edm.DateTimeOffset\",", Json = "{0}{1}\"" + JsonLightConstants.ODataValuePropertyName + "\":\"2012-04-13T02:43:10.215Z\"", }, }; bool[] withExpectedTypes = new bool[] { true, false }; bool[] withPayloadTypes = new bool[] { true, false }; bool[] includeContextUri = new bool[] { true, false }; this.CombinatorialEngineProvider.RunCombinations( testCases, withExpectedTypes, withPayloadTypes, includeContextUri, this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations, (testCase, withExpectedType, withPayloadType, withContextUri, testConfiguration) => { if (withContextUri && testConfiguration.IsRequest) { return; } string expectedTypeName = testCase.ExpectedPropertyType is IEdmCollectionTypeReference ? "Collection(" + ((IEdmCollectionType)testCase.ExpectedPropertyType.Definition).ElementType.FullName() + ")" : testCase.ExpectedPropertyType.TestFullName(); string contextUri = withContextUri ? "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataContextAnnotationName + string.Format("\":\"http://odata.org/test/$metadata#{0}\",", expectedTypeName) : string.Empty; string json = string.Format( CultureInfo.InvariantCulture, testCase.Json, contextUri, withPayloadType ? testCase.JsonTypeInformation : string.Empty); bool typeGiven = withExpectedType || withPayloadType || withContextUri; if (!typeGiven && testCase.ExpectedPropertyWhenTypeUnavailable == null) { testCase.ExpectedException = ODataExpectedExceptions.ODataException("ReaderValidationUtils_ValueWithoutType"); } PropertyInstance property = typeGiven || testCase.ExpectedPropertyWhenTypeUnavailable == null ? testCase.ExpectedProperty : testCase.ExpectedPropertyWhenTypeUnavailable; property = property.DeepCopy(); if (withExpectedType) { property = property.ExpectedPropertyType(testCase.ExpectedPropertyType); } if (!withPayloadType) { ComplexProperty complexProperty = property as ComplexProperty; if (complexProperty != null) { complexProperty.Value.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null }); } else { PrimitiveMultiValueProperty primitiveCollectionProperty = property as PrimitiveMultiValueProperty; if (primitiveCollectionProperty != null) { primitiveCollectionProperty.Value.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null }); } else { ComplexMultiValueProperty complexCollectionProperty = property as ComplexMultiValueProperty; if (complexCollectionProperty != null) { complexCollectionProperty.Value.AddAnnotation(new SerializationTypeNameTestAnnotation() { TypeName = null }); } } } } ExpectedException expectedException = testCase.ExpectedException; if (!withContextUri && !testConfiguration.IsRequest) { expectedException = ODataExpectedExceptions.ODataException("ODataJsonLightDeserializer_ContextLinkNotFoundAsFirstProperty"); } PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings) { DebugDescription = testCase.DebugDescription + "[Expected type: " + withExpectedType + ", payload type: " + withPayloadType + "]", PayloadElement = property .JsonRepresentation("{" + json + "}"), PayloadEdmModel = model, ExpectedException = expectedException, }; // These descriptors are already tailored specifically for Json Light and // do not require normalization. testDescriptor.TestDescriptorNormalizers.Clear(); testDescriptor.RunTest(testConfiguration); }); }