Пример #1
0
        public void DuplicatePropertyNamesTest()
        {
            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[] allProperties = new[] { primitiveProperty, complexProperty, collectionProperty };
            PropertyInstance[] propertiesWithPossibleDuplication = new[] { primitiveProperty, complexProperty };
            PropertyInstance[] propertiesWithNoDuplication = new[] { collectionProperty };

            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, allowDuplicateProperties, useMetadata, testConfiguration) =>
                {
                    EdmModel model = new EdmModel();
                    var complexType = model.ComplexType("DuplicateComplexType");
                    complexType.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);
                    model.Fixup();

                    PropertyInstance firstProperty = duplicatePropertySet.Properties.ElementAt(0);
                    PropertyInstance secondProperty = duplicatePropertySet.Properties.ElementAt(1);

                    // Non-metadata reading is not possible in JSON
                    if (!useMetadata && (testConfiguration.Format == ODataFormat.Json))
                    {
                        return;
                    }

                    // If we will have metadata then we can only allow combinations of the same kind
                    if (useMetadata)
                    {
                        if (firstProperty.ElementType != secondProperty.ElementType)
                        {
                            return;
                        }
                    }

                    // Copy the test config
                    testConfiguration = new ReaderTestConfiguration(testConfiguration);
                    if (allowDuplicateProperties)
                    {
                        testConfiguration.MessageReaderSettings.EnableODataServerBehavior();
                    }

                    // Create a descriptor with the first property
                    PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(this.Settings)
                    {
                        PayloadElement = firstProperty,
                        PayloadEdmModel = useMetadata ? model : null
                    };

                    // Now generate entity around it
                    testDescriptor = testDescriptor.InComplexValue(5, 5);

                    // Now add the second property to it
                    ((ComplexInstance)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)
                    {
                        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
                    if ((!duplicatePropertySet.DuplicationPotentiallyAllowed || !allowDuplicateProperties))
                    {
                        testDescriptor.ExpectedException = ODataExpectedExceptions.ODataException("DuplicatePropertyNamesChecker_DuplicatePropertyNamesNotAllowed", "DuplicateProperty");
                    }

                    IEnumerable<PayloadReaderTestDescriptor> testDescriptors = new PayloadReaderTestDescriptor[]
                    {
                        testDescriptor.InProperty("TopLevelProperty"),
                        testDescriptor.InProperty("ComplexProperty").InEntity(2, 2),
                        testDescriptor.InCollection(5, 5).InProperty("TopLevelCollection"),
                    };

                    this.CombinatorialEngineProvider.RunCombinations(
                        testDescriptors, 
                        td =>
                        {
                            var property = td.PayloadElement as PropertyInstance;
                            if (property != null && testConfiguration.Format == ODataFormat.Atom)
                            {
                                property.Name = null;
                            }
                            td.RunTest(testConfiguration);
                        });
                });
        }
