Beispiel #1
0
        public void StartBufferingAndTryToReadInStreamErrorPropertyValue_Works()
        {
            // Arrange
            const string payload =
                @"{""code"":"""",""message"":"""",""target"":""any target"","
                + @"""details"":[{""code"":""500"",""target"":""another target"",""message"":""any msg""}]}";
            var        stringReader = new StringReader(payload);
            var        innerReader  = new JsonReader(stringReader, false);
            var        jsonReader   = new BufferingJsonReader(innerReader, "any", 0);
            ODataError error;

            // Act
            jsonReader.Read();
            var result = jsonReader.StartBufferingAndTryToReadInStreamErrorPropertyValue(out error);

            // Assert
            Assert.True(result);
            Assert.Equal("any target", error.Target);
            Assert.Equal(1, error.Details.Count);
            var detail = error.Details.Single();

            Assert.Equal("500", detail.ErrorCode);
            Assert.Equal("another target", detail.Target);
            Assert.Equal("any msg", detail.Message);
        }
Beispiel #2
0
        public async Task ReadInStreamErrorPropertyAsync_SkipsNonSupportedPropertiesInErrorDetails()
        {
            // Arrange
            var payload = "{\"error\":{" +
                          $"\"code\":\"{ErrorCode}\"," +
                          $"\"message\":\"{ErrorMessage}\"," +
                          $"\"target\":\"{ErrorTarget}\"," +
                          $"\"details\":[{{\"code\":\"{ErrorDetailErrorCode}\",\"message\":\"{ErrorDetailErrorMessage}\",\"target\":null,\"foo\":\"bar\"}}]}}}}";

            var stringReader = new StringReader(payload);

            using (var jsonReader = new JsonReader(stringReader, false))
            {
                var bufferingReader = new BufferingJsonReader(jsonReader, "error", MaxInnerErrorDepth);

                // Act
                var exception = await Assert.ThrowsAsync <ODataErrorException>(
                    () => bufferingReader.ReadAsync());

                // Assert
                var error = exception.Error;
                Assert.NotNull(error);
                Assert.Null(error.InnerError);
                Assert.NotNull(error.Details);
                var errorDetail = Assert.Single(error.Details);
                Assert.Equal(ErrorDetailErrorCode, errorDetail.ErrorCode);
                Assert.Equal(ErrorDetailErrorMessage, errorDetail.Message);
                Assert.Null(errorDetail.Target);
            }
        }
        private static void AdvanceReaderToFirstPropertyValue(BufferingJsonReader bufferingJsonReader)
        {
            AdvanceReaderToFirstProperty(bufferingJsonReader);

            // Read over property name
            bufferingJsonReader.Read();
        }
Beispiel #4
0
        public async Task ReadODataResourceAsync()
        {
            // Arrange
            var payload = "{\"Customer\":{\"Id\":1,\"Name\":\"Sue\"}}";

            var stringReader = new StringReader(payload);

            using (var jsonReader = new JsonReader(stringReader, false))
            {
                var bufferingReader = new BufferingJsonReader(jsonReader, "any", MaxInnerErrorDepth);

                // Act
                await bufferingReader.ReadAsync();

                await bufferingReader.ReadStartObjectAsync();

                await bufferingReader.ReadPropertyNameAsync();

                var odataValue = await bufferingReader.ReadODataValueAsync();

                // Assert
                var resourceValue = Assert.IsType <ODataResourceValue>(odataValue);
                Assert.Equal(2, resourceValue.Properties.Count());
                var prop1 = resourceValue.Properties.First();
                var prop2 = resourceValue.Properties.Last();
                Assert.Equal("Id", prop1.Name);
                Assert.Equal(1, prop1.Value);
                Assert.Equal("Name", prop2.Name);
                Assert.Equal("Sue", prop2.Value);
            }
        }
Beispiel #5
0
        /// <summary>Constructor.</summary>
        /// <param name="format">The format for this input context.</param>
        /// <param name="reader">The reader to use.</param>
        /// <param name="contentType">The content type of the message to read.</param>
        /// <param name="messageReaderSettings">Configuration settings of the OData reader.</param>
        /// <param name="version">The OData protocol version to be used for reading the payload.</param>
        /// <param name="readingResponse">true if reading a response message; otherwise false.</param>
        /// <param name="synchronous">true if the input should be read synchronously; false if it should be read asynchronously.</param>
        /// <param name="model">The model to use.</param>
        /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs read from the payload.</param>
        /// <param name="payloadKindDetectionState">JSON Ligth specific state stored during payload kind detection (or null if no payload kind detection happened).</param>
        internal ODataJsonLightInputContext(
            ODataFormat format,
            TextReader reader,
            MediaType contentType,
            ODataMessageReaderSettings messageReaderSettings,
            ODataVersion version,
            bool readingResponse,
            bool synchronous,
            IEdmModel model,
            IODataUrlResolver urlResolver,
            ODataJsonLightPayloadKindDetectionState payloadKindDetectionState)
            : base(format, messageReaderSettings, version, readingResponse, synchronous, model, urlResolver)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(reader != null, "reader != null");
            Debug.Assert(contentType != null, "contentType != null");

            try
            {
                ExceptionUtils.CheckArgumentNotNull(format, "format");
                ExceptionUtils.CheckArgumentNotNull(messageReaderSettings, "messageReaderSettings");
            }
            catch (ArgumentNullException)
            {
                // Dispose the message stream if we failed to create the input context.
                reader.Dispose();
                throw;
            }

            try
            {
                this.textReader = reader;

                if (contentType.HasStreamingSetToTrue())
                {
                    this.jsonReader = new BufferingJsonReader(
                        this.textReader,
                        ODataAnnotationNames.ODataError,
                        messageReaderSettings.MessageQuotas.MaxNestingDepth,
                        ODataFormat.Json);
                }
                else
                {
                    // If we have a non-streaming Json Light content type we need to use the re-ordering Json reader
                    this.jsonReader = new ReorderingJsonReader(this.textReader, messageReaderSettings.MessageQuotas.MaxNestingDepth);
                }
            }
            catch (Exception e)
            {
                // Dispose the message stream if we failed to create the input context.
                if (ExceptionUtils.IsCatchableExceptionType(e) && reader != null)
                {
                    reader.Dispose();
                }

                throw;
            }

            this.payloadKindDetectionState = payloadKindDetectionState;
        }
 private static void AdvanceReaderToFirstProperty(BufferingJsonReader bufferingJsonReader)
 {
     // Read start and then over the object start.
     bufferingJsonReader.Read();
     bufferingJsonReader.Read();
     bufferingJsonReader.NodeType.Should().Be(JsonNodeType.Property);
 }
            /// <summary>
            /// Peeks and collects a raw annotation value from BufferingJsonReader.
            /// </summary>
            /// <param name="jsonReader">The BufferingJsonReader.</param>
            /// <param name="propertyName">The property name.</param>
            /// <param name="annotationName">The annotation name.</param>
            private void PeekAndCollectAnnotationRawJson(
                BufferingJsonReader jsonReader,
                string propertyName,
                string annotationName)
            {
                if (jsonReader.IsBuffering)
                {
                    return; // only need to collect annotation for not-buffering pass reading.
                }

                try
                {
                    jsonReader.StartBuffering();
                    if (jsonReader.NodeType == JsonNodeType.Property)
                    {
                        jsonReader.Read(); // read over annotation name
                    }

                    StringBuilder builder = new StringBuilder();
                    jsonReader.SkipValue(builder);
                    string annotationRawJson = builder.ToString();
                    this.AddPropertyAnnotationRawJson(propertyName, annotationName, annotationRawJson);
                }
                finally
                {
                    jsonReader.StopBuffering();
                }
            }
Beispiel #8
0
        public async Task ReadInStreamErrorPropertyAsync_SkipsNonSupportedPropertiesInInnerError()
        {
            // Arrange
            var payload = "{\"error\":{" +
                          $"\"code\":\"{ErrorCode}\"," +
                          $"\"message\":\"{ErrorMessage}\"," +
                          $"\"target\":\"{ErrorTarget}\"," +
                          "\"innererror\":{" +
                          $"\"type\":\"{InnerErrorTypeName}\"," +
                          $"\"message\":\"{InnerErrorMessage}\"," +
                          $"\"stacktrace\":\"{InnerErrorStackTrace}\"," +
                          "\"foo\":\"bar\"}}}";

            var stringReader = new StringReader(payload);

            using (var jsonReader = new JsonReader(stringReader, false))
            {
                var bufferingReader = new BufferingJsonReader(jsonReader, "error", MaxInnerErrorDepth);

                // Act
                var exception = await Assert.ThrowsAsync <ODataErrorException>(
                    () => bufferingReader.ReadAsync());

                // Assert
                var error = exception.Error;
                Assert.NotNull(error);
                var innerError = error.InnerError;
                Assert.NotNull(innerError);
                Assert.Equal(3, innerError.Properties.Count);
                Assert.Single(innerError.Properties.Where(d => d.Key.Equals("message")));
                Assert.Single(innerError.Properties.Where(d => d.Key.Equals("type")));
                Assert.Single(innerError.Properties.Where(d => d.Key.Equals("stacktrace")));
                Assert.Empty(innerError.Properties.Where(d => d.Key.Equals("foo")));
            }
        }
 private static void AdvanceReaderToFirstProperty(BufferingJsonReader bufferingJsonReader)
 {
     // Read start and then over the object start.
     bufferingJsonReader.Read();
     bufferingJsonReader.Read();
     Assert.Equal(JsonNodeType.Property, bufferingJsonReader.NodeType);
 }
Beispiel #10
0
        internal static void AssertBuffering(this BufferingJsonReader bufferedJsonReader)
        {
            DebugUtils.CheckNoExternalCallers();

#if DEBUG
            Debug.Assert(bufferedJsonReader.IsBuffering, "bufferedJsonReader.IsBuffering");
#endif
        }
 /// <summary>
 /// Tries to peek and collect a raw annotation value from BufferingJsonReader.
 /// </summary>
 /// <param name="jsonReader">The BufferingJsonReader.</param>
 /// <param name="propertyName">The property name.</param>
 /// <param name="annotationName">The annotation name.</param>
 public void TryPeekAndCollectAnnotationRawJson(
     BufferingJsonReader jsonReader,
     string propertyName,
     string annotationName)
 {
     if (this.shouldCollectAnnotation)
     {
         this.PeekAndCollectAnnotationRawJson(jsonReader, propertyName, annotationName);
     }
 }
Beispiel #12
0
        public async Task ReadInStreamErrorPropertyAsync_DoesNotThrowExceptionForUnintelligibleError(string payload)
        {
            // Arrange
            var stringReader = new StringReader(payload);

            using (var jsonReader = new JsonReader(stringReader, false))
            {
                var bufferingReader = new BufferingJsonReader(jsonReader, "error", MaxInnerErrorDepth);

                // Act & Assert
                Assert.True(await bufferingReader.ReadAsync());
            }
        }
        /// <summary>Constructor.</summary>
        /// <param name="textReader">The text reader to use.</param>
        /// <param name="messageInfo">The context information for the message.</param>
        /// <param name="messageReaderSettings">Configuration settings of the OData reader.</param>
        internal ODataJsonLightInputContext(
            TextReader textReader,
            ODataMessageInfo messageInfo,
            ODataMessageReaderSettings messageReaderSettings)
            : base(ODataFormat.Json, messageInfo, messageReaderSettings)
        {
            Debug.Assert(messageInfo.MediaType != null, "messageInfo.MediaType != null");

            try
            {
                this.textReader = textReader;
                var innerReader = CreateJsonReader(this.Container, this.textReader, messageInfo.MediaType.HasIeee754CompatibleSetToTrue());
                if (messageReaderSettings.ArrayPool != null)
                {
                    // make sure customer also can use reading setting if without DI.
                    JsonReader jsonReader = innerReader as JsonReader;
                    if (jsonReader != null && jsonReader.ArrayPool == null)
                    {
                        jsonReader.ArrayPool = messageReaderSettings.ArrayPool;
                    }
                }

                if (messageInfo.MediaType.HasStreamingSetToTrue())
                {
                    this.jsonReader = new BufferingJsonReader(
                        innerReader,
                        JsonLightConstants.ODataErrorPropertyName,
                        messageReaderSettings.MessageQuotas.MaxNestingDepth);
                }
                else
                {
                    // If we have a non-streaming Json Light content type we need to use the re-ordering Json reader
                    this.jsonReader = new ReorderingJsonReader(innerReader, messageReaderSettings.MessageQuotas.MaxNestingDepth);
                }
            }
            catch (Exception e)
            {
                // Dispose the message stream if we failed to create the input context.
                if (ExceptionUtils.IsCatchableExceptionType(e) && this.textReader != null)
                {
                    this.textReader.Dispose();
                }

                throw;
            }

            // don't know how to get MetadataDocumentUri uri here, messageReaderSettings do not have one
            // Uri metadataDocumentUri = messageReaderSettings..MetadataDocumentUri == null ? null : messageReaderSettings.MetadataDocumentUri.BaseUri;
            // the uri here is used here to create the FullMetadataLevel can pass null in
            this.metadataLevel = JsonLightMetadataLevel.Create(messageInfo.MediaType, null, this.Model, this.ReadingResponse);
        }
 /// <summary>
 /// Disposes the input context.
 /// </summary>
 protected override void DisposeImplementation()
 {
     try
     {
         if (this.textReader != null)
         {
             this.textReader.Dispose();
         }
     }
     finally
     {
         this.textReader = null;
         this.jsonReader = null;
     }
 }
Beispiel #15
0
        public async Task StartBufferingAndTryToReadInStreamErrorPropertyValueAsync_Works()
        {
            // Arrange
            var payload = "{" +
                          $"\"code\":\"{ErrorCode}\"," +
                          $"\"message\":\"{ErrorMessage}\"," +
                          $"\"target\":\"{ErrorTarget}\"," +
                          "\"innererror\":{" +
                          $"\"type\":\"{InnerErrorTypeName}\"," +
                          $"\"message\":\"{InnerErrorMessage}\"," +
                          $"\"stacktrace\":\"{InnerErrorStackTrace}\"," +
                          $"\"internalexception\":{{}}}}," +
                          $"\"details\":[{{\"code\":\"{ErrorDetailErrorCode}\",\"message\":\"{ErrorDetailErrorMessage}\",\"target\":null}}]}}";

            var stringReader = new StringReader(payload);

            using (var jsonReader = new JsonReader(stringReader, false))
            {
                var bufferingReader = new BufferingJsonReader(jsonReader, "other", MaxInnerErrorDepth);

                // Act
                var result1 = await bufferingReader.ReadAsync();

                var result2 = await bufferingReader.StartBufferingAndTryToReadInStreamErrorPropertyValueAsync();

                // Assert
                Assert.True(result1);
                Assert.True(result2.Item1);

                var error = result2.Item2;
                Assert.NotNull(error);
                Assert.Equal(ErrorCode, error.ErrorCode);
                Assert.Equal(ErrorMessage, error.Message);
                Assert.Equal(ErrorTarget, error.Target);
                var innerError = error.InnerError;
                Assert.NotNull(innerError);
                Assert.Equal(InnerErrorMessage, innerError.Message);
                Assert.Equal(InnerErrorTypeName, innerError.TypeName);
                Assert.Equal(InnerErrorStackTrace.Replace("\\\\", "\\"), innerError.StackTrace);
                Assert.NotNull(innerError.InnerError);
                Assert.NotNull(error.Details);
                var errorDetail = Assert.Single(error.Details);
                Assert.Equal(ErrorDetailErrorCode, errorDetail.ErrorCode);
                Assert.Equal(ErrorDetailErrorMessage, errorDetail.Message);
                Assert.Null(errorDetail.Target);
            }
        }
Beispiel #16
0
        public async Task CanStreamAsync_ForReaderNotInBufferingState(string payload, bool expected)
        {
            var stringReader = new StringReader(string.Format("{{\"Data\":{0}}}", payload));

            using (var jsonReader = new JsonReader(stringReader, false))
            {
                var bufferingReader = new BufferingJsonReader(jsonReader, "any", MaxInnerErrorDepth);

                await bufferingReader.ReadAsync();

                await bufferingReader.ReadStartObjectAsync();

                await bufferingReader.ReadPropertyNameAsync();

                Assert.Equal(expected, await bufferingReader.CanStreamAsync());
            }
        }
Beispiel #17
0
 internal ODataJsonInputContext(ODataFormat format, TextReader reader, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool readingResponse, bool synchronous, IEdmModel model, IODataUrlResolver urlResolver) : base(format, messageReaderSettings, version, readingResponse, synchronous, model, urlResolver)
 {
     ExceptionUtils.CheckArgumentNotNull<ODataFormat>(format, "format");
     ExceptionUtils.CheckArgumentNotNull<ODataMessageReaderSettings>(messageReaderSettings, "messageReaderSettings");
     try
     {
         this.textReader = reader;
         this.jsonReader = new BufferingJsonReader(this.textReader, base.UseServerFormatBehavior, messageReaderSettings.MessageQuotas.MaxNestingDepth);
     }
     catch (Exception exception)
     {
         if (ExceptionUtils.IsCatchableExceptionType(exception) && (reader != null))
         {
             reader.Dispose();
         }
         throw;
     }
 }
Beispiel #18
0
        public async Task ReadInStreamErrorPropertyAsync_ThrowsExceptionForODataErrorRead()
        {
            // Arrange
            var payload = "{\"error\":{" +
                          $"\"code\":\"{ErrorCode}\"," +
                          $"\"message\":\"{ErrorMessage}\"," +
                          $"\"target\":\"{ErrorTarget}\"," +
                          "\"innererror\":{" +
                          $"\"type\":\"{InnerErrorTypeName}\"," +
                          $"\"message\":\"{InnerErrorMessage}\"," +
                          $"\"stacktrace\":\"{InnerErrorStackTrace}\"," +
                          $"\"internalexception\":{{}}}}," +
                          $"\"details\":[{{\"code\":\"{ErrorDetailErrorCode}\",\"message\":\"{ErrorDetailErrorMessage}\",\"target\":null}}]}}}}";

            var stringReader = new StringReader(payload);

            using (var jsonReader = new JsonReader(stringReader, false))
            {
                var bufferingReader = new BufferingJsonReader(jsonReader, "error", MaxInnerErrorDepth);

                // Act
                var exception = await Assert.ThrowsAsync <ODataErrorException>(
                    () => bufferingReader.ReadAsync());

                // Assert
                var error = exception.Error;
                Assert.NotNull(error);
                Assert.Equal(ErrorCode, error.ErrorCode);
                Assert.Equal(ErrorMessage, error.Message);
                Assert.Equal(ErrorTarget, error.Target);
                var innerError = error.InnerError;
                Assert.NotNull(innerError);
                Assert.Equal(InnerErrorMessage, innerError.Message);
                Assert.Equal(InnerErrorTypeName, innerError.TypeName);
                Assert.Equal(InnerErrorStackTrace.Replace("\\\\", "\\"), innerError.StackTrace);
                Assert.NotNull(innerError.InnerError);
                Assert.NotNull(error.Details);
                var errorDetail = Assert.Single(error.Details);
                Assert.Equal(ErrorDetailErrorCode, errorDetail.ErrorCode);
                Assert.Equal(ErrorDetailErrorMessage, errorDetail.Message);
                Assert.Null(errorDetail.Target);
            }
        }
        /// <summary>
        /// Perform the actual cleanup work.
        /// </summary>
        /// <param name="disposing">If 'true' this method is called from user code; if 'false' it is called by the runtime.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                try
                {
                    if (this.textReader != null)
                    {
                        this.textReader.Dispose();
                    }
                }
                finally
                {
                    this.textReader = null;
                    this.jsonReader = null;
                }
            }

            base.Dispose(disposing);
        }
        /// <summary>Constructor.</summary>
        /// <param name="format">The format for this input context.</param>
        /// <param name="reader">The reader to read data from.</param>
        /// <param name="messageReaderSettings">Configuration settings of the OData reader.</param>
        /// <param name="version">The OData protocol version to be used for reading the payload.</param>
        /// <param name="readingResponse">true if reading a response message; otherwise false.</param>
        /// <param name="synchronous">true if the input should be read synchronously; false if it should be read asynchronously.</param>
        /// <param name="model">The model to use.</param>
        /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs read from the payload.</param>
        internal ODataVerboseJsonInputContext(
            ODataFormat format,
            TextReader reader,
            ODataMessageReaderSettings messageReaderSettings,
            ODataVersion version,
            bool readingResponse,
            bool synchronous,
            IEdmModel model,
            IODataUrlResolver urlResolver)
            : base(format, messageReaderSettings, version, readingResponse, synchronous, model, urlResolver)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(reader != null, "reader != null");

            try
            {
                ExceptionUtils.CheckArgumentNotNull(format, "format");
                ExceptionUtils.CheckArgumentNotNull(messageReaderSettings, "messageReaderSettings");

                this.textReader = reader;
                if (this.UseServerFormatBehavior)
                {
                    this.jsonReader = new PropertyDeduplicatingJsonReader(this.textReader, messageReaderSettings.MessageQuotas.MaxNestingDepth);
                }
                else
                {
                    this.jsonReader = new BufferingJsonReader(this.textReader, JsonConstants.ODataErrorName, messageReaderSettings.MessageQuotas.MaxNestingDepth, ODataFormat.VerboseJson);
                }
            }
            catch (Exception e)
            {
                // Dispose the message stream if we failed to create the input context.
                if (ExceptionUtils.IsCatchableExceptionType(e) && reader != null)
                {
                    reader.Dispose();
                }

                throw;
            }
        }
Beispiel #21
0
        internal static void AssertBuffering(this BufferingJsonReader bufferedJsonReader)
        {
#if DEBUG
            Debug.Assert(bufferedJsonReader.IsBuffering, "bufferedJsonReader.IsBuffering");
#endif
        }
Beispiel #22
0
 protected override void DisposeImplementation()
 {
     try
     {
         if (this.textReader != null)
         {
             this.textReader.Dispose();
         }
     }
     finally
     {
         this.textReader = null;
         this.jsonReader = null;
     }
 }
        internal ODataJsonLightInputContext(
            ODataFormat format,
            TextReader reader,
            MediaType contentType,
            ODataMessageReaderSettings messageReaderSettings,
            ODataVersion version,
            bool readingResponse,
            bool synchronous,
            IEdmModel model,
            IODataUrlResolver urlResolver,
            ODataJsonLightPayloadKindDetectionState payloadKindDetectionState)
            : base(format, messageReaderSettings, version, readingResponse, synchronous, model, urlResolver)
        {
            Debug.Assert(reader != null, "reader != null");
            Debug.Assert(contentType != null, "contentType != null");

            try
            {
                ExceptionUtils.CheckArgumentNotNull(format, "format");
                ExceptionUtils.CheckArgumentNotNull(messageReaderSettings, "messageReaderSettings");
            }
            catch (ArgumentNullException)
            {
                // Dispose the message stream if we failed to create the input context.
                reader.Dispose();
                throw;
            }

            try
            {
                this.textReader = reader;

                if (contentType.HasStreamingSetToTrue())
                {
                    this.jsonReader = new BufferingJsonReader(
                        this.textReader,
                        JsonLightConstants.ODataErrorPropertyName,
                        messageReaderSettings.MessageQuotas.MaxNestingDepth,
                        ODataFormat.Json,
                        contentType.HasIeee754CompatibleSetToTrue());
                }
                else
                {
                    // If we have a non-streaming Json Light content type we need to use the re-ordering Json reader
                    this.jsonReader = new ReorderingJsonReader(this.textReader, messageReaderSettings.MessageQuotas.MaxNestingDepth, contentType.HasIeee754CompatibleSetToTrue());
                }
            }
            catch (Exception e)
            {
                // Dispose the message stream if we failed to create the input context.
                if (ExceptionUtils.IsCatchableExceptionType(e) && reader != null)
                {
                    reader.Dispose();
                }

                throw;
            }

            this.payloadKindDetectionState = payloadKindDetectionState;

            // dont know how to get MetadataDocumentUri uri here, messageReaderSettings do not have one
            // Uri metadataDocumentUri = messageReaderSettings..MetadataDocumentUri == null ? null : messageReaderSettings.MetadataDocumentUri.BaseUri;
            // the uri here is used here to create the FullMetadataLevel can pass null in
            this.metadataLevel = JsonLight.JsonLightMetadataLevel.Create(contentType, null, model, readingResponse);
        }