Esempio n. 1
0
        /// <summary>
        /// Creates a batch payload with the specified number of changesets and the specified number of operations in each changeset.
        /// </summary>
        /// <param name="requestManager">Used for building the requests/responses.</param>
        /// <param name="changeSetCount">The number of changesets to create in the batch payload.</param>
        /// <param name="changeSetSizes">The size of each changeset.</param>
        /// <param name="forRequest">true if creating a batch request payload; otherwise false.</param>
        /// <param name="batchBoundary">The batch boundary to use; or null to use an auto-generated one.</param>
        /// <returns>A <see cref="PayloadTestDescriptor"/> for the batch payload.</returns>
        public static PayloadTestDescriptor CreateDefaultQueryBatch(
            IODataRequestManager requestManager,
            int queryCount,
            bool forRequest,
            string batchBoundary = null)
        {
            Debug.Assert(queryCount >= 0, "batchSize >= 0");

            var emptyPayload = new PayloadTestDescriptor()
            {
                PayloadEdmModel = CreateEmptyEdmModel()
            };

            var root = ODataUriBuilder.Root(new Uri("http://www.odata.org/service.svc"));

            IMimePart[] parts = new IMimePart[queryCount];

            if (forRequest)
            {
                var queryOperation = emptyPayload.InRequestOperation(HttpVerb.Get, new ODataUri(new ODataUriSegment[] { root }), requestManager);

                for (int i = 0; i < queryCount; ++i)
                {
                    parts[i] = queryOperation;
                }
                ;

                string requestBoundary = batchBoundary ?? "bb_multiple_request_queries_" + queryCount;
                return(new PayloadTestDescriptor()
                {
                    PayloadElement = PayloadBuilder.BatchRequestPayload(parts)
                                     .AddAnnotation(new BatchBoundaryAnnotation(requestBoundary)),
                });
            }

            // Response operation with no payload and a status code of 200
            var emptyPayloadResponse = emptyPayload.InResponseOperation(200, requestManager);

            for (int i = 0; i < queryCount; ++i)
            {
                parts[i] = emptyPayloadResponse;
            }
            ;

            string responseBoundary = batchBoundary ?? "bb_multiple_response_queries_" + queryCount;

            return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchResponsePayload(parts)
                                 .AddAnnotation(new BatchBoundaryAnnotation(responseBoundary)),
            });
        }
Esempio n. 2
0
            /// <summary>
            /// Visits an ODataBatch.
            /// </summary>
            /// <param name="batch">The batch to visit.</param>
            protected override ODataPayloadElement VisitBatch(ODataBatch batch)
            {
                List <IMimePart> parts = new List <IMimePart>();

                if (batch.Parts != null)
                {
                    foreach (ODataBatchPart part in batch.Parts)
                    {
                        ODataBatchChangeset changeset = part as ODataBatchChangeset;
                        if (changeset == null)
                        {
                            parts.Add(this.ConvertBatchOperation((ODataBatchOperation)part));
                        }
                        else
                        {
                            List <IMimePart> changeSetOperations = new List <IMimePart>();
                            if (changeset.Operations != null)
                            {
                                foreach (ODataBatchOperation batchOperation in changeset.Operations)
                                {
                                    changeSetOperations.Add(this.ConvertBatchOperation(batchOperation));
                                }
                            }

                            // TODO: the ODataBatchReader does not expose boundary strings or encodings; should it?
                            if (this.response)
                            {
                                BatchResponseChangeset responseChangeset =
                                    BatchPayloadBuilder.ResponseChangeset(/*boundary*/ null, /*charset*/ null, changeSetOperations.ToArray());
                                parts.Add(responseChangeset);
                            }
                            else
                            {
                                BatchRequestChangeset requestChangeset =
                                    BatchPayloadBuilder.RequestChangeset(/*boundary*/ null, /*charset*/ null, changeSetOperations.ToArray());
                                parts.Add(requestChangeset);
                            }
                        }
                    }
                }

                return(this.response
                    ? (ODataPayloadElement)PayloadBuilder.BatchResponsePayload(parts.ToArray())
                    : (ODataPayloadElement)PayloadBuilder.BatchRequestPayload(parts.ToArray()));
            }
