You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by bi...@apache.org on 2014/05/09 09:22:13 UTC

[04/24] a) Convert all the DataJS supported functionality from V3 to V4. 1. Remove all the Json verbose logic, make the DataJS accepted and returned javascript object be in Json light format. (Since Json verbose has been completely removed on V4, making

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/e387fc92/JSLib/tests/common/djstest.js
----------------------------------------------------------------------
diff --git a/JSLib/tests/common/djstest.js b/JSLib/tests/common/djstest.js
index c7b2de5..4145149 100644
--- a/JSLib/tests/common/djstest.js
+++ b/JSLib/tests/common/djstest.js
@@ -1,400 +1,409 @@
-// Copyright (c) Microsoft Open Technologies, Inc.  All rights reserved.
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
-// files (the "Software"), to deal  in the Software without restriction, including without limitation the rights  to use, copy,
-// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-// WARRANTIES OF MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
-// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-(function (window, undefined) {
-    var djstest = {};
-
-    window.djstest = djstest;
-
-    djstest.indexedDB = window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.indexedDB;
-
-    djstest.cleanStoreOnIndexedDb = function (storeObjects, done) {
-        /// <summary>Cleans all the test data saved in the IndexedDb database.</summary>
-        /// <param name="storeNames" type="Array">Array of store objects with a property that is the name of the store</param>
-        /// <param name="done" type="Function">Callback function</param>
-
-        var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || {};
-
-        var deleteObjectStores = function (db) {
-            $.each(db.objectStoreNames, function (_, storeName) {
-                db.deleteObjectStore(storeName);
-            });
-        };
-
-        if (djstest.indexedDB) {
-            var job = new djstest.Job();
-            $.each(storeObjects, function (_, storeObject) {
-                job.queue((function (storeObject) {
-                    return function (success, fail) {
-                        var dbname = "_datajs_" + storeObject.name;
-                        var request = djstest.indexedDB.open(dbname);
-                        request.onsuccess = function (event) {
-                            var db = request.result;
-
-                            if ("setVersion" in db) {
-                                var versionRequest = db.setVersion("0.1");
-                                versionRequest.onsuccess = function (event) {
-                                    var transaction = versionRequest.transaction;
-                                    transaction.oncomplete = function () {
-                                        db.close();
-                                        success();
-                                    }
-                                    deleteObjectStores(db);
-                                };
-                                versionRequest.onerror = function (e) {
-                                    djstest.fail("Error on cleanup - code: " + e.code + " name: " + e.name + "message: " + message);
-                                    fail();
-                                };
-                                return;
-                            }
-
-                            // new api cleanup
-                            db.close();
-                            var deleteRequest = djstest.indexedDB.deleteDatabase(dbname);
-                            deleteRequest.onsuccess = function (event) {
-                                djstest.log("djstest indexeddb cleanup - deleted database " + dbname);
-                                success();
-                            };
-                            deleteRequest.onerror = function (e) {
-                                djstest.fail("djstest indexeddb cleanup - error deleting database " + dbname);
-                                fail();
-                            };
-                            djstest.log("djstest indexeddb cleanup - requested deletion of database " + dbname);
-                        };
-
-                        request.onerror = function (e) {
-                            djstest.fail(e.code + ": " + e.message);
-                        };
-                    };
-                })(storeObject));
-            });
-        }
-
-        if (job) {
-            job.run(function (succeeded) {
-                if (!succeeded) {
-                    djstest.fail("cleanup job failed");
-                }
-                done();
-            });
-        }
-        else {
-            done();
-        }
-    };
-
-    djstest.Job = function () {
-        /// <summary>Constructs a Job object that allows for enqueuing and synchronizing the execution of functions.</summary>
-        /// <returns type="Object">Job object</returns>
-        var currentTask = -1;
-        var tasks = [];
-
-        var failedTasks = 0;
-
-        this.queue = function (fn) {
-            /// <summary>Adds a function to the job queue regardless if the queue is already executing or not.</summary>
-            /// <param name="fn" type="Function">Function to execute.</param>
-            tasks.push(fn);
-        };
-
-        this.queueNext = function (fn) {
-            /// <summary>Adds a function to the front of the job queue regardless if the queue is already executing or not.</summary>
-            /// <param name="fn" type="Function">Function to execute.</param>
-            if (currentTask < 0) {
-                tasks.unshift(fn);
-            } else {
-                tasks.splice(currentTask + 1, 0, fn);
-            }
-        };
-
-        this.run = function (done) {
-            /// <summary>Starts the execution of this job.</summary>
-            /// <param name="done" type="Function">Callback invoked when the job has finished executing all of its enqueued tasks.</param>
-            /// <remarks>
-            /// This method does nothing if called on a unit of work that is already executing.
-            /// </remarks>
-
-            if (currentTask >= 0) {
-                return;
-            }
-
-            if (tasks.length === 0) {
-                done(true);
-                return;
-            }
-
-            var makeTaskDoneCallBack = function (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();
-                    }
-                };
-            };
-
-            var runNextTask = function () {
-                /// <summary>Executes the next function in the queue.</summary>
-                defer(function () {
-                    try {
-                        tasks[currentTask](makeTaskDoneCallBack(false), makeTaskDoneCallBack(true));
-                    } catch (e) {
-                        makeTaskDoneCallBack(true)();
-                    }
-                });
-            };
-
-            currentTask = 0;
-            runNextTask();
-        };
-    };
-
-    var defer = function (fn) {
-        /// <summary>Defers the execution of an arbitrary function that takes no parameters.</summary>
-        /// <param name="fn" type="Function">Function to schedule for later execution.</param>
-        setTimeout(fn, 0);
-    }
-
-    var exposeDateValues = function (data) {
-        /// <summary>Exposes date values for Date objects to facilitate debugging</summary>
-        /// <param name="data" type="Object">The object to operate on</param>
-        if (typeof data === "object") {
-            if (data instanceof Date) {
-                data["__date__"] = data.toUTCString();
-            }
-            else {
-                for (var prop in data) {
-                    exposeDateValues(data[prop]);
-                }
-            }
-        }
-
-        return data;
-    }
-
-    var extractFunctionName = function (text) {
-        /// <summary>Determines the name of a function.</summary>
-        /// <param name="text" type="String">Function text.</param>
-        /// <returns type="String">The name of the function from text if found; the original text otherwise.</returns>
-
-        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;
-    };
-
-    var removeMetadata = function (data) {
-        /// <summary>Removes metadata annotations from the specified object.</summary>
-        /// <param name="data">Object to remove metadata from; possibly null.</param>
-
-        if (typeof data === "object" && data !== null) {
-            delete data["__metadata"];
-            for (prop in data) {
-                removeMetadata(data[prop]);
-            }
-        }
-    };
-
-    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);
-        });
-    }
-
-    djstest.assert = function (test, message) {
-        /// <summary>Asserts that a condition is true.</summary>
-        /// <param name="test" type="Boolean">Condition to test.</param>
-        /// <param name="message" type="String">Text message for condition being tested.</param>
-        QUnit.ok(test, message);
-    };
-
-    djstest.assertAreEqual = function (actual, expected, message) {
-        /// <summary>Asserts that the values of the expected and actualobjects are equal.</summary>
-        QUnit.equal(actual, expected, message);
-    };
-
-    djstest.assertAreEqualDeep = function (actual, expected, message) {
-        /// <summary>Asserts that the actual and expected objects are the same.</summary>
-        QUnit.deepEqual(exposeDateValues(actual), exposeDateValues(expected), message);
-    };
-
-    djstest.assertWithoutMetadata = function (actual, expected, message) {
-        removeMetadata(actual)
-        removeMetadata(expected);
-        djstest.assertAreEqualDeep(actual, expected, message);
-    };
-
-    djstest.asyncDo = function (asyncActions, done) {
-        /// <summary>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.</summary>
-        /// <param name="asyncActions" type="Array">Array of asynchronous actions to be executed, 
-        /// each taking a single parameter - the callback function to call when the action is done.</param>
-        /// <param name="done" type="Function">Function to be executed in the last async action to complete.</param>
-        var count = 0;
-        var doneOne = function () {
-            count++;
-            if (count >= asyncActions.length) {
-                done();
-            }
-        };
-
-        if (asyncActions.length > 0) {
-            $.each(asyncActions, function (_, asyncAction) {
-                asyncAction(doneOne);
-            });
-        } else {
-            done();
-        }
-    }
-
-    djstest.clone = function (object) {
-        /// <summary>Makes a deep copy of an object.</summary>
-        return $.extend(true, {}, object);
-    };
-
-    djstest.destroyCacheAndDone = function (cache) {
-        /// <summary>Destroys the cache and then completes the test</summary>
-        /// <param name="cache">The cache to destroy</param>
-        cache.clear().then(function () {
-            djstest.done();
-        }, function (err) {
-            djstest.fail("Failed to destroy cache: " + djstest.toString(err));
-            djstest.done();
-        });
-    };
-
-    djstest.done = function () {
-        /// <summary>Indicates that the currently running test has finished.</summary>
-        QUnit.start();
-    };
-
-    djstest.expectException = function (testFunction, message) {
-        /// <summary>Test passes if and only if an exception is thrown.</summary>
-        try {
-            testFunction();
-            djstest.fail("Expected exception but function succeeded: " + " " + message);
-        }
-        catch (e) {
-            // Swallow exception.
-            djstest.pass("Thrown exception expected");
-        }
-    };
-
-    djstest.assertsExpected = function (asserts) {
-        /// <summary>Indicates the expected number of asserts, fails test if number is not met.</summary>
-        /// <param name="asserts" type="Number">Number of asserts expected in test.</param>
-        expect(asserts);
-    }
-
-    djstest.fail = function (message) {
-        /// <summary>Marks the current test as failed.</summary>
-        /// <param name="message" type="String">Failure message.</param>
-        QUnit.ok(false, message);
-    };
-
-    djstest.failAndDoneCallback = function (message, cleanupCallback) {
-        /// <summary>Returns a function that when invoked will fail this test and be done with it.</summary>
-        /// <param name="message" type="String">Failure message.</param>
-        /// <param name="cleanupCallback" type="Function" optional="true">Optional cleanup function in case of failure.</param>
-        /// <returns type="Function">A new function.</returns>
-
-        return function (err) {
-            message = "" + message + (err) ? window.JSON.stringify(err) : "";
-            djstest.fail(message);
-            if (cleanupCallback) {
-                try {
-                    cleanupCallback();
-                } catch (e) {
-                    djstest.fail("error during cleanupCallback: " + window.JSON.stringify(e));
-                }
-            }
-
-            djstest.done();
-        };
-    };
-
-    djstest.log = function (message) {
-        /// <summary>Logs a test message.</summary>
-        /// <param name="message" type="String">Test message.</param>
-        var context = { result: true, actual: true, expected: true, message: message };
-        QUnit.log(context);
-    };
-
-    djstest.pass = function (message) {
-        /// <summary>Marks the current test as failed.</summary>
-        /// <param name="message" type="String">Failure message.</param>
-        QUnit.ok(true, message);
-    };
-
-    djstest.toString = function (obj) {
-        /// <summary>Dumps the object as a string</summary>
-        /// <param name="obj" type="Object">Object to dump</param>
-        return QUnit.jsDump.parse(obj);
-    };
-
-    djstest.wait = function (fn) {
-        /// <summary>Executes the function, pausing test execution until the callback is called</summary>
-        /// <param name="fn" type="Function">Function to execute; takes one parameter which is the callback</param>
-        /// <remarks>This function is typically used in asynchronous setup/teardown methods</remarks>
-        QUnit.stop();
-        fn(function () {
-            QUnit.start();
-        });
-    };
-
-    // Disable caching to ensure that every test-related AJAX request is actually being sent,
-    // and set up a default error handler
-    $.ajaxSetup({
-        cache: false,
-        error: function (jqXHR, textStatus, errorThrown) {
-            // Work around bug in IE-Mobile on Windows Phone 7
-            if (jqXHR.status !== 1223) {
-                var err = {
-                    status: jqXHR.status,
-                    statusText: jqXHR.statusText,
-                    responseText: jqXHR.responseText
-                };
-                djstest.fail("AJAX request failed with: " + djstest.toString(err));
-            }
-            djstest.done();
-        }
-    });
+// Copyright (c) Microsoft Open Technologies, Inc.  All rights reserved.
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
+// files (the "Software"), to deal  in the Software without restriction, including without limitation the rights  to use, copy,
+// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+// WARRANTIES OF MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+(function (window, undefined) {
+    var djstest = {};
+
+    window.djstest = djstest;
+
+    djstest.indexedDB = window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.indexedDB;
+
+    djstest.cleanStoreOnIndexedDb = function (storeObjects, done) {
+        /// <summary>Cleans all the test data saved in the IndexedDb database.</summary>
+        /// <param name="storeNames" type="Array">Array of store objects with a property that is the name of the store</param>
+        /// <param name="done" type="Function">Callback function</param>
+
+        var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || {};
+
+        var deleteObjectStores = function (db) {
+            $.each(db.objectStoreNames, function (_, storeName) {
+                db.deleteObjectStore(storeName);
+            });
+        };
+
+        if (djstest.indexedDB) {
+            var job = new djstest.Job();
+            $.each(storeObjects, function (_, storeObject) {
+                job.queue((function (storeObject) {
+                    return function (success, fail) {
+                        var dbname = "_datajs_" + storeObject.name;
+                        var request = djstest.indexedDB.open(dbname);
+                        request.onsuccess = function (event) {
+                            var db = request.result;
+
+                            if ("setVersion" in db) {
+                                var versionRequest = db.setVersion("0.1");
+                                versionRequest.onsuccess = function (event) {
+                                    var transaction = versionRequest.transaction;
+                                    transaction.oncomplete = function () {
+                                        db.close();
+                                        success();
+                                    }
+                                    deleteObjectStores(db);
+                                };
+                                versionRequest.onerror = function (e) {
+                                    djstest.fail("Error on cleanup - code: " + e.code + " name: " + e.name + "message: " + message);
+                                    fail();
+                                };
+                                return;
+                            }
+
+                            // new api cleanup
+                            db.close();
+                            var deleteRequest = djstest.indexedDB.deleteDatabase(dbname);
+                            deleteRequest.onsuccess = function (event) {
+                                djstest.log("djstest indexeddb cleanup - deleted database " + dbname);
+                                success();
+                            };
+                            deleteRequest.onerror = function (e) {
+                                djstest.fail("djstest indexeddb cleanup - error deleting database " + dbname);
+                                fail();
+                            };
+                            djstest.log("djstest indexeddb cleanup - requested deletion of database " + dbname);
+                        };
+
+                        request.onerror = function (e) {
+                            djstest.fail(e.code + ": " + e.message);
+                        };
+                    };
+                })(storeObject));
+            });
+        }
+
+        if (job) {
+            job.run(function (succeeded) {
+                if (!succeeded) {
+                    djstest.fail("cleanup job failed");
+                }
+                done();
+            });
+        }
+        else {
+            done();
+        }
+    };
+
+    djstest.Job = function () {
+        /// <summary>Constructs a Job object that allows for enqueuing and synchronizing the execution of functions.</summary>
+        /// <returns type="Object">Job object</returns>
+        var currentTask = -1;
+        var tasks = [];
+
+        var failedTasks = 0;
+
+        this.queue = function (fn) {
+            /// <summary>Adds a function to the job queue regardless if the queue is already executing or not.</summary>
+            /// <param name="fn" type="Function">Function to execute.</param>
+            tasks.push(fn);
+        };
+
+        this.queueNext = function (fn) {
+            /// <summary>Adds a function to the front of the job queue regardless if the queue is already executing or not.</summary>
+            /// <param name="fn" type="Function">Function to execute.</param>
+            if (currentTask < 0) {
+                tasks.unshift(fn);
+            } else {
+                tasks.splice(currentTask + 1, 0, fn);
+            }
+        };
+
+        this.run = function (done) {
+            /// <summary>Starts the execution of this job.</summary>
+            /// <param name="done" type="Function">Callback invoked when the job has finished executing all of its enqueued tasks.</param>
+            /// <remarks>
+            /// This method does nothing if called on a unit of work that is already executing.
+            /// </remarks>
+
+            if (currentTask >= 0) {
+                return;
+            }
+
+            if (tasks.length === 0) {
+                done(true);
+                return;
+            }
+
+            var makeTaskDoneCallBack = function (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();
+                    }
+                };
+            };
+
+            var runNextTask = function () {
+                /// <summary>Executes the next function in the queue.</summary>
+                defer(function () {
+                    try {
+                        tasks[currentTask](makeTaskDoneCallBack(false), makeTaskDoneCallBack(true));
+                    } catch (e) {
+                        makeTaskDoneCallBack(true)();
+                    }
+                });
+            };
+
+            currentTask = 0;
+            runNextTask();
+        };
+    };
+
+    var defer = function (fn) {
+        /// <summary>Defers the execution of an arbitrary function that takes no parameters.</summary>
+        /// <param name="fn" type="Function">Function to schedule for later execution.</param>
+        setTimeout(fn, 0);
+    }
+
+    var exposeDateValues = function (data) {
+        /// <summary>Exposes date values for Date objects to facilitate debugging</summary>
+        /// <param name="data" type="Object">The object to operate on</param>
+        if (typeof data === "object") {
+            if (data instanceof Date) {
+                data["__date__"] = data.toUTCString();
+            }
+            else {
+                for (var prop in data) {
+                    exposeDateValues(data[prop]);
+                }
+            }
+        }
+
+        return data;
+    }
+
+    var extractFunctionName = function (text) {
+        /// <summary>Determines the name of a function.</summary>
+        /// <param name="text" type="String">Function text.</param>
+        /// <returns type="String">The name of the function from text if found; the original text otherwise.</returns>
+
+        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;
+    };
+
+    var removeMetadata = function (data) {
+        /// <summary>Removes metadata annotations from the specified object.</summary>
+        /// <param name="data">Object to remove metadata from; possibly null.</param>
+
+        if (typeof data === "object" && data !== null) {
+            delete data["__metadata"];
+            for (prop in data) {
+                removeMetadata(data[prop]);
+            }
+        }
+    };
+
+    djstest.addFullTest = function (disable, fn, name, arg, timeout) {
+        /// <summary>Add the unit test cases</summary>
+        /// <param name="disable">Indicate whether this test case should be disabled</param>
+        if (disable != true) {
+            djstest.addTest(fn, name, arg, timeout);
+        }
+    };
+
+
+    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);
+        });
+    };
+
+    djstest.assert = function (test, message) {
+        /// <summary>Asserts that a condition is true.</summary>
+        /// <param name="test" type="Boolean">Condition to test.</param>
+        /// <param name="message" type="String">Text message for condition being tested.</param>
+        QUnit.ok(test, message);
+    };
+
+    djstest.assertAreEqual = function (actual, expected, message) {
+        /// <summary>Asserts that the values of the expected and actualobjects are equal.</summary>
+        QUnit.equal(actual, expected, message);
+    };
+
+    djstest.assertAreEqualDeep = function (actual, expected, message) {
+        /// <summary>Asserts that the actual and expected objects are the same.</summary>
+        QUnit.deepEqual(exposeDateValues(actual), exposeDateValues(expected), message);
+    };
+
+    djstest.assertWithoutMetadata = function (actual, expected, message) {
+        removeMetadata(actual)
+        removeMetadata(expected);
+        djstest.assertAreEqualDeep(actual, expected, message);
+    };
+
+    djstest.asyncDo = function (asyncActions, done) {
+        /// <summary>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.</summary>
+        /// <param name="asyncActions" type="Array">Array of asynchronous actions to be executed, 
+        /// each taking a single parameter - the callback function to call when the action is done.</param>
+        /// <param name="done" type="Function">Function to be executed in the last async action to complete.</param>
+        var count = 0;
+        var doneOne = function () {
+            count++;
+            if (count >= asyncActions.length) {
+                done();
+            }
+        };
+
+        if (asyncActions.length > 0) {
+            $.each(asyncActions, function (_, asyncAction) {
+                asyncAction(doneOne);
+            });
+        } else {
+            done();
+        }
+    }
+
+    djstest.clone = function (object) {
+        /// <summary>Makes a deep copy of an object.</summary>
+        return $.extend(true, {}, object);
+    };
+
+    djstest.destroyCacheAndDone = function (cache) {
+        /// <summary>Destroys the cache and then completes the test</summary>
+        /// <param name="cache">The cache to destroy</param>
+        cache.clear().then(function () {
+            djstest.done();
+        }, function (err) {
+            djstest.fail("Failed to destroy cache: " + djstest.toString(err));
+            djstest.done();
+        });
+    };
+
+    djstest.done = function () {
+        /// <summary>Indicates that the currently running test has finished.</summary>
+        QUnit.start();
+    };
+
+    djstest.expectException = function (testFunction, message) {
+        /// <summary>Test passes if and only if an exception is thrown.</summary>
+        try {
+            testFunction();
+            djstest.fail("Expected exception but function succeeded: " + " " + message);
+        }
+        catch (e) {
+            // Swallow exception.
+            djstest.pass("Thrown exception expected");
+        }
+    };
+
+    djstest.assertsExpected = function (asserts) {
+        /// <summary>Indicates the expected number of asserts, fails test if number is not met.</summary>
+        /// <param name="asserts" type="Number">Number of asserts expected in test.</param>
+        expect(asserts);
+    }
+
+    djstest.fail = function (message) {
+        /// <summary>Marks the current test as failed.</summary>
+        /// <param name="message" type="String">Failure message.</param>
+        QUnit.ok(false, message);
+    };
+
+    djstest.failAndDoneCallback = function (message, cleanupCallback) {
+        /// <summary>Returns a function that when invoked will fail this test and be done with it.</summary>
+        /// <param name="message" type="String">Failure message.</param>
+        /// <param name="cleanupCallback" type="Function" optional="true">Optional cleanup function in case of failure.</param>
+        /// <returns type="Function">A new function.</returns>
+
+        return function (err) {
+            message = "" + message + (err) ? window.JSON.stringify(err) : "";
+            djstest.fail(message);
+            if (cleanupCallback) {
+                try {
+                    cleanupCallback();
+                } catch (e) {
+                    djstest.fail("error during cleanupCallback: " + window.JSON.stringify(e));
+                }
+            }
+
+            djstest.done();
+        };
+    };
+
+    djstest.log = function (message) {
+        /// <summary>Logs a test message.</summary>
+        /// <param name="message" type="String">Test message.</param>
+        var context = { result: true, actual: true, expected: true, message: message };
+        QUnit.log(context);
+    };
+
+    djstest.pass = function (message) {
+        /// <summary>Marks the current test as failed.</summary>
+        /// <param name="message" type="String">Failure message.</param>
+        QUnit.ok(true, message);
+    };
+
+    djstest.toString = function (obj) {
+        /// <summary>Dumps the object as a string</summary>
+        /// <param name="obj" type="Object">Object to dump</param>
+        return QUnit.jsDump.parse(obj);
+    };
+
+    djstest.wait = function (fn) {
+        /// <summary>Executes the function, pausing test execution until the callback is called</summary>
+        /// <param name="fn" type="Function">Function to execute; takes one parameter which is the callback</param>
+        /// <remarks>This function is typically used in asynchronous setup/teardown methods</remarks>
+        QUnit.stop();
+        fn(function () {
+            QUnit.start();
+        });
+    };
+
+    // Disable caching to ensure that every test-related AJAX request is actually being sent,
+    // and set up a default error handler
+    $.ajaxSetup({
+        cache: false,
+        error: function (jqXHR, textStatus, errorThrown) {
+            // Work around bug in IE-Mobile on Windows Phone 7
+            if (jqXHR.status !== 1223) {
+                var err = {
+                    status: jqXHR.status,
+                    statusText: jqXHR.statusText,
+                    responseText: jqXHR.responseText
+                };
+                djstest.fail("AJAX request failed with: " + djstest.toString(err));
+            }
+            djstest.done();
+        }
+    });
 })(window);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/e387fc92/JSLib/tests/endpoints/FoodStoreDataService.svc
