/// <summary>
        /// Puts the specified <paramref name="payload"/> into a changeset.
        /// </summary>
        /// <param name="payload">The payload to be used as content for the expanded link.</param>
        /// <param name="verb">The verb associated with the payload.</param>
        /// <param name="random">Use of random makes this method non deterministic.</param>
        /// <param name="requestManager">Used to construct requests</param>
        /// <param name="operationsBefore">Number of extra operations before payload.</param>
        /// <param name="operationsAfter">Number of extra operations after payload.</param>
        /// <param name="version">Highest version of allowed features</param>
        /// <returns>An entry payload with an expanded link that contains the specified <paramref name="payload"/>.</returns>
        public static BatchRequestChangeset InRequestChangeset <T>(
            this T payload,
            HttpVerb verb,
            IRandomNumberGenerator random,
            IODataRequestManager requestManager,
            int operationsBefore = 0,
            int operationsAfter  = 0,
            ODataVersion version = ODataVersion.V4
            ) where T : PayloadTestDescriptor
        {
            ExceptionUtilities.CheckArgumentNotNull(payload, "payload");
            ExceptionUtilities.CheckArgumentNotNull(verb, "verb");
            ExceptionUtilities.CheckArgumentNotNull(random, "random");
            ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager");

            var baseUri         = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org/service.svc")));
            var extraOperations = BatchUtils.ExtraRequestChangesetOperations(random, requestManager, (EdmModel)payload.PayloadEdmModel, baseUri, version);

            // Build the list of all properties
            IEnumerable <IHttpRequest> operations = Enumerable.Range(0, operationsBefore).Select(i => random.ChooseFrom(extraOperations));

            operations.ConcatSingle(payload.InRequestOperation(verb, baseUri, requestManager));
            operations = operations.Concat(Enumerable.Range(0, operationsAfter).Select(i => extraOperations[extraOperations.Length - 1 - (i % extraOperations.Length)]));

            var changeset = BatchPayloadBuilder.RequestChangeset("changeset_" + Guid.NewGuid().ToString(), Encoding.UTF8.WebName, operations.ToArray());

            return(changeset);
        }
        /// <summary>
        /// Puts payload in a batch response.
        /// </summary>
        /// <typeparam name="T">T must be a PayloadTestDescriptor.</typeparam>
        /// <param name="originalPayload">Payload to be inserted into batch.</param>
        /// <param name="statusCode">Status code associated with payload</param>
        /// <param name="random">Use of random makes this method non deterministic</param>
        /// <param name="requestManager">Used to construct the response payload.</param>
        /// <param name="inChangeset">Specifies whether this is in a changeset or an operation.</param>
        /// <param name="operationsBefore">Number of operations/changesets to go before payload.</param>
        /// <param name="operationsAfter">Number of operations/changesets to go after payload.</param>
        /// <param name="version">Maximum version for extra generated payloads</param>
        /// <returns>Test descriptor for the new BatchResponsePayload.</returns>
        public static T InBatchResponse <T>(
            this T originalPayload,
            int statusCode,
            IRandomNumberGenerator random,
            IODataRequestManager requestManager,
            bool inChangeset     = false,
            int operationsBefore = 0,
            int operationsAfter  = 0,
            ODataVersion version = ODataVersion.V4
            ) where T : PayloadTestDescriptor
        {
            ExceptionUtilities.CheckArgumentNotNull(originalPayload, "originalPayload");
            ExceptionUtilities.CheckArgumentNotNull(statusCode, "statusCode");
            ExceptionUtilities.CheckArgumentNotNull(random, "random");
            ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager");
            var payload = (T)originalPayload.Clone();

            var headers = new Dictionary <string, string> {
                { "ResponseHeader", "ResponseValue" }
            };
            var baseUri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org/service.svc")));

            IMimePart[] extraoperations = BatchUtils.ExtraResponseChangesets(random, (EdmModel)payload.PayloadEdmModel, version);  // add extraChangesets methods
            extraoperations.Concat(BatchUtils.ExtraResponseOperations(random, (EdmModel)payload.PayloadEdmModel, version));

            //Work out the operations and changesets to go before the payload
            var parts = Enumerable.Range(0, operationsBefore).Select(i => random.ChooseFrom(extraoperations));

            if (!inChangeset)
            {
                extraoperations.ConcatSingle(payload.InResponseOperation(statusCode, requestManager));
            }
            else
            {
                extraoperations.ConcatSingle(payload.InResponseChangeset(statusCode, random, requestManager, random.NextFromRange(0, 2), random.NextFromRange(0, 2), version));
            }

            parts.Concat(Enumerable.Range(0, operationsAfter).Select(i => random.ChooseFrom(extraoperations)));

            var batchResponse = new BatchResponsePayload();

            foreach (var part in parts)
            {
                HttpResponseData operation = part as HttpResponseData;
                if (operation != null)
                {
                    batchResponse.Add(operation.AsBatchFragment());
                }

                BatchResponseChangeset changeset = part as BatchResponseChangeset;
                if (changeset != null)
                {
                    batchResponse.Add(changeset);
                }
            }

            //payload.PayloadEdmModel.Fixup();
            payload.PayloadElement = batchResponse;
            return(payload);
        }
