You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by sk...@apache.org on 2014/05/23 12:58:47 UTC

[52/59] [abbrv] git commit: [OLINGO-286] fixed: provided intengration test for '13.2 Interoperable OData Clients'

[OLINGO-286] fixed: provided intengration test for '13.2 Interoperable OData Clients'


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/259eb078
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/259eb078
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/259eb078

Branch: refs/heads/olingo-266-tecsvc
Commit: 259eb07851593ba863ac820c2fa2e40d5e792b56
Parents: a57926b
Author: fmartelli <fa...@gmail.com>
Authored: Thu May 22 17:04:04 2014 +0200
Committer: fmartelli <fa...@gmail.com>
Committed: Thu May 22 17:04:04 2014 +0200

----------------------------------------------------------------------
 .../java/org/apache/olingo/fit/V4Services.java  |  32 +-
 .../olingo/fit/utils/AbstractUtilities.java     |   5 +-
 fit/src/main/resources/esigate.properties       |   2 +-
 .../olingo/fit/proxy/v4/AbstractTestITCase.java |   2 +-
 .../olingo/fit/v3/AbstractTestITCase.java       |   2 +-
 .../olingo/fit/v4/AbstractTestITCase.java       |   2 +-
 .../olingo/fit/v4/ConformanceTestITCase.java    | 420 +++++++++++++++++++
 7 files changed, 448 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/main/java/org/apache/olingo/fit/V4Services.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/V4Services.java b/fit/src/main/java/org/apache/olingo/fit/V4Services.java
index db88da0..e4a2c73 100644
--- a/fit/src/main/java/org/apache/olingo/fit/V4Services.java
+++ b/fit/src/main/java/org/apache/olingo/fit/V4Services.java
@@ -114,6 +114,16 @@ public class V4Services extends AbstractServices {
   }
 
   @GET
+  @Path("/redirect/{name}({id})")
+  public Response conformanceRedirect(
+          @Context UriInfo uriInfo,
+          @PathParam("name") String name,
+          @PathParam("id") String id) {
+    return Response.temporaryRedirect(
+            URI.create(uriInfo.getRequestUri().toASCIIString().replace("/redirect", ""))).build();
+  }
+
+  @GET
   @Path("/$crossjoin({elements:.*})")
   public Response crossjoin(
           @PathParam("elements") String elements,
@@ -364,7 +374,7 @@ public class V4Services extends AbstractServices {
     return StringUtils.isBlank(filter) && StringUtils.isBlank(search)
             ? NumberUtils.isNumber(type)
             ? super.getEntityInternal(
-                    uriInfo.getRequestUri().toASCIIString(), accept, "People", type, format, null, null, true)
+            uriInfo.getRequestUri().toASCIIString(), accept, "People", type, format, null, null, true)
             : super.getEntitySet(accept, "People", type)
             : super.getEntitySet(uriInfo, accept, "People", top, skip, format, count, filter, orderby, skiptoken);
   }
@@ -668,7 +678,7 @@ public class V4Services extends AbstractServices {
           @PathParam("entityId") String entityId,
           @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) {
 
-    return getContainedEntity(accept, entityId, "MyPaymentInstruments", entityId+ "901", format);
+    return getContainedEntity(accept, entityId, "MyPaymentInstruments", entityId + "901", format);
   }
 
   @GET