----------------------------------------------------------------------
diff --git a/JSLib/tests/endpoints/FoodStoreDataService.svc b/JSLib/tests/endpoints/FoodStoreDataService.svc
index 9e7e332..e3b0706 100644
--- a/JSLib/tests/endpoints/FoodStoreDataService.svc
+++ b/JSLib/tests/endpoints/FoodStoreDataService.svc
@@ -1,430 +1,430 @@
-<%@ ServiceHost Language="C#" Factory="System.Data.Services.DataServiceHostFactory, Microsoft.Data.Services, Version=5.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-    Service="DataJS.Tests.V1.FoodStoreDataService" %>
-
-// Copyright (c) Microsoft Open Technologies, Inc.  All rights reserved.
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
-// files (the "Software"), to deal  in the Software without restriction, including without limitation the rights  to use, copy,
-// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
-// Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-// WARRANTIES OF MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
-// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-namespace DataJS.Tests.V1
-{
-    using System;
-    using System.Collections.Generic;
-    using System.Data.Services;
-    using System.Data.Services.Common;
-    using System.Linq;
-    using System.ServiceModel.Web;
-    using System.Web;
-
-    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
-    public class FoodStoreDataService : DataService<FoodContainer>
-    {
-        // 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 = DataServiceProtocolVersion.V1;
-            config.UseVerboseErrors = true;
-        }
-        
-        [WebInvoke]
-        public void ResetData()
-        {
-            this.CurrentDataSource.ResetData();
-        }
-
-        [WebGet]
-        public IQueryable<string> FoodsAvailable()
-        {
-            return this.CurrentDataSource.Foods.Select(food => food.Name);
-        }
-
-        [WebGet]
-        public IQueryable<Package> PackagingTypes()
-        {
-            return this.CurrentDataSource.Foods.Select(food => food.Packaging);
-        }
-
-        [WebGet]
-        public string UserNameAndPassword()
-        {
-            var request = WebOperationContext.Current.IncomingRequest;
-            string authorization = request.Headers["Authorization"];
-            if (String.IsNullOrEmpty(authorization))
-            {
-                WebOperationContext.Current.OutgoingResponse.Headers["WWW-Authenticate"] = "Basic realm=\"localhost\"";
-                throw new DataServiceException(401, "Access denied in UserNameAndPassword");
-            }
-
-            return authorization;
-        }
-    }
-    
-    public class FoodContainer : ReflectionDataContext, IUpdatable
-    {
-        private static bool dataInitialized;
-
-        public IQueryable<Category> Categories
-        {
-            get { return this.GetResourceSetEntities<Category>("Categories").AsQueryable(); }
-        }
-        
-        public IQueryable<Food> Foods
-        {
-            get { return this.GetResourceSetEntities<Food>("Foods").AsQueryable(); }
-        }
-        
-        public IQueryable<SpecialDay> SpecialDays
-        {
-            get { return this.GetResourceSetEntities<SpecialDay>("SpecialDays").AsQueryable(); }
-        }
-
-        public void ResetData()
-        {
-            this.ClearData();
-            
-            int i = 0;
-            Category[] categories = new Category[]
-            {
-                new Category { CategoryID = i++, Name = "Baking Supplies", Foods = new List<Food>() },
-                new Category { CategoryID = i++, Name = "Condiments", Foods = new List<Food>() },
-                new Category { CategoryID = i++, Name = "Empty Category", Foods = new List<Food>() }
-            };
-            Array.ForEach(categories, (category) => this.GetResourceSetEntities<Category>("Categories").Add(category));
-            
-            i = 0;
-            Food[] foods = new Food[]
-            {            
-                new Food()
-                {
-                    FoodID = i++,
-                    Name = "flour",
-                    UnitPrice = .19999,
-                    ServingSize = 1,
-                    MeasurementUnit = "Cup",
-                    ProteinGrams = 3,
-                    FatGrams = 1,
-                    CarbohydrateGrams = 20,
-                    CaloriesPerServing = 140,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(2010, 12, 25, 12, 0, 0),
-                    ItemGUID = new Guid("27272727272727272727272727272727"),
-                    Weight = 10f,
-                    AvailableUnits = 1,
-                    
-                    Packaging = new Package(){
-                        Type = null, 
-                        Color = String.Empty, 
-                        NumberPerPackage = int.MaxValue, 
-                        RequiresRefridgeration = false, 
-                        PackageDimensions = new Dimensions()
-                        {
-                            Length = Decimal.MaxValue, 
-                            Height = Int16.MaxValue, 
-                            Width = Int64.MaxValue, 
-                            Volume = double.MaxValue,   
-                        },
-                        ShipDate = new DateTime(2000, 12, 29)
-                    },
-                    
-                    Category = categories[0],
-                },
-                
-                new Food()
-                {
-                    FoodID = i++,
-                    Name = "sugar",
-                    UnitPrice = .2,
-                    ServingSize = 1,
-                    MeasurementUnit = "tsp",
-                    ProteinGrams = 0,
-                    FatGrams = 0,
-                    CarbohydrateGrams = 4,
-                    CaloriesPerServing = 16,
-                    IsAvailable = false,
-                    ExpirationDate = new DateTime(2011, 12, 28),
-                    ItemGUID = new Guid("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
-                    Weight = 0.1f,
-                    AvailableUnits = 0,
-
-                    Packaging = new Package(){
-                        Type = " ",
-                        Color = "BLUE",
-                        NumberPerPackage = int.MinValue,
-                        RequiresRefridgeration = true,
-                        PackageDimensions = new Dimensions(){
-                            Length = Decimal.MinValue,
-                            Height = Int16.MinValue,
-                            Width = Int64.MinValue,
-                            Volume = double.MinValue,
-                        },
-                        ShipDate = new DateTime(2000, 12, 29),
-                    },
-                    
-                    Category = categories[1],
-                },
-
-                new Food()
-                {
-                    FoodID = i++,
-                    Name = "1 Chicken Egg",
-                    UnitPrice = 0.55,
-                    MeasurementUnit = null,
-                    ServingSize = 1,
-                    ProteinGrams = 6,
-                    FatGrams = 1,
-                    CarbohydrateGrams = 1,
-                    CaloriesPerServing = 70,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(2000, 12, 29),
-                    ItemGUID = new Guid("00000000000000000000000000000000"),
-                    Weight = 0,
-                    AvailableUnits = -128,
-                    
-                    Packaging = new Package(){
-                        Type = "18     - Carton",
-                        Color = " brown ",
-                        NumberPerPackage = 0,
-                        RequiresRefridgeration = true,
-                        PackageDimensions = null,
-                        ShipDate = new DateTime(2000, 12, 29),
-                    },
-                    
-                    Category = null,
-                },
-
-                new Food()
-                {
-                    FoodID = i++,
-                    Name = "Brown Sugar",
-                    UnitPrice = 1.6,
-                    ServingSize = 1,
-                    MeasurementUnit = "TSP.",
-                    ProteinGrams = 0,
-                    FatGrams = 0,
-                    CarbohydrateGrams = 5, 
-                    CaloriesPerServing = 16,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(2011, 12, 28),
-                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
-                    Weight = 4.5f,
-                    AvailableUnits = 127,
-                    Packaging = null,
-                    Category = categories[1],
-                },
-                
-                new PreparedFood()
-                {
-                    FoodID = i++,
-                    Name = "Cobb Salad",
-                    UnitPrice = 1.99,
-                    ServingSize = -1,
-                    MeasurementUnit = "cups",
-                    ProteinGrams = 6,
-                    FatGrams = 1,
-                    CarbohydrateGrams = 3, 
-                    CaloriesPerServing = 5,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(2000, 12, 29),
-                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
-                    Weight = 5.674f,
-                    AvailableUnits = 127,
-                    Packaging = null,
-                    Category = categories[1],
-                    Instructions = "1.) Open 2.) Eat",
-                    NumberOfIngredients = 4,
-                },
-                
-                new PreparedFood()
-                {
-                    FoodID = i++,
-                    Name = "Lasagna",
-                    UnitPrice = 0,
-                    ServingSize = 8,
-                    MeasurementUnit = " servings",
-                    ProteinGrams = 100,
-                    FatGrams = 4,
-                    CarbohydrateGrams = 27, 
-                    CaloriesPerServing = 389,
-                    IsAvailable = true,
-                    ExpirationDate = new DateTime(1904, 2, 29),
-                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
-                    Weight = 0,
-                    AvailableUnits = 4,
-                    Packaging = new Package(){
-                        Type = "box",
-                        Color = " 1 ",
-                        NumberPerPackage = 1,
-                        RequiresRefridgeration = true,
-                        PackageDimensions = new Dimensions(){
-                            Length = 3,
-                            Height = 1,
-                            Width = 5,
-                            Volume = 1.5,
-                        },
-                        ShipDate = new DateTime(2000, 12, 29),
-                    },
-                    Category = categories[0],
-                    Instructions = "Bake in oven",
-                    NumberOfIngredients = 15,
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Chocolate"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Pizza"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Avocados"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Quinoa"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Oatmeal"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Peanut Butter"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Banana"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Yam"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Clam"
-                },
-                
-                new Food()
-                {                    
-                    FoodID = i++,
-                    Name = "Spam"
-                }
-            };
-            Array.ForEach(foods, (food) => this.GetResourceSetEntities<Food>("Foods").Add(food));
-
-            categories[0].Foods.Add(foods[0]);
-            categories[1].Foods.Add(foods[2]);
-            categories[1].Foods.Add(foods[3]);
-
-            SpecialDay[] specialDays = new SpecialDay[]
-            {
-                new SpecialDay { ID = 0, Name = "Some date", Date = new DateTime(2010, 12, 29, 1, 2, 3, 456) },
-                
-                // These entries deliberately inject "date-like" XML/JSON strings into string properties
-                new SpecialDay { ID = 1, Name = "2010-12-29T01:02:03.456", Date = new DateTime(2010, 12, 29, 1, 2, 3, 456) },
-                new SpecialDay { ID = 2, Name = "/Date(1293584523456)/", Date = new DateTime(2010, 12, 29, 1, 2, 3, 456) }
-            };
-            Array.ForEach(specialDays, (specialDay) => this.GetResourceSetEntities<SpecialDay>("SpecialDays").Add(specialDay));
-        }
-
-        protected override void EnsureDataIsInitialized()
-        {
-            if (!dataInitialized)
-            {
-                this.ResetData();
-                dataInitialized = true;
-            }
-        }
-    }
-
-    public class Category
-    {
-        public int CategoryID { get; set; }
-        public string Name { get; set; }
-        public List<Food> Foods { get; set; }
-    }
-    
-    public class Food
-    {
-        // Primitive types
-        public int FoodID { get; set; }
-        public string Name { get; set; }
-        public double UnitPrice { get; set; }
-        public Decimal ServingSize { get; set; }
-        public string MeasurementUnit { get; set; }
-        public Byte ProteinGrams { get; set; }
-        public Int16 FatGrams { get; set; }
-        public Int32 CarbohydrateGrams { get; set; }
-        public Int64 CaloriesPerServing { get; set; }
-        public Boolean IsAvailable { get; set; }
-        public DateTime ExpirationDate { get; set; }
-        public Guid ItemGUID { get; set; }
-        public Single Weight { get; set; }
-        public sbyte AvailableUnits { get; set; }
-        
-        // Complex types
-        public Package Packaging { get; set; }
-        
-        // Navigation properties
-        public Category Category { get; set; }
-    }
-
-    public class Package
-    {
-        public string Type { get; set; }
-        public string Color { get; set; }
-        public int NumberPerPackage { get; set; }
-        public Boolean RequiresRefridgeration { get; set; }
-        public DateTime ShipDate { get; set; }
-        public Dimensions PackageDimensions { get; set; }
-    }
-
-    public class Dimensions
-    {
-        public Decimal Length { get; set; }
-        public Int16 Height { get; set; }
-        public Int64 Width { get; set; }
-        public double Volume { get; set; }
-    }
-
-    public class PreparedFood : Food
-    {
-        public string Instructions { get; set; }
-        public float NumberOfIngredients { get; set; }
-    }
-    
-    public class SpecialDay
-    {
-        public int ID { get; set; }
-        public string Name { get; set; }
-        public DateTime Date { get; set; }
-    }
-}
+<%@ ServiceHost Language="C#" Factory="System.Data.Services.DataServiceHostFactory, Microsoft.Data.Services, Version=5.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+    Service="DataJS.Tests.V1.FoodStoreDataService" %>
+
+// Copyright (c) Microsoft.  All rights reserved.
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
+// files (the "Software"), to deal  in the Software without restriction, including without limitation the rights  to use, copy,
+// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+// WARRANTIES OF MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+namespace DataJS.Tests.V1
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Data.Services;
+    using System.Data.Services.Common;
+    using System.Linq;
+    using System.ServiceModel.Web;
+    using System.Web;
+
+    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+    public class FoodStoreDataService : DataService<FoodContainer>
+    {
+        // 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 = DataServiceProtocolVersion.V1;
+            config.UseVerboseErrors = true;
+        }
+        
+        [WebInvoke]
+        public void ResetData()
+        {
+            this.CurrentDataSource.ResetData();
+        }
+
+        [WebGet]
+        public IQueryable<string> FoodsAvailable()
+        {
+            return this.CurrentDataSource.Foods.Select(food => food.Name);
+        }
+
+        [WebGet]
+        public IQueryable<Package> PackagingTypes()
+        {
+            return this.CurrentDataSource.Foods.Select(food => food.Packaging);
+        }
+
+        [WebGet]
+        public string UserNameAndPassword()
+        {
+            var request = WebOperationContext.Current.IncomingRequest;
+            string authorization = request.Headers["Authorization"];
+            if (String.IsNullOrEmpty(authorization))
+            {
+                WebOperationContext.Current.OutgoingResponse.Headers["WWW-Authenticate"] = "Basic realm=\"localhost\"";
+                throw new DataServiceException(401, "Access denied in UserNameAndPassword");
+            }
+
+            return authorization;
+        }
+    }
+    
+    public class FoodContainer : ReflectionDataContext, IUpdatable
+    {
+        private static bool dataInitialized;
+
+        public IQueryable<Category> Categories
+        {
+            get { return this.GetResourceSetEntities<Category>("Categories").AsQueryable(); }
+        }
+        
+        public IQueryable<Food> Foods
+        {
+            get { return this.GetResourceSetEntities<Food>("Foods").AsQueryable(); }
+        }
+        
+        public IQueryable<SpecialDay> SpecialDays
+        {
+            get { return this.GetResourceSetEntities<SpecialDay>("SpecialDays").AsQueryable(); }
+        }
+
+        public void ResetData()
+        {
+            this.ClearData();
+            
+            int i = 0;
+            Category[] categories = new Category[]
+            {
+                new Category { CategoryID = i++, Name = "Baking Supplies", Foods = new List<Food>() },
+                new Category { CategoryID = i++, Name = "Condiments", Foods = new List<Food>() },
+                new Category { CategoryID = i++, Name = "Empty Category", Foods = new List<Food>() }
+            };
+            Array.ForEach(categories, (category) => this.GetResourceSetEntities<Category>("Categories").Add(category));
+            
+            i = 0;
+            Food[] foods = new Food[]
+            {            
+                new Food()
+                {
+                    FoodID = i++,
+                    Name = "flour",
+                    UnitPrice = .19999,
+                    ServingSize = 1,
+                    MeasurementUnit = "Cup",
+                    ProteinGrams = 3,
+                    FatGrams = 1,
+                    CarbohydrateGrams = 20,
+                    CaloriesPerServing = 140,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(2010, 12, 25, 12, 0, 0),
+                    ItemGUID = new Guid("27272727272727272727272727272727"),
+                    Weight = 10f,
+                    AvailableUnits = 1,
+                    
+                    Packaging = new Package(){
+                        Type = null, 
+                        Color = String.Empty, 
+                        NumberPerPackage = int.MaxValue, 
+                        RequiresRefridgeration = false, 
+                        PackageDimensions = new Dimensions()
+                        {
+                            Length = Decimal.MaxValue, 
+                            Height = Int16.MaxValue, 
+                            Width = Int64.MaxValue, 
+                            Volume = double.MaxValue,   
+                        },
+                        ShipDate = new DateTime(2000, 12, 29)
+                    },
+                    
+                    Category = categories[0],
+                },
+                
+                new Food()
+                {
+                    FoodID = i++,
+                    Name = "sugar",
+                    UnitPrice = .2,
+                    ServingSize = 1,
+                    MeasurementUnit = "tsp",
+                    ProteinGrams = 0,
+                    FatGrams = 0,
+                    CarbohydrateGrams = 4,
+                    CaloriesPerServing = 16,
+                    IsAvailable = false,
+                    ExpirationDate = new DateTime(2011, 12, 28),
+                    ItemGUID = new Guid("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
+                    Weight = 0.1f,
+                    AvailableUnits = 0,
+
+                    Packaging = new Package(){
+                        Type = " ",
+                        Color = "BLUE",
+                        NumberPerPackage = int.MinValue,
+                        RequiresRefridgeration = true,
+                        PackageDimensions = new Dimensions(){
+                            Length = Decimal.MinValue,
+                            Height = Int16.MinValue,
+                            Width = Int64.MinValue,
+                            Volume = double.MinValue,
+                        },
+                        ShipDate = new DateTime(2000, 12, 29),
+                    },
+                    
+                    Category = categories[1],
+                },
+
+                new Food()
+                {
+                    FoodID = i++,
+                    Name = "1 Chicken Egg",
+                    UnitPrice = 0.55,
+                    MeasurementUnit = null,
+                    ServingSize = 1,
+                    ProteinGrams = 6,
+                    FatGrams = 1,
+                    CarbohydrateGrams = 1,
+                    CaloriesPerServing = 70,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(2000, 12, 29),
+                    ItemGUID = new Guid("00000000000000000000000000000000"),
+                    Weight = 0,
+                    AvailableUnits = -128,
+                    
+                    Packaging = new Package(){
+                        Type = "18     - Carton",
+                        Color = " brown ",
+                        NumberPerPackage = 0,
+                        RequiresRefridgeration = true,
+                        PackageDimensions = null,
+                        ShipDate = new DateTime(2000, 12, 29),
+                    },
+                    
+                    Category = null,
+                },
+
+                new Food()
+                {
+                    FoodID = i++,
+                    Name = "Brown Sugar",
+                    UnitPrice = 1.6,
+                    ServingSize = 1,
+                    MeasurementUnit = "TSP.",
+                    ProteinGrams = 0,
+                    FatGrams = 0,
+                    CarbohydrateGrams = 5, 
+                    CaloriesPerServing = 16,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(2011, 12, 28),
+                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
+                    Weight = 4.5f,
+                    AvailableUnits = 127,
+                    Packaging = null,
+                    Category = categories[1],
+                },
+                
+                new PreparedFood()
+                {
+                    FoodID = i++,
+                    Name = "Cobb Salad",
+                    UnitPrice = 1.99,
+                    ServingSize = -1,
+                    MeasurementUnit = "cups",
+                    ProteinGrams = 6,
+                    FatGrams = 1,
+                    CarbohydrateGrams = 3, 
+                    CaloriesPerServing = 5,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(2000, 12, 29),
+                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
+                    Weight = 5.674f,
+                    AvailableUnits = 127,
+                    Packaging = null,
+                    Category = categories[1],
+                    Instructions = "1.) Open 2.) Eat",
+                    NumberOfIngredients = 4,
+                },
+                
+                new PreparedFood()
+                {
+                    FoodID = i++,
+                    Name = "Lasagna",
+                    UnitPrice = 0,
+                    ServingSize = 8,
+                    MeasurementUnit = " servings",
+                    ProteinGrams = 100,
+                    FatGrams = 4,
+                    CarbohydrateGrams = 27, 
+                    CaloriesPerServing = 389,
+                    IsAvailable = true,
+                    ExpirationDate = new DateTime(1904, 2, 29),
+                    ItemGUID = new Guid("0123456789abcdef0123456789abcdef"),
+                    Weight = 0,
+                    AvailableUnits = 4,
+                    Packaging = new Package(){
+                        Type = "box",
+                        Color = " 1 ",
+                        NumberPerPackage = 1,
+                        RequiresRefridgeration = true,
+                        PackageDimensions = new Dimensions(){
+                            Length = 3,
+                            Height = 1,
+                            Width = 5,
+                            Volume = 1.5,
+                        },
+                        ShipDate = new DateTime(2000, 12, 29),
+                    },
+                    Category = categories[0],
+                    Instructions = "Bake in oven",
+                    NumberOfIngredients = 15,
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Chocolate"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Pizza"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Avocados"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Quinoa"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Oatmeal"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Peanut Butter"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Banana"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Yam"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Clam"
+                },
+                
+                new Food()
+                {                    
+                    FoodID = i++,
+                    Name = "Spam"
+                }
+            };
+            Array.ForEach(foods, (food) => this.GetResourceSetEntities<Food>("Foods").Add(food));
+
+            categories[0].Foods.Add(foods[0]);
+            categories[1].Foods.Add(foods[2]);
+            categories[1].Foods.Add(foods[3]);
+
+            SpecialDay[] specialDays = new SpecialDay[]
+            {
+                new SpecialDay { ID = 0, Name = "Some date", Date = new DateTime(2010, 12, 29, 1, 2, 3, 456) },
+                
+                // These entries deliberately inject "date-like" XML/JSON strings into string properties
+                new SpecialDay { ID = 1, Name = "2010-12-29T01:02:03.456", Date = new DateTime(2010, 12, 29, 1, 2, 3, 456) },
+                new SpecialDay { ID = 2, Name = "/Date(1293584523456)/", Date = new DateTime(2010, 12, 29, 1, 2, 3, 456) }
+            };
+            Array.ForEach(specialDays, (specialDay) => this.GetResourceSetEntities<SpecialDay>("SpecialDays").Add(specialDay));
+        }
+
+        protected override void EnsureDataIsInitialized()
+        {
+            if (!dataInitialized)
+            {
+                this.ResetData();
+                dataInitialized = true;
+            }
+        }
+    }
+
+    public class Category
+    {
+        public int CategoryID { get; set; }
+        public string Name { get; set; }
+        public List<Food> Foods { get; set; }
+    }
+    
+    public class Food
+    {
+        // Primitive types
+        public int FoodID { get; set; }
+        public string Name { get; set; }
+        public double UnitPrice { get; set; }
+        public Decimal ServingSize { get; set; }
+        public string MeasurementUnit { get; set; }
+        public Byte ProteinGrams { get; set; }
+        public Int16 FatGrams { get; set; }
+        public Int32 CarbohydrateGrams { get; set; }
+        public Int64 CaloriesPerServing { get; set; }
+        public Boolean IsAvailable { get; set; }
+        public DateTime ExpirationDate { get; set; }
+        public Guid ItemGUID { get; set; }
+        public Single Weight { get; set; }
+        public sbyte AvailableUnits { get; set; }
+        
+        // Complex types
+        public Package Packaging { get; set; }
+        
+        // Navigation properties
+        public Category Category { get; set; }
+    }
+
+    public class Package
+    {
+        public string Type { get; set; }
+        public string Color { get; set; }
+        public int NumberPerPackage { get; set; }
+        public Boolean RequiresRefridgeration { get; set; }
+        public DateTime ShipDate { get; set; }
+        public Dimensions PackageDimensions { get; set; }
+    }
+
+    public class Dimensions
+    {
+        public Decimal Length { get; set; }
+        public Int16 Height { get; set; }
+        public Int64 Width { get; set; }
+        public double Volume { get; set; }
+    }
+
+    public class PreparedFood : Food
+    {
+        public string Instructions { get; set; }
+        public float NumberOfIngredients { get; set; }
+    }
+    
+    public class SpecialDay
+    {
+        public int ID { get; set; }
+        public string Name { get; set; }
+        public DateTime Date { get; set; }
+    }
+}