/// <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); }
/// <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); }
/// <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)), }); }
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); }); }
/// <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)), }); }
/// <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); }
/// <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); }