/// <summary>
        /// Finds the n-th query operation (where n is specified in <paramref name="queryOperationIndex"/>) in the list of invocations and operations; return it.
        /// </summary>
        /// <param name="queryOperationIndex">The index of the desired query operation.</param>
        /// <returns>The requested query operation.</returns>
        internal BatchWriterTestDescriptor.BatchWriterOperationTestDescriptor GetQueryOperation(int queryOperationIndex)
        {
            // search for n-th query operation; return null if not found
            int currentQueryOperationIx = -1;

            BatchWriterTestDescriptor.BatchWriterOperationTestDescriptor queryOperation = null;
            for (int i = 0; i < this.InvocationsAndOperationDescriptors.Length; ++i)
            {
                if (this.InvocationsAndOperationDescriptors[i].Invocation == BatchWriterTestDescriptor.WriterInvocations.WriteQueryOperation)
                {
                    currentQueryOperationIx++;
                    if (currentQueryOperationIx == queryOperationIndex)
                    {
                        queryOperation = this.InvocationsAndOperationDescriptors[i].OperationDescriptor;
                        break;
                    }
                }
            }

            return(queryOperation);
        }
        internal static Func <string, string> GetComparer(BatchWriterTestDescriptor.BatchWriterOperationTestDescriptor operationDescriptor, WriterTestConfiguration testConfiguration)
        {
            string expectedContent = null;

            bool indent    = testConfiguration.MessageWriterSettings.Indent;
            var  variables = TestWriterUtils.GetPayloadVariablesForTestConfiguration(testConfiguration);

            Func <string, string> normalizer = null;
            Func <string, string> comparer   = null;

            var queryOperation = operationDescriptor as BatchWriterTestDescriptor.BatchWriterQueryOperationTestDescriptor;

            if (queryOperation != null)
            {
                // query operations don't specify content
                expectedContent = null;
            }
            else
            {
                var changeSetOperation = operationDescriptor as BatchWriterTestDescriptor.BatchWriterChangeSetOperationTestDescriptor;
                if (changeSetOperation != null)
                {
                    if (changeSetOperation.Payload != null)
                    {
                        Debug.Assert(changeSetOperation.ODataPayload == null, "changeSetOperation.ODataPayload == null");
                        expectedContent = changeSetOperation.Payload;
                        expectedContent = StringUtils.ResolveVariables(expectedContent, variables);
                    }
                    else if (changeSetOperation.ODataPayload != null)
                    {
                        Debug.Assert(changeSetOperation.Payload == null, "changeSetOperation.Payload == null");
                        if (changeSetOperation.ODataPayload.WriterTestExpectedResults != null)
                        {
                            comparer = GetComparerForWriterTestExpectedResults(changeSetOperation.ODataPayload);
                        }
                        else
                        {
                            expectedContent = changeSetOperation.ODataPayload.ExpectedResult;
                            if (changeSetOperation.ODataPayload.TestConfiguration.Format == ODataFormat.Atom)
                            {
                                expectedContent = XmlUtils.GetComparableXmlString(expectedContent, variables, indent);
                                normalizer      = (observed) => XmlUtils.GetComparableXmlString(observed, null, indent);
                            }
                            else if (changeSetOperation.ODataPayload.TestConfiguration.Format == ODataFormat.Json)
                            {
                                expectedContent = JsonUtils.GetComparableJsonString(expectedContent, variables);
                            }
                            else
                            {
                                throw new NotSupportedException("Only ATOM and JSON formats are supported for batch payloads.");
                            }
                        }
                    }
                }
                else
                {
                    var responseOperation = operationDescriptor as BatchWriterTestDescriptor.BatchWriterResponseOperationTestDescriptor;
                    if (responseOperation != null)
                    {
                        if (responseOperation.Payload != null)
                        {
                            Debug.Assert(responseOperation.ODataPayload == null, "responsePart.ODataPayload == null");
                            expectedContent = responseOperation.Payload;
                            expectedContent = StringUtils.ResolveVariables(expectedContent, variables);
                        }
                        else if (responseOperation.ODataPayload != null)
                        {
                            Debug.Assert(responseOperation.Payload == null, "responsePart.Payload == null");
                            if (responseOperation.ODataPayload.WriterTestExpectedResults != null)
                            {
                                comparer = GetComparerForWriterTestExpectedResults(responseOperation.ODataPayload);
                            }
                            else
                            {
                                expectedContent = responseOperation.ODataPayload.ExpectedResult;
                                if (responseOperation.ODataPayload.TestConfiguration.Format == ODataFormat.Atom)
                                {
                                    expectedContent = XmlUtils.GetComparableXmlString(expectedContent, variables, indent);
                                    normalizer      = (observed) => XmlUtils.GetComparableXmlString(observed, null, indent);
                                }
                                else if (responseOperation.ODataPayload.TestConfiguration.Format == ODataFormat.Json)
                                {
                                    expectedContent = JsonUtils.GetComparableJsonString(expectedContent, variables);
                                }
                                else
                                {
                                    throw new NotSupportedException("Only ATOM and JSON formats are supported for batch payloads.");
                                }
                            }
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("Found unsupported operation descriptor of type " + operationDescriptor.GetType().FullName + ".");
                    }
                }
            }

            return((observedContent) =>
            {
                if (comparer != null)
                {
                    return comparer(observedContent);
                }

                if (normalizer != null)
                {
                    observedContent = normalizer(observedContent);
                }

                if (string.CompareOrdinal(expectedContent, observedContent) != 0)
                {
                    return string.Format(
                        "Different operation content.{0}Expected:{0}-->{1}<--{0}Actual:{0}-->{2}<--{0}",
                        Environment.NewLine,
                        expectedContent,
                        observedContent);
                }

                return null;
            });
        }