Esempio n. 3
0
        /// <summary>
        /// Creates several PayloadTestDescriptors containing Batch Responses
        /// </summary>
        /// <param name="requestManager">Used for building the requests/responses.</param>
        /// <param name="model">The model to use for adding additional types.</param>
        /// <param name="withTypeNames">Whether or not to use full type names.</param>
        /// <returns>PayloadTestDescriptors</returns>
        public static IEnumerable <PayloadTestDescriptor> CreateBatchResponseTestDescriptors(
            IODataRequestManager requestManager,
            EdmModel model,
            bool withTypeNames = false)
        {
            EdmEntityType  personType = null;
            EdmComplexType carType    = null;

            if (model != null)
            {
                //TODO: CLONE for EdmModel
                //model = model.Clone();

                personType = model.FindDeclaredType("TestModel.TFPerson") as EdmEntityType;
                carType    = model.FindDeclaredType("TestModel.TFCar") as EdmComplexType;

                // Create the metadata types for the entity instance used in the entity set
                if (carType == null)
                {
                    carType = new EdmComplexType("TestModel", "TFCar");
                    model.AddElement(carType);
                    carType.AddStructuralProperty("Make", EdmPrimitiveTypeKind.String, true);
                    carType.AddStructuralProperty("Color", EdmPrimitiveTypeKind.String, true);
                }

                if (personType == null)
                {
                    personType = new EdmEntityType("TestModel", "TFPerson");
                    model.AddElement(personType);
                    personType.AddKeys(personType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32));
                    personType.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String, true);
                    personType.AddStructuralProperty("Car", carType.ToTypeReference());

                    EdmEntityContainer container = (EdmEntityContainer)model.EntityContainer;
                    if (container == null)
                    {
                        container = new EdmEntityContainer("TestModel", "DefaultContainer");
                        model.AddElement(container);
                        container.AddEntitySet("Customers", personType);
                        container.AddEntitySet("TFPerson", personType);
                    }
                }
            }

            ComplexInstance carInstance = PayloadBuilder.ComplexValue(withTypeNames ? "TestModel.TFCar" : null)
                                          .Property("Make", PayloadBuilder.PrimitiveValue("Ford"))
                                          .Property("Color", PayloadBuilder.PrimitiveValue("Blue"));
            ComplexProperty carProperty = (ComplexProperty)PayloadBuilder.Property("Car", carInstance)
                                          .WithTypeAnnotation(carType);

            EntityInstance personInstance = PayloadBuilder.Entity(withTypeNames ? "TestModel.TFPerson" : null)
                                            .Property("Id", PayloadBuilder.PrimitiveValue(1))
                                            .Property("Name", PayloadBuilder.PrimitiveValue("John Doe"))
                                            .Property("Car", carInstance)
                                            .WithTypeAnnotation(personType);

            ODataErrorPayload errorInstance = PayloadBuilder.Error("ErrorCode")
                                              .Message("ErrorValue")
                                              .InnerError(
                PayloadBuilder.InnerError().Message("InnerErrorMessage").StackTrace("InnerErrorStackTrace").TypeName("InnerErrorTypeName"));

            var carPropertyPayload = new PayloadTestDescriptor()
            {
                PayloadElement  = carProperty,
                PayloadEdmModel = model
            };

            var emptyPayload = new PayloadTestDescriptor()
            {
                PayloadEdmModel = CreateEmptyEdmModel()
            };

            var personPayload = new PayloadTestDescriptor()
            {
                // This payload will be serialised to JSON so we need the annotation to mark it as a response.
                PayloadElement = personInstance.AddAnnotation(new PayloadFormatVersionAnnotation()
                {
                    Response = true, ResponseWrapper = true
                }),
                PayloadEdmModel = model
            };

            var errorPayload = new PayloadTestDescriptor()
            {
                PayloadElement  = errorInstance,
                PayloadEdmModel = model,
            };

            // response operation with a status code of 5 containing a complex instance
            var carPropertyPayloadOperation = carPropertyPayload.InResponseOperation(5, requestManager);
            // response operation with no payload and a status code of 200
            var emptyPayloadOperation = emptyPayload.InResponseOperation(200, requestManager);
            // response operation with a status code of 418 containing an entity instance
            var personPayloadOperation = personPayload.InResponseOperation(418, requestManager, MimeTypes.ApplicationJsonLight);
            // response operation with a status code of 404 containing an error instance
            var errorPayloadOperation = errorPayload.InResponseOperation(404, requestManager);

            // changeset with multiple operations
            var twoOperationsChangeset = BatchUtils.GetResponseChangeset(new IMimePart[] { carPropertyPayloadOperation, emptyPayloadOperation }, requestManager);
            // changesets with a single operation
            var oneOperationChangeset = BatchUtils.GetResponseChangeset(new IMimePart[] { personPayloadOperation }, requestManager);
            var oneErrorChangeset     = BatchUtils.GetResponseChangeset(new IMimePart[] { errorPayloadOperation }, requestManager);
            // empty changeset
            var emptyChangeset = BatchUtils.GetResponseChangeset(new IMimePart[] { }, requestManager);

            // Empty Batch
            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchResponsePayload(new IMimePart[] {  })
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_emptybatch")),
                PayloadEdmModel = emptyPayload.PayloadEdmModel,
                SkipTestConfiguration = (tc) => tc.IsRequest,
            });

            // Single Operation
            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchResponsePayload(new IMimePart[] { carPropertyPayloadOperation })
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_singleoperation")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => tc.IsRequest,
            });

            // Multiple Operations
            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchResponsePayload(new IMimePart[] { carPropertyPayloadOperation, emptyPayloadOperation, errorPayloadOperation, personPayloadOperation })
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_multipleoperations")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => tc.IsRequest,
            });

            // Single Changeset
            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchResponsePayload(new IMimePart[] { twoOperationsChangeset })
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_singlechangeset")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => tc.IsRequest,
            });

            // Multiple Changesets
            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchResponsePayload(new IMimePart[] { twoOperationsChangeset, oneOperationChangeset })
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_multiplechangesets")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => tc.IsRequest,
            });

            // Operations and changesets
            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchResponsePayload(new IMimePart[] { twoOperationsChangeset, carPropertyPayloadOperation, oneOperationChangeset })
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_operationsandchangesets_1")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => tc.IsRequest,
            });

            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchResponsePayload(new IMimePart[] { carPropertyPayloadOperation, oneOperationChangeset, emptyPayloadOperation })
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_operationsandchangesets_2")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => tc.IsRequest,
            });

            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchResponsePayload(new IMimePart[] { errorPayloadOperation, carPropertyPayloadOperation, emptyPayloadOperation, twoOperationsChangeset, oneOperationChangeset })
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_operationsandchangesets_3")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => tc.IsRequest,
            });

            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchResponsePayload(
                    new IMimePart[] { oneErrorChangeset, carPropertyPayloadOperation, emptyChangeset, emptyPayloadOperation, twoOperationsChangeset, personPayloadOperation, oneOperationChangeset, errorPayloadOperation })
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_operationsandchangesets_4")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => tc.IsRequest,
            });
        }
