/// <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> /// Deserializes the given response's binary payload into a batch payload /// </summary> /// <param name="requestPayload">The batch request payload that corresponds to the request</param> /// <param name="response">The response to deserialize</param> /// <returns>The deserialized batch response payload</returns> public BatchResponsePayload DeserializeBatchResponse(BatchRequestPayload requestPayload, HttpResponseData response) { var encoding = HttpUtilities.DefaultEncoding; string charset; if (response.TryGetMimeCharset(out charset)) { encoding = Encoding.GetEncoding(charset); } MultipartMimeData <MimePartData <byte[]> > split; ExceptionUtilities.Assert(TrySplitMimePart(response, encoding, out split), "Failed to split batch response body"); var batchResponse = new BatchResponsePayload(); var requestPartQueue = new Queue <IMimePart>(requestPayload.Parts); foreach (var subPart in split.ToList()) { MultipartMimeData <MimePartData <byte[]> > splitChangeset; if (TrySplitMimePart(subPart, encoding, out splitChangeset)) { ExceptionUtilities.Assert(requestPartQueue.Count > 0, "Response changeset did not line up anything in request"); var requestChangeset = requestPartQueue.Dequeue() as BatchRequestChangeset; ExceptionUtilities.CheckObjectNotNull(requestChangeset, "Response changeset did not line up with a request changeset"); var requestsQueue = new Queue <IHttpRequest>(requestChangeset.Operations); var changeset = new BatchResponseChangeset(); changeset.Headers.AddRange(splitChangeset.Headers); foreach (var changesetPart in splitChangeset) { ExceptionUtilities.Assert(requestsQueue.Count > 0, "Response did not line up anything in request changeset"); changeset.Add(this.BuildResponseFromPart(changesetPart, requestsQueue.Dequeue(), encoding)); } batchResponse.Add(changeset); } else { ExceptionUtilities.Assert(requestPartQueue.Count > 0, "Response did not line up anything in request"); var requestOperation = requestPartQueue.Dequeue() as MimePartData <IHttpRequest>; ExceptionUtilities.CheckObjectNotNull(requestOperation, "Response operation did not line up with request operation"); batchResponse.Add(this.BuildResponseFromPart(subPart, requestOperation.Body, encoding)); } } return(batchResponse); }
/// <summary> /// Compare aspects of batch response changeSets specific to response changeSets /// </summary> /// <param name="expectedBatchChangeset">Expected batch response changeSets</param> /// <param name="actualBatchChangeset">Actual batch response changeSets</param> private void CompareResponseChangeSets(BatchResponseChangeset expectedBatchChangeset, BatchResponseChangeset actualBatchChangeset) { ExceptionUtilities.CheckArgumentNotNull(actualBatchChangeset, "actualBatchChangeset"); ExceptionUtilities.CheckArgumentNotNull(expectedBatchChangeset, "expectedBatchChangeset"); this.Assert.IsNotNull(actualBatchChangeset.Operations, "actual Operations cannot be null"); this.Assert.IsNotNull(expectedBatchChangeset.Operations, "expected Operations cannot be null"); var actualOperations = actualBatchChangeset.Operations.ToList(); var expectedOperations = expectedBatchChangeset.Operations.ToList(); for (int i = 0; i < actualOperations.Count; i++) { var actualPart = actualOperations[i]; var expectedPart = expectedOperations[i]; this.CompareResponseParts(expectedPart, actualPart); } }
/// <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())); }
private BatchRequestChangeset GenerateRequestChangeset(BatchResponseChangeset batchResponseChangeset, EntityModelSchema model) { ExceptionUtilities.CheckArgumentNotNull(batchResponseChangeset, "batchResponseChangeset"); ExceptionUtilities.CheckArgumentNotNull(model, "model"); var contentTypeValue = batchResponseChangeset.GetHeaderValueIfExists(HttpHeaders.ContentType); ExceptionUtilities.CheckObjectNotNull(contentTypeValue, "Can't generate request for a response with no content type"); var parts = contentTypeValue.Split(';'); string boundary = parts.Where(s => s.Contains("boundary")).Single(); string contentType = String.Concat(parts.Where(s=> s.Contains("charset")).ToArray()); IList<MimePartData<IHttpRequest>> operations = new List<MimePartData<IHttpRequest>>(); foreach (var operation in batchResponseChangeset.Operations) { operations.Add(this.GenerateRequestOperation((ODataResponse)operation, model).AsBatchFragment()); } return BatchPayloadBuilder.RequestChangeset(boundary, contentType, operations.ToArray()); }
private BatchRequestChangeset GenerateRequestChangeset(BatchResponseChangeset batchResponseChangeset, EntityModelSchema model) { ExceptionUtilities.CheckArgumentNotNull(batchResponseChangeset, "batchResponseChangeset"); ExceptionUtilities.CheckArgumentNotNull(model, "model"); var contentTypeValue = batchResponseChangeset.GetHeaderValueIfExists(HttpHeaders.ContentType); ExceptionUtilities.CheckObjectNotNull(contentTypeValue, "Can't generate request for a response with no content type"); var parts = contentTypeValue.Split(';'); string boundary = parts.Where(s => s.Contains("boundary")).Single(); string contentType = String.Concat(parts.Where(s => s.Contains("charset")).ToArray()); IList <MimePartData <IHttpRequest> > operations = new List <MimePartData <IHttpRequest> >(); foreach (var operation in batchResponseChangeset.Operations) { operations.Add(this.GenerateRequestOperation((ODataResponse)operation, model).AsBatchFragment()); } return(BatchPayloadBuilder.RequestChangeset(boundary, contentType, operations.ToArray())); }
/// <summary> /// Generates a dummy request based on the supplied response and model /// </summary> /// <param name="batchResponse">Response to build the request for.</param> /// <param name="model">Model to get the types from.</param> /// <returns></returns> public BatchRequestPayload GenerateRequestPayload(BatchResponsePayload batchResponse, EntityModelSchema model) { ExceptionUtilities.CheckArgumentNotNull(batchResponse, "batchResponse"); ExceptionUtilities.CheckArgumentNotNull(model, "model"); var batchRequest = new BatchRequestPayload(); foreach (var part in batchResponse.Parts) { var operation = part as MimePartData <HttpResponseData>; if (operation != null) { batchRequest.Add(this.GenerateRequestOperation(operation.Body as ODataResponse, model).AsBatchFragment()); } BatchResponseChangeset changeset = part as BatchResponseChangeset; if (changeset != null) { batchRequest.Add(this.GenerateRequestChangeset(changeset, model)); } } return(batchRequest); }
/// <summary> /// Deserializes the given response's binary payload into a batch payload /// </summary> /// <param name="requestPayload">The batch request payload that corresponds to the request</param> /// <param name="response">The response to deserialize</param> /// <returns>The deserialized batch response payload</returns> public BatchResponsePayload DeserializeBatchResponse(BatchRequestPayload requestPayload, HttpResponseData response) { var encoding = HttpUtilities.DefaultEncoding; string charset; if (response.TryGetMimeCharset(out charset)) { encoding = Encoding.GetEncoding(charset); } MultipartMimeData<MimePartData<byte[]>> split; ExceptionUtilities.Assert(TrySplitMimePart(response, encoding, out split), "Failed to split batch response body"); var batchResponse = new BatchResponsePayload(); var requestPartQueue = new Queue<IMimePart>(requestPayload.Parts); foreach (var subPart in split.ToList()) { MultipartMimeData<MimePartData<byte[]>> splitChangeset; if (TrySplitMimePart(subPart, encoding, out splitChangeset)) { ExceptionUtilities.Assert(requestPartQueue.Count > 0, "Response changeset did not line up anything in request"); var requestChangeset = requestPartQueue.Dequeue() as BatchRequestChangeset; ExceptionUtilities.CheckObjectNotNull(requestChangeset, "Response changeset did not line up with a request changeset"); var requestsQueue = new Queue<IHttpRequest>(requestChangeset.Operations); var changeset = new BatchResponseChangeset(); changeset.Headers.AddRange(splitChangeset.Headers); foreach (var changesetPart in splitChangeset) { ExceptionUtilities.Assert(requestsQueue.Count > 0, "Response did not line up anything in request changeset"); changeset.Add(this.BuildResponseFromPart(changesetPart, requestsQueue.Dequeue(), encoding)); } batchResponse.Add(changeset); } else { ExceptionUtilities.Assert(requestPartQueue.Count > 0, "Response did not line up anything in request"); var requestOperation = requestPartQueue.Dequeue() as MimePartData<IHttpRequest>; ExceptionUtilities.CheckObjectNotNull(requestOperation, "Response operation did not line up with request operation"); batchResponse.Add(this.BuildResponseFromPart(subPart, requestOperation.Body, encoding)); } } return batchResponse; }