Exemple #1
0
 protected void EnterScope(ODataParameterReaderState state, string name, object value)
 {
     if (((state == ODataParameterReaderState.Value) && (value != null)) && (!(value is ODataComplexValue) && !EdmLibraryExtensions.IsPrimitiveType(value.GetType())))
     {
         throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ODataParameterReaderCore_ValueMustBePrimitiveOrComplexOrNull));
     }
     if ((this.scopes.Count == 0) || (this.State != ODataParameterReaderState.Exception))
     {
         if (state == ODataParameterReaderState.Completed)
         {
             List <string> list = new List <string>();
             foreach (IEdmFunctionParameter parameter in this.FunctionImport.Parameters.Skip <IEdmFunctionParameter>(this.FunctionImport.IsBindable ? 1 : 0))
             {
                 if (!this.parametersRead.Contains(parameter.Name))
                 {
                     list.Add(parameter.Name);
                 }
             }
             if (list.Count > 0)
             {
                 this.scopes.Push(new Scope(ODataParameterReaderState.Exception, null, null));
                 throw new ODataException(Microsoft.Data.OData.Strings.ODataParameterReaderCore_ParametersMissingInPayload(this.FunctionImport.Name, string.Join(",", list.ToArray())));
             }
         }
         this.scopes.Push(new Scope(state, name, value));
     }
 }
        public override bool Read()
        {
            switch (this.State)
            {
                case ODataParameterReaderState.Start:
                    if (!this.inputContext.AvroReader.MoveNext())
                    {
                        this.state = ODataParameterReaderState.Completed;
                        return false;
                    }

                    this.avroRecord = this.inputContext.AvroReader.Current as AvroRecord;
                    if (this.avroRecord == null)
                    {
                        this.state = ODataParameterReaderState.Exception;
                        return false;
                    }

                    this.enumerator = this.avroRecord.Schema.Fields.GetEnumerator();
                    return this.UpdateState();
                case ODataParameterReaderState.Value:
                case ODataParameterReaderState.Entry:
                case ODataParameterReaderState.Feed:
                    return this.UpdateState();
                default:
                    throw new ApplicationException("Invalid state " + this.State);
            }
        }