Beispiel #3
0
        /// <summary>
        /// Build QueryValue from query expresion and server response.
        /// </summary>
        /// <param name="expression">The query expresion of client request.</param>
        /// <param name="response">The http response from the server.</param>
        /// <returns>The baseline QueryValue converted from payload.</returns>
        public QueryValue BuildQueryValue(QueryExpression expression, HttpResponseData response)
        {
            ExceptionUtilities.CheckArgumentNotNull(expression, "expression");
            ExceptionUtilities.CheckArgumentNotNull(response, "response");
            ExceptionUtilities.CheckAllRequiredDependencies(this);

            // get type resolver and payload deserializer.
            var typeResolver = new LinqToAstoriaTypeResolutionVisitor(this.TypeLibrary);

            // if the response has an error
            if (response.StatusCode != HttpStatusCode.OK)
            {
                return(expression.ExpressionType.CreateErrorValue(new QueryError("Response from server has an error!")));
            }

            string contentType;

            ExceptionUtilities.Assert(response.Headers.TryGetValue(HttpHeaders.ContentType, out contentType), "Cannot get content type from response.");
            var deserializer = this.StrategySelector.GetStrategy(contentType, null).GetDeserializer();

            this.currentExpression = expression;

            var      expressionForUri = this.ClientSideProjectionReplacer.ReplaceClientSideProjections(expression);
            ODataUri queryUri         = this.QueryToODataUriConverter.ComputeUri(expressionForUri);

            queryUri.Segments.Insert(0, ODataUriBuilder.Root(this.Workspace.ServiceUri));

            // deserialize byte array payload to OData payload element.
            ODataPayloadElement payload = this.DeserializePayloadData(deserializer, response, queryUri);

            this.PayloadElementMetadataResolver.ResolveMetadata(payload, queryUri);
            var normalizer = this.StrategySelector.GetStrategy(contentType, null).GetPayloadNormalizer();

            payload = normalizer.Normalize(payload);

            if (this.ShouldUsePayloadDrivenVerification(queryUri))
            {
                return(this.BuildQueryValueForActionResponse(payload, expression.ExpressionType));
            }
            else
            {
                // build query data set from payload for evaluation. It's a different data set from the initial one of current workspace.
                IQueryDataSet dataSet = this.BuildQueryDataSet(payload);

                // filter the query and resolve types. Need to remove expressions such as $top, $skip, $orderby, $filter because the returned payload is already the result of performing these expressions.
                // need to keep root expression, key expression, $expand and $select to have correct anonymous type.
                var filteredQuery = this.FilterExpression(expression);
                filteredQuery = typeResolver.ResolveTypes(filteredQuery, this.EvaluationStrategy);

                // replace the evaluator's query-data-set with the one generated in the payload
                using (this.Evaluator.WithTemporaryDataSet(dataSet))
                {
                    return(this.Evaluator.Evaluate(filteredQuery));
                }
            }
        }
        /// <summary>
        /// Puts payload in a batch request.
        /// </summary>
        /// <typeparam name="T">T must be a PayloadTestDescriptor.</typeparam>
        /// <param name="originalPayload">Payload to put into batch.</param>
        /// <param name="verb">HttpVerb associated with payload.</param>
        /// <param name="random">Use of random makes this method non deterministic.</param>
        /// <param name="requestManager">Used to construct requests.</param>
        /// <param name="operationsBefore">Number of operations/changesets to go before payload.</param>
        /// <param name="operationsAfter">Number of operations/changesets to go after payload.</param>
        /// <param name="version">Maximum version for extra payloads</param>
        /// <returns>The test descriptor for the new BatchRequestPayload</returns>
        public static T InBatchRequest <T>(
            this T originalPayload,
            HttpVerb verb,
            IRandomNumberGenerator random,
            IODataRequestManager requestManager,
            int operationsBefore = 0,
            int operationsAfter  = 0,
            ODataVersion version = ODataVersion.V4
            ) where T : PayloadTestDescriptor
        {
            ExceptionUtilities.CheckArgumentNotNull(originalPayload, "originalPayload");
            ExceptionUtilities.CheckArgumentNotNull(verb, "verb");
            ExceptionUtilities.CheckArgumentNotNull(random, "random");
            ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager");
            var payload = (T)originalPayload.Clone();

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

            IMimePart[] extraOperations = BatchUtils.ExtraRequestChangesets(random, requestManager, (EdmModel)payload.PayloadEdmModel, baseUri, version);  // add extraChangesets methods
            extraOperations.Concat(BatchUtils.ExtraRequestChangesets(random, requestManager, (EdmModel)payload.PayloadEdmModel, baseUri, version));

            //Work out the operations and changesets to go before the payload
            var parts = Enumerable.Range(0, operationsBefore).Select(i => random.ChooseFrom(extraOperations));

            if (verb != HttpVerb.Get)
            {
                extraOperations.ConcatSingle(payload.InRequestOperation(HttpVerb.Get, baseUri, requestManager));
            }
            else
            {
                extraOperations.ConcatSingle(payload.InRequestChangeset(verb, random, requestManager, random.NextFromRange(0, 2), random.NextFromRange(0, 2), version));
            }

            parts.Concat(Enumerable.Range(0, operationsAfter).Select(i => random.ChooseFrom(extraOperations)));

            var batchRequest = new BatchRequestPayload();

            foreach (var part in parts)
            {
                IHttpRequest operation = part as IHttpRequest;
                if (operation != null)
                {
                    batchRequest.Add(operation.AsBatchFragment());
                }
                BatchRequestChangeset changeset = part as BatchRequestChangeset;
                if (changeset != null)
                {
                    batchRequest.Add(changeset);
                }
            }

            //payload.PayloadEdmModel.Fixup();
            payload.PayloadElement = batchRequest;
            return(payload);
        }
