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:22 UTC

[15/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-tmp/common/djstest.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/djstest.js b/odatajs/tests-tmp/common/djstest.js
new file mode 100644
index 0000000..104c4cf
--- /dev/null
+++ b/odatajs/tests-tmp/common/djstest.js
@@ -0,0 +1,412 @@
+/*
+ * 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.
+ */
+
+
+// Because this code contains a init function to be useable directly inside the browser as well as in nodejs
+// we define the @namespace djstest here instead of the a @module name djstest
+
+/** Create namespace djstest in window.djstest when this file is loaded as java script by the browser
+ * @namespace djstest
+ */
+
+if (typeof window !== 'undefined') {
+    //expose to browsers window object
+    window.djstest = window.djstest || {};
+    init(window.djstest);
+} else {
+    //expose in commonjs style
+    module.exports = init();
+}
+
+
+function init (parent) {
+    djstest = parent || {};
+
+    /** Constructs a Job object that allows for enqueuing and synchronizing the execution of functions.
+     * @class Job
+     * @constructor
+     * @returns {Object} Job object
+     */
+    djstest.Job = function () {
+        
+        var currentTask = -1;
+        var tasks = [];
+
+        var failedTasks = 0;
+
+        /** Adds a function to the job queue regardless if the queue is already executing or not.
+         * @method djstest.Job#queue
+         * @param {Function} fn - Function to execute.
+         */
+        this.queue = function (fn) {
+            
+            tasks.push(fn);
+        };
+
+        /** Adds a function to the front of the job queue regardless if the queue is already executing or not.
+         * @method djstest.Job#queueNext
+         * @param {Function} fn - Function to execute.
+         */
+        this.queueNext = function (fn) {
+        
+            if (currentTask < 0) {
+                tasks.unshift(fn);
+            } else {
+                tasks.splice(currentTask + 1, 0, fn);
+            }
+        };
+
+        /** Starts the execution of this job.
+         * @method djstest.Job#run
+         * @param {Function} done - Callback invoked when the job has finished executing all of its enqueued tasks.
+         */
+        this.run = function (done) {
+            /// This method does nothing if called on a unit of work that is already executing.
+            if (currentTask >= 0) {
+                return;
+            }
+
+            if (tasks.length === 0) {
+                done(true);
+                return;
+            }
+
+            /**
+             * @method djstest.Job~makeTaskDoneCallBack
+            */
+            function makeTaskDoneCallBack(failed) {
+                return function () {
+                    // Track the failed task and continue the execution of the job. 
+                    if (failed) {
+                        failedTasks++;
+                    }
+                    currentTask++;
+                    if (currentTask === tasks.length) {
+                        done(failedTasks === 0);
+                    } else {
+                        runNextTask();
+                    }
+                };
+            }
+
+            /** Executes the next function in the queue.
+             * @method djstest.Job~runNextTask
+            */
+            function runNextTask() {
+                defer(function () {
+                    try {
+                        tasks[currentTask](makeTaskDoneCallBack(false), makeTaskDoneCallBack(true));
+                    } catch (e) {
+                        makeTaskDoneCallBack(true)();
+                    }
+                });
+            }
+
+            currentTask = 0;
+            runNextTask();
+        };
+    };
+
+    /** Defers the execution of an arbitrary function that takes no parameters.
+     * @memberof djstest
+     * @inner
+     * @param {Function} fn - Function to schedule for later execution.
+     */
+    function defer(fn) {
+        setTimeout(fn, 0);
+    }
+
+    /** Exposes date values for Date objects to facilitate debugging
+     * @memberof djstest
+     * @inner
+     * @param {Object} data - The object to operate on
+     */
+    function exposeDateValues(data) {
+     
+        if (typeof data === "object") {
+            if (data instanceof Date) {
+                data.__date__ = data.toUTCString();
+            }
+            else {
+                for (var prop in data) {
+                    exposeDateValues(data[prop]);
+                }
+            }
+        }
+
+        return data;
+    }
+
+    /** Determines the name of a function.
+     * @memberof djstest
+     * @inner
+     * @param {String} text - Function text.
+     * @returns {String} The name of the function from text if found; the original text otherwise.
+     */
+    function extractFunctionName(text) {
+
+        var index = text.indexOf("function ");
+        if (index < 0) {
+            return text;
+        }
+
+        var nameStart = index + "function ".length;
+        var parensIndex = text.indexOf("(", nameStart);
+        if (parensIndex < 0) {
+            return text;
+        }
+
+        var result = text.substr(nameStart, parensIndex - nameStart);
+        if (result.indexOf("test") === 0) {
+            result = result.substr("test".length);
+        }
+
+        return result;
+    }
+
+    /** Removes metadata annotations from the specified object.
+     * @memberof djstest
+     * @inner
+     * @param data - Object to remove metadata from; possibly null.
+     */
+    function removeMetadata(data) {
+
+        if (typeof data === "object" && data !== null) {
+            delete data.__metadata;
+            for (var prop in data) {
+                removeMetadata(data[prop]);
+            }
+        }
+    }
+
+    /** Add the unit test cases
+     * @param disable - Indicate whether this test case should be disabled
+    */
+    djstest.addFullTest = function (disable, fn, name, arg, timeout) {
+
+        if (disable !== true) {
+            djstest.addTest(fn, name, arg, timeout);
+        }
+    };
+
+    /** Add the unit test cases
+     * @param disable - Indicate whether this test case should be disabled
+    */
+    djstest.addTest = function (fn, name, arg, timeout) {
+        if (!name) {
+            name = extractFunctionName(fn.toString());
+        }
+
+        test(name, function () {
+            if (!timeout) {
+                timeout = 20000;
+            }
+
+            QUnit.config.testTimeout = timeout;
+            QUnit.stop();
+            fn.call(this, arg);
+        });
+    };
+
+    /** Asserts that a condition is true.
+     * @param {Boolean} test - Condition to test.
+     * @param {String} message - Text message for condition being tested.
+     */
+    djstest.assert = function (test, message) {
+        
+        QUnit.ok(test, message);
+    };
+
+    /** Asserts that the values of the expected and actualobjects are equal.
+     * @memberof djstest
+     * @inner
+     */
+    djstest.assertAreEqual = function (actual, expected, message) {
+        QUnit.equal(actual, expected, message);
+    };
+
+    /** Asserts that the actual and expected objects are the same.
+     */
+    djstest.assertAreEqualDeep = function (actual, expected, message) {
+        QUnit.deepEqual(exposeDateValues(actual), exposeDateValues(expected), message);
+    };
+
+    /** Asserts that the actual and expected objects are the same but removes the metadata bevore
+     */
+    djstest.assertWithoutMetadata = function (actual, expected, message) {
+        removeMetadata(actual);
+        removeMetadata(expected);
+        djstest.assertAreEqualDeep(actual, expected, message);
+    };
+
+    /** Calls each async action in asyncActions, passing each action a function which keeps a count and
+     * calls the passed done function when all async actions complete
+     * @param {Array} asyncActions -Array of asynchronous actions to be executed, 
+     * each taking a single parameter - the callback function to call when the action is done.</param>
+     * @param {Function} done - Function to be executed in the last async action to complete.
+     */
+    djstest.asyncDo = function (asyncActions, done) {
+
+        var count = 0;
+        var doneOne = function () {
+            count++;
+            if (count >= asyncActions.length) {
+                done();
+            }
+        };
+
+        if (asyncActions.length > 0) {
+            for ( var i = 0; i < asyncActions.length; i++) {
+                asyncActions[i](doneOne);
+            }
+        } else {
+            done();
+        }
+    };
+
+    /** Makes a deep copy of an object.
+     */
+    djstest.clone = function (object) {
+        if ( object === undefined ) {
+            return undefined;
+        } else if (object === null) {
+            return null;
+        } else if (typeof(object) !== 'object') {
+            return object;
+        } else {
+            var ret = {};
+            for(var key in object) {
+                if(object.hasOwnProperty(key)) {
+                    ret[key] = this.clone(object[key]);
+                }
+            }
+            return ret;
+        }
+        throw("Error cloning an object");
+    };
+
+    /** Destroys the cache and then completes the test
+     * @param cache - The cache to destroy
+     */
+    djstest.destroyCacheAndDone = function (cache) {
+     
+        cache.clear().then(function () {
+            djstest.done();
+        }, function (err) {
+            djstest.fail("Failed to destroy cache: " + djstest.toString(err));
+            djstest.done();
+        });
+    };
+
+    /** Indicates that the currently running test has finished.
+     */
+    djstest.done = function () {
+      
+        QUnit.start();
+    };
+
+    /** Test passes if and only if an exception is thrown.
+     */
+    djstest.expectException = function (testFunction, message) {
+     
+        try {
+            testFunction();
+            djstest.fail("Expected exception but function succeeded: " + " " + message);
+        }
+        catch (e) {
+            // Swallow exception.
+            djstest.pass("Thrown exception expected");
+        }
+    };
+
+    /** Indicates the expected number of asserts, fails test if number is not met.
+     * @param {Number} asserts - Number of asserts expected in test.
+     */
+    djstest.assertsExpected = function (asserts) {
+        
+        expect(asserts);
+    };
+    /** Marks the current test as failed.
+     * @param {String} message - Failure message.
+     */
+    djstest.fail = function (message) {
+
+        QUnit.ok(false, message);
+    };
+
+    /** Returns a function that when invoked will fail this test and be done with it.
+     * @param {String} message - Failure message.
+     * @param {Function} [cleanupCallback] - 
+     * @returns {Function} A new function.
+     */
+    djstest.failAndDoneCallback = function (message, cleanupCallback) {
+
+        return function (err) {
+            message = "" + message + (err) ? JSON.stringify(err) : "";
+            djstest.fail(message);
+            if (cleanupCallback) {
+                try {
+                    cleanupCallback();
+                } catch (e) {
+                    djstest.fail("error during cleanupCallback: " + JSON.stringify(e));
+                }
+            }
+
+            djstest.done();
+        };
+    };
+
+    /** Logs a test message.
+     * @param {String} message - Test message.
+     */
+    djstest.log = function (message) {
+
+        var context = { result: true, actual: true, expected: true, message: message };
+        QUnit.ok(true, message);
+        
+    };
+
+    /** Marks the current test as failed.
+     * @param {String} message - Failure message.
+     */
+    djstest.pass = function (message) {
+        QUnit.ok(true, message);
+    };
+
+    /** Dumps the object as a string
+     * @param {Object} obj - Object to dump
+     */
+    djstest.toString = function (obj) {
+        return QUnit.jsDump.parse(obj);
+    };
+
+    /** Executes the function, pausing test execution until the callback is called
+     * @param {Function} fn - Function to execute; takes one parameter which is the callback
+     * This function is typically used in asynchronous setup/teardown methods</remarks>
+     */
+    djstest.wait = function (fn) {
+        QUnit.stop();
+        fn(function () {
+            QUnit.start();
+        });
+    };
+
+    return djstest;
+}
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/logging.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/logging.js b/odatajs/tests-tmp/common/logging.js
new file mode 100644
index 0000000..9297527
--- /dev/null
+++ b/odatajs/tests-tmp/common/logging.js
@@ -0,0 +1,5 @@
+QUnit.log( function (context) {
+    if (window.console && window.console.log && context.message) {
+        window.console.log(context.result + ' :: ' + context.message  );
+    }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/mockHttpClient.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/mockHttpClient.js b/odatajs/tests-tmp/common/mockHttpClient.js
new file mode 100644
index 0000000..2ec97e7
--- /dev/null
+++ b/odatajs/tests-tmp/common/mockHttpClient.js
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+ 
+//mockHttpClient.js
+//this object allows for associating a uri with a requestVerfier and mock responses that will be sent back to the client of the httpStack.  
+//It can be used to replace OData's httpClient for testing purposes.
+//
+//RequestVerifiers
+//
+//    A request verifier is a function associated to a particular URI that will be executed by the mockHttpClient when it receives a request with the matching URI.
+//    the callback receives as its only parameter the request object passed to the mockHttpClient.
+//
+//    To register a request verifier, simply do 
+//        
+//            MockHttpClient.addRequestVerifier("http://someUri", function(request) {
+//                djstest.assertAreEqual(request.requestUri,"http://someUri");
+//            }
+//
+//Responses
+//    Mock responses can be associated with a particular URI.  When the MockHttpClient receives a request with a URI mapped to a response, then it will, 
+//    depending on the response status code invoke either the success or the error callbacks. 
+//
+//    To register a response,
+//       
+//           MockHttpClient.addResponse("http://someUri", {status: 200, body:"some body"});
+//
+//Exceptions
+//    MockHttpClient will throw an exception if it receives a request to a URI that is not mapped to either a request verifier or a response.
+//
+
+
+if (typeof window !== 'undefined') {
+    //in browser call init() directly window as context
+    window.MockHttpClient = window.MockHttpClient || {};
+    init(window.MockHttpClient);
+} else {
+    //expose function init to be called with a custom context
+    module.exports = init();
+}
+
+
+function init(parent, undefined) {
+    httpClient = parent || {};
+
+    var responses = {};
+    var requestVerifiers = {};
+
+    httpClient.addRequestVerifier = function (uri, verifier) {
+        requestVerifiers[uri] = verifier;
+        return this;
+    };
+
+    httpClient.addResponse = function (uri, response) {
+        responses[uri] = response;
+        return this;
+    };
+
+    httpClient.async = false;
+
+    httpClient.clear = function () {
+        /** Clears all registered responses and verifiers.
+         * @returns this client
+         */
+        responses = {};
+        requestVerifiers = {};
+        this.async = false;
+        return this;
+    };
+
+    httpClient.request = function (request, success, error) {
+        var uri = request.requestUri;
+        var verifier = requestVerifiers[uri];
+        var response = responses[uri];
+
+        if (verifier === undefined) {
+            verifier = requestVerifiers["*"];
+        }
+
+        if (response === undefined) {
+            response = responses["*"];
+        }
+
+        if (!verifier && !response) {
+            throw { message: "neither verifier or response defined for uri: " + uri };
+        }
+
+        if (verifier) {
+            verifier(request);
+        }
+
+        if (response) {
+            response.requestUri = uri;
+            if (response.statusCode >= 200 && response.statusCode <= 299) {
+                if (this.async) {
+                    setTimeout(function () {
+                        success(response);
+                    });
+                } else {
+                    success(response);
+                }
+            } else {
+                if (this.async) {
+                    setTimeout(function () {
+                        error({ message: "failed test response", request: request, response: response });
+                    });
+                }
+                else {
+                    error({ message: "failed test response", request: request, response: response });
+                }
+            }
+        }
+    };
+
+    httpClient.setAsync = function (value) {
+        this.async = value;
+        return this;
+    };
+
+    return httpClient;
+}
+
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/node-test-setup.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/node-test-setup.js b/odatajs/tests-tmp/common/node-test-setup.js
new file mode 100644
index 0000000..c08c439
--- /dev/null
+++ b/odatajs/tests-tmp/common/node-test-setup.js
@@ -0,0 +1,30 @@
+/*
+ * 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.
+*/
+//Creates the global objects
+
+//tools
+
+var window = {};
+window.djstest = require("./djstest.js");
+window.mockHttpClient = require("./mockHttpClient.js");
+window.odatajs  = require('./../../src/index.js');
+
+global.window = window;
+console.log(global.window.odatajs.node+'asdfasdfasdfasdf');
+

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/observableHttpClient.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/observableHttpClient.js b/odatajs/tests-tmp/common/observableHttpClient.js
new file mode 100644
index 0000000..9be75f8
--- /dev/null
+++ b/odatajs/tests-tmp/common/observableHttpClient.js
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+// ObservableHttpClient.js
+// This object extends OData's default httpClient by supporting request and response recording sessions, and firing a custom
+// JQuery event for each request/response.
+//
+// The events fired by this object are:
+//      request: Before a request is made
+//      success: Before the primary success handler is called
+//
+// To bind to an event, JQuery event attachers can be used on the object, e.g.
+//      $(observableHttpClient).bind("request", function (request) { ... });
+//
+// To begin a new recording session, use:
+//      var session = observableHttpClient.newSession();
+//
+// Requests and responses are then recorded in session.requests and session.responses. Session can be ended by session.end().
+// Multiple simultaneous sessions are supported.
+
+(function (window, undefined) {
+
+    var ObservableHttpClient = function (provider) {
+        this.provider = provider ? provider : window.odatajs.oData.net.defaultHttpClient;
+    };
+
+    ObservableHttpClient.prototype.newSession = function () {
+        return new Session(this);
+    };
+
+    ObservableHttpClient.prototype.request = function (request, success, error) {
+        var that = this;
+
+        $(this).triggerHandler("request", request);
+        return this.provider.request(request, function (response) {
+            $(that).triggerHandler("success", response);
+            success(response);
+        }, error);
+    };
+
+
+    var Session = function (client) {
+        var that = this;
+
+        this.client = client;
+        this.clear();
+
+        this.requestHandler = function (event, request) { that.requests.push(request); };
+        $(client).bind("request", this.requestHandler);
+
+        this.successHandler = function (event, response) { that.responses.push(response); };
+        $(client).bind("success", this.successHandler);
+    };
+
+    Session.prototype.clear = function () {
+        this.requests = [];
+        this.responses = [];
+    }
+
+    Session.prototype.end = function () {
+        $(this.client).unbind("request", this.requestHandler);
+        $(this.client).unbind("success", this.successHandler);
+    };
+
+    window.ObservableHttpClient = ObservableHttpClient;
+    window.Session = Session;
+
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/odataCacheVerifier.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/odataCacheVerifier.js b/odatajs/tests-tmp/common/odataCacheVerifier.js
new file mode 100644
index 0000000..54e4659
--- /dev/null
+++ b/odatajs/tests-tmp/common/odataCacheVerifier.js
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ */
+
+// CacheVerifier.js
+// This object verifies the operation of the cache.
+// Internally it maintains a simple model of the cache implemented using a lookup array of the expected cached pages.
+
+(function (window, undefined) {
+
+    var CacheVerifier = function (baseUri, pageSize, total, cacheSize) {
+        /** Creates a new CacheVerifier
+         * @param {String} baseUri - The base URI of the collection
+         * @param {Integer} pageSize - The page size used in the cache
+         * @param {Integer} total - The total number of items in the collection
+         * @param {Integer} cacheSize - Cache size in bytes
+         */
+        this.baseUri = baseUri;
+        this.pageSize = pageSize;
+        this.total = total;
+        this.cacheSize = (cacheSize !== undefined) ? cacheSize : 1024 * 1024;
+        this.actualSize = 0;
+        this.actualCount = 0;
+        this.cachedPages = [];
+        this.exactPageCount = (total % pageSize === 0);
+        this.maxPage = Math.floor(total / pageSize);
+        this.overflowed = this.cacheSize === 0;
+    };
+
+    CacheVerifier.mechanisms = {
+        memory: "memory",
+        indexeddb: "indexeddb",
+        dom: "dom",
+        best: "best"
+    };
+
+    CacheVerifier.isMechanismAvailable = function (mechanism) {
+        /** Determines if the specified local storage mechanism is available
+         * @param mechanism - The name of the mechanism
+         * @returns Whether the mechanism is available
+         */
+        switch (mechanism) {
+            case CacheVerifier.mechanisms.indexeddb:
+                if (window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.indexedDB) {
+                    return true;
+                }
+                else {
+                    return false;
+                }
+                break;
+            case CacheVerifier.mechanisms.dom:
+                if (window.localStorage) {
+                    return true;
+                }
+                else {
+                    return false;
+                }
+                break;
+            case CacheVerifier.mechanisms.memory:
+            case CacheVerifier.mechanisms.best:
+            case undefined:
+                return true;
+            default:
+                return false;
+        }
+    };
+
+    CacheVerifier.prototype.clear = function () {
+        /** Clears the cache in the oracle
+        */
+        this.cachedPages = [];
+        this.actualSize = 0;
+        this.actualCount = 0;
+        this.overflowed = this.cacheSize === 0;
+    };
+
+    CacheVerifier.prototype.verifyRequests = function (requests, responses, index, count, description, backwards, isPrefetch) {
+        /** Verifies the HTTP requests for a single data request, and updates the oracle with cached pages
+         * @param {Array} requests - The sequence of request objects (from OData.defaultHttpClient)
+         * @param {Array} responses - The sequence of response objects (from OData.defaultHttpClient)
+         * @param {Integer} index - The starting index of the read
+         * @param {Integer} count - The count of items in the read
+         * @param {String} description - The description of the requests being verified
+         * @param {Boolean} backwards - Whether or not filterBack is being verified
+         * @param {Boolean} isPrefetch - Whether the requests being verified come from the prefetcher
+         */
+        var that = this;
+
+        index = (index < 0 ? 0 : index);
+        var pageIndex = function (index) {
+            /** Returns the page index that the given item index belongs to
+             * @param {Integer} index - The item index
+             * @returns The page index
+             */
+            return Math.floor(index / that.pageSize);
+        };
+
+        var estimateSize = function (obj) {
+            /** Estimates the size of an object in bytes.
+             * @param {Object} obj - Object to determine the size of.
+             * @returns {Number} Estimated size of the object in bytes.
+             */
+
+            var size = 0;
+            var type = typeof obj;
+
+            if (type === "object" && obj) {
+                for (var name in obj) {
+                    size += name.length * 2 + estimateSize(obj[name]);
+                }
+            } else if (type === "string") {
+                size = obj.length * 2;
+            } else {
+                size = 8;
+            }
+            return size;
+        };
+
+        var expectedUris = [];
+        var responseIndex = 0;
+        if (count >= 0) {
+            var minPage = pageIndex(index);
+            var maxPage = Math.min(pageIndex(index + count - 1), pageIndex(this.total));
+
+            // In the case that the index is outside the range of the collection the minPage will be greater than the maxPage  
+            maxPage = Math.max(minPage, maxPage);
+
+            if (!(isPrefetch && !this.exactPageCount && minPage > this.maxPage)) {
+                for (var page = minPage; page <= maxPage && this.actualCount <= this.total && !(isPrefetch && this.overflowed); page++) {
+                    if (!this.cachedPages[page]) {
+
+                        expectedUris.push(that.baseUri + "?$skip=" + page * this.pageSize + "&$top=" + (this.pageSize));
+
+                        var actualPageSize = 0;
+                        var actualPageCount = 0;
+                        if (responses[responseIndex] && responses[responseIndex].data) {
+                            actualPageSize += estimateSize(responses[responseIndex].data);
+                            actualPageCount += responses[responseIndex].data.value.length;
+                            // Handle server paging skipToken requests
+                            while (responses[responseIndex].data["@odata.nextLink"]) {
+                                var nextLink = responses[responseIndex].data["@odata.nextLink"];
+                                if (nextLink) {
+                                    var index = that.baseUri.indexOf(".svc/", 0);
+                                    if (index != -1) {
+                                        nextLink = that.baseUri.substring(0, index + 5) + nextLink;
+                                    }
+                                }
+
+                                expectedUris.push(nextLink);
+                                responseIndex++;
+                                actualPageSize += estimateSize(responses[responseIndex].data);
+                                actualPageCount += responses[responseIndex].data.value.length;
+                            }
+
+                            actualPageSize += 24; // 24 byte overhead for the pages (i)ndex, and (c)ount fields
+                        }
+
+                        responseIndex++;
+
+                        this.overflowed = this.cacheSize >= 0 && this.actualSize + actualPageSize > this.cacheSize;
+                        if (!this.overflowed) {
+                            this.cachedPages[page] = true;
+                            this.actualSize += actualPageSize;
+                            this.actualCount += actualPageCount;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (backwards) {
+            expectedUris.reverse();
+        }
+
+        var actualUris = $.map(requests, function (r) { return r.requestUri; });
+        djstest.assertAreEqualDeep(actualUris, expectedUris, description);
+    };
+
+    CacheVerifier.getExpectedFilterResults = function (data, filterIndex, filterCount, predicate, backwards) {
+        /** Verifies the cache filter returns the correct data
+         * @param {Array} collection - Array of items in the collection
+         * @param {Integer} filterIndex - The index value
+         * @param {Integer} filterCount - The count value
+         * @param {Function} predicate - Predicate to be applied in filter, takes an item
+         * @param {Boolean} backwards - Whether or not filterBackwards is being verified
+         */
+        if (!data || !data.value) {
+            return data;
+        }
+
+        var value = [];
+        if (filterCount !== 0) {
+            // Convert [item0, item1, ...] into [{ index: 0, item: item0 }, { index: 1, item: item1 }, ...]
+            var indexedCollection = $.map(data.value, function (item, index) {
+                return { index: index, item: item };
+            });
+
+            var grepPredicate = function (element, index) {
+                return predicate(element.item);
+            };
+
+            var index = filterIndex < 0 ? 0 : filterIndex;
+            var count = filterCount < 0 ? indexedCollection.length : filterCount;
+
+            value = backwards ?
+            // Slice up to 'index', filter, then slice 'count' number of items from the end
+                $.grep(indexedCollection.slice(0, index + 1), grepPredicate).slice(-count) :
+            // Slice from 'index' to the end, filter, then slice 'count' number of items from the beginning
+                $.grep(indexedCollection.slice(index), grepPredicate).slice(0, count);
+        }
+
+        var expectedResults = {};
+        for (var property in data) {
+            if (property == "value") {
+                expectedResults[property] = value;
+            } else {
+                expectedResults[property] = data[property];
+            }
+        }
+
+        return expectedResults;
+    };
+
+    window.CacheVerifier = CacheVerifier;
+
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/common/odataVerifyReader.js
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/common/odataVerifyReader.js b/odatajs/tests-tmp/common/odataVerifyReader.js
new file mode 100644
index 0000000..14bf54e
--- /dev/null
+++ b/odatajs/tests-tmp/common/odataVerifyReader.js
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+ 
+
+// Client for the odata.read oracle service
+
+(function (window, undefined) {
+    var jsonMime = "application/json";
+    var universalMime = "*/*";
+
+    function readFeed(url, success, mimeType, recognizeDates) {
+        /** Calls the ReadFeed endpoint with the specified URL
+         * @param {String} url - The URL to read the feed from
+         * @param {Function} success - The success callback function
+         * @param {String} mimeType - The MIME media type in the Accept header
+         */
+        var readMethod = getReadMethod(mimeType);
+        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, recognizeDates, function (data) {
+            success(data);
+        });
+    }
+
+    function readEntry(url, success, mimeType, recognizeDates) {
+        /** Calls the ReadEntry endpoint with the specified URL
+         * @param {String} url - The URL to read the entry from
+         * @param {Function} success - The success callback function
+         * @param {String} mimeType - The MIME media type in the Accept header
+         */
+        var readMethod = getReadMethod(mimeType);
+        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, recognizeDates, success);
+    }
+
+    function readLinksEntry(url, success) {
+        /** Calls the ReadMetadata endpoint with the specified URL
+         * @param {String} url - The URL to read the metadata from
+         * @param {Function} success - The success callback function
+         */
+        readJson(
+            url,
+            success
+        );
+    }
+
+    function readLinksFeed(url, success) {
+        /** Calls the ReadMetadata endpoint with the specified URL
+         * @param {String} url - The URL to read the metadata from
+         * @param {Function} success - The success callback function
+         */
+        readJson(
+            url,
+            function (data) {
+                success(data);
+            }
+        );
+    }
+
+    function readMetadata(url, success) {
+        /** Calls the ReadMetadata endpoint with the specified URL
+         * @param {String} url - The URL to read the metadata from
+         * @param {Function} success - The success callback function
+         */
+        oracleRequest("GET", "ReadMetadata", typeof url === "string" ? { url: url} : url, null, null, success);
+    }
+
+    function readServiceDocument (url, success, mimeType) {
+        /** Calls the ReadServiceDocument endpoint with the specified URL
+         * @param {String} url - The URL to the service
+         * @param {Function} success - The success callback function
+         * @param {String} mimeType - The MIME type being tested
+         */
+        var readMethod = getReadMethod(mimeType);
+        oracleRequest("GET", readMethod, typeof url === "string" ? { url: url} : url, mimeType, null, success);
+    }
+
+    function readJson(url, success) {
+        $.ajax({
+            url: url,
+            accepts: null,
+            dataType: "json",
+            beforeSend: function (xhr) {
+                xhr.setRequestHeader("Accept", jsonMime);
+                xhr.setRequestHeader("OData-MaxVersion", "4.0");
+            },
+            success: function (data) {
+                success(data);
+            }
+        });
+    }
+
+    function readJsonAcrossServerPages(url, success) {
+        var data = {};
+        var readPage = function (url) {
+            readJson(url, function (feedData) {
+                var nextLink = feedData["@odata.nextLink"];
+                if (nextLink) {
+                    var index = url.indexOf(".svc/", 0);
+                    if (index != -1) {
+                        nextLink = url.substring(0, index + 5) + nextLink;
+                    }
+                }
+
+                if (data.value && feedData.value) {
+                    data.value = data.value.concat(feedData.value);
+                }
+                else {
+                    for (var property in feedData) {
+                        if (property != "@odata.nextLink") {
+                            data[property] = feedData[property];
+                        }
+                    }
+                }
+
+                if (nextLink) {
+                    readPage(nextLink);
+                }
+                else {
+                    success(data);
+                }
+            });
+        };
+
+        readPage(url);
+    }
+
+    function getReadMethod(mimeType) {
+        switch (mimeType) {
+            case jsonMime:
+            case universalMime:
+                /* falls through */
+            default:
+                return "ReadJson";
+        }
+        return undefined;
+    }
+
+    function oracleRequest(method, endpoint, data, mimeType, recognizeDates, success) {
+        /** Requests a JSON object from the oracle service, removing WCF-specific artifacts
+         * @param {String} method - The HTTP method (GET or POST)
+         * @param {String} endpoint - The oracle endpoint
+         * @param {Object} data - The data to send with the request
+         * @param {Function} reviver - The reviver function to run on each deserialized object
+         * @param {Function} success - Success callback
+         */
+        var url = "./common/ODataVerifiyReader.svc/" + endpoint;
+        if (mimeType) {
+            data.mimeType = mimeType;
+        }
+
+        $.ajax({
+            type: method,
+            url: url,
+            data: data,
+            dataType: "text",
+            success: function (data) {
+                var json = JSON.parse(data);
+                success(json);
+            }
+        });
+    }
+
+    function removeProperty(data, property) {
+        /** Removes the specified property recursively from the given object
+         * @param {Object} data - The object to operate on
+         * @param {String} property - The name of the property to remove
+         */
+        if (typeof data === "object" && data !== null) {
+            if (data[property]) {
+                delete data[property];
+            }
+
+            for (var prop in data) {
+                removeProperty(data[prop], property);
+            }
+        }
+    }
+
+    window.ODataVerifyReader = {
+        readFeed: readFeed,
+        readEntry: readEntry,
+        readLinksEntry: readLinksEntry,
+        readLinksFeed: readLinksFeed,
+        readJson: readJson,
+        readJsonAcrossServerPages: readJsonAcrossServerPages,
+        readMetadata: readMetadata,
+        readServiceDocument: readServiceDocument
+    };
+})(this);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/done.txt
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/done.txt b/odatajs/tests-tmp/done.txt
new file mode 100644
index 0000000..85ca39b
--- /dev/null
+++ b/odatajs/tests-tmp/done.txt
@@ -0,0 +1,29 @@
+This tests-tmp folder will repleace the tests folder.
+The plan is to 
+- select test case per testcase,
+- verify it, and 
+- copy it to the tmp-tests
+- once each tests is checkt and copied the folder tests will be deleted and replaced by tmp-tests
+
+DONE
+
+TestSynchronizerClient.js 
+  -> removed
+  -> Moved from custom c# logging service to jenkins
+
+ODataReadOracle.js 
+  -> removed
+  -> TODO check dependencies
+
+rx.js 
+  -> removed
+  -> TODO check dependencies
+
+odata-json-test.js 
+  -> copied and splittet 
+
+  
+ODataReadOracle.js -> odataVerifyReader.js
+ODataReadOracle.svc -> odataVerifyReader.svc
+
+ODataReadOracle -> odataVerifyReader

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/BasicAuthDataService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/BasicAuthDataService.svc b/odatajs/tests-tmp/endpoints/BasicAuthDataService.svc
new file mode 100644
index 0000000..e059314
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/BasicAuthDataService.svc
@@ -0,0 +1,124 @@
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.BasicAuthDataService" %>
+/*
+ * 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.
+ */
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using System.Linq;
+    using System.ServiceModel;
+    using System.ServiceModel.Web;
+    using System.Text;
+    using System.Web;
+
+    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    public class BasicAuthDataService : DataService<BasicAuthDataSource>
+    {
+        const string Username = "djsUser";
+        const string Password = "djsPassword";
+        
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
+            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
+            config.UseVerboseErrors = true;
+        }
+
+        public BasicAuthDataService()
+            : base()
+        {
+            this.ProcessingPipeline.ProcessingRequest += OnRequest;
+        }
+
+        [WebInvoke]
+        public void ResetData()
+        {
+            this.CurrentDataSource.ResetData();
+        }
+
+        private static void UnauthorizedRequest(DataServiceOperationContext context)
+        {
+            context.ResponseHeaders["WWW-Authenticate"] = "Basic realm=\"DataJS.Tests\"";
+            throw new DataServiceException(401, "401 Unauthorized");
+        }
+
+        private void OnRequest(object sender, DataServiceProcessingPipelineEventArgs e)
+        {
+            string authHeader = e.OperationContext.RequestHeaders["Authorization"];
+            
+            // Validate the Authorization header
+            if (authHeader == null || !authHeader.StartsWith("Basic"))
+            {
+                UnauthorizedRequest(e.OperationContext);
+            }
+
+            // Decode the username and password from the header
+            string base64Credentials = authHeader.Substring(6);
+            string[] credentials = Encoding.ASCII.GetString(Convert.FromBase64String(base64Credentials)).Split(':');
+            if (credentials.Length != 2 || !(credentials[0].Equals(Username) && credentials[1].Equals(Password)))
+            {
+                UnauthorizedRequest(e.OperationContext);
+            }
+        }
+    }
+
+    public class BasicAuthDataSource : ReflectionDataContext, IUpdatable
+    {
+        private static bool dataInitialized;
+
+        public IQueryable<Customer> Customers
+        {
+            get { return this.GetResourceSetEntities<Customer>("Customers").AsQueryable(); }
+        }
+
+        public void ResetData()
+        {
+            this.ClearData();
+
+            IList<Customer> customers = this.GetResourceSetEntities<Customer>("Customers");
+            foreach (int i in Enumerable.Range(1, 16))
+            {
+                customers.Add(new Customer()
+                {
+                    ID = i,
+                    Name = "Customer " + i
+                });
+            }
+        }
+
+        protected override void EnsureDataIsInitialized()
+        {
+            if (!dataInitialized)
+            {
+                this.ResetData();
+                dataInitialized = true;
+            }
+        }
+    }
+
+    public class Customer
+    {
+        public int ID { get; set; }
+        public string Name { get; set; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/CustomAnnotations.xml
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/CustomAnnotations.xml b/odatajs/tests-tmp/endpoints/CustomAnnotations.xml
new file mode 100644
index 0000000..ebf4e26
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/CustomAnnotations.xml
@@ -0,0 +1,121 @@
+<!--/*
+ * 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.
+*/
+-->
+<?xml version="1.0" encoding="utf-8"?>
+<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" Version="1.0">
+  <edmx:DataServices m:DataServiceVersion="2.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
+    <Schema xmlns="http://schemas.microsoft.com/ado/2007/05/edm" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:mcns="http://MyCustomNamespace.com"
+             Namespace="DataJS.Tests">
+      <EntityType Name="MappedEntry" mcns:MyCustomAnnotation="My custom attribute.">
+        <Key mcns:MyCustomAnnotation="//">
+          <PropertyRef Name="ID" mcns:MyCustomAnnotation="  "/>
+        </Key>
+        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
+        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
+        <Property Name="Author" Nullable="false" Type="DataJS.Tests.Author" m:FC_KeepInContent_5="false" m:FC_SourcePath_5="Contributor/Name" m:FC_ContentKind_5="text" m:FC_TargetPath_5="SyndicationContributorName" m:FC_KeepInContent_4="false" m:FC_SourcePath_4="Contributor/Email" m:FC_ContentKind_4="text" m:FC_TargetPath_4="SyndicationContributorEmail" m:FC_KeepInContent_3="false" m:FC_SourcePath_3="Uri" m:FC_ContentKind_3="text" m:FC_TargetPath_3="SyndicationAuthorUri" m:FC_KeepInContent_2="false" m:FC_SourcePath_2="Name" m:FC_ContentKind_2="text" m:FC_TargetPath_2="SyndicationAuthorName" m:FC_KeepInContent_1="false" m:FC_SourcePath_1="Email" m:FC_ContentKind_1="text" m:FC_TargetPath_1="SyndicationAuthorEmail" m:FC_KeepInContent="false" m:FC_SourcePath="Contributor/Uri" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationContributorUri"/>
+        <Property Name="Published" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationPublished"/>
+        <Property Name="Rights" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationRights"/>
+        <Property Name="Summary" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="xhtml" m:FC_TargetPath="SyndicationSummary"/>
+        <Property Name="Title" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="html" m:FC_TargetPath="SyndicationTitle"/>
+        <Property Name="Updated" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationUpdated"/>
+        <Property Name="CustomElement" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="customElement" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
+        <Property Name="CustomAttribute" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="customElement/@customAttribute" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
+        <Property Name="NestedElement1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/nestedElement1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="NestedElement2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/nestedElement2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="CommonAttribute1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/@commonAttribute1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="CommonAttribute2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="commonElement/@commonAttribute2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="Location" Nullable="false" Type="DataJS.Tests.Location" m:FC_KeepInContent_1="false" m:FC_SourcePath_1="Long" m:FC_TargetPath_1="long" m:FC_KeepInContent="false" m:FC_SourcePath="Lat" m:FC_TargetPath="lat" m:FC_NsPrefix="geo" m:FC_NsUri="http://www.georss.org/georss" m:FC_NsPrefix_1="geo" m:FC_NsUri_1="http://www.georss.org/georss"/>
+      </EntityType>
+      <ComplexType Name="Author" mcns:MyCustomAnnotation="">
+        <Property Name="Email" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation=""/>
+        <Property Name="Name" Nullable="true" Type="Edm.String"/>
+        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
+        <Property Name="Contributor" Nullable="false" Type="DataJS.Tests.Contributor"/>
+      </ComplexType>
+      <ComplexType Name="Contributor">
+        <Property Name="Email" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation=" "/>
+        <Property Name="Name" Nullable="true" Type="Edm.String"/>
+        <Property Name="Uri" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation="true"/>
+      </ComplexType>
+      <ComplexType Name="Location">
+        <Property Name="Lat" Nullable="false" Type="Edm.Single" mcns:MyCustomAnnotation="27"/>
+        <Property Name="Long" Nullable="false" Type="Edm.Single"/>
+      </ComplexType>
+      <EntityType Name="ReplicatedEntry">
+        <Key>
+          <PropertyRef Name="ID"/>
+        </Key>
+        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
+        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
+        <Property Name="Author" Nullable="false" Type="DataJS.Tests.Author2" m:FC_KeepInContent_5="true" m:FC_SourcePath_5="Contributor/Uri" m:FC_ContentKind_5="text" m:FC_TargetPath_5="SyndicationContributorUri" m:FC_KeepInContent_4="true" m:FC_SourcePath_4="Contributor/Name" m:FC_ContentKind_4="text" m:FC_TargetPath_4="SyndicationContributorName" m:FC_KeepInContent_3="true" m:FC_SourcePath_3="Contributor/Email" m:FC_ContentKind_3="text" m:FC_TargetPath_3="SyndicationContributorEmail" m:FC_KeepInContent_2="true" m:FC_SourcePath_2="Uri" m:FC_ContentKind_2="text" m:FC_TargetPath_2="SyndicationAuthorUri" m:FC_KeepInContent_1="true" m:FC_SourcePath_1="Name" m:FC_ContentKind_1="text" m:FC_TargetPath_1="SyndicationAuthorName" m:FC_KeepInContent="true" m:FC_SourcePath="Email" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationAuthorEmail" mcns:MyCustomAnnotation="b>100/b>"/>
+        <Property Name="Published" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationPublished" mcns:MyCustomAnnotation=" . "/>
+        <Property Name="Rights" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationRights"/>
+        <Property Name="Summary" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="xhtml" m:FC_TargetPath="SyndicationSummary" mcns:MyCustomAnnotation="/Property"/>
+        <Property Name="Title" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="html" m:FC_TargetPath="SyndicationTitle"/>
+        <Property Name="Updated" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_ContentKind="text" m:FC_TargetPath="SyndicationUpdated"/>
+        <Property Name="CustomElement" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="customElement" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
+        <Property Name="CustomAttribute" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="customElement/@customAttribute" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.org/dummy"/>
+        <Property Name="NestedElement1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/nestedElement1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="NestedElement2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/nestedElement2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="CommonAttribute1" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/@commonAttribute1" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="CommonAttribute2" Nullable="true" Type="Edm.String" m:FC_KeepInContent="true" m:FC_TargetPath="commonElement/@commonAttribute2" m:FC_NsPrefix="pr" m:FC_NsUri="http://www.example.com/dummy"/>
+        <Property Name="Location" Nullable="false" Type="DataJS.Tests.Location2" m:FC_KeepInContent_1="true" m:FC_SourcePath_1="Long" m:FC_TargetPath_1="long" m:FC_KeepInContent="true" m:FC_SourcePath="Lat" m:FC_TargetPath="lat" m:FC_NsPrefix="geo" m:FC_NsUri="http://www.georss.org/georss" m:FC_NsPrefix_1="geo" m:FC_NsUri_1="http://www.georss.org/georss"/>
+      </EntityType>
+      <ComplexType Name="Author2">
+        <Property Name="Email" Nullable="true" Type="Edm.String"/>
+        <Property Name="Name" Nullable="true" Type="Edm.String"/>
+        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
+        <Property Name="Contributor" Nullable="false" Type="DataJS.Tests.Contributor2"/>
+      </ComplexType>
+      <ComplexType Name="Contributor2">
+        <Property Name="Email" Nullable="true" Type="Edm.String"/>
+        <Property Name="Name" Nullable="true" Type="Edm.String"/>
+        <Property Name="Uri" Nullable="true" Type="Edm.String"/>
+      </ComplexType>
+      <ComplexType Name="Location2">
+        <Property Name="Lat" Nullable="false" Type="Edm.Single"/>
+        <Property Name="Long" Nullable="false" Type="Edm.Single"/>
+      </ComplexType>
+      <EntityType Name="DerivedEntry" m:FC_KeepInContent="false" m:FC_SourcePath="MappedInDerivedField" m:FC_TargetPath="mappedField/@mappedInDerived" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy" BaseType="DataJS.Tests.BaseEntry">
+        <Property Name="UnmappedConcreteField" Nullable="true" Type="Edm.String"/>
+        <Property Name="MappedConcreteField" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="mappedField/@mappedConcrete" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy"/>
+      </EntityType>
+      <EntityType Name="BaseEntry">
+        <Key>
+          <PropertyRef Name="ID"/>
+        </Key>
+        <Property Name="ID" Nullable="false" Type="Edm.Int32"/>
+        <Property Name="UnmappedField" Nullable="true" Type="Edm.String"/>
+        <Property Name="MappedInDerivedField" Nullable="true" Type="Edm.String" mcns:MyCustomAnnotation="false"/>
+        <Property Name="MappedField" Nullable="true" Type="Edm.String" m:FC_KeepInContent="false" m:FC_TargetPath="mappedField" m:FC_NsPrefix="pre" m:FC_NsUri="http://www.example.com/dummy"/>
+      </EntityType>
+      <EntityContainer Name="EpmDataSource" m:IsDefaultEntityContainer="true" mcns:MyCustomAnnotation="0">
+        <EntitySet Name="MappedEntries" EntityType="DataJS.Tests.MappedEntry"/>
+        <EntitySet Name="ReplicatedEntries" EntityType="DataJS.Tests.ReplicatedEntry"/>
+        <EntitySet Name="HierarchicalEntries" EntityType="DataJS.Tests.BaseEntry"/>
+        <FunctionImport Name="ResetData" m:HttpMethod="POST" mcns:MyCustomAnnotation="null"/>
+      </EntityContainer>
+      <mcns:EmptyElement></mcns:EmptyElement>
+      <mcns:ParentCustomElement mcns:MyCustomAnnotation="annotation" mcns:MySecondCustomAnnotation="annotation 2">
+        <mcns:CustomChildElement1>Custom metadata 1.</mcns:CustomChildElement1>
+        <mcns:CustomChildElement2>Custom metadata 2.</mcns:CustomChildElement2>
+      </mcns:ParentCustomElement>
+    </Schema>
+  </edmx:DataServices>
+</edmx:Edmx>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/CustomDataService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/CustomDataService.svc b/odatajs/tests-tmp/endpoints/CustomDataService.svc
new file mode 100644
index 0000000..67fcfd0
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/CustomDataService.svc
@@ -0,0 +1,85 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebServiceHostFactory"
+    Service="DataJS.Tests.CustomDataService" %>
+
+
+using System.Collections;
+using System.IO;
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using System.ServiceModel;
+    using System.ServiceModel.Activation;
+    using System.ServiceModel.Web;
+
+    /// <summary>
+    /// Custom data service that does not use OData
+    /// </summary>
+    [ServiceContract]
+    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
+    public class CustomDataService
+    {
+        static readonly Item[] data = Enumerable.Range(0, 16).Select(i => new Item
+        {
+            ID = i,
+            Name = "Item " + i
+        }).ToArray();
+
+        // This uses the same URI template as OData so that the CacheOracle can be reused
+        [OperationContract]
+        [WebGet(UriTemplate = "ReadRange?$skip={skip}&$top={top}")]
+        public Stream ReadRange(int skip, int top)
+        {
+            IEnumerable selectData = data.Skip(skip).Take(top);
+            Dictionary<string, object> result = new Dictionary<string, object>();
+            List<Dictionary<string, string>> value = new List<Dictionary<string, string>>(); 
+            foreach (Item d in selectData)
+            {
+                Dictionary<string, string> item = new Dictionary<string, string>();
+                item.Add("ID", d.ID.ToString());
+                item.Add("Name", d.Name);
+                value.Add(item);
+            }
+            
+            result.Add("value", value);
+            return ReaderUtils.ConvertDictionarytoJsonlightStream(result);
+        }
+
+        [OperationContract]
+        [WebGet(ResponseFormat = WebMessageFormat.Json)]
+        public int Count()
+        {
+            return data.Count();
+        }
+    }
+
+    public class Item
+    {
+        public int ID { get; set; }
+        public string Name { get; set; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/EpmDataService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/EpmDataService.svc b/odatajs/tests-tmp/endpoints/EpmDataService.svc
new file mode 100644
index 0000000..316c9ae
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/EpmDataService.svc
@@ -0,0 +1,336 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.EpmDataService" %>
+
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using System.Linq;
+    using System.ServiceModel.Web;
+
+    /// <summary>
+    /// A data service that uses EPM
+    /// </summary>
+    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    public class EpmDataService : DataService<EpmDataSource>
+    {
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
+            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
+            config.UseVerboseErrors = true;
+
+        }
+        
+        [WebInvoke]
+        public void ResetData()
+        {
+            this.CurrentDataSource.ResetData();
+        }
+    }
+
+    public class EpmDataSource : ReflectionDataContext, IUpdatable
+    {
+        private static bool dataInitialized;
+
+        public IQueryable<MappedEntry> MappedEntries
+        {
+            get { return this.GetResourceSetEntities<MappedEntry>("MappedEntries").AsQueryable(); }
+        }
+
+        public IQueryable<ReplicatedEntry> ReplicatedEntries
+        {
+            get { return this.GetResourceSetEntities<ReplicatedEntry>("ReplicatedEntries").AsQueryable(); }
+        }
+
+        public IQueryable<BaseEntry> HierarchicalEntries
+        {
+            get { return this.GetResourceSetEntities<BaseEntry>("HierarchicalEntries").AsQueryable(); }
+        }
+
+        public void ResetData()
+        {
+            this.ClearData();
+
+            MappedEntry[] mappedEntries = new MappedEntry[]
+            {
+                new MappedEntry
+                {
+                    ID = 0,
+                    UnmappedField = "Unmapped0",
+                    Author = new Author
+                    {
+                        Email = "AuthorEmail0",
+                        Name = "AuthorName0",
+                        Uri = "http://www.example.com/AuthorUri",
+                        Contributor = new Contributor
+                        {
+                            Email = "ContributorEmail0",
+                            Name = "ContributorName0",
+                            Uri = "http://www.example.com/ContributorUri",
+                        },
+                    },
+                    Published = "2000-01-01T00:00:00-08:00",
+                    Rights = "Rights0",
+                    Summary = "<xmlElement xmlns=\"http://www.example.org/dummy\" attr=\"value0\">Summary0</xmlElement>",
+                    Title = "Title<b>0</b>",
+                    Updated = "2000-01-01T00:00:00-08:00",
+                    CustomElement = "CustomElement0",
+                    CustomAttribute = "CustomAttribute0",
+                    NestedElement1 = "NestedElement1_0",
+                    NestedElement2 = "NestedElement2_0",
+                    CommonAttribute1 = "CommonAttribute1_0",
+                    CommonAttribute2 = "CommonAttribute2_0",
+                    Location = new Location
+                    {
+                        Lat = 3.14f,
+                        Long = 2.72f
+                    }
+                },
+                
+                new MappedEntry
+                {
+                    ID = 1,
+                    UnmappedField = null,
+                    Author = new Author
+                    {
+                        Email = null,
+                        Name = string.Empty,
+                        Uri = "http://www.example.com/AuthorUri1",
+                        Contributor = new Contributor
+                        {
+                            Email = null,
+                            Name = string.Empty,
+                            Uri = "http://www.example.com/ContributorUri1",
+                        },
+                    },
+                    Published = "2000-01-01T00:00:00-08:00",
+                    Rights = null,
+                    Summary = "",
+                    Title = "Title<i>1</i>",
+                    Updated = "2111-01-01T00:00:00-08:00",
+                    CustomElement = null,
+                    NestedElement1 = string.Empty,
+                    NestedElement2 = "NestedElement2_1",
+                    CustomAttribute = null,
+                    CommonAttribute1 = string.Empty,
+                    CommonAttribute2 = "CommonAttribute2_1",
+                    Location = new Location
+                    {
+                        Lat = float.MaxValue,
+                        Long = float.MinValue
+                    }
+                },
+                
+                new MappedEntry
+                {
+                    ID = 2,
+                    UnmappedField = "Unmapped2",
+                    Author = new Author
+                    {
+                        Email = "AuthorEmail2",
+                        Name = "AuthorName2",
+                        Uri = "http://www.example.com/AuthorUri2",
+                        Contributor = null
+                    },
+                    Published = "2000-01-01T00:00:00-08:00",
+                    Rights = "Rights2",
+                    Summary = "Summary2",
+                    Title = "Title2",
+                    Updated = "2000-01-01T00:00:00-08:00",
+                    CustomElement = "CustomElement2",
+                    CustomAttribute = "CustomAttribute2",
+                    NestedElement1 = "NestedElement1_2",
+                    NestedElement2 = "NestedElement2_2",
+                    CommonAttribute1 = "CommonAttribute1_2",
+                    CommonAttribute2 = "CommonAttribute2_2",
+                    Location = null
+                },
+            };
+            Array.ForEach(mappedEntries, (item) => this.GetResourceSetEntities<MappedEntry>("MappedEntries").Add(item));
+
+            Array.ForEach(mappedEntries, (item) => this.GetResourceSetEntities<ReplicatedEntry>("ReplicatedEntries").Add(new ReplicatedEntry
+            {
+                ID = item.ID,
+                UnmappedField = item.UnmappedField,
+                Author = item.Author == null ? null : new Author2
+                {
+                    Email = item.Author.Email,
+                    Name = item.Author.Name,
+                    Uri = item.Author.Uri,
+                    Contributor = item.Author.Contributor == null ? null : new Contributor2
+                    {
+                        Name = item.Author.Contributor.Name,
+                        Email = item.Author.Contributor.Email,
+                        Uri = item.Author.Contributor.Uri
+                    },
+                },
+                Published = item.Published,
+                Rights = item.Rights,
+                Summary = item.Summary,
+                Title = item.Title,
+                Updated = item.Updated,
+                CustomElement = item.CustomElement,
+                CustomAttribute = item.CustomAttribute,
+                NestedElement1 = item.NestedElement1,
+                NestedElement2 = item.NestedElement2,
+                CommonAttribute1 = item.CommonAttribute1,
+                CommonAttribute2 = item.CommonAttribute2,
+                Location = item.Location == null ? null : new Location2
+                {
+                    Lat = item.Location.Lat,
+                    Long = item.Location.Long
+                }
+            }));
+
+            BaseEntry[] hierarchicalEntries = new BaseEntry[]
+            {
+                new BaseEntry
+                {
+                    ID = 0,
+                    MappedField = "MappedField0",
+                    MappedInDerivedField = "MappedInDerivedField0",
+                    UnmappedField = "UnmappedField0"
+                },
+                new DerivedEntry
+                {
+                    ID = 1,
+                    MappedField = "MappedField1",
+                    MappedInDerivedField = "MappedInDerivedField1",
+                    UnmappedField = "UnmappedField1",
+                    MappedConcreteField = "MappedConcreteField1",
+                    UnmappedConcreteField = "UnmappedConcreteField1"
+                },
+            };
+            Array.ForEach(hierarchicalEntries, (item) => this.GetResourceSetEntities<BaseEntry>("HierarchicalEntries").Add(item));
+        }
+
+        protected override void EnsureDataIsInitialized()
+        {
+            if (!dataInitialized)
+            {
+                this.ResetData();
+                dataInitialized = true;
+            }
+        }
+    }
+
+    public class Author
+    {
+        public string Email { get; set; }
+        public string Name { get; set; }
+        public string Uri { get; set; }
+        public Contributor Contributor { get; set; }
+    }
+
+    public class Contributor
+    {
+        public string Email { get; set; }
+        public string Name { get; set; }
+        public string Uri { get; set; }
+    }
+    
+    public class Location
+    {
+        public float Lat { get; set; }
+        public float Long { get; set; }
+    }
+
+    public class Author2
+    {
+        public string Email { get; set; }
+        public string Name { get; set; }
+        public string Uri { get; set; }
+        public Contributor2 Contributor { get; set; }
+    }
+
+    public class Contributor2
+    {
+        public string Email { get; set; }
+        public string Name { get; set; }
+        public string Uri { get; set; }
+    }
+
+    public class Location2
+    {
+        public float Lat { get; set; }
+        public float Long { get; set; }
+    }
+    
+    public class MappedEntry
+    {
+        public int ID { get; set; }
+        public string UnmappedField { get; set; }
+        public Author Author { get; set; }
+        public string Published { get; set; }
+        public string Rights { get; set; }
+        public string Summary { get; set; }
+        public string Title { get; set; }
+        public string Updated { get; set; }
+        public string CustomElement { get; set; }
+        public string CustomAttribute { get; set; }
+        public string NestedElement1 { get; set; }
+        public string NestedElement2 { get; set; }
+        public string CommonAttribute1 { get; set; }
+        public string CommonAttribute2 { get; set; }
+        public Location Location { get; set; }
+    }
+
+    public class ReplicatedEntry
+    {
+        public int ID { get; set; }
+        public string UnmappedField { get; set; }
+        public Author2 Author { get; set; }
+        public string Published { get; set; }
+        public string Rights { get; set; }
+        public string Summary { get; set; }
+        public string Title { get; set; }
+        public string Updated { get; set; }
+        public string CustomElement { get; set; }
+        public string CustomAttribute { get; set; }
+        public string NestedElement1 { get; set; }
+        public string NestedElement2 { get; set; }
+        public string CommonAttribute1 { get; set; }
+        public string CommonAttribute2 { get; set; }
+        public Location2 Location { get; set; }
+    }
+    
+    public class BaseEntry
+    {
+        public int ID { get; set; }
+        public string UnmappedField { get; set; }
+        public string MappedInDerivedField { get; set; }
+        public string MappedField { get; set; }
+    }
+    
+    public class DerivedEntry : BaseEntry
+    {
+        public string UnmappedConcreteField { get; set; }
+        public string MappedConcreteField { get; set; }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/d5ec5557/odatajs/tests-tmp/endpoints/ErrorDataService.svc
----------------------------------------------------------------------
diff --git a/odatajs/tests-tmp/endpoints/ErrorDataService.svc b/odatajs/tests-tmp/endpoints/ErrorDataService.svc
new file mode 100644
index 0000000..052a2df
--- /dev/null
+++ b/odatajs/tests-tmp/endpoints/ErrorDataService.svc
@@ -0,0 +1,78 @@
+<!--
+/*
+ * 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.
+ */
+-->
+
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.ErrorDataService" %>
+
+
+
+namespace DataJS.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Microsoft.OData.Service;
+    using System.Linq;
+
+    /// <summary>
+    /// A data service that contains in-stream errors
+    /// </summary>
+    public class ErrorDataService : DataService<ErrorDataSource>
+    {
+        // This method is called only once to initialize service-wide policies.
+        public static void InitializeService(DataServiceConfiguration config)
+        {
+            config.SetEntitySetAccessRule("*", EntitySetRights.All);
+            config.DataServiceBehavior.MaxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4;
+        }
+    }
+
+    public class ErrorDataSource
+    {
+        public IQueryable<ErrorType> Entities
+        {
+            get
+            {
+                ErrorType[] entities = new ErrorType[]
+                {
+                    new ErrorType(() => 0),
+                    new ErrorType(() => { throw new ApplicationException(); })
+                };
+
+                return entities.AsQueryable();
+            }
+        }
+    }
+    
+    public class ErrorType
+    {
+        Func<int> generateID;
+        
+        public ErrorType(Func<int> generateID)
+        {
+            this.generateID = generateID;
+        }
+        
+        public int ID
+        {
+            get { return this.generateID(); }
+        }
+    }
+}
\ No newline at end of file