Exemple #3
0
        /// <summary>
        /// Creates a new <see cref="Scope"/> for the specified <paramref name="state"/> with the provided
        /// <paramref name="name"/> and <paramref name="value"/> and pushes it on the stack of scopes.
        /// </summary>
        /// <param name="state">The <see cref="ODataParameterReaderState"/> to use for the new scope.</param>
        /// <param name="name">The parameter name to attach with the state in the new scope.</param>
        /// <param name="value">The parameter value to attach with the state in the new scope.</param>
        protected internal void EnterScope(ODataParameterReaderState state, string name, object value)
        {
            if (state == ODataParameterReaderState.Value)
            {
                if (value != null && !EdmLibraryExtensions.IsPrimitiveType(value.GetType()) && !(value is ODataEnumValue))
                {
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataParameterReaderCore_ValueMustBePrimitiveOrNull));
                }
            }

            Debug.Assert(this.scopes.Count == 0 || this.State != ODataParameterReaderState.Exception || state == ODataParameterReaderState.Exception, "If the reader is already in Exception state, we shouldn't call EnterScope() except for another Exception.");

            // We only need to enter the exception state once.
            if (this.scopes.Count == 0 || this.State != ODataParameterReaderState.Exception)
            {
                Debug.Assert(
                    state == ODataParameterReaderState.Exception ||
                    state == ODataParameterReaderState.Start && this.scopes.Count == 0 ||
                    state == ODataParameterReaderState.Completed && this.scopes.Count == 0 ||
                    this.scopes.Count == 1 && this.scopes.Peek().State == ODataParameterReaderState.Start,
                    "Unexpected state in the scopes stack.");

                // Make sure there aren't any missing parameter in the payload.
                if (state == ODataParameterReaderState.Completed)
                {
                    List <string> missingParameters = new List <string>();

                    // Note that the binding parameter will be specified on the Uri rather than the payload, skip the binding parameter.
                    foreach (IEdmOperationParameter parameter in this.Operation.Parameters.Skip(this.Operation.IsBound ? 1 : 0))
                    {
                        // only check the non-optional parameter
                        if (!(parameter is IEdmOptionalParameter))
                        {
                            if (!this.parametersRead.Contains(parameter.Name) && !this.inputContext.EdmTypeResolver.GetParameterType(parameter).IsNullable)
                            {
                                missingParameters.Add(parameter.Name);
                            }
                        }
                    }

                    if (missingParameters.Count > 0)
                    {
                        this.scopes.Push(new Scope(ODataParameterReaderState.Exception, null, null));
                        throw new ODataException(Strings.ODataParameterReaderCore_ParametersMissingInPayload(this.Operation.Name, string.Join(",", missingParameters.ToArray())));
                    }
                }
                else if (name != null)
                {
                    // Record the parameter names we read and check for duplicates.
                    if (this.parametersRead.Contains(name))
                    {
                        throw new ODataException(Strings.ODataParameterReaderCore_DuplicateParametersInPayload(name));
                    }

                    this.parametersRead.Add(name);
                }

                this.scopes.Push(new Scope(state, name, value));
            }
        }
        public override bool Read()
        {
            switch (this.State)
            {
            case ODataParameterReaderState.Start:
                if (!this.inputContext.AvroReader.MoveNext())
                {
                    this.state = ODataParameterReaderState.Completed;
                    return(false);
                }

                this.avroRecord = this.inputContext.AvroReader.Current as AvroRecord;
                if (this.avroRecord == null)
                {
                    this.state = ODataParameterReaderState.Exception;
                    return(false);
                }

                this.enumerator = this.avroRecord.Schema.Fields.GetEnumerator();
                return(this.UpdateState());

            case ODataParameterReaderState.Value:
            case ODataParameterReaderState.Resource:
            case ODataParameterReaderState.ResourceSet:
                return(this.UpdateState());

            default:
                throw new ApplicationException("Invalid state " + this.State);
            }
        }
        protected internal void PopScope(ODataParameterReaderState state)
        {
            Debug.Assert(this.scopes.Count > 0, "Stack must have more than 1 items in order to pop an item.");

            Scope scope = this.scopes.Pop();

            Debug.Assert(scope.State == state, "scope.State == state");
        }
        public ODataAvroParameterReader(ODataAvroInputContext inputContext, IEdmOperation operation)
        {
            Debug.Assert(inputContext != null, "inputContext != null");
            Debug.Assert(operation != null, "operation != null");

            this.inputContext = inputContext;
            this.operation    = operation;
            this.state        = ODataParameterReaderState.Start;
        }
        public ODataAvroParameterReader(ODataAvroInputContext inputContext, IEdmOperation operation)
        {
            Debug.Assert(inputContext != null, "inputContext != null");
            Debug.Assert(operation != null, "operation != null");

            this.inputContext = inputContext;
            this.operation = operation;
            this.state = ODataParameterReaderState.Start;
        }
        /// <summary>
        /// Gets the corresponding create reader method name for the given state.
        /// </summary>
        /// <param name="state">State in question.</param>
        /// <returns>Returns the name of the method to create the correct reader for the given state.</returns>
        private static string GetCreateReaderMethodName(ODataParameterReaderState state)
        {
#if SUPPORT_ENTITY_PARAMETER
            Debug.Assert(state == ODataParameterReaderState.Entry || state == ODataParameterReaderState.Feed || state == ODataParameterReaderState.Collection, "state must be Entry, Feed or Collection.");
#else
            Debug.Assert(state == ODataParameterReaderState.Collection, "state must be Collection.");
#endif
            return("Create" + state.ToString() + "Reader");
        }
