olingo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jhues...@apache.org
Subject [2/4] Batch Support, Validation in Deserialization
Date Fri, 23 Aug 2013 14:29:03 GMT
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
index cb2f420..b0babf7 100644
--- a/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
@@ -30,11 +30,8 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.List;
 
-import org.junit.BeforeClass;
-import org.junit.Test;
-
 import org.apache.olingo.odata2.api.batch.BatchException;
-import org.apache.olingo.odata2.api.batch.BatchPart;
+import org.apache.olingo.odata2.api.batch.BatchRequestPart;
 import org.apache.olingo.odata2.api.commons.HttpHeaders;
 import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
 import org.apache.olingo.odata2.api.ep.EntityProviderBatchProperties;
@@ -42,24 +39,27 @@ import org.apache.olingo.odata2.api.processor.ODataRequest;
 import org.apache.olingo.odata2.core.ODataPathSegmentImpl;
 import org.apache.olingo.odata2.core.PathInfoImpl;
 import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.junit.BeforeClass;
+import org.junit.Test;
 
 /**
  *  
  */
 public class BatchRequestParserTest {
 
+  private static final String LF = "\r\n";
   private static final String CONTENT_ID_REFERENCE = "NewEmployee";
   private static final String PUT_MIME_HEADER_CONTENT_ID = "BBB_MIMEPART1";
   private static final String PUT_REQUEST_HEADER_CONTENT_ID = "BBB_REQUEST1";
   private static final String SERVICE_ROOT = "http://localhost/odata/";
   private static EntityProviderBatchProperties batchProperties;
   private static final String contentType = "multipart/mixed;boundary=batch_8194-cf13-1f56";
-  private static final String MIME_HEADERS = "Content-Type: application/http" + "\r\n"
-      + "Content-Transfer-Encoding: binary" + "\r\n";
-  private static final String GET_REQUEST = MIME_HEADERS + "\n"
-      + "GET Employees('1')/EmployeeName HTTP/1.1" + "\n"
-      + "\n"
-      + "\n";
+  private static final String MIME_HEADERS = "Content-Type: application/http" + LF
+      + "Content-Transfer-Encoding: binary" + LF;
+  private static final String GET_REQUEST = MIME_HEADERS + LF
+      + "GET Employees('1')/EmployeeName HTTP/1.1" + LF
+      + LF
+      + LF;
 
   @BeforeClass
   public static void setProperties() throws URISyntaxException {
@@ -78,10 +78,10 @@ public class BatchRequestParserTest {
     }
 
     BatchRequestParser parser = new BatchRequestParser(contentType, batchProperties);
-    List<BatchPart> batchParts = parser.parse(in);
-    assertNotNull(batchParts);
-    assertEquals(false, batchParts.isEmpty());
-    for (BatchPart object : batchParts) {
+    List<BatchRequestPart> batchRequestParts = parser.parse(in);
+    assertNotNull(batchRequestParts);
+    assertEquals(false, batchRequestParts.isEmpty());
+    for (BatchRequestPart object : batchRequestParts) {
       if (!object.isChangeSet()) {
         assertEquals(1, object.getRequests().size());
         ODataRequest retrieveRequest = object.getRequests().get(0);
@@ -128,34 +128,34 @@ public class BatchRequestParserTest {
       throw new IOException("Requested file '" + fileName + "' was not found.");
     }
     String content = StringHelper.inputStreamToString(contentInputStream);
-    String batch = "\r\n"
-        + "--batch_8194-cf13-1f56" + "\r" + "\n"
-        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + "\r\n"
-        + "\r\n"
-        + "--changeset_f980-1cb6-94dd" + "\r\n"
-        + "content-type:     Application/http" + "\r\n"
-        + "content-transfer-encoding: Binary" + "\r\n"
-        + "Content-ID: 1" + "\r\n"
-        + "\r\n"
-        + "POST Employees HTTP/1.1" + "\r\n"
-        + "Content-length: 100000" + "\r\n"
-        + "Content-type: application/octet-stream" + "\r\n"
-        + "\r\n"
-        + content + "\r\n"
-        + "\r\n"
-        + "--changeset_f980-1cb6-94dd--" + "\r\n"
-        + "\r\n"
-        + "--batch_8194-cf13-1f56" + "\r\n"
+    String batch = LF
+        + "--batch_8194-cf13-1f56" + LF
+        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + LF
+        + LF
+        + "--changeset_f980-1cb6-94dd" + LF
+        + "content-type:     Application/http" + LF
+        + "content-transfer-encoding: Binary" + LF
+        + "Content-ID: 1" + LF
+        + LF
+        + "POST Employees HTTP/1.1" + LF
+        + "Content-length: 100000" + LF
+        + "Content-type: application/octet-stream" + LF
+        + LF
+        + content + LF
+        + LF
+        + "--changeset_f980-1cb6-94dd--" + LF
+        + LF
+        + "--batch_8194-cf13-1f56" + LF
         + MIME_HEADERS
-        + "\r\n"
-        + "GET Employees?$filter=Age%20gt%2040 HTTP/1.1" + "\r\n"
-        + "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + "\r\n"
-        + "MaxDataServiceVersion: 2.0" + "\r\n"
-        + "\r\n"
-        + "\r\n"
+        + LF
+        + "GET Employees?$filter=Age%20gt%2040 HTTP/1.1" + LF
+        + "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + LF
+        + "MaxDataServiceVersion: 2.0" + LF
+        + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
-    List<BatchPart> batchParts = parse(batch);
-    for (BatchPart object : batchParts) {
+    List<BatchRequestPart> BatchRequestParts = parse(batch);
+    for (BatchRequestPart object : BatchRequestParts) {
       if (!object.isChangeSet()) {
         assertEquals(1, object.getRequests().size());
         ODataRequest retrieveRequest = object.getRequests().get(0);
@@ -167,7 +167,7 @@ public class BatchRequestParserTest {
         for (ODataRequest request : requests) {
           assertEquals(ODataHttpMethod.POST, request.getMethod());
           assertEquals("100000", request.getRequestHeaderValue(HttpHeaders.CONTENT_LENGTH.toLowerCase()));
-          assertEquals("1", request.getRequestHeaderValue(BatchConstants.MIME_HEADER_CONTENT_ID.toLowerCase()));
+          assertEquals("1", request.getRequestHeaderValue(BatchHelper.MIME_HEADER_CONTENT_ID.toLowerCase()));
           assertEquals("application/octet-stream", request.getContentType());
           InputStream body = request.getBody();
           assertEquals(content, StringHelper.inputStreamToString(body));
@@ -186,23 +186,23 @@ public class BatchRequestParserTest {
       throw new IOException("Requested file '" + fileName + "' was not found.");
     }
     StringHelper.inputStreamToString(contentInputStream);
-    String batch = "\r\n"
-        + "--batch_8194-cf13-1f56" + "\r" + "\n"
-        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + "\r\n"
-        + "\r\n"
-        + "--changeset_f980-1cb6-94dd" + "\r\n"
+    String batch = LF
+        + "--batch_8194-cf13-1f56" + LF
+        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + LF
+        + LF
+        + "--changeset_f980-1cb6-94dd" + LF
         + MIME_HEADERS
-        + "\r\n"
-        + "POST Employees('2') HTTP/1.1" + "\r\n"
-        + "Content-Length: 100" + "\r\n"
-        + "Content-Type: application/octet-stream" + "\r\n"
-        + "\r\n"
-        + "\r\n"
-        + "--changeset_f980-1cb6-94dd--" + "\r\n"
-        + "\r\n"
+        + LF
+        + "POST Employees('2') HTTP/1.1" + LF
+        + "Content-Length: 100" + LF
+        + "Content-Type: application/octet-stream" + LF
+        + LF
+        + LF
+        + "--changeset_f980-1cb6-94dd--" + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
-    List<BatchPart> batchParts = parse(batch);
-    for (BatchPart object : batchParts) {
+    List<BatchRequestPart> batchRequestParts = parse(batch);
+    for (BatchRequestPart object : batchRequestParts) {
       if (object.isChangeSet()) {
         List<ODataRequest> requests = object.getRequests();
         for (ODataRequest request : requests) {
@@ -219,21 +219,21 @@ public class BatchRequestParserTest {
   public void testBoundaryParameterWithQuotas() throws BatchException {
     String contentType = "multipart/mixed; boundary=\"batch_1.2+34:2j)0?\"";
 
-    String batch = "--batch_1.2+34:2j)0?" + "\n"
+    String batch = "--batch_1.2+34:2j)0?" + LF
         + GET_REQUEST
         + "--batch_1.2+34:2j)0?--";
     InputStream in = new ByteArrayInputStream(batch.getBytes());
     BatchRequestParser parser = new BatchRequestParser(contentType, batchProperties);
-    List<BatchPart> batchParts = parser.parse(in);
-    assertNotNull(batchParts);
-    assertEquals(false, batchParts.isEmpty());
+    List<BatchRequestPart> batchRequestParts = parser.parse(in);
+    assertNotNull(batchRequestParts);
+    assertEquals(false, batchRequestParts.isEmpty());
   }
 
   @Test(expected = BatchException.class)
   public void testBatchWithInvalidContentType() throws BatchException {
     String invalidContentType = "multipart;boundary=batch_1740-bb84-2f7f";
 
-    String batch = "--batch_1740-bb84-2f7f" + "\n"
+    String batch = "--batch_1740-bb84-2f7f" + LF
         + GET_REQUEST
         + "--batch_1740-bb84-2f7f--";
     InputStream in = new ByteArrayInputStream(batch.getBytes());
@@ -244,7 +244,7 @@ public class BatchRequestParserTest {
   @Test(expected = BatchException.class)
   public void testBatchWithoutBoundaryParameter() throws BatchException {
     String invalidContentType = "multipart/mixed";
-    String batch = "--batch_1740-bb84-2f7f" + "\n"
+    String batch = "--batch_1740-bb84-2f7f" + LF
         + GET_REQUEST
         + "--batch_1740-bb84-2f7f--";
     InputStream in = new ByteArrayInputStream(batch.getBytes());
@@ -255,7 +255,7 @@ public class BatchRequestParserTest {
   @Test(expected = BatchException.class)
   public void testBoundaryParameterWithoutQuota() throws BatchException {
     String invalidContentType = "multipart;boundary=batch_1740-bb:84-2f7f";
-    String batch = "--batch_1740-bb:84-2f7f" + "\n"
+    String batch = "--batch_1740-bb:84-2f7f" + LF
         + GET_REQUEST
         + "--batch_1740-bb:84-2f7f--";
     InputStream in = new ByteArrayInputStream(batch.getBytes());
@@ -265,7 +265,7 @@ public class BatchRequestParserTest {
 
   @Test(expected = BatchException.class)
   public void testWrongBoundaryString() throws BatchException {
-    String batch = "--batch_8194-cf13-1f5" + "\n"
+    String batch = "--batch_8194-cf13-1f5" + LF
         + GET_REQUEST
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
@@ -273,9 +273,9 @@ public class BatchRequestParserTest {
 
   @Test(expected = BatchException.class)
   public void testBoundaryWithoutHyphen() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
         + GET_REQUEST
-        + "batch_8194-cf13-1f56" + "\n"
+        + "batch_8194-cf13-1f56" + LF
         + GET_REQUEST
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
@@ -283,7 +283,7 @@ public class BatchRequestParserTest {
 
   @Test(expected = BatchException.class)
   public void testNoBoundaryString() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
         + GET_REQUEST
         //+ no boundary string
         + GET_REQUEST
@@ -293,161 +293,184 @@ public class BatchRequestParserTest {
 
   @Test(expected = BatchException.class)
   public void testBatchBoundaryEqualsChangeSetBoundary() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
-        + "Content-Type: multipart/mixed;boundary=batch_8194-cf13-1f56" + "\n"
-        + "\n"
-        + "--batch_8194-cf13-1f56" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
+        + "Content-Type: multipart/mixed;boundary=batch_8194-cf13-1f56" + LF
+        + LF
+        + "--batch_8194-cf13-1f56" + LF
         + MIME_HEADERS
-        + "\n"
-        + "PUT Employees('2')/EmployeeName HTTP/1.1" + "\n"
-        + "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + "\n"
-        + "Content-Type: application/json;odata=verbose" + "\n"
-        + "MaxDataServiceVersion: 2.0" + "\n"
-        + "\n"
-        + "{\"EmployeeName\":\"Frederic Fall MODIFIED\"}" + "\n"
-        + "\n"
+        + LF
+        + "PUT Employees('2')/EmployeeName HTTP/1.1" + LF
+        + "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + LF
+        + "Content-Type: application/json;odata=verbose" + LF
+        + "MaxDataServiceVersion: 2.0" + LF
+        + LF
+        + "{\"EmployeeName\":\"Frederic Fall MODIFIED\"}" + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
 
   @Test(expected = BatchException.class)
   public void testNoContentType() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
-        + "Content-Transfer-Encoding: binary" + "\n"
-        + "\n"
-        + "GET Employees('1')/EmployeeName HTTP/1.1" + "\n"
-        + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
+        + "Content-Transfer-Encoding: binary" + LF
+        + LF
+        + "GET Employees('1')/EmployeeName HTTP/1.1" + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
 
   @Test(expected = BatchException.class)
   public void testMimeHeaderContentType() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
-        + "Content-Type: text/plain" + "\n"
-        + "Content-Transfer-Encoding: binary" + "\n"
-        + "\n"
-        + "GET Employees('1')/EmployeeName HTTP/1.1" + "\n"
-        + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
+        + "Content-Type: text/plain" + LF
+        + "Content-Transfer-Encoding: binary" + LF
+        + LF
+        + "GET Employees('1')/EmployeeName HTTP/1.1" + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
 
   @Test(expected = BatchException.class)
   public void testMimeHeaderEncoding() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
-        + "Content-Type: application/http" + "\n"
-        + "Content-Transfer-Encoding: 8bit" + "\n"
-        + "\n"
-        + "GET Employees('1')/EmployeeName HTTP/1.1" + "\n"
-        + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
+        + "Content-Type: application/http" + LF
+        + "Content-Transfer-Encoding: 8bit" + LF
+        + LF
+        + "GET Employees('1')/EmployeeName HTTP/1.1" + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
 
   @Test(expected = BatchException.class)
   public void testMimeHeaderContentId() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
         + MIME_HEADERS
-        + "Content-ID: 1" + "\n"
-        + "\n"
-        + "GET Employees('1')/EmployeeName HTTP/1.1" + "\n"
-        + "\n"
+        + "Content-ID: 1" + LF
+        + LF
+        + "GET Employees('1')/EmployeeName HTTP/1.1" + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
 
   @Test(expected = BatchException.class)
   public void testInvalidMethodForBatch() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
         + MIME_HEADERS
-        + "\n"
-        + "POST Employees('1')/EmployeeName HTTP/1.1" + "\n"
-        + "\n"
+        + LF
+        + "POST Employees('1')/EmployeeName HTTP/1.1" + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
 
   @Test(expected = BatchException.class)
   public void testNoMethod() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
         + MIME_HEADERS
-        + "\n"
-        + /*GET*/"Employees('1')/EmployeeName HTTP/1.1" + "\n"
-        + "\n"
+        + LF
+        + /*GET*/"Employees('1')/EmployeeName HTTP/1.1" + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
 
   @Test(expected = BatchException.class)
   public void testInvalidMethodForChangeset() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
-        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + "\n"
-        + "\n"
-        + "--changeset_f980-1cb6-94dd" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
+        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + LF
+        + LF
+        + "--changeset_f980-1cb6-94dd" + LF
         + MIME_HEADERS
-        + "\n"
-        + "GET Employees('2')/EmployeeName HTTP/1.1" + "\n"
-        + "Content-Type: application/json;odata=verbose" + "\n"
-        + "MaxDataServiceVersion: 2.0" + "\n"
-        + "\n"
+        + LF
+        + "GET Employees('2')/EmployeeName HTTP/1.1" + LF
+        + "Content-Type: application/json;odata=verbose" + LF
+        + "MaxDataServiceVersion: 2.0" + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
 
   @Test(expected = BatchException.class)
   public void testInvalidChangeSetBoundary() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
-        + "Content-Type: multipart/mixed;boundary=changeset_f980-1cb6-94dd" + "\n"
-        + "\n"
-        + "--changeset_f980-1cb6-94d"/*+"d"*/+ "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
+        + "Content-Type: multipart/mixed;boundary=changeset_f980-1cb6-94dd" + LF
+        + LF
+        + "--changeset_f980-1cb6-94d"/*+"d"*/+ LF
         + MIME_HEADERS
-        + "\n"
-        + "POST Employees('2') HTTP/1.1" + "\n"
-        + "Content-Type: application/json;odata=verbose" + "\n"
-        + "MaxDataServiceVersion: 2.0" + "\n"
-        + "\n"
+        + LF
+        + "POST Employees('2') HTTP/1.1" + LF
+        + "Content-Type: application/json;odata=verbose" + LF
+        + "MaxDataServiceVersion: 2.0" + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
 
   @Test(expected = BatchException.class)
   public void testNoCloseDelimiter() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
         + GET_REQUEST;
     parseInvalidBatchBody(batch);
   }
 
   @Test(expected = BatchException.class)
   public void testNoCloseDelimiter2() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
         + MIME_HEADERS
-        + "\n"
-        + "GET Employees('1')/EmployeeName HTTP/1.1" + "\n"
-    /*--batch_8194-cf13-1f56--*/;
+        + LF
+        + "GET Employees('1')/EmployeeName HTTP/1.1" + LF;
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidUri() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + LF
+        + MIME_HEADERS
+        + LF
+        + "GET http://localhost/aa/odata/Employees('1')/EmployeeName HTTP/1.1" + LF
+        + LF
+        + LF
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testUriWithAbsolutePath() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + LF
+        + MIME_HEADERS
+        + LF
+        + "GET /odata/Employees('1')/EmployeeName HTTP/1.1" + LF
+        + LF
+        + LF
+        + "--batch_8194-cf13-1f56--";
     parseInvalidBatchBody(batch);
   }
 
   @Test(expected = BatchException.class)
   public void testNoCloseDelimiter3() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n" + GET_REQUEST + "--batch_8194-cf13-1f56-"/*no hash*/;
+    String batch = "--batch_8194-cf13-1f56" + LF + GET_REQUEST + "--batch_8194-cf13-1f56-"/*no hash*/;
     parseInvalidBatchBody(batch);
   }
 
   @Test
   public void testAcceptHeaders() throws BatchException, URISyntaxException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
         + MIME_HEADERS
-        + "\n"
-        + "GET Employees('2')/EmployeeName HTTP/1.1" + "\n"
-        + "Content-Length: 100000" + "\n"
-        + "Content-Type: application/json;odata=verbose" + "\n"
-        + "Accept: application/xml;q=0.3, application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.001" + "\n"
-        + "\n"
-        + "\n"
+        + LF
+        + "GET Employees('2')/EmployeeName HTTP/1.1" + LF
+        + "Content-Length: 100000" + LF
+        + "Content-Type: application/json;odata=verbose" + LF
+        + "Accept: application/xml;q=0.3, application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.001" + LF
+        + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
-    List<BatchPart> batchParts = parse(batch);
-    for (BatchPart multipart : batchParts) {
+    List<BatchRequestPart> batchRequestParts = parse(batch);
+    for (BatchRequestPart multipart : batchRequestParts) {
       if (!multipart.isChangeSet()) {
         assertEquals(1, multipart.getRequests().size());
         ODataRequest retrieveRequest = multipart.getRequests().get(0);
@@ -463,18 +486,18 @@ public class BatchRequestParserTest {
 
   @Test
   public void testAcceptHeaders2() throws BatchException, URISyntaxException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
         + MIME_HEADERS
-        + "\n"
-        + "GET Employees('2')/EmployeeName HTTP/1.1" + "\n"
-        + "Content-Length: 100000" + "\n"
-        + "Content-Type: application/json;odata=verbose" + "\n"
-        + "Accept: */*;q=0.5, application/json;odata=verbose;q=1.0,application/atom+xml" + "\n"
-        + "\n"
-        + "\n"
+        + LF
+        + "GET Employees('2')/EmployeeName HTTP/1.1" + LF
+        + "Content-Length: 100000" + LF
+        + "Content-Type: application/json;odata=verbose" + LF
+        + "Accept: */*;q=0.5, application/json;odata=verbose;q=1.0,application/atom+xml" + LF
+        + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
-    List<BatchPart> batchParts = parse(batch);
-    for (BatchPart multipart : batchParts) {
+    List<BatchRequestPart> batchRequestParts = parse(batch);
+    for (BatchRequestPart multipart : batchRequestParts) {
       if (!multipart.isChangeSet()) {
         assertEquals(1, multipart.getRequests().size());
         ODataRequest retrieveRequest = multipart.getRequests().get(0);
@@ -491,18 +514,18 @@ public class BatchRequestParserTest {
 
   @Test
   public void testAcceptHeaders3() throws BatchException, URISyntaxException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
         + MIME_HEADERS
-        + "\n"
-        + "GET Employees('2')/EmployeeName HTTP/1.1" + "\n"
-        + "Content-Length: 100000" + "\n"
-        + "Content-Type: application/json;odata=verbose" + "\n"
-        + "accept: */*,application/atom+xml,application/atomsvc+xml,application/xml" + "\n"
-        + "\n"
-        + "\n"
+        + LF
+        + "GET Employees('2')/EmployeeName HTTP/1.1" + LF
+        + "Content-Length: 100000" + LF
+        + "Content-Type: application/json;odata=verbose" + LF
+        + "accept: */*,application/atom+xml,application/atomsvc+xml,application/xml" + LF
+        + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
-    List<BatchPart> batchParts = parse(batch);
-    for (BatchPart multipart : batchParts) {
+    List<BatchRequestPart> batchRequestParts = parse(batch);
+    for (BatchRequestPart multipart : batchRequestParts) {
       if (!multipart.isChangeSet()) {
         assertEquals(1, multipart.getRequests().size());
         ODataRequest retrieveRequest = multipart.getRequests().get(0);
@@ -521,53 +544,53 @@ public class BatchRequestParserTest {
 
   @Test
   public void testContentId() throws BatchException {
-    String batch = "--batch_8194-cf13-1f56" + "\n"
+    String batch = "--batch_8194-cf13-1f56" + LF
         + MIME_HEADERS
-        + "\n"
-        + "GET Employees HTTP/1.1" + "\n"
-        + "accept: */*,application/atom+xml,application/atomsvc+xml,application/xml" + "\n"
-        + "Content-Id: BBB" + "\n"
-        + "\n" + "\n"
-        + "--batch_8194-cf13-1f56" + "\n"
-        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + "\n"
-        + "\n"
-        + "--changeset_f980-1cb6-94dd" + "\n"
+        + LF
+        + "GET Employees HTTP/1.1" + LF
+        + "accept: */*,application/atom+xml,application/atomsvc+xml,application/xml" + LF
+        + "Content-Id: BBB" + LF
+        + LF + LF
+        + "--batch_8194-cf13-1f56" + LF
+        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + LF
+        + LF
+        + "--changeset_f980-1cb6-94dd" + LF
         + MIME_HEADERS
-        + "Content-Id: " + CONTENT_ID_REFERENCE + "\n"
-        + "\n"
-        + "POST Employees HTTP/1.1" + "\n"
-        + "Content-type: application/octet-stream" + "\n"
-        + "\n"
-        + "/9j/4AAQSkZJRgABAQEBLAEsAAD/4RM0RXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAA" + "\n"
-        + "\n"
-        + "--changeset_f980-1cb6-94dd" + "\n"
+        + "Content-Id: " + CONTENT_ID_REFERENCE + LF
+        + LF
+        + "POST Employees HTTP/1.1" + LF
+        + "Content-type: application/octet-stream" + LF
+        + LF
+        + "/9j/4AAQSkZJRgABAQEBLAEsAAD/4RM0RXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAA" + LF
+        + LF
+        + "--changeset_f980-1cb6-94dd" + LF
         + MIME_HEADERS
-        + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + "\n"
-        + "\n"
-        + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + "\n"
-        + "Content-Type: application/json;odata=verbose" + "\n"
-        + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + "\n"
-        + "\n"
-        + "{\"EmployeeName\":\"Peter Fall\"}" + "\n"
-        + "--changeset_f980-1cb6-94dd--" + "\n"
-        + "\n"
+        + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + LF
+        + LF
+        + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + LF
+        + "Content-Type: application/json;odata=verbose" + LF
+        + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + LF
+        + LF
+        + "{\"EmployeeName\":\"Peter Fall\"}" + LF
+        + "--changeset_f980-1cb6-94dd--" + LF
+        + LF
         + "--batch_8194-cf13-1f56--";
     InputStream in = new ByteArrayInputStream(batch.getBytes());
     BatchRequestParser parser = new BatchRequestParser(contentType, batchProperties);
-    List<BatchPart> batchParts = parser.parse(in);
-    assertNotNull(batchParts);
-    for (BatchPart multipart : batchParts) {
+    List<BatchRequestPart> batchRequestParts = parser.parse(in);
+    assertNotNull(batchRequestParts);
+    for (BatchRequestPart multipart : batchRequestParts) {
       if (!multipart.isChangeSet()) {
         assertEquals(1, multipart.getRequests().size());
         ODataRequest retrieveRequest = multipart.getRequests().get(0);
-        assertEquals("BBB", retrieveRequest.getRequestHeaderValue(BatchConstants.REQUEST_HEADER_CONTENT_ID.toLowerCase()));
+        assertEquals("BBB", retrieveRequest.getRequestHeaderValue(BatchHelper.REQUEST_HEADER_CONTENT_ID.toLowerCase()));
       } else {
         for (ODataRequest request : multipart.getRequests()) {
           if (ODataHttpMethod.POST.equals(request.getMethod())) {
-            assertEquals(CONTENT_ID_REFERENCE, request.getRequestHeaderValue(BatchConstants.MIME_HEADER_CONTENT_ID.toLowerCase()));
+            assertEquals(CONTENT_ID_REFERENCE, request.getRequestHeaderValue(BatchHelper.MIME_HEADER_CONTENT_ID.toLowerCase()));
           } else if (ODataHttpMethod.PUT.equals(request.getMethod())) {
-            assertEquals(PUT_MIME_HEADER_CONTENT_ID, request.getRequestHeaderValue(BatchConstants.MIME_HEADER_CONTENT_ID.toLowerCase()));
-            assertEquals(PUT_REQUEST_HEADER_CONTENT_ID, request.getRequestHeaderValue(BatchConstants.REQUEST_HEADER_CONTENT_ID.toLowerCase()));
+            assertEquals(PUT_MIME_HEADER_CONTENT_ID, request.getRequestHeaderValue(BatchHelper.MIME_HEADER_CONTENT_ID.toLowerCase()));
+            assertEquals(PUT_REQUEST_HEADER_CONTENT_ID, request.getRequestHeaderValue(BatchHelper.REQUEST_HEADER_CONTENT_ID.toLowerCase()));
             assertNull(request.getPathInfo().getRequestUri());
             assertEquals("$" + CONTENT_ID_REFERENCE, request.getPathInfo().getODataSegments().get(0).getPath());
           }
@@ -576,13 +599,13 @@ public class BatchRequestParserTest {
     }
   }
 
-  private List<BatchPart> parse(final String batch) throws BatchException {
+  private List<BatchRequestPart> parse(final String batch) throws BatchException {
     InputStream in = new ByteArrayInputStream(batch.getBytes());
     BatchRequestParser parser = new BatchRequestParser(contentType, batchProperties);
-    List<BatchPart> batchParts = parser.parse(in);
-    assertNotNull(batchParts);
-    assertEquals(false, batchParts.isEmpty());
-    return batchParts;
+    List<BatchRequestPart> batchRequestParts = parser.parse(in);
+    assertNotNull(batchRequestParts);
+    assertEquals(false, batchRequestParts.isEmpty());
+    return batchRequestParts;
   }
 
   private void parseInvalidBatchBody(final String batch) throws BatchException {

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestWriterTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestWriterTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestWriterTest.java
new file mode 100644
index 0000000..61e6709
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestWriterTest.java
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * 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.core.batch;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+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.testutil.helper.StringHelper;
+import org.junit.Test;
+
+public class BatchRequestWriterTest {
+
+  private static final String POST = "POST";
+  private static final String GET = "GET";
+  private static final String PUT = "PUT";
+  private static final String BOUNDARY = "batch_123";
+
+  private void checkMimeHeaders(final String requestBody) {
+    assertTrue(requestBody.contains("Content-Type: application/http"));
+    assertTrue(requestBody.contains("Content-Transfer-Encoding: binary"));
+  }
+
+  @Test
+  public void testBatchQueryPart() throws BatchException, IOException {
+    List<BatchPart> batch = new ArrayList<BatchPart>();
+    Map<String, String> headers = new HashMap<String, String>();
+    headers.put("Accept", "application/json");
+    BatchPart request = BatchQueryPart.method(GET).uri("Employees").headers(headers).build();
+    batch.add(request);
+
+    BatchRequestWriter writer = new BatchRequestWriter();
+    InputStream batchRequest = writer.writeBatchRequest(batch, BOUNDARY);
+
+    String requestBody = StringHelper.inputStreamToString(batchRequest);
+    assertNotNull(batchRequest);
+    checkMimeHeaders(requestBody);
+
+    assertTrue(requestBody.contains("--batch_"));
+    assertTrue(requestBody.contains("GET Employees HTTP/1.1"));
+    checkHeaders(headers, requestBody);
+  }
+
+  @Test
+  public void testBatchChangeSet() throws IOException, BatchException {
+    List<BatchPart> batch = new ArrayList<BatchPart>();
+    Map<String, String> headers = new HashMap<String, String>();
+    headers.put("content-type", "application/json");
+    BatchChangeSetPart request = BatchChangeSetPart.method(PUT)
+        .uri("Employees('2')")
+        .body("{\"Возраст\":40}")
+        .headers(headers)
+        .contentId("111")
+        .build();
+    BatchChangeSet changeSet = BatchChangeSet.newBuilder().build();
+    changeSet.add(request);
+    batch.add(changeSet);
+
+    BatchRequestWriter writer = new BatchRequestWriter();
+    InputStream batchRequest = writer.writeBatchRequest(batch, BOUNDARY);
+
+    String requestBody = StringHelper.inputStreamToString(batchRequest, true);
+    assertNotNull(batchRequest);
+    checkMimeHeaders(requestBody);
+    checkHeaders(headers, requestBody);
+
+    assertTrue(requestBody.contains("--batch_"));
+    assertTrue(requestBody.contains("--changeset_"));
+    assertTrue(requestBody.contains("PUT Employees('2') HTTP/1.1"));
+    assertTrue(requestBody.contains("{\"Возраст\":40}"));
+  }
+
+  @Test
+  public void testBatchWithGetAndPost() throws BatchException, IOException {
+    List<BatchPart> batch = new ArrayList<BatchPart>();
+    Map<String, String> headers = new HashMap<String, String>();
+    headers.put("Accept", "application/json");
+    BatchPart request = BatchQueryPart.method(GET).uri("Employees").headers(headers).contentId("000").build();
+    batch.add(request);
+
+    Map<String, String> changeSetHeaders = new HashMap<String, String>();
+    changeSetHeaders.put("content-type", "application/json");
+    String body = "/9j/4AAQSkZJRgABAQEBLAEsAAD/4RM0RXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEA";
+    BatchChangeSetPart changeRequest = BatchChangeSetPart.method(POST)
+        .uri("Employees")
+        .body(body)
+        .headers(changeSetHeaders)
+        .contentId("111")
+        .build();
+    BatchChangeSet changeSet = BatchChangeSet.newBuilder().build();
+    changeSet.add(changeRequest);
+    batch.add(changeSet);
+    BatchRequestWriter writer = new BatchRequestWriter();
+    InputStream batchRequest = writer.writeBatchRequest(batch, BOUNDARY);
+
+    String requestBody = StringHelper.inputStreamToString(batchRequest);
+    assertNotNull(batchRequest);
+    checkMimeHeaders(requestBody);
+
+    checkHeaders(headers, requestBody);
+    checkHeaders(changeSetHeaders, requestBody);
+    assertTrue(requestBody.contains("GET Employees HTTP/1.1"));
+    assertTrue(requestBody.contains("POST Employees HTTP/1.1"));
+    assertTrue(requestBody.contains(body));
+  }
+
+  @Test
+  public void testChangeSetWithContentIdReferencing() throws BatchException, IOException {
+    List<BatchPart> batch = new ArrayList<BatchPart>();
+
+    Map<String, String> changeSetHeaders = new HashMap<String, String>();
+    changeSetHeaders.put("content-type", "application/json");
+    String body = "/9j/4AAQSkZJRgABAQEBLAEsAAD/4RM0RXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEA";
+    BatchChangeSetPart changeRequest = BatchChangeSetPart.method(POST)
+        .uri("Employees('2')")
+        .body(body)
+        .headers(changeSetHeaders)
+        .contentId("1")
+        .build();
+    BatchChangeSet changeSet = BatchChangeSet.newBuilder().build();
+    changeSet.add(changeRequest);
+
+    changeSetHeaders = new HashMap<String, String>();
+    changeSetHeaders.put("content-type", "application/json;odata=verbose");
+    BatchChangeSetPart changeRequest2 = BatchChangeSetPart.method(PUT)
+        .uri("$/ManagerId")
+        .body("{\"ManagerId\":1}")
+        .headers(changeSetHeaders)
+        .contentId("2")
+        .build();
+    changeSet.add(changeRequest2);
+    batch.add(changeSet);
+
+    BatchRequestWriter writer = new BatchRequestWriter();
+    InputStream batchRequest = writer.writeBatchRequest(batch, BOUNDARY);
+
+    String requestBody = StringHelper.inputStreamToString(batchRequest);
+    assertNotNull(batchRequest);
+    checkMimeHeaders(requestBody);
+
+    assertTrue(requestBody.contains("POST Employees('2') HTTP/1.1"));
+    assertTrue(requestBody.contains("PUT $/ManagerId HTTP/1.1"));
+    assertTrue(requestBody.contains(BatchHelper.HTTP_CONTENT_ID + ": 1"));
+    assertTrue(requestBody.contains(BatchHelper.HTTP_CONTENT_ID + ": 2"));
+    assertTrue(requestBody.contains(body));
+
+  }
+
+  @Test
+  public void testBatchWithTwoChangeSets() throws BatchException, IOException {
+    List<BatchPart> batch = new ArrayList<BatchPart>();
+
+    Map<String, String> changeSetHeaders = new HashMap<String, String>();
+    changeSetHeaders.put("content-type", "application/json");
+    changeSetHeaders.put("content-Id", "111");
+    String body = "/9j/4AAQSkZJRgABAQEBLAEsAAD/4RM0RXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEA";
+    BatchChangeSetPart changeRequest = BatchChangeSetPart.method(POST)
+        .uri("Employees")
+        .body(body)
+        .headers(changeSetHeaders)
+        .build();
+    BatchChangeSet changeSet = BatchChangeSet.newBuilder().build();
+    changeSet.add(changeRequest);
+    batch.add(changeSet);
+
+    Map<String, String> changeSetHeaders2 = new HashMap<String, String>();
+    changeSetHeaders2.put("content-type", "application/json;odata=verbose");
+    changeSetHeaders2.put("content-Id", "222");
+    BatchChangeSetPart changeRequest2 = BatchChangeSetPart.method(PUT)
+        .uri("Employees('2')/ManagerId")
+        .body("{\"ManagerId\":1}")
+        .headers(changeSetHeaders2)
+        .build();
+    BatchChangeSet changeSet2 = BatchChangeSet.newBuilder().build();
+    changeSet2.add(changeRequest2);
+    batch.add(changeSet2);
+
+    BatchRequestWriter writer = new BatchRequestWriter();
+    InputStream batchRequest = writer.writeBatchRequest(batch, BOUNDARY);
+
+    String requestBody = StringHelper.inputStreamToString(batchRequest);
+    assertNotNull(batchRequest);
+    checkMimeHeaders(requestBody);
+
+    assertTrue(requestBody.contains("POST Employees HTTP/1.1"));
+    assertTrue(requestBody.contains("PUT Employees('2')/ManagerId HTTP/1.1"));
+
+    assertTrue(requestBody.contains(body));
+
+  }
+
+  private void checkHeaders(final Map<String, String> headers, final String requestBody) {
+    for (Map.Entry<String, String> header : headers.entrySet()) {
+      assertTrue(requestBody.contains(header.getKey() + ": " + header.getValue()));
+    }
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testBatchQueryPartWithInvalidMethod() throws BatchException, IOException {
+    BatchQueryPart.method(PUT).uri("Employees").build();
+
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testBatchChangeSetPartWithInvalidMethod() throws BatchException, IOException {
+    BatchChangeSetPart.method(GET).uri("Employees('2')").build();
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseParserTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseParserTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseParserTest.java
new file mode 100644
index 0000000..7936051
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseParserTest.java
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * 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.core.batch;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+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.junit.Test;
+
+public class BatchResponseParserTest {
+
+  private static final String LF = "\r\n";
+
+  @Test
+  public void testSimpleBatchResponse() throws BatchException {
+    String getResponse = "--batch_123" + LF
+        + "Content-Type: application/http" + LF
+        + "Content-Transfer-Encoding: binary" + LF
+        + "Content-ID: 1" + LF
+        + LF
+        + "HTTP/1.1 200 OK" + LF
+        + "DataServiceVersion: 2.0" + LF
+        + "Content-Type: text/plain;charset=utf-8" + LF
+        + "Content-length: 22" + LF
+        + LF
+        + "Frederic Fall MODIFIED" + LF
+        + LF
+        + "--batch_123--";
+
+    InputStream in = new ByteArrayInputStream(getResponse.getBytes());
+    BatchResponseParser parser = new BatchResponseParser("multipart/mixed;boundary=batch_123");
+    List<BatchSingleResponse> responses = parser.parse(in);
+    for (BatchSingleResponse response : responses) {
+      assertEquals("200", response.getStatusCode());
+      assertEquals("OK", response.getStatusInfo());
+      assertEquals("text/plain;charset=utf-8", response.getHeaders().get(HttpHeaders.CONTENT_TYPE));
+      assertEquals("22", response.getHeaders().get("Content-length"));
+      assertEquals("1", response.getContentId());
+    }
+  }
+
+  @Test
+  public void testBatchResponse() throws BatchException, IOException {
+    String fileName = "/batchResponse.batch";
+    InputStream in = ClassLoader.class.getResourceAsStream(fileName);
+    if (in == null) {
+      throw new IOException("Requested file '" + fileName + "' was not found.");
+    }
+    BatchResponseParser parser = new BatchResponseParser("multipart/mixed;boundary=batch_123");
+    List<BatchSingleResponse> responses = parser.parse(in);
+    for (BatchSingleResponse response : responses) {
+      if ("1".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());
+      }
+    }
+  }
+
+  @Test
+  public void testResponseToChangeSet() throws BatchException {
+    String putResponse = "--batch_123" + LF
+        + "Content-Type: " + HttpContentType.MULTIPART_MIXED + ";boundary=changeset_12ks93js84d" + LF
+        + LF
+        + "--changeset_12ks93js84d" + LF
+        + "Content-Type: application/http" + LF
+        + "Content-Transfer-Encoding: binary" + LF
+        + "Content-ID: 1" + LF
+        + LF
+        + "HTTP/1.1 204 No Content" + LF
+        + "DataServiceVersion: 2.0" + LF
+        + LF
+        + LF
+        + "--changeset_12ks93js84d--" + LF
+        + LF
+        + "--batch_123--";
+
+    InputStream in = new ByteArrayInputStream(putResponse.getBytes());
+    BatchResponseParser parser = new BatchResponseParser("multipart/mixed;boundary=batch_123");
+    List<BatchSingleResponse> responses = parser.parse(in);
+    for (BatchSingleResponse response : responses) {
+      assertEquals("204", response.getStatusCode());
+      assertEquals("No Content", response.getStatusInfo());
+      assertEquals("1", response.getContentId());
+    }
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidMimeHeader() throws BatchException {
+    String putResponse = "--batch_123" + LF
+        + "Content-Type: " + HttpContentType.MULTIPART_MIXED + ";boundary=changeset_12ks93js84d" + LF
+        + LF
+        + "--changeset_12ks93js84d" + LF
+        + "Content-Type: application/http" + LF
+        + "Content-Transfer-Encoding: 7bit" + LF // Content-Transfer-Encoding must be binary
+        + LF
+        + "HTTP/1.1 No Content" + LF
+        + "DataServiceVersion: 2.0" + LF
+        + LF
+        + LF
+        + "--changeset_12ks93js84d--" + LF
+        + LF
+        + "--batch_123--";
+
+    parseInvalidBatchResponseBody(putResponse);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testMissingMimeHeader() throws BatchException {
+    String putResponse = "--batch_123" + LF
+        + "Content-Type: " + HttpContentType.MULTIPART_MIXED + ";boundary=changeset_12ks93js84d" + LF
+        + LF
+        + "--changeset_12ks93js84d" + LF
+        + LF
+        + "HTTP/1.1 No Content" + LF
+        + "DataServiceVersion: 2.0" + LF
+        + LF
+        + LF
+        + "--changeset_12ks93js84d--" + LF
+        + LF
+        + "--batch_123--";
+
+    parseInvalidBatchResponseBody(putResponse);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidContentType() throws BatchException {
+    String putResponse = "--batch_123" + LF
+        + "Content-Type: " + HttpContentType.MULTIPART_MIXED + LF //Missing boundary parameter
+        + LF
+        + "--changeset_12ks93js84d" + LF
+        + "Content-Type: application/http" + LF
+        + "Content-Transfer-Encoding: binary" + LF
+        + LF
+        + "HTTP/1.1 No Content" + LF
+        + "DataServiceVersion: 2.0" + LF
+        + LF
+        + LF
+        + "--changeset_12ks93js84d--" + LF
+        + LF
+        + "--batch_123--";
+
+    parseInvalidBatchResponseBody(putResponse);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidStatusLine() throws BatchException {
+    String putResponse = "--batch_123" + LF
+        + "Content-Type: " + HttpContentType.MULTIPART_MIXED + ";boundary=changeset_12ks93js84d" + LF
+        + LF
+        + "--changeset_12ks93js84d" + LF
+        + "Content-Type: application/http" + LF
+        + "Content-Transfer-Encoding: binary" + LF
+        + LF
+        + "HTTP/1.1 No Content" + LF
+        + "DataServiceVersion: 2.0" + LF
+        + LF
+        + LF
+        + "--changeset_12ks93js84d--" + LF
+        + LF
+        + "--batch_123--";
+
+    parseInvalidBatchResponseBody(putResponse);
+
+  }
+
+  @Test(expected = BatchException.class)
+  public void testMissingCloseDelimiter() throws BatchException {
+    String putResponse = "--batch_123" + LF
+        + "Content-Type: " + HttpContentType.MULTIPART_MIXED + ";boundary=changeset_12ks93js84d" + LF
+        + LF
+        + "--changeset_12ks93js84d" + LF
+        + "Content-Type: application/http" + LF
+        + "Content-Transfer-Encoding: binary" + LF
+        + LF
+        + "HTTP/1.1 204 No Content" + LF
+        + "DataServiceVersion: 2.0" + LF
+        + LF
+        + LF
+        + "--changeset_12ks93js84d--" + LF
+        + LF;
+
+    parseInvalidBatchResponseBody(putResponse);
+
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidEnteredContentLength() throws BatchException {
+    String getResponse = "--batch_123" + LF
+        + "Content-Type: application/http" + LF
+        + "Content-Transfer-Encoding: binary" + LF
+        + "Content-ID: 1" + LF
+        + LF
+        + "HTTP/1.1 200 OK" + LF
+        + "DataServiceVersion: 2.0" + LF
+        + "Content-Type: text/plain;charset=utf-8" + LF
+        + "Content-length: 100" + LF
+        + LF
+        + "Frederic Fall" + LF
+        + LF
+        + "--batch_123--";
+
+    parseInvalidBatchResponseBody(getResponse);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidBoundary() throws BatchException {
+    String getResponse = "--batch_321" + LF
+        + "Content-Type: application/http" + LF
+        + "Content-Transfer-Encoding: binary" + LF
+        + "Content-ID: 1" + LF
+        + LF
+        + "HTTP/1.1 200 OK" + LF
+        + "DataServiceVersion: 2.0" + LF
+        + "Content-Type: text/plain;charset=utf-8" + LF
+        + LF
+        + "Frederic Fall" + LF
+        + LF
+        + "--batch_123--";
+
+    parseInvalidBatchResponseBody(getResponse);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidBoundary2() throws BatchException {
+    String getResponse = "--batch_123" + LF
+        + "Content-Type: application/http" + LF
+        + "Content-Transfer-Encoding: binary" + LF
+        + LF
+        + "HTTP/1.1 200 OK" + LF
+        + "Content-Type: text/plain;charset=utf-8" + LF
+        + "Content-Length: 13" + LF
+        + LF
+        + "Frederic Fall" + LF
+        + LF
+        + "batch_123" + LF
+        + "Content-Type: application/http" + LF
+        + "Content-Transfer-Encoding: binary" + LF
+        + LF
+        + "HTTP/1.1 200 OK" + LF
+        + "Content-Type: text/plain;charset=utf-8" + LF
+        + LF
+        + "Walter Winter" + LF
+        + LF
+        + "--batch_123--";
+    parseInvalidBatchResponseBody(getResponse);
+  }
+
+  private void parseInvalidBatchResponseBody(final String putResponse) throws BatchException {
+    InputStream in = new ByteArrayInputStream(putResponse.getBytes());
+    BatchResponseParser parser = new BatchResponseParser("multipart/mixed;boundary=batch_123");
+    parser.parse(in);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseWriterTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseWriterTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseWriterTest.java
index f236226..d63ab83 100644
--- a/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseWriterTest.java
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseWriterTest.java
@@ -125,8 +125,8 @@ public class BatchResponseWriterTest {
     ODataResponse response = ODataResponse.entity("Walter Winter")
         .status(HttpStatusCodes.OK)
         .contentHeader("application/json")
-        .header(BatchConstants.MIME_HEADER_CONTENT_ID, "mimeHeaderContentId123")
-        .header(BatchConstants.REQUEST_HEADER_CONTENT_ID, "requestHeaderContentId123")
+        .header(BatchHelper.MIME_HEADER_CONTENT_ID, "mimeHeaderContentId123")
+        .header(BatchHelper.REQUEST_HEADER_CONTENT_ID, "requestHeaderContentId123")
         .build();
     List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
     responses.add(response);

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmParserTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmParserTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmParserTest.java
index 9860fef..da91133 100644
--- a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmParserTest.java
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmParserTest.java
@@ -30,8 +30,6 @@ import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 
-import org.junit.Test;
-
 import org.apache.olingo.odata2.api.edm.Edm;
 import org.apache.olingo.odata2.api.edm.EdmAction;
 import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
@@ -61,10 +59,16 @@ import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
 import org.apache.olingo.odata2.api.ep.EntityProvider;
 import org.apache.olingo.odata2.api.ep.EntityProviderException;
 import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.core.ep.AbstractXmlProducerTestHelper;
 import org.apache.olingo.odata2.testutil.helper.StringHelper;
 import org.apache.olingo.odata2.testutil.mock.EdmTestProvider;
+import org.junit.Test;
 
-public class EdmParserTest {
+public class EdmParserTest extends AbstractXmlProducerTestHelper {
+
+  public EdmParserTest(final StreamWriterImplType type) {
+    super(type);
+  }
 
   private static final String DEFAULT_VALUE = "Photo";
   private static final String FC_TARGET_PATH = "Содержание";
@@ -663,6 +667,7 @@ public class EdmParserTest {
         }
       }
       for (EntityType entityType : schema.getEntityTypes()) {
+        assertEquals(1, entityType.getAnnotationAttributes().size());
         AnnotationAttribute attr = entityType.getAnnotationAttributes().get(0);
         assertEquals("href", attr.getName());
         assertEquals("prefix1", attr.getPrefix());

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractXmlProducerTestHelper.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractXmlProducerTestHelper.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractXmlProducerTestHelper.java
index f86b658..56d7118 100644
--- a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractXmlProducerTestHelper.java
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractXmlProducerTestHelper.java
@@ -37,13 +37,16 @@ public abstract class AbstractXmlProducerTestHelper extends BaseTest {
   public AbstractXmlProducerTestHelper(final StreamWriterImplType type) {
     switch (type) {
     case WOODSTOCKIMPL:
+      System.setProperty("javax.xml.stream.XMLInputFactory", "com.ctc.wstx.stax.WstxInputFactory"); //NOSONAR
       System.setProperty("javax.xml.stream.XMLOutputFactory", "com.ctc.wstx.stax.WstxOutputFactory"); //NOSONAR
       break;
     case SUNINTERNALIMPL:
+      System.setProperty("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl"); //NOSONAR
       System.setProperty("javax.xml.stream.XMLOutputFactory", "com.sun.xml.internal.stream.XMLOutputFactoryImpl"); //NOSONAR
       break;
     default:
       System.setProperty("javax.xml.stream.XMLOutputFactory", "com.sun.xml.internal.stream.XMLOutputFactoryImpl"); //NOSONAR
+      System.setProperty("javax.xml.stream.XMLInputFactory", "com.sun.xml.internal.stream.XMLInputFactoryImpl"); //NOSONAR
       break;
     }
   }

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumerTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumerTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumerTest.java
index 23dcdda..37edd4d 100644
--- a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumerTest.java
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumerTest.java
@@ -21,6 +21,7 @@ package org.apache.olingo.odata2.core.ep.consumer;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.io.InputStream;
@@ -29,13 +30,13 @@ import java.util.List;
 import java.util.Map;
 import java.util.TimeZone;
 
-import org.junit.Test;
-
 import org.apache.olingo.odata2.api.edm.EdmEntitySet;
 import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
 import org.apache.olingo.odata2.api.ep.entry.MediaMetadata;
 import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
 import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Test;
 
 /**
  *  
@@ -86,7 +87,7 @@ public class JsonEntryConsumerTest extends AbstractConsumerTest {
     assertEquals("Heidelberg", city.get("CityName"));
     assertEquals(Integer.valueOf(52), properties.get("Age"));
     Calendar entryDate = (Calendar) properties.get("EntryDate");
-    assertEquals(Long.valueOf(915148800000l), Long.valueOf(entryDate.getTimeInMillis()));
+    assertEquals(915148800000L, entryDate.getTimeInMillis());
     assertEquals(TimeZone.getTimeZone("GMT"), entryDate.getTimeZone());
     assertEquals("Employees('1')/$value", properties.get("ImageUrl"));
 
@@ -135,7 +136,7 @@ public class JsonEntryConsumerTest extends AbstractConsumerTest {
     assertNotNull(properties);
     assertEquals("1", properties.get("Id"));
     assertEquals("Building 1", properties.get("Name"));
-    assertEquals(null, properties.get("Image"));
+    assertNull(properties.get("Image"));
     assertNull(properties.get("nb_Rooms"));
 
     List<String> associationUris = result.getMetadata().getAssociationUris("nb_Rooms");
@@ -153,7 +154,7 @@ public class JsonEntryConsumerTest extends AbstractConsumerTest {
     assertNotNull(properties);
     assertEquals("1", properties.get("Id"));
     assertEquals("Building 1", properties.get("Name"));
-    assertEquals(null, properties.get("Image"));
+    assertNull(properties.get("Image"));
     assertNull(properties.get("nb_Rooms"));
 
     List<String> associationUris = result.getMetadata().getAssociationUris("nb_Rooms");
@@ -164,6 +165,41 @@ public class JsonEntryConsumerTest extends AbstractConsumerTest {
   }
 
   @Test
+  public void readMinimalEntry() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    final ODataEntry result = new JsonEntityConsumer().readEntry(entitySet, createContentAsStream("{\"Id\":\"99\"}"), DEFAULT_PROPERTIES);
+
+    final Map<String, Object> properties = result.getProperties();
+    assertNotNull(properties);
+    assertEquals(1, properties.size());
+    assertEquals("99", properties.get("Id"));
+
+    assertTrue(result.getMetadata().getAssociationUris("nt_Employees").isEmpty());
+    checkMediaDataInitial(result.getMediaMetadata());
+  }
+
+  @Test
+  public void readEntryWithNullProperty() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    final String content = "{\"Id\":\"99\",\"Seats\":null}";
+
+    for (final boolean merge : new boolean[] { false, true }) {
+      final ODataEntry result = new JsonEntityConsumer().readEntry(entitySet, createContentAsStream(content),
+          EntityProviderReadProperties.init().mergeSemantic(merge).build());
+
+      final Map<String, Object> properties = result.getProperties();
+      assertNotNull(properties);
+      assertEquals(2, properties.size());
+      assertEquals("99", properties.get("Id"));
+      assertTrue(properties.containsKey("Seats"));
+      assertNull(properties.get("Seats"));
+
+      assertTrue(result.getMetadata().getAssociationUris("nr_Employees").isEmpty());
+      checkMediaDataInitial(result.getMediaMetadata());
+    }
+  }
+
+  @Test
   public void readWithDoublePropertyOnTeam() throws Exception {
     //The file contains the name property two times
     try {

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/45c27419/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumerTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumerTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumerTest.java
index 5cedb91..61ef209 100644
--- a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumerTest.java
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumerTest.java
@@ -36,10 +36,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
 
-import org.junit.Test;
-
-import com.google.gson.stream.JsonReader;
-import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
 import org.apache.olingo.odata2.api.edm.EdmProperty;
 import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
 import org.apache.olingo.odata2.api.ep.EntityProviderException;
@@ -49,6 +46,9 @@ import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
 import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
 import org.apache.olingo.odata2.testutil.fit.BaseTest;
 import org.apache.olingo.odata2.testutil.mock.MockFacade;
+import org.junit.Test;
+
+import com.google.gson.stream.JsonReader;
 
 /**
  *  
@@ -56,6 +56,18 @@ import org.apache.olingo.odata2.testutil.mock.MockFacade;
 public class JsonPropertyConsumerTest extends BaseTest {
 
   @Test
+  public void booleanSimpleProperty() throws Exception {
+    EdmProperty property = mock(EdmProperty.class);
+    when(property.getName()).thenReturn("Boolean");
+    when(property.isSimple()).thenReturn(true);
+    when(property.getType()).thenReturn(EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance());
+
+    JsonReader reader = prepareReader("{\"Boolean\":true}");
+    final Map<String, Object> resultMap = execute(property, reader);
+    assertEquals(Boolean.TRUE, resultMap.get("Boolean"));
+  }
+
+  @Test
   public void allNumberSimplePropertyKinds() throws Exception {
     String simplePropertyJson = "{\"d\":{\"Age\":67}}";
     EdmProperty edmProperty = mock(EdmProperty.class);
@@ -143,15 +155,12 @@ public class JsonPropertyConsumerTest extends BaseTest {
     resultMap = execute(edmProperty, reader);
     assertEquals(UUID.fromString("aabbccdd-aabb-ccdd-eeff-aabbccddeeff"), resultMap.get("Name"));
     //Binary
-    byte[] binary = new byte[] { (byte) 0xAA, (byte) 0xBB, (byte) 0xCC };
     simplePropertyJson = "{\"d\":{\"Name\":\"qrvM\"}}";
     reader = prepareReader(simplePropertyJson);
     when(edmProperty.getType()).thenReturn(EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance());
     resultMap = execute(edmProperty, reader);
-    //TODO: check why byte is comming back insted of Byte object
-    //Byte[] expectedArray = new Byte[] { binary[0], binary[1], binary[2] };
-    byte[] actualArray = (byte[]) resultMap.get("Name");
-    assertTrue(Arrays.equals(binary, actualArray));
+    assertTrue(Arrays.equals(new byte[] { (byte) 0xAA, (byte) 0xBB, (byte) 0xCC },
+        (byte[]) resultMap.get("Name")));
     //Time
     simplePropertyJson = "{\"d\":{\"Name\":\"PT23H32M3S\"}}";
     reader = prepareReader(simplePropertyJson);
@@ -196,6 +205,26 @@ public class JsonPropertyConsumerTest extends BaseTest {
   }
 
   @Test
+  public void simplePropertyNull() throws Exception {
+    JsonReader reader = prepareReader("{\"Name\":null}");
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Room").getProperty("Name");
+    final Map<String, Object> resultMap = new JsonPropertyConsumer().readPropertyStandalone(reader, property, null);
+    assertTrue(resultMap.containsKey("Name"));
+    assertNull(resultMap.get("Name"));
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void simplePropertyNullValueNotAllowed() throws Exception {
+    JsonReader reader = prepareReader("{\"Age\":null}");
+    EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.isNullable()).thenReturn(false);
+    when(property.getFacets()).thenReturn(facets);
+
+    new JsonPropertyConsumer().readPropertyStandalone(reader, property, null);
+  }
+
+  @Test
   public void simplePropertyWithNullMappingStandalone() throws Exception {
     String simplePropertyJson = "{\"d\":{\"Age\":67}}";
     JsonReader reader = prepareReader(simplePropertyJson);
@@ -289,10 +318,9 @@ public class JsonPropertyConsumerTest extends BaseTest {
 
   @Test
   public void complexPropertyWithStringToStringMappingStandalone() throws Exception {
-    String simplePropertyJson = "{\"d\":{\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}}}";
-    JsonReader reader = prepareReader(simplePropertyJson);
-    EdmComplexType complexPropertyType = (EdmComplexType) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location").getType();
-    EdmProperty edmProperty = (EdmProperty) complexPropertyType.getProperty("City");
+    final String complexPropertyJson = "{\"d\":{\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}}}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
 
     EntityProviderReadProperties readProperties = mock(EntityProviderReadProperties.class);
     Map<String, Object> innerMappings = new HashMap<String, Object>();
@@ -300,7 +328,7 @@ public class JsonPropertyConsumerTest extends BaseTest {
     Map<String, Object> typeMappings = new HashMap<String, Object>();
     typeMappings.put("City", innerMappings);
     when(readProperties.getTypeMappings()).thenReturn(typeMappings);
-    Map<String, Object> result = new JsonPropertyConsumer().readPropertyStandalone(reader, edmProperty, readProperties);
+    Map<String, Object> result = new JsonPropertyConsumer().readPropertyStandalone(reader, property, readProperties);
 
     assertEquals(1, result.size());
     @SuppressWarnings("unchecked")
@@ -311,8 +339,8 @@ public class JsonPropertyConsumerTest extends BaseTest {
 
   @Test
   public void deepComplexPropertyWithStringToStringMappingStandalone() throws Exception {
-    String simplePropertyJson = "{\"d\":{\"Location\":{\"__metadata\":{\"type\":\"RefScenario.c_Location\"},\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"},\"Country\":\"Germany\"}}}";
-    JsonReader reader = prepareReader(simplePropertyJson);
+    final String complexPropertyJson = "{\"d\":{\"Location\":{\"__metadata\":{\"type\":\"RefScenario.c_Location\"},\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"},\"Country\":\"Germany\"}}}";
+    JsonReader reader = prepareReader(complexPropertyJson);
     EdmProperty edmProperty = (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location");
 
     EntityProviderReadProperties readProperties = mock(EntityProviderReadProperties.class);
@@ -340,11 +368,10 @@ public class JsonPropertyConsumerTest extends BaseTest {
 
   @Test
   public void complexPropertyOnOpenReader() throws Exception {
-    String simplePropertyJson = "{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}";
-    JsonReader reader = prepareReader(simplePropertyJson);
-    EdmComplexType complexPropertyType = (EdmComplexType) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location").getType();
-    EdmProperty edmProperty = (EdmProperty) complexPropertyType.getProperty("City");
-    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) EntityInfoAggregator.create(edmProperty);
+    final String complexPropertyJson = "{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
+    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) EntityInfoAggregator.create(property);
 
     JsonPropertyConsumer jpc = new JsonPropertyConsumer();
     @SuppressWarnings("unchecked")
@@ -357,11 +384,10 @@ public class JsonPropertyConsumerTest extends BaseTest {
 
   @Test
   public void complexPropertyOnOpenReaderWithNoMetadata() throws Exception {
-    String simplePropertyJson = "{\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}";
-    JsonReader reader = prepareReader(simplePropertyJson);
-    EdmComplexType complexPropertyType = (EdmComplexType) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location").getType();
-    EdmProperty edmProperty = (EdmProperty) complexPropertyType.getProperty("City");
-    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) EntityInfoAggregator.create(edmProperty);
+    final String complexPropertyJson = "{\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
+    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) EntityInfoAggregator.create(property);
 
     JsonPropertyConsumer jpc = new JsonPropertyConsumer();
     @SuppressWarnings("unchecked")
@@ -374,8 +400,8 @@ public class JsonPropertyConsumerTest extends BaseTest {
 
   @Test
   public void deepComplexPropertyOnOpenReader() throws Exception {
-    String simplePropertyJson = "{\"__metadata\":{\"type\":\"RefScenario.c_Location\"},\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"},\"Country\":\"Germany\"}";
-    JsonReader reader = prepareReader(simplePropertyJson);
+    final String complexPropertyJson = "{\"__metadata\":{\"type\":\"RefScenario.c_Location\"},\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"},\"Country\":\"Germany\"}";
+    JsonReader reader = prepareReader(complexPropertyJson);
     EdmProperty edmProperty = (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location");
     EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) EntityInfoAggregator.create(edmProperty);
 
@@ -404,12 +430,11 @@ public class JsonPropertyConsumerTest extends BaseTest {
 
   @Test
   public void complexPropertyStandalone() throws Exception {
-    String simplePropertyJson = "{\"d\":{\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}}}";
-    JsonReader reader = prepareReader(simplePropertyJson);
-    EdmComplexType complexPropertyType = (EdmComplexType) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location").getType();
-    EdmProperty edmProperty = (EdmProperty) complexPropertyType.getProperty("City");
+    final String complexPropertyJson = "{\"d\":{\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}}}";
+    JsonReader reader = prepareReader(complexPropertyJson);
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
 
-    Map<String, Object> result = new JsonPropertyConsumer().readPropertyStandalone(reader, edmProperty, null);
+    final Map<String, Object> result = new JsonPropertyConsumer().readPropertyStandalone(reader, property, null);
 
     assertEquals(1, result.size());
     @SuppressWarnings("unchecked")
@@ -420,8 +445,8 @@ public class JsonPropertyConsumerTest extends BaseTest {
 
   @Test
   public void deepComplexPropertyStandalone() throws Exception {
-    String simplePropertyJson = "{\"d\":{\"Location\":{\"__metadata\":{\"type\":\"RefScenario.c_Location\"},\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"},\"Country\":\"Germany\"}}}";
-    JsonReader reader = prepareReader(simplePropertyJson);
+    final String complexPropertyJson = "{\"d\":{\"Location\":{\"__metadata\":{\"type\":\"RefScenario.c_Location\"},\"City\":{\"__metadata\":{\"type\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"},\"Country\":\"Germany\"}}}";
+    JsonReader reader = prepareReader(complexPropertyJson);
     EdmProperty edmProperty = (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location");
 
     JsonPropertyConsumer jpc = new JsonPropertyConsumer();
@@ -443,44 +468,66 @@ public class JsonPropertyConsumerTest extends BaseTest {
   public void complexPropertyWithInvalidChild() throws Exception {
     String cityProperty = "{\"d\":{\"City\":{\"Invalid\":\"69124\",\"CityName\":\"Heidelberg\"}}}";
     JsonReader reader = prepareReader(cityProperty);
-    EdmComplexType complexPropertyType = (EdmComplexType) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location").getType();
-    EdmProperty edmProperty = (EdmProperty) complexPropertyType.getProperty("City");
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
 
-    new JsonPropertyConsumer().readPropertyStandalone(reader, edmProperty, null);
+    new JsonPropertyConsumer().readPropertyStandalone(reader, property, null);
   }
 
   @Test(expected = EntityProviderException.class)
   public void complexPropertyWithInvalidName() throws Exception {
     String cityProperty = "{\"d\":{\"Invalid\":{\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}}}";
     JsonReader reader = prepareReader(cityProperty);
-    EdmComplexType complexPropertyType = (EdmComplexType) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location").getType();
-    EdmProperty edmProperty = (EdmProperty) complexPropertyType.getProperty("City");
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
 
-    new JsonPropertyConsumer().readPropertyStandalone(reader, edmProperty, null);
+    new JsonPropertyConsumer().readPropertyStandalone(reader, property, null);
+  }
+
+  @Test
+  public void complexPropertyNull() throws Exception {
+    final String locationProperty = "{\"Location\":null}";
+    JsonReader reader = prepareReader(locationProperty);
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location");
+
+    final Map<String, Object> propertyData = new JsonPropertyConsumer().readPropertyStandalone(reader, property, null);
+    assertNotNull(propertyData);
+    assertEquals(1, propertyData.size());
+    assertTrue(propertyData.containsKey("Location"));
+    assertNull(propertyData.get("Location"));
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void complexPropertyNullValueNotAllowed() throws Exception {
+    final String locationProperty = "{\"Location\":null}";
+    JsonReader reader = prepareReader(locationProperty);
+    EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location");
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.isNullable()).thenReturn(false);
+    when(property.getFacets()).thenReturn(facets);
+
+    new JsonPropertyConsumer().readPropertyStandalone(reader, property, null);
   }
 
   @Test
   public void complexPropertyEmpty() throws Exception {
-    String cityProperty = "{\"d\":{\"City\":null}}";
+    final String cityProperty = "{\"d\":{\"City\":{}}}";
     JsonReader reader = prepareReader(cityProperty);
-    EdmComplexType complexPropertyType = (EdmComplexType) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location").getType();
-    EdmProperty edmProperty = (EdmProperty) complexPropertyType.getProperty("City");
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
 
-    Map<String, Object> propertyData = new JsonPropertyConsumer().readPropertyStandalone(reader, edmProperty, null);
+    final Map<String, Object> propertyData = new JsonPropertyConsumer().readPropertyStandalone(reader, property, null);
     assertNotNull(propertyData);
     assertEquals(1, propertyData.size());
+    assertNotNull(propertyData.get("City"));
     @SuppressWarnings("unchecked")
-    Map<String, Object> innerResult = (Map<String, Object>) propertyData.get("City");
-    assertNull(innerResult);
+    final Map<String, Object> innerMap = (Map<String, Object>) propertyData.get("City");
+    assertTrue(innerMap.isEmpty());
   }
 
   @Test(expected = EntityProviderException.class)
   public void complexPropertyMetadataInvalidTag() throws Exception {
     String complexPropertyJson = "{\"__metadata\":{\"invalid\":\"RefScenario.c_City\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}";
     JsonReader reader = prepareReader(complexPropertyJson);
-    EdmComplexType complexPropertyType = (EdmComplexType) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location").getType();
-    EdmProperty edmProperty = (EdmProperty) complexPropertyType.getProperty("City");
-    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) EntityInfoAggregator.create(edmProperty);
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
+    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) EntityInfoAggregator.create(property);
 
     new JsonPropertyConsumer().readPropertyValue(reader, entityPropertyInfo, null);
   }
@@ -489,9 +536,8 @@ public class JsonPropertyConsumerTest extends BaseTest {
   public void complexPropertyMetadataInvalidTypeContent() throws Exception {
     String complexPropertyJson = "{\"__metadata\":{\"type\":\"Invalid\"},\"PostalCode\":\"69124\",\"CityName\":\"Heidelberg\"}";
     JsonReader reader = prepareReader(complexPropertyJson);
-    EdmComplexType complexPropertyType = (EdmComplexType) MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees").getEntityType().getProperty("Location").getType();
-    EdmProperty edmProperty = (EdmProperty) complexPropertyType.getProperty("City");
-    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) EntityInfoAggregator.create(edmProperty);
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getComplexType("RefScenario", "c_Location").getProperty("City");
+    EntityComplexPropertyInfo entityPropertyInfo = (EntityComplexPropertyInfo) EntityInfoAggregator.create(property);
 
     new JsonPropertyConsumer().readPropertyValue(reader, entityPropertyInfo, null);
   }


Mime
View raw message