@@ -738,7 +748,7 @@ public class V4Services extends AbstractServices {
 
       return utils.getValue().createResponse(
               FSManager.instance(version).readFile(Constants.get(version, ConstantKey.REF)
-                      + File.separatorChar + filename, utils.getKey()),
+              + File.separatorChar + filename, utils.getKey()),
               null,
               utils.getKey());
     } catch (Exception e) {
@@ -760,7 +770,7 @@ public class V4Services extends AbstractServices {
 
     final Response response =
             getEntityInternal(uriInfo.getRequestUri().toASCIIString(),
-                    accept, entitySetName, entityId, accept, StringUtils.EMPTY, StringUtils.EMPTY, false);
+            accept, entitySetName, entityId, accept, StringUtils.EMPTY, StringUtils.EMPTY, false);
     return response.getStatus() >= 400
             ? postNewEntity(uriInfo, accept, contentType, prefer, entitySetName, changes)
             : super.patchEntity(uriInfo, accept, contentType, prefer, ifMatch, entitySetName, entityId, changes);
@@ -858,8 +868,8 @@ public class V4Services extends AbstractServices {
       } else {
         final ResWrap<JSONEntityImpl> jcontainer =
                 mapper.readValue(IOUtils.toInputStream(entity, Constants.ENCODING),
-                        new TypeReference<JSONEntityImpl>() {
-                        });
+                new TypeReference<JSONEntityImpl>() {
+        });
 
         entry = dataBinder.toAtomEntity(jcontainer.getPayload());
 
@@ -957,7 +967,7 @@ public class V4Services extends AbstractServices {
 
         final ResWrap<JSONEntityImpl> jsonContainer = mapper.readValue(
                 IOUtils.toInputStream(changes, Constants.ENCODING), new TypeReference<JSONEntityImpl>() {
-                });
+        });
         jsonContainer.getPayload().setType(typeInfo.getFullQualifiedName().toString());
         entryChanges = dataBinder.toAtomEntity(jsonContainer.getPayload());
       }
@@ -991,7 +1001,7 @@ public class V4Services extends AbstractServices {
       // 1. Fetch the contained entity to be removed
       final InputStream entry = FSManager.instance(version).
               readFile(containedPath(entityId, containedEntitySetName).
-                      append('(').append(containedEntityId).append(')').toString(), Accept.ATOM);
+              append('(').append(containedEntityId).append(')').toString(), Accept.ATOM);
       final ResWrap<AtomEntityImpl> container = atomDeserializer.read(entry, AtomEntityImpl.class);
 
       // 2. Remove the contained entity
@@ -1237,8 +1247,8 @@ public class V4Services extends AbstractServices {
       } else {
         final ResWrap<JSONPropertyImpl> paramContainer =
                 mapper.readValue(IOUtils.toInputStream(param, Constants.ENCODING),
-                        new TypeReference<JSONPropertyImpl>() {
-                        });
+                new TypeReference<JSONPropertyImpl>() {
+        });
         property = paramContainer.getPayload();
       }
 