Exemple #9
0
 private void VerifyCanCreateSubReader(ODataParameterReaderState expectedState)
 {
     this.inputContext.VerifyNotDisposed();
     if (this.State != expectedState)
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ODataParameterReaderCore_InvalidCreateReaderMethodCalledForState(GetCreateReaderMethodName(expectedState), this.State));
     }
     if (this.subReaderState != SubReaderState.None)
     {
         throw new ODataException(Microsoft.Data.OData.Strings.ODataParameterReaderCore_CreateReaderAlreadyCalled(GetCreateReaderMethodName(expectedState), this.Name));
     }
 }
Exemple #10
0
        private void RunParameterReaderErrorTest(
            ODataParameterReaderTestWrapper reader,
            ExpectedException expectedException,
            ODataParameterReaderState expectedState = ODataParameterReaderState.Exception)
        {
            if (reader == null)
            {
                // Reader creation failed and we verified the exception already
                return;
            }

            this.Assert.ExpectedException(() => reader.Read(), expectedException, this.ExceptionVerifier);
            this.Assert.AreEqual(expectedState, reader.State, "Reader should be in '" + expectedState.ToString() + "' state.");
        }
        /// <summary>
        /// Verifies that one of CreateEntryReader(), CreateFeedReader() or CreateCollectionReader() can be called.
        /// </summary>
        /// <param name="expectedState">The expected state of the reader.</param>
        private void VerifyCanCreateSubReader(ODataParameterReaderState expectedState)
        {
            this.inputContext.VerifyNotDisposed();
            if (this.State != expectedState)
            {
                throw new ODataException(Strings.ODataParameterReaderCore_InvalidCreateReaderMethodCalledForState(ODataParameterReaderCore.GetCreateReaderMethodName(expectedState), this.State));
            }

            if (this.subReaderState != SubReaderState.None)
            {
                Debug.Assert(this.Name != null, "this.Name != null");
                throw new ODataException(Strings.ODataParameterReaderCore_CreateReaderAlreadyCalled(ODataParameterReaderCore.GetCreateReaderMethodName(expectedState), this.Name));
            }
        }
