/// <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="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 BatchResponseChangeset InResponseChangeset <T>( this T payload, int statuscode, IRandomNumberGenerator random, IODataRequestManager requestManager, int operationsBefore = 0, int operationsAfter = 0, ODataVersion version = ODataVersion.V4) where T : PayloadTestDescriptor { ExceptionUtilities.CheckArgumentNotNull(payload, "payload"); ExceptionUtilities.CheckArgumentNotNull(statuscode, "statuscode"); ExceptionUtilities.CheckArgumentNotNull(random, "random"); ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager"); var extraOperations = BatchUtils.ExtraResponseOperations(random, (EdmModel)payload.PayloadEdmModel, version); // Build the list of all properties IEnumerable <IMimePart> operations = Enumerable.Range(0, operationsBefore).Select(i => random.ChooseFrom(extraOperations)); operations.ConcatSingle(InResponseOperation(payload, statuscode, requestManager)); operations = operations.Concat(Enumerable.Range(0, operationsAfter).Select(i => random.ChooseFrom(extraOperations))); var changeset = BatchPayloadBuilder.ResponseChangeset("changeset_" + Guid.NewGuid().ToString(), Encoding.UTF8.WebName, operations.ToArray()); return(changeset); }
/// <summary> /// Gets the response changeset with the specified mime parts and content type. /// </summary> /// <param name="operations">Operations to go into changeset</param> /// <param name="contentTypeName">ContentType associated with changeset</param> /// <param name="requestManager">RequestManager to build the response changeset.</param> /// <returns>A batch response changeset.</returns> public static BatchResponseChangeset GetResponseChangeset( IMimePart[] operations, IODataRequestManager requestManager ) { ExceptionUtilities.CheckArgumentNotNull(operations, "operations"); ExceptionUtilities.CheckArgumentNotNull(requestManager, "requestManager"); return(BatchPayloadBuilder.ResponseChangeset("changeset_" + Guid.NewGuid().ToString(), Encoding.UTF8.WebName, operations.ToArray())); }
/// <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())); }
/// <summary> /// Generates extra response changesets. /// </summary> /// <param name="random">For generating arbitrary changesets.</param> /// <param name="model">For adding any generated types to.</param> /// <param name="version">Maximum version of any generated types.</param> /// <returns>An array of response changesets.</returns> public static BatchResponseChangeset[] ExtraResponseChangesets( IRandomNumberGenerator random, EdmModel model = null, ODataVersion version = ODataVersion.V4) { ExceptionUtilities.CheckArgumentNotNull(random, "random"); string contentType = HttpUtilities.BuildContentType(MimeTypes.ApplicationXml, Encoding.UTF8.WebName, null); var responses = ExtraResponseOperations(random, model, version); List <BatchResponseChangeset> changesets = new List <BatchResponseChangeset>(); for (int x = 0; x < 5; ++x) { IEnumerable <IMimePart> operations = Enumerable.Range(0, random.Next(4)).Select(i => random.ChooseFrom(responses)); changesets.Add(BatchPayloadBuilder.ResponseChangeset("changeset_" + Guid.NewGuid().ToString(), contentType, operations.ToArray())); } return(changesets.ToArray()); }
/// <summary> /// Generates the raw test message with mixed encodings defined by the test case, as well as the expected ODataPayloadElement. /// </summary> /// <param name="testCase">The test case defining the structure and encodings of the batch payload.</param> /// <param name="payload">The payload to use for all generated batch operations.</param> /// <param name="payloadUri">The URI to use for all generated batch operations.</param> /// <param name="isRequest">If true, generates a batch request, otherwise a batch response.</param> /// <returns>The test descriptor for this test case/configuration.</returns> private BatchReaderMixedEncodingTestDescriptor CreateTestDescriptor(BatchReaderMixedEncodingTestCase testCase, ODataPayloadElement payload, ODataUri payloadUri, bool isRequest) { ExceptionUtilities.Assert(testCase.BatchEncoding != null, "Batch encoding has not been specified."); string batchBoundary = "batch_" + Guid.NewGuid().ToString(); string payloadUriString = this.UriConverter.ConvertToString(payloadUri); var batchPayload = isRequest ? (ODataPayloadElement) new BatchRequestPayload() : (ODataPayloadElement) new BatchResponsePayload(); batchPayload.AddAnnotation(new BatchBoundaryAnnotation(batchBoundary)); var rawMessage = new List <byte>(); // TODO: Batch reader does not support multi codepoint encodings Encoding unsupportedEncoding = AsUnsupportedEncoding(testCase.BatchEncoding); foreach (var changeset in testCase.Changesets) { string changesetBoundary = "change_" + Guid.NewGuid().ToString(); Encoding changesetEncoding = changeset.ChangesetEncoding ?? testCase.BatchEncoding; // TODO: Batch reader does not support multi codepoint encodings unsupportedEncoding = unsupportedEncoding ?? AsUnsupportedEncoding(changesetEncoding); string changesetContentType = HttpUtilities.BuildContentType( MimeTypes.MultipartMixed, changeset.ChangesetEncoding == null ? string.Empty : changeset.ChangesetEncoding.WebName, changesetBoundary); rawMessage.AddRange( WriteMessagePart( testCase.BatchEncoding, (writer) => { writer.Write("--"); writer.WriteLine(batchBoundary); writer.WriteLine(HttpHeaders.ContentType + ": " + changesetContentType); writer.WriteLine(); })); var mimeParts = new List <IMimePart>(); int contentId = 0; foreach (var operation in changeset.Operations) { ExceptionUtilities.Assert(operation.PayloadFormat == ODataFormat.Atom || operation.PayloadFormat == ODataFormat.Json, "Payload format must be ATOM or JSON."); string formatType = MimeTypes.ApplicationAtomXml + ";type=entry"; Encoding payloadEncoding = operation.OperationEncoding ?? changesetEncoding; string payloadContentType = HttpUtilities.BuildContentType( formatType, operation.OperationEncoding == null ? string.Empty : operation.OperationEncoding.WebName, string.Empty); string httpStatus = isRequest ? "POST " + payloadUriString + " HTTP/1.1" : "HTTP/1.1 201 Created"; rawMessage.AddRange( WriteMessagePart( changesetEncoding, (writer) => { writer.WriteLine(); writer.Write("--"); writer.WriteLine(changesetBoundary); writer.WriteLine(HttpHeaders.ContentType + ": application/http"); writer.WriteLine(HttpHeaders.ContentTransferEncoding + ": binary"); writer.WriteLine(HttpHeaders.ContentId + ": " + (++contentId).ToString()); writer.WriteLine(); writer.WriteLine(httpStatus); writer.WriteLine(HttpHeaders.ContentType + ": " + payloadContentType); writer.WriteLine(); })); IPayloadSerializer payloadSerializer = operation.PayloadFormat == ODataFormat.Atom ? (IPayloadSerializer) new XmlPayloadSerializer(this.PayloadElementToXmlConverter) : (IPayloadSerializer) new JsonPayloadSerializer(this.PayloadElementToJsonConverter.ConvertToJson); byte[] payloadBytes = payloadSerializer.SerializeToBinary(payload, payloadEncoding.WebName); rawMessage.AddRange(payloadBytes.Skip(payloadEncoding.GetPreamble().Length)); if (isRequest) { var request = this.RequestManager.BuildRequest(payloadUri, HttpVerb.Post, new Dictionary <string, string> { { HttpHeaders.ContentType, payloadContentType } }); request.Body = new ODataPayloadBody(payloadBytes, payload); mimeParts.Add(request); } else { var httpResponseData = new HttpResponseData { StatusCode = HttpStatusCode.Created, }; httpResponseData.Headers.Add(HttpHeaders.ContentType, payloadContentType); var response = new ODataResponse(httpResponseData) { Body = payloadBytes, RootElement = payload }; mimeParts.Add(response); } } rawMessage.AddRange( WriteMessagePart( changesetEncoding, (writer) => { writer.WriteLine(); writer.Write("--"); writer.Write(changesetBoundary); writer.WriteLine("--"); })); if (isRequest) { ((BatchRequestPayload)batchPayload).Add(BatchPayloadBuilder.RequestChangeset(changesetBoundary, changesetEncoding.WebName, mimeParts.ToArray())); } else { ((BatchResponsePayload)batchPayload).Add(BatchPayloadBuilder.ResponseChangeset(changesetBoundary, changesetEncoding.WebName, mimeParts.ToArray())); } } rawMessage.AddRange( WriteMessagePart( testCase.BatchEncoding, (writer) => { writer.WriteLine(); writer.Write("--"); writer.Write(batchBoundary); writer.WriteLine("--"); })); return(new BatchReaderMixedEncodingTestDescriptor(this.PayloadReaderSettings) { BatchContentTypeHeader = HttpUtilities.BuildContentType(MimeTypes.MultipartMixed, testCase.BatchEncoding.WebName, batchBoundary), RawMessage = rawMessage.ToArray(), PayloadElement = batchPayload, ExpectedException = unsupportedEncoding == null ? null : ODataExpectedExceptions.ODataException("ODataBatchReaderStream_MultiByteEncodingsNotSupported", unsupportedEncoding.WebName) }); }