@@ -1278,7 +1288,7 @@ public class V4Services extends AbstractServices {
 
       final ResWrap<AtomPropertyImpl> result = new ResWrap<AtomPropertyImpl>(
               URI.create(Constants.get(version, ConstantKey.ODATA_METADATA_PREFIX)
-                      + "Microsoft.Test.OData.Services.ODataWCFService.Address"),
+              + "Microsoft.Test.OData.Services.ODataWCFService.Address"),
               null,
               (AtomPropertyImpl) entity.getProperty("address"));
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
----------------------------------------------------------------------
diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
index 00259321..0c60609 100644
--- a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
+++ b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java
@@ -367,7 +367,8 @@ public abstract class AbstractUtilities {
 
     final Map<String, NavigationProperty> navigationProperties = metadata.getNavigationProperties(entitySetName);
 
-    if (navigationProperties.get(linkName).isEntitySet()) {
+    // check for nullability in order to support navigation property on open types
+    if (navigationProperties.get(linkName) != null && navigationProperties.get(linkName).isEntitySet()) {
       try {
         final Map.Entry<String, List<String>> currents = extractLinkURIs(entitySetName, entityKey, linkName);
         uris.addAll(currents.getValue());
@@ -701,7 +702,7 @@ public abstract class AbstractUtilities {
                   + ",ProductID=" + entity.getProperty("ProductID").getValue().asPrimitive().get();
         }
         Commons.SEQUENCE.put(entitySetName, productID);
-      }else if ("Message".equals(entitySetName)) {
+      } else if ("Message".equals(entitySetName)) {
         int messageId;
         if (entity.getProperty("MessageId") == null || entity.getProperty("FromUsername") == null) {
           if (Commons.SEQUENCE.containsKey(entitySetName)) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/main/resources/esigate.properties
----------------------------------------------------------------------
diff --git a/fit/src/main/resources/esigate.properties b/fit/src/main/resources/esigate.properties
index 38c4450..0db861a 100644
--- a/fit/src/main/resources/esigate.properties
+++ b/fit/src/main/resources/esigate.properties
@@ -17,7 +17,7 @@
 # under the License.
 #
 
-webapp.remoteUrlBase=http://localhost:${cargo.servlet.port}/stub/StaticService/V30/Static.svc/
+webapp.remoteUrlBase=http://localhost:${cargo.servlet.port}/stub/StaticService/
 visibleUrlBase=http://localhost:${cargo.servlet.port}/stub/DefaultService.svc/
 useCache=true
 extensions=org.apache.olingo.fit.rproxy.LinkRewrite

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java
index 4efc7d0..d3301e8 100644
--- a/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/proxy/v4/AbstractTestITCase.java
@@ -75,7 +75,7 @@ public abstract class AbstractTestITCase {
     testActionOverloadingServiceRootURL = "http://localhost:9080/stub/StaticService/V40/ActionOverloading.svc";
     testOpenTypeServiceRootURL = "http://localhost:9080/stub/StaticService/V40/OpenType.svc";
     testLargeModelServiceRootURL = "http://localhost:9080/stub/StaticService/V40/Static.svc/large";
-    testAuthServiceRootURL = "http://localhost:9080/stub/DefaultService.svc";
+    testAuthServiceRootURL = "http://localhost:9080/stub/DefaultService.svc/V40/Static.svc";
 
     containerFactory = EntityContainerFactory.getV4(testStaticServiceRootURL);
     containerFactory.getClient().getConfiguration().setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/test/java/org/apache/olingo/fit/v3/AbstractTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v3/AbstractTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v3/AbstractTestITCase.java
index d9bf300..aacecdc 100644
--- a/fit/src/test/java/org/apache/olingo/fit/v3/AbstractTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/v3/AbstractTestITCase.java
@@ -93,7 +93,7 @@ public abstract class AbstractTestITCase extends AbstractBaseTestITCase {
     testActionOverloadingServiceRootURL = "http://localhost:9080/stub/StaticService/V30/ActionOverloading.svc";
     testOpenTypeServiceRootURL = "http://localhost:9080/stub/StaticService/V30/OpenType.svc";
     testLargeModelServiceRootURL = "http://localhost:9080/stub/StaticService/V30/Static.svc/large";
-    testAuthServiceRootURL = "http://localhost:9080/stub/DefaultService.svc";
+    testAuthServiceRootURL = "http://localhost:9080/stub/DefaultService.svc/V30/Static.svc";
     
     client.getConfiguration().setDefaultBatchAcceptFormat(ContentType.APPLICATION_OCTET_STREAM);
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java
index 32a6e19..31619e3 100644
--- a/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java
@@ -73,7 +73,7 @@ public abstract class AbstractTestITCase extends AbstractBaseTestITCase {
     testKeyAsSegmentServiceRootURL = "http://localhost:9080/stub/StaticService/V40/KeyAsSegment.svc";
     testOpenTypeServiceRootURL = "http://localhost:9080/stub/StaticService/V40/OpenType.svc";
     testLargeModelServiceRootURL = "http://localhost:9080/stub/StaticService/V40/Static.svc/large";
-    testAuthServiceRootURL = "http://localhost:9080/stub/DefaultService.svc";
+    testAuthServiceRootURL = "http://localhost:9080/stub/DefaultService.svc/V40/Static.svc";
 
     edmClient = ODataClientFactory.getEdmEnabledV4(testStaticServiceRootURL);
     

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/259eb078/fit/src/test/java/org/apache/olingo/fit/v4/ConformanceTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/ConformanceTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/ConformanceTestITCase.java
new file mode 100644
index 0000000..7e95014
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v4/ConformanceTestITCase.java
@@ -0,0 +1,420 @@
+/*
+ * 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.v4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Test;
+import java.net.URI;
+
+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.ODataEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.request.cud.v4.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.request.retrieve.v4.ODataDeltaRequest;
+import org.apache.olingo.client.api.communication.request.v4.AsyncRequestWrapper;
+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.communication.response.v4.AsyncResponseWrapper;
+import org.apache.olingo.client.api.uri.CommonURIBuilder;
+import org.apache.olingo.client.api.uri.v4.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.domain.ODataCollectionValue;
+import org.apache.olingo.commons.api.domain.v4.ODataDelta;
+import org.apache.olingo.commons.api.domain.v4.ODataEntity;
+import org.apache.olingo.commons.api.domain.v4.ODataEntitySet;
+import org.apache.olingo.commons.api.domain.v4.ODataProperty;
+import org.apache.olingo.commons.api.domain.v4.ODataValue;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.apache.olingo.commons.core.domain.v4.ODataEntityImpl;
+
+/**
+ * 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<ODataEntity> req =
+            client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+
+    assertEquals("4.0", req.getHeader("OData-MaxVersion"));
+    assertEquals("4.0", req.getHeader(HeaderName.odataMaxVersion.toString()));
+
+    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 ODataEntity order =
+            new ODataEntityImpl(new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Order"));
+
+    final ODataProperty orderId = getClient().getObjectFactory().newPrimitiveProperty("OrderID",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(2000));
+    order.getProperties().add(orderId);
+
+    final ODataProperty orderDate = getClient().getObjectFactory().newPrimitiveProperty("OrderDate",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.DateTimeOffset).setText("2011-03-04T16:03:57Z").build());
+    order.getProperties().add(orderDate);
+
+    final ODataProperty shelfLife = getClient().getObjectFactory().newPrimitiveProperty("ShelfLife",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.Duration).setText("PT0.0000001S").build());
+    order.getProperties().add(shelfLife);
+
+    final ODataCollectionValue<ODataValue> orderShelfLifesValue = getClient().getObjectFactory().
+            newCollectionValue("Collection(Duration)");
+    orderShelfLifesValue.add(getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.Duration).setText("PT0.0000001S").build());
+    orderShelfLifesValue.add(getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.Duration).setText("PT0.0000002S").build());
+    final ODataProperty orderShelfLifes = getClient().getObjectFactory().
+            newCollectionProperty("OrderShelfLifes", orderShelfLifesValue);
+    order.getProperties().add(orderShelfLifes);
+
+    final ODataEntityCreateRequest<ODataEntity> req = getClient().getCUDRequestFactory().getEntityCreateRequest(
+            getClient().newURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Orders").build(), order);
+    req.setFormat(ODataPubFormat.JSON_FULL_METADATA);
+
+    // check for OData-Version
+    assertEquals("4.0", req.getHeader("OData-Version"));
+    assertEquals("4.0", req.getHeader(HeaderName.odataVersion.toString()));
+
+    // check for Content-Type
+    assertEquals(
+            ODataPubFormat.JSON_FULL_METADATA.toString(ODataServiceVersion.V40),
+            req.getHeader("Content-Type"));
+    assertEquals(
+            ODataPubFormat.JSON_FULL_METADATA.toString(ODataServiceVersion.V40),
+            req.getHeader(HeaderName.contentType.toString()));
+    assertEquals(
+            ODataPubFormat.JSON_FULL_METADATA.toString(ODataServiceVersion.V40),
+            req.getContentType());
+
+    final ODataEntity 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<ODataEntity> req =
+            client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+
+    assertEquals("4.0", req.getHeader("OData-MaxVersion"));
+    assertEquals("4.0", req.getHeader(HeaderName.odataMaxVersion.toString()));
+
+    final ODataRetrieveResponse<ODataEntity> res = req.execute();
+    final ODataEntity 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<ODataEntitySet> req = client.getRetrieveRequestFactory().
+            getEntitySetRequest(uriBuilder.build());
+    req.setFormat(ODataPubFormat.JSON_FULL_METADATA);
+    req.setPrefer(client.newPreferences().maxPageSize(5));
+
+    ODataRetrieveResponse<ODataEntitySet> res = req.execute();
+    ODataEntitySet 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(ODataPubFormat.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;
+
+    ODataEntity 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<ODataEntity> createReq = getClient().getCUDRequestFactory().
+            getEntityCreateRequest(getClient().newURIBuilder(testOpenTypeServiceRootURL).
+            appendEntitySetSegment("RowIndex").build(), rowIndex);
+
+    final ODataEntityCreateResponse<ODataEntity> createRes = createReq.execute();
+    assertEquals(201, createRes.getStatusCode());
+
+    final URIBuilder builder = getClient().newURIBuilder(testOpenTypeServiceRootURL).
+            appendEntitySetSegment("RowIndex").appendKeySegment(id);
+
+
+    rowIndex = read(ODataPubFormat.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 ODataEntity 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<ODataEntity> req =
+            getClient().getCUDRequestFactory().getEntityUpdateRequest(UpdateType.PATCH, patch);
+
+    final ODataEntityUpdateResponse<ODataEntity> res = req.execute();
+    assertEquals(204, res.getStatusCode());
+
+    final ODataEntity actual = read(ODataPubFormat.JSON, uri);
+
+    assertEquals(newname, actual.getProperty("FirstName").getValue().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 CommonURIBuilder<?> uriBuilder = client.newURIBuilder(testAuthServiceRootURL).
+            appendEntitySetSegment("Customers").appendKeySegment(1).expand("Company");
+
+    final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(ODataPubFormat.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<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(ODataPubFormat.JSON_FULL_METADATA);
+
+    ODataRetrieveResponse<ODataEntity> res = req.execute();
+    assertNotNull(res);
+
+    final ODataEntity entity = res.getBody();
+    assertNotNull(entity);
+    assertTrue(entity.getReference().endsWith("/StaticService/V40/Static.svc/Customers(PersonID=1)"));
+
+    final URI referenceURI =
+            client.newURIBuilder(testStaticServiceRootURL).appendEntityIdSegment(entity.getReference()).build();
+
+    req = client.getRetrieveRequestFactory().getEntityRequest(referenceURI);
+    req.setFormat(ODataPubFormat.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<ODataEntitySet> req = client.getRetrieveRequestFactory().getEntitySetRequest(
+            client.newURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").build());
+    req.setPrefer(client.newPreferences().trackChanges());
+
+    final ODataEntitySet customers = req.execute().getBody();
+    assertNotNull(customers);
+    assertNotNull(customers.getDeltaLink());
+
+    final ODataDeltaRequest deltaReq = client.getRetrieveRequestFactory().getDeltaRequest(customers.getDeltaLink());
+    deltaReq.setFormat(ODataPubFormat.JSON_FULL_METADATA);
+
+    final ODataDelta 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());
+    ODataProperty 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<ODataEntitySet> req =
+            client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build());
+    req.setFormat(ODataPubFormat.JSON_FULL_METADATA);
+
+    final AsyncRequestWrapper<ODataRetrieveResponse<ODataEntitySet>> async =
+            client.getAsyncRequestFactory().<ODataRetrieveResponse<ODataEntitySet>>getAsyncRequestWrapper(req);
+    async.callback(URI.create("http://client.service.it/callback/endpoint"));
+
+    final AsyncResponseWrapper<ODataRetrieveResponse<ODataEntitySet>> responseWrapper = async.execute();
+
+    assertTrue(responseWrapper.isPreferenceApplied());
+    assertTrue(responseWrapper.isDone());
+
+    final ODataRetrieveResponse<ODataEntitySet> res = responseWrapper.getODataResponse();
+    final ODataEntitySet 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<ODataEntity> req =
+            client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(ODataPubFormat.JSON);
+
+    assertEquals("application/json;odata.metadata=minimal", req.getHeader("Accept"));
+    assertEquals("application/json;odata.metadata=minimal", req.getHeader(HeaderName.accept.toString()));
+    assertEquals("application/json;odata.metadata=minimal", req.getAccept());
+
+    final ODataRetrieveResponse<ODataEntity> res = req.execute();
+    assertTrue(res.getContentType().startsWith("application/json; odata.metadata=minimal"));
+
+    assertNotNull(res.getBody());
+  }
+}