Exemple #12
0
            /// <summary>
            /// Constructor creating a new reader scope.
            /// </summary>
            /// <param name="state">The reader state of this scope.</param>
            /// <param name="name">The parameter name attached to this scope.</param>
            /// <param name="value">The parameter value attached to this scope.</param>
            public Scope(ODataParameterReaderState state, string name, object value)
            {
                Debug.Assert(
                    state == ODataParameterReaderState.Start && name == null && value == null ||
                    state == ODataParameterReaderState.Value && !string.IsNullOrEmpty(name) && (value == null || value is ODataEnumValue || EdmLibraryExtensions.IsPrimitiveType(value.GetType())) ||
                    state == ODataParameterReaderState.Resource && !string.IsNullOrEmpty(name) && value == null ||
                    state == ODataParameterReaderState.ResourceSet && !string.IsNullOrEmpty(name) && value == null ||
                    state == ODataParameterReaderState.Collection && !string.IsNullOrEmpty(name) && value == null ||
                    state == ODataParameterReaderState.Exception && name == null && value == null ||
                    state == ODataParameterReaderState.Completed && name == null && value == null,
                    "Reader state and associated item do not match.");

                this.state = state;
                this.name  = name;
                this.value = value;
            }
        /// <summary>
        /// Creates a new <see cref="Scope"/> for the specified <paramref name="state"/> with the provided
        /// <paramref name="name"/> and <paramref name="value"/> and pushes it on the stack of scopes.
        /// </summary>
        /// <param name="state">The <see cref="ODataParameterReaderState"/> to use for the new scope.</param>
        /// <param name="name">The paramter name to attach with the state in the new scope.</param>
        /// <param name="value">The paramter value to attach with the state in the new scope.</param>
        protected void EnterScope(ODataParameterReaderState state, string name, object value)
        {
            if (state == ODataParameterReaderState.Value)
            {
                if (value != null && !(value is ODataComplexValue) && !EdmLibraryExtensions.IsPrimitiveType(value.GetType()))
                {
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataParameterReaderCore_ValueMustBePrimitiveOrComplexOrNull));
                }
            }

            Debug.Assert(this.scopes.Count == 0 || this.State != ODataParameterReaderState.Exception || state == ODataParameterReaderState.Exception, "If the reader is already in Exception state, we shouldn't call EnterScope() except for another Exception.");

            // We only need to enter the exception state once.
            if (this.scopes.Count == 0 || this.State != ODataParameterReaderState.Exception)
            {
                Debug.Assert(
                    state == ODataParameterReaderState.Exception ||
                    state == ODataParameterReaderState.Start && this.scopes.Count == 0 ||
                    state == ODataParameterReaderState.Completed && this.scopes.Count == 0 ||
                    this.scopes.Count == 1 && this.scopes.Peek().State == ODataParameterReaderState.Start,
                    "Unexpected state in the scopes stack.");

                // Make sure there aren't any missing parameter in the payload.
                if (state == ODataParameterReaderState.Completed)
                {
                    List <string> missingParameters = new List <string>();

                    // Note that the binding parameter will be specified on the Uri rather than the payload, skip the binding parameter.
                    foreach (IEdmFunctionParameter parameter in this.FunctionImport.Parameters.Skip(this.FunctionImport.IsBindable ? 1 : 0))
                    {
                        if (!this.parametersRead.Contains(parameter.Name) && !parameter.Type.IsNullable)
                        {
                            missingParameters.Add(parameter.Name);
                        }
                    }

                    if (missingParameters.Count > 0)
                    {
                        this.scopes.Push(new Scope(ODataParameterReaderState.Exception, null, null));
                        throw new ODataException(Strings.ODataParameterReaderCore_ParametersMissingInPayload(this.FunctionImport.Name, string.Join(",", missingParameters.ToArray())));
                    }
                }

                this.scopes.Push(new Scope(state, name, value));
            }
        }