Esempio n. 4
0
        /// <summary>
        /// Creates a batch payload with the specified number of changesets and the specified number of operations in each changeset.
        /// </summary>
        /// <param name="requestManager">Used for building the requests/responses.</param>
        /// <param name="changeSetCount">The number of changesets to create in the batch payload.</param>
        /// <param name="changeSetSizes">The size of each changeset.</param>
        /// <param name="forRequest">true if creating a batch request payload; otherwise false.</param>
        /// <param name="changeSetBoundary">The changeset boundary to use; or null to use an auto-generated one.</param>
        /// <returns>A <see cref="PayloadTestDescriptor"/> for the batch payload.</returns>
        public static PayloadTestDescriptor CreateDefaultChangeSetBatch(
            IODataRequestManager requestManager,
            int changeSetCount,
            int[] changeSetSizes,
            bool forRequest,
            string changeSetBoundary = null)
        {
            Debug.Assert(changeSetCount >= 0, "batchSize >= 0");
            Debug.Assert(changeSetSizes != null, "changeSetSizes != null");
            Debug.Assert(changeSetSizes.Length == changeSetCount, "Size of the batch must match the length of the change set sizes array!");

            var emptyPayload = new PayloadTestDescriptor()
            {
                PayloadEdmModel = CreateEmptyEdmModel()
            };

            var root = ODataUriBuilder.Root(new Uri("http://www.odata.org/service.svc"));

            IMimePart[] parts = new IMimePart[changeSetCount];

            if (forRequest)
            {
                // Delete operation with no payload
                var deleteOperation = emptyPayload.InRequestOperation(HttpVerb.Delete, new ODataUri(new ODataUriSegment[] { root }), requestManager);

                for (int i = 0; i < changeSetCount; ++i)
                {
                    int changeSetSize    = changeSetSizes[i];
                    var deleteOperations = new IMimePart[changeSetSize];
                    for (int j = 0; j < changeSetSize; ++j)
                    {
                        deleteOperations[j] = deleteOperation;
                    }

                    var changeset = BatchUtils.GetRequestChangeset(deleteOperations, requestManager);
                    parts[i] = changeset;
                }
                ;

                string requestBoundary = changeSetBoundary ?? "bb_multiple_request_changesets_" + changeSetCount;
                return(new PayloadTestDescriptor()
                {
                    PayloadElement = PayloadBuilder.BatchRequestPayload(parts)
                                     .AddAnnotation(new BatchBoundaryAnnotation(requestBoundary)),
                });
            }

            // Response operation with no payload and a status code of 200
            var emptyPayloadOperation = emptyPayload.InResponseOperation(200, requestManager);

            for (int i = 0; i < changeSetCount; ++i)
            {
                int changeSetSize      = changeSetSizes[i];
                var operationResponses = new IMimePart[changeSetSize];
                for (int j = 0; j < changeSetSize; ++j)
                {
                    operationResponses[j] = emptyPayloadOperation;
                }

                var changeset = BatchUtils.GetResponseChangeset(operationResponses, requestManager);
                parts[i] = changeset;
            }
            ;

            string responseBoundary = changeSetBoundary ?? "bb_multiple_response_changesets_" + changeSetCount;

            return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchResponsePayload(parts)
                                 .AddAnnotation(new BatchBoundaryAnnotation(responseBoundary)),
            });
        }
