You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2014/11/18 15:46:48 UTC

[3/7] olingo-odata4 git commit: [OLINGO-472] Batch Refactoring

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/51acf8ae/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/BatchParserCommonTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/BatchParserCommonTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/BatchParserCommonTest.java
deleted file mode 100644
index e3a1acc..0000000
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/BatchParserCommonTest.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * 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.server.core.batch.parser;
-
-import static org.junit.Assert.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.olingo.commons.api.http.HttpHeader;
-import org.apache.olingo.server.api.batch.BatchException;
-import org.apache.olingo.server.core.batch.parser.BatchParserCommon;
-import org.apache.olingo.server.core.batch.parser.BufferedReaderIncludingLineEndings.Line;
-import org.apache.olingo.server.core.batch.parser.Header;
-import org.junit.Test;
-
-public class BatchParserCommonTest {
-
-  private static final String CRLF = "\r\n";
-
-  @Test
-  public void testMultipleHeader() throws BatchException {
-    String[] messageRaw = new String[] {
-        "Content-Id: 1" + CRLF,
-        "Content-Id: 2" + CRLF,
-        "content-type: Application/http" + CRLF,
-        "content-transfer-encoding: Binary" + CRLF
-      };
-    List<Line> message = toLineList(messageRaw);
-    
-    final Header header = BatchParserCommon.consumeHeaders(message);
-    assertNotNull(header);
-    
-    final List<String> contentIdHeaders = header.getHeaders(BatchParserCommon.HTTP_CONTENT_ID);
-    assertNotNull(contentIdHeaders);
-    assertEquals(2, contentIdHeaders.size());
-    assertEquals("1", contentIdHeaders.get(0));
-    assertEquals("2", contentIdHeaders.get(1));
-  }
-  
-  @Test
-  public void testMultipleHeaderSameValue() throws BatchException {
-    String[] messageRaw = new String[] {
-        "Content-Id: 1" + CRLF,
-        "Content-Id: 1" + CRLF,
-        "content-type: Application/http" + CRLF,
-        "content-transfer-encoding: Binary" + CRLF
-      };
-    List<Line> message = toLineList(messageRaw);
-    
-    final Header header = BatchParserCommon.consumeHeaders(message);
-    assertNotNull(header);
-    
-    final List<String> contentIdHeaders = header.getHeaders(BatchParserCommon.HTTP_CONTENT_ID);
-    assertNotNull(contentIdHeaders);
-    assertEquals(1, contentIdHeaders.size());
-    assertEquals("1", contentIdHeaders.get(0));
-  }
-  
-  @Test
-  public void testHeaderSperatedByComma() throws BatchException {
-    String[] messageRaw = new String[] {
-        "Content-Id: 1" + CRLF,
-        "Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11" + CRLF,
-        "content-type: Application/http" + CRLF,
-        "content-transfer-encoding: Binary" + CRLF
-      };
-    List<Line> message = toLineList(messageRaw);
-    
-    final Header header = BatchParserCommon.consumeHeaders(message);
-    assertNotNull(header);
-    
-    final List<String> upgradeHeader = header.getHeaders("upgrade");
-    assertNotNull(upgradeHeader);
-    assertEquals(4, upgradeHeader.size());
-    assertEquals("HTTP/2.0", upgradeHeader.get(0));
-    assertEquals("SHTTP/1.3", upgradeHeader.get(1));
-    assertEquals("IRC/6.9", upgradeHeader.get(2));
-    assertEquals("RTA/x11", upgradeHeader.get(3));
-  }
-  
-  @Test
-  public void testMultipleAcceptHeader() throws BatchException {
-    String[] messageRaw = new String[] {
-        "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + CRLF,
-        "Accept: text/plain;q=0.3" + CRLF,
-        "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
-        "content-type: Application/http" + CRLF,
-        "content-transfer-encoding: Binary" + CRLF
-      };
-    List<Line> message = toLineList(messageRaw);
-    
-    final Header header = BatchParserCommon.consumeHeaders(message);
-    assertNotNull(header);
-    
-    final List<String> acceptHeader = header.getHeaders(HttpHeader.ACCEPT);
-    assertNotNull(acceptHeader);
-    assertEquals(4, acceptHeader.size());
-  }
-  
-  @Test
-  public void testMultipleAcceptHeaderSameValue() throws BatchException {
-    String[] messageRaw = new String[] {
-        "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + CRLF,
-        "Accept: application/atomsvc+xml;q=0.8" + CRLF,
-        "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
-        "content-type: Application/http" + CRLF,
-        "content-transfer-encoding: Binary" + CRLF
-      };
-    List<Line> message = toLineList(messageRaw);
-    
-    final Header header = BatchParserCommon.consumeHeaders(message);
-    assertNotNull(header);
-    
-    final List<String> acceptHeader = header.getHeaders(HttpHeader.ACCEPT);
-    assertNotNull(acceptHeader);
-    assertEquals(3, acceptHeader.size());
-  }
-  
-  @Test
-  public void testMultipleAccepLanguagetHeader() throws BatchException {
-    String[] messageRaw = new String[] {
-        "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
-        "Accept-Language: de-DE;q=0.3" + CRLF,
-        "content-type: Application/http" + CRLF,
-        "content-transfer-encoding: Binary" + CRLF
-      };
-    List<Line> message = toLineList(messageRaw);
-    
-    final Header header = BatchParserCommon.consumeHeaders(message);
-    assertNotNull(header);
-    
-    final List<String> acceptLanguageHeader = header.getHeaders(HttpHeader.ACCEPT_LANGUAGE);
-    assertNotNull(acceptLanguageHeader);
-    assertEquals(4, acceptLanguageHeader.size());
-  }
-  
-  @Test
-  public void testMultipleAccepLanguagetHeaderSameValue() throws BatchException {
-    String[] messageRaw = new String[] {
-        "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
-        "Accept-Language:en-US,en;q=0.7" + CRLF,
-        "content-type: Application/http" + CRLF,
-        "content-transfer-encoding: Binary" + CRLF
-      };
-    List<Line> message = toLineList(messageRaw);
-    
-    final Header header = BatchParserCommon.consumeHeaders(message);
-    assertNotNull(header);
-    
-    final List<String> acceptLanguageHeader = header.getHeaders(HttpHeader.ACCEPT_LANGUAGE);
-    assertNotNull(acceptLanguageHeader);
-    assertEquals(3, acceptLanguageHeader.size());
-  }
-  
-  @Test
-  public void testRemoveEndingCRLF() {
-    String line = "Test\r\n";
-    assertEquals("Test", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
-  }
-
-  @Test
-  public void testRemoveLastEndingCRLF() {
-    String line = "Test\r\n\r\n";
-    assertEquals("Test\r\n", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
-  }
-
-  @Test
-  public void testRemoveEndingCRLFWithWS() {
-    String line = "Test\r\n            ";
-    assertEquals("Test", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
-  }
-
-  @Test
-  public void testRemoveEndingCRLFNothingToRemove() {
-    String line = "Hallo\r\nBla";
-    assertEquals("Hallo\r\nBla", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
-  }
-
-  @Test
-  public void testRemoveEndingCRLFAll() {
-    String line = "\r\n";
-    assertEquals("", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
-  }
-
-  @Test
-  public void testRemoveEndingCRLFSpace() {
-    String line = "\r\n                      ";
-    assertEquals("", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
-  }
-
-  @Test
-  public void testRemoveLastEndingCRLFWithWS() {
-    String line = "Test            \r\n";
-    assertEquals("Test            ", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
-  }
-
-  @Test
-  public void testRemoveLastEndingCRLFWithWSLong() {
-    String line = "Test            \r\nTest2    \r\n";
-    assertEquals("Test            \r\nTest2    ", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
-  }
-  
-  private List<Line> toLineList(String[] messageRaw) {
-    final List<Line> lineList = new ArrayList<Line>();
-    int counter = 1;
-    
-    for(final String currentLine : messageRaw) {
-      lineList.add(new Line(currentLine, counter++));
-    }
-    
-    return lineList;
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/51acf8ae/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/BufferedReaderIncludingLineEndingsTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/BufferedReaderIncludingLineEndingsTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/BufferedReaderIncludingLineEndingsTest.java
deleted file mode 100644
index eac9dff..0000000
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/BufferedReaderIncludingLineEndingsTest.java
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * 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.server.core.batch.parser;
-
-import static org.junit.Assert.*;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.util.List;
-
-import org.apache.olingo.server.core.batch.parser.BufferedReaderIncludingLineEndings;
-import org.apache.olingo.server.core.batch.parser.BufferedReaderIncludingLineEndings.Line;
-import org.junit.Test;
-
-public class BufferedReaderIncludingLineEndingsTest {
-
-
-  private static final String TEXT_COMBINED = "Test\r" +
-      "Test2\r\n" +
-      "Test3\n" +
-      "Test4\r" +
-      "\r" +
-      "\r\n" +
-      "\r\n" +
-      "Test5\n" +
-      "Test6\r\n" +
-      "Test7\n" +
-      "\n";
-
-  private static final String TEXT_SMALL = "Test\r" +
-      "123";
-  private static final String TEXT_EMPTY = "";
-
-  @Test
-  public void testSimpleText() throws IOException {
-    final String TEXT = "Test";
-    BufferedReaderIncludingLineEndings reader = create(TEXT);
-
-    assertEquals(TEXT, reader.readLine());
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testNoText() throws IOException {
-    final String TEXT = "";
-    BufferedReaderIncludingLineEndings reader = create(TEXT);
-
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testNoBytes() throws IOException {
-    BufferedReaderIncludingLineEndings reader =
-        new BufferedReaderIncludingLineEndings(new InputStreamReader(new ByteArrayInputStream(new byte[0])));
-
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testCRLF() throws IOException {
-    final String TEXT = "Test\r\n" +
-        "Test2";
-
-    BufferedReaderIncludingLineEndings reader = create(TEXT);
-
-    assertEquals("Test\r\n", reader.readLine());
-    assertEquals("Test2", reader.readLine());
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testLF() throws IOException {
-    final String TEXT = "Test\n" +
-        "Test2";
-
-    BufferedReaderIncludingLineEndings reader = create(TEXT);
-
-    assertEquals("Test\n", reader.readLine());
-    assertEquals("Test2", reader.readLine());
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testCR() throws IOException {
-    final String TEXT = "Test\r" +
-        "Test2";
-
-    BufferedReaderIncludingLineEndings reader = create(TEXT);
-
-    assertEquals("Test\r", reader.readLine());
-    assertEquals("Test2", reader.readLine());
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testCombined() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create(TEXT_COMBINED);
-
-    assertEquals("Test\r", reader.readLine());
-    assertEquals("Test2\r\n", reader.readLine());
-    assertEquals("Test3\n", reader.readLine());
-    assertEquals("Test4\r", reader.readLine());
-    assertEquals("\r", reader.readLine());
-    assertEquals("\r\n", reader.readLine());
-    assertEquals("\r\n", reader.readLine());
-    assertEquals("Test5\n", reader.readLine());
-    assertEquals("Test6\r\n", reader.readLine());
-    assertEquals("Test7\n", reader.readLine());
-    assertEquals("\n", reader.readLine());
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testCombinedBufferSizeTwo() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create(TEXT_COMBINED, 2);
-
-    assertEquals("Test\r", reader.readLine());
-    assertEquals("Test2\r\n", reader.readLine());
-    assertEquals("Test3\n", reader.readLine());
-    assertEquals("Test4\r", reader.readLine());
-    assertEquals("\r", reader.readLine());
-    assertEquals("\r\n", reader.readLine());
-    assertEquals("\r\n", reader.readLine());
-    assertEquals("Test5\n", reader.readLine());
-    assertEquals("Test6\r\n", reader.readLine());
-    assertEquals("Test7\n", reader.readLine());
-    assertEquals("\n", reader.readLine());
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testCombinedBufferSizeOne() throws IOException {
-    final String TEXT = "Test\r" +
-        "Test2\r\n" +
-        "Test3\n" +
-        "Test4\r" +
-        "\r" +
-        "\r\n" +
-        "\r\n" +
-        "Test5\n" +
-        "Test6\r\n" +
-        "Test7\n" +
-        "\r\n";
-
-    BufferedReaderIncludingLineEndings reader = create(TEXT, 1);
-
-    assertEquals("Test\r", reader.readLine());
-    assertEquals("Test2\r\n", reader.readLine());
-    assertEquals("Test3\n", reader.readLine());
-    assertEquals("Test4\r", reader.readLine());
-    assertEquals("\r", reader.readLine());
-    assertEquals("\r\n", reader.readLine());
-    assertEquals("\r\n", reader.readLine());
-    assertEquals("Test5\n", reader.readLine());
-    assertEquals("Test6\r\n", reader.readLine());
-    assertEquals("Test7\n", reader.readLine());
-    assertEquals("\r\n", reader.readLine());
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-
-    reader.close();
-  }
-
-  @Test
-  public void testDoubleLF() throws IOException {
-    final String TEXT = "Test\r" +
-        "\r";
-
-    BufferedReaderIncludingLineEndings reader = create(TEXT, 1);
-
-    assertEquals("Test\r", reader.readLine());
-    assertEquals("\r", reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testSkipSimple() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create(TEXT_SMALL);
-
-    assertEquals(5, reader.skip(5)); // Test\r
-    assertEquals("123", reader.readLine());
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testSkipBufferOne() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create(TEXT_SMALL, 1);
-
-    assertEquals(5, reader.skip(5)); // Test\r
-    assertEquals("123", reader.readLine());
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testReadThanSkip() throws IOException {
-    final String TEXT = "Test\r" +
-        "\r" +
-        "123";
-
-    BufferedReaderIncludingLineEndings reader = create(TEXT);
-
-    assertEquals("Test\r", reader.readLine());
-    assertEquals(1, reader.skip(1)); // Test\r
-    assertEquals("123", reader.readLine());
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testReadMoreBufferCapacityThanCharacterAvailable() throws IOException {
-    final String TEXT = "Foo";
-    char[] buffer = new char[20];
-
-    BufferedReaderIncludingLineEndings reader = create(TEXT);
-    assertEquals(3, reader.read(buffer, 0, 20));
-    assertEquals(-1, reader.read(buffer, 0, 20));
-    reader.close();
-
-    BufferedReaderIncludingLineEndings readerBufferOne = create(TEXT, 1);
-    assertEquals(3, readerBufferOne.read(buffer, 0, 20));
-    assertEquals(-1, readerBufferOne.read(buffer, 0, 20));
-    readerBufferOne.close();
-  }
-
-  @Test
-  public void testSkipZero() throws IOException {
-    final String TEXT = "Test\r" +
-        "123\r\n";
-
-    BufferedReaderIncludingLineEndings reader = create(TEXT);
-
-    assertEquals(0, reader.skip(0)); // Test\r
-    assertEquals("Test\r", reader.readLine());
-    assertEquals("123\r\n", reader.readLine());
-    assertNull(reader.readLine());
-    assertNull(reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testSkipToMuch() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create(TEXT_SMALL);
-
-    assertEquals(8, reader.skip(10)); // Test\r
-    assertEquals(null, reader.readLine());
-    reader.close();
-  }
-
-  @Test
-  public void testReadBufferOne() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create(TEXT_SMALL, 1);
-
-    assertEquals('T', reader.read());
-    assertEquals('e', reader.read());
-    assertEquals('s', reader.read());
-    assertEquals('t', reader.read());
-    assertEquals('\r', reader.read());
-    assertEquals('1', reader.read());
-    assertEquals('2', reader.read());
-    assertEquals('3', reader.read());
-    assertEquals(-1, reader.read());
-    assertEquals(-1, reader.read());
-  }
-
-  @Test
-  public void testReadZeroBytes() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create(TEXT_SMALL, 1);
-
-    char[] buffer = new char[3];
-    assertEquals(0, reader.read(buffer, 0, 0));
-    assertEquals('T', reader.read());
-    assertEquals(0, reader.read(buffer, 0, 0));
-    assertEquals("est\r", reader.readLine());
-    assertEquals("123", reader.readLine());
-
-    reader.close();
-  }
-
-  @Test
-  public void testRead() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create(TEXT_SMALL);
-
-    assertEquals('T', reader.read());
-    assertEquals('e', reader.read());
-    assertEquals('s', reader.read());
-    assertEquals('t', reader.read());
-    assertEquals('\r', reader.read());
-    assertEquals('1', reader.read());
-    assertEquals('2', reader.read());
-    assertEquals('3', reader.read());
-    assertEquals(-1, reader.read());
-    assertEquals(-1, reader.read());
-  }
-
-  @Test(expected = IndexOutOfBoundsException.class)
-  public void testFailReadBufferAndOffsetBiggerThanBuffer() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create("");
-
-    final char[] buffer = new char[3];
-    reader.read(buffer, 1, 3);
-  }
-
-  @Test(expected = IndexOutOfBoundsException.class)
-  public void testFailLengthNegative() throws IOException {
-    final char[] buffer = new char[3];
-    BufferedReaderIncludingLineEndings reader = create("123");
-
-    reader.read(buffer, 1, -2);
-    reader.close();
-  }
-
-  @Test(expected = IndexOutOfBoundsException.class)
-  public void testFailOffsetNegative() throws IOException {
-    final char[] buffer = new char[3];
-    BufferedReaderIncludingLineEndings reader = create("123");
-
-    reader.read(buffer, -1, 2);
-    reader.close();
-  }
-
-  @Test
-  public void testReadAndReadLine() throws IOException {
-    final String TEXT = "Test\r" +
-        "bar\n" +
-        "123\r\n" +
-        "foo";
-
-    BufferedReaderIncludingLineEndings reader = create(TEXT);
-
-    assertEquals('T', reader.read());
-    assertEquals('e', reader.read());
-    assertEquals('s', reader.read());
-    assertEquals('t', reader.read());
-    assertEquals("\r", reader.readLine());
-    assertEquals("bar\n", reader.readLine());
-    assertEquals('1', reader.read());
-    assertEquals('2', reader.read());
-    assertEquals("3\r\n", reader.readLine());
-    assertEquals("foo", reader.readLine());
-    assertEquals(null, reader.readLine());
-    assertEquals(-1, reader.read());
-  }
-  
-  @Test
-  public void testLineEqualsAndHashCode() {
-    Line l1 = new Line("The first line", 1);
-    Line l2 = new Line("The first line", 1);
-    Line l3 = new Line("The second line", 2);
-    
-    assertEquals(l1, l2);
-    assertFalse(l1.equals(l3));
-    assertTrue(l1.hashCode() != l3.hashCode());
-  }
-  
-  @Test(expected = IllegalArgumentException.class)
-  public void testSkipNegative() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create("123");
-    reader.skip(-1);
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void testFailBufferSizeZero() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create(TEXT_EMPTY, 0);
-    reader.close();
-  }
-
-  @Test(expected = NullPointerException.class)
-  public void testInputStreamIsNull() throws IOException {
-    // Same behaviour like BufferedReader
-    BufferedReaderIncludingLineEndings reader = new BufferedReaderIncludingLineEndings(null);
-    reader.close();
-  }
-
-  @Test(expected = IllegalArgumentException.class)
-  public void testFailBufferSizeNegative() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create(TEXT_EMPTY, -1);
-    reader.close();
-  }
-
-  @Test
-  public void testMarkSupoorted() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create(TEXT_EMPTY);
-
-    assertEquals(false, reader.markSupported());
-    reader.close();
-  }
-
-  @Test(expected = IOException.class)
-  public void testFailMark() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create("123");
-
-    reader.mark(1);
-  }
-
-  @Test(expected = IOException.class)
-  public void testFailReset() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create("123");
-
-    reader.reset();
-  }
-
-  @Test
-  public void testReady() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create("123\r123");
-    assertEquals(false, reader.ready());
-    assertEquals("123\r", reader.readLine());
-    assertEquals(true, reader.ready());
-    assertEquals("123", reader.readLine());
-    assertEquals(false, reader.ready());
-
-    reader.close();
-  }
-
-  @Test
-  public void testToList() throws IOException {
-    BufferedReaderIncludingLineEndings reader = create(TEXT_COMBINED);
-    List<Line> stringList = reader.toLineList();
-
-    assertEquals(11, stringList.size());
-    assertEquals("Test\r", stringList.get(0).toString());
-    assertEquals("Test2\r\n", stringList.get(1).toString());
-    assertEquals("Test3\n", stringList.get(2).toString());
-    assertEquals("Test4\r", stringList.get(3).toString());
-    assertEquals("\r", stringList.get(4).toString());
-    assertEquals("\r\n", stringList.get(5).toString());
-    assertEquals("\r\n", stringList.get(6).toString());
-    assertEquals("Test5\n", stringList.get(7).toString());
-    assertEquals("Test6\r\n", stringList.get(8).toString());
-    assertEquals("Test7\n", stringList.get(9).toString());
-    assertEquals("\n", stringList.get(10).toString());
-    reader.close();
-  }
-
-  private BufferedReaderIncludingLineEndings create(final String inputString) throws UnsupportedEncodingException {
-    return new BufferedReaderIncludingLineEndings(new InputStreamReader(new ByteArrayInputStream(inputString
-        .getBytes("UTF-8"))));
-  }
-
-  private BufferedReaderIncludingLineEndings create(final String inputString, int bufferSize)
-      throws UnsupportedEncodingException {
-    return new BufferedReaderIncludingLineEndings(new InputStreamReader(new ByteArrayInputStream(inputString
-        .getBytes("UTF-8"))), bufferSize);
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/51acf8ae/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/HeaderTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/HeaderTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/HeaderTest.java
deleted file mode 100644
index f38ac89..0000000
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/parser/HeaderTest.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * 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.server.core.batch.parser;
-
-import static org.junit.Assert.*;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.olingo.commons.api.http.HttpContentType;
-import org.apache.olingo.commons.api.http.HttpHeader;
-import org.apache.olingo.server.core.batch.parser.BatchParserCommon;
-import org.apache.olingo.server.core.batch.parser.Header;
-import org.junit.Test;
-
-public class HeaderTest {
-
-  @Test
-  public void test() {
-    Header header = new Header(1);
-    header.addHeader(HttpHeader.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 1);
-
-    assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeader(HttpHeader.CONTENT_TYPE));
-    assertEquals(1, header.getHeaders(HttpHeader.CONTENT_TYPE).size());
-    assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeaders(HttpHeader.CONTENT_TYPE).get(0));
-  }
-
-  @Test
-  public void testNotAvailable() {
-    Header header = new Header(1);
-
-    assertNull(header.getHeader(HttpHeader.CONTENT_TYPE));
-    assertEquals(0, header.getHeaders(HttpHeader.CONTENT_TYPE).size());
-    assertEquals("", header.getHeaderNotNull(HttpHeader.CONTENT_TYPE));
-  }
-
-  @Test
-  public void testCaseInsensitive() {
-    Header header = new Header(1);
-    header.addHeader(HttpHeader.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 1);
-
-    assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeader("cOnTenT-TyPE"));
-    assertEquals(1, header.getHeaders("cOnTenT-TyPE").size());
-    assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeaders("cOnTenT-TyPE").get(0));
-  }
-
-  @Test
-  public void testDuplicatedAdd() {
-    Header header = new Header(1);
-    header.addHeader(HttpHeader.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 1);
-    header.addHeader(HttpHeader.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 2);
-
-    assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeader(HttpHeader.CONTENT_TYPE));
-    assertEquals(1, header.getHeaders(HttpHeader.CONTENT_TYPE).size());
-    assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeaders(HttpHeader.CONTENT_TYPE).get(0));
-  }
-
-  @Test
-  public void testMatcher() {
-    Header header = new Header(1);
-    header.addHeader(HttpHeader.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + ";boundary=123", 1);
-
-    assertTrue(header.isHeaderMatching(HttpHeader.CONTENT_TYPE, BatchParserCommon.PATTERN_MULTIPART_BOUNDARY));
-  }
-
-  @Test
-  public void testFieldName() {
-    Header header = new Header(0);
-    header.addHeader("MyFieldNamE", "myValue", 1);
-
-    assertEquals("MyFieldNamE", header.getHeaderField("myfieldname").getFieldName());
-    assertEquals("MyFieldNamE", header.toSingleMap().keySet().toArray(new String[0])[0]);
-    assertEquals("MyFieldNamE", header.toMultiMap().keySet().toArray(new String[0])[0]);
-
-    assertEquals("myValue", header.toMultiMap().get("MyFieldNamE").get(0));
-    assertEquals("myValue", header.toSingleMap().get("MyFieldNamE"));
-  }
-
-  @Test
-  public void testDeepCopy() {
-    Header header = new Header(1);
-    header.addHeader(HttpHeader.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + ";boundary=123", 1);
-
-    Header copy = header.clone();
-    assertEquals(header.getHeaders(HttpHeader.CONTENT_TYPE), copy.getHeaders(HttpHeader.CONTENT_TYPE));
-    assertEquals(header.getHeader(HttpHeader.CONTENT_TYPE), copy.getHeader(HttpHeader.CONTENT_TYPE));
-    assertEquals(header.getHeaderField(HttpHeader.CONTENT_TYPE), copy.getHeaderField(HttpHeader.CONTENT_TYPE));
-
-    assertTrue(header.getHeaders(HttpHeader.CONTENT_TYPE) != copy.getHeaders(HttpHeader.CONTENT_TYPE));
-    assertTrue(header.getHeaderField(HttpHeader.CONTENT_TYPE) != copy.getHeaderField(HttpHeader.CONTENT_TYPE));
-  }
-
-  @Test
-  public void testMatcherNoHeader() {
-    Header header = new Header(1);
-
-    assertFalse(header.isHeaderMatching(HttpHeader.CONTENT_TYPE, BatchParserCommon.PATTERN_MULTIPART_BOUNDARY));
-  }
-
-//  @Test
-//  public void testMatcherFail() {
-//    Header header = new Header(1);
-//    header.addHeader(HttpHeader.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED + ";boundary=123", 1);
-//
-//    assertFalse(header.isHeaderMatching(HttpHeader.CONTENT_TYPE, BatchParserCommon.PATTERN_HEADER_LINE));
-//  }
-
-  @Test
-  public void testDuplicatedAddList() {
-    Header header = new Header(1);
-    header.addHeader(HttpHeader.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 1);
-    header.addHeader(HttpHeader.CONTENT_TYPE, Arrays.asList(new String[] { HttpContentType.MULTIPART_MIXED,
-        HttpContentType.APPLICATION_ATOM_SVC }), 2);
-
-    assertEquals(HttpContentType.MULTIPART_MIXED + ", " + HttpContentType.APPLICATION_ATOM_SVC, header
-        .getHeader(HttpHeader.CONTENT_TYPE));
-    assertEquals(2, header.getHeaders(HttpHeader.CONTENT_TYPE).size());
-    assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeaders(HttpHeader.CONTENT_TYPE).get(0));
-    assertEquals(HttpContentType.APPLICATION_ATOM_SVC, header.getHeaders(HttpHeader.CONTENT_TYPE).get(1));
-  }
-
-  @Test
-  public void testRemove() {
-    Header header = new Header(1);
-    header.addHeader(HttpHeader.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 1);
-    header.removeHeader(HttpHeader.CONTENT_TYPE);
-
-    assertNull(header.getHeader(HttpHeader.CONTENT_TYPE));
-    assertEquals(0, header.getHeaders(HttpHeader.CONTENT_TYPE).size());
-  }
-
-  @Test
-  public void testMultipleValues() {
-    Header header = new Header(1);
-    header.addHeader(HttpHeader.CONTENT_TYPE, HttpContentType.MULTIPART_MIXED, 1);
-    header.addHeader(HttpHeader.CONTENT_TYPE, HttpContentType.APPLICATION_ATOM_SVC, 2);
-    header.addHeader(HttpHeader.CONTENT_TYPE, HttpContentType.APPLICATION_ATOM_XML, 3);
-
-    final String fullHeaderString =
-        HttpContentType.MULTIPART_MIXED + ", " + HttpContentType.APPLICATION_ATOM_SVC + ", "
-            + HttpContentType.APPLICATION_ATOM_XML;
-
-    assertEquals(fullHeaderString, header.getHeader(HttpHeader.CONTENT_TYPE));
-    assertEquals(3, header.getHeaders(HttpHeader.CONTENT_TYPE).size());
-    assertEquals(HttpContentType.MULTIPART_MIXED, header.getHeaders(HttpHeader.CONTENT_TYPE).get(0));
-    assertEquals(HttpContentType.APPLICATION_ATOM_SVC, header.getHeaders(HttpHeader.CONTENT_TYPE).get(1));
-    assertEquals(HttpContentType.APPLICATION_ATOM_XML, header.getHeaders(HttpHeader.CONTENT_TYPE).get(2));
-  }
-  
-  @Test
-  public void testSplitValues() {
-    final String values = "abc, def,123,77,   99, ysd";
-    List<String> splittedValues = Header.splitValuesByComma(values);
-
-    assertEquals(6, splittedValues.size());
-    assertEquals("abc", splittedValues.get(0));
-    assertEquals("def", splittedValues.get(1));
-    assertEquals("123", splittedValues.get(2));
-    assertEquals("77", splittedValues.get(3));
-    assertEquals("99", splittedValues.get(4));
-    assertEquals("ysd", splittedValues.get(5));
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/51acf8ae/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/writer/BatchResponseWriterTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/writer/BatchResponseWriterTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/writer/BatchResponseWriterTest.java
deleted file mode 100644
index ea05bfb..0000000
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/batch/writer/BatchResponseWriterTest.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * 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.server.core.batch.writer;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.olingo.commons.api.http.HttpHeader;
-import org.apache.olingo.commons.api.http.HttpStatusCode;
-import org.apache.olingo.server.api.ODataResponse;
-import org.apache.olingo.server.api.batch.BatchException;
-import org.apache.olingo.server.api.batch.ODataResponsePart;
-import org.apache.olingo.server.core.batch.StringUtil;
-import org.apache.olingo.server.core.batch.parser.BatchParserCommon;
-import org.apache.olingo.server.core.batch.parser.BufferedReaderIncludingLineEndings;
-import org.junit.Test;
-
-public class BatchResponseWriterTest {
-  private static final String CRLF = "\r\n";
-
-  @Test
-  public void testBatchResponse() throws IOException, BatchException {
-    final List<ODataResponsePart> parts = new ArrayList<ODataResponsePart>();
-    ODataResponse response = new ODataResponse();
-    response.setStatusCode(HttpStatusCode.OK.getStatusCode());
-    response.setHeader(HttpHeader.CONTENT_TYPE, "application/json");
-    response.setContent(StringUtil.toInputStream("Walter Winter" + CRLF));
-
-    List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
-    responses.add(response);
-    parts.add(new ODataResponsePart(responses, false));
-
-    ODataResponse changeSetResponse = new ODataResponse();
-    changeSetResponse.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
-    changeSetResponse.setHeader(BatchParserCommon.HTTP_CONTENT_ID, "1");
-    responses = new ArrayList<ODataResponse>(1);
-    responses.add(changeSetResponse);
-    parts.add(new ODataResponsePart(responses, true));
-
-    BatchResponseWriter writer = new BatchResponseWriter();
-    ODataResponse batchResponse = new ODataResponse();
-    writer.toODataResponse(parts, batchResponse);
-
-    assertEquals(202, batchResponse.getStatusCode());
-    assertNotNull(batchResponse.getContent());
-    final BufferedReaderIncludingLineEndings reader =
-        new BufferedReaderIncludingLineEndings(new InputStreamReader(batchResponse.getContent()));
-    final List<String> body = reader.toList();
-    reader.close();
-    
-    int line = 0;
-    assertEquals(25, body.size());
-    assertTrue(body.get(line++).contains("--batch_"));
-    assertEquals("Content-Type: application/http" + CRLF, body.get(line++));
-    assertEquals("Content-Transfer-Encoding: binary" + CRLF, body.get(line++));
-    assertEquals(CRLF, body.get(line++));
-    assertEquals("HTTP/1.1 200 OK" + CRLF, body.get(line++));
-    assertEquals("Content-Type: application/json" + CRLF, body.get(line++));
-    assertEquals("Content-Length: 15" + CRLF, body.get(line++));
-    assertEquals(CRLF, body.get(line++));
-    assertEquals("Walter Winter" + CRLF, body.get(line++));
-    assertEquals(CRLF, body.get(line++));
-    assertTrue(body.get(line++).contains("--batch_"));
-    assertTrue(body.get(line++).contains("Content-Type: multipart/mixed; boundary=changeset_"));
-    assertEquals(CRLF, body.get(line++));
-    assertTrue(body.get(line++).contains("--changeset_"));
-    assertEquals("Content-Type: application/http" + CRLF, body.get(line++));
-    assertEquals("Content-Transfer-Encoding: binary" + CRLF, body.get(line++));
-    assertEquals("Content-Id: 1" + CRLF, body.get(line++));
-    assertEquals(CRLF, body.get(line++));
-    assertEquals("HTTP/1.1 204 No Content" + CRLF, body.get(line++));
-    assertEquals("Content-Length: 0" + CRLF, body.get(line++));
-    assertEquals(CRLF, body.get(line++));
-    assertEquals(CRLF, body.get(line++));
-    assertTrue(body.get(line++).contains("--changeset_"));
-    assertEquals(CRLF, body.get(line++));
-    assertTrue(body.get(line++).contains("--batch_"));
-  }
-
-  @Test
-  public void testResponse() throws IOException, BatchException {
-    List<ODataResponsePart> parts = new ArrayList<ODataResponsePart>();
-    ODataResponse response = new ODataResponse();
-    response.setStatusCode(HttpStatusCode.OK.getStatusCode());
-    response.setHeader(HttpHeader.CONTENT_TYPE, "application/json");
-    response.setContent(StringUtil.toInputStream("Walter Winter"));
-
-    List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
-    responses.add(response);
-    parts.add(new ODataResponsePart(responses, false));
-
-    ODataResponse batchResponse = new ODataResponse();
-    new BatchResponseWriter().toODataResponse(parts, batchResponse);
-
-    assertEquals(202, batchResponse.getStatusCode());
-    assertNotNull(batchResponse.getContent());
-    final BufferedReaderIncludingLineEndings reader =
-        new BufferedReaderIncludingLineEndings(new InputStreamReader(batchResponse.getContent()));
-    final List<String> body = reader.toList();
-    reader.close();
-    
-    int line = 0;
-    assertEquals(10, body.size());
-    assertTrue(body.get(line++).contains("--batch_"));
-    assertEquals("Content-Type: application/http" + CRLF, body.get(line++));
-    assertEquals("Content-Transfer-Encoding: binary" + CRLF, body.get(line++));
-    assertEquals(CRLF, body.get(line++));
-    assertEquals("HTTP/1.1 200 OK" + CRLF, body.get(line++));
-    assertEquals("Content-Type: application/json" + CRLF, body.get(line++));
-    assertEquals("Content-Length: 13" + CRLF, body.get(line++));
-    assertEquals(CRLF, body.get(line++));
-    assertEquals("Walter Winter" + CRLF, body.get(line++));
-    assertTrue(body.get(line++).contains("--batch_"));
-  }
-
-  @Test
-  public void testChangeSetResponse() throws IOException, BatchException {
-    List<ODataResponsePart> parts = new ArrayList<ODataResponsePart>();
-    ODataResponse response = new ODataResponse();
-    response.setHeader(BatchParserCommon.HTTP_CONTENT_ID, "1");
-    response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
-
-    List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
-    responses.add(response);
-    parts.add(new ODataResponsePart(responses, true));
-
-    BatchResponseWriter writer = new BatchResponseWriter();
-    ODataResponse batchResponse = new ODataResponse();
-    writer.toODataResponse(parts, batchResponse);
-
-    assertEquals(202, batchResponse.getStatusCode());
-    assertNotNull(batchResponse.getContent());
-
-    final BufferedReaderIncludingLineEndings reader =
-        new BufferedReaderIncludingLineEndings(new InputStreamReader(batchResponse.getContent()));
-    final List<String> body = reader.toList();
-    reader.close();
-    
-    int line = 0;
-    assertEquals(15, body.size());
-    assertTrue(body.get(line++).contains("--batch_"));
-    assertTrue(body.get(line++).contains("Content-Type: multipart/mixed; boundary=changeset_"));
-    assertEquals(CRLF, body.get(line++));
-    assertTrue(body.get(line++).contains("--changeset_"));
-    assertEquals("Content-Type: application/http" + CRLF, body.get(line++));
-    assertEquals("Content-Transfer-Encoding: binary" + CRLF, body.get(line++));
-    assertEquals("Content-Id: 1" + CRLF, body.get(line++));
-    assertEquals(CRLF, body.get(line++));
-    assertEquals("HTTP/1.1 204 No Content" + CRLF, body.get(line++));
-    assertEquals("Content-Length: 0" + CRLF, body.get(line++));
-    assertEquals(CRLF, body.get(line++));
-    assertEquals(CRLF, body.get(line++));
-    assertTrue(body.get(line++).contains("--changeset_"));
-    assertEquals(CRLF, body.get(line++));
-    assertTrue(body.get(line++).contains("--batch_"));
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/51acf8ae/lib/server-core/src/test/java/org/apache/olingo/server/core/batchhandler/BatchChangeSetSorterTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/batchhandler/BatchChangeSetSorterTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/batchhandler/BatchChangeSetSorterTest.java
new file mode 100644
index 0000000..7b73e43
--- /dev/null
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/batchhandler/BatchChangeSetSorterTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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.server.core.batchhandler;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.olingo.commons.api.http.HttpMethod;
+import org.apache.olingo.server.api.ODataRequest;
+import org.apache.olingo.server.api.batch.BatchException;
+import org.apache.olingo.server.core.batchhandler.BatchChangeSetSorter;
+import org.apache.olingo.server.core.deserializer.batch.BatchParserCommon;
+import org.junit.Test;
+
+public class BatchChangeSetSorterTest {
+
+  private static final String BASE_URI = "http://localhost/odata.src";
+  
+  @Test
+  public void test() throws BatchException {
+    final List<ODataRequest> changeSet = new ArrayList<ODataRequest>();
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "$1/Adress", "2"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "/Employees", "1"));
+    
+   BatchChangeSetSorter sorter = new BatchChangeSetSorter(changeSet);
+   final List<ODataRequest> sortedChangeSet = sorter.getOrderdRequests();
+   
+   assertEquals(2, sortedChangeSet.size());
+   assertEquals("1", getContentId(sortedChangeSet.get(0)));
+   assertEquals("2", getContentId(sortedChangeSet.get(1)));
+  }
+  
+  private String getContentId(ODataRequest request) {
+    return request.getHeader(BatchParserCommon.HTTP_CONTENT_ID);
+  }
+  
+  @Test
+  public void testNoContentId() throws BatchException {
+    final List<ODataRequest> changeSet = new ArrayList<ODataRequest>();
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "$1/Department", "2"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "Employees", "1"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "Employee('2')/Address"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "Employee('3')/Address"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "$2/Manager", "3"));
+    
+    BatchChangeSetSorter sorter = new BatchChangeSetSorter(changeSet);
+   final List<ODataRequest> sortedChangeSet = sorter.getOrderdRequests();
+   
+   assertEquals(5, sortedChangeSet.size());
+   assertEquals("1", getContentId(sortedChangeSet.get(0)));
+   assertEquals(null, getContentId(sortedChangeSet.get(1)));
+   assertEquals(null, getContentId(sortedChangeSet.get(2)));
+   assertEquals("2", getContentId(sortedChangeSet.get(3)));
+   assertEquals("3", getContentId(sortedChangeSet.get(4)));
+  }
+  
+  @SuppressWarnings("unused")
+  @Test(expected=BatchException.class)
+  public void testContentIdNotAvailable() throws BatchException {
+    final List<ODataRequest> changeSet = new ArrayList<ODataRequest>();
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "$1/Department", "2"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "Employees", "1"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "Employee('2')/Address"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "Employee('3')/Address"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "$4/Manager", "3")); //4 is not available
+    
+   BatchChangeSetSorter sorter = new BatchChangeSetSorter(changeSet);
+   final List<ODataRequest> sortedChangeSet = sorter.getOrderdRequests();
+  }
+  
+  @Test
+  public void testStringAsContentId() throws BatchException {
+    final List<ODataRequest> changeSet = new ArrayList<ODataRequest>();
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "$One/Department", "Two"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "Employees", "One"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "Employee('2')/Address"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "Employee('3')/Address"));
+    changeSet.add(createRequest(HttpMethod.POST, BASE_URI, "$Two/Manager", "Three"));
+    
+   BatchChangeSetSorter sorter = new BatchChangeSetSorter(changeSet);
+   final List<ODataRequest> sortedChangeSet = sorter.getOrderdRequests();
+   
+   assertEquals(5, sortedChangeSet.size());
+   assertEquals("One", getContentId(sortedChangeSet.get(0)));
+   assertEquals(null, getContentId(sortedChangeSet.get(1)));
+   assertEquals(null, getContentId(sortedChangeSet.get(2)));
+   assertEquals("Two", getContentId(sortedChangeSet.get(3)));
+   assertEquals("Three", getContentId(sortedChangeSet.get(4)));
+  }
+  
+  @Test
+  public void testRewriting() {
+    final String CONTENT_ID = "1";
+    final String ODATA_PATH ="/$" + CONTENT_ID + "/Address";
+    final String RESOURCE_URI = "Employee('1')";
+    final ODataRequest request = createRequest(HttpMethod.POST, BASE_URI, ODATA_PATH);
+    
+    BatchChangeSetSorter.replaceContentIdReference(request, CONTENT_ID, RESOURCE_URI);
+    assertEquals(BASE_URI + "/" + "Employee('1')/Address", request.getRawRequestUri());
+    assertEquals("Employee('1')/Address", request.getRawODataPath());
+  }
+  
+  @Test
+  public void testRewritingNoContentId() {
+    final String CONTENT_ID = "1";
+    final String ODATA_PATH = /* "$" + CONTENT_ID + */ "Address";
+    final String RESOURCE_URI = "Employee('1')";
+    final ODataRequest request = createRequest(HttpMethod.POST, BASE_URI, ODATA_PATH);
+    
+    BatchChangeSetSorter.replaceContentIdReference(request, CONTENT_ID, RESOURCE_URI);
+    assertEquals(BASE_URI + "/" + "Address", request.getRawRequestUri());
+    assertEquals("Address", request.getRawODataPath());
+  }
+  
+  @Test
+  public void testWrongRewriting() {
+    final String CONTENT_ID = "1";
+    final String ODATA_PATH = /*"$1" */ "$2" + "/Address";
+    final String RESOURCE_URI = "Employee('1')";
+    final ODataRequest request = createRequest(HttpMethod.POST, BASE_URI, ODATA_PATH);
+    
+    BatchChangeSetSorter.replaceContentIdReference(request, CONTENT_ID, RESOURCE_URI);
+    assertEquals(BASE_URI + "/" + "$2/Address", request.getRawRequestUri());
+    assertEquals("$2/Address", request.getRawODataPath());
+  }
+  
+  private ODataRequest createRequest(HttpMethod method, String baseUrl, String oDataPath) {
+    return createRequest(method, baseUrl, oDataPath, null);
+  }
+  
+  private ODataRequest createRequest(HttpMethod method, String baseUrl, String oDataPath, String contentId) {
+    final ODataRequest request = new ODataRequest();
+    request.setBody(new ByteArrayInputStream(new byte[0]));
+    request.setMethod(HttpMethod.GET);
+    request.setRawBaseUri(baseUrl);
+    request.setRawODataPath(oDataPath);
+    request.setRawRequestUri(baseUrl + "/" + oDataPath);
+    request.setRawQueryPath("");
+    
+    if(contentId != null) {
+      request.addHeader(BatchParserCommon.HTTP_CONTENT_ID, Arrays.asList(new String[] { contentId }));
+    }
+    return request;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/51acf8ae/lib/server-core/src/test/java/org/apache/olingo/server/core/batchhandler/MockedBatchHandlerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/batchhandler/MockedBatchHandlerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/batchhandler/MockedBatchHandlerTest.java
new file mode 100644
index 0000000..c814184
--- /dev/null
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/batchhandler/MockedBatchHandlerTest.java
@@ -0,0 +1,671 @@
+/*
+ * 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.server.core.batchhandler;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.commons.api.ODataRuntimeException;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.commons.api.http.HttpMethod;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ODataRequest;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.batch.BatchException;
+import org.apache.olingo.server.api.batch.BatchFacade;
+import org.apache.olingo.server.api.deserializer.batch.BatchRequestPart;
+import org.apache.olingo.server.api.deserializer.batch.ODataResponsePart;
+import org.apache.olingo.server.api.processor.BatchProcessor;
+import org.apache.olingo.server.api.serializer.SerializerException;
+import org.apache.olingo.server.core.ODataHandler;
+import org.apache.olingo.server.core.batchhandler.BatchHandler;
+import org.apache.olingo.server.core.deserializer.batch.BatchParserCommon;
+import org.apache.olingo.server.core.deserializer.batch.BufferedReaderIncludingLineEndings;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class MockedBatchHandlerTest {
+
+  private static final String BATCH_CONTENT_TYPE = "multipart/mixed;boundary=batch_12345";
+  private static final String BATCH_ODATA_PATH = "/$batch";
+  private static final String BATCH_REQUEST_URI = "http://localhost:8080/odata/$batch";
+  private static final String BASE_URI = "http://localhost:8080/odata";
+  private static final String CRLF = "\r\n";
+  private ODataHandler oDataHandler;
+  private BatchHandler batchHandler;
+  private int entityCounter = 1;
+
+  @Before
+  public void setup() {
+    final BatchProcessor batchProcessor = new BatchTestProcessorImpl();
+    batchProcessor.init(OData.newInstance(), null);
+
+    entityCounter = 1;
+    oDataHandler = mock(ODataHandler.class);
+    batchHandler = new BatchHandler(oDataHandler, batchProcessor);
+  }
+
+  @Test
+  public void test() throws Exception {
+    final String content = "--batch_12345" + CRLF
+        + "Content-Type: multipart/mixed; boundary=changeset_12345" + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 4" + CRLF
+        + CRLF
+        + "PUT /$3/PropertyInt32 HTTP/1.1" + CRLF // Absolute URI with separate Host header and ref.
+        + "Host: http://localhost:8080/odata" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 5" + CRLF
+        + CRLF
+        + "POST http://localhost:8080/odata/$1/NavPropertyETTwoPrimMany HTTP/1.1" + CRLF // Absolute URI with ref.
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 2" + CRLF
+        + CRLF
+        + "POST $1/NavPropertyETTwoPrimMany HTTP/1.1" + CRLF // Relative URI with ref.
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 1" + CRLF
+        + CRLF
+        + "POST http://localhost:8080/odata/ESAllPrim HTTP/1.1" + CRLF // Absolute URI
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 3" + CRLF
+        + CRLF
+        + "PUT ESAllPrim(1) HTTP/1.1" + CRLF // Relative URI
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 6" + CRLF
+        + CRLF
+        + "PUT /ESAllPrim(1) HTTP/1.1" + CRLF // Absolute URI with separate Host header
+        + "Host: http://localhost:8080/odata"
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345--" + CRLF
+        + CRLF
+        + "--batch_12345--";
+    final Map<String, List<String>> header = getMimeHeader();
+    final ODataResponse response = new ODataResponse();
+    final ODataRequest request = buildODataRequest(content, header);
+
+    batchHandler.process(request, response, true);
+
+    BufferedReaderIncludingLineEndings reader =
+        new BufferedReaderIncludingLineEndings(new InputStreamReader(response.getContent()));
+
+    final List<String> responseContent = reader.toList();
+    reader.close();
+
+    int line = 0;
+    assertEquals(63, responseContent.size());
+
+    // Check change set
+    assertTrue(responseContent.get(line++).contains("--batch_"));
+    assertTrue(responseContent.get(line++).contains("Content-Type: multipart/mixed; boundary=changeset_"));
+
+    for (int i = 0; i < 6; i++) {
+      String contentId = checkChangeSetPartHeader(responseContent, line);
+      line += 6;
+
+      if ("1".equals(contentId)) {
+        assertEquals("HTTP/1.1 201 Created" + CRLF, responseContent.get(line++));
+        assertEquals("Location: " + BASE_URI + "/ESAllPrim(1)" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else if ("2".equals(contentId)) {
+        assertEquals("HTTP/1.1 201 Created" + CRLF, responseContent.get(line++));
+        assertEquals("Location: " + BASE_URI + "/ESTwoPrim(3)" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else if ("3".equals(contentId)) {
+        assertEquals("HTTP/1.1 200 OK" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else if ("4".equals(contentId)) {
+        assertEquals("HTTP/1.1 200 OK" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else if ("5".equals(contentId)) {
+        assertEquals("HTTP/1.1 201 Created" + CRLF, responseContent.get(line++));
+        assertEquals("Location: " + BASE_URI + "/ESTwoPrim(2)" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else if ("6".equals(contentId)) {
+        assertEquals("HTTP/1.1 200 OK" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else {
+        fail();
+      }
+
+      assertEquals(CRLF, responseContent.get(line++));
+    }
+
+    // Close body part (change set)
+    assertEquals(CRLF, responseContent.get(line++));
+    assertTrue(responseContent.get(line++).contains("--changeset_"));
+
+    // Close batch
+    assertEquals(CRLF, responseContent.get(line++));
+    assertTrue(responseContent.get(line++).contains("--batch_"));
+    assertEquals(63, line);
+  }
+
+  @Test
+  public void testGetRequest() throws Exception {
+    final String content = ""
+        + "--batch_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + CRLF
+        + "GET ESAllPrim(0) HTTP/1.1" + CRLF
+        + CRLF
+        + CRLF
+        + "--batch_12345--";
+
+    final Map<String, List<String>> header = getMimeHeader();
+    final ODataResponse response = new ODataResponse();
+    final ODataRequest request = buildODataRequest(content, header);
+
+    batchHandler.process(request, response, true);
+
+    BufferedReaderIncludingLineEndings reader =
+        new BufferedReaderIncludingLineEndings(new InputStreamReader(response.getContent()));
+
+    final List<String> responseContent = reader.toList();
+    int line = 0;
+
+    assertEquals(9, responseContent.size());
+    assertTrue(responseContent.get(line++).contains("--batch_"));
+    assertEquals("Content-Type: application/http" + CRLF, responseContent.get(line++));
+    assertEquals("Content-Transfer-Encoding: binary" + CRLF, responseContent.get(line++));
+    assertEquals(CRLF, responseContent.get(line++));
+    assertEquals("HTTP/1.1 200 OK" + CRLF, responseContent.get(line++));
+    assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+    assertEquals(CRLF, responseContent.get(line++));
+    assertEquals(CRLF, responseContent.get(line++));
+    assertTrue(responseContent.get(line++).contains("--batch_"));
+
+    assertEquals(9, line);
+
+    reader.close();
+  }
+
+  @Test
+  public void testMultipleChangeSets() throws Exception {
+    final String content = ""
+        + "--batch_12345" + CRLF
+        + "Content-Type: multipart/mixed; boundary=changeset_12345" + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 2" + CRLF
+        + CRLF
+        + "POST /$1/NavPropertyETTwoPrimMany HTTP/1.1" + CRLF
+        + "Host: http://localhost:8080/odata" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 1" + CRLF
+        + CRLF
+        + "PUT ESAllPrim(1) HTTP/1.1" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345--" + CRLF
+
+        + "--batch_12345" + CRLF
+        + "Content-Type: multipart/mixed; boundary=changeset_54321" + CRLF
+        + CRLF
+        + "--changeset_54321" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 2" + CRLF
+        + CRLF
+        + "POST /$1/NavPropertyETTwoPrimMany HTTP/1.1" + CRLF
+        + "Host: http://localhost:8080/odata" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_54321" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 1" + CRLF
+        + CRLF
+        + "PUT ESAllPrim(2) HTTP/1.1" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_54321--" + CRLF
+
+        + CRLF
+        + "--batch_12345--";
+    final Map<String, List<String>> header = getMimeHeader();
+    final ODataResponse response = new ODataResponse();
+    final ODataRequest request = buildODataRequest(content, header);
+
+    batchHandler.process(request, response, true);
+
+    BufferedReaderIncludingLineEndings reader =
+        new BufferedReaderIncludingLineEndings(new InputStreamReader(response.getContent()));
+
+    final List<String> responseContent = reader.toList();
+    reader.close();
+
+    int line = 0;
+    assertEquals(49, responseContent.size());
+
+    // Check first change set
+    assertTrue(responseContent.get(line++).contains("--batch_"));
+    assertTrue(responseContent.get(line++).contains("Content-Type: multipart/mixed; boundary=changeset_"));
+
+    for (int i = 0; i < 2; i++) {
+      String contentId = checkChangeSetPartHeader(responseContent, line);
+      line += 6;
+
+      if ("1".equals(contentId)) {
+        assertEquals("HTTP/1.1 200 OK" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else if ("2".equals(contentId)) {
+        assertEquals("HTTP/1.1 201 Created" + CRLF, responseContent.get(line++));
+        assertEquals("Location: " + BASE_URI + "/ESTwoPrim(1)" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else {
+        fail();
+      }
+
+      assertEquals(CRLF, responseContent.get(line++));
+    }
+    // Close body part (1st change set)
+    assertEquals(CRLF, responseContent.get(line++));
+    assertTrue(responseContent.get(line++).contains("--changeset_"));
+
+    // Check second change set
+    assertEquals(CRLF, responseContent.get(line++));
+    assertTrue(responseContent.get(line++).contains("--batch_"));
+    assertTrue(responseContent.get(line++).contains("Content-Type: multipart/mixed; boundary=changeset_"));
+
+    for (int i = 0; i < 2; i++) {
+      String contentId = checkChangeSetPartHeader(responseContent, line);
+      line += 6;
+
+      if ("1".equals(contentId)) {
+        assertEquals("HTTP/1.1 200 OK" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else if ("2".equals(contentId)) {
+        assertEquals("HTTP/1.1 201 Created" + CRLF, responseContent.get(line++));
+        assertEquals("Location: " + BASE_URI + "/ESTwoPrim(2)" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else {
+        fail();
+      }
+
+      assertEquals(CRLF, responseContent.get(line++));
+    }
+    // Close body part (2nd change set)
+    assertEquals(CRLF, responseContent.get(line++));
+    assertTrue(responseContent.get(line++).contains("--changeset_"));
+
+    // Close batch
+    assertEquals(CRLF, responseContent.get(line++));
+    assertTrue(responseContent.get(line++).contains("--batch_"));
+
+    assertEquals(49, line);
+  }
+
+  @Test
+  public void testMineBodyPartTransitiv() throws Exception {
+    final String content = ""
+        + "--batch_12345" + CRLF
+        + "Content-Type: multipart/mixed; boundary=changeset_12345" + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 4" + CRLF
+        + CRLF
+        + "POST $3/NavPropertyETTwoPrimOne HTTP/1.1" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 2" + CRLF
+        + CRLF
+        + "POST /$1/NavPropertyETTwoPrimMany HTTP/1.1" + CRLF
+        + "Host: http://localhost:8080/odata" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 1" + CRLF
+        + CRLF
+        + "PUT ESAllPrim(1) HTTP/1.1" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 3" + CRLF
+        + CRLF
+        + "POST $2/NavPropertyETAllPrimMany HTTP/1.1" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345--" + CRLF
+
+        + CRLF
+        + "--batch_12345--";
+
+    final Map<String, List<String>> header = getMimeHeader();
+    final ODataResponse response = new ODataResponse();
+    final ODataRequest request = buildODataRequest(content, header);
+
+    batchHandler.process(request, response, true);
+
+    BufferedReaderIncludingLineEndings reader =
+        new BufferedReaderIncludingLineEndings(new InputStreamReader(response.getContent()));
+
+    final List<String> responseContent = reader.toList();
+    reader.close();
+
+    int line = 0;
+    assertEquals(45, responseContent.size());
+
+    // Check change set
+    assertTrue(responseContent.get(line++).contains("--batch_"));
+    assertTrue(responseContent.get(line++).contains("Content-Type: multipart/mixed; boundary=changeset_"));
+
+    for (int i = 0; i < 4; i++) {
+      String contentId = checkChangeSetPartHeader(responseContent, line);
+      line += 6;
+
+      if ("1".equals(contentId)) {
+        assertEquals("HTTP/1.1 200 OK" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else if ("2".equals(contentId)) {
+        assertEquals("HTTP/1.1 201 Created" + CRLF, responseContent.get(line++));
+        assertEquals("Location: " + BASE_URI + "/ESTwoPrim(1)" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else if ("3".equals(contentId)) {
+        assertEquals("HTTP/1.1 201 Created" + CRLF, responseContent.get(line++));
+        assertEquals("Location: " + BASE_URI + "/ESAllPrim(2)" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else if ("4".equals(contentId)) {
+        assertEquals("HTTP/1.1 201 Created" + CRLF, responseContent.get(line++));
+        assertEquals("Location: " + BASE_URI + "/ESTwoPrim(3)" + CRLF, responseContent.get(line++));
+        assertEquals("Content-Length: 0" + CRLF, responseContent.get(line++));
+      } else {
+        fail();
+      }
+
+      assertEquals(CRLF, responseContent.get(line++));
+    }
+
+    // Close body part (change set)
+    assertEquals(CRLF, responseContent.get(line++));
+    assertTrue(responseContent.get(line++).contains("--changeset_"));
+
+    // Close batch
+    assertEquals(CRLF, responseContent.get(line++));
+    assertTrue(responseContent.get(line++).contains("--batch_"));
+    assertEquals(45, line);
+  }
+
+  private String checkChangeSetPartHeader(final List<String> response, int line) {
+    assertEquals(CRLF, response.get(line++));
+    assertTrue(response.get(line++).contains("--changeset_"));
+    assertEquals("Content-Type: application/http" + CRLF, response.get(line++));
+    assertEquals("Content-Transfer-Encoding: binary" + CRLF, response.get(line++));
+
+    assertTrue(response.get(line).contains("Content-Id:"));
+    String contentId = response.get(line).split(":")[1].trim();
+    line++;
+
+    assertEquals(CRLF, response.get(line++));
+
+    return contentId;
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidMethod() throws Exception {
+    final String content = ""
+        + "--batch_12345" + CRLF
+        + "Content-Type: multipart/mixed; boundary=changeset_12345" + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 1" + CRLF
+        + CRLF
+        + "PUT ESAllPrim(1) HTTP/1.1" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345--" + CRLF
+        + CRLF
+        + "--batch_12345--";
+
+    final Map<String, List<String>> header = getMimeHeader();
+    final ODataResponse response = new ODataResponse();
+    final ODataRequest request = buildODataRequest(content, header);
+    request.setMethod(HttpMethod.GET);
+
+    batchHandler.process(request, response, true);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidContentType() throws Exception {
+    final String content = ""
+        + "--batch_12345" + CRLF
+        + "Content-Type: multipart/mixed; boundary=changeset_12345" + CRLF
+        + CRLF
+        + "--changeset_12345" + CRLF
+        + "Content-Type: application/http" + CRLF
+        + "Content-Transfer-Encoding: binary" + CRLF
+        + "Content-Id: 1" + CRLF
+        + CRLF
+        + "PUT ESAllPrim(1) HTTP/1.1" + CRLF
+        + "Content-Type: application/json;odata=verbose" + CRLF
+        + CRLF
+        + CRLF
+        + "--changeset_12345--" + CRLF
+        + CRLF
+        + "--batch_12345--";
+
+    final Map<String, List<String>> header = new HashMap<String, List<String>>();
+    header.put(HttpHeader.CONTENT_TYPE, Arrays.asList(new String[] { "application/http" }));
+    final ODataResponse response = new ODataResponse();
+    final ODataRequest request = buildODataRequest(content, header);
+
+    batchHandler.process(request, response, true);
+  }
+
+  /*
+   * Helper methods
+   */
+  private Map<String, List<String>> getMimeHeader() {
+    final Map<String, List<String>> header = new HashMap<String, List<String>>();
+    header.put(HttpHeader.CONTENT_TYPE, Arrays.asList(new String[] { BATCH_CONTENT_TYPE }));
+
+    return header;
+  }
+
+  private ODataRequest buildODataRequest(final String content, final Map<String, List<String>> header)
+      throws UnsupportedEncodingException {
+    final ODataRequest request = new ODataRequest();
+
+    for (final String key : header.keySet()) {
+      request.addHeader(key, header.get(key));
+    }
+
+    request.setMethod(HttpMethod.POST);
+    request.setRawBaseUri(BASE_URI);
+    request.setRawODataPath(BATCH_ODATA_PATH);
+    request.setRawQueryPath("");
+    request.setRawRequestUri(BATCH_REQUEST_URI);
+    request.setRawServiceResolutionUri("");
+
+    request.setBody(new ByteArrayInputStream(content.getBytes("UTF-8")));
+
+    return request;
+  }
+
+  /**
+   * Batch processor
+   */
+  private class BatchTestProcessorImpl implements BatchProcessor {
+
+    private OData odata;
+
+    @Override
+    public void init(OData odata, ServiceMetadata serviceMetadata) {
+      this.odata = odata;
+    }
+
+    @Override
+    public ODataResponsePart executeChangeSet(BatchFacade operation, List<ODataRequest> requests,
+        BatchRequestPart requestPart) {
+      List<ODataResponse> responses = new ArrayList<ODataResponse>();
+
+      for (ODataRequest request : requests) {
+        try {
+          responses.add(operation.handleODataRequest(request, requestPart));
+        } catch (BatchException e) {
+          fail();
+        }
+      }
+
+      return new ODataResponsePart(responses, true);
+    }
+
+    @Override
+    public void executeBatch(BatchFacade operation, ODataRequest request, ODataResponse response)
+        throws SerializerException, BatchException {
+      try {
+        final List<BatchRequestPart> parts = odata.createFixedFormatDeserializer().parseBatchRequest(request, true);
+        final List<ODataResponsePart> responseParts = new ArrayList<ODataResponsePart>();
+
+        for (BatchRequestPart part : parts) {
+          for (final ODataRequest oDataRequest : part.getRequests()) {
+            // Mock the processor for a given requests
+            when(oDataHandler.process(oDataRequest)).then(new Answer<ODataResponse>() {
+              @Override
+              public ODataResponse answer(InvocationOnMock invocation) throws Throwable {
+                Object[] arguments = invocation.getArguments();
+
+                return buildResponse((ODataRequest) arguments[0]);
+              }
+            });
+          }
+
+          responseParts.add(operation.handleBatchRequest(part));
+        }
+
+        odata.createFixedFormatSerializer().writeResponseParts(responseParts, response);
+      } catch (IOException e) {
+        throw new ODataRuntimeException(e);
+      }
+    }
+  }
+
+  private ODataResponse buildResponse(ODataRequest request) {
+    final ODataResponse oDataResponse = new ODataResponse();
+
+    if (request.getMethod() == HttpMethod.POST) {
+      oDataResponse.setStatusCode(HttpStatusCode.CREATED.getStatusCode());
+      oDataResponse.setHeader(HttpHeader.LOCATION, createResourceUri(request));
+    } else {
+      oDataResponse.setStatusCode(HttpStatusCode.OK.getStatusCode());
+    }
+
+    final String contentId = request.getHeader(BatchParserCommon.HTTP_CONTENT_ID);
+    if (contentId != null) {
+      oDataResponse.setHeader(BatchParserCommon.HTTP_CONTENT_ID, contentId);
+    }
+
+    return oDataResponse;
+  }
+
+  private String createResourceUri(final ODataRequest request) {
+    final String parts[] = request.getRawODataPath().split("/");
+    String oDataPath = "";
+
+    if (parts.length == 2) {
+      // Entity Collection
+      oDataPath = parts[1];
+    } else {
+      // Navigation property
+
+      final String navProperty = parts[parts.length - 1];
+      if (navProperty.equals("NavPropertyETTwoPrimMany")) {
+        oDataPath = "ESTwoPrim";
+      } else if (navProperty.equals("NavPropertyETAllPrimMany")) {
+        oDataPath = "ESAllPrim";
+      } else if (navProperty.equals("NavPropertyETTwoPrimOne")) {
+        oDataPath = "ESTwoPrim";
+      }
+    }
+
+    return BASE_URI + "/" + oDataPath + "(" + entityCounter++ + ")";
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/51acf8ae/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BatchParserCommonTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BatchParserCommonTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BatchParserCommonTest.java
new file mode 100644
index 0000000..2191555
--- /dev/null
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/deserializer/BatchParserCommonTest.java
@@ -0,0 +1,230 @@
+/*
+ * 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.server.core.deserializer;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.server.api.batch.BatchException;
+import org.apache.olingo.server.core.deserializer.batch.BatchParserCommon;
+import org.apache.olingo.server.core.deserializer.batch.Header;
+import org.apache.olingo.server.core.deserializer.batch.BufferedReaderIncludingLineEndings.Line;
+import org.junit.Test;
+
+public class BatchParserCommonTest {
+
+  private static final String CRLF = "\r\n";
+
+  @Test
+  public void testMultipleHeader() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Content-Id: 1" + CRLF,
+        "Content-Id: 2" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<Line> message = toLineList(messageRaw);
+    
+    final Header header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final List<String> contentIdHeaders = header.getHeaders(BatchParserCommon.HTTP_CONTENT_ID);
+    assertNotNull(contentIdHeaders);
+    assertEquals(2, contentIdHeaders.size());
+    assertEquals("1", contentIdHeaders.get(0));
+    assertEquals("2", contentIdHeaders.get(1));
+  }
+  
+  @Test
+  public void testMultipleHeaderSameValue() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Content-Id: 1" + CRLF,
+        "Content-Id: 1" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<Line> message = toLineList(messageRaw);
+    
+    final Header header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final List<String> contentIdHeaders = header.getHeaders(BatchParserCommon.HTTP_CONTENT_ID);
+    assertNotNull(contentIdHeaders);
+    assertEquals(1, contentIdHeaders.size());
+    assertEquals("1", contentIdHeaders.get(0));
+  }
+  
+  @Test
+  public void testHeaderSperatedByComma() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Content-Id: 1" + CRLF,
+        "Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<Line> message = toLineList(messageRaw);
+    
+    final Header header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final List<String> upgradeHeader = header.getHeaders("upgrade");
+    assertNotNull(upgradeHeader);
+    assertEquals(4, upgradeHeader.size());
+    assertEquals("HTTP/2.0", upgradeHeader.get(0));
+    assertEquals("SHTTP/1.3", upgradeHeader.get(1));
+    assertEquals("IRC/6.9", upgradeHeader.get(2));
+    assertEquals("RTA/x11", upgradeHeader.get(3));
+  }
+  
+  @Test
+  public void testMultipleAcceptHeader() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + CRLF,
+        "Accept: text/plain;q=0.3" + CRLF,
+        "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<Line> message = toLineList(messageRaw);
+    
+    final Header header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final List<String> acceptHeader = header.getHeaders(HttpHeader.ACCEPT);
+    assertNotNull(acceptHeader);
+    assertEquals(4, acceptHeader.size());
+  }
+  
+  @Test
+  public void testMultipleAcceptHeaderSameValue() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + CRLF,
+        "Accept: application/atomsvc+xml;q=0.8" + CRLF,
+        "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<Line> message = toLineList(messageRaw);
+    
+    final Header header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final List<String> acceptHeader = header.getHeaders(HttpHeader.ACCEPT);
+    assertNotNull(acceptHeader);
+    assertEquals(3, acceptHeader.size());
+  }
+  
+  @Test
+  public void testMultipleAccepLanguagetHeader() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
+        "Accept-Language: de-DE;q=0.3" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<Line> message = toLineList(messageRaw);
+    
+    final Header header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final List<String> acceptLanguageHeader = header.getHeaders(HttpHeader.ACCEPT_LANGUAGE);
+    assertNotNull(acceptLanguageHeader);
+    assertEquals(4, acceptLanguageHeader.size());
+  }
+  
+  @Test
+  public void testMultipleAccepLanguagetHeaderSameValue() throws BatchException {
+    String[] messageRaw = new String[] {
+        "Accept-Language:en-US,en;q=0.7,en-UK;q=0.9" + CRLF,
+        "Accept-Language:en-US,en;q=0.7" + CRLF,
+        "content-type: Application/http" + CRLF,
+        "content-transfer-encoding: Binary" + CRLF
+      };
+    List<Line> message = toLineList(messageRaw);
+    
+    final Header header = BatchParserCommon.consumeHeaders(message);
+    assertNotNull(header);
+    
+    final List<String> acceptLanguageHeader = header.getHeaders(HttpHeader.ACCEPT_LANGUAGE);
+    assertNotNull(acceptLanguageHeader);
+    assertEquals(3, acceptLanguageHeader.size());
+  }
+  
+  @Test
+  public void testRemoveEndingCRLF() {
+    String line = "Test\r\n";
+    assertEquals("Test", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
+  }
+
+  @Test
+  public void testRemoveLastEndingCRLF() {
+    String line = "Test\r\n\r\n";
+    assertEquals("Test\r\n", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
+  }
+
+  @Test
+  public void testRemoveEndingCRLFWithWS() {
+    String line = "Test\r\n            ";
+    assertEquals("Test", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
+  }
+
+  @Test
+  public void testRemoveEndingCRLFNothingToRemove() {
+    String line = "Hallo\r\nBla";
+    assertEquals("Hallo\r\nBla", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
+  }
+
+  @Test
+  public void testRemoveEndingCRLFAll() {
+    String line = "\r\n";
+    assertEquals("", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
+  }
+
+  @Test
+  public void testRemoveEndingCRLFSpace() {
+    String line = "\r\n                      ";
+    assertEquals("", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
+  }
+
+  @Test
+  public void testRemoveLastEndingCRLFWithWS() {
+    String line = "Test            \r\n";
+    assertEquals("Test            ", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
+  }
+
+  @Test
+  public void testRemoveLastEndingCRLFWithWSLong() {
+    String line = "Test            \r\nTest2    \r\n";
+    assertEquals("Test            \r\nTest2    ", BatchParserCommon.removeEndingCRLF(new Line(line,1)).toString());
+  }
+  
+  private List<Line> toLineList(String[] messageRaw) {
+    final List<Line> lineList = new ArrayList<Line>();
+    int counter = 1;
+    
+    for(final String currentLine : messageRaw) {
+      lineList.add(new Line(currentLine, counter++));
+    }
+    
+    return lineList;
+  }
+}