blob: cf6c9f3b84ad0d8b59d87f79e59f4ab1bb2935ba [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
******************************************************************************/
package org.apache.olingo.odata2.fit.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.olingo.odata2.api.client.batch.BatchChangeSet;
import org.apache.olingo.odata2.api.client.batch.BatchChangeSetPart;
import org.apache.olingo.odata2.api.client.batch.BatchPart;
import org.apache.olingo.odata2.api.client.batch.BatchQueryPart;
import org.apache.olingo.odata2.api.client.batch.BatchSingleResponse;
import org.apache.olingo.odata2.api.commons.HttpContentType;
import org.apache.olingo.odata2.api.commons.HttpHeaders;
import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
import org.apache.olingo.odata2.api.ep.EntityProvider;
import org.apache.olingo.odata2.fit.ref.AbstractRefTest;
import org.apache.olingo.odata2.testutil.helper.StringHelper;
import org.apache.olingo.odata2.testutil.server.ServletType;
import org.junit.Test;
public class ClientBatchTest extends AbstractRefTest {
public ClientBatchTest(final ServletType servletType) {
super(servletType);
}
private static final String BOUNDARY = "batch_123";
@Test
public void simpleBatch() throws Exception {
List<BatchPart> batch = new ArrayList<BatchPart>();
BatchPart request = BatchQueryPart.method(ODataHttpMethod.GET.name()).uri("$metadata").build();
batch.add(request);
InputStream body = EntityProvider.writeBatchRequest(batch, BOUNDARY);
String batchRequestBody = StringHelper.inputStreamToStringCRLFLineBreaks(body);
checkMimeHeaders(batchRequestBody);
checkBoundaryDelimiters(batchRequestBody);
assertTrue(batchRequestBody.contains("GET $metadata HTTP/1.1"));
HttpResponse batchResponse = execute(batchRequestBody);
InputStream responseBody = batchResponse.getEntity().getContent();
String contentType = batchResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue();
List<BatchSingleResponse> responses = EntityProvider.parseBatchResponse(responseBody, contentType);
for (BatchSingleResponse response : responses) {
assertEquals("200", response.getStatusCode());
assertEquals("OK", response.getStatusInfo());
assertTrue(response.getBody().contains("<edmx:Edmx"));
assertEquals("application/xml;charset=utf-8", response.getHeader(HttpHeaders.CONTENT_TYPE));
assertNotNull(response.getHeader(HttpHeaders.CONTENT_LENGTH));
}
}
@Test
public void simpleBatchWithAbsoluteUri() throws Exception {
final String batchRequestBody = StringHelper.inputStreamToStringCRLFLineBreaks(
EntityProvider.writeBatchRequest(
Collections.<BatchPart> singletonList(
BatchQueryPart
.method(ODataHttpMethod.GET.name())
.uri(getEndpoint().getPath() + "Employees('2')/EmployeeName/$value")
.build()),
BOUNDARY));
final HttpResponse batchResponse = execute(batchRequestBody);
final List<BatchSingleResponse> responses = EntityProvider.parseBatchResponse(
batchResponse.getEntity().getContent(),
batchResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue());
assertEquals(1, responses.size());
final BatchSingleResponse response = responses.get(0);
assertEquals(Integer.toString(HttpStatusCodes.OK.getStatusCode()), response.getStatusCode());
assertEquals(HttpStatusCodes.OK.getInfo(), response.getStatusInfo());
assertEquals(EMPLOYEE_2_NAME, response.getBody());
assertEquals(HttpContentType.TEXT_PLAIN_UTF8, response.getHeader(HttpHeaders.CONTENT_TYPE));
assertNotNull(response.getHeader(HttpHeaders.CONTENT_LENGTH));
}
@Test
public void changeSetBatch() throws Exception {
List<BatchPart> batch = new ArrayList<BatchPart>();
BatchChangeSet changeSet = BatchChangeSet.newBuilder().build();
Map<String, String> changeSetHeaders = new HashMap<String, String>();
changeSetHeaders.put(HttpHeaders.CONTENT_TYPE, HttpContentType.APPLICATION_JSON_VERBOSE);
BatchChangeSetPart changeRequest = BatchChangeSetPart.method(ODataHttpMethod.PUT.name())
.uri("Employees('2')/EmployeeName")
.body("{\"EmployeeName\":\"Frederic Fall MODIFIED\"}")
.headers(changeSetHeaders)
.build();
changeSet.add(changeRequest);
batch.add(changeSet);
BatchPart request = BatchQueryPart.method(ODataHttpMethod.GET.name())
.uri("Employees('2')/EmployeeName/$value")
.build();
batch.add(request);
InputStream body = EntityProvider.writeBatchRequest(batch, BOUNDARY);
String bodyAsString = StringHelper.inputStreamToStringCRLFLineBreaks(body);
checkMimeHeaders(bodyAsString);
checkBoundaryDelimiters(bodyAsString);
assertTrue(bodyAsString.contains("PUT Employees('2')/EmployeeName HTTP/1.1"));
assertTrue(bodyAsString.contains("GET Employees('2')/EmployeeName/$value HTTP/1.1"));
assertTrue(bodyAsString.contains("Content-Type: application/json;odata=verbose"));
HttpResponse batchResponse = execute(bodyAsString);
InputStream responseBody = batchResponse.getEntity().getContent();
String contentType = batchResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue();
List<BatchSingleResponse> responses = EntityProvider.parseBatchResponse(responseBody, contentType);
for (BatchSingleResponse response : responses) {
if ("204".equals(response.getStatusCode())) {
assertEquals("No Content", response.getStatusInfo());
} else if ("200".equals(response.getStatusCode())) {
assertEquals("OK", response.getStatusInfo());
assertTrue(response.getBody().contains("Frederic Fall MODIFIED"));
} else {
fail();
}
}
}
@Test
public void changeSetBatchUmlauts() throws Exception {
List<BatchPart> batch = new ArrayList<BatchPart>();
BatchChangeSet changeSet = BatchChangeSet.newBuilder().build();
Map<String, String> changeSetHeaders = new HashMap<String, String>();
changeSetHeaders.put(HttpHeaders.CONTENT_TYPE, HttpContentType.APPLICATION_JSON_VERBOSE);
BatchChangeSetPart changeRequest = BatchChangeSetPart.method(ODataHttpMethod.PUT.name())
.uri("Employees('2')/EmployeeName")
.body("{\"EmployeeName\":\"Frederic üäö Fall\"}")
.headers(changeSetHeaders)
.build();
changeSet.add(changeRequest);
batch.add(changeSet);
BatchPart request = BatchQueryPart.method(ODataHttpMethod.GET.name())
.uri("Employees('2')/EmployeeName/$value")
.build();
batch.add(request);
InputStream body = EntityProvider.writeBatchRequest(batch, BOUNDARY);
StringHelper.Stream bodyStream = StringHelper.toStream(body);
String bodyAsString = bodyStream.asStringWithLineSeparation("\r\n");
checkMimeHeaders(bodyAsString);
checkBoundaryDelimiters(bodyAsString);
assertTrue(bodyAsString.contains("PUT Employees('2')/EmployeeName HTTP/1.1"));
assertTrue(bodyAsString.contains("GET Employees('2')/EmployeeName/$value HTTP/1.1"));
assertTrue(bodyAsString.contains("Content-Type: application/json;odata=verbose"));
HttpResponse batchResponse = execute(bodyStream.asStreamWithLineSeparation("\r\n"));
InputStream responseBody = batchResponse.getEntity().getContent();
//
String contentType = batchResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue();
List<BatchSingleResponse> responses = EntityProvider.parseBatchResponse(responseBody, contentType);
for (BatchSingleResponse response : responses) {
if ("204".equals(response.getStatusCode())) {
assertEquals("No Content", response.getStatusInfo());
} else if ("200".equals(response.getStatusCode())) {
assertEquals("OK", response.getStatusInfo());
assertTrue(response.getBody().contains("Frederic üäö Fall"));
} else {
fail();
}
}
}
@Test
public void contentIdReferencing() throws Exception {
List<BatchPart> batch = new ArrayList<BatchPart>();
BatchChangeSet changeSet = BatchChangeSet.newBuilder().build();
Map<String, String> changeSetHeaders = new HashMap<String, String>();
changeSetHeaders.put(HttpHeaders.CONTENT_TYPE, "application/octet-stream");
changeSetHeaders.put(HttpHeaders.ACCEPT,
"application/atom+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1");
BatchChangeSetPart changeRequest = BatchChangeSetPart.method(ODataHttpMethod.POST.name())
.uri("Employees")
.contentId("1")
.body("gAAAAgABwESAAMAAAABAAEA")
.headers(changeSetHeaders)
.build();
changeSet.add(changeRequest);
changeSetHeaders = new HashMap<String, String>();
changeSetHeaders.put(HttpHeaders.CONTENT_TYPE, HttpContentType.APPLICATION_JSON_VERBOSE);
BatchChangeSetPart changeRequest2 = BatchChangeSetPart.method(ODataHttpMethod.PUT.name())
.uri("$1/EmployeeName")
.contentId("2")
.body("{\"EmployeeName\":\"Frederic Fall MODIFIED\"}")
.headers(changeSetHeaders)
.build();
changeSet.add(changeRequest2);
batch.add(changeSet);
Map<String, String> getRequestHeaders = new HashMap<String, String>();
getRequestHeaders.put("content-id", "3");
BatchPart request = BatchQueryPart.method(ODataHttpMethod.GET.name())
.uri("Employees('7')/EmployeeName")
.contentId("3")
.headers(getRequestHeaders).build();
batch.add(request);
InputStream body = EntityProvider.writeBatchRequest(batch, BOUNDARY);
String bodyAsString = StringHelper.inputStreamToStringCRLFLineBreaks(body);
checkMimeHeaders(bodyAsString);
checkBoundaryDelimiters(bodyAsString);
assertTrue(bodyAsString.contains("POST Employees HTTP/1.1"));
assertTrue(bodyAsString.contains("PUT $1/EmployeeName"));
assertTrue(bodyAsString.contains("GET Employees('7')/EmployeeName HTTP/1.1"));
HttpResponse batchResponse = execute(bodyAsString);
InputStream responseBody = batchResponse.getEntity().getContent();
String contentType = batchResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue();
List<BatchSingleResponse> responses = EntityProvider.parseBatchResponse(responseBody, contentType);
for (BatchSingleResponse response : responses) {
if ("1".equals(response.getContentId())) {
assertEquals("201", response.getStatusCode());
assertEquals("Created", response.getStatusInfo());
} else if ("2".equals(response.getContentId())) {
assertEquals("204", response.getStatusCode());
assertEquals("No Content", response.getStatusInfo());
} else if ("3".equals(response.getContentId())) {
assertEquals("200", response.getStatusCode());
assertEquals("OK", response.getStatusInfo());
} else {
fail();
}
}
}
@Test
public void errorBatch() throws Exception {
List<BatchPart> batch = new ArrayList<BatchPart>();
BatchPart request = BatchQueryPart.method(ODataHttpMethod.GET.name())
.uri("nonsense")
.build();
batch.add(request);
InputStream body = EntityProvider.writeBatchRequest(batch, BOUNDARY);
String bodyAsString = StringHelper.inputStreamToStringCRLFLineBreaks(body);
checkMimeHeaders(bodyAsString);
checkBoundaryDelimiters(bodyAsString);
assertTrue(bodyAsString.contains("GET nonsense HTTP/1.1"));
HttpResponse batchResponse = execute(bodyAsString);
InputStream responseBody = batchResponse.getEntity().getContent();
String contentType = batchResponse.getFirstHeader(HttpHeaders.CONTENT_TYPE).getValue();
List<BatchSingleResponse> responses = EntityProvider.parseBatchResponse(responseBody, contentType);
for (BatchSingleResponse response : responses) {
assertEquals("404", response.getStatusCode());
assertEquals("Not Found", response.getStatusInfo());
}
}
private HttpResponse execute(final HttpEntity entity) throws IOException {
final HttpPost post = new HttpPost(URI.create(getEndpoint().toString() + "$batch"));
post.setHeader(HttpHeaders.CONTENT_TYPE, "multipart/mixed;boundary=" + BOUNDARY);
post.setEntity(entity);
HttpResponse response = getHttpClient().execute(post);
assertNotNull(response);
assertEquals(HttpStatusCodes.ACCEPTED.getStatusCode(), response.getStatusLine().getStatusCode());
return response;
}
private HttpResponse execute(final String body) throws IOException {
return execute(new StringEntity(body));
}
private HttpResponse execute(final InputStream body) throws IOException {
return execute(new InputStreamEntity(body, -1));
}
private void checkMimeHeaders(final String requestBody) {
assertTrue(requestBody.contains("Content-Type: application/http"));
assertTrue(requestBody.contains("Content-Transfer-Encoding: binary"));
}
private void checkBoundaryDelimiters(final String requestBody) {
assertTrue(requestBody.contains("--" + BOUNDARY));
assertTrue(requestBody.contains("--" + BOUNDARY + "--"));
}
}