Beispiel #5
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)),
            });
        }
Beispiel #6
0
        public void BatchReaderMixedEncodingTest()
        {
            EdmModel      model      = new EdmModel();
            EdmEntityType personType = model.EntityType("Person")
                                       .KeyProperty("Id", EdmCoreModel.Instance.GetInt32(false) as EdmTypeReference)
                                       .Property("Name", EdmPrimitiveTypeKind.String, isNullable: true);

            model.Fixup();

            EdmEntitySet personSet = model.EntitySet("Person", personType);

            EntityInstance personInstance = PayloadBuilder.Entity("TestModel.Person")
                                            .Property("Id", PayloadBuilder.PrimitiveValue(1))
                                            .Property("Name", PayloadBuilder.PrimitiveValue("Mr Foo Baz"));

            ODataUriSegment root    = ODataUriBuilder.Root(new Uri("http://www.odata.org"));
            ODataUri        testUri = new ODataUri(root, ODataUriBuilder.EntitySet(personSet));


            Encoding[] encodings = new Encoding[]
            {
                Encoding.UTF8,
                Encoding.BigEndianUnicode,
                Encoding.Unicode
            };

            IEnumerable <BatchReaderMixedEncodingTestCase> testCases =
                encodings.SelectMany(batchEncoding =>
                                     encodings.Select(changesetEncoding =>
                                                      new BatchReaderMixedEncodingTestCase
            {
                BatchEncoding = batchEncoding,
                Changesets    = new[]
                {
                    new BatchReaderMixedEncodingChangeset
                    {
                        ChangesetEncoding = changesetEncoding,
                        Operations        = new[]
                        {
                            new BatchReaderMixedEncodingOperation
                            {
                                OperationEncoding = Encoding.Unicode,
                                PayloadFormat     = ODataFormat.Atom,
                            },
                            new BatchReaderMixedEncodingOperation
                            {
                                // Uses changeset's encoding
                                PayloadFormat = ODataFormat.Atom,
                            },
                        },
                    },
                    new BatchReaderMixedEncodingChangeset
                    {
                        Operations = new[]
                        {
                            new BatchReaderMixedEncodingOperation
                            {
                                // Uses batch's encoding
                                OperationEncoding = batchEncoding,
                                PayloadFormat     = ODataFormat.Atom,
                            },
                        },
                    },
                },
            }
                                                      ));

            this.CombinatorialEngineProvider.RunCombinations(
                testCases,
                this.ReaderTestConfigurationProvider.DefaultFormatConfigurations,
                (testCase, testConfiguration) =>
            {
                var testPayload = personInstance.DeepCopy();
                if (!testConfiguration.IsRequest)
                {
                    testPayload.AddAnnotation(new PayloadFormatVersionAnnotation()
                    {
                        Response = true, ResponseWrapper = true
                    });
                }

                var testDescriptor             = this.CreateTestDescriptor(testCase, testPayload, testUri, testConfiguration.IsRequest);
                testDescriptor.PayloadEdmModel = model;
                testDescriptor.RunTest(testConfiguration);
            });
        }
