You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2015/09/01 14:45:30 UTC

[28/31] olingo-odata4 git commit: [OLINGO-659] Removed v4 from package and class names

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/78a9539e/fit/src/test/java/org/apache/olingo/fit/base/AuthBatchTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/base/AuthBatchTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/base/AuthBatchTestITCase.java
new file mode 100644
index 0000000..9103818
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/base/AuthBatchTestITCase.java
@@ -0,0 +1,119 @@
+/*
+ * 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.fit.base;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.URI;
+
+import org.apache.olingo.client.api.ODataClient;
+import org.apache.olingo.client.api.communication.request.batch.BatchManager;
+import org.apache.olingo.client.api.communication.request.batch.ODataBatchRequest;
+import org.apache.olingo.client.api.communication.request.batch.ODataChangeset;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.request.cud.UpdateType;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.communication.response.ODataBatchResponse;
+import org.apache.olingo.client.api.domain.ClientEntity;
+import org.apache.olingo.client.api.http.HttpClientException;
+import org.apache.olingo.client.api.uri.URIBuilder;
+import org.apache.olingo.client.core.ODataClientFactory;
+import org.apache.olingo.client.core.http.BasicAuthHttpClientFactory;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.junit.Test;
+
+public class AuthBatchTestITCase extends AbstractTestITCase {
+
+  private final static ContentType ACCEPT = ContentType.APPLICATION_OCTET_STREAM;
+
+  @Test
+  public void clean() throws EdmPrimitiveTypeException {
+    final ODataClient authclient = ODataClientFactory.getClient();
+    batchRequest(authclient, testStaticServiceRootURL);
+  }
+
+  @Test
+  public void authorized() throws EdmPrimitiveTypeException {
+    final ODataClient authclient = ODataClientFactory.getClient();
+    authclient.getConfiguration().setHttpClientFactory(new BasicAuthHttpClientFactory("odatajclient", "odatajclient"));
+    batchRequest(authclient, testAuthServiceRootURL);
+  }
+
+  @Test(expected = HttpClientException.class)
+  public void unauthorized() throws EdmPrimitiveTypeException {
+    final ODataClient unauthclient = ODataClientFactory.getClient();
+    unauthclient.getConfiguration().setHttpClientFactory(new BasicAuthHttpClientFactory("not_auth", "not_auth"));
+    batchRequest(unauthclient, testAuthServiceRootURL);
+  }
+
+  private void batchRequest(final ODataClient client, final String baseURL) throws EdmPrimitiveTypeException {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(baseURL);
+    request.setAccept(ACCEPT.toContentTypeString());
+    request.addCustomHeader("User-Agent", "Apache Olingo OData Client");
+    request.addCustomHeader(HttpHeader.ACCEPT_CHARSET, "UTF-8");
+
+    final BatchManager streamManager = request.payloadManager();
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    // prepare URI
+    URIBuilder targetURI = client.newURIBuilder(baseURL);
+    targetURI.appendEntitySetSegment("Customers").appendKeySegment(1);
+
+    // create new request
+    ODataEntityRequest<ClientEntity> queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+    queryReq.setFormat(ContentType.JSON);
+
+    streamManager.addRequest(queryReq);
+    // -------------------------------------------
+
+    // -------------------------------------------
+    // Add changeset item
+    // -------------------------------------------
+    final ODataChangeset changeset = streamManager.addChangeset();
+
+    // Update Customer into the changeset
+    targetURI = client.newURIBuilder(baseURL).appendEntitySetSegment("Customers").appendKeySegment(1);
+    final URI editLink = targetURI.build();
+
+    final ClientEntity patch = client.getObjectFactory().newEntity(
+        new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Customer"));
+    patch.setEditLink(editLink);
+
+    patch.getProperties().add(client.getObjectFactory().newPrimitiveProperty(
+        "LastName",
+        client.getObjectFactory().newPrimitiveValueBuilder().buildString("new last name")));
+
+    final ODataEntityUpdateRequest<ClientEntity> changeReq =
+        client.getCUDRequestFactory().getEntityUpdateRequest(UpdateType.PATCH, patch);
+    changeReq.setFormat(ContentType.JSON_FULL_METADATA);
+
+    changeset.addRequest(changeReq);
+    // -------------------------------------------
+
+    final ODataBatchResponse response = streamManager.getResponse();
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/78a9539e/fit/src/test/java/org/apache/olingo/fit/base/BatchTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/base/BatchTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/base/BatchTestITCase.java
new file mode 100644
index 0000000..2e77a08
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/base/BatchTestITCase.java
@@ -0,0 +1,647 @@
+/*
+ * 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.fit.base;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.http.HttpResponse;
+import org.apache.olingo.client.api.ODataBatchConstants;
+import org.apache.olingo.client.api.communication.request.AsyncBatchRequestWrapper;
+import org.apache.olingo.client.api.communication.request.ODataPayloadManager;
+import org.apache.olingo.client.api.communication.request.batch.BatchManager;
+import org.apache.olingo.client.api.communication.request.batch.ODataBatchRequest;
+import org.apache.olingo.client.api.communication.request.batch.ODataBatchResponseItem;
+import org.apache.olingo.client.api.communication.request.batch.ODataChangeset;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.request.cud.UpdateType;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
+import org.apache.olingo.client.api.communication.response.AsyncResponse;
+import org.apache.olingo.client.api.communication.response.AsyncResponseWrapper;
+import org.apache.olingo.client.api.communication.response.ODataBatchResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
+import org.apache.olingo.client.api.communication.response.ODataResponse;
+import org.apache.olingo.client.api.domain.ClientEntity;
+import org.apache.olingo.client.api.domain.ClientEntitySet;
+import org.apache.olingo.client.api.uri.URIBuilder;
+import org.apache.olingo.client.core.communication.request.AbstractODataStreamManager;
+import org.apache.olingo.client.core.communication.request.Wrapper;
+import org.apache.olingo.client.core.communication.request.batch.ODataChangesetResponseItem;
+import org.apache.olingo.client.core.communication.request.batch.ODataSingleResponseItem;
+import org.apache.olingo.client.core.communication.request.retrieve.ODataEntityRequestImpl;
+import org.apache.olingo.client.core.communication.request.retrieve.ODataEntityRequestImpl.ODataEntityResponseImpl;
+import org.apache.olingo.client.core.uri.URIUtils;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.junit.Test;
+
+public class BatchTestITCase extends AbstractTestITCase {
+
+  private static final String PREFIX = "!!PREFIX!!";
+
+  private static final String SUFFIX = "!!SUFFIX!!";
+
+  private static final int MAX = 10000;
+
+  private final static String ACCEPT = ContentType.APPLICATION_OCTET_STREAM.toContentTypeString();
+
+  @Test
+  public void stringStreaming() {
+    final TestStreamManager streaming = new TestStreamManager();
+
+    new StreamingThread(streaming).start();
+
+    streaming.addObject((PREFIX + "\n").getBytes());
+
+    for (int i = 0; i <= MAX; i++) {
+      streaming.addObject((i + ") send info\n").getBytes());
+    }
+
+    streaming.addObject(SUFFIX.getBytes());
+    streaming.finalizeBody();
+  }
+
+  @Test
+  public void emptyBatchRequest() {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+    request.setAccept(ACCEPT);
+
+    final BatchManager payload = request.payloadManager();
+    final ODataBatchResponse response = payload.getResponse();
+
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+    assertFalse(iter.hasNext());
+  }
+
+  @Test
+  public void changesetWithError() {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+    request.setAccept(ACCEPT);
+
+    final BatchManager payload = request.payloadManager();
+    final ODataChangeset changeset = payload.addChangeset();
+
+    URIBuilder targetURI;
+    ODataEntityCreateRequest<ClientEntity> createReq;
+
+    targetURI = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Orders");
+    for (int i = 1; i <= 2; i++) {
+      // Create Customer into the changeset
+      createReq = client.getCUDRequestFactory().getEntityCreateRequest(targetURI.build(), newOrder(100 + i));
+      createReq.setFormat(ContentType.JSON);
+      changeset.addRequest(createReq);
+    }
+
+    targetURI = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("WrongEntitySet");
+    createReq = client.getCUDRequestFactory().getEntityCreateRequest(targetURI.build(), newOrder(105));
+    createReq.setFormat(ContentType.JSON);
+    changeset.addRequest(createReq);
+
+    targetURI = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Orders");
+    for (int i = 3; i <= 4; i++) {
+      // Create Customer into the changeset
+      createReq = client.getCUDRequestFactory().getEntityCreateRequest(targetURI.build(), newOrder(100 + i));
+      createReq.setFormat(ContentType.JSON);
+      changeset.addRequest(createReq);
+    }
+
+    final ODataBatchResponse response = payload.getResponse();
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+    // retrieve the first item (ODataRetrieve)
+    ODataBatchResponseItem item = iter.next();
+
+    ODataChangesetResponseItem retitem = (ODataChangesetResponseItem) item;
+    ODataResponse res = retitem.next();
+    assertEquals(404, res.getStatusCode());
+    assertEquals("Not Found", res.getStatusMessage());
+    assertEquals(Integer.valueOf(3), Integer.valueOf(
+        res.getHeader(ODataBatchConstants.CHANGESET_CONTENT_ID_NAME).iterator().next()));
+
+    assertFalse(retitem.hasNext());
+    assertFalse(iter.hasNext());
+  }
+
+  @Test
+  public void continueOnError() {
+    continueOnError(true);
+  }
+
+  @Test
+  public void doNotContinueOnError() {
+    continueOnError(false);
+  }
+
+  private void continueOnError(final boolean continueOnError) {
+    final boolean preContinueOnError = client.getConfiguration().isContinueOnError();
+    client.getConfiguration().setContinueOnError(continueOnError);
+
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+    request.setAccept(ACCEPT);
+
+    final BatchManager streamManager = request.payloadManager();
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    // prepare URI
+    URIBuilder targetURI = client.newURIBuilder(testStaticServiceRootURL);
+    targetURI.appendEntitySetSegment("UnexistingEntitySet").appendKeySegment(1);
+
+    // create new request
+    ODataEntityRequest<ClientEntity> queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+    queryReq.setFormat(ContentType.JSON);
+
+    streamManager.addRequest(queryReq);
+    // -------------------------------------------
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    // prepare URI
+    targetURI = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").appendKeySegment(1);
+
+    // create new request
+    queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+
+    streamManager.addRequest(queryReq);
+    // -------------------------------------------
+
+    final ODataBatchResponse response = streamManager.getResponse();
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+
+    // retrieve the first item (ODataRetrieve)
+    ODataBatchResponseItem item = iter.next();
+    assertTrue(item instanceof ODataSingleResponseItem);
+
+    ODataSingleResponseItem retitem = (ODataSingleResponseItem) item;
+    ODataResponse res = retitem.next();
+    assertEquals(404, res.getStatusCode());
+    assertEquals("Not Found", res.getStatusMessage());
+
+    if (continueOnError) {
+      item = iter.next();
+      assertTrue(item instanceof ODataSingleResponseItem);
+
+      retitem = (ODataSingleResponseItem) item;
+      res = retitem.next();
+      assertTrue(res instanceof ODataEntityResponseImpl);
+      assertEquals(200, res.getStatusCode());
+      assertEquals("OK", res.getStatusMessage());
+    }
+
+    client.getConfiguration().setContinueOnError(preContinueOnError);
+  }
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void changesetWithReference() throws Exception {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+    request.setAccept(ACCEPT);
+    final BatchManager streamManager = request.payloadManager();
+
+    final ODataChangeset changeset = streamManager.addChangeset();
+    ClientEntity order = newOrder(20);
+
+    final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Orders");
+
+    // add create request
+    final ODataEntityCreateRequest<ClientEntity> createReq =
+        client.getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), order);
+
+    changeset.addRequest(createReq);
+
+    // retrieve request reference
+    int createRequestRef = changeset.getLastContentId();
+
+    // add update request: link CustomerInfo(17) to the new customer
+    final ClientEntity customerChanges = client.getObjectFactory().newEntity(order.getTypeName());
+    customerChanges.addLink(client.getObjectFactory().newEntitySetNavigationLink(
+        "OrderDetails", new URI(testStaticServiceRootURL + "/OrderDetails(OrderID=7,ProductID=5)")));
+    
+    final ODataEntityUpdateRequest<ClientEntity> updateReq = client.getCUDRequestFactory().getEntityUpdateRequest(
+        URI.create("$" + createRequestRef), UpdateType.PATCH, customerChanges);
+
+    changeset.addRequest(updateReq);
+
+    final ODataBatchResponse response = streamManager.getResponse();
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+
+    // verify response payload ...
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+
+    final ODataBatchResponseItem item = iter.next();
+    assertTrue(item instanceof ODataChangesetResponseItem);
+
+    final ODataChangesetResponseItem chgitem = (ODataChangesetResponseItem) item;
+
+    ODataResponse res = chgitem.next();
+    assertEquals(201, res.getStatusCode());
+    assertTrue(res instanceof ODataEntityCreateResponse);
+
+    order = ((ODataEntityCreateResponse<ClientEntity>) res).getBody();
+    final ODataEntitySetRequest<ClientEntitySet> req = client.getRetrieveRequestFactory().getEntitySetRequest(
+        URIUtils.getURI(testStaticServiceRootURL, order.getEditLink().toASCIIString() + "/OrderDetails"));
+
+    assertEquals(Integer.valueOf(7),
+        req.execute().getBody().getEntities().get(0).getProperty("OrderID").getPrimitiveValue().
+        toCastValue(Integer.class));
+
+    res = chgitem.next();
+    assertEquals(204, res.getStatusCode());
+    assertTrue(res instanceof ODataEntityUpdateResponse);
+
+    // clean ...
+    assertEquals(204, client.getCUDRequestFactory().getDeleteRequest(
+        URIUtils.getURI(testStaticServiceRootURL, order.getEditLink().toASCIIString())).execute().
+        getStatusCode());
+
+    try {
+      client.getRetrieveRequestFactory().getEntityRequest(
+          URIUtils.getURI(testStaticServiceRootURL, order.getEditLink().toASCIIString())).
+          execute().getBody();
+      fail();
+    } catch (Exception e) {
+      // ignore
+    }
+  }
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void batchRequestWithOutsideUpdates() throws EdmPrimitiveTypeException {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+    request.setAccept(ACCEPT);
+    final BatchManager streamManager = request.payloadManager();
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    // prepare URI
+    URIBuilder targetURI = client.newURIBuilder(testStaticServiceRootURL);
+    targetURI.appendEntitySetSegment("Customers").appendKeySegment(1).
+    expand("Orders").select("PersonID,Orders/OrderID");
+
+    // create new request
+    ODataEntityRequest<ClientEntity> queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+    queryReq.setFormat(ContentType.JSON);
+
+    streamManager.addRequest(queryReq);
+    // -------------------------------------------
+
+    // -------------------------------------------
+    // Add new order with outside item
+    // -------------------------------------------
+    // prepare URI
+    targetURI = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Orders");
+    final ClientEntity original = newOrder(2000);
+    final ODataEntityCreateRequest<ClientEntity> createReq =
+        client.getCUDRequestFactory().getEntityCreateRequest(targetURI.build(), original);
+    createReq.setFormat(ContentType.JSON);
+    streamManager.addRequest(createReq);
+    // -------------------------------------------
+
+    final ODataBatchResponse response = streamManager.getResponse();
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+
+    // retrieve the first item (ODataRetrieve)
+    ODataBatchResponseItem item = iter.next();
+    assertTrue(item instanceof ODataSingleResponseItem);
+
+    ODataSingleResponseItem retitem = (ODataSingleResponseItem) item;
+    ODataResponse res = retitem.next();
+    assertTrue(res instanceof ODataEntityResponseImpl);
+    assertEquals(200, res.getStatusCode());
+    assertEquals("OK", res.getStatusMessage());
+
+    // retrieve the second item (ODataChangeset)
+    item = iter.next();
+    assertTrue(item instanceof ODataSingleResponseItem);
+
+    final ODataSingleResponseItem outitem = (ODataSingleResponseItem) item;
+    res = outitem.next();
+    assertTrue(res instanceof ODataEntityCreateResponse);
+    assertEquals(201, res.getStatusCode());
+    assertEquals("Created", res.getStatusMessage());
+
+    final ODataEntityCreateResponse<ClientEntity> entres = (ODataEntityCreateResponse<ClientEntity>) res;
+    final ClientEntity entity = entres.getBody();
+    assertEquals(2000, entity.getProperty("OrderID").getPrimitiveValue().toCastValue(Integer.class).intValue());
+
+    assertFalse(iter.hasNext());
+  }
+
+  @Test
+  @SuppressWarnings({ "unchecked", "rawtypes" })
+  public void batchRequest() throws EdmPrimitiveTypeException {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+    request.setAccept(ACCEPT);
+
+    final BatchManager streamManager = request.payloadManager();
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    // prepare URI
+    URIBuilder targetURI = client.newURIBuilder(testStaticServiceRootURL);
+    targetURI.appendEntitySetSegment("Customers").appendKeySegment(1);
+
+    // create new request
+    ODataEntityRequest<ClientEntity> queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+    queryReq.setFormat(ContentType.JSON);
+
+    streamManager.addRequest(queryReq);
+    // -------------------------------------------
+
+    // -------------------------------------------
+    // Add changeset item
+    // -------------------------------------------
+    final ODataChangeset changeset = streamManager.addChangeset();
+
+    // Update Customer into the changeset
+    targetURI = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").appendKeySegment(1);
+    final URI editLink = targetURI.build();
+
+    final ClientEntity patch = client.getObjectFactory().newEntity(
+        new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Customer"));
+    patch.setEditLink(editLink);
+
+    patch.getProperties().add(client.getObjectFactory().newPrimitiveProperty(
+        "LastName",
+        client.getObjectFactory().newPrimitiveValueBuilder().buildString("new last name")));
+
+    final ODataEntityUpdateRequest<ClientEntity> changeReq =
+        client.getCUDRequestFactory().getEntityUpdateRequest(UpdateType.PATCH, patch);
+    changeReq.setFormat(ContentType.JSON_FULL_METADATA);
+
+    changeset.addRequest(changeReq);
+
+    // Create Order into the changeset
+    targetURI = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Orders");
+    final ClientEntity original = newOrder(1000);
+    final ODataEntityCreateRequest<ClientEntity> createReq =
+        client.getCUDRequestFactory().getEntityCreateRequest(targetURI.build(), original);
+    createReq.setFormat(ContentType.JSON);
+    changeset.addRequest(createReq);
+    // -------------------------------------------
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    // prepare URI
+    targetURI = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").appendKeySegment(1);
+
+    // create new request
+    queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+
+    streamManager.addRequest(queryReq);
+    // -------------------------------------------
+
+    final ODataBatchResponse response = streamManager.getResponse();
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+
+    // retrieve the first item (ODataRetrieve)
+    ODataBatchResponseItem item = iter.next();
+    assertTrue(item instanceof ODataSingleResponseItem);
+
+    ODataSingleResponseItem retitem = (ODataSingleResponseItem) item;
+    ODataResponse res = retitem.next();
+    assertTrue(res instanceof ODataEntityResponseImpl);
+    assertEquals(200, res.getStatusCode());
+    assertEquals("OK", res.getStatusMessage());
+
+    ODataEntityRequestImpl<ClientEntity>.ODataEntityResponseImpl entres =
+        (ODataEntityRequestImpl.ODataEntityResponseImpl) res;
+
+    ClientEntity entity = entres.getBody();
+    assertEquals(1, entity.getProperty("PersonID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    // retrieve the second item (ODataChangeset)
+    item = iter.next();
+    assertTrue(item instanceof ODataChangesetResponseItem);
+
+    final ODataChangesetResponseItem chgitem = (ODataChangesetResponseItem) item;
+    res = chgitem.next();
+    assertTrue(res instanceof ODataEntityUpdateResponse);
+    assertEquals(204, res.getStatusCode());
+    assertEquals("No Content", res.getStatusMessage());
+
+    res = chgitem.next();
+    assertTrue(res instanceof ODataEntityCreateResponse);
+    assertEquals(201, res.getStatusCode());
+    assertEquals("Created", res.getStatusMessage());
+
+    final ODataEntityCreateResponse<ClientEntity> createres = (ODataEntityCreateResponse<ClientEntity>) res;
+    entity = createres.getBody();
+    assertEquals(new Integer(1000), entity.getProperty("OrderID").getPrimitiveValue().toCastValue(Integer.class));
+
+    // retrieve the third item (ODataRetrieve)
+    item = iter.next();
+    assertTrue(item instanceof ODataSingleResponseItem);
+
+    retitem = (ODataSingleResponseItem) item;
+    res = retitem.next();
+    assertTrue(res instanceof ODataEntityResponseImpl);
+    assertEquals(200, res.getStatusCode());
+    assertEquals("OK", res.getStatusMessage());
+
+    entres = (ODataEntityRequestImpl.ODataEntityResponseImpl) res;
+    entity = entres.getBody();
+    assertEquals("new last name", entity.getProperty("LastName").getPrimitiveValue().toCastValue(String.class));
+
+    assertFalse(iter.hasNext());
+  }
+
+  @Test
+  public void async() {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(
+        URI.create(testStaticServiceRootURL + "/async/").normalize().toASCIIString());
+    request.setAccept(ACCEPT);
+
+    final AsyncBatchRequestWrapper async = client.getAsyncRequestFactory().getAsyncBatchRequestWrapper(request);
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    // prepare URI
+    URIBuilder targetURI = client.newURIBuilder(testStaticServiceRootURL);
+    targetURI.appendEntitySetSegment("People").appendKeySegment(5);
+
+    // create new request
+    ODataEntityRequest<ClientEntity> queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+    queryReq.setFormat(ContentType.JSON);
+
+    async.addRetrieve(queryReq);
+    // -------------------------------------------
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    // prepare URI
+    targetURI = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").appendKeySegment(1);
+
+    // create new request
+    queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+
+    async.addRetrieve(queryReq);
+    // -------------------------------------------
+
+    final AsyncResponseWrapper<ODataBatchResponse> responseWrapper = async.execute();
+
+    assertTrue(responseWrapper.isPreferenceApplied());
+    assertTrue(responseWrapper.isDone());
+
+    final ODataBatchResponse response = responseWrapper.getODataResponse();
+
+    assertEquals(200, response.getStatusCode());
+    assertEquals("Ok", response.getStatusMessage());
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+
+    // retrieve the first item (ODataRetrieve)
+    final ODataBatchResponseItem item = iter.next();
+    assertTrue(item instanceof ODataSingleResponseItem);
+
+    // The service return interim results to an asynchronously executing batch.
+    final ODataSingleResponseItem retitem = (ODataSingleResponseItem) item;
+    final ODataResponse res = retitem.next();
+    assertTrue(res instanceof AsyncResponse);
+    assertEquals(202, res.getStatusCode());
+    assertEquals("Accepted", res.getStatusMessage());
+
+    final Collection<String> newMonitorLocation = res.getHeader(HttpHeader.LOCATION);
+    if (newMonitorLocation != null && !newMonitorLocation.isEmpty()) {
+      responseWrapper.forceNextMonitorCheck(URI.create(newMonitorLocation.iterator().next()));
+      // .... now you can start again with isDone() and getODataResponse().
+    }
+
+    assertFalse(retitem.hasNext());
+    assertFalse(iter.hasNext());
+  }
+
+  private static class TestStreamManager extends AbstractODataStreamManager<ODataBatchResponse> {
+
+    public TestStreamManager() {
+      super(new Wrapper<Future<HttpResponse>>());
+    }
+
+    public ODataPayloadManager<ODataBatchResponse> addObject(final byte[] src) {
+      stream(src);
+      return this;
+    }
+
+    @Override
+    protected ODataBatchResponse getResponse(final long timeout, final TimeUnit unit) {
+      throw new UnsupportedOperationException("Not supported yet.");
+    }
+  };
+
+  /**
+   * To be used for debug purposes.
+   */
+  private static class StreamingThread extends Thread {
+
+    private final TestStreamManager streaming;
+
+    public StreamingThread(final TestStreamManager streaming) {
+      super();
+      this.streaming = streaming;
+    }
+
+    @Override
+    public void run() {
+      try {
+        final StringBuilder builder = new StringBuilder();
+
+        byte[] buff = new byte[1024];
+
+        int len;
+
+        while ((len = streaming.getBody().read(buff)) >= 0) {
+          builder.append(new String(buff, 0, len));
+        }
+
+        assertTrue(builder.toString().startsWith(PREFIX));
+        assertTrue(builder.toString().contains((MAX / 2) + ") send info"));
+        assertTrue(builder.toString().contains((MAX / 3) + ") send info"));
+        assertTrue(builder.toString().contains((MAX / 20) + ") send info"));
+        assertTrue(builder.toString().contains((MAX / 30) + ") send info"));
+        assertTrue(builder.toString().contains(MAX + ") send info"));
+        assertTrue(builder.toString().endsWith(SUFFIX));
+
+      } catch (IOException e) {
+        fail();
+      }
+    }
+  }
+
+  private ClientEntity newOrder(final int id) {
+    final ClientEntity order = getClient().getObjectFactory().
+        newEntity(new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Order"));
+
+    order.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("OrderID",
+        getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(id)));
+    order.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("OrderDate",
+        getClient().getObjectFactory().newPrimitiveValueBuilder().
+        setType(EdmPrimitiveTypeKind.DateTimeOffset).setValue(Calendar.getInstance()).build()));
+    order.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("ShelfLife",
+        getClient().getObjectFactory().newPrimitiveValueBuilder().
+        setType(EdmPrimitiveTypeKind.Duration).setValue(new BigDecimal("0.0000002")).build()));
+    order.getProperties().add(getClient().getObjectFactory().newCollectionProperty("OrderShelfLifes",
+        getClient().getObjectFactory().newCollectionValue(EdmPrimitiveTypeKind.Duration.name()).add(
+            getClient().getObjectFactory().newPrimitiveValueBuilder().setType(EdmPrimitiveTypeKind.Duration).
+            setValue(new BigDecimal("0.0000002")).build())));
+
+    return order;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/78a9539e/fit/src/test/java/org/apache/olingo/fit/base/BoundOperationInvokeTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/base/BoundOperationInvokeTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/base/BoundOperationInvokeTestITCase.java
new file mode 100644
index 0000000..ecd15c7
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/base/BoundOperationInvokeTestITCase.java
@@ -0,0 +1,459 @@
+/*
+ * 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.fit.base;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.apache.olingo.client.api.communication.request.invoke.ODataInvokeRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.domain.ClientCollectionValue;
+import org.apache.olingo.client.api.domain.ClientComplexValue;
+import org.apache.olingo.client.api.domain.ClientEntity;
+import org.apache.olingo.client.api.domain.ClientEntitySet;
+import org.apache.olingo.client.api.domain.ClientEnumValue;
+import org.apache.olingo.client.api.domain.ClientOperation;
+import org.apache.olingo.client.api.domain.ClientPrimitiveValue;
+import org.apache.olingo.client.api.domain.ClientProperty;
+import org.apache.olingo.client.api.domain.ClientSingleton;
+import org.apache.olingo.client.api.domain.ClientValue;
+import org.apache.olingo.client.api.uri.URIBuilder;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.junit.Test;
+
+public class BoundOperationInvokeTestITCase extends AbstractTestITCase {
+
+  private void functions(final ContentType contentType) throws EdmPrimitiveTypeException {
+    // GetEmployeesCount
+    URIBuilder builder = client.newURIBuilder(testStaticServiceRootURL).appendSingletonSegment("Company");
+    final ODataEntityRequest<ClientSingleton> singletonReq =
+        client.getRetrieveRequestFactory().getSingletonRequest(builder.build());
+    singletonReq.setFormat(contentType);
+    final ClientSingleton company = singletonReq.execute().getBody();
+    assertNotNull(company);
+
+    ClientOperation boundOp = company.getOperation("Microsoft.Test.OData.Services.ODataWCFService.GetEmployeesCount");
+    assertNotNull(boundOp);
+
+    final ODataInvokeRequest<ClientProperty> getEmployeesCountReq =
+        client.getInvokeRequestFactory().getFunctionInvokeRequest(boundOp.getTarget(), ClientProperty.class);
+    getEmployeesCountReq.setFormat(contentType);
+    final ClientProperty getEmployeesCountRes = getEmployeesCountReq.execute().getBody();
+    assertNotNull(getEmployeesCountRes);
+    assertTrue(getEmployeesCountRes.hasPrimitiveValue());
+
+    // GetProductDetails
+    builder = client.newURIBuilder(testStaticServiceRootURL).
+        appendEntitySetSegment("Products").appendKeySegment(5);
+    ODataEntityRequest<ClientEntity> entityReq = client.getRetrieveRequestFactory().
+        getEntityRequest(builder.build());
+    entityReq.setFormat(contentType);
+    ClientEntity entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.GetProductDetails");
+    assertNotNull(boundOp);
+
+    final ClientPrimitiveValue count = client.getObjectFactory().newPrimitiveValueBuilder().buildInt32(1);
+    final ODataInvokeRequest<ClientEntitySet> getProductDetailsReq =
+        client.getInvokeRequestFactory().getFunctionInvokeRequest(boundOp.getTarget(), ClientEntitySet.class,
+            Collections.<String, ClientValue> singletonMap("count", count));
+    getProductDetailsReq.setFormat(contentType);
+    final ClientEntitySet getProductDetailsRes = getProductDetailsReq.execute().getBody();
+    assertNotNull(getProductDetailsRes);
+    assertEquals(1, getProductDetailsRes.getEntities().size());
+
+    // GetRelatedProduct
+    final Map<String, Object> keyMap = new LinkedHashMap<String, Object>();
+    keyMap.put("ProductID", 6);
+    keyMap.put("ProductDetailID", 1);
+    builder = client.newURIBuilder(testStaticServiceRootURL).
+        appendEntitySetSegment("ProductDetails").appendKeySegment(keyMap);
+    entityReq = client.getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(contentType);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.GetRelatedProduct");
+    assertNotNull(boundOp);
+
+    final ODataInvokeRequest<ClientEntity> getRelatedProductReq =
+        client.getInvokeRequestFactory().getFunctionInvokeRequest(boundOp.getTarget(), ClientEntity.class);
+    getRelatedProductReq.setFormat(contentType);
+    final ClientEntity getRelatedProductRes = getRelatedProductReq.execute().getBody();
+    assertNotNull(getRelatedProductRes);
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.Product",
+        getRelatedProductRes.getTypeName().toString());
+    assertEquals(6, getRelatedProductRes.getProperty("ProductID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    // GetDefaultPI
+    builder = client.newURIBuilder(testStaticServiceRootURL).
+        appendEntitySetSegment("Accounts").appendKeySegment(102);
+    entityReq = client.getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(contentType);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.GetDefaultPI");
+    assertNotNull(boundOp);
+
+    final ODataInvokeRequest<ClientEntity> getDefaultPIReq =
+        client.getInvokeRequestFactory().getFunctionInvokeRequest(boundOp.getTarget(), ClientEntity.class);
+    getDefaultPIReq.setFormat(contentType);
+    final ClientEntity getDefaultPIRes = getDefaultPIReq.execute().getBody();
+    assertNotNull(getDefaultPIRes);
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument",
+        getDefaultPIRes.getTypeName().toString());
+    assertEquals(102901,
+        getDefaultPIRes.getProperty("PaymentInstrumentID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    // GetAccountInfo
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.GetAccountInfo");
+    assertNotNull(boundOp);
+
+    final ODataInvokeRequest<ClientProperty> getAccountInfoReq =
+        client.getInvokeRequestFactory().getFunctionInvokeRequest(boundOp.getTarget(), ClientProperty.class);
+    getAccountInfoReq.setFormat(contentType);
+    final ClientProperty getAccountInfoRes = getAccountInfoReq.execute().getBody();
+    assertNotNull(getAccountInfoRes);
+    assertTrue(getAccountInfoRes.hasComplexValue());
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.AccountInfo",
+        getAccountInfoRes.getComplexValue().getTypeName());
+
+    // GetActualAmount
+    entityReq = client.getRetrieveRequestFactory().getEntityRequest(
+        entity.getNavigationLink("MyGiftCard").getLink());
+    entityReq.setFormat(contentType);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+    assertEquals(301, entity.getProperty("GiftCardID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.GetActualAmount");
+    assertNotNull(boundOp);
+
+    final ClientPrimitiveValue bonusRate = client.getObjectFactory().newPrimitiveValueBuilder().buildDouble(1.1);
+    final ODataInvokeRequest<ClientProperty> getActualAmountReq =
+        client.getInvokeRequestFactory().getFunctionInvokeRequest(boundOp.getTarget(), ClientProperty.class,
+            Collections.<String, ClientValue> singletonMap("bonusRate", bonusRate));
+    getActualAmountReq.setFormat(contentType);
+    final ClientProperty getActualAmountRes = getActualAmountReq.execute().getBody();
+    assertNotNull(getActualAmountRes);
+    assertEquals(41.79, getActualAmountRes.getPrimitiveValue().toCastValue(Double.class), 0);
+  }
+
+  @Test
+  public void atomFunctions() throws EdmPrimitiveTypeException {
+    functions(ContentType.APPLICATION_ATOM_XML);
+  }
+
+  @Test
+  public void jsonFunctions() throws EdmPrimitiveTypeException {
+    functions(ContentType.JSON_FULL_METADATA);
+  }
+
+  @Test
+  public void edmEnabledFunctions() throws EdmPrimitiveTypeException {
+    // GetEmployeesCount
+    final ODataInvokeRequest<ClientProperty> getEmployeesCountReq =
+        edmClient.getInvokeRequestFactory().getBoundFunctionInvokeRequest(
+            edmClient.newURIBuilder().appendSingletonSegment("Company").build(),
+            new FullQualifiedName(("Microsoft.Test.OData.Services.ODataWCFService.GetEmployeesCount")),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Company"),
+            false);
+    final ClientProperty getEmployeesCountRes = getEmployeesCountReq.execute().getBody();
+    assertNotNull(getEmployeesCountRes);
+    assertTrue(getEmployeesCountRes.hasPrimitiveValue());
+
+    // GetProductDetails
+    final ClientPrimitiveValue count = edmClient.getObjectFactory().newPrimitiveValueBuilder().buildInt32(1);
+    final ODataInvokeRequest<ClientEntitySet> getProductDetailsReq =
+        edmClient.getInvokeRequestFactory().getBoundFunctionInvokeRequest(
+            edmClient.newURIBuilder().appendEntitySetSegment("Products").appendKeySegment(5).build(),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.GetProductDetails"),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Product"),
+            false,
+            Collections.<String, ClientValue> singletonMap("count", count));
+    final ClientEntitySet getProductDetailsRes = getProductDetailsReq.execute().getBody();
+    assertNotNull(getProductDetailsRes);
+    assertEquals(1, getProductDetailsRes.getEntities().size());
+
+    // GetRelatedProduct
+    final Map<String, Object> keyMap = new LinkedHashMap<String, Object>();
+    keyMap.put("ProductID", 6);
+    keyMap.put("ProductDetailID", 1);
+    URIBuilder builder = edmClient.newURIBuilder().appendEntitySetSegment("ProductDetails").appendKeySegment(keyMap);
+
+    final ODataInvokeRequest<ClientEntity> getRelatedProductReq =
+        edmClient.getInvokeRequestFactory().getBoundFunctionInvokeRequest(
+            builder.build(),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.GetRelatedProduct"),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.ProductDetail"),
+            false);
+    final ClientEntity getRelatedProductRes = getRelatedProductReq.execute().getBody();
+    assertNotNull(getRelatedProductRes);
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.Product",
+        getRelatedProductRes.getTypeName().toString());
+    assertEquals(6, getRelatedProductRes.getProperty("ProductID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    // GetDefaultPI
+    final ODataInvokeRequest<ClientEntity> getDefaultPIReq =
+        edmClient.getInvokeRequestFactory().getBoundFunctionInvokeRequest(
+            edmClient.newURIBuilder().appendEntitySetSegment("Accounts").appendKeySegment(102).build(),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.GetDefaultPI"),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Account"),
+            false);
+    final ClientEntity getDefaultPIRes = getDefaultPIReq.execute().getBody();
+    assertNotNull(getDefaultPIRes);
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument",
+        getDefaultPIRes.getTypeName().toString());
+    assertEquals(102901,
+        getDefaultPIRes.getProperty("PaymentInstrumentID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    // GetAccountInfo
+    final ODataInvokeRequest<ClientProperty> getAccountInfoReq =
+        edmClient.getInvokeRequestFactory().getBoundFunctionInvokeRequest(
+            edmClient.newURIBuilder().appendEntitySetSegment("Accounts").appendKeySegment(102).build(),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.GetAccountInfo"),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Account"),
+            false);
+    final ClientProperty getAccountInfoRes = getAccountInfoReq.execute().getBody();
+    assertNotNull(getAccountInfoRes);
+    assertTrue(getAccountInfoRes.hasComplexValue());
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.AccountInfo",
+        getAccountInfoRes.getComplexValue().getTypeName());
+
+    // GetActualAmount
+    final ClientPrimitiveValue bonusRate = edmClient.getObjectFactory().newPrimitiveValueBuilder().buildDouble(1.1);
+    final ODataInvokeRequest<ClientProperty> getActualAmountReq =
+        edmClient.getInvokeRequestFactory().getBoundFunctionInvokeRequest(
+            edmClient.newURIBuilder().appendEntitySetSegment("Accounts").appendKeySegment(102).
+            appendNavigationSegment("MyGiftCard").build(),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.GetActualAmount"),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.GiftCard"),
+            false,
+            Collections.<String, ClientValue> singletonMap("bonusRate", bonusRate));
+    final ClientProperty getActualAmountRes = getActualAmountReq.execute().getBody();
+    assertNotNull(getActualAmountRes);
+    assertEquals(41.79, getActualAmountRes.getPrimitiveValue().toCastValue(Double.class), 0);
+  }
+
+  private void actions(final ContentType contentType) throws EdmPrimitiveTypeException {
+    // IncreaseRevenue
+    URIBuilder builder = client.newURIBuilder(testStaticServiceRootURL).appendSingletonSegment("Company");
+    ODataEntityRequest<ClientEntity> entityReq =
+        client.getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(contentType);
+    ClientEntity entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    ClientOperation boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.IncreaseRevenue");
+    assertNotNull(boundOp);
+
+    final ClientPrimitiveValue increaseValue =
+        client.getObjectFactory().newPrimitiveValueBuilder().buildInt64(12L);
+    final ODataInvokeRequest<ClientProperty> increaseRevenueReq =
+        client.getInvokeRequestFactory().getActionInvokeRequest(boundOp.getTarget(), ClientProperty.class,
+            Collections.<String, ClientValue> singletonMap("IncreaseValue", increaseValue));
+    increaseRevenueReq.setFormat(contentType);
+    final ClientProperty increaseRevenueRes = increaseRevenueReq.execute().getBody();
+    assertNotNull(increaseRevenueRes);
+    assertTrue(increaseRevenueRes.hasPrimitiveValue());
+
+    // AddAccessRight
+    builder = client.newURIBuilder(testStaticServiceRootURL).
+        appendEntitySetSegment("Products").appendKeySegment(5);
+    entityReq = client.getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(contentType);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.AddAccessRight");
+    assertNotNull(boundOp);
+
+    final ClientEnumValue accessRight = client.getObjectFactory().
+        newEnumValue("Microsoft.Test.OData.Services.ODataWCFService.AccessLevel", "Execute");
+    final ODataInvokeRequest<ClientProperty> getProductDetailsReq =
+        client.getInvokeRequestFactory().getActionInvokeRequest(boundOp.getTarget(), ClientProperty.class,
+            Collections.<String, ClientValue> singletonMap("accessRight", accessRight));
+    getProductDetailsReq.setFormat(contentType);
+    final ClientProperty getProductDetailsRes = getProductDetailsReq.execute().getBody();
+    assertNotNull(getProductDetailsRes);
+    assertTrue(getProductDetailsRes.hasEnumValue());
+
+    // ResetAddress
+    builder = client.newURIBuilder(testStaticServiceRootURL).
+        appendEntitySetSegment("Customers").appendKeySegment(2);
+    entityReq = client.getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(contentType);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.ResetAddress");
+    assertNotNull(boundOp);
+
+    final ClientCollectionValue<ClientValue> addresses =
+        client.getObjectFactory().
+        newCollectionValue("Collection(Microsoft.Test.OData.Services.ODataWCFService.Address)");
+    final ClientComplexValue address = client.getObjectFactory().
+        newComplexValue("Microsoft.Test.OData.Services.ODataWCFService.Address");
+    address.add(client.getObjectFactory().newPrimitiveProperty("Street",
+        client.getObjectFactory().newPrimitiveValueBuilder().buildString("Piazza La Bomba E Scappa")));
+    address.add(client.getObjectFactory().newPrimitiveProperty("City",
+        client.getObjectFactory().newPrimitiveValueBuilder().buildString("Tollo")));
+    address.add(client.getObjectFactory().newPrimitiveProperty("PostalCode",
+        client.getObjectFactory().newPrimitiveValueBuilder().buildString("66010")));
+    addresses.add(address);
+    final ClientPrimitiveValue index = client.getObjectFactory().newPrimitiveValueBuilder().buildInt32(0);
+    final Map<String, ClientValue> params = new LinkedHashMap<String, ClientValue>(2);
+    params.put("addresses", addresses);
+    params.put("index", index);
+    final ODataInvokeRequest<ClientEntity> resetAddressReq =
+        client.getInvokeRequestFactory().getActionInvokeRequest(boundOp.getTarget(), ClientEntity.class, params);
+    resetAddressReq.setFormat(contentType);
+    final ClientEntity resetAddressRes = resetAddressReq.execute().getBody();
+    assertNotNull(resetAddressRes);
+    assertEquals(2, resetAddressRes.getProperty("PersonID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    // RefreshDefaultPI
+    builder = client.newURIBuilder(testStaticServiceRootURL).
+        appendEntitySetSegment("Accounts").appendKeySegment(102);
+    entityReq = client.getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(contentType);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.RefreshDefaultPI");
+    assertNotNull(boundOp);
+
+    Calendar dateTime = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    dateTime.set(2014, 3, 9, 0, 0, 0);
+    final ClientPrimitiveValue newDate = client.getObjectFactory().newPrimitiveValueBuilder().
+        setType(EdmPrimitiveTypeKind.DateTimeOffset).setValue(dateTime).build();
+    final ODataInvokeRequest<ClientEntity> getDefaultPIReq =
+        client.getInvokeRequestFactory().getActionInvokeRequest(boundOp.getTarget(), ClientEntity.class,
+            Collections.<String, ClientValue> singletonMap("newDate", newDate));
+    getDefaultPIReq.setFormat(contentType);
+    final ClientEntity getDefaultPIRes = getDefaultPIReq.execute().getBody();
+    assertNotNull(getDefaultPIRes);
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument",
+        getDefaultPIRes.getTypeName().toString());
+    assertEquals(102901,
+        getDefaultPIRes.getProperty("PaymentInstrumentID").getPrimitiveValue().toCastValue(Integer.class), 0);
+  }
+
+  @Test
+  public void atomActions() throws EdmPrimitiveTypeException {
+    actions(ContentType.APPLICATION_ATOM_XML);
+  }
+
+  @Test
+  public void jsonActions() throws EdmPrimitiveTypeException {
+    actions(ContentType.JSON_FULL_METADATA);
+  }
+
+  @Test
+  public void edmEnabledActions() throws EdmPrimitiveTypeException {
+    // IncreaseRevenue
+    final ClientPrimitiveValue increaseValue = edmClient.getObjectFactory().newPrimitiveValueBuilder().buildInt64(12L);
+    final ODataInvokeRequest<ClientProperty> increaseRevenueReq =
+        edmClient.getInvokeRequestFactory().getBoundActionInvokeRequest(
+            edmClient.newURIBuilder().appendSingletonSegment("Company").build(),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.IncreaseRevenue"),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Company"),
+            false,
+            Collections.<String, ClientValue> singletonMap("IncreaseValue", increaseValue));
+    final ClientProperty increaseRevenueRes = increaseRevenueReq.execute().getBody();
+    assertNotNull(increaseRevenueRes);
+    assertTrue(increaseRevenueRes.hasPrimitiveValue());
+
+    // AddAccessRight
+    final ClientEnumValue accessRight = edmClient.getObjectFactory().
+        newEnumValue("Microsoft.Test.OData.Services.ODataWCFService.AccessLevel", "Execute");
+    final ODataInvokeRequest<ClientProperty> getProductDetailsReq =
+        edmClient.getInvokeRequestFactory().getBoundActionInvokeRequest(
+            edmClient.newURIBuilder().appendEntitySetSegment("Products").appendKeySegment(5).build(),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.AddAccessRight"),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Product"),
+            false,
+            Collections.<String, ClientValue> singletonMap("accessRight", accessRight));
+    final ClientProperty getProductDetailsRes = getProductDetailsReq.execute().getBody();
+    assertNotNull(getProductDetailsRes);
+    assertTrue(getProductDetailsRes.hasEnumValue());
+
+    // ResetAddress
+    final ClientCollectionValue<ClientValue> addresses =
+        edmClient.getObjectFactory().
+        newCollectionValue("Collection(Microsoft.Test.OData.Services.ODataWCFService.Address)");
+    final ClientComplexValue address = edmClient.getObjectFactory().
+        newComplexValue("Microsoft.Test.OData.Services.ODataWCFService.Address");
+    address.add(edmClient.getObjectFactory().newPrimitiveProperty("Street",
+        edmClient.getObjectFactory().newPrimitiveValueBuilder().buildString("Piazza La Bomba E Scappa")));
+    address.add(edmClient.getObjectFactory().newPrimitiveProperty("City",
+        edmClient.getObjectFactory().newPrimitiveValueBuilder().buildString("Tollo")));
+    address.add(edmClient.getObjectFactory().newPrimitiveProperty("PostalCode",
+        edmClient.getObjectFactory().newPrimitiveValueBuilder().buildString("66010")));
+    addresses.add(address);
+    final ClientPrimitiveValue index = edmClient.getObjectFactory().newPrimitiveValueBuilder().buildInt32(0);
+    final Map<String, ClientValue> params = new LinkedHashMap<String, ClientValue>(2);
+    params.put("addresses", addresses);
+    params.put("index", index);
+    final Map<String, Object> keys = new HashMap<String, Object>();
+    keys.put("PersonID", 2);
+    final ODataInvokeRequest<ClientEntity> resetAddressReq =
+        edmClient.getInvokeRequestFactory().getBoundActionInvokeRequest(
+            edmClient.newURIBuilder().appendEntitySetSegment("Customers").appendKeySegment(keys).build(),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.ResetAddress"),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Person"),
+            false,
+            params);
+    final ClientEntity resetAddressRes = resetAddressReq.execute().getBody();
+    assertNotNull(resetAddressRes);
+    assertEquals(2, resetAddressRes.getProperty("PersonID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    // RefreshDefaultPI
+    Calendar dateTime = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    dateTime.set(2014, 3, 9, 0, 0, 0);
+    final ClientPrimitiveValue newDate = edmClient.getObjectFactory().newPrimitiveValueBuilder().
+        setType(EdmPrimitiveTypeKind.DateTimeOffset).setValue(dateTime).build();
+    final ODataInvokeRequest<ClientEntity> getDefaultPIReq =
+        edmClient.getInvokeRequestFactory().getBoundActionInvokeRequest(
+            edmClient.newURIBuilder().appendEntitySetSegment("Accounts").appendKeySegment(102).build(),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.RefreshDefaultPI"),
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Account"),
+            false,
+            Collections.<String, ClientValue> singletonMap("newDate", newDate));
+    final ClientEntity getDefaultPIRes = getDefaultPIReq.execute().getBody();
+    assertNotNull(getDefaultPIRes);
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument",
+        getDefaultPIRes.getTypeName().toString());
+    assertEquals(102901,
+        getDefaultPIRes.getProperty("PaymentInstrumentID").getPrimitiveValue().toCastValue(Integer.class), 0);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/78a9539e/fit/src/test/java/org/apache/olingo/fit/base/ConformanceTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/base/ConformanceTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/base/ConformanceTestITCase.java
new file mode 100644
index 0000000..d682e64
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/base/ConformanceTestITCase.java
@@ -0,0 +1,415 @@
+/*
+ * 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.fit.base;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigDecimal;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import org.apache.olingo.client.api.communication.request.AsyncRequestWrapper;
+import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.request.cud.UpdateType;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataDeltaRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
+import org.apache.olingo.client.api.communication.response.AsyncResponseWrapper;
+import org.apache.olingo.client.api.communication.response.ODataDeleteResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.domain.ClientCollectionValue;
+import org.apache.olingo.client.api.domain.ClientDelta;
+import org.apache.olingo.client.api.domain.ClientEntity;
+import org.apache.olingo.client.api.domain.ClientEntitySet;
+import org.apache.olingo.client.api.domain.ClientProperty;
+import org.apache.olingo.client.api.domain.ClientValue;
+import org.apache.olingo.client.api.uri.URIBuilder;
+import org.apache.olingo.client.core.http.BasicAuthHttpClientFactory;
+import org.apache.olingo.client.core.http.DefaultHttpClientFactory;
+import org.apache.olingo.client.core.uri.URIUtils;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.junit.Test;
+
+/**
+ * 13.2 Interoperable OData Clients
+ * <br />
+ * http://docs.oasis-open.org/odata/odata/v4.0/os/part1-protocol/odata-v4.0-os-part1-protocol.html#_Toc372793762
+ */
+public class ConformanceTestITCase extends AbstractTestITCase {
+
+  /**
+   * 1. MUST specify the OData-MaxVersion header in requests (section 8.2.6).
+   */
+  @Test
+  public void item1() {
+    final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL).
+        appendEntitySetSegment("Customers").appendKeySegment(1).expand("Company");
+
+    final ODataEntityRequest<ClientEntity> req =
+        client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+
+    assertEquals("4.0", req.getHeader(HttpHeader.ODATA_MAX_VERSION));
+
+    assertNotNull(req.execute().getBody());
+  }
+
+  /**
+   * 2. MUST specify OData-Version (section 8.1.5) and Content-Type (section 8.1.1) in any request with a payload.
+   */
+  @Test
+  public void item2() {
+    final ClientEntity order = getClient().getObjectFactory().newEntity(
+        new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Order"));
+
+    final ClientProperty orderId = getClient().getObjectFactory().newPrimitiveProperty("OrderID",
+        getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(2000));
+    order.getProperties().add(orderId);
+
+    Calendar dateTime = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    dateTime.set(2011, 2, 4, 16, 3, 57);
+    final ClientProperty orderDate = getClient().getObjectFactory().newPrimitiveProperty("OrderDate",
+        getClient().getObjectFactory().newPrimitiveValueBuilder().
+        setType(EdmPrimitiveTypeKind.DateTimeOffset).setValue(dateTime).build());
+    order.getProperties().add(orderDate);
+
+    final ClientProperty shelfLife = getClient().getObjectFactory().newPrimitiveProperty("ShelfLife",
+        getClient().getObjectFactory().newPrimitiveValueBuilder().
+        setType(EdmPrimitiveTypeKind.Duration).setValue(new BigDecimal("0.0000001")).build());
+    order.getProperties().add(shelfLife);
+
+    final ClientCollectionValue<ClientValue> orderShelfLifesValue = getClient().getObjectFactory().
+        newCollectionValue("Collection(Duration)");
+    orderShelfLifesValue.add(getClient().getObjectFactory().newPrimitiveValueBuilder().
+        setType(EdmPrimitiveTypeKind.Duration).setValue(new BigDecimal("0.0000001")).build());
+    orderShelfLifesValue.add(getClient().getObjectFactory().newPrimitiveValueBuilder().
+        setType(EdmPrimitiveTypeKind.Duration).setValue(new BigDecimal("0.0000002")).build());
+    final ClientProperty orderShelfLifes = getClient().getObjectFactory().
+        newCollectionProperty("OrderShelfLifes", orderShelfLifesValue);
+    order.getProperties().add(orderShelfLifes);
+
+    final ODataEntityCreateRequest<ClientEntity> req = getClient().getCUDRequestFactory().getEntityCreateRequest(
+        getClient().newURIBuilder(testStaticServiceRootURL).
+        appendEntitySetSegment("Orders").build(), order);
+    req.setFormat(ContentType.JSON_FULL_METADATA);
+
+    // check for OData-Version
+    assertEquals("4.0", req.getHeader(HttpHeader.ODATA_VERSION));
+
+    // check for Content-Type
+    assertEquals(
+        ContentType.JSON_FULL_METADATA.toContentTypeString(),
+        req.getHeader("Content-Type"));
+    assertEquals(
+        ContentType.JSON_FULL_METADATA.toContentTypeString(),
+        req.getContentType());
+
+    final ClientEntity created = req.execute().getBody();
+    assertNotNull(created);
+
+    final URI deleteURI = created.getEditLink() == null
+        ? getClient().newURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Orders").appendKeySegment(2000).build()
+            : created.getEditLink();
+            final ODataDeleteRequest deleteReq = getClient().getCUDRequestFactory().getDeleteRequest(deleteURI);
+            final ODataDeleteResponse deleteRes = deleteReq.execute();
+            assertEquals(204, deleteRes.getStatusCode());
+  }
+
+  /**
+   * 4. MUST follow redirects (section 9.1.5).
+   */
+  @Test
+  public void item4() {
+    final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("redirect").
+        appendEntitySetSegment("Customers").appendKeySegment(1).expand("Company");
+
+    final ODataEntityRequest<ClientEntity> req =
+        client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+
+    assertEquals("4.0", req.getHeader(HttpHeader.ODATA_MAX_VERSION));
+
+    final ODataRetrieveResponse<ClientEntity> res = req.execute();
+    final ClientEntity entity = res.getBody();
+
+    assertNotNull(entity);
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.Customer", entity.getTypeName().toString());
+    assertTrue(entity.getProperty("Home").hasPrimitiveValue());
+    assertEquals("Edm.GeographyPoint", entity.getProperty("Home").getPrimitiveValue().getTypeName());
+  }
+
+  /**
+   * 5. MUST correctly handle next links (section 11.2.5.7).
+   */
+  @Test
+  public void item5() {
+    final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("People");
+
+    ODataEntitySetRequest<ClientEntitySet> req = client.getRetrieveRequestFactory().
+        getEntitySetRequest(uriBuilder.build());
+    req.setFormat(ContentType.JSON_FULL_METADATA);
+    req.setPrefer(client.newPreferences().maxPageSize(5));
+
+    ODataRetrieveResponse<ClientEntitySet> res = req.execute();
+    ClientEntitySet feed = res.getBody();
+
+    assertNotNull(feed);
+
+    assertEquals(5, feed.getEntities().size());
+    assertNotNull(feed.getNext());
+
+    final URI expected = URI.create(testStaticServiceRootURL + "/People?$skiptoken=5");
+    final URI found = URIUtils.getURI(testStaticServiceRootURL, feed.getNext().toASCIIString());
+
+    assertEquals(expected, found);
+
+    req = client.getRetrieveRequestFactory().getEntitySetRequest(found);
+    req.setFormat(ContentType.JSON_FULL_METADATA);
+
+    res = req.execute();
+    feed = res.getBody();
+
+    assertNotNull(feed);
+  }
+
+  /**
+   * 6. MUST support instances returning properties and navigation properties not specified in metadata (section 11.2).
+   */
+  @Test
+  public void item6() {
+    final Integer id = 2000;
+
+    ClientEntity rowIndex = getClient().getObjectFactory().newEntity(
+        new FullQualifiedName("Microsoft.Test.OData.Services.OpenTypesServiceV4.RowIndex"));
+    getClient().getBinder().add(rowIndex,
+        getClient().getObjectFactory().newPrimitiveProperty("Id",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(id)));
+
+    // add property not in metadata
+    getClient().getBinder().add(rowIndex,
+        getClient().getObjectFactory().newPrimitiveProperty("aString",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("string")));
+
+    // add navigation property not in metadata
+    rowIndex.addLink(client.getObjectFactory().newEntityNavigationLink(
+        "Row", URI.create(testOpenTypeServiceRootURL + "/Row(71f7d0dc-ede4-45eb-b421-555a2aa1e58f)")));
+
+    final ODataEntityCreateRequest<ClientEntity> createReq = getClient().getCUDRequestFactory().
+        getEntityCreateRequest(getClient().newURIBuilder(testOpenTypeServiceRootURL).
+            appendEntitySetSegment("RowIndex").build(), rowIndex);
+
+    final ODataEntityCreateResponse<ClientEntity> createRes = createReq.execute();
+    assertEquals(201, createRes.getStatusCode());
+
+    final URIBuilder builder = getClient().newURIBuilder(testOpenTypeServiceRootURL).
+        appendEntitySetSegment("RowIndex").appendKeySegment(id);
+
+    rowIndex = read(ContentType.JSON_FULL_METADATA, builder.build());
+    assertNotNull(rowIndex);
+    assertEquals(EdmPrimitiveTypeKind.Int32, rowIndex.getProperty("Id").getPrimitiveValue().getTypeKind());
+    assertEquals(EdmPrimitiveTypeKind.String, rowIndex.getProperty("aString").getPrimitiveValue().getTypeKind());
+    assertNotNull(rowIndex.getNavigationLink("Row"));
+
+    final ODataDeleteResponse deleteRes = getClient().getCUDRequestFactory().
+        getDeleteRequest(rowIndex.getEditLink()).execute();
+    assertEquals(204, deleteRes.getStatusCode());
+  }
+
+  /**
+   * 7. MUST generate PATCH requests for updates, if the client supports updates (section 11.4.3).
+   */
+  @Test
+  public void item7() {
+    final URI uri = client.newURIBuilder(testStaticServiceRootURL).
+        appendEntitySetSegment("Customers").appendKeySegment(1).build();
+
+    final ClientEntity patch = client.getObjectFactory().newEntity(
+        new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Customer"));
+    patch.setEditLink(uri);
+
+    final String newname = "New Name (" + System.currentTimeMillis() + ")";
+    patch.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("FirstName",
+        getClient().getObjectFactory().newPrimitiveValueBuilder().buildString(newname)));
+
+    final ODataEntityUpdateRequest<ClientEntity> req =
+        getClient().getCUDRequestFactory().getEntityUpdateRequest(UpdateType.PATCH, patch);
+
+    final ODataEntityUpdateResponse<ClientEntity> res = req.execute();
+    assertEquals(204, res.getStatusCode());
+
+    final ClientEntity actual = read(ContentType.JSON, uri);
+
+    assertEquals(newname, actual.getProperty("FirstName").getPrimitiveValue().toString());
+  }
+
+  /**
+   * 8. SHOULD support basic authentication as specified in [RFC2617] over HTTPS.
+   * <br />
+   * Unfortunately no service over HTTPs is available yet.
+   */
+  @Test
+  public void item8() {
+    client.getConfiguration().setHttpClientFactory(new BasicAuthHttpClientFactory("odatajclient", "odatajclient"));
+
+    final URIBuilder uriBuilder = client.newURIBuilder(testAuthServiceRootURL).
+        appendEntitySetSegment("Customers").appendKeySegment(1).expand("Company");
+
+    final ODataEntityRequest<ClientEntity> req =
+        client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(ContentType.JSON_FULL_METADATA);
+
+    assertNotNull(req.execute().getBody());
+
+    client.getConfiguration().setHttpClientFactory(new DefaultHttpClientFactory());
+  }
+
+  /**
+   * 9. MAY request entity references in place of entities previously returned in the response (section 11.2.7).
+   */
+  @Test
+  public void item9() {
+    final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL).
+        appendEntitySetSegment("Orders").appendKeySegment(8).appendNavigationSegment("CustomerForOrder").
+        appendRefSegment();
+
+    ODataEntityRequest<ClientEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(ContentType.JSON_FULL_METADATA);
+
+    ODataRetrieveResponse<ClientEntity> res = req.execute();
+    assertNotNull(res);
+
+    final ClientEntity entity = res.getBody();
+    assertNotNull(entity);
+    assertTrue(entity.getId().toASCIIString().endsWith("/StaticService/V40/Static.svc/Customers(PersonID=1)"));
+
+    final URI referenceURI = client.newURIBuilder(testStaticServiceRootURL).
+        appendEntityIdSegment(entity.getId().toASCIIString()).build();
+
+    req = client.getRetrieveRequestFactory().getEntityRequest(referenceURI);
+    req.setFormat(ContentType.JSON_FULL_METADATA);
+
+    res = req.execute();
+    assertNotNull(res);
+    assertNotNull(res.getBody());
+  }
+
+  /**
+   * 10. MAY support deleted entities, link entities, deleted link entities in a delta response (section 11.3).
+   */
+  @Test
+  public void item10() {
+    final ODataEntitySetRequest<ClientEntitySet> req = client.getRetrieveRequestFactory().getEntitySetRequest(
+        client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").build());
+    req.setPrefer(client.newPreferences().trackChanges());
+
+    final ClientEntitySet customers = req.execute().getBody();
+    assertNotNull(customers);
+    assertNotNull(customers.getDeltaLink());
+
+    final ODataDeltaRequest deltaReq = client.getRetrieveRequestFactory().getDeltaRequest(customers.getDeltaLink());
+    deltaReq.setFormat(ContentType.JSON_FULL_METADATA);
+
+    final ClientDelta delta = deltaReq.execute().getBody();
+    assertNotNull(delta);
+
+    assertNotNull(delta.getDeltaLink());
+    assertTrue(delta.getDeltaLink().isAbsolute());
+    assertEquals(5, delta.getCount(), 0);
+
+    assertEquals(1, delta.getDeletedEntities().size());
+    assertTrue(delta.getDeletedEntities().get(0).getId().isAbsolute());
+    assertTrue(delta.getDeletedEntities().get(0).getId().toASCIIString().endsWith("Customers('ANTON')"));
+
+    assertEquals(1, delta.getAddedLinks().size());
+    assertTrue(delta.getAddedLinks().get(0).getSource().isAbsolute());
+    assertTrue(delta.getAddedLinks().get(0).getSource().toASCIIString().endsWith("Customers('BOTTM')"));
+    assertEquals("Orders", delta.getAddedLinks().get(0).getRelationship());
+
+    assertEquals(1, delta.getDeletedLinks().size());
+    assertTrue(delta.getDeletedLinks().get(0).getSource().isAbsolute());
+    assertTrue(delta.getDeletedLinks().get(0).getSource().toASCIIString().endsWith("Customers('ALFKI')"));
+    assertEquals("Orders", delta.getDeletedLinks().get(0).getRelationship());
+
+    assertEquals(2, delta.getEntities().size());
+    ClientProperty property = delta.getEntities().get(0).getProperty("ContactName");
+    assertNotNull(property);
+    assertTrue(property.hasPrimitiveValue());
+    property = delta.getEntities().get(1).getProperty("ShippingAddress");
+    assertNotNull(property);
+    assertTrue(property.hasComplexValue());
+  }
+
+  /**
+   * 11. MAY support asynchronous responses (section 9.1.3).
+   */
+  @Test
+  public void item11() {
+    final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL).
+        appendEntitySetSegment("async").appendEntitySetSegment("Orders");
+
+    final ODataEntitySetRequest<ClientEntitySet> req =
+        client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build());
+    req.setFormat(ContentType.JSON_FULL_METADATA);
+
+    final AsyncRequestWrapper<ODataRetrieveResponse<ClientEntitySet>> async =
+        client.getAsyncRequestFactory().<ODataRetrieveResponse<ClientEntitySet>> getAsyncRequestWrapper(req);
+    async.callback(URI.create("http://client.service.it/callback/endpoint"));
+
+    final AsyncResponseWrapper<ODataRetrieveResponse<ClientEntitySet>> responseWrapper = async.execute();
+
+    assertTrue(responseWrapper.isPreferenceApplied());
+    assertTrue(responseWrapper.isDone());
+
+    final ODataRetrieveResponse<ClientEntitySet> res = responseWrapper.getODataResponse();
+    final ClientEntitySet entitySet = res.getBody();
+
+    assertFalse(entitySet.getEntities().isEmpty());
+  }
+
+  /**
+   * 12. MAY support odata.metadata=minimal in a JSON response (see [OData-JSON]).
+   */
+  @Test
+  public void item12() {
+    final URIBuilder uriBuilder = client.newURIBuilder(testStaticServiceRootURL).
+        appendEntitySetSegment("Customers").appendKeySegment(1).expand("Company");
+
+    final ODataEntityRequest<ClientEntity> req =
+        client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(ContentType.JSON);
+
+    assertEquals("application/json;odata.metadata=minimal", req.getHeader("Accept"));
+    assertEquals("application/json;odata.metadata=minimal", req.getAccept());
+
+    final ODataRetrieveResponse<ClientEntity> res = req.execute();
+    assertTrue(res.getContentType().startsWith("application/json; odata.metadata=minimal"));
+
+    assertNotNull(res.getBody());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/78a9539e/fit/src/test/java/org/apache/olingo/fit/base/DeltaTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/base/DeltaTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/base/DeltaTestITCase.java
new file mode 100644
index 0000000..6c7bfc6
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/base/DeltaTestITCase.java
@@ -0,0 +1,86 @@
+/*
+ * 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.fit.base;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.olingo.client.api.communication.request.retrieve.ODataDeltaRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
+import org.apache.olingo.client.api.domain.ClientDelta;
+import org.apache.olingo.client.api.domain.ClientEntitySet;
+import org.apache.olingo.client.api.domain.ClientProperty;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.junit.Test;
+
+public class DeltaTestITCase extends AbstractTestITCase {
+
+  private void parse(final ContentType format) {
+    final ODataEntitySetRequest<ClientEntitySet> req = client.getRetrieveRequestFactory().getEntitySetRequest(
+        client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").build());
+    req.setPrefer(client.newPreferences().trackChanges());
+
+    final ClientEntitySet customers = req.execute().getBody();
+    assertNotNull(customers);
+    assertNotNull(customers.getDeltaLink());
+
+    final ODataDeltaRequest deltaReq = client.getRetrieveRequestFactory().getDeltaRequest(customers.getDeltaLink());
+    deltaReq.setFormat(format);
+
+    final ClientDelta delta = deltaReq.execute().getBody();
+    assertNotNull(delta);
+
+    assertNotNull(delta.getDeltaLink());
+    assertTrue(delta.getDeltaLink().isAbsolute());
+    assertEquals(5, delta.getCount(), 0);
+
+    assertEquals(1, delta.getDeletedEntities().size());
+    assertTrue(delta.getDeletedEntities().get(0).getId().isAbsolute());
+    assertTrue(delta.getDeletedEntities().get(0).getId().toASCIIString().endsWith("Customers('ANTON')"));
+
+    assertEquals(1, delta.getAddedLinks().size());
+    assertTrue(delta.getAddedLinks().get(0).getSource().isAbsolute());
+    assertTrue(delta.getAddedLinks().get(0).getSource().toASCIIString().endsWith("Customers('BOTTM')"));
+    assertEquals("Orders", delta.getAddedLinks().get(0).getRelationship());
+
+    assertEquals(1, delta.getDeletedLinks().size());
+    assertTrue(delta.getDeletedLinks().get(0).getSource().isAbsolute());
+    assertTrue(delta.getDeletedLinks().get(0).getSource().toASCIIString().endsWith("Customers('ALFKI')"));
+    assertEquals("Orders", delta.getDeletedLinks().get(0).getRelationship());
+
+    assertEquals(2, delta.getEntities().size());
+    ClientProperty property = delta.getEntities().get(0).getProperty("ContactName");
+    assertNotNull(property);
+    assertTrue(property.hasPrimitiveValue());
+    property = delta.getEntities().get(1).getProperty("ShippingAddress");
+    assertNotNull(property);
+    assertTrue(property.hasComplexValue());
+  }
+
+  @Test
+  public void atomParse() {
+    parse(ContentType.APPLICATION_ATOM_XML);
+  }
+
+  @Test
+  public void jsonParse() {
+    parse(ContentType.JSON);
+  }
+}