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

[03/51] [partial] rename folder /datajs into /odatajs. no file modification.

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-read-crossdomain-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-read-crossdomain-functional-tests.js b/odatajs/tests/odata-read-crossdomain-functional-tests.js
new file mode 100644
index 0000000..9e8aca9
--- /dev/null
+++ b/odatajs/tests/odata-read-crossdomain-functional-tests.js
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    var fixConstructors = function (obj) {
+        /** Fix the constructors of the supplied object graph.
+        */
+        
+        /// When using IE9 or a non-IE browser, the JSONP support in the library creates objects in a separate IFRAME,
+        /// causing the constructor property to be different to that of objects created by the oracle. This function
+        /// stringifies and then re-parses the object, which fixes the constructors.
+        
+        if (!window.ActiveXObject || window.DOMParser) {
+            return window.JSON.parse(window.JSON.stringify(obj));
+        } else {
+            return obj;
+        }
+    };
+
+    var handlerAcceptStrings = [
+        "*/*",
+        "application/json",
+        undefined
+    ];
+
+    var formatJsonStrings = [
+        "application/json",
+        "application/json;odata.metadata=none",
+        "application/json;odata.metadata=minimal",
+        "application/json;odata.metadata=full", // to do: all the full metadata scenarios fail currently, need to fix.
+        undefined
+    ];
+    var azureOdataService = "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/";
+    var azureOdataFeed = azureOdataService + "Categories";
+    var crossDomainTimeout = 45000;
+
+    module("CrossDomain", {
+        setup: function () {
+            this.oldEnableJsonpCallback = window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback;
+            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = true;
+        },
+        teardown: function () {
+            window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = this.oldEnableJsonpCallback;
+        }
+    });
+
+    for (var i = 0; i < handlerAcceptStrings.length; i++) {
+        for (var j = 0; j < formatJsonStrings.length; j++) {
+            djstest.addTest(function readCrossDomainFullFeedTest(params) {
+                djstest.assertsExpected(1);
+                var request = { requestUri: azureOdataFeed, headers: { Accept: params.handlerAccept}, enableJsonpCallback: true };
+                if (params.formatJsonString != undefined) {
+                    request.formatQueryString = "$format=" + params.formatJsonString;
+                }
+
+                djstest.log("Reading data over the wire.");
+                odatajs.oData.read(request, function (data, response) {
+                    djstest.log("Verifying data over the wire from Oracle.");
+                    window.ODataReadOracle.readFeed(azureOdataFeed, function (expectedData) {
+                        data = fixConstructors(data);
+                        djstest.assertWithoutMetadata(data, expectedData, "Response data not same as expected");
+                        djstest.done();
+                    }, params.formatJsonString);
+                }, unexpectedErrorHandler);
+            }, "Testing valid read of cross domain feed collection with " + handlerAcceptStrings[i] + "," + formatJsonStrings[j], { handlerAccept: handlerAcceptStrings[i], formatJsonString: formatJsonStrings[j] }, crossDomainTimeout);
+        }
+
+        djstest.addTest(function readCrossDomainEntryTest(handlerAccept) {
+            var endPoint = azureOdataFeed + "(1)";
+            djstest.assertsExpected(1);
+            djstest.log("Reading data over the wire.");
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} }, function (data, response) {
+                djstest.log("Verifying data over the wire from Oracle.");
+                window.ODataReadOracle.readEntry(endPoint, function (expectedData) {
+                    data = fixConstructors(data);
+                    djstest.assertWithoutMetadata(data, expectedData, "Response data not same as expected");
+                    djstest.done();
+                }, "application/json");
+            }, unexpectedErrorHandler);
+        }, "Testing valid read of cross domain entry with " + handlerAcceptStrings[i], handlerAcceptStrings[i], crossDomainTimeout);
+    }
+
+    var prefetchSizes = [-1, 0, 15];
+    var cacheSizes = [-1, 0, 15];
+    var skipValues = [
+        0,
+        14, // < pageSize
+        15, // = pageSize
+        16 // > pageSize but < pageSize + prefetchSize
+    ];
+
+    var createTestName = function (params) {
+        return "Testing ReadRange of " + params.feed + " skip " + params.skip + " take " + params.take + " with pageSize " +
+            params.pageSize + ", prefetch " + params.prefetchSize + " and cacheSize " + params.cacheSize;
+    };
+
+    var dataCacheReadRangeSingleTest = function (params) {
+        var options = { name: "cache", source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize, cacheSize: params.cacheSize };
+        window.odatajs.oData.net.defaultHttpClient.enableJsonpCallback = true;
+        var cache = odatajs.cache.createDataCache(options);
+        cache.readRange(params.skip, params.take).then(function (data) {
+            validateExpectedRange(cache, data, params.feed, params.skip, params.take);
+        }, unexpectedErrorHandler);
+    };
+
+    var validateExpectedRange = function (cache, data, feed, skipValue, takeValue) {
+        var expectedRangeUrl = feed + "?$skip=" + skipValue + "&$top=" + takeValue;
+        window.ODataReadOracle.readFeed(expectedRangeUrl, function (expectedData) {
+            if (expectedData.results) {
+                expectedData = expectedData.results;
+            }
+            data = fixConstructors(data);
+            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+            djstest.destroyCacheAndDone(cache);
+        });
+    };
+
+    $.each(prefetchSizes, function (_, prefetchSizeValue) {
+        $.each(cacheSizes, function (_, cacheSizeValue) {
+            var parameters = { feed: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/Categories", skip: 0, take: 5, pageSize: 15, prefetchSize: prefetchSizeValue, cacheSize: cacheSizeValue };
+            djstest.addTest(dataCacheReadRangeSingleTest, createTestName(parameters), parameters);
+        });
+    });
+
+    $.each(skipValues, function (_, skipValue) {
+        var parameters = { feed: "http://odatasampleservices.azurewebsites.net/V4/OData/OData.svc/Categories", skip: skipValue, take: 14, pageSize: 5, prefetchSize: 5, cacheSize: 5 };
+        djstest.addTest(dataCacheReadRangeSingleTest, createTestName(parameters), parameters, crossDomainTimeout);
+    });
+})(this);

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-read-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-read-functional-tests.html b/odatajs/tests/odata-read-functional-tests.html
new file mode 100644
index 0000000..11d930d
--- /dev/null
+++ b/odatajs/tests/odata-read-functional-tests.html
@@ -0,0 +1,49 @@
+<!--
+/*
+ * 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.
+*/
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>OData tests against local service</title>
+    <meta http-equiv="cache-control" content="no-cache"/> 
+    <meta http-equiv="pragma" content="no-cache"/> 
+    <meta http-equiv="expires" content="-1"/> 
+
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
+    <script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.10.0.js"></script>
+    <script type="text/javascript" src="common/ODataReadOracle.js"></script>
+    <script type="text/javascript" src="common/TestSynchronizerClient.js"></script>
+        <script type="text/javascript">
+            window.TestSynchronizer.init(QUnit);
+        </script>
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
+    <script type="text/javascript" src="common/common.js"></script>   
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="odata-read-functional-tests.js"></script>  
+</head>
+<body>
+ <h1 id="qunit-header">OData.Read tests against local in-memory service</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-read-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-read-functional-tests.js b/odatajs/tests/odata-read-functional-tests.js
new file mode 100644
index 0000000..6253856
--- /dev/null
+++ b/odatajs/tests/odata-read-functional-tests.js
@@ -0,0 +1,594 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    var validServiceDocumentAcceptHeaders = [
+            "*/*",
+            "application/json",
+            undefined
+          ];
+
+    var validMetadataAcceptHeaders = [
+            "*/*",
+            "application/xml",
+            undefined
+          ];
+
+    var invalidServiceDocumentAcceptHeaders = [
+        "application/atom+xml"
+    ];
+
+    var invalidMetadataAcceptHeaders = [
+            "application/json"
+        ];
+
+    var handlerAcceptStrings = [
+        "*/*",
+        "application/json",
+         undefined
+      ];
+
+    var httpStatusCode = {
+        notFound: 404,
+        badRequest: 400,
+        unsupportedMediaType: 415
+    };
+
+    var service = "./endpoints/FoodStoreDataServiceV4.svc/";
+    var epmService = "./endpoints/EpmDataService.svc/";
+    var feed = service + "Foods";
+    var categoriesFeed = service + "Categories";
+
+    var expectedErrorMessage = "HTTP request failed";
+
+    module("Functional", {
+        setup: function () {
+            djstest.wait(function (done) {
+                $.post(service + "ResetData", done);
+            });
+            window.odatajs.oData.json.jsonHandler.recognizeDates = false;
+        }
+    });
+
+    for (var i = 0; i < handlerAcceptStrings.length; i++) {
+
+        djstest.addTest(function readFullFeedTest(handlerAccept) {
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: feed, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readFeed(feed,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                );
+        }, "Testing valid read of full feed collection with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readMaxAndNullValueEntryTest(handlerAccept) {
+            var endPoint = feed + "(0)";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endPoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                );
+        }, "Testing valid read of entry with max numbers, complex types, and null and empty strings " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readMinAndZeroValueEntryTest(handlerAccept) {
+            var endPoint = feed + "(1)";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: "./endpoints/FoodStoreDataServiceV4.svc/Foods(1)", headers: { Accept: handlerAccept} },
+                function (data, response) {
+                    window.ODataReadOracle.readEntry(endPoint,
+                        function (expectedData) {
+                            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                            djstest.done();
+                        }, handlerAccept
+                    );
+                },
+                unexpectedErrorHandler);
+        }, "Testing valid read of minimum and zero values " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readNullNestedComplexTypeEntryTest(handlerAccept) {
+            var endPoint = feed + "(2)";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endPoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                 );
+        }, "Testing valid read of null nested complex type and navigation property " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readNullComplexTypeEntryTest(handlerAccept) {
+            var endPoint = feed + "(3)";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endPoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                 );
+        }, "Testing valid read of null top level complex type" + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readNullPropertiesDerivedEntryTest(handlerAccept) {
+            djstest.assertsExpected(1);
+            var endPoint = feed + "(4)";
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endPoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                );
+        }, "Testing valid read of derived type null properties with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readNextComplexTypeDerivedEntryTest(handlerAccept) {
+
+            djstest.assertsExpected(1);
+            var endPoint = feed + "(5)";
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endPoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                 );
+        }, "Testing valid read of derived type with full nested complex type properties with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readEntryWithInlineFeedTest(handlerAccept) {
+            var endpoint = categoriesFeed + "(0)?$expand=Foods";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data.value, expectedData.value, "Verify inline feed");
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify entry");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                );
+        }, "Testing read of entry with inline feed with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readFeedWithEmptyInlineFeedTest(handlerAccept) {
+            var endpoint = categoriesFeed + "?$filter=Name eq 'Empty Category'&$expand=Foods";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readFeed(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data.value, expectedData.value, "Verify inline feed");
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify feed");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+               );
+        }, "Testing read of entry with empty inline feed with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readEntryWithInlineEntryTest(handlerAccept) {
+            var endpoint = feed + "(0)?$expand=Category";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data.Category, expectedData.Category, "Verify inline entry");
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify entry");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+               );
+        }, "Testing read of entry with inline entry with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readFeedWithNullInlineEntryTest(handlerAccept) {
+            var endpoint = feed + "?$expand=Category&$filter=Category eq null";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readFeed(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data.value, expectedData.value, "Verify inline data");
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify feed");
+                                djstest.done();
+                            }, handlerAccept);
+                    },
+                    unexpectedErrorHandler
+               );
+        }, "Testing read of feed with null inline entry with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readFeedWithInlineCountTest(handlerAccept) {
+            var endpoint = feed + "?$count=true";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readFeed(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqual(data["@odata.count"], expectedData["@odata.count"], "Verify count in response data");
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify feed");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    },
+                    unexpectedErrorHandler
+                );
+        }, "Testing read of collection with inline count with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function selectSinglePropertyOnEntryTest(handlerAccept) {
+            var endpoint = feed + "(0)?$select=Name";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                function (data, response) {
+                    window.ODataReadOracle.readEntry(endpoint,
+                        function (expectedData) {
+                            djstest.assertAreEqualDeep(data, expectedData, "Verify select result");
+                            djstest.done();
+                        }, handlerAccept
+                    );
+                },
+                unexpectedErrorHandler);
+        }, "Select single property of entry " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function selectComplexTypeOnFeedTest(handlerAccept) {
+            var endpoint = feed + "?$select=Packaging";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                function (data, response) {
+                    window.ODataReadOracle.readFeed(endpoint,
+                        function (expectedData) {
+                            djstest.assertAreEqualDeep(data, expectedData, "Verify select result");
+                            djstest.done();
+                        }, handlerAccept
+                    );
+                },
+                unexpectedErrorHandler);
+        }, "Select single complex type property of feed " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function selectMultiplePropertiesOnEntryTest(handlerAccept) {
+            var endpoint = feed + "(3)?$select=Packaging,ExpirationDate,IsAvailable";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                function (data, response) {
+                    window.ODataReadOracle.readEntry(endpoint,
+                        function (expectedData) {
+                            djstest.assertAreEqualDeep(data, expectedData, "Verify select result");
+                            djstest.done();
+                        }, handlerAccept
+                    );
+                },
+                unexpectedErrorHandler);
+        }, "Select multiple primitive properties of feed " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readPagedCategoriesCollectionTest(handlerAccept) {
+            var endpoint = categoriesFeed;
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readFeed(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    }, unexpectedErrorHandler);
+        }, "Testing read of paged collection with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readPagedCollectionWithInlineCountTest(handlerAccept) {
+            var endpoint = categoriesFeed + "?$count=true";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readFeed(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqual(data["@odata.context"], expectedData["@odata.context"], "Verify count in response data");
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify feed");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    }, unexpectedErrorHandler);
+        }, "Testing read of paged collection with inline count with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readEntryWithNamedStreams(handlerAccept) {
+            var endpoint = feed + "(1)?$expand=Category";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify entry");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    }, unexpectedErrorHandler);
+        }, "Testing read of entry with named streams " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readEntryWithCollectionProperties(handlerAccept) {
+            var endpoint = feed + "(0)";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        window.ODataReadOracle.readEntry(endpoint,
+                            function (expectedData) {
+                                djstest.assertAreEqualDeep(data, expectedData, "Verify entry");
+                                djstest.done();
+                            }, handlerAccept
+                        );
+                    }, unexpectedErrorHandler);
+        }, "Testing read of entry with collection properties " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function invalidEntryReadTest(handlerAccept) {
+            var endPoint = feed + "(16)";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        djstest.assert(false, "We should not get here because data is not valid.");
+                        djstest.done()
+                    },
+                    function (err) {
+                        djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
+                        djstest.assertAreEqual(err.response.statusCode, httpStatusCode.notFound, "Response status code");
+                        djstest.done();
+                    });
+        }, "Testing invalid entry read with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function invalidFeedReadTest(handlerAccept) {
+            var endPoint = feed + "Invalid";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                    function (data, response) {
+                        djstest.assert(false, "We should not get here because data is not valid.");
+                        djstest.done();
+                    },
+                    function (err) {
+                        djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
+                        djstest.assertAreEqual(err.response.statusCode, httpStatusCode.notFound, "Response status code");
+                        djstest.done();
+                    });
+        }, "Testing invalid feed read with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function standardErrorReadTest(handlerAccept) {
+            var endPoint = feed + "?$foo=bar";
+            djstest.assertsExpected(2);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} },
+                                    function (data, response) {
+                                        djstest.assert(false, "We should not get here because data is not valid.");
+                                        djstest.done()
+                                    },
+                                    function (err) {
+                                        djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
+                                        djstest.assertAreEqual(err.response.statusCode, httpStatusCode.badRequest, "Response status code");
+                                        djstest.done();
+                                    });
+        }, "Testing standard error read with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function inStreamErrorReadTest(handlerAccept) {
+            var endPoint = "./endpoints/ErrorDataService.svc/Entities";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endPoint, headers: { Accept: handlerAccept} }, function (data, response) {
+                djstest.assert(false, "Unexpected call to success handler with response: " + djstest.toString(response));
+                djstest.done()
+            }, function (err) {
+                djstest.assert(err.response.body.indexOf("An error occurred while processing this request") > -1, "Error handler was called with the correct response body");
+                djstest.done();
+            });
+        }, "Testing in-stream error read with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        var user = "djsUser";
+        var password = "djsPassword";
+
+        djstest.addTest(function readFullFeedBasicAuthTest(handlerAccept) {
+            var endpoint = "./endpoints/BasicAuthDataService.svc/Customers";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept }, user: user, password: password }, function (data, response) {
+                window.ODataReadOracle.readFeed({ url: endpoint, user: user, password: password }, function (expectedData) {
+                    djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                    djstest.done();
+                }, handlerAccept);
+            }, unexpectedErrorHandler);
+        }, "Testing valid read of full feed collection on basic auth with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+
+        djstest.addTest(function readEntryBasicAuthTest(handlerAccept) {
+            var endpoint = "./endpoints/BasicAuthDataService.svc/Customers(1)";
+            djstest.assertsExpected(1);
+            odatajs.oData.read({ requestUri: endpoint, headers: { Accept: handlerAccept }, user: user, password: password }, function (data, response) {
+                window.ODataReadOracle.readEntry({ url: endpoint, user: user, password: password }, function (expectedData) {
+                    djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                    djstest.done();
+                }, handlerAccept);
+            }, unexpectedErrorHandler);
+        }, "Testing valid read of entry on basic auth with " + handlerAcceptStrings[i], handlerAcceptStrings[i]);
+    }
+
+    var services = [
+            service,
+            epmService
+        ];
+
+    $.each(services, function (_, serviceName) {
+        $.each(validServiceDocumentAcceptHeaders, function (_, validServiceDocumentAcceptHeader) {
+            var parameters = { handlerAccept: validServiceDocumentAcceptHeader, serviceName: serviceName };
+
+            djstest.addTest(function validReadServiceDocumentTest(params) {
+                djstest.assertsExpected(1);
+                odatajs.oData.read({ requestUri: params.serviceName, headers: { Accept: params.handlerAccept} },
+                        function (data, response) {
+                            window.ODataReadOracle.readServiceDocument(serviceName,
+                                function (expectedData) {
+                                    djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                    djstest.done();
+                                }, params.handlerAccept
+                            );
+                        },
+                        unexpectedErrorHandler
+                    );
+            }, "Testing valid read of service document " + parameters.handlerAccept + " on service " + parameters.serviceName, parameters);
+        });
+
+        $.each(invalidServiceDocumentAcceptHeaders, function (_, invalidServiceDocumentAcceptHeader) {
+            var parameters = { handlerAccept: invalidServiceDocumentAcceptHeader, serviceName: serviceName };
+
+            djstest.addTest(function invalidReadServiceDocumentTest(params) {
+                djstest.assertsExpected(2);
+                odatajs.oData.read({ requestUri: params.serviceName, headers: { Accept: params.handlerAccept} },
+                        function success(data, response) {
+                            djstest.fail("Reading service document should produce error with " + params.handlerAccept);
+                            djstest.done();
+                        },
+                        function (err) {
+                            djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
+                            djstest.assertAreEqual(err.response.statusCode, httpStatusCode.unsupportedMediaType, "Response status code");
+                            djstest.done();
+                        }
+                    );
+            }, "Testing read of service document with invalid MIME type " + parameters.invalidServiceDocumentAcceptHeader + " on service " + serviceName, parameters);
+        });
+
+        //to do:
+        $.each(validMetadataAcceptHeaders, function (_, validMetadataAcceptHeader) {
+            var parameters = { handlerAccept: validMetadataAcceptHeader, serviceName: serviceName };
+
+            djstest.addTest(function validReadMetadataTest(params) {
+                djstest.assertsExpected(1);
+                var endPoint = params.serviceName + "$metadata";
+                odatajs.oData.read({ requestUri: endPoint, headers: { Accept: params.handlerAccept} },
+                        function (data, response) {
+                            window.ODataReadOracle.readMetadata(endPoint,
+                                function (expectedData) {
+                                    djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                    djstest.done();
+                                }
+                            );
+                        },
+                        unexpectedErrorHandler,
+                        OData.metadataHandler
+                    );
+            }, "Testing valid read metadata " + parameters.handlerAccept + " on service " + parameters.serviceName, parameters);
+        });
+
+        $.each(invalidMetadataAcceptHeaders, function (_, invalidMetadataAcceptHeader) {
+            var parameters = { handlerAccept: invalidMetadataAcceptHeader, serviceName: serviceName };
+            djstest.addTest(function invlaidReadMetadataTest(params) {
+                djstest.assertsExpected(2);
+                var endPoint = params.serviceName + "$metadata";
+                odatajs.oData.read({ requestUri: endPoint, headers: { Accept: params.handlerAccept} },
+                        function success(data, response) {
+                            djstest.fail("Reading metadata should produce error with " + params.handlerAccept);
+                            djstest.done();
+                        },
+                        function (err) {
+                            djstest.assertAreEqual(err.message, expectedErrorMessage, "Error message");
+                            djstest.assertAreEqual(err.response.statusCode, httpStatusCode.unsupportedMediaType, "Response status code");
+                            djstest.done();
+                        },
+                        OData.metadataHandler
+                    );
+            }, "Testing read metadata with invalid MIME type " + parameters.handlerAccept + " on service " + parameters.serviceName, parameters);
+        });
+    });
+
+    // To do: update the test data for enabling the annotation test
+    djstest.addFullTest(true, function metadataElementExtensionsTest() {
+        var csdlFile = "./endpoints/CustomAnnotations.xml";
+        var modifyTypeHttpClient = {};
+        var originalHttpClient = window.odatajs.oData.net.defaultHttpClient;
+
+        // Modify the content-type of the response so that it is accepted by the metadataHandler.
+        // By default, the content-type of CustomAnnotations.xml comes back as text/xml
+        modifyTypeHttpClient.request = function (request, success, error) {
+            return originalHttpClient.request(request, function (response) {
+                response.headers["Content-Type"] = "application/xml";
+                success(response);
+            }, error);
+        }
+
+        window.odatajs.oData.net.defaultHttpClient = modifyTypeHttpClient;
+
+        odatajs.oData.read({ requestUri: csdlFile, headers: { Accept: "text/xml"} },
+            function (data) {
+                window.ODataReadOracle.readMetadata(csdlFile,
+                    function (expectedData) {
+                        djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                        djstest.done();
+                    }
+                )
+            },
+            unexpectedErrorHandler, OData.metadataHandler
+         );
+    });
+
+    djstest.addTest(function verifyNonDefaultReadMethodCalled() {
+        var endPoint = feed + "(0)";
+        djstest.assertsExpected(2);
+        odatajs.oData.read(
+                { requestUri: endPoint },
+                function success(data, response) {
+                    djstest.assert(true, "Test executed");
+                    djstest.done();
+                },
+                null,
+                {
+                    read: function (response) {
+                        djstest.assert(true, "Non-default read reached");
+                        djstest.done();
+                    },
+                    accept: "*/*"
+                }
+            );
+    }, "Testing nondefault read is called.");
+
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-request-functional-tests.html
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-request-functional-tests.html b/odatajs/tests/odata-request-functional-tests.html
new file mode 100644
index 0000000..4148634
--- /dev/null
+++ b/odatajs/tests/odata-request-functional-tests.html
@@ -0,0 +1,49 @@
+<!--
+/*
+ * 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.
+*/
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>odata.request tests</title>
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <meta http-equiv="expires" content="-1" />
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
+    <script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.10.0.js"></script>
+    <script type="text/javascript" src="common/ODataReadOracle.js"></script>
+    <script type="text/javascript" src="common/TestSynchronizerClient.js"></script>
+    <script type="text/javascript">
+        window.TestSynchronizer.init(QUnit);
+    </script>
+    
+    <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
+    <script type="text/javascript" src="common/common.js"></script>
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="odata-request-functional-tests.js"></script>
+</head>
+<body>
+    <h1 id="qunit-header">odata.request tests</h1>
+    <h2 id="qunit-banner"></h2>
+    <h2 id="qunit-userAgent"></h2>
+    <ol id="qunit-tests"></ol>
+</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-request-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-request-functional-tests.js b/odatajs/tests/odata-request-functional-tests.js
new file mode 100644
index 0000000..82e4258
--- /dev/null
+++ b/odatajs/tests/odata-request-functional-tests.js
@@ -0,0 +1,399 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    OData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    var verifyRequest = function (request, done) {
+        if (request.method == "POST") {
+            verifyPost(request, done);
+        }
+        else if (request.method == "PUT") {
+            verifyPut(request, done);
+        }
+        else if (request.method == "PATCH") {
+            verifyPatch(request, done);
+        }
+    };
+
+    var tryRemoveOdataType = function (data) {
+        if (data && data["@odata.type"]) {
+            delete data["@odata.type"];
+        }
+
+        return data;
+    };
+
+    var verifyPost = function (request, done) {
+        var httpOperation = request.method + " " + request.requestUri;
+        djstest.log(httpOperation);
+        odatajs.oData.request(request, function (data, response) {
+            djstest.log("Status code:" + response.statusCode);
+            djstest.assertAreEqual(response.statusCode, httpStatusCode.created, "Verify response code: " + httpOperation);
+            djstest.log("Uri:" + request.requestUri);
+            ODataReadOracle.readEntry(response.headers["Location"], function (expectedData) {
+                djstest.assertAreEqualDeep(response.data, expectedData, "Verify new entry against response: " + httpOperation);
+                done();
+            }, request.headers.Accept);
+        }, unexpectedErrorHandler);
+    };
+
+    var verifyPut = function(request, done) {
+        var httpOperation = request.method + " " + request.requestUri;
+        djstest.log(httpOperation);
+        odatajs.oData.request(request, function(data, response) {
+            djstest.log("Status code:" + response.statusCode);
+            djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code: " + httpOperation);
+            djstest.log("Uri:" + request.requestUri);
+            ODataReadOracle.readEntry(request.requestUri, function(actualData) {
+                var requestData = tryRemoveOdataType(request.data);
+                djstest.assertAreEqualDeep(subset(actualData, requestData), requestData, "Verify updated entry: " + httpOperation);
+                done();
+            }, request.headers.Accept);
+        }, unexpectedErrorHandler);
+    };
+
+    var verifyPatch = function (request, done) {
+        var httpOperation = request.method + " " + request.requestUri;
+        djstest.log(httpOperation);
+        ODataReadOracle.readEntry(request.requestUri, function (originalData) {
+            odatajs.oData.request(request, function (data, response) {
+                djstest.log("Status code:" + response.statusCode);
+                djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code");
+                djstest.log("Uri:" + request.requestUri);
+                ODataReadOracle.readEntry(request.requestUri, function (actualData) {
+
+                    // Merge the original data with the updated data to get the expected data
+                    var expectedData = $.extend(true, {}, originalData, request.data);
+                    djstest.assertAreEqualDeep(actualData, tryRemoveOdataType(expectedData), "Verify merged data");
+                    done();
+                }, request.headers["Content-Type"]);
+            }, unexpectedErrorHandler);
+        }, request.headers["Content-Type"]);
+    };
+
+    // Returns a subset of object with the same set of properties (recursive) as the subsetObject
+    var subset = function (object, subsetObject) {
+        if (typeof (object) == "object" && typeof (subsetObject) == "object") {
+            var result = {};
+            for (subsetProp in subsetObject) {
+                result[subsetProp] = subset(object[subsetProp], subsetObject[subsetProp]);
+            }
+            return result;
+        }
+        else {
+            return object;
+        }
+    };
+
+    var foodData = {
+        "@odata.type": "#DataJS.Tests.V4.Food",
+        FoodID: 42,
+        Name: "olive oil",
+        UnitPrice: 3.14,
+        ServingSize: 1,
+        MeasurementUnit: "",
+        ProteinGrams: 5,
+        FatGrams: 9,
+        CarbohydrateGrams: 2,
+        CaloriesPerServing: 6,
+        IsAvailable: true,
+        ExpirationDate: "2010-12-25T12:00:00Z",
+        ItemGUID: "27272727-2727-2727-2727-272727272727",
+        Weight: 10,
+        AvailableUnits: 1,
+        Packaging: {
+            Type: "Can",
+            Color: null,
+            NumberPerPackage: 1,
+            RequiresRefridgeration: false,
+            PackageDimensions: {
+                Length: 4,
+                Height: 3,
+                Width: 2,
+                Volume: 1
+            },
+            ShipDate: "2010-12-25T12:00:00Z"
+        }
+    };
+
+    var testServices = {
+        V4: "./endpoints/FoodStoreDataServiceV4.svc"
+    };
+
+    var testData = {
+        V4: $.extend(true, {}, foodData, {
+            AlternativeNames: ["name1", "name2"],
+            Providers:
+                    [{
+                        Name: "Provider",
+                        Aliases: ["alias1"],
+                        Details: {
+                            Telephone: "555-555-555",
+                            PreferredCode: 999
+                        }
+                    },
+                    {
+                        Name: "Provider2",
+                        Aliases: [],
+                        Details: null
+                    }
+                ]
+        })
+    };
+
+    var mimeTypes = [undefined, "application/json;odata.metadata=minimal"];
+
+    var httpStatusCode = {
+        created: 201,
+        noContent: 204,
+        notFound: 404
+    };
+
+    $.each(testServices, function (serviceName, service) {
+        var newFood = testData[serviceName];
+
+        var foodsFeed = service + "/Foods";
+        var categoriesFeed = service + "/Categories";
+
+        module("Functional", {
+            setup: function () {
+                djstest.log("Resetting data");
+                djstest.wait(function (done) {
+                    $.post(service + "/ResetData", done);
+                });
+            }
+        });
+
+        $.each(mimeTypes, function (_, mimeType) {
+            // Provide coverage for both undefined and specific DSVs
+            // For all other cases DSV = undefined is a valid scenario
+            var dataServiceVersions = ["4.0"];
+
+            $.each(dataServiceVersions, function (_, dataServiceVersion) {
+                var headers;
+                if (mimeType || dataServiceVersion) {
+                    headers = {
+                        "Content-Type": mimeType,
+                        Accept: mimeType,
+                        "OData-Version": dataServiceVersion
+                    };
+                }
+
+                djstest.addTest(function addEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: {
+                            CategoryID: 42,
+                            Name: "New Category"
+                        }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Add new entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function addEntityWithUTF16CharTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: {
+                            CategoryID: 42,
+                            Name: "\u00f6 New Category \u00f1"
+                        }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Add new entity with UTF-16 character to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function addLinkedEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed + "(0)/Foods",
+                        method: "POST",
+                        headers: headers,
+                        data: newFood
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Add new linked entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function addEntityWithInlineFeedTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: {
+                            CategoryID: 42,
+                            Name: "Olive Products",
+                            Foods: [newFood]
+                        }
+                    };
+
+                    djstest.assertsExpected(3);
+                    verifyRequest(request, function () {
+                        ODataReadOracle.readEntry(foodsFeed + "(" + newFood.FoodID + ")", function (actualData) {
+                            djstest.assertAreEqual(actualData.Name, newFood.Name, "Verify inline entities were added");
+                            djstest.done();
+                        }, headers ? headers.Accept : undefined);
+                    });
+                }, "Add new entity with inline feed to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function addEntityWithInlineEntryTest(headers) {
+                    var request = {
+                        requestUri: foodsFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: $.extend({}, newFood, {
+                            Category: {
+                                CategoryID: 42,
+                                Name: "Olive Products"
+                            }
+                        })
+                    };
+
+                    djstest.assertsExpected(3);
+                    verifyRequest(request, function () {
+                        ODataReadOracle.readEntry(categoriesFeed + "(" + request.data.Category.CategoryID + ")", function (actualData) {
+                            djstest.assertAreEqual(actualData.Name, request.data.Category.Name, "Verify inline entities were added");
+                            djstest.done();
+                        }, headers ? headers.Accept : undefined);
+                    });
+                }, "Add new entity with inline entry to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function updateEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed + "(0)",
+                        method: "PUT",
+                        headers: headers,
+                        data: {
+                            CategoryID: 0,
+                            Name: "Updated Category"
+                        }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Update entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                if (serviceName === "V4") {
+                    djstest.addTest(function updateEntityTest(headers) {
+                        var request = {
+                            requestUri: foodsFeed + "(0)",
+                            method: "PATCH",
+                            headers: headers,
+                            data: {
+                                "@odata.type": "#DataJS.Tests.V4.Food",
+                                AlternativeNames: ["one", "two"]
+                            }
+                        };
+
+                        djstest.assertsExpected(2);
+                        verifyRequest(request, djstest.done);
+                    }, "Update collection property to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+                }
+
+                djstest.addTest(function updatePrimitivePropertyTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed + "(0)/Name",
+                        method: "PUT",
+                        headers: headers,
+                        data: { value: "Updated Category" }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Update primitive property to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function updateLinkedEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed + "(0)/Foods(0)",
+                        method: "PUT",
+                        headers: headers,
+                        data: {
+                            "@odata.type": "#DataJS.Tests.V4.Food",
+                            Name: "Updated Food"
+                        }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Update linked entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function mergeEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed + "(0)",
+                        method: "PATCH",
+                        headers: headers,
+                        data: { Name: "Merged Category" }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Merge entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function mergeLinkedEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed + "(0)/Foods(0)",
+                        method: "PATCH",
+                        headers: headers,
+                        data: {
+                            "@odata.type": "#DataJS.Tests.V4.Food",
+                            Name: "Merged Food"
+                        }
+                    };
+
+                    djstest.assertsExpected(2);
+                    verifyRequest(request, djstest.done);
+                }, "Merge linked entity to " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+
+                djstest.addTest(function deleteEntityTest(headers) {
+                    var endpoint = categoriesFeed + "(0)";
+                    djstest.assertsExpected(2);
+                    odatajs.oData.request({
+                        requestUri: endpoint,
+                        method: "DELETE",
+                        headers: headers
+                    }, function (data, response) {
+                        djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code");
+                        $.ajax({
+                            url: endpoint,
+                            error: function (xhr) {
+                                djstest.assertAreEqual(xhr.status, httpStatusCode.notFound, "Verify response code of attempted retrieval after delete");
+                                djstest.done();
+                            },
+                            success: function () {
+                                djstest.fail("Delete failed: querying the endpoint did not return expected response code");
+                                djstest.done();
+                            }
+                        });
+                    }, unexpectedErrorHandler);
+                }, "Delete entity from " + serviceName + " service using mimeType = " + mimeType + " and DSV = " + dataServiceVersion, headers);
+            });
+        });
+    });
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests/odata-roundtrip-functional-tests.js
----------------------------------------------------------------------
diff --git a/odatajs/tests/odata-roundtrip-functional-tests.js b/odatajs/tests/odata-roundtrip-functional-tests.js
new file mode 100644
index 0000000..6e3c356
--- /dev/null
+++ b/odatajs/tests/odata-roundtrip-functional-tests.js
@@ -0,0 +1,389 @@
+/*
+ * 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.
+ */
+
+(function (window, undefined) {
+    var unexpectedErrorHandler = function (err) {
+        djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+        djstest.done();
+    };
+
+    var verifyRequest = function (request, done) {
+        if (request.method == "POST") {
+            if (request.headers && request.headers["X-HTTP-Method"] == "MERGE") {
+                verifyMerge(request, done);
+            }
+            else {
+                verifyPost(request, done);
+            }
+        }
+        else if (request.method == "PUT") {
+            verifyPut(request, done);
+        }
+    };
+
+    var verifyPost = function (request, done) {
+        var httpOperation = request.method + " " + request.requestUri;
+        odatajs.oData.request(request, function (data, response) {
+            djstest.assertAreEqual(response.statusCode, httpStatusCode.created, "Verify response code: " + httpOperation);
+            ODataReadOracle.readJson(data.__metadata.uri, function (expectedData) {
+                djstest.assertAreEqualDeep(response.data, expectedData, "Verify new entry against response: " + httpOperation);
+                done();
+            }, request.headers.Accept);
+        }, unexpectedErrorHandler);
+    };
+
+    var verifyPut = function (request, done) {
+        var httpOperation = request.method + " " + request.requestUri;
+        odatajs.oData.request(request, function (data, response) {
+            djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code: " + httpOperation);
+            ODataReadOracle.readJson(request.requestUri, function (actualData) {
+                djstest.assertAreEqualDeep(actualData, request.data, "Verify updated entry: " + httpOperation);
+                done();
+            }, request.headers.Accept);
+        }, unexpectedErrorHandler);
+    }
+
+    var verifyMerge = function (request, done) {
+        var httpOperation = request.method + " " + request.requestUri;
+        ODataReadOracle.readJson(request.requestUri, function (originalData) {
+            odatajs.oData.request(request, function (data, response) {
+                djstest.assertAreEqual(response.statusCode, httpStatusCode.noContent, "Verify response code");
+                ODataReadOracle.readJson(request.requestUri, function (actualData) {
+                    // Merge the original data with the updated data to get the expected data
+                    var expectedData = $.extend(true, {}, originalData, request.data);
+                    djstest.assertAreEqualDeep(actualData, expectedData, "Verify merged data");
+                    done();
+                }, request.headers["Content-Type"]);
+            }, unexpectedErrorHandler);
+        }, request.headers["Content-Type"]);
+    }
+
+    // Returns a subset of object with the same set of properties (recursive) as the subsetObject
+    var subset = function (object, subsetObject) {
+        if (typeof (object) == "object" && typeof (subsetObject) == "object") {
+            var result = {};
+            for (subsetProp in subsetObject) {
+                result[subsetProp] = subset(object[subsetProp], subsetObject[subsetProp]);
+            }
+            return result;
+        }
+        else {
+            return object;
+        }
+    };
+
+    var service = "./endpoints/FoodStoreDataService.svc";
+    var foodsFeed = service + "/Foods";
+    var categoriesFeed = service + "/Categories";
+    //var mimeTypes = [undefined, "application/json", "application/atom+xml"];
+    var mimeTypes = ["application/json", "application/atom+xml"];
+
+    var httpStatusCode = {
+        created: 201,
+        noContent: 204,
+        notFound: 404
+    };
+
+    var newFood = {
+        "__metadata": {
+            type: "DataJS.Tests.Food"
+        },
+        FoodID: 42,
+        Name: "olive oil",
+        UnitPrice: 3.14,
+        ServingSize: "1",
+        MeasurementUnit: "Cup",
+        ProteinGrams: 5,
+        FatGrams: 9,
+        CarbohydrateGrams: 2,
+        CaloriesPerServing: "6",
+        IsAvailable: true,
+        ExpirationDate: new Date("2011/05/03 12:00:00 PM"),
+        ItemGUID: "27272727-2727-2727-2727-272727272727",
+        Weight: 10,
+        AvailableUnits: 1,
+        Packaging: {
+            Type: "Can",
+            Color: "White",
+            NumberPerPackage: 1,
+            RequiresRefridgeration: false,
+            PackageDimensions: {
+                Length: "4",
+                Height: 3,
+                Width: "2",
+                Volume: 1
+            },
+            ShipDate: new Date("2011/01/01 12:00:00 PM")
+        }
+    };
+
+    var newFoodLinks = {
+        uri: foodsFeed + "(1)"
+    }
+
+    module("Functional", {
+        setup: function () {
+            $.ajax({ async: false, type: "POST", url: service + "/ResetData" });
+        }
+    });
+
+    $.each(mimeTypes, function (_, mimeType) {
+        var headers = mimeType ? { "Content-Type": mimeType, Accept: mimeType} : undefined;
+
+                djstest.addTest(function addEntityTest(headers) {
+                    var request = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: {
+                            CategoryID: 42,
+                            Name: "New Category"
+                        }
+                    };
+
+                    verifyRequest(request, function () {
+                        odatajs.oData.read({ requestUri: categoriesFeed + "(42)", headers: { Accept: mimeType} }, function (actualData, response) {
+                            actualData.CategoryID = 27;
+                            var newRequest = {
+                                requestUri: categoriesFeed,
+                                method: "POST",
+                                headers: headers,
+                                data: actualData
+                            };
+                            verifyRequest(newRequest, function () { djstest.done(); });
+                        }, request.headers["Content-Type"]);
+                    });
+
+                }, "Post, read posted data, post read data (mimeType = " + mimeType + ")", headers);
+
+        djstest.addTest(function addLinkedEntityTest(headers) {
+            var request = {
+                requestUri: categoriesFeed + "(0)/Foods",
+                method: "POST",
+                headers: headers,
+                data: newFood
+            };
+
+            verifyRequest(request, function () {
+                odatajs.oData.read({ requestUri: categoriesFeed + "(0)/Foods(42)", headers: { Accept: mimeType} }, function (actualData, response) {
+                    actualData.FoodID = 94;
+                    var newRequest = {
+                        requestUri: categoriesFeed + "(0)/Foods",
+                        method: "POST",
+                        headers: headers,
+                        data: actualData
+                    };
+                    verifyRequest(newRequest, function () { djstest.done(); });
+                }, request.headers["Content-Type"]);
+            });
+        }, "POST, read, POST an entry " + mimeType + ")", headers);
+
+
+        djstest.addTest(function addLinkedEntityTest(headers) {
+            var request = {
+                requestUri: categoriesFeed + "(0)/Foods(0)",
+                method: "PUT",
+                headers: headers,
+                data: newFood
+            };
+
+            verifyRequest(request, function () {
+                odatajs.oData.read({ requestUri: categoriesFeed + "(0)/Foods(0)", headers: { Accept: mimeType} }, function (actualData, response) {
+                    var newRequest = {
+                        requestUri: categoriesFeed + "(0)/Foods(0)",
+                        method: "PUT",
+                        headers: headers,
+                        data: {
+                            "__metadata": { type: "DataJS.Tests.Food" },
+                            Name: "New Food" 
+                        }
+                    };
+                    verifyRequest(newRequest, function () { djstest.done(); });
+                });
+            });
+        }, "PUT, read, PUT a new linked entry " + mimeType + ")", headers);
+
+        djstest.addTest(function addEntityWithInlineFeedTest(headers) {
+            var request = {
+                requestUri: categoriesFeed,
+                method: "POST",
+                headers: headers,
+                data: {
+                    CategoryID: 42,
+                    Name: "Olive Products",
+                    Foods: [newFood]
+                }
+            };
+
+            verifyRequest(request, function () {
+                odatajs.oData.read({ requestUri: foodsFeed + "(" + newFood.FoodID + ")", headers: { Accept: mimeType} }, function (actualData, response) {
+                    var newRequest = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: {
+                            CategoryID: 27,
+                            Name: "Olive Products",
+                            Foods: [actualData]
+                        }
+                    };
+                    verifyRequest(newRequest, function () { djstest.done(); });
+                });
+            });
+
+        }, "POST, read, POST an entity with inline feed " + mimeType + ")", headers);
+
+        djstest.addTest(function addEntityWithInlineEntryTest(headers) {
+            var request = {
+                requestUri: foodsFeed,
+                method: "POST",
+                headers: headers,
+                data: $.extend({}, newFood, {
+                    Category: {
+                        "__metadata": { uri: "" },
+                        CategoryID: 42,
+                        Name: "Olive Products"
+                    }
+                })
+            };
+
+            verifyRequest(request, function () {
+                odatajs.oData.read({ requestUri: foodsFeed + "(" + newFood.FoodID + ")", headers: { Accept: mimeType} }, function (actualData, response) {
+                    actualData.FoodID = 76;
+                    var newRequest = {
+                        requestUri: foodsFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: $.extend({}, actualData, {
+                            Category: {
+                                "__metadata": { uri: "" },
+                                CategoryID: 27,
+                                Name: "Olive Products"
+                            }
+                        })
+                    };
+                    verifyRequest(newRequest, function () { djstest.done(); });
+                });
+            });
+        }, "Add new entity with inline entry (mimeType = " + mimeType + ")", headers);
+
+        djstest.addTest(function addEntityTest(headers) {
+            var request = {
+                requestUri: categoriesFeed + "(1)",
+                method: "PUT",
+                headers: headers,
+                data: {
+                    CategoryID: 1,
+                    Name: "New Category"
+                }
+            };
+
+            verifyRequest(request, function () {
+                odatajs.oData.read({ requestUri: categoriesFeed + "(1)", headers: { Accept: mimeType} }, function (actualData, response) {
+                    actualData.CategoryID = 2;
+                    var newRequest = {
+                        requestUri: categoriesFeed + "(2)",
+                        method: "PUT",
+                        headers: headers,
+                        data: actualData
+                    };
+                    verifyRequest(newRequest, function () { djstest.done(); });
+                }, request.headers["Content-Type"]);
+            });
+
+        }, "Put, read put data, put read data (mimeType = " + mimeType + ")", headers);
+
+        djstest.addTest(function addEntityTest(headers) {
+            odatajs.oData.read({ requestUri: foodsFeed + "(0)", headers: { Accept: mimeType} },
+                function (actualData, response) {
+                    actualData.CategoryID = 216;
+                    var request = {
+                        requestUri: foodsFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: actualData
+                    };
+                    verifyRequest(request,
+                        function () {
+                            odatajs.oData.read({ requestUri: foodsFeed + "(216)", headers: { Accept: mimeType} },
+                                function (data, response) {
+                                    ODataReadOracle.readJson(foodsFeed + "(216)",
+                                        function (expectedData) {
+                                            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                            djstest.done();
+                                        });
+                                });
+                        });
+                });
+        }, "Read data with dates, post read data with dates to new ID, read new ID data with dates" + mimeType + ")", headers);
+
+        djstest.addTest(function addEntityTest(headers) {
+            odatajs.oData.read({ requestUri: categoriesFeed + "(0)", headers: { Accept: mimeType} }, 
+                function (actualData, response) {
+                    actualData.CategoryID = 81;
+                    var request = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: actualData
+                    };
+                    verifyRequest(request, 
+                        function () { 
+                            odatajs.oData.read({ requestUri: categoriesFeed + "(81)", headers: { Accept: mimeType} }, 
+                                function (data, response) {
+                                    ODataReadOracle.readJson(categoriesFeed + "(81)",
+                                        function (expectedData) {
+                                            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                            djstest.done();
+                                        }
+                                    );
+                                }
+                            );
+                        }
+                    );
+                }
+            );
+        }, "Read existing data, post existing data to new idea, read new ID data" + mimeType + ")", headers);
+
+
+        djstest.addTest(function addEntityTest(headers) {
+            odatajs.oData.read({ requestUri: categoriesFeed + "(0)", headers: { Accept: mimeType} },
+                function (actualData, response) {
+                    actualData.CategoryID = 81;
+                    var request = {
+                        requestUri: categoriesFeed,
+                        method: "POST",
+                        headers: headers,
+                        data: actualData
+                    };
+                    verifyRequest(request,
+                        function () {
+                            odatajs.oData.read({ requestUri: categoriesFeed + "(81)", headers: { Accept: mimeType} },
+                                function (data, response) {
+                                    ODataReadOracle.readJson(categoriesFeed + "(81)",
+                                        function (expectedData) {
+                                            djstest.assertAreEqualDeep(data, expectedData, "Response data not same as expected");
+                                            djstest.done();
+                                        });
+                                });
+                        });
+                });
+        }, "Read existing data, post existing data to new idea, read new ID data" + mimeType + ")", headers);
+    });
+})(this);
\ No newline at end of file