package com.sap.core.odata.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.InputStream;
import java.net.URI;
import java.util.ArrayList;
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.StringEntity;
import org.junit.Test;
import com.sap.core.odata.api.client.batch.BatchChangeSet;
import com.sap.core.odata.api.client.batch.BatchChangeSetPart;
import com.sap.core.odata.api.client.batch.BatchPart;
import com.sap.core.odata.api.client.batch.BatchQueryPart;
import com.sap.core.odata.api.client.batch.BatchSingleResponse;
import com.sap.core.odata.api.commons.HttpHeaders;
import com.sap.core.odata.api.ep.EntityProvider;
import com.sap.core.odata.fit.ref.AbstractRefTest;
import com.sap.core.odata.testutil.helper.StringHelper;
public class ClientBatchTest extends AbstractRefTest {
private static final String PUT = "PUT";
private static final String POST = "POST";
private static final String GET = "GET";
private static final String BOUNDARY = "batch_123";
@Test
public void testSimpleBatch() throws Exception {
List<BatchPart> batch = new ArrayList<BatchPart>();
BatchPart request = BatchQueryPart.method(GET).uri("$metadata").build();
batch.add(request);
InputStream body = EntityProvider.writeBatchRequest(batch, BOUNDARY);
String batchRequestBody = StringHelper.inputStreamToString(body, true);
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 Version=\"1.0\""));
assertEquals("application/xml;charset=utf-8", response.getHeader(HttpHeaders.CONTENT_TYPE));
assertNotNull(response.getHeader(HttpHeaders.CONTENT_LENGTH));
}
}
@Test
public void testChangeSetBatch() throws Exception {
List<BatchPart> batch = new ArrayList<BatchPart>();
BatchChangeSet changeSet = BatchChangeSet.newBuilder().build();
Map<String, String> changeSetHeaders = new HashMap<String, String>();
changeSetHeaders.put("content-type", "application/json;odata=verbose");
BatchChangeSetPart changeRequest = BatchChangeSetPart.method(PUT)
.uri("Employees('2')/EmployeeName")
.body("{\"EmployeeName\":\"Frederic Fall MODIFIED\"}")
.headers(changeSetHeaders)
.build();
changeSet.add(changeRequest);
batch.add(changeSet);
BatchPart request = BatchQueryPart.method(GET)
.uri("Employees('2')/EmployeeName/$value")
.build();
batch.add(request);
InputStream body = EntityProvider.writeBatchRequest(batch, BOUNDARY);
String bodyAsString = StringHelper.inputStreamToString(body, true);
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 testContentIdReferencing() throws Exception {
List<BatchPart> batch = new ArrayList<BatchPart>();
BatchChangeSet changeSet = BatchChangeSet.newBuilder().build();
Map<String, String> changeSetHeaders = new HashMap<String, String>();
changeSetHeaders.put("content-type", "application/octet-stream");
changeSetHeaders.put("Accept", "application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1");
BatchChangeSetPart changeRequest = BatchChangeSetPart.method(POST)
.uri("Employees")
.contentId("1")
.body("gAAAAgABwESAAMAAAABAAEA")
.headers(changeSetHeaders)
.build();
changeSet.add(changeRequest);
changeSetHeaders = new HashMap<String, String>();
changeSetHeaders.put("content-type", "application/json;odata=verbose");
BatchChangeSetPart changeRequest2 = BatchChangeSetPart.method(PUT)
.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(GET)
.uri("Employees('7')/EmployeeName")
.contentId("3")
.headers(getRequestHeaders).build();
batch.add(request);
InputStream body = EntityProvider.writeBatchRequest(batch, BOUNDARY);
String bodyAsString = StringHelper.inputStreamToString(body, true);
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 testErrorBatch() throws Exception {
List<BatchPart> batch = new ArrayList<BatchPart>();
BatchPart request = BatchQueryPart.method(GET)
.uri("nonsense")
.build();
batch.add(request);
InputStream body = EntityProvider.writeBatchRequest(batch, BOUNDARY);
String bodyAsString = StringHelper.inputStreamToString(body, true);
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 String body) throws Exception {
final HttpPost post = new HttpPost(URI.create(getEndpoint().toString() + "$batch"));
post.setHeader("Content-Type", "multipart/mixed;boundary=" + BOUNDARY);
HttpEntity entity = new StringEntity(body);
post.setEntity(entity);
HttpResponse response = getHttpClient().execute(post);
assertNotNull(response);
assertEquals(202, response.getStatusLine().getStatusCode());
return response;
}
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 + "--"));
}
}