private void RunPropertyParsingTest(
            string jsonInput,
            ODataJsonLightDeserializer.PropertyParsingResult expectedPropertyParsingResult,
            string expectedName,
            Action<JsonReader, DuplicatePropertyNamesChecker> additionalVerification = null,
            Func<JsonReader, string, object> readPropertyAnnotationValue = null,
            DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = null)
        {
            if (duplicatePropertyNamesChecker == null)
            {
                duplicatePropertyNamesChecker = new DuplicatePropertyNamesChecker(false, true);
            }
            if (readPropertyAnnotationValue == null)
            {
                readPropertyAnnotationValue = (jsonReader, annotationName) => jsonReader.ReadPrimitiveValue();
            }

            using (ODataJsonLightInputContext inputContext = this.CreateJsonLightInputContext(jsonInput))
            {
                ODataJsonLightDeserializer deserializer = new ODataJsonLightPropertyAndValueDeserializer(inputContext);
                AdvanceReaderToFirstProperty(deserializer.JsonReader);

                deserializer.ProcessProperty(
                    duplicatePropertyNamesChecker,
                    (propertyName) => readPropertyAnnotationValue(deserializer.JsonReader, propertyName),
                    (propertyParsingResult, propertyName) =>
                    {
                        propertyParsingResult.Should().Be(expectedPropertyParsingResult, "parsing JSON object '{0}'", jsonInput);
                        propertyName.Should().Be(expectedName, "reported name is wrong for JSON object '{0}'", jsonInput);
                        if (additionalVerification != null)
                        {
                            additionalVerification(deserializer.JsonReader, duplicatePropertyNamesChecker);
                        }
                    });
            }
        }
        /// <summary>
        /// Detects the payload kind(s).
        /// </summary>
        /// <param name="detectionInfo">Additional information available for the payload kind detection.</param>
        /// <returns>An enumerable of zero, one or more payload kinds that were detected from looking at the payload in the message stream.</returns>
        private IEnumerable <ODataPayloadKind> DetectPayloadKindImplementation(ODataPayloadKindDetectionInfo detectionInfo)
        {
            Debug.Assert(detectionInfo != null, "detectionInfo != null");
            Debug.Assert(this.JsonReader.DisableInStreamErrorDetection, "The in-stream error detection should be disabled for payload kind detection.");

            this.AssertJsonCondition(JsonNodeType.Property, JsonNodeType.EndObject);

            // If we found a context URI and parsed it, look at the detected payload kind and return it.
            if (this.ContextUriParseResult != null)
            {
                // Store the parsed context URI on the input context so we can avoid parsing it again.
                detectionInfo.SetPayloadKindDetectionFormatState(new ODataJsonLightPayloadKindDetectionState(this.ContextUriParseResult));

                return(this.ContextUriParseResult.DetectedPayloadKinds);
            }

            // Otherwise this is a payload without context URI and we have to start sniffing; only error payloads
            // don't have a context URI so check for a single 'error' property (ignoring custom annotations).
            ODataError error = null;

            while (this.JsonReader.NodeType == JsonNodeType.Property)
            {
                string propertyName = this.JsonReader.ReadPropertyName();
                string annotatedPropertyName, annotationName;
                if (!ODataJsonLightDeserializer.TryParsePropertyAnnotation(propertyName, out annotatedPropertyName, out annotationName))
                {
                    if (ODataJsonLightReaderUtils.IsAnnotationProperty(propertyName))
                    {
                        if (propertyName != null && propertyName.StartsWith(JsonLightConstants.ODataPropertyAnnotationSeparatorChar + JsonLightConstants.ODataAnnotationNamespacePrefix, System.StringComparison.Ordinal))
                        {
                            // Any @odata.* instance annotations are not allowed for errors.
                            return(Enumerable.Empty <ODataPayloadKind>());
                        }
                        else
                        {
                            // Skip custom instance annotations
                            this.JsonReader.SkipValue();
                        }
                    }
                    else
                    {
                        if (string.CompareOrdinal(JsonLightConstants.ODataErrorPropertyName, propertyName) == 0)
                        {
                            // If we find multiple errors or an invalid error value, this is not an error payload.
                            if (error != null || !this.JsonReader.StartBufferingAndTryToReadInStreamErrorPropertyValue(out error))
                            {
                                return(Enumerable.Empty <ODataPayloadKind>());
                            }

                            // At this point we successfully read the first error property.
                            // Skip the error value and check whether there are more properties.
                            this.JsonReader.SkipValue();
                        }
                        else
                        {
                            // if it contains non-annotation property, it is not an error payload.
                            return(Enumerable.Empty <ODataPayloadKind>());
                        }
                    }
                }
                else
                {
                    // Property annotation
                    return(Enumerable.Empty <ODataPayloadKind>());
                }
            }

            // If we got here without finding a context URI or an error payload, we don't know what this is.
            if (error == null)
            {
                return(Enumerable.Empty <ODataPayloadKind>());
            }

            return(new ODataPayloadKind[] { ODataPayloadKind.Error });
        }