Exemple #14
0
        private bool UpdateState()
        {
            if (!this.enumerator.MoveNext())
            {
                this.state = ODataParameterReaderState.Completed;
                return(false);
            }

            var parameter = this.operation.Parameters.SingleOrDefault(para => para.Name == this.enumerator.Current.Name);

            if (parameter == null)
            {
                throw new ApplicationException("Given parameter name " + this.enumerator.Current.Name + " not found.");
            }

            this.name  = parameter.Name;
            this.value = this.avroRecord[this.enumerator.Current.Position];
            if (this.value is AvroRecord)
            {
                if (parameter.Type.Definition is IEdmComplexType)
                {
                    this.value = ODataAvroConvert.ToODataComplexValue((AvroRecord)this.value);
                    this.state = ODataParameterReaderState.Value;
                }
                else if (parameter.Type.Definition is IEdmEntityType)
                {
                    this.state = ODataParameterReaderState.Entry;
                }
                else
                {
                    this.state = ODataParameterReaderState.Exception;
                    return(false);
                }
            }
            else if (this.value is Array && !(this.value is byte[]))
            {
                this.state = ODataParameterReaderState.Feed;
            }
            else
            {
                this.state = ODataParameterReaderState.Value;
            }

            return(true);
        }
            /// <summary>
            /// Constructor creating a new reader scope.
            /// </summary>
            /// <param name="state">The reader state of this scope.</param>
            /// <param name="name">The parameter name attached to this scope.</param>
            /// <param name="value">The parameter value attached to this scope.</param>
            public Scope(ODataParameterReaderState state, string name, object value)
            {
                Debug.Assert(
                    state == ODataParameterReaderState.Start && name == null && value == null ||
                    state == ODataParameterReaderState.Value && !string.IsNullOrEmpty(name) && (value == null || value is ODataComplexValue || EdmLibraryExtensions.IsPrimitiveType(value.GetType())) ||
#if SUPPORT_ENTITY_PARAMETER
                    state == ODataParameterReaderState.Entry && !string.IsNullOrEmpty(name) && value == null ||
                    state == ODataParameterReaderState.Feed && !string.IsNullOrEmpty(name) && value == null ||
#endif
                    state == ODataParameterReaderState.Collection && !string.IsNullOrEmpty(name) && value == null ||
                    state == ODataParameterReaderState.Exception && name == null && value == null ||
                    state == ODataParameterReaderState.Completed && name == null && value == null,
                    "Reader state and associated item do not match.");

                this.state = state;
                this.name  = name;
                this.value = value;
            }
        private void RunParameterReaderErrorTest(
            ODataParameterReaderTestWrapper reader,
            ExpectedException expectedException,
            ODataParameterReaderState expectedState = ODataParameterReaderState.Exception)
        {
            if (reader == null)
            {
                // Reader creation failed and we verified the exception already
                return;
            }

            this.Assert.ExpectedException(() => reader.Read(), expectedException, this.ExceptionVerifier);
            this.Assert.AreEqual(expectedState, reader.State, "Reader should be in '" + expectedState.ToString() + "' state.");
        }
        private bool UpdateState()
        {
            if (!this.enumerator.MoveNext())
            {
                this.state = ODataParameterReaderState.Completed;
                return false;
            }

            var parameter = this.operation.Parameters.SingleOrDefault(para => para.Name == this.enumerator.Current.Name);
            if (parameter == null)
            {
                throw new ApplicationException("Given parameter name " + this.enumerator.Current.Name + " not found.");
            }

            this.name = parameter.Name;
            this.value = this.avroRecord[this.enumerator.Current.Position];
            if (this.value is AvroRecord)
            {
                if (parameter.Type.Definition is IEdmComplexType)
                {
                    this.value = ODataAvroConvert.ToODataComplexValue((AvroRecord)this.value);
                    this.state = ODataParameterReaderState.Value;
                }
                else if (parameter.Type.Definition is IEdmEntityType)
                {
                    this.state = ODataParameterReaderState.Entry;
                }
                else
                {
                    this.state = ODataParameterReaderState.Exception;
                    return false;
                }
            }
            else if (this.value is Array && !(this.value is byte[]))
            {
                this.state = ODataParameterReaderState.Feed;
            }
            else
            {
                this.state = ODataParameterReaderState.Value;
            }

            return true;
        }
Exemple #18
0
 /// <summary>
 /// Gets the corresponding create reader method name for the given state.
 /// </summary>
 /// <param name="state">State in question.</param>
 /// <returns>Returns the name of the method to create the correct reader for the given state.</returns>
 private static string GetCreateReaderMethodName(ODataParameterReaderState state)
 {
     Debug.Assert(state == ODataParameterReaderState.Entry || state == ODataParameterReaderState.Feed || state == ODataParameterReaderState.Collection, "state must be Entry, Feed or Collection.");
     return("Create" + state.ToString() + "Reader");
 }
Exemple #19
0
 protected void PopScope(ODataParameterReaderState state)
 {
     this.scopes.Pop();
 }
Exemple #20
0
 /// <summary>
 /// Gets the corresponding create reader method name for the given state.
 /// </summary>
 /// <param name="state">State in question.</param>
 /// <returns>Returns the name of the method to create the correct reader for the given state.</returns>
 private static string GetCreateReaderMethodName(ODataParameterReaderState state)
 {
     Debug.Assert(state == ODataParameterReaderState.Resource || state == ODataParameterReaderState.ResourceSet || state == ODataParameterReaderState.Collection, "state must be Resource, ResourceSet or Collection.");
     return("Create" + state.ToString() + "Reader");
 }
Exemple #21
0
 public Scope(ODataParameterReaderState state, string name, object value)
 {
     this.state = state;
     this.name  = name;
     this.value = value;
 }
Exemple #22
0
 private static string GetCreateReaderMethodName(ODataParameterReaderState state)
 {
     return("Create" + state.ToString() + "Reader");
 }