Esempio n. 5
0
        /// <summary>
        /// Helper method to run a single iteration of the URI reading tests in a specified configuration.
        /// </summary>
        /// <typeparam name="T">The type of the payload to read.</typeparam>
        /// <param name="payloadElement">The payload to read.</param>
        /// <param name="setExpectedUriAction">An action to set the URI in question on the payload.</param>
        /// <param name="model">The metadata model.</param>
        /// <param name="payloadUri">The payload URI for the current iteration.</param>
        /// <param name="baseUriValue">The base URI value for the current iteration.</param>
        /// <param name="resolver">The resolver to use.</param>
        /// <param name="testConfiguration">The reader test configuration.</param>
        private void RunBaseUriReadingTest <T>(
            T payloadElement,
            Action <T, Uri, ReaderTestConfiguration> setExpectedUriAction,
            IEdmModel model,
            Uri payloadUri,
            BaseUriValue baseUriValue,
            KeyValuePair <Func <Uri, Uri, Uri, Uri>, Uri> resolver,
            ReaderTestConfiguration testConfiguration,
            bool runInBatch = false) where T : ODataPayloadElement
        {
            this.Assert.IsNull(testConfiguration.MessageReaderSettings.BaseUri, "No base URI expected on reader settings.");
            ExpectedException expectedException = null;

            Uri settingsBaseUri = baseUriValue.ReaderSettingBaseUri;

            // Set the base URI on the message reader settings if specified
            if (settingsBaseUri != null)
            {
                testConfiguration = new ReaderTestConfiguration(testConfiguration);
                testConfiguration.MessageReaderSettings.BaseUri = settingsBaseUri;
            }

            // Create the payload element
            T clonedPayloadElement = payloadElement.DeepCopy();

            setExpectedUriAction(clonedPayloadElement, payloadUri, testConfiguration);

            if (testConfiguration.Format == ODataFormat.Atom)
            {
                XElement xmlRepresentation = this.PayloadElementToXmlConverter.ConvertToXml(clonedPayloadElement);

                // add an xml:base attribute if specified
                Uri xmlBaseUri = baseUriValue.XmlBaseUri;
                if (xmlBaseUri != null)
                {
                    xmlRepresentation.Add(new XAttribute(XNamespace.Xml.GetName("base"), xmlBaseUri.OriginalString));
                }

                clonedPayloadElement.XmlRepresentation(xmlRepresentation);

                if (resolver.Value != null)
                {
                    setExpectedUriAction(clonedPayloadElement, resolver.Value, testConfiguration);
                }
                else
                {
                    // compute the expected URI value for ATOM
                    if (!payloadUri.IsAbsoluteUri)
                    {
                        if (xmlBaseUri != null)
                        {
                            setExpectedUriAction(clonedPayloadElement, new Uri(xmlBaseUri, payloadUri), testConfiguration);
                        }
                        else if (settingsBaseUri != null)
                        {
                            setExpectedUriAction(clonedPayloadElement, new Uri(settingsBaseUri, payloadUri), testConfiguration);
                        }
                        else
                        {
                            // fail for relative URIs without base URI
                            expectedException = ODataExpectedExceptions.ODataException("ODataAtomDeserializer_RelativeUriUsedWithoutBaseUriSpecified", payloadUri.OriginalString);
                        }
                    }
                }
            }
            else
            {
                throw new NotSupportedException("Unsupported configuration format: " + testConfiguration.Format.ToString());
            }

            PayloadReaderTestDescriptor testDescriptor = new PayloadReaderTestDescriptor(resolver.Key == null ? this.Settings : this.NoValidatorSettings)
            {
                PayloadElement    = clonedPayloadElement,
                PayloadEdmModel   = model,
                ExpectedException = expectedException,
                UrlResolver       = resolver.Key == null ? null : new TestUrlResolver {
                    ResolutionCallback = (baseUri, realPayloadUri) => resolver.Key(payloadUri, baseUri, realPayloadUri)
                },
                SkipTestConfiguration = tc => ODataPayloadElementConfigurationValidator.GetSkipTestConfiguration(payloadElement, ODataPayloadElementConfigurationValidator.AllValidators)(tc),
            };

            if (runInBatch)
            {
                // TODO: Batch reader does not enter Exception state upon cross reference error in payload.
                // Once fixed allow the batch tests to run even for error cases.
                if (expectedException != null)
                {
                    return;
                }

                if (testConfiguration.IsRequest)
                {
                    testDescriptor = new PayloadReaderTestDescriptor(testDescriptor)
                    {
                        PayloadElement =
                            PayloadBuilder.BatchRequestPayload(
                                BatchUtils.GetRequestChangeset(
                                    new IMimePart[] { testDescriptor.PayloadDescriptor.InRequestOperation(
                                                          HttpVerb.Put,
                                                          new ODataUri(ODataUriBuilder.Root(new Uri("http://odata.org/service"))),
                                                          this.RequestManager,
                                                          TestMediaTypeUtils.GetDefaultContentType(testDescriptor.PayloadDescriptor.PayloadKind, testConfiguration.Format)) },
                                    this.RequestManager))
                            .AddAnnotation(new BatchBoundaryAnnotation("bb_request"))
                    };
                }
                else
                {
                    testDescriptor = new PayloadReaderTestDescriptor(testDescriptor)
                    {
                        PayloadElement =
                            PayloadBuilder.BatchResponsePayload(
                                testDescriptor.PayloadDescriptor.InResponseOperation(
                                    200,
                                    this.RequestManager,
                                    TestMediaTypeUtils.GetDefaultContentType(testDescriptor.PayloadDescriptor.PayloadKind, testConfiguration.Format)))
                            .AddAnnotation(new BatchBoundaryAnnotation("bb_response"))
                    };
                }

                testConfiguration = new ReaderTestConfiguration(null, testConfiguration.MessageReaderSettings, testConfiguration.IsRequest, testConfiguration.Synchronous, testConfiguration.Version);
            }

            testDescriptor.RunTest(testConfiguration);
        }