Пример #2
0
        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 ResourceCollectionNamePropertyTests()
        {
            // The behavior of the Name property depends on the format.
            // ATOM: We use it to populate the <title> element if no title has been specified on the ATOM metadata annotation. If there is both a title annotation and a Name property, they must match or else we'll fail.
            // JSON Light: The Name property is required and written to the "name" property in the format.

            IList<CollectionInfo> interestingCollections =
                new[]
                {
                    // Non null collection name
                    new CollectionInfo
                    {
                        Name = "CollectionName",
                        Url = "CollectionRelativeUrl",
                    },
                    // No name or title annotation
                    new CollectionInfo
                    {
                        Url = "CollectionRelativeUrl"
                    },
                    // Name and title annotation are both non null and are equal.
                    new CollectionInfo
                    {
                        Name = "CollectionName",
                        Url = "CollectionRelativeUrl",
                        TitleAnnotation = "CollectionName"
                    },
                    // Name and title annotation differ (expect failure in ATOM).
                    new CollectionInfo
                    {
                        Name = "CollectionName",
                        Url = "CollectionRelativeUrl",
                        TitleAnnotation = "CollectionTitle"
                    }
                };

            var collectionArrays = interestingCollections.Variations(0, 1, 3);

            EdmModel model=new EdmModel();
            EdmEntityContainer edmEntityContainer = new EdmEntityContainer("DefaultNamespace", "DefaultContainer");
            model.AddElement(edmEntityContainer);

            var testDescriptors = collectionArrays.Select(collectionArray => new PayloadWriterTestDescriptor<ODataServiceDocument>(
                this.Settings,
                CreateWorkspace( /*createMetadataFirst*/ false, /* workspaceName */ null, collectionArray),
                CreateExpectedResultCallback(baseUri, /* workspaceName */ null, collectionArray))
                {
                    Model = model,
                });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent,
                (testDescriptor, testConfig) =>
                {
                    WriterTestConfiguration newConfiguration = testConfig.Clone();
                    newConfiguration.MessageWriterSettings.PayloadBaseUri = new Uri(baseUri);
                    newConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);
                    TestWriterUtils.WriteAndVerifyTopLevelContent(
                        testDescriptor,
                        newConfiguration,
                        (messageWriter) => messageWriter.WriteServiceDocument(testDescriptor.PayloadItems.Single()),
                        this.Assert,
                        baselineLogger: this.Logger);
                });
        }
        public void AssociationLinkTest()
        {
            string associationLinkName1 = "AssociationLinkOne";
            string linkUrl1 = "http://odata.org/associationlink";
            Uri linkUrlUri1 = new Uri(linkUrl1);
            string associationLinkName2 = "AssociationLinkTwo";
            string linkUrl2 = "http://odata.org/associationlink2";
            Uri linkUrlUri2 = new Uri(linkUrl2);

            EdmModel model = new EdmModel();

            var edmEntityTypeOrderType = new EdmEntityType("TestModel", "OrderType");
            model.AddElement(edmEntityTypeOrderType);

            var edmEntityTypeCustomerType = new EdmEntityType("TestModel", "CustomerType");
            var edmNavigationPropertyAssociationLinkOne = edmEntityTypeCustomerType.AddUnidirectionalNavigation(
                new EdmNavigationPropertyInfo { Name = associationLinkName1, Target = edmEntityTypeOrderType, TargetMultiplicity = EdmMultiplicity.One });
            var edmNavigationPropertyAssociationLinkTwo = edmEntityTypeCustomerType.AddUnidirectionalNavigation(
                new EdmNavigationPropertyInfo { Name = associationLinkName2, Target = edmEntityTypeOrderType, TargetMultiplicity = EdmMultiplicity.Many });
            model.AddElement(edmEntityTypeCustomerType);

            var container = new EdmEntityContainer("TestModel", "Default");
            model.AddElement(container);

            var customerSet = container.AddEntitySet("Customers", edmEntityTypeCustomerType);
            var orderSet = container.AddEntitySet("Orders", edmEntityTypeOrderType);
            customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkOne, orderSet);
            customerSet.AddNavigationTarget(edmNavigationPropertyAssociationLinkTwo, orderSet);

            var testCases = new[]
            {
                new {
                    NavigationLink = ObjectModelUtils.CreateDefaultNavigationLink(associationLinkName1, linkUrlUri1),
                    Atom = BuildXmlAssociationLink(associationLinkName1, "application/xml", linkUrl1),
                    JsonLight = (string)null,
                },
                new {
                    NavigationLink = ObjectModelUtils.CreateDefaultNavigationLink(associationLinkName2, linkUrlUri2),
                    Atom = BuildXmlAssociationLink(associationLinkName2, "application/xml", linkUrl2),
                    JsonLight = (string)null
                },
            };

            var testCasesWithMultipleLinks = testCases.Variations()
                .Select(tcs =>
                new
                {
                    NavigationLinks = tcs.Select(tc => tc.NavigationLink),
                    Atom = string.Concat(tcs.Select(tc => tc.Atom)),
                    JsonLight = string.Join(",", tcs.Where(tc => tc.JsonLight != null).Select(tc => tc.JsonLight))
                });

            var testDescriptors = testCasesWithMultipleLinks.Select(testCase =>
            {
                ODataEntry entry = ObjectModelUtils.CreateDefaultEntry();
                entry.TypeName = "TestModel.CustomerType";
                List<ODataItem> items = new ODataItem[] { entry }.ToList();
                foreach (var navLink in testCase.NavigationLinks)
                {
                    items.Add(navLink);
                    items.Add(null);
                }

                return new PayloadWriterTestDescriptor<ODataItem>(
                    this.Settings,
                    items,
                    (testConfiguration) =>
                    {
                        var firstAssocLink = testCase.NavigationLinks == null ? null : testCase.NavigationLinks.FirstOrDefault();
                        if (testConfiguration.Format == ODataFormat.Atom)
                        {
                            return new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                Xml = "<AssociationLinks>" + testCase.Atom + "</AssociationLinks>",
                                FragmentExtractor = (result) =>
                                {
                                    var links = result.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                        .Where(l => l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName).Value.StartsWith(
                                            TestAtomConstants.ODataNavigationPropertiesAssociationLinkRelationPrefix));
                                    result = new XElement("AssociationLinks", links);
                                    if (result.FirstNode == null)
                                    {
                                        result.Add("");
                                    }

                                    return result;
                                },
                                ExpectedException2 = testConfiguration.IsRequest && firstAssocLink != null
                                    ? ODataExpectedExceptions.ODataException("ODataWriterCore_DeferredLinkInRequest")
                                    : null
                            };
                        }
                        else if (testConfiguration.Format == ODataFormat.Json)
                        {
                            return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                Json = string.Join(
                                    "$(NL)",
                                    "{",
                                    testCase.JsonLight,
                                    "}"),
                                FragmentExtractor = (result) =>
                                {
                                    var associationLinks = result.Object().GetAnnotationsWithName("@" + JsonLightConstants.ODataAssociationLinkUrlAnnotationName).ToList();
                                    var jsonResult = new JsonObject();
                                    associationLinks.ForEach(l =>
                                    {
                                        // NOTE we remove all annoatations here and in particular the text annotations to be able to easily compare
                                        //      against the expected results. This however means that we do not distinguish between the indented and non-indented case here.
                                        l.RemoveAllAnnotations(true);
                                        jsonResult.Add(l);
                                    });
                                    return jsonResult;
                                },
                            };
                        }
                        else
                        {
                            this.Settings.Assert.Fail("Unknown format '{0}'.", testConfiguration.Format);
                            return null;
                        }
                    })
                    {
                        Model = model,
                        PayloadEdmElementContainer = customerSet
                    };
            });

            // With and without model
            testDescriptors = testDescriptors.SelectMany(td =>
                new[]
                {
                    td,
                    new PayloadWriterTestDescriptor<ODataItem>(td)
                    {
                        Model = null,
                        PayloadEdmElementContainer = null
                    }
                });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors.PayloadCases(WriterPayloads.EntryPayloads),
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent,
                (testDescriptor, testConfiguration) =>
                {
                    testConfiguration = testConfiguration.Clone();
                    testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                    if (testDescriptor.Model == null && testConfiguration.Format == ODataFormat.Json)
                    {
                        return;
                    }

                    if (testDescriptor.IsGeneratedPayload && testDescriptor.Model != null)
                    {
                        return;
                    }

                    TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger);
                });
        }