Exemple #23
0
        public void ParameterReaderCreateReaderStateMachineTests()
        {
            IEdmModel           model = TestModels.BuildModelWithFunctionImport();
            IEdmOperationImport functionImport_Primitive           = model.FindEntityContainer("TestContainer").FindOperationImports("FunctionImport_Primitive").First();
            IEdmOperationImport functionImport_PrimitiveCollection = model.FindEntityContainer("TestContainer").FindOperationImports("FunctionImport_PrimitiveCollection").First();
            IEdmOperationImport functionImport_Complex             = model.FindEntityContainer("TestContainer").FindOperationImports("FunctionImport_Complex").First();
            IEdmOperationImport functionImport_ComplexCollection   = model.FindEntityContainer("TestContainer").FindOperationImports("FunctionImport_ComplexCollection").First();
            IEdmOperationImport functionImport_Entry = model.FindEntityContainer("TestContainer").FindOperationImports("FunctionImport_Entry").First();
            IEdmOperationImport functionImport_Feed  = model.FindEntityContainer("TestContainer").FindOperationImports("FunctionImport_Feed").First();

            CreateReaderMethods[] createReaderMethods = new CreateReaderMethods[]
            {
                CreateReaderMethods.CreateCollectionReader,
            };

            var testConfigurations = this.ReaderTestConfigurationProvider.JsonLightFormatConfigurations.Where(c => c.IsRequest);

            this.CombinatorialEngineProvider.RunCombinations(
                testConfigurations,
                createReaderMethods,
                (testConfiguration, createReaderMethod) =>
            {
                // Calling Create*Reader in Start state should fail.
                ODataParameterReader reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport_Complex, testConfiguration, "{ complex : { PrimitiveProperty : \"456\" } }");
                this.Assert.ExpectedException(
                    () => CreateSubReader(reader, createReaderMethod),
                    ODataExpectedExceptions.ODataException("ODataParameterReaderCore_InvalidCreateReaderMethodCalledForState", createReaderMethod.ToString(), ODataParameterReaderState.Start.ToString()), this.ExceptionVerifier);
                this.Assert.AreEqual(ODataParameterReaderState.Start, reader.State, "Unexpected parameter reader state.");

                // Calling Create*Reader in Value state should fail.
                reader.Read();
                this.Assert.AreEqual(ODataParameterReaderState.Resource, reader.State, "Unexpected parameter reader state.");
                this.Assert.ExpectedException(
                    () => CreateSubReader(reader, createReaderMethod),
                    ODataExpectedExceptions.ODataException("ODataParameterReaderCore_InvalidCreateReaderMethodCalledForState", createReaderMethod.ToString(), ODataParameterReaderState.Resource.ToString()), this.ExceptionVerifier);
                this.Assert.AreEqual(ODataParameterReaderState.Resource, reader.State, "Unexpected parameter reader state.");

                if (createReaderMethod != CreateReaderMethods.CreateResourceReader)
                {
                    // Calling Create*Reader in Entry state should fail.
                    reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport_Entry, testConfiguration, "{ entry : {} }");
                    reader.Read();
                    this.Assert.AreEqual(ODataParameterReaderState.Resource, reader.State, "Unexpected parameter reader state.");
                    this.Assert.ExpectedException(
                        () => CreateSubReader(reader, createReaderMethod),
                        ODataExpectedExceptions.ODataException("ODataParameterReaderCore_InvalidCreateReaderMethodCalledForState", createReaderMethod.ToString(), ODataParameterReaderState.Resource.ToString()), this.ExceptionVerifier);
                    this.Assert.AreEqual(ODataParameterReaderState.Resource, reader.State, "Unexpected parameter reader state.");
                }

                if (createReaderMethod != CreateReaderMethods.CreateResourceSetReader)
                {
                    // Calling Create*Reader in Feed state should fail.
                    reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport_Feed, testConfiguration, "{ feed : [] }");
                    reader.Read();
                    this.Assert.AreEqual(ODataParameterReaderState.ResourceSet, reader.State, "Unexpected parameter reader state.");
                    this.Assert.ExpectedException(
                        () => CreateSubReader(reader, createReaderMethod),
                        ODataExpectedExceptions.ODataException("ODataParameterReaderCore_InvalidCreateReaderMethodCalledForState", createReaderMethod.ToString(), ODataParameterReaderState.ResourceSet.ToString()), this.ExceptionVerifier);
                    this.Assert.AreEqual(ODataParameterReaderState.ResourceSet, reader.State, "Unexpected parameter reader state.");
                }

                if (createReaderMethod != CreateReaderMethods.CreateCollectionReader)
                {
                    // Calling Create*Reader in Collection state should fail.
                    reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport_ComplexCollection, testConfiguration, "{ complexCollection : [] }");
                    reader.Read();
                    this.Assert.AreEqual(ODataParameterReaderState.Collection, reader.State, "Unexpected parameter reader state.");
                    this.Assert.ExpectedException(
                        () => CreateSubReader(reader, createReaderMethod),
                        ODataExpectedExceptions.ODataException("ODataParameterReaderCore_InvalidCreateReaderMethodCalledForState", createReaderMethod.ToString(), ODataParameterReaderState.Collection.ToString()), this.ExceptionVerifier);
                    this.Assert.AreEqual(ODataParameterReaderState.Collection, reader.State, "Unexpected parameter reader state.");
                }

                // Calling Read() in Entry/Feed/Collection state without calling Create***Reader should fail.
                IEdmOperationImport functionImport = createReaderMethod == CreateReaderMethods.CreateResourceReader ? functionImport_Entry : (createReaderMethod == CreateReaderMethods.CreateResourceSetReader ? functionImport_Feed : functionImport_ComplexCollection);
                string payload = createReaderMethod == CreateReaderMethods.CreateResourceReader ? "{ entry : {} }" : (createReaderMethod == CreateReaderMethods.CreateResourceSetReader ? "{ feed : [] }" : "{ complexCollection : [] }");
                ODataParameterReaderState expectedParameterState = createReaderMethod == CreateReaderMethods.CreateResourceReader ? ODataParameterReaderState.Resource : ODataParameterReaderState.ResourceSet;
                var expectedReaderMethod = createReaderMethod == CreateReaderMethods.CreateCollectionReader ? CreateReaderMethods.CreateResourceSetReader.ToString() : createReaderMethod.ToString();
                reader = this.CreateParameterReaderForRequestOrResponse(model, functionImport, testConfiguration, payload);
                reader.Read();
                this.Assert.AreEqual(expectedParameterState, reader.State, "Unexpected parameter reader state.");
                this.Assert.ExpectedException(
                    () => reader.Read(),
                    ODataExpectedExceptions.ODataException("ODataParameterReaderCore_SubReaderMustBeCreatedAndReadToCompletionBeforeTheNextReadOrReadAsyncCall", expectedParameterState.ToString(), expectedReaderMethod), this.ExceptionVerifier);
                this.Assert.AreEqual(expectedParameterState, reader.State, "Unexpected parameter reader state.");

                // Calling Read() in Entry/Feed/Collection state after Create***Reader() is called but before the created reader finishes should fail.
                var subReaderMethod = createReaderMethod == CreateReaderMethods.CreateCollectionReader
                        ? CreateReaderMethods.CreateResourceSetReader : createReaderMethod;
                object subReader = CreateSubReader(reader,
                                                   subReaderMethod);
                this.Assert.ExpectedException(
                    () => reader.Read(),
                    ODataExpectedExceptions.ODataException("ODataParameterReaderCore_SubReaderMustBeInCompletedStateBeforeTheNextReadOrReadAsyncCall", expectedParameterState.ToString(), expectedReaderMethod), this.ExceptionVerifier);
                this.Assert.AreEqual(expectedParameterState, reader.State, "Unexpected parameter reader state.");

                // Calling Create*Reader() before the sub-reader is completed should fail.
                string parameterName = createReaderMethod == CreateReaderMethods.CreateResourceReader ? "entry" : (createReaderMethod == CreateReaderMethods.CreateResourceSetReader ? "feed" : "complexCollection");
                subReader.GetType().GetMethod("Read").Invoke(subReader, null);
                this.Assert.ExpectedException(
                    () => CreateSubReader(reader, subReaderMethod),
                    ODataExpectedExceptions.ODataException("ODataParameterReaderCore_CreateReaderAlreadyCalled", expectedReaderMethod, parameterName), this.ExceptionVerifier);
                this.Assert.AreEqual(expectedParameterState, reader.State, "Unexpected parameter reader state.");

                // Calling Create*Reader() after sub-reader is completed should fail.
                while ((bool)subReader.GetType().GetMethod("Read").Invoke(subReader, null))
                {
                    ;
                }
                this.Assert.AreEqual("Completed", subReader.GetType().GetProperty("State").GetValue(subReader, null).ToString(), "Unexpected sub-reader state.");
                this.Assert.ExpectedException(
                    () => CreateSubReader(reader, subReaderMethod),
                    ODataExpectedExceptions.ODataException("ODataParameterReaderCore_CreateReaderAlreadyCalled", expectedReaderMethod, parameterName), this.ExceptionVerifier);
                this.Assert.AreEqual(expectedParameterState, reader.State, "Unexpected parameter reader state.");

                // Finish reading...
                reader.Read();
                this.Assert.AreEqual(ODataParameterReaderState.Completed, reader.State, "Unexpected parameter reader state.");

                // Calling Create*Reader in Completed state should fail.
                this.Assert.ExpectedException(
                    () => CreateSubReader(reader, subReaderMethod),
                    ODataExpectedExceptions.ODataException("ODataParameterReaderCore_InvalidCreateReaderMethodCalledForState", expectedReaderMethod, ODataParameterReaderState.Completed.ToString()), this.ExceptionVerifier);
                this.Assert.AreEqual(ODataParameterReaderState.Completed, reader.State, "Unexpected parameter reader state.");

                // Exception in subReader should put parent reader in Exception state.
                payload = createReaderMethod == CreateReaderMethods.CreateResourceReader ? "{ entry : \"foo\" }" : (createReaderMethod == CreateReaderMethods.CreateResourceSetReader ? "{ feed : { \"foo\" : \"bar\" } }" : "{ complexCollection : { \"foo\" : \"bar\" } }");
                reader  = this.CreateParameterReaderForRequestOrResponse(model, functionImport, testConfiguration, payload);
                reader.Read();
                this.Assert.AreEqual(expectedParameterState, reader.State, "Unexpected parameter reader state.");
                subReader = CreateSubReader(reader, subReaderMethod);
                this.Assert.IsNotNull(TestExceptionUtils.RunCatching(() => { while ((bool)subReader.GetType().GetMethod("Read").Invoke(subReader, null))
                                                                             {
                                                                             }
                                                                     }), "Expecting sub-reader.Read() to fail.");
                this.Assert.AreEqual("Exception", subReader.GetType().GetProperty("State").GetValue(subReader, null).ToString(), "Unexpected sub-reader state.");
                this.Assert.AreEqual(ODataParameterReaderState.Exception, reader.State, "Unexpected parameter reader state.");

                // Calling Create*Reader in Exception state should fail.
                this.Assert.ExpectedException(
                    () => CreateSubReader(reader, subReaderMethod),
                    ODataExpectedExceptions.ODataException("ODataParameterReaderCore_InvalidCreateReaderMethodCalledForState", expectedReaderMethod, ODataParameterReaderState.Exception.ToString()), this.ExceptionVerifier);
                this.Assert.AreEqual(ODataParameterReaderState.Exception, reader.State, "Unexpected parameter reader state.");
            });
        }