Beispiel #7
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)),
            });
        }
Beispiel #8
0
        /// <summary>
        /// Creates several PayloadTestDescriptors containing Batch Requests
        /// </summary>
        /// <param name="requestManager">Used for building the requests</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> CreateBatchRequestTestDescriptors(
            IODataRequestManager requestManager,
            EdmModel model,
            bool withTypeNames = false)
        {
            ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager");
            EdmEntityType      personType       = null;
            EdmComplexType     carType          = null;
            EdmEntitySet       personsEntitySet = null;
            EdmEntityContainer container        = model.EntityContainer as EdmEntityContainer;

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

                if (container == null)
                {
                    container = new EdmEntityContainer("TestModel", "DefaultContainer");
                    model.AddElement(container);
                }

                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());
                    container.AddEntitySet("Customers", personType);
                }

                personsEntitySet = container.AddEntitySet("People", 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(personType);

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

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

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

            var personPayload = new PayloadTestDescriptor()
            {
                PayloadElement  = personInstance,
                PayloadEdmModel = model
            };

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

            // Get operations
            var queryOperation1 = emptyPayload.InRequestOperation(HttpVerb.Get, new ODataUri(new ODataUriSegment[] { root }), requestManager);
            var queryOperation2 = emptyPayload.InRequestOperation(HttpVerb.Get, new ODataUri(new ODataUriSegment[] { root }), requestManager);

            // Post operation containing a complex property
            var postOperation = carPropertyPayload.InRequestOperation(HttpVerb.Post, new ODataUri(new ODataUriSegment[] { root, entityset }), requestManager, MimeTypes.ApplicationJsonLight);
            // Delete operation with no payload
            var deleteOperation = emptyPayload.InRequestOperation(HttpVerb.Delete, new ODataUri(new ODataUriSegment[] { root, entityset }), requestManager);
            // Put operation where the payload is an EntityInstance
            var putOperation = personPayload.InRequestOperation(HttpVerb.Put, new ODataUri(new ODataUriSegment[] { root, entityset }), requestManager);

            // A changeset containing a delete with no payload and a put
            var twoOperationsChangeset = BatchUtils.GetRequestChangeset(new IMimePart[] { postOperation, deleteOperation }, requestManager);
            // A changeset containing a delete with no payload
            var oneOperationChangeset = BatchUtils.GetRequestChangeset(new IMimePart[] { deleteOperation }, requestManager);
            // A changeset containing a put, post and delete
            var threeOperationsChangeset = BatchUtils.GetRequestChangeset(new IMimePart[] { putOperation, postOperation, deleteOperation }, requestManager);
            // A changeset containing no operations
            var emptyChangeset = BatchUtils.GetRequestChangeset(new IMimePart[] { }, requestManager);

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

            // Single Operation
            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchRequestPayload(queryOperation1)
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_singleoperation")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => !tc.IsRequest,
            });

            // Multiple Operations
            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchRequestPayload(queryOperation1, queryOperation2)
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_multipleoperations")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => !tc.IsRequest,
            });

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

            // Multiple Changesets (different content types)
            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchRequestPayload(twoOperationsChangeset, oneOperationChangeset, emptyChangeset)
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_multiplechangesets")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => !tc.IsRequest,
            });

            // Operations and changesets
            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchRequestPayload(twoOperationsChangeset, queryOperation1, oneOperationChangeset)
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_operationsandchangesets_1")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => !tc.IsRequest,
            });

            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchRequestPayload(queryOperation1, oneOperationChangeset, queryOperation2)
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_operationsandchangesets_2")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => !tc.IsRequest,
            });

            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchRequestPayload(queryOperation1, queryOperation2, twoOperationsChangeset, oneOperationChangeset)
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_operationsandchangesets_3")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => !tc.IsRequest,
            });

            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchRequestPayload(queryOperation1, threeOperationsChangeset, queryOperation2, twoOperationsChangeset, queryOperation1, oneOperationChangeset)
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_operationsandchangesets_4")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => !tc.IsRequest,
            });

            yield return(new PayloadTestDescriptor()
            {
                PayloadElement = PayloadBuilder.BatchRequestPayload(queryOperation1, emptyChangeset, queryOperation1, threeOperationsChangeset, queryOperation2, oneOperationChangeset)
                                 .AddAnnotation(new BatchBoundaryAnnotation("bb_operationsandchangesets_5")),
                PayloadEdmModel = model,
                SkipTestConfiguration = (tc) => !tc.IsRequest,
            });
        }
        private IHttpRequest GenerateRequestOperation(ODataResponse batchResponseOperation, EntityModelSchema model)
        {
            ExceptionUtilities.CheckArgumentNotNull(batchResponseOperation, "batchResponseOperation");
            ExceptionUtilities.CheckArgumentNotNull(model, "model");
            var headers = new Dictionary <string, string> {
                { "GivenPayloadRequestHeader", "PayloadHeaderValue" }
            };

            string   mergeContentType = HttpUtilities.BuildContentType(MimeTypes.ApplicationXml, Encoding.UTF8.WebName, null);
            ODataUri uri  = null;
            HttpVerb verb = HttpVerb.Get;

            if (batchResponseOperation.RootElement != null)
            {
                var complexInstanceCollection = batchResponseOperation.RootElement as ComplexInstanceCollection;
                if (complexInstanceCollection != null)
                {
                    var function = batchResponseOperation.RootElement.GetAnnotation <FunctionAnnotation>();
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.ServiceOperation(function.Function));
                }

                var complexMultivalue = batchResponseOperation.RootElement as ComplexMultiValueProperty;
                if (complexMultivalue != null)
                {
                    var entityType = complexMultivalue.GetAnnotation <EntityModelTypeAnnotation>().EntityModelType as EntityDataType;
                    var entitySet  = model.GetEntitySet(entityType.Definition.Name);
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.EntitySet(entitySet), ODataUriBuilder.Property(entityType.Definition, complexMultivalue.Name));
                }

                var complexProperty = batchResponseOperation.RootElement as ComplexProperty;
                if (complexProperty != null)
                {
                    var type            = complexProperty.GetAnnotation <EntityModelTypeAnnotation>();
                    var complexDataType = type.EntityModelType as ComplexDataType;
                    // Using first because we don't need a specific entity just one that contains this type. If there is more than one the first works fine.
                    var entityType          = model.EntityTypes.Where(et => et.Properties.Where(p => p.Name == complexProperty.Name).Count() == 1).First();
                    var complexType         = model.ComplexTypes.Where(ct => complexDataType.Definition.Name == ct.Name).Single();
                    var complexPropertyName = entityType.AllProperties.Where(p =>
                    {
                        var complex = p.PropertyType as ComplexDataType;
                        if (complex == null)
                        {
                            return(false);
                        }

                        return(complex.Definition.Name == complexDataType.Definition.Name);
                    }).Single();

                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.Property(entityType, complexPropertyName.Name));
                }

                var deferredLink = batchResponseOperation.RootElement as DeferredLink;
                if (deferredLink != null)
                {
                    var navigationProperty = deferredLink.GetAnnotation <NavigationPropertyAnnotation>();
                    var entityType         = model.EntityTypes.Where(et => et.Properties.Where(p => p.Name == navigationProperty.Property.Name).Count() == 1).First();
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.Property(entityType, navigationProperty.Property.Name));
                }

                var linkCollection = batchResponseOperation.RootElement as LinkCollection;
                if (linkCollection != null)
                {
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), SystemSegment.EntityReferenceLinks);
                }

                var entityInstance = batchResponseOperation.RootElement as EntityInstance;
                if (entityInstance != null)
                {
                    var type          = entityInstance.GetAnnotation <EntityModelTypeAnnotation>().EntityModelType as EntityDataType;
                    var entitySetType = model.GetEntitySet(type.Definition.Name);
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.EntitySet(entitySetType));
                }

                var entitySetInstance = batchResponseOperation.RootElement as EntitySetInstance;
                if (entitySetInstance != null)
                {
                    var entitySetType = model.GetEntitySet(entityInstance.FullTypeName);
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.EntitySet(entitySetType));
                }

                var primitiveCollection = batchResponseOperation.RootElement as PrimitiveCollection;
                if (primitiveCollection != null)
                {
                    var function = batchResponseOperation.RootElement.GetAnnotation <FunctionAnnotation>();
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.ServiceOperation(function.Function));
                }

                var primitiveMultiValueProperty = batchResponseOperation.RootElement as PrimitiveMultiValueProperty;
                if (primitiveMultiValueProperty != null)
                {
                    var type       = primitiveMultiValueProperty.GetAnnotation <EntityModelTypeAnnotation>();
                    var entityType = type.EntityModelType as EntityDataType;

                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.EntitySet(model.GetEntitySet(entityType.Definition.Name)), ODataUriBuilder.Property(entityType.Definition, primitiveMultiValueProperty.Name));
                }

                var primitiveProperty = batchResponseOperation.RootElement as PrimitiveProperty;
                if (primitiveProperty != null)
                {
                    var type       = complexProperty.GetAnnotation <EntityModelTypeAnnotation>();
                    var entityType = type.EntityModelType as EntityDataType;

                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.Property(entityType.Definition, primitiveProperty.Name));
                }

                var primitiveValue = batchResponseOperation.RootElement as PrimitiveValue;
                if (primitiveValue != null)
                {
                    var primitiveType = primitiveValue.GetAnnotation <DataTypeAnnotation>();
                    var entityType    = primitiveValue.GetAnnotation <EntityModelTypeAnnotation>().EntityModelType as EntityDataType;
                    var propertyName  = entityType.Definition.Properties.Where(p => p.PropertyType == primitiveType.DataType).First().Name;
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")), ODataUriBuilder.Property(entityType.Definition, propertyName), SystemSegment.Value);
                }

                var odataError = batchResponseOperation.RootElement as ODataErrorPayload;
                if (odataError != null)
                {
                    uri = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")));
                }
            }
            else
            {
                verb = HttpVerb.Put;
                uri  = new ODataUri(ODataUriBuilder.Root(new Uri("http://www.odata.org")));
            }

            ExceptionUtilities.Assert(uri != null, "The request URI has not been defined.");
            var request = this.RequestManager.BuildRequest(uri, verb, headers);

            return(request);
        }
Beispiel #10
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);
        }