You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by il...@apache.org on 2014/04/29 11:51:54 UTC

[10/11] [OLINGO-236] Refactor complete

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v3/EntityCreateTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v3/EntityCreateTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v3/EntityCreateTestITCase.java
new file mode 100644
index 0000000..cc97521
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v3/EntityCreateTestITCase.java
@@ -0,0 +1,484 @@
+/*
+ * 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.v3;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Set;
+import org.apache.http.entity.ContentType;
+import org.apache.olingo.client.api.communication.header.HeaderName;
+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.v3.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.ODataDeleteResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.http.NoContentException;
+import org.apache.olingo.client.api.uri.v3.URIBuilder;
+import org.apache.olingo.client.core.uri.URIUtils;
+import org.apache.olingo.commons.api.domain.ODataInlineEntitySet;
+import org.apache.olingo.commons.api.domain.ODataLink;
+import org.apache.olingo.commons.api.domain.v3.ODataEntity;
+import org.apache.olingo.commons.api.domain.v3.ODataEntitySet;
+import org.apache.olingo.commons.api.domain.v3.ODataProperty;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+
+import org.junit.Test;
+
+/**
+ * This is the unit test class to check create entity operations.
+ */
+public class EntityCreateTestITCase extends AbstractTestITCase {
+
+  protected String getServiceRoot() {
+    return testStaticServiceRootURL;
+  }
+
+  @Test
+  public void createAsAtom() {
+    final ODataPubFormat format = ODataPubFormat.ATOM;
+    final int id = 1;
+    final ODataEntity original = getSampleCustomerProfile(id, "Sample customer", false);
+
+    createEntity(getServiceRoot(), format, original, "Customer");
+    final ODataEntity actual = compareEntities(getServiceRoot(), format, original, id, null);
+
+    cleanAfterCreate(format, actual, false, getServiceRoot());
+  }
+
+  @Test
+  public void createAsJSON() {
+    final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+    final int id = 2;
+    final ODataEntity original = getSampleCustomerProfile(id, "Sample customer", false);
+
+    createEntity(getServiceRoot(), format, original, "Customer");
+    final ODataEntity actual = compareEntities(getServiceRoot(), format, original, id, null);
+
+    cleanAfterCreate(format, actual, false, getServiceRoot());
+  }
+
+  @Test
+  public void createWithInlineAsAtom() {
+    final ODataPubFormat format = ODataPubFormat.ATOM;
+    final int id = 3;
+    final ODataEntity original = getSampleCustomerProfile(id, "Sample customer", true);
+
+    createEntity(getServiceRoot(), format, original, "Customer");
+    final ODataEntity actual =
+            compareEntities(getServiceRoot(), format, original, id, Collections.<String>singleton("Info"));
+
+    cleanAfterCreate(format, actual, true, getServiceRoot());
+  }
+
+  @Test
+  public void createWithInlineAsJSON() {
+    // this needs to be full, otherwise there is no mean to recognize links
+    final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+    final int id = 4;
+    final ODataEntity original = getSampleCustomerProfile(id, "Sample customer", true);
+
+    createEntity(getServiceRoot(), format, original, "Customer");
+    final ODataEntity actual =
+            compareEntities(getServiceRoot(), format, original, id, Collections.<String>singleton("Info"));
+
+    cleanAfterCreate(format, actual, true, getServiceRoot());
+  }
+
+  @Test
+  public void createInlineWithoutLinkAsAtom() {
+    final ODataPubFormat format = ODataPubFormat.ATOM;
+    final int id = 5;
+    final ODataEntity original = getSampleCustomerProfile(id, "Sample customer", false);
+
+    original.addLink(client.getObjectFactory().newDeepInsertEntity(
+            "Info", getSampleCustomerInfo(id, "Sample Customer_Info")));
+
+    createEntity(getServiceRoot(), format, original, "Customer");
+    final ODataEntity actual =
+            compareEntities(getServiceRoot(), format, original, id, Collections.<String>singleton("Info"));
+
+    boolean found = false;
+
+    for (ODataLink link : actual.getNavigationLinks()) {
+      assertNotNull(link.getLink());
+      if (link.getLink().toASCIIString().endsWith("Customer(" + id + ")/Info")) {
+        found = true;
+      }
+    }
+
+    assertTrue(found);
+
+    cleanAfterCreate(format, actual, true, getServiceRoot());
+  }
+
+  @Test
+  public void createInlineWithoutLinkAsJSON() {
+    final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+    final int id = 6;
+    final ODataEntity original = getSampleCustomerProfile(id, "Sample customer", false);
+
+    original.addLink(client.getObjectFactory().newDeepInsertEntity(
+            "Info", getSampleCustomerInfo(id, "Sample Customer_Info")));
+
+    createEntity(getServiceRoot(), format, original, "Customer");
+    final ODataEntity actual =
+            compareEntities(getServiceRoot(), format, original, id, Collections.<String>singleton("Info"));
+
+    boolean found = false;
+
+    for (ODataLink link : actual.getNavigationLinks()) {
+      assertNotNull(link.getLink());
+      if (link.getLink().toASCIIString().endsWith("Customer(" + id + ")/Info")) {
+        found = true;
+      }
+    }
+
+    assertTrue(found);
+
+    cleanAfterCreate(format, actual, true, getServiceRoot());
+  }
+
+  @Test
+  public void createWithNavigationAsAtom() {
+    final ODataPubFormat format = ODataPubFormat.ATOM;
+    final ODataEntity actual = createWithNavigationLink(format, 5);
+    cleanAfterCreate(format, actual, false, getServiceRoot());
+  }
+
+  @Test
+  public void createWithNavigationAsJSON() {
+    // this needs to be full, otherwise there is no mean to recognize links
+    final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+    final ODataEntity actual = createWithNavigationLink(format, 6);
+    cleanAfterCreate(format, actual, false, getServiceRoot());
+  }
+
+  @Test
+  public void createWithFeedNavigationAsAtom() throws EdmPrimitiveTypeException {
+    final ODataPubFormat format = ODataPubFormat.ATOM;
+    final ODataEntity actual = createWithFeedNavigationLink(format, 7);
+    cleanAfterCreate(format, actual, false, getServiceRoot());
+  }
+
+  @Test
+  public void createWithFeedNavigationAsJSON() throws EdmPrimitiveTypeException {
+    // this needs to be full, otherwise there is no mean to recognize links
+    final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+    final ODataEntity actual = createWithFeedNavigationLink(format, 8);
+    cleanAfterCreate(format, actual, false, getServiceRoot());
+  }
+
+  @Test
+  public void createWithBackNavigationAsAtom() throws EdmPrimitiveTypeException {
+    final ODataPubFormat format = ODataPubFormat.ATOM;
+    final ODataEntity actual = createWithBackNavigationLink(format, 9);
+    cleanAfterCreate(format, actual, true, getServiceRoot());
+  }
+
+  @Test
+  public void createWithBackNavigationAsJSON() throws EdmPrimitiveTypeException {
+    // this needs to be full, otherwise there is no mean to recognize links
+    final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+    final ODataEntity actual = createWithBackNavigationLink(format, 10);
+    cleanAfterCreate(format, actual, true, getServiceRoot());
+  }
+
+  @Test
+  public void multiKeyAsAtom() {
+    multiKey(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void multiKeyAsJSON() {
+    multiKey(ODataPubFormat.JSON);
+  }
+
+  @Test
+  public void createReturnNoContent() {
+    final int id = 1;
+    final ODataEntity original = getSampleCustomerProfile(id, "Sample customer", false);
+
+    final ODataEntityCreateRequest<ODataEntity> createReq = client.getCUDRequestFactory().getEntityCreateRequest(
+            client.getURIBuilder(getServiceRoot()).appendEntitySetSegment("Customer").build(), original);
+    createReq.setPrefer(client.newPreferences().returnNoContent());
+
+    final ODataEntityCreateResponse<ODataEntity> createRes = createReq.execute();
+    assertEquals(204, createRes.getStatusCode());
+    assertEquals(client.newPreferences().returnNoContent(),
+            createRes.getHeader(HeaderName.preferenceApplied).iterator().next());
+
+    try {
+      createRes.getBody();
+      fail();
+    } catch (NoContentException e) {
+      assertNotNull(e);
+    }
+
+    final ODataDeleteResponse deleteRes = client.getCUDRequestFactory().getDeleteRequest(
+            client.getURIBuilder(getServiceRoot()).appendEntitySetSegment("Customer").appendKeySegment(id).build()).
+            execute();
+    assertEquals(204, deleteRes.getStatusCode());
+  }
+
+  @Test
+  public void issue135() {
+    final int id = 2;
+    final ODataEntity original = getSampleCustomerProfile(id, "Sample customer for issue 135", false);
+
+    final URIBuilder uriBuilder = client.getURIBuilder(getServiceRoot()).appendEntitySetSegment("Customer");
+    final ODataEntityCreateRequest<ODataEntity> createReq =
+            client.getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), original);
+    createReq.setFormat(ODataPubFormat.JSON_FULL_METADATA);
+    createReq.setContentType(ContentType.APPLICATION_ATOM_XML.getMimeType());
+    createReq.setPrefer(client.newPreferences().returnContent());
+
+    try {
+      final ODataEntityCreateResponse createRes = createReq.execute();
+      assertEquals(201, createRes.getStatusCode());
+    } catch (Exception e) {
+      fail(e.getMessage());
+    } finally {
+      final ODataDeleteResponse deleteRes = client.getCUDRequestFactory().getDeleteRequest(
+              client.getURIBuilder(getServiceRoot()).appendEntitySetSegment("Customer").appendKeySegment(id).
+              build()).
+              execute();
+      assertEquals(204, deleteRes.getStatusCode());
+    }
+  }
+
+  private ODataEntity createWithFeedNavigationLink(final ODataPubFormat format, final int id)
+          throws EdmPrimitiveTypeException {
+
+    final String sampleName = "Sample customer";
+    final ODataEntity original = getSampleCustomerProfile(id, sampleName, false);
+
+    final Set<Integer> keys = new HashSet<Integer>();
+    keys.add(-100);
+    keys.add(-101);
+
+    for (Integer key : keys) {
+      final ODataEntity order = client.getObjectFactory().
+              newEntity(new FullQualifiedName("Microsoft.Test.OData.Services.AstoriaDefaultService.Order"));
+
+      order.getProperties().add(client.getObjectFactory().newPrimitiveProperty("OrderId",
+              client.getObjectFactory().newPrimitiveValueBuilder().buildInt32(key)));
+      order.getProperties().add(client.getObjectFactory().newPrimitiveProperty("CustomerId",
+              client.getObjectFactory().newPrimitiveValueBuilder().buildInt32(id)));
+
+      final ODataEntityCreateRequest<ODataEntity> createReq = client.getCUDRequestFactory().getEntityCreateRequest(
+              client.getURIBuilder(getServiceRoot()).appendEntitySetSegment("Order").build(), order);
+      createReq.setFormat(format);
+
+      original.addLink(client.getObjectFactory().newEntitySetNavigationLink(
+              "Orders",
+              createReq.execute().getBody().getEditLink()));
+    }
+
+    final ODataEntity created = createEntity(getServiceRoot(), format, original, "Customer");
+    // now, compare the created one with the actual one and go deeply into the associated customer info.....
+    final ODataEntity actual = compareEntities(getServiceRoot(), format, created, id, null);
+
+    final URIBuilder uriBuilder = client.getURIBuilder(getServiceRoot());
+    uriBuilder.appendEntitySetSegment("Customer").appendKeySegment(id).appendEntitySetSegment("Orders");
+
+    final ODataEntitySetRequest<ODataEntitySet> req = client.getRetrieveRequestFactory().
+            getEntitySetRequest(uriBuilder.build());
+    req.setFormat(format);
+
+    final ODataRetrieveResponse<ODataEntitySet> res = req.execute();
+    assertEquals(200, res.getStatusCode());
+
+    final ODataEntitySet entitySet = res.getBody();
+    assertNotNull(entitySet);
+    assertEquals(2, entitySet.getCount());
+
+    for (ODataEntity entity : entitySet.getEntities()) {
+      final Integer key = entity.getProperty("OrderId").getPrimitiveValue().toCastValue(Integer.class);
+      final Integer customerId = entity.getProperty("CustomerId").getPrimitiveValue().toCastValue(Integer.class);
+      assertTrue(keys.contains(key));
+      assertEquals(Integer.valueOf(id), customerId);
+      keys.remove(key);
+
+      final ODataDeleteRequest deleteReq = client.getCUDRequestFactory().getDeleteRequest(
+              URIUtils.getURI(getServiceRoot(), entity.getEditLink().toASCIIString()));
+
+      deleteReq.setFormat(format);
+      assertEquals(204, deleteReq.execute().getStatusCode());
+    }
+
+    return actual;
+  }
+
+  private ODataEntity createWithNavigationLink(final ODataPubFormat format, final int id) {
+    final String sampleName = "Sample customer";
+
+    final ODataEntity original = getSampleCustomerProfile(id, sampleName, false);
+    original.addLink(client.getObjectFactory().newEntityNavigationLink(
+            "Info", URI.create(getServiceRoot() + "/CustomerInfo(12)")));
+
+    final ODataEntity created = createEntity(getServiceRoot(), format, original, "Customer");
+    // now, compare the created one with the actual one and go deeply into the associated customer info.....
+    final ODataEntity actual = compareEntities(getServiceRoot(), format, created, id, null);
+
+    final URIBuilder uriBuilder = client.getURIBuilder(getServiceRoot());
+    uriBuilder.appendEntitySetSegment("Customer").appendKeySegment(id).appendEntitySetSegment("Info");
+
+    final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(format);
+
+    final ODataRetrieveResponse<ODataEntity> res = req.execute();
+    assertEquals(200, res.getStatusCode());
+
+    final ODataEntity info = res.getBody();
+    assertNotNull(info);
+
+    boolean found = false;
+
+    for (ODataProperty prop : info.getProperties()) {
+      if ("CustomerInfoId".equals(prop.getName())) {
+        assertEquals("12", prop.getValue().toString());
+        found = true;
+      }
+    }
+
+    assertTrue(found);
+
+    return actual;
+  }
+
+  private ODataEntity createWithBackNavigationLink(final ODataPubFormat format, final int id)
+          throws EdmPrimitiveTypeException {
+
+    final String sampleName = "Sample customer";
+
+    ODataEntity customer = getSampleCustomerProfile(id, sampleName, false);
+    customer = createEntity(getServiceRoot(), format, customer, "Customer");
+
+    ODataEntity order = client.getObjectFactory().newEntity(new FullQualifiedName(
+            "Microsoft.Test.OData.Services.AstoriaDefaultService.Order"));
+    getClient().getBinder().add(order,
+            client.getObjectFactory().newPrimitiveProperty("CustomerId",
+                    client.getObjectFactory().newPrimitiveValueBuilder().buildInt32(id)));
+    getClient().getBinder().add(order,
+            client.getObjectFactory().newPrimitiveProperty("OrderId",
+                    client.getObjectFactory().newPrimitiveValueBuilder().buildInt32(id)));
+
+    order.addLink(client.getObjectFactory().newEntityNavigationLink(
+            "Customer", URIUtils.getURI(getServiceRoot(), customer.getEditLink().toASCIIString())));
+
+    order = createEntity(getServiceRoot(), format, order, "Order");
+
+    final ODataEntity changes = client.getObjectFactory().newEntity(new FullQualifiedName(
+            "Microsoft.Test.OData.Services.AstoriaDefaultService.Customer"));
+    changes.setEditLink(customer.getEditLink());
+    changes.addLink(client.getObjectFactory().newEntitySetNavigationLink(
+            "Orders", URIUtils.getURI(getServiceRoot(), order.getEditLink().toASCIIString())));
+    update(UpdateType.PATCH, changes, format, null);
+
+    final ODataEntityRequest<ODataEntity> customerreq = client.getRetrieveRequestFactory().getEntityRequest(
+            URIUtils.getURI(getServiceRoot(), order.getEditLink().toASCIIString() + "/Customer"));
+    customerreq.setFormat(format);
+
+    customer = customerreq.execute().getBody();
+
+    assertEquals(Integer.valueOf(id),
+            customer.getProperty("CustomerId").getPrimitiveValue().toCastValue(Integer.class));
+
+    final ODataEntitySetRequest<ODataEntitySet> orderreq = client.getRetrieveRequestFactory().getEntitySetRequest(
+            URIUtils.getURI(getServiceRoot(), customer.getEditLink().toASCIIString() + "/Orders"));
+    orderreq.setFormat(format);
+
+    final ODataRetrieveResponse<ODataEntitySet> orderres = orderreq.execute();
+    assertEquals(200, orderres.getStatusCode());
+
+    assertEquals(Integer.valueOf(id),
+            orderres.getBody().getEntities().get(0).getProperty("OrderId").getPrimitiveValue().
+            toCastValue(Integer.class));
+
+    final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(
+            URIUtils.getURI(getServiceRoot(), customer.getEditLink().toASCIIString() + "?$expand=Orders"));
+    req.setFormat(format);
+
+    customer = req.execute().getBody();
+
+    boolean found = false;
+    for (ODataLink link : customer.getNavigationLinks()) {
+      if (link instanceof ODataInlineEntitySet && "Orders".equals(link.getName())) {
+        found = true;
+      }
+    }
+    assertTrue(found);
+
+    return customer;
+  }
+
+  private void multiKey(final ODataPubFormat format) {
+    final ODataEntity message = client.getObjectFactory().newEntity(new FullQualifiedName(
+            "Microsoft.Test.OData.Services.AstoriaDefaultService.Message"));
+
+    getClient().getBinder().add(message,
+            client.getObjectFactory().newPrimitiveProperty("MessageId",
+                    client.getObjectFactory().newPrimitiveValueBuilder().buildInt32(1000)));
+    getClient().getBinder().add(message,
+            client.getObjectFactory().newPrimitiveProperty("FromUsername",
+                    client.getObjectFactory().newPrimitiveValueBuilder().buildString("1")));
+    getClient().getBinder().add(message,
+            client.getObjectFactory().newPrimitiveProperty("ToUsername",
+                    client.getObjectFactory().newPrimitiveValueBuilder().buildString("xlodhxzzusxecbzptxlfxprneoxkn")));
+    getClient().getBinder().add(message,
+            client.getObjectFactory().newPrimitiveProperty("Subject",
+                    client.getObjectFactory().newPrimitiveValueBuilder().buildString("Test subject")));
+    getClient().getBinder().add(message,
+            client.getObjectFactory().newPrimitiveProperty("Body",
+                    client.getObjectFactory().newPrimitiveValueBuilder().buildString("Test body")));
+    getClient().getBinder().add(message,
+            client.getObjectFactory().newPrimitiveProperty("IsRead",
+                    client.getObjectFactory().newPrimitiveValueBuilder().buildBoolean(false)));
+
+    final URIBuilder builder =
+            client.getURIBuilder(getServiceRoot()).appendEntitySetSegment("Message");
+    final ODataEntityCreateRequest<ODataEntity> req = client.getCUDRequestFactory().
+            getEntityCreateRequest(builder.build(), message);
+    req.setFormat(format);
+
+    final ODataEntityCreateResponse<ODataEntity> res = req.execute();
+    assertNotNull(res);
+    assertEquals(201, res.getStatusCode());
+
+    final LinkedHashMap<String, Object> multiKey = new LinkedHashMap<String, Object>();
+    multiKey.put("FromUsername", "1");
+    multiKey.put("MessageId", 1000);
+
+    final ODataDeleteResponse deleteRes = client.getCUDRequestFactory().
+            getDeleteRequest(builder.appendKeySegment(multiKey).build()).execute();
+    assertEquals(204, deleteRes.getStatusCode());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v3/EntityRetrieveTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v3/EntityRetrieveTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v3/EntityRetrieveTestITCase.java
new file mode 100644
index 0000000..1b95c60
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v3/EntityRetrieveTestITCase.java
@@ -0,0 +1,242 @@
+/*
+ * 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.v3;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataRawRequest;
+import org.apache.olingo.client.api.communication.response.ODataRawResponse;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.uri.CommonURIBuilder;
+import org.apache.olingo.commons.api.data.ResWrap;
+import org.apache.olingo.commons.api.domain.CommonODataEntity;
+import org.apache.olingo.commons.api.domain.CommonODataEntitySet;
+import org.apache.olingo.commons.api.domain.CommonODataProperty;
+import org.apache.olingo.commons.api.domain.ODataInlineEntity;
+import org.apache.olingo.commons.api.domain.ODataInlineEntitySet;
+import org.apache.olingo.commons.api.domain.ODataLink;
+import org.apache.olingo.commons.api.domain.v3.ODataEntity;
+import org.apache.olingo.commons.api.domain.v3.ODataEntitySet;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.apache.olingo.commons.core.op.ResourceFactory;
+import org.junit.Test;
+
+/**
+ * This is the unit test class to check entity retrieve operations.
+ */
+public class EntityRetrieveTestITCase extends AbstractTestITCase {
+
+  protected String getServiceRoot() {
+    return testStaticServiceRootURL;
+  }
+
+  private void withInlineEntry(final ODataPubFormat format) {
+    final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Customer").appendKeySegment(-10).expand("Info");
+
+    final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(format);
+
+    final ODataRetrieveResponse<ODataEntity> res = req.execute();
+    final ODataEntity entity = res.getBody();
+
+    assertNotNull(entity);
+    assertEquals("Microsoft.Test.OData.Services.AstoriaDefaultService.Customer", entity.getTypeName().toString());
+    assertEquals(getServiceRoot() + "/Customer(-10)", entity.getEditLink().toASCIIString());
+
+    assertEquals(5, entity.getNavigationLinks().size());
+    assertTrue(entity.getAssociationLinks().isEmpty());
+
+    boolean found = false;
+
+    for (ODataLink link : entity.getNavigationLinks()) {
+      if (link instanceof ODataInlineEntity) {
+        final CommonODataEntity inline = ((ODataInlineEntity) link).getEntity();
+        assertNotNull(inline);
+
+        debugEntity(client.getBinder().getEntity(
+                inline, ResourceFactory.entityClassForFormat(format == ODataPubFormat.ATOM)), "Just read");
+
+        final List<? extends CommonODataProperty> properties = inline.getProperties();
+        assertEquals(2, properties.size());
+
+        assertTrue(properties.get(0).getName().equals("CustomerInfoId")
+                || properties.get(1).getName().equals("CustomerInfoId"));
+        assertTrue(properties.get(0).getValue().toString().equals("11")
+                || properties.get(1).getValue().toString().equals("11"));
+
+        found = true;
+      }
+    }
+
+    assertTrue(found);
+  }
+
+  @Test
+  public void withInlineEntryFromAtom() {
+    withInlineEntry(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void withInlineEntryFromJSON() {
+    // this needs to be full, otherwise there is no mean to recognize links
+    withInlineEntry(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+  private void withInlineFeed(final ODataPubFormat format) {
+    final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Customer").appendKeySegment(-10).expand("Orders");
+
+    final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(format);
+
+    final ODataRetrieveResponse<ODataEntity> res = req.execute();
+    final ODataEntity entity = res.getBody();
+    assertNotNull(entity);
+
+    boolean found = false;
+
+    for (ODataLink link : entity.getNavigationLinks()) {
+      if (link instanceof ODataInlineEntitySet) {
+        final CommonODataEntitySet inline = ((ODataInlineEntitySet) link).getEntitySet();
+        assertNotNull(inline);
+
+        debugEntitySet(client.getBinder().getEntitySet(inline, ResourceFactory.entitySetClassForFormat(
+                format == ODataPubFormat.ATOM)), "Just read");
+
+        found = true;
+      }
+    }
+
+    assertTrue(found);
+  }
+
+  @Test
+  public void withInlineFeedFromAtom() {
+    withInlineFeed(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void withInlineFeedFromJSON() {
+    // this needs to be full, otherwise there is no mean to recognize links
+    withInlineFeed(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+  private void rawRequest(final ODataPubFormat format) {
+    final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Car").appendKeySegment(16);
+
+    final ODataRawRequest req = client.getRetrieveRequestFactory().getRawRequest(uriBuilder.build());
+    req.setFormat(format.toString(client.getServiceVersion()));
+
+    final ODataRawResponse res = req.execute();
+    assertNotNull(res);
+
+    final ResWrap<ODataEntitySet> entitySet = res.getBodyAs(ODataEntitySet.class);
+    assertNull(entitySet);
+
+    final ResWrap<ODataEntity> entity = res.getBodyAs(ODataEntity.class);
+    assertNotNull(entity.getPayload());
+  }
+
+  @Test
+  public void rawRequestAsAtom() {
+    rawRequest(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void rawRequestAsJSON() {
+    // this needs to be full, otherwise actions will not be provided
+    rawRequest(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+  private void multiKey(final ODataPubFormat format) throws EdmPrimitiveTypeException {
+    final LinkedHashMap<String, Object> multiKey = new LinkedHashMap<String, Object>();
+    multiKey.put("FromUsername", "1");
+    multiKey.put("MessageId", -10);
+
+    final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Message").appendKeySegment(multiKey);
+
+    final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(format);
+
+    final ODataRetrieveResponse<ODataEntity> res = req.execute();
+    final ODataEntity entity = res.getBody();
+    assertNotNull(entity);
+    assertEquals("1", entity.getProperty("FromUsername").getPrimitiveValue().toCastValue(String.class));
+  }
+
+  @Test
+  public void multiKeyAsAtom() throws EdmPrimitiveTypeException {
+    multiKey(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void multiKeyAsJSON() throws EdmPrimitiveTypeException {
+    multiKey(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+  @Test
+  public void checkForETagAsATOM() {
+    checkForETag(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void checkForETagAsJSON() {
+    checkForETag(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+  private void checkForETag(final ODataPubFormat format) {
+    final CommonURIBuilder<?> uriBuilder =
+            client.getURIBuilder(getServiceRoot()).appendEntitySetSegment("Product").appendKeySegment(-10);
+
+    final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(format);
+
+    final ODataRetrieveResponse<ODataEntity> res = req.execute();
+    assertEquals(200, res.getStatusCode());
+
+    final String etag = res.getETag();
+    assertTrue(StringUtils.isNotBlank(etag));
+
+    final CommonODataEntity product = res.getBody();
+    assertEquals(etag, product.getETag());
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void issue99() {
+    final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(getServiceRoot()).appendEntitySetSegment("Car");
+
+    final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(ODataPubFormat.JSON);
+
+    // this statement should cause an IllegalArgumentException bearing JsonParseException
+    // since we are attempting to parse an EntitySet as if it was an Entity
+    req.execute().getBody();
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v3/EntitySetTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v3/EntitySetTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v3/EntitySetTestITCase.java
new file mode 100644
index 0000000..6bcd248
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v3/EntitySetTestITCase.java
@@ -0,0 +1,176 @@
+/*
+ * 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.v3;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.URI;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetIteratorRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataRawRequest;
+import org.apache.olingo.client.api.communication.response.ODataRawResponse;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.domain.ODataEntitySetIterator;
+import org.apache.olingo.client.api.uri.v3.URIBuilder;
+import org.apache.olingo.client.core.uri.URIUtils;
+import org.apache.olingo.commons.api.data.ResWrap;
+import org.apache.olingo.commons.api.domain.v3.ODataEntity;
+import org.apache.olingo.commons.api.domain.v3.ODataEntitySet;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.apache.olingo.commons.core.op.ResourceFactory;
+import org.junit.Test;
+
+/**
+ * This is the unit test class to check basic feed operations.
+ */
+public class EntitySetTestITCase extends AbstractTestITCase {
+
+  protected String getServiceRoot() {
+    return testStaticServiceRootURL;
+  }
+
+  @Test
+  public void rawRequestAsAtom() throws IOException {
+    rawRequest(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void rawRequestAsJSON() throws IOException {
+    rawRequest(ODataPubFormat.JSON);
+  }
+
+  @Test
+  public void readWithInlineCountAsJSON() throws IOException {
+    readWithInlineCount(ODataPubFormat.JSON);
+  }
+
+  @Test
+  public void readWithInlineCountAsAtom() throws IOException {
+    readWithInlineCount(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void readODataEntitySetIteratorFromAtom() {
+    readODataEntitySetIterator(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void readODataEntitySetIteratorFromJSON() {
+    readODataEntitySetIterator(ODataPubFormat.JSON);
+  }
+
+  @Test
+  public void readODataEntitySetIteratorFromJSONFullMeta() {
+    readODataEntitySetIterator(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+  @Test
+  public void readODataEntitySetIteratorFromJSONNoMeta() {
+    readODataEntitySetIterator(ODataPubFormat.JSON_NO_METADATA);
+  }
+
+  @Test
+  public void readODataEntitySetWithNextFromAtom() {
+    readEntitySetWithNextLink(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void readODataEntitySetWithNextFromJSON() {
+    readEntitySetWithNextLink(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+  private void readEntitySetWithNextLink(final ODataPubFormat format) {
+    final URIBuilder uriBuilder = client.getURIBuilder(getServiceRoot());
+    uriBuilder.appendEntitySetSegment("Customer");
+
+    final ODataEntitySetRequest<ODataEntitySet> req = client.getRetrieveRequestFactory().
+            getEntitySetRequest(uriBuilder.build());
+    req.setFormat(format);
+
+    final ODataRetrieveResponse<ODataEntitySet> res = req.execute();
+    final ODataEntitySet feed = res.getBody();
+
+    assertNotNull(feed);
+
+    debugEntitySet(client.getBinder().getEntitySet(feed, ResourceFactory.entitySetClassForFormat(
+            ODataPubFormat.ATOM == format)), "Just retrieved feed");
+
+    assertEquals(2, feed.getEntities().size());
+    assertNotNull(feed.getNext());
+
+    final URI expected = URI.create(getServiceRoot() + "/Customer?$skiptoken=-9");
+    final URI found = URIUtils.getURI(getServiceRoot(), feed.getNext().toASCIIString());
+
+    assertEquals(expected, found);
+  }
+
+  private void readODataEntitySetIterator(final ODataPubFormat format) {
+    final URIBuilder uriBuilder = client.getURIBuilder(getServiceRoot());
+    uriBuilder.appendEntitySetSegment("Customer");
+
+    final ODataEntitySetIteratorRequest<ODataEntitySet, ODataEntity> req =
+            client.getRetrieveRequestFactory().getEntitySetIteratorRequest(uriBuilder.build());
+    req.setFormat(format);
+
+    final ODataRetrieveResponse<ODataEntitySetIterator<ODataEntitySet, ODataEntity>> res = req.execute();
+    final ODataEntitySetIterator<ODataEntitySet, ODataEntity> feedIterator = res.getBody();
+
+    assertNotNull(feedIterator);
+
+    int count = 0;
+
+    while (feedIterator.hasNext()) {
+      assertNotNull(feedIterator.next());
+      count++;
+    }
+    assertEquals(2, count);
+    assertTrue(feedIterator.getNext().toASCIIString().endsWith("Customer?$skiptoken=-9"));
+  }
+
+  private void readWithInlineCount(final ODataPubFormat format) {
+    final URIBuilder uriBuilder = client.getURIBuilder(getServiceRoot());
+    uriBuilder.appendEntitySetSegment("Product").inlineCount(URIBuilder.InlineCount.allpages);
+
+    final ODataRawRequest req = client.getRetrieveRequestFactory().getRawRequest(uriBuilder.build());
+    req.setFormat(format.toString(client.getServiceVersion()));
+
+    final ODataRawResponse res = req.execute();
+    assertNotNull(res);
+
+    final ResWrap<ODataEntitySet> entitySet = res.getBodyAs(ODataEntitySet.class);
+    assertEquals(10, entitySet.getPayload().getCount());
+  }
+
+  private void rawRequest(final ODataPubFormat format) {
+    final URIBuilder uriBuilder = client.getURIBuilder(getServiceRoot());
+    uriBuilder.appendEntitySetSegment("Car");
+
+    final ODataRawRequest req = client.getRetrieveRequestFactory().getRawRequest(uriBuilder.build());
+    req.setFormat(format.toString(client.getServiceVersion()));
+
+    final ODataRawResponse res = req.execute();
+    assertNotNull(res);
+
+    final ResWrap<ODataEntitySet> entitySet = res.getBodyAs(ODataEntitySet.class);
+    assertNotNull(entitySet.getPayload());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v3/EntityUpdateTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v3/EntityUpdateTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v3/EntityUpdateTestITCase.java
new file mode 100644
index 0000000..3e78f60
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v3/EntityUpdateTestITCase.java
@@ -0,0 +1,242 @@
+/*
+ * 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.v3;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.net.URI;
+import java.util.LinkedHashMap;
+import org.apache.olingo.client.api.communication.ODataClientErrorException;
+import org.apache.olingo.client.api.communication.header.HeaderName;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.request.cud.v3.UpdateType;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
+import org.apache.olingo.commons.api.domain.v3.ODataEntity;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+
+import org.junit.Test;
+
+/**
+ * This is the unit test class to check entity update operations.
+ */
+public class EntityUpdateTestITCase extends AbstractTestITCase {
+
+  protected String getServiceRoot() {
+    return testStaticServiceRootURL;
+  }
+
+  @Test
+  public void mergeAsAtom() {
+    final ODataPubFormat format = ODataPubFormat.ATOM;
+    final URI uri = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Product").appendKeySegment(-10).build();
+    final String etag = getETag(uri);
+    final ODataEntity merge = client.getObjectFactory().newEntity(TEST_PRODUCT_TYPE);
+    merge.setEditLink(uri);
+    updateEntityDescription(format, merge, UpdateType.MERGE, etag);
+  }
+
+  @Test
+  public void mergeAsJSON() {
+    final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+    final URI uri = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Product").appendKeySegment(-10).build();
+    final String etag = getETag(uri);
+    final ODataEntity merge = client.getObjectFactory().newEntity(TEST_PRODUCT_TYPE);
+    merge.setEditLink(uri);
+    updateEntityDescription(format, merge, UpdateType.MERGE, etag);
+  }
+
+  @Test
+  public void patchAsAtom() {
+    final ODataPubFormat format = ODataPubFormat.ATOM;
+    final URI uri = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Product").appendKeySegment(-10).build();
+    final String etag = getETag(uri);
+    final ODataEntity patch = client.getObjectFactory().newEntity(TEST_PRODUCT_TYPE);
+    patch.setEditLink(uri);
+    updateEntityDescription(format, patch, UpdateType.PATCH, etag);
+  }
+
+  @Test
+  public void patchAsJSON() {
+    final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+    final URI uri = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Product").appendKeySegment(-10).build();
+    final String etag = getETag(uri);
+    final ODataEntity patch = client.getObjectFactory().newEntity(TEST_PRODUCT_TYPE);
+    patch.setEditLink(uri);
+    updateEntityDescription(format, patch, UpdateType.PATCH, etag);
+  }
+
+  @Test
+  public void replaceAsAtom() {
+    final ODataPubFormat format = ODataPubFormat.ATOM;
+    final ODataEntity changes = read(format, client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Car").appendKeySegment(14).build());
+    updateEntityDescription(format, changes, UpdateType.REPLACE);
+  }
+
+  @Test
+  public void replaceAsJSON() {
+    final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+    final ODataEntity changes = read(format, client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Car").appendKeySegment(14).build());
+    updateEntityDescription(format, changes, UpdateType.REPLACE);
+  }
+
+  @Test
+  public void patchLinkAsAtom() throws EdmPrimitiveTypeException {
+    patchLink(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void patchLinkAsJSON() throws EdmPrimitiveTypeException {
+    patchLink(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+  public void patchLink(final ODataPubFormat format) throws EdmPrimitiveTypeException {
+    final URI uri = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Customer").appendKeySegment(-10).build();
+
+    final ODataEntity patch = client.getObjectFactory().
+            newEntity(new FullQualifiedName("Microsoft.Test.OData.Services.AstoriaDefaultService.Customer"));
+    patch.setEditLink(uri);
+
+    // ---------------------------------------
+    // Update to CustomerInfo(12)
+    // ---------------------------------------
+    URI customerInfoURI = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("CustomerInfo").appendKeySegment(12).build();
+
+    patch.addLink(client.getObjectFactory().newEntityNavigationLink("Info", customerInfoURI));
+
+    update(UpdateType.PATCH, patch, format, null);
+
+    customerInfoURI = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Customer").appendKeySegment(-10).appendNavigationSegment("Info").build();
+
+    ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(customerInfoURI);
+    req.setFormat(format);
+
+    ODataEntity newInfo = req.execute().getBody();
+
+    assertEquals(Integer.valueOf(12),
+            newInfo.getProperty("CustomerInfoId").getPrimitiveValue().toCastValue(Integer.class));
+    // ---------------------------------------
+
+    // ---------------------------------------
+    // Restore to CustomerInfo(11)
+    // ---------------------------------------
+    patch.getNavigationLinks().clear();
+
+    customerInfoURI = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("CustomerInfo").appendKeySegment(11).build();
+    read(format, customerInfoURI);
+
+    patch.addLink(client.getObjectFactory().newEntityNavigationLink("Info", customerInfoURI));
+
+    update(UpdateType.PATCH, patch, format, null);
+
+    customerInfoURI = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Customer").appendKeySegment(-10).appendNavigationSegment("Info").build();
+
+    req = client.getRetrieveRequestFactory().getEntityRequest(customerInfoURI);
+    req.setFormat(format);
+
+    newInfo = req.execute().getBody();
+
+    assertEquals(Integer.valueOf(11),
+            newInfo.getProperty("CustomerInfoId").getPrimitiveValue().toCastValue(Integer.class));
+    // ---------------------------------------
+  }
+
+  private ODataEntityUpdateRequest<ODataEntity> buildMultiKeyUpdateReq(final ODataPubFormat format)
+          throws EdmPrimitiveTypeException {
+
+    final LinkedHashMap<String, Object> multiKey = new LinkedHashMap<String, Object>();
+    multiKey.put("FromUsername", "1");
+    multiKey.put("MessageId", -10);
+    final ODataEntity message = read(format, client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Message").appendKeySegment(multiKey).build());
+    message.getAssociationLinks().clear();
+    message.getNavigationLinks().clear();
+
+    final boolean before = message.getProperty("IsRead").getPrimitiveValue().toCastValue(Boolean.class);
+    message.getProperties().remove(message.getProperty("IsRead"));
+    getClient().getBinder().add(message,
+            client.getObjectFactory().newPrimitiveProperty("IsRead",
+                    client.getObjectFactory().newPrimitiveValueBuilder().buildBoolean(!before)));
+
+    return client.getCUDRequestFactory().getEntityUpdateRequest(UpdateType.MERGE, message);
+  }
+
+  private void mergeMultiKey(final ODataPubFormat format) throws EdmPrimitiveTypeException {
+    final ODataEntityUpdateResponse<ODataEntity> res = buildMultiKeyUpdateReq(format).execute();
+    assertEquals(204, res.getStatusCode());
+  }
+
+  @Test
+  public void mergeMultiKeyAsAtom() throws EdmPrimitiveTypeException {
+    mergeMultiKey(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void mergeMultiKeyAsJSON() throws EdmPrimitiveTypeException {
+    mergeMultiKey(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+  @Test
+  public void updateReturnContent() throws EdmPrimitiveTypeException {
+    final ODataEntityUpdateRequest<ODataEntity> req =
+            buildMultiKeyUpdateReq(client.getConfiguration().getDefaultPubFormat());
+    req.setPrefer(client.newPreferences().returnContent());
+
+    final ODataEntityUpdateResponse<ODataEntity> res = req.execute();
+    assertEquals(200, res.getStatusCode());
+    assertEquals(client.newPreferences().returnContent(),
+            res.getHeader(HeaderName.preferenceApplied).iterator().next());
+    assertNotNull(res.getBody());
+  }
+
+  @Test
+  public void concurrentModification() {
+    final URI uri = client.getURIBuilder(getServiceRoot()).
+            appendEntitySetSegment("Product").appendKeySegment(-10).build();
+    String etag = getETag(uri);
+    final ODataEntity product = client.getObjectFactory().newEntity(TEST_PRODUCT_TYPE);
+    product.setEditLink(uri);
+    updateEntityStringProperty("BaseConcurrency",
+            client.getConfiguration().getDefaultPubFormat(), product, UpdateType.MERGE, etag);
+
+    try {
+      etag += "-invalidone";
+      updateEntityStringProperty("BaseConcurrency",
+              client.getConfiguration().getDefaultPubFormat(), product, UpdateType.MERGE, etag);
+      fail();
+    } catch (ODataClientErrorException e) {
+      assertEquals(412, e.getStatusLine().getStatusCode());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v3/ErrorTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v3/ErrorTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v3/ErrorTestITCase.java
new file mode 100644
index 0000000..21fb8f8
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v3/ErrorTestITCase.java
@@ -0,0 +1,172 @@
+/*
+ * 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.v3;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.URI;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.olingo.client.api.communication.ODataClientErrorException;
+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.communication.response.ODataEntityCreateResponse;
+import org.apache.olingo.client.api.communication.response.ODataInvokeResponse;
+import org.apache.olingo.client.api.http.HttpMethod;
+import org.apache.olingo.client.api.uri.v3.URIBuilder;
+import org.apache.olingo.client.api.v3.ODataClient;
+import org.apache.olingo.client.core.communication.request.AbstractODataBasicRequest;
+import org.apache.olingo.client.core.communication.response.AbstractODataResponse;
+import org.apache.olingo.client.core.uri.URIUtils;
+import org.apache.olingo.commons.api.domain.v3.ODataEntity;
+import org.apache.olingo.commons.api.domain.v3.ODataEntitySet;
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmEntityContainer;
+import org.apache.olingo.commons.api.edm.EdmFunctionImport;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.junit.Test;
+
+/**
+ * This is the unit test class to check basic entity operations.
+ */
+public class ErrorTestITCase extends AbstractTestITCase {
+
+  private class ErrorGeneratingRequest
+          extends AbstractODataBasicRequest<ODataEntityCreateResponse<ODataEntity>, ODataPubFormat> {
+
+    public ErrorGeneratingRequest(final HttpMethod method, final URI uri) {
+      super(client, ODataPubFormat.class, method, uri);
+    }
+
+    @Override
+    protected InputStream getPayload() {
+      return new ByteArrayInputStream(new byte[0]);
+    }
+
+    @Override
+    public ODataEntityCreateResponse<ODataEntity> execute() {
+      final HttpResponse res = doExecute();
+      return new ErrorResponseImpl(client, httpClient, res);
+    }
+
+    private class ErrorResponseImpl extends AbstractODataResponse implements ODataEntityCreateResponse<ODataEntity> {
+
+      private final ODataClient odataClient;
+
+      public ErrorResponseImpl(final ODataClient odataClient, final HttpClient client, final HttpResponse res) {
+        super(client, res);
+        this.odataClient = odataClient;
+      }
+
+      @Override
+      public ODataEntity getBody() {
+        return odataClient.getObjectFactory().newEntity(new FullQualifiedName("Invalid.Invalid"));
+      }
+    }
+  }
+
+  private void stacktraceError(final ODataPubFormat format) {
+    final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL);
+    uriBuilder.appendEntitySetSegment("Customer");
+
+    final ErrorGeneratingRequest errorReq = new ErrorGeneratingRequest(HttpMethod.POST, uriBuilder.build());
+    errorReq.setFormat(format);
+
+    try {
+      errorReq.execute();
+      fail();
+    } catch (ODataClientErrorException e) {
+      LOG.error("ODataClientErrorException found", e);
+      assertEquals(400, e.getStatusLine().getStatusCode());
+      assertNotNull(e.getODataError());
+    }
+  }
+
+  @Test
+  public void xmlStacktraceError() {
+    stacktraceError(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void jsonStacktraceError() {
+    stacktraceError(ODataPubFormat.JSON);
+  }
+
+  private void notfoundError(final ODataPubFormat format) {
+    final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL);
+    uriBuilder.appendEntitySetSegment("Customer(154)");
+
+    final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(format);
+
+    try {
+      req.execute();
+      fail();
+    } catch (ODataClientErrorException e) {
+      LOG.error("ODataClientErrorException found", e);
+      assertEquals(404, e.getStatusLine().getStatusCode());
+      assertNull(e.getCause());
+      assertNotNull(e.getODataError());
+    }
+  }
+
+  @Test
+  public void xmlNotfoundError() {
+    notfoundError(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void jsonNotfoundError() {
+    notfoundError(ODataPubFormat.JSON);
+  }
+
+  private void instreamError(final ODataPubFormat format) {
+    final Edm metadata =
+            client.getRetrieveRequestFactory().getMetadataRequest(testStaticServiceRootURL).execute().getBody();
+    assertNotNull(metadata);
+
+    final EdmEntityContainer container = metadata.getSchemas().get(0).getEntityContainer();
+    final EdmFunctionImport funcImp = container.getFunctionImport("InStreamErrorGetCustomer");
+    final URIBuilder builder = client.getURIBuilder(testStaticServiceRootURL).
+            appendOperationCallSegment(URIUtils.operationImportURISegment(container, funcImp.getName()));
+    final ODataInvokeRequest<ODataEntitySet> req =
+            client.getInvokeRequestFactory().getInvokeRequest(builder.build(), funcImp.getUnboundFunction(null));
+    req.setFormat(format);
+
+    final ODataInvokeResponse<ODataEntitySet> res = req.execute();
+    res.getBody();
+    fail("Shouldn't get here");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void atomInstreamError() {
+    instreamError(ODataPubFormat.ATOM);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void jsonInstreamError() {
+    instreamError(ODataPubFormat.JSON);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v3/FilterFactoryTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v3/FilterFactoryTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v3/FilterFactoryTestITCase.java
new file mode 100644
index 0000000..2b447ad
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v3/FilterFactoryTestITCase.java
@@ -0,0 +1,167 @@
+/*
+ * 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.v3;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.olingo.commons.api.domain.CommonODataEntitySet;
+import org.apache.olingo.client.api.uri.URIFilter;
+import org.apache.olingo.client.api.uri.v3.FilterArgFactory;
+import org.apache.olingo.client.api.uri.v3.FilterFactory;
+import org.apache.olingo.client.api.uri.v3.URIBuilder;
+import org.junit.Test;
+
+public class FilterFactoryTestITCase extends AbstractTestITCase {
+
+  private FilterFactory getFilterFactory() {
+    return getClient().getFilterFactory();
+  }
+
+  private FilterArgFactory getFilterArgFactory() {
+    return getFilterFactory().getArgFactory();
+  }
+
+  private void match(final String entitySet, final URIFilter filter, final int expected) {
+    final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment(entitySet).filter(filter);
+
+    final CommonODataEntitySet feed = client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build()).
+            execute().getBody();
+    assertNotNull(feed);
+    assertEquals(expected, feed.getEntities().size());
+  }
+
+  @Test
+  public void simple() {
+    match("Car", getFilterFactory().lt("VIN", 16), 5);
+  }
+
+  @Test
+  public void and() {
+    final URIFilter filter =
+            getFilterFactory().and(
+            getFilterFactory().lt("VIN", 16),
+            getFilterFactory().gt("VIN", 12));
+
+    match("Car", filter, 3);
+  }
+
+  @Test
+  public void not() {
+    final URIFilter filter =
+            getFilterFactory().not(
+            getFilterFactory().or(
+            getFilterFactory().ge("VIN", 16),
+            getFilterFactory().le("VIN", 12)));
+
+    match("Car", filter, 3);
+  }
+
+  @Test
+  public void operator() {
+    URIFilter filter =
+            getFilterFactory().eq(
+            getFilterArgFactory().add(getFilterArgFactory().property("VIN"), getFilterArgFactory().
+            literal(1)),
+            getFilterArgFactory().literal(16));
+
+    match("Car", filter, 1);
+
+    filter =
+            getFilterFactory().eq(
+            getFilterArgFactory().add(getFilterArgFactory().literal(1), getFilterArgFactory().
+            property("VIN")),
+            getFilterArgFactory().literal(16));
+
+    match("Car", filter, 1);
+
+    filter =
+            getFilterFactory().eq(
+            getFilterArgFactory().literal(16),
+            getFilterArgFactory().add(getFilterArgFactory().literal(1), getFilterArgFactory().
+            property("VIN")));
+
+    match("Car", filter, 1);
+  }
+
+  @Test
+  public void function() {
+    final URIFilter filter =
+            getFilterFactory().match(
+            getFilterArgFactory().startswith(
+            getFilterArgFactory().property("Description"), getFilterArgFactory().literal("cen")));
+
+    match("Car", filter, 1);
+  }
+
+  @Test
+  public void composed() {
+    final URIFilter filter =
+            getFilterFactory().gt(
+            getFilterArgFactory().length(getFilterArgFactory().property("Description")),
+            getFilterArgFactory().add(getFilterArgFactory().property("VIN"), getFilterArgFactory().literal(
+            10)));
+
+    match("Car", filter, 5);
+  }
+
+  @Test
+  public void propertyPath() {
+    URIFilter filter =
+            getFilterFactory().eq(
+            getFilterArgFactory().indexof(
+            getFilterArgFactory().property("PrimaryContactInfo/HomePhone/PhoneNumber"),
+            getFilterArgFactory().literal("ODataJClient")),
+            getFilterArgFactory().literal(1));
+
+    match("Customer", filter, 0);
+
+    filter =
+            getFilterFactory().ne(
+            getFilterArgFactory().indexof(
+            getFilterArgFactory().property("PrimaryContactInfo/HomePhone/PhoneNumber"),
+            getFilterArgFactory().literal("lccvussrv")),
+            getFilterArgFactory().literal(-1));
+
+    match("Customer", filter, 2);
+  }
+
+  @Test
+  public void datetime() {
+    final URIFilter filter =
+            getFilterFactory().eq(
+            getFilterArgFactory().month(
+            getFilterArgFactory().property("PurchaseDate")),
+            getFilterArgFactory().literal(12));
+
+    match("ComputerDetail", filter, 1);
+  }
+
+  @Test
+  public void isof() {
+    final URIFilter filter =
+            getFilterFactory().match(
+            getFilterArgFactory().isof(
+            getFilterArgFactory().literal(
+            "Microsoft.Test.OData.Services.AstoriaDefaultService.SpecialEmployee")));
+
+    match("Person", filter, 4);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v3/FilterTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v3/FilterTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v3/FilterTestITCase.java
new file mode 100644
index 0000000..7d3bbdb
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v3/FilterTestITCase.java
@@ -0,0 +1,94 @@
+/*
+ * 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.v3;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.olingo.client.api.uri.v3.URIBuilder;
+import org.apache.olingo.commons.api.domain.v3.ODataEntitySet;
+import org.junit.Test;
+
+public class FilterTestITCase extends AbstractTestITCase {
+
+  private void filterQueryTest(final String entity, final String filter, final int expected) {
+    final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment(entity).filter(filter);
+    final ODataEntitySet entitySet = client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build()).
+            execute().getBody();
+    assertNotNull(entitySet);
+    assertEquals(expected, entitySet.getEntities().size());
+  }
+
+  @Test
+  public void withId() {
+    filterQueryTest("Customer", "CustomerId eq -10", 1);
+  }
+
+  @Test
+  public void logical() {
+    filterQueryTest("Customer", "CustomerId gt -10", 2);
+    filterQueryTest("Customer", "CustomerId lt -10", 0);
+    filterQueryTest("Customer", "not endswith(Name,'Chandan')", 2);
+    filterQueryTest("Car", "VIN le 18 and VIN gt 12", 6);
+  }
+
+  @Test
+  public void arithmetic() {
+    filterQueryTest("Car", "VIN add 5 lt 11", 0);
+    filterQueryTest("Car", "VIN div 2 le 8", 7);
+    filterQueryTest("Car", "VIN mul 2 le 30", 5);
+    filterQueryTest("Person", "PersonId sub 2 lt -10", 2);
+  }
+
+  @Test
+  public void stringOperations() {
+    filterQueryTest("Product", "length(Description) eq 7", 1);
+    filterQueryTest("Product", "length(Description) eq 7", 1);
+    filterQueryTest("Product", "substringof('kdcuklu', Description) eq true", 1);
+    filterQueryTest("Product", "startswith(Description, 'k') eq true", 2);
+    filterQueryTest("Product", "startswith(Description, 'k') eq true", 2);
+    filterQueryTest("Product", "indexof(Description, 'k') eq 0", 2);
+    filterQueryTest("Product", "toupper(Description) eq 'KDCUKLU'", 1);
+    filterQueryTest("Product", "concat(Description, ', newname') eq 'kdcuklu, newname'", 1);
+  }
+
+  @Test
+  public void math() {
+    filterQueryTest("Product", "round(Dimensions/Width) eq 7338", 1);
+    filterQueryTest("Product", "round(Dimensions/Width) eq 7338", 1);
+    filterQueryTest("Product", "floor(Dimensions/Width) eq 7337", 1);
+    filterQueryTest("Product", "ceiling(Dimensions/Width) eq 7338", 1);
+  }
+
+  @Test
+  public void date() {
+    filterQueryTest("ComputerDetail", "day(PurchaseDate) eq 15", 1);
+    filterQueryTest("ComputerDetail", "month(PurchaseDate) eq 12", 2);
+    filterQueryTest("ComputerDetail", "hour(PurchaseDate) eq 1", 1);
+    filterQueryTest("ComputerDetail", "minute(PurchaseDate) eq 33", 1);
+    filterQueryTest("ComputerDetail", "second(PurchaseDate) eq 35", 1);
+    filterQueryTest("ComputerDetail", "year(PurchaseDate) eq 2020", 1);
+  }
+
+  @Test
+  public void isOfTest() {
+    filterQueryTest("Customer", "isof(Name,'Edm.String') eq true", 2);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v3/InvokeTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v3/InvokeTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v3/InvokeTestITCase.java
new file mode 100644
index 0000000..02edf6e
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v3/InvokeTestITCase.java
@@ -0,0 +1,318 @@
+/*
+ * 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.v3;
+
+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.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.lang3.StringUtils;
+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.invoke.ODataInvokeRequest;
+import org.apache.olingo.client.api.communication.request.invoke.ODataNoContent;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+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.ODataInvokeResponse;
+import org.apache.olingo.client.api.uri.v3.URIBuilder;
+import org.apache.olingo.client.core.uri.URIUtils;
+import org.apache.olingo.commons.api.domain.ODataOperation;
+import org.apache.olingo.commons.api.domain.ODataPrimitiveValue;
+import org.apache.olingo.commons.api.domain.ODataValue;
+import org.apache.olingo.commons.api.domain.v3.ODataEntity;
+import org.apache.olingo.commons.api.domain.v3.ODataEntitySet;
+import org.apache.olingo.commons.api.domain.v3.ODataProperty;
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmAction;
+import org.apache.olingo.commons.api.edm.EdmEntityContainer;
+import org.apache.olingo.commons.api.edm.EdmFunction;
+import org.apache.olingo.commons.api.edm.EdmFunctionImport;
+import org.apache.olingo.commons.api.edm.EdmParameter;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.apache.olingo.commons.core.edm.EdmTypeInfo;
+import org.junit.Test;
+
+public class InvokeTestITCase extends AbstractTestITCase {
+
+  private void getWithNoParams(final ODataPubFormat format) {
+    final Edm edm = getClient().getRetrieveRequestFactory().
+            getMetadataRequest(testStaticServiceRootURL).execute().getBody();
+    assertNotNull(edm);
+
+    final EdmEntityContainer container = edm.getSchemas().get(0).getEntityContainer();
+
+    // 1. get primitive value property
+    EdmFunctionImport funcImp = container.getFunctionImport("GetPrimitiveString");
+    EdmFunction func = funcImp.getUnboundFunction(null);
+
+    URIBuilder builder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendOperationCallSegment(URIUtils.operationImportURISegment(container, funcImp.getName()));
+
+    ODataInvokeRequest<ODataProperty> req = getClient().getInvokeRequestFactory().
+            getInvokeRequest(builder.build(), func);
+    req.setFormat(format);
+    ODataInvokeResponse<ODataProperty> res = req.execute();
+    assertNotNull(res);
+
+    ODataProperty property = res.getBody();
+    assertNotNull(property);
+    assertEquals("Foo", property.getPrimitiveValue().toString());
+
+    // 2. get collection of complex type property
+    funcImp = container.getFunctionImport("EntityProjectionReturnsCollectionOfComplexTypes");
+    func = funcImp.getUnboundFunction(null);
+
+    builder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendOperationCallSegment(URIUtils.operationImportURISegment(container, funcImp.getName()));
+
+    req = getClient().getInvokeRequestFactory().getInvokeRequest(builder.build(), func);
+    req.setFormat(format);
+    res = req.execute();
+    assertNotNull(res);
+
+    property = res.getBody();
+    assertNotNull(property);
+    assertTrue(property.hasCollectionValue());
+    assertFalse(property.getCollectionValue().isEmpty());
+  }
+
+  @Test
+  public void getWithNoParamsAsAtom() {
+    getWithNoParams(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void getWithNoParamsAsJSON() {
+    getWithNoParams(ODataPubFormat.JSON);
+  }
+
+  private void getWithParams(final ODataPubFormat format) throws EdmPrimitiveTypeException {
+    // 1. primitive result
+    final Edm edm = getClient().getRetrieveRequestFactory().
+            getMetadataRequest(testStaticServiceRootURL).execute().getBody();
+    assertNotNull(edm);
+
+    final EdmEntityContainer container = edm.getSchemas().get(0).getEntityContainer();
+    EdmFunctionImport funcImp = container.getFunctionImport("GetArgumentPlusOne");
+
+    URIBuilder builder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendOperationCallSegment(URIUtils.operationImportURISegment(container, funcImp.getName()));
+
+    EdmFunction function = funcImp.getUnboundFunction(Collections.singletonList("arg1"));
+    EdmParameter param = function.getParameter(function.getParameterNames().get(0));
+    ODataPrimitiveValue paramValue = getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(param.getType()).
+            setValue(154).
+            build();
+
+    final ODataInvokeRequest<ODataProperty> primitiveReq = getClient().getInvokeRequestFactory().
+            getInvokeRequest(builder.build(), function,
+                    Collections.<String, ODataValue>singletonMap(param.getName(), paramValue));
+    primitiveReq.setFormat(format);
+
+    final ODataInvokeResponse<ODataProperty> primitiveRes = primitiveReq.execute();
+    assertNotNull(primitiveRes);
+
+    final ODataProperty property = primitiveRes.getBody();
+    assertNotNull(property);
+    assertEquals(Integer.valueOf(155), property.getPrimitiveValue().toCastValue(Integer.class));
+
+    // 2. feed result
+    funcImp = container.getFunctionImport("GetSpecificCustomer");
+
+    builder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendOperationCallSegment(URIUtils.operationImportURISegment(container, funcImp.getName()));
+
+    function = funcImp.getUnboundFunction(Collections.singletonList("Name"));
+    param = function.getParameter(function.getParameterNames().get(0));
+    paramValue = getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(param.getType()).
+            setValue(StringUtils.EMPTY).
+            build();
+
+    final ODataInvokeRequest<ODataEntitySet> feedReq = getClient().getInvokeRequestFactory().
+            getInvokeRequest(builder.build(), function,
+                    Collections.<String, ODataValue>singletonMap(param.getName(), paramValue));
+    feedReq.setFormat(format);
+
+    final ODataInvokeResponse<ODataEntitySet> feedRes = feedReq.execute();
+    assertNotNull(feedRes);
+
+    final ODataEntitySet feed = feedRes.getBody();
+    assertNotNull(feed);
+
+    final Set<Integer> customerIds = new HashSet<Integer>(feed.getEntities().size());
+    for (ODataEntity entity : feed.getEntities()) {
+      customerIds.add(entity.getProperty("CustomerId").getPrimitiveValue().toCastValue(Integer.class));
+    }
+    assertTrue(customerIds.contains(-8));
+  }
+
+  @Test
+  public void getWithParamsAsAtom() throws EdmPrimitiveTypeException {
+    getWithParams(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void getWithParamsAsJSON() throws EdmPrimitiveTypeException {
+    getWithParams(ODataPubFormat.JSON);
+  }
+
+  private ODataEntity createEmployee(final ODataPubFormat format) {
+    final ODataEntity employee = getClient().getObjectFactory().newEntity(new FullQualifiedName(
+            "Microsoft.Test.OData.Services.AstoriaDefaultService.Employee"));
+
+    employee.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("PersonId",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(1244)));
+    employee.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("Name",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("Test employee")));
+    employee.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty(
+            "ManagersPersonId", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(3777)));
+    employee.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty(
+            "Salary", getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(1000)));
+    employee.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty(
+            "Title", getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("CEO")));
+
+    final URIBuilder uriBuilder = getClient().getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Person");
+
+    final ODataEntityCreateRequest<ODataEntity> createReq =
+            getClient().getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), employee);
+    createReq.setFormat(format);
+    final ODataEntityCreateResponse<ODataEntity> createRes = createReq.execute();
+    assertEquals(201, createRes.getStatusCode());
+
+    final ODataEntityRequest<ODataEntity> req =
+            getClient().getRetrieveRequestFactory().getEntityRequest(uriBuilder.appendKeySegment(1244).build());
+    return req.execute().getBody();
+  }
+
+  private void deleteEmployee(final ODataPubFormat format, final Integer id) {
+    final URIBuilder uriBuilder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Person").appendKeySegment(id);
+
+    final ODataDeleteRequest deleteReq = getClient().getCUDRequestFactory().getDeleteRequest(uriBuilder.build());
+    deleteReq.setFormat(format);
+    final ODataDeleteResponse deleteRes = deleteReq.execute();
+    assertEquals(204, deleteRes.getStatusCode());
+  }
+
+  @Test
+  public void boundPost() throws EdmPrimitiveTypeException {
+    // 0. create an employee
+    final ODataEntity created = createEmployee(ODataPubFormat.JSON_FULL_METADATA);
+    assertNotNull(created);
+    final Integer createdId = created.getProperty("PersonId").getPrimitiveValue().toCastValue(Integer.class);
+    assertNotNull(createdId);
+
+    // 1. invoke action bound with the employee just created
+    final ODataOperation operation = created.getOperations().get(0);
+
+    final Edm edm = getClient().getRetrieveRequestFactory().
+            getMetadataRequest(testStaticServiceRootURL).execute().getBody();
+    assertNotNull(edm);
+
+    final EdmEntityContainer container = edm.getSchemas().get(0).getEntityContainer();
+    final EdmAction action = edm.getBoundAction(
+            new FullQualifiedName(container.getNamespace(), operation.getTitle()),
+            created.getTypeName(), false);
+
+    final ODataInvokeRequest<ODataNoContent> req = getClient().getInvokeRequestFactory().
+            getInvokeRequest(operation.getTarget(), action);
+    req.setFormat(ODataPubFormat.JSON_FULL_METADATA);
+    final ODataInvokeResponse<ODataNoContent> res = req.execute();
+    assertNotNull(res);
+    assertEquals(204, res.getStatusCode());
+
+    // 2. check that invoked action has effectively run
+    final URIBuilder uriBuilder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Person").appendKeySegment(createdId);
+    final ODataEntityRequest<ODataEntity> retrieveRes =
+            getClient().getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    retrieveRes.setFormat(ODataPubFormat.JSON_FULL_METADATA);
+    final ODataEntity read = retrieveRes.execute().getBody();
+    assertEquals("0", read.getProperty("Salary").getPrimitiveValue().toString());
+    assertTrue(read.getProperty("Title").getPrimitiveValue().toString().endsWith("[Sacked]"));
+
+    // 3. remove the test employee
+    deleteEmployee(ODataPubFormat.JSON_FULL_METADATA, createdId);
+  }
+
+  @Test
+  public void boundPostWithParams() throws EdmPrimitiveTypeException {
+    // 1. read employees and store their current salary
+    final URIBuilder builder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Person").
+            appendEntitySetSegment("Microsoft.Test.OData.Services.AstoriaDefaultService.Employee");
+    final URI employeesURI = builder.build();
+    ODataEntitySet employees = getClient().getRetrieveRequestFactory().
+            getEntitySetRequest(employeesURI).execute().getBody();
+    assertFalse(employees.getEntities().isEmpty());
+    final Map<Integer, Integer> preSalaries = new HashMap<Integer, Integer>(employees.getCount());
+    for (ODataEntity employee : employees.getEntities()) {
+      preSalaries.put(employee.getProperty("PersonId").getPrimitiveValue().toCastValue(Integer.class),
+              employee.getProperty("Salary").getPrimitiveValue().toCastValue(Integer.class));
+    }
+    assertFalse(preSalaries.isEmpty());
+
+    // 2. invoke action bound, with additional parameter
+    final Edm edm = getClient().getRetrieveRequestFactory().
+            getMetadataRequest(testStaticServiceRootURL).execute().getBody();
+    assertNotNull(edm);
+
+    final EdmEntityContainer container = edm.getSchemas().get(0).getEntityContainer();
+
+    final EdmTypeInfo employeesTypeInfo = new EdmTypeInfo.Builder().setEdm(edm).
+            setTypeExpression("Collection(Microsoft.Test.OData.Services.AstoriaDefaultService.Employee)").build();
+    final EdmAction action = edm.getBoundAction(
+            new FullQualifiedName(container.getNamespace(), "IncreaseSalaries"),
+            employeesTypeInfo.getFullQualifiedName(), employeesTypeInfo.isCollection());
+
+    final EdmParameter param = action.getParameter(action.getParameterNames().get(1));
+    final ODataPrimitiveValue paramValue = getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(param.getType()).
+            setValue(1).
+            build();
+
+    final ODataInvokeRequest<ODataNoContent> req = getClient().getInvokeRequestFactory().getInvokeRequest(
+            builder.appendOperationCallSegment(action.getName()).build(), action,
+            Collections.<String, ODataValue>singletonMap(param.getName(), paramValue));
+    final ODataInvokeResponse<ODataNoContent> res = req.execute();
+    assertNotNull(res);
+    assertEquals(204, res.getStatusCode());
+
+    // 3. check whether salaries were incremented
+    employees = getClient().getRetrieveRequestFactory().getEntitySetRequest(employeesURI).execute().getBody();
+    assertFalse(employees.getEntities().isEmpty());
+    for (ODataEntity employee : employees.getEntities()) {
+      assertTrue(
+              preSalaries.get(employee.getProperty("PersonId").getPrimitiveValue().toCastValue(Integer.class))
+              < employee.getProperty("Salary").getPrimitiveValue().toCastValue(Integer.class));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v3/KeyAsSegmentTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v3/KeyAsSegmentTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v3/KeyAsSegmentTestITCase.java
new file mode 100644
index 0000000..7a1bebc
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v3/KeyAsSegmentTestITCase.java
@@ -0,0 +1,110 @@
+/*
+ * 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.v3;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.olingo.client.api.communication.request.cud.v3.UpdateType;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.uri.v3.URIBuilder;
+import org.apache.olingo.commons.api.domain.v3.ODataEntity;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class KeyAsSegmentTestITCase extends AbstractTestITCase {
+
+  @BeforeClass
+  public static void enableKeyAsSegment() {
+    client.getConfiguration().setKeyAsSegment(true);
+  }
+
+  private void read(final ODataPubFormat format) {
+    final URIBuilder uriBuilder = client.getURIBuilder(testKeyAsSegmentServiceRootURL).
+            appendEntitySetSegment("Customer").appendKeySegment(-10);
+
+    final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(format);
+
+    final ODataRetrieveResponse<ODataEntity> res = req.execute();
+    final ODataEntity entity = res.getBody();
+    assertNotNull(entity);
+
+    assertFalse(entity.getEditLink().toASCIIString().contains("("));
+    assertFalse(entity.getEditLink().toASCIIString().contains(")"));
+  }
+
+  @Test
+  public void fromAtom() {
+    read(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void fromJSON() {
+    read(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+  @Test
+  public void createODataEntityAsAtom() {
+    final ODataPubFormat format = ODataPubFormat.ATOM;
+    final int id = 1;
+    final ODataEntity original = getSampleCustomerProfile(id, "Sample customer", false);
+
+    createEntity(testKeyAsSegmentServiceRootURL, format, original, "Customer");
+    final ODataEntity actual = compareEntities(testKeyAsSegmentServiceRootURL, format, original, id, null);
+
+    cleanAfterCreate(format, actual, false, testKeyAsSegmentServiceRootURL);
+  }
+
+  @Test
+  public void createODataEntityAsJSON() {
+    final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+    final int id = 2;
+    final ODataEntity original = getSampleCustomerProfile(id, "Sample customer", false);
+
+    createEntity(testKeyAsSegmentServiceRootURL, format, original, "Customer");
+    final ODataEntity actual = compareEntities(testKeyAsSegmentServiceRootURL, format, original, id, null);
+
+    cleanAfterCreate(format, actual, false, testKeyAsSegmentServiceRootURL);
+  }
+
+  @Test
+  public void replaceODataEntityAsAtom() {
+    final ODataPubFormat format = ODataPubFormat.ATOM;
+    final ODataEntity changes = read(format, client.getURIBuilder(testKeyAsSegmentServiceRootURL).
+            appendEntitySetSegment("Car").appendKeySegment(14).build());
+    updateEntityDescription(format, changes, UpdateType.REPLACE);
+  }
+
+  @Test
+  public void replaceODataEntityAsJSON() {
+    final ODataPubFormat format = ODataPubFormat.JSON_FULL_METADATA;
+    final ODataEntity changes = read(format, client.getURIBuilder(testKeyAsSegmentServiceRootURL).
+            appendEntitySetSegment("Car").appendKeySegment(14).build());
+    updateEntityDescription(format, changes, UpdateType.REPLACE);
+  }
+
+  @AfterClass
+  public static void disableKeyAsSegment() {
+    client.getConfiguration().setKeyAsSegment(false);
+  }
+}