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/16 04:26:35 UTC
[07/11] [OLINGO-289] Upgrade the datajs version to 1.1.3 and check in
some missing test cases
http://git-wip-us.apache.org/repos/asf/olingo-odata3-js/blob/9aa185d4/JSLib/tests/odata-cache-filter-functional-tests.js
----------------------------------------------------------------------
diff --git a/JSLib/tests/odata-cache-filter-functional-tests.js b/JSLib/tests/odata-cache-filter-functional-tests.js
new file mode 100644
index 0000000..44fb96e
--- /dev/null
+++ b/JSLib/tests/odata-cache-filter-functional-tests.js
@@ -0,0 +1,433 @@
+/// <reference path="../src/datajs.js" />
+/// <reference path="../src/odata-utils.js" />
+/// <reference path="../src/cache.js" />
+/// <reference path="common/djstest.js" />
+
+(function (window, undefined) {
+ OData.defaultHandler.accept = "application/atomsvc+xml;q=0.9, application/json;odata=verbose;q=0.8, application/json;odata=fullmetadata;q=0.7, application/json;q=0.5, */*;q=0.1";
+ var feeds = [
+ { feed: "./endpoints/FoodStoreDataService.svc/Foods" },
+ { feed: "./endpoints/FoodStoreDataServiceV2.svc/Foods" },
+ { feed: "./endpoints/FoodStoreDataServiceV3.svc/Foods" }
+ ];
+
+ var itemsInCollection = 16;
+
+ var pageSize = 3;
+ var readRangeStart = pageSize + 1;
+ var readRangeTake = pageSize;
+
+ // Indices for filterForward after an initial readRange has partially filled the cache
+ var filterForwardAfterReadIndices = [
+ readRangeStart - 1, // before items in the cache
+ readRangeStart, // beginning of items in the cache
+ readRangeStart + readRangeTake, // last item prefetched in the cache
+ readRangeStart + readRangeTake + 1 // past range already in cache
+ ];
+
+ // Indices for filterBack after an initial readRange has partially filled the cache
+ var filterBackAfterReadIndices = [
+ readRangeStart - 1, // before items in the cache
+ readRangeStart, // beginning of items in the cache
+ readRangeStart + readRangeTake, // last item prefetched in the cache
+ readRangeStart + readRangeTake + 1 // past range already in cache
+ ];
+
+ // Counts for filterForward after a readRange has partially filled the cache
+ var filterForwardAfterReadCounts = [
+ -5, // Get all items
+ 3, // Subset of all items found in the cache
+ itemsInCollection
+ ];
+
+ // Counts for filterBack after a readRange has partially filled the cache
+ var filterBackAfterReadCounts = [
+ -5, // Get all items
+ 3, // Subset of all items found in the cache
+ itemsInCollection
+ ];
+
+ // Indices for single filterForward
+ var singleFilterForwardIndices = [
+ -5,
+ itemsInCollection - 1,
+ itemsInCollection, // beyond the end of the collection
+ itemsInCollection + pageSize // more than one page beyond the collection
+ ];
+
+ // Indices for single filterBack
+ var singleFilterBackIndices = [
+ -1,
+ 0,
+ itemsInCollection - 1
+ ];
+
+ // Count for single filterForward
+ var singleFilterForwardCounts = [
+ 5,
+ itemsInCollection + 1 // more than number of items in collection
+ ];
+
+ // Count for single filterBack
+ var singleFilterBackCounts = [
+ 5,
+ itemsInCollection + 1 // more than number of items in collection
+ ];
+
+ // Index/count variations for multiple filterForwards
+ var multipleFilterForwards = [
+ { index: 0, count: -1 }, // everything
+ {index: 2, count: 5 }, // range in first half
+ {index: 4, count: 7 }, // range in the middle to overlap first and second half
+ {index: 9, count: 4} // range in second half
+ ];
+
+ // Index/count variations for multiple filterBacks
+ var multipleFilterBacks = [
+ { index: itemsInCollection - 1, count: -1 }, // everything
+ {index: itemsInCollection - 2, count: 5 }, // range in second half
+ {index: itemsInCollection - 4, count: 7 }, // range in the middle to overlap first and second half
+ {index: itemsInCollection - 9, count: 4} // range in first half
+ ];
+
+
+ var invalidIndices = [NaN, undefined, Infinity, "not a valid value"];
+ var invalidCounts = [NaN, undefined, Infinity, "not a valid value"];
+
+ // Predicate which returns all items in the collection
+ var getAllItemsPredicate = function (item) {
+ return true;
+ };
+
+ // Predicate which returns none of the items in the collection
+ var getNoItemsPredicate = function (item) {
+ return false;
+ };
+
+ var getEveryThirdPredicate = function (item) {
+ return ((item.FoodID % 3) === 0);
+ };
+
+ var filterPredicates = [
+ getAllItemsPredicate,
+ getNoItemsPredicate,
+ getEveryThirdPredicate
+ ];
+
+ var expectException = function (cache) {
+ djstest.assert(false, "We should not get here because the an exception is expected.");
+ djstest.destroyCacheAndDone(cache);
+ };
+
+ var makeUnexpectedErrorHandler = function (cache) {
+ return function (err) {
+ djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+ if (cache) {
+ djstest.destroyCacheAndDone(cache);
+ } else {
+ djstest.done();
+ }
+ };
+ };
+
+ var validateFilterResultsAndRequests = function (feed, cache, index, count, predicate, finished, backwards, session, cacheOracle) {
+ /// <summary>Runs filter and validates the results and network requests</summary>
+ /// <param name="feed" type="Object">The feed being read from</param>
+ /// <param name="cache" type="Object">The cache to perform the filter on</param>
+ /// <param name="index" type="Integer">The index value</param>
+ /// <param name="count" type="Integer">The count value</param>
+ /// <param name="predicate" type="Object">Filter string to append to the feed to validate the predicate</param>
+ /// <param name="finished" type="Function">Callback function called after data is verified</param>
+ /// <param name="session" type="Object">Session object to validate the network requests</param>
+ /// <param name="cacheOracle" type="Object">cacheOracle object to validate the network requests</param>
+
+ // If the count is zero, avoid a network call by comparing actual results to an empty array.
+ if (count === 0) {
+ var verifyZeroCount = function (actualResults) {
+ var filterMethod = backwards ? "filterBack" : "filterForward";
+ djstest.assertAreEqualDeep(actualResults, [], "results for zero count " + filterMethod);
+ cacheOracle.verifyRequests(session.requests, session.responses, index, count, filterMethod + " requests", backwards);
+ finished();
+ }
+
+ if (backwards) {
+ cache.filterBack(index, count, predicate).then(verifyZeroCount);
+ }
+ else {
+ cache.filterForward(index, count, predicate).then(verifyZeroCount);
+ }
+ }
+ else {
+ if (count < 0) {
+ count = itemsInCollection;
+ }
+
+ if (index < 0) {
+ index = 0;
+ }
+
+ window.ODataReadOracle.readJsonAcrossServerPages(feed, function (collection) {
+ if (backwards) {
+ cache.filterBack(index, count, predicate).then(function (actualResults) {
+ var expectedResults = CacheOracle.getExpectedFilterResults(collection, index, count, predicate, backwards);
+ djstest.assertAreEqualDeep(actualResults, expectedResults, "results for " + "filterBack requests");
+
+ if (session && cacheOracle) {
+ // If the count is not satisfied in the expected results, read to the beginning of the collection
+ // otherwise read to the first expected index
+ var firstIndex = (expectedResults.length < count) ? 0 : expectedResults[0].index;
+ // The effective count is the number of items between the first and last index
+ var expectedCount = index - firstIndex + 1;
+ cacheOracle.verifyRequests(session.requests, session.responses, firstIndex, expectedCount, "filterBack requests", backwards);
+ }
+ finished();
+ });
+ }
+ else {
+ cache.filterForward(index, count, predicate).then(function (actualResults) {
+ var expectedResults = CacheOracle.getExpectedFilterResults(collection, index, count, predicate, backwards)
+ djstest.assertAreEqualDeep(actualResults, expectedResults, "results for " + "filterForward requests");
+
+ if (session && cacheOracle) {
+ if (expectedResults.length > 0) {
+ // If the count is not satisfied in the expected results, read to the end of the collection
+ // otherwise read to the last index
+ var lastIndex = (expectedResults.length < count) ? itemsInCollection : expectedResults[expectedResults.length - 1].index + 1;
+ // One request is made if the index is outside the range of the collection if the end of the collection has not yet been found
+ var expectedCount = (index < itemsInCollection) ? (lastIndex - index) : 1;
+ }
+ else {
+ var expectedCount = itemsInCollection;
+ }
+
+ cacheOracle.verifyRequests(session.requests, session.responses, index, expectedCount, "filterForward requests", backwards);
+ }
+ finished();
+ });
+ }
+ });
+ }
+ };
+
+ var createMultipleFilterTestName = function (scenarioName, params) {
+ return "Testing " + scenarioName + (params.backwards ? "filterBack: " : "filterForward: ") + " of " + params.feed + " with predicate " + params.predicate + " [index " +
+ params.firstIndex + ", count " + params.firstCount + "] and [index " + params.secondIndex + ", count " + params.secondCount +
+ "] with pageSize " + params.pageSize + ", and prefetch " + params.prefetchSize;
+ };
+
+ var createSingleFilterTestName = function (scenarioName, params) {
+ return "Testing " + scenarioName + (params.backwards ? "filterBack: " : "filterForward: ") + " of " + params.feed + " with predicate " + params.predicate + " [index " +
+ params.index + ", count " + params.count + "] with pageSize " + params.pageSize + ", and prefetch " + params.prefetchSize;
+ };
+
+ var singleFilterTest = function (params) {
+ djstest.assertsExpected(2);
+ var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize };
+
+ var cache = datajs.createDataCache(options);
+ var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
+ var session = this.observableHttpClient.newSession();
+ validateFilterResultsAndRequests(params.feed, cache, params.index, params.count, params.predicate, function () { djstest.destroyCacheAndDone(cache) }, params.backwards, session, cacheOracle);
+ };
+
+ var filterAfterReadRangeTest = function (params) {
+ djstest.assertsExpected(3);
+ var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize };
+
+ var cache = datajs.createDataCache(options);
+ var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
+ var session = this.observableHttpClient.newSession();
+
+ cache.readRange(params.skip, params.take).then(function (data) {
+ cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "readRange requests");
+ session.clear();
+ validateFilterResultsAndRequests(params.feed, cache, params.index, params.count, params.predicate, function () { djstest.destroyCacheAndDone(cache); }, params.backwards, session, cacheOracle);
+ });
+ };
+
+ var parallelFilterTest = function (params) {
+ djstest.assertsExpected(2);
+ var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize };
+
+ var cache = datajs.createDataCache(options);
+
+ var firstfilter = function (finished) {
+ validateFilterResultsAndRequests(params.feed, cache, params.firstIndex, params.firstCount, params.predicate, finished, params.backwards);
+ };
+
+ var secondfilter = function (finished) {
+ validateFilterResultsAndRequests(params.feed, cache, params.secondIndex, params.secondCount, params.predicate, finished, params.backwards);
+ };
+
+ djstest.asyncDo([firstfilter, secondfilter], function () {
+ djstest.destroyCacheAndDone(cache);
+ });
+ };
+
+ var serialFilterTest = function (params) {
+ djstest.assertsExpected(4);
+ var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize };
+
+ var cache = datajs.createDataCache(options);
+ var cacheOracle = new CacheOracle(params.feed, params.pageSize, itemsInCollection);
+ var session = this.observableHttpClient.newSession();
+
+ var filterMethod = function (index, count, predicate, backwards) {
+ if (backwards) {
+ return cache.filterBack(index, count, predicate);
+ }
+ else {
+ return cache.filterForward(index, count, predicate)
+ }
+ }
+
+ filterMethod(params.firstIndex, params.firstCount, params.predicate, params.backwards).then(
+ function (results) {
+ validateFilterResultsAndRequests(params.feed, cache, params.firstIndex, params.firstCount, params.predicate,
+ function () {
+ session.clear();
+ validateFilterResultsAndRequests(params.feed, cache, params.secondIndex, params.secondCount, params.predicate, function () { djstest.destroyCacheAndDone(cache) }, params.backwards, session, cacheOracle);
+ }, params.backwards, session, cacheOracle);
+ });
+ };
+
+ module("Functional", {
+ setup: function () {
+ this.observableHttpClient = new ObservableHttpClient();
+ OData.defaultHttpClient = this.observableHttpClient;
+ },
+
+ teardown: function () {
+ OData.defaultHttpClient = this.observableHttpClient.provider;
+ }
+ });
+
+ $.each(filterPredicates, function (_, filterPredicate) {
+ $.each(feeds, function (_, feedObject) {
+ $.each(filterForwardAfterReadCounts, function (_, filterCount) {
+ $.each(filterForwardAfterReadIndices, function (_, filterIndex) {
+ var parameters = { index: filterIndex, count: filterCount, predicate: filterPredicate, feed: feedObject.feed, take: readRangeTake,
+ skip: readRangeStart, pageSize: pageSize, prefetchSize: 0, backwards: false
+ };
+ djstest.addTest(filterAfterReadRangeTest, createSingleFilterTestName("after readRange, ", parameters), parameters);
+ });
+ });
+
+ $.each(filterBackAfterReadCounts, function (_, filterCount) {
+ $.each(filterBackAfterReadIndices, function (_, filterIndex) {
+ var parameters = { index: filterIndex, count: filterCount, predicate: filterPredicate, feed: feedObject.feed, take: readRangeTake,
+ skip: readRangeStart, pageSize: pageSize, prefetchSize: 0, backwards: true
+ };
+ djstest.addTest(filterAfterReadRangeTest, createSingleFilterTestName("After readRange, ", parameters), parameters);
+ });
+ });
+ });
+
+ $.each(singleFilterForwardIndices, function (_, filterIndex) {
+ $.each(singleFilterForwardCounts, function (_, filterCount) {
+ var parameters = { index: filterIndex, count: filterCount, predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: false };
+ djstest.addTest(singleFilterTest, createSingleFilterTestName("single ", parameters), parameters);
+ });
+ });
+
+ $.each(singleFilterBackIndices, function (_, filterIndex) {
+ $.each(singleFilterBackCounts, function (_, filterCount) {
+ var parameters = { index: filterIndex, count: filterCount, predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 0, backwards: true };
+ djstest.addTest(singleFilterTest, createSingleFilterTestName("single ", parameters), parameters);
+ });
+ });
+
+ $.each(multipleFilterForwards, function (_, firstFilter) {
+ $.each(multipleFilterForwards, function (_, secondFilter) {
+ var serialParameters = { firstIndex: firstFilter.index, firstCount: firstFilter.count, secondIndex: secondFilter.index, secondCount: secondFilter.count,
+ predicate: filterPredicate, feed: feeds[1].feed, pageSize: pageSize, prefetchSize: 0, backwards: false
+ };
+ djstest.addTest(serialFilterTest, createMultipleFilterTestName("serial ", serialParameters), serialParameters);
+ });
+ });
+
+ $.each(multipleFilterBacks, function (_, firstFilter) {
+ $.each(multipleFilterBacks, function (_, secondFilter) {
+ var serialParameters = { firstIndex: firstFilter.index, firstCount: firstFilter.count, secondIndex: secondFilter.index, secondCount: secondFilter.count,
+ predicate: filterPredicate, feed: feeds[1].feed, pageSize: pageSize, prefetchSize: 0, backwards: true
+ };
+ djstest.addTest(serialFilterTest, createMultipleFilterTestName("serial ", serialParameters), serialParameters);
+ });
+ });
+
+ $.each(multipleFilterForwards, function (_, firstFilter) {
+ $.each(multipleFilterForwards, function (_, secondFilter) {
+ var parallelParameters = { firstIndex: firstFilter.index, firstCount: firstFilter.count, secondIndex: secondFilter.index, secondCount: secondFilter.count,
+ predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 6, backwards: false
+ };
+ djstest.addTest(parallelFilterTest, createMultipleFilterTestName("parallel ", parallelParameters), parallelParameters);
+ });
+ });
+
+ $.each(multipleFilterBacks, function (_, firstFilter) {
+ $.each(multipleFilterBacks, function (_, secondFilter) {
+ var parallelParameters = { firstIndex: firstFilter.index, firstCount: firstFilter.count, secondIndex: secondFilter.index, secondCount: secondFilter.count,
+ predicate: filterPredicate, feed: feeds[0].feed, pageSize: pageSize, prefetchSize: 6, backwards: true
+ };
+ djstest.addTest(parallelFilterTest, createMultipleFilterTestName("parallel ", parallelParameters), parallelParameters);
+ });
+ });
+
+ $.each([true, false], function (_, isBackwards) {
+ var zeroCountParameters = { index: 0, count: 0, predicate: filterPredicate, feed: feeds[1].feed, take: readRangeTake,
+ skip: readRangeStart, pageSize: pageSize, prefetchSize: 0, backwards: isBackwards
+ };
+ djstest.addTest(singleFilterTest, createSingleFilterTestName("Count 0 ", zeroCountParameters), zeroCountParameters);
+ });
+ });
+
+ $.each([true, false], function (_, backwards) {
+ $.each(invalidIndices, function (_, invalidIndex) {
+ var invalidIndexParameters = { index: invalidIndex, count: -1, predicate: filterPredicates[0], feed: feeds[1].feed, pageSize: pageSize, prefetchSize: 0, backwards: backwards };
+
+ djstest.addTest(
+ function (params) {
+ djstest.assertsExpected(1);
+ var options = { name: "cache" + new Date().valueOf(), source: params.feed };
+ var cache = datajs.createDataCache(options);
+ try {
+ params.backwards ?
+ cache.filterForward(params.index, params.count, params.predicate).then(function (results) {
+ djstest.log(results);
+ }) :
+ cache.filterForward(params.index, params.count, params.predicate).then(function (results) {
+ djstest.log(results);
+ });
+ expectException(cache);
+ } catch (e) {
+ djstest.assertAreEqual(e.message, "'index' must be a valid number.", "Error message validation");
+ djstest.destroyCacheAndDone(cache);
+ }
+ }, createSingleFilterTestName("invalid index ", invalidIndexParameters), invalidIndexParameters);
+ });
+
+ $.each(invalidCounts, function (_, invalidCount) {
+ var invalidCountParameters = { index: 0, count: invalidCount, predicate: filterPredicates[0], feed: feeds[1].feed, pageSize: pageSize, prefetchSize: 0, backwards: backwards };
+
+ djstest.addTest(
+ function (params) {
+ djstest.assertsExpected(1);
+ var options = { name: "cache" + new Date().valueOf(), source: params.feed };
+ var cache = datajs.createDataCache(options);
+ try {
+ params.backwards ?
+ cache.filterBack(params.index, params.count, params.predicate).then(function (results) {
+ djstest.log(results);
+ }) :
+ cache.filterForward(params.index, params.count, params.predicate).then(function (results) {
+ djstest.log(results);
+ });
+ expectException(cache);
+ } catch (e) {
+ djstest.assertAreEqual(e.message, "'count' must be a valid number.", "Error message validation");
+ djstest.destroyCacheAndDone(cache);
+ }
+ }, createSingleFilterTestName("invalid count ", invalidCountParameters), invalidCountParameters);
+ });
+ });
+})(this);
http://git-wip-us.apache.org/repos/asf/olingo-odata3-js/blob/9aa185d4/JSLib/tests/odata-cache-fperf-tests.html
----------------------------------------------------------------------
diff --git a/JSLib/tests/odata-cache-fperf-tests.html b/JSLib/tests/odata-cache-fperf-tests.html
new file mode 100644
index 0000000..3323199
--- /dev/null
+++ b/JSLib/tests/odata-cache-fperf-tests.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>datajs.cache functional perf tests</title>
+ <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
+ <meta http-equiv="cache-control" content="no-cache"/>
+ <meta http-equiv="pragma" content="no-cache"/>
+ <meta http-equiv="expires" content="-1"/>
+
+ <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+ <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
+ <script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.10.0.js"></script>
+ <script type="text/javascript" src="common/TestSynchronizerClient.js"></script>
+ <script type="text/javascript">
+ window.TestSynchronizer.init(QUnit);
+ </script>
+
+ <script type="text/javascript" src="../src/datajs.js"></script>
+ <script type="text/javascript" src="../src/utils.js"></script>
+ <script type="text/javascript" src="../src/xml.js"></script>
+
+ <script type="text/javascript" src="../src/odata-utils.js"></script>
+ <script type="text/javascript" src="../src/odata-handler.js"></script>
+ <script type="text/javascript" src="../src/odata-gml.js"></script>
+ <script type="text/javascript" src="../src/odata-xml.js"></script>
+ <script type="text/javascript" src="../src/odata-net.js"></script>
+ <script type="text/javascript" src="../src/odata-json-light.js"></script>
+ <script type="text/javascript" src="../src/odata-json.js"></script>
+ <script type="text/javascript" src="../src/odata-atom.js"></script>
+ <script type="text/javascript" src="../src/odata-metadata.js"></script>
+ <script type="text/javascript" src="../src/odata-batch.js"></script>
+ <script type="text/javascript" src="../src/odata.js"></script>
+
+ <script type="text/javascript" src="../src/store-dom.js"></script>
+ <script type="text/javascript" src="../src/store-indexeddb.js"></script>
+ <script type="text/javascript" src="../src/store-memory.js"></script>
+ <script type="text/javascript" src="../src/store.js"></script>
+
+ <script type="text/javascript" src="../src/deferred.js"></script>
+ <script type="text/javascript" src="../src/cache-source.js"></script>
+ <script type="text/javascript" src="../src/cache.js"></script>
+
+ <script type="text/javascript" src="common/CacheOracle.js"></script>
+ <script type="text/javascript" src="common/djstest.js"></script>
+ <script type="text/javascript" src="odata-cache-fperf-tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">datajs.cache functional perf tests</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata3-js/blob/9aa185d4/JSLib/tests/odata-cache-fperf-tests.js
----------------------------------------------------------------------
diff --git a/JSLib/tests/odata-cache-fperf-tests.js b/JSLib/tests/odata-cache-fperf-tests.js
new file mode 100644
index 0000000..bd08af4
--- /dev/null
+++ b/JSLib/tests/odata-cache-fperf-tests.js
@@ -0,0 +1,105 @@
+/// <reference path="../src/datajs.js" />
+/// <reference path="../src/odata-utils.js" />
+/// <reference path="../src/cache.js" />
+/// <reference path="common/CacheOracle.js" />
+/// <reference path="common/djstest.js" />
+
+(function (window, undefined) {
+
+ var slowHttpClient = {
+ latency: 500,
+ provider: OData.defaultHttpClient,
+ request: function (request, success, error) {
+ setTimeout(function () {
+ slowHttpClient.provider.request(request, success, error);
+ }, slowHttpClient.latency);
+ }
+ };
+
+ var feeds = [
+ { uri: "./endpoints/FoodStoreDataService.svc/Foods" },
+ { uri: "./endpoints/FoodStoreDataServiceV2.svc/Foods" },
+ { uri: "./endpoints/FoodStoreDataServiceV3.svc/Foods" }
+ ];
+
+ module("Functional", {
+ setup: function () {
+ OData.defaultHttpClient = slowHttpClient;
+ },
+ teardown: function () {
+ OData.defaultHttpClient = slowHttpClient.provider;
+ }
+ });
+
+ var cacheReadRangeWallClockTest = function (totalReads, interval, mechanism, source, pageSize, prefetchSize, generateRange, threshold) {
+ /// <summary>Cache readRange wall-clock test</summary>
+ /// <remarks>
+ /// The average time computed by the wall-clock test does *not* include the initial readRange
+ /// </remarks>
+ /// <param name="totalReads">Number of reads to collect data from</param>
+ /// <param name="interval">Interval (milliseconds) between reads</param>
+ /// <param name="mechanism">The cache store mechanism</param>
+ /// <param name="source">The feed source</param>
+ /// <param name="pageSize">The page size</param>
+ /// <param name="prefetchSize">The prefetch size</param>
+ /// <param name="generateRange">The range generator function: given the read index, returns the readRange index and count</param>
+ /// <param name="threshold">The average read time threshold for test to pass; if not specified, defaults to the slowHttpClient latency</param>
+ /// <returns>The test function</param>
+ return function () {
+ var cache = datajs.createDataCache({ name: "cache" + new Date().valueOf(), source: source, pageSize: pageSize, prefetchSize: prefetchSize });
+ var totalTime = 0;
+ var readCount = 0;
+
+ var callReadRange = function () {
+ var range = generateRange(readCount);
+ var startTime = new Date().valueOf();
+ cache.readRange(range.index, range.count).then(function (data) {
+ var duration = (new Date().valueOf()) - startTime;
+ djstest.log("readRange " + readCount + " [" + range.index + ", " + range.count + "]: " + duration + "ms");
+
+ // The first readRange is not counted
+ totalTime += (readCount > 0) ? duration : 0;
+ readCount += 1;
+
+ if (readCount < totalReads) {
+ setTimeout(callReadRange, interval);
+ } else {
+ // The first readRange is not counted
+ var averageTime = totalTime / (totalReads - 1);
+ var actualThreshold = threshold === undefined ? slowHttpClient.latency : threshold;
+ djstest.assert(averageTime < actualThreshold, "Average: " + averageTime + "ms, Threshold: " + actualThreshold + "ms");
+ djstest.destroyCacheAndDone(cache);
+ }
+ }, function (err) {
+ djstest.fail("Unexpected call to error handler with error: " + djstest.toString(err));
+ djstest.destroyCacheAndDone(cache);
+ });
+ };
+
+ callReadRange();
+ }
+ };
+
+ $.each(CacheOracle.mechanisms, function (_, mechanism) {
+ if (mechanism !== "best" && CacheOracle.isMechanismAvailable(mechanism)) {
+ $.each(feeds, function (_, feed) {
+ djstest.addTest(cacheReadRangeWallClockTest(2, 1000, mechanism, feed.uri, 5, 0, function () {
+ return { index: 0, count: 5 };
+ }), "Cache small single-page wall-clock test with " + mechanism + " on " + feed.uri);
+
+ djstest.addTest(cacheReadRangeWallClockTest(5, 1000, mechanism, feed.uri, 3, -1, function (readCount) {
+ return { index: readCount * 3, count: 3 };
+ }), "Cache page-by-page wall-clock test with " + mechanism + " on " + feed.uri);
+
+ djstest.addTest(cacheReadRangeWallClockTest(5, 1000, mechanism, feed.uri, 3, -1, function (readCount) {
+ return { index: readCount, count: 3 };
+ }), "Cache line-by-line wall-clock test with " + mechanism + " on " + feed.uri);
+ });
+
+ var largeFeedUri = "./endpoints/LargeCollectionService.svc/Customers";
+ djstest.addTest(cacheReadRangeWallClockTest(2, 1000, mechanism, largeFeedUri, 100, 0, function () {
+ return { index: 0, count: 500 };
+ }), "Cache large single-page wall-clock test with " + mechanism + " on " + largeFeedUri, undefined, 60000);
+ }
+ });
+})(this);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata3-js/blob/9aa185d4/JSLib/tests/odata-cache-functional-tests.html
----------------------------------------------------------------------
diff --git a/JSLib/tests/odata-cache-functional-tests.html b/JSLib/tests/odata-cache-functional-tests.html
new file mode 100644
index 0000000..e6f2992
--- /dev/null
+++ b/JSLib/tests/odata-cache-functional-tests.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>OData tests against local service</title>
+ <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
+ <meta http-equiv="cache-control" content="no-cache"/>
+ <meta http-equiv="pragma" content="no-cache"/>
+ <meta http-equiv="expires" content="-1"/>
+
+ <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+ <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
+ <script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.10.0.js"></script>
+ <script type="text/javascript" src="common/TestSynchronizerClient.js"></script>
+ <script type="text/javascript">
+ window.TestSynchronizer.init(QUnit);
+ </script>
+
+ <script type="text/javascript" src="../src/datajs.js"></script>
+ <script type="text/javascript" src="../src/utils.js"></script>
+ <script type="text/javascript" src="../src/xml.js"></script>
+
+ <script type="text/javascript" src="../src/odata-utils.js"></script>
+ <script type="text/javascript" src="../src/odata-handler.js"></script>
+ <script type="text/javascript" src="../src/odata-gml.js"></script>
+ <script type="text/javascript" src="../src/odata-xml.js"></script>
+ <script type="text/javascript" src="../src/odata-net.js"></script>
+ <script type="text/javascript" src="../src/odata-json-light.js"></script>
+ <script type="text/javascript" src="../src/odata-json.js"></script>
+ <script type="text/javascript" src="../src/odata-atom.js"></script>
+ <script type="text/javascript" src="../src/odata-metadata.js"></script>
+ <script type="text/javascript" src="../src/odata-batch.js"></script>
+ <script type="text/javascript" src="../src/odata.js"></script>
+
+ <script type="text/javascript" src="../src/store-dom.js"></script>
+ <script type="text/javascript" src="../src/store-indexeddb.js"></script>
+ <script type="text/javascript" src="../src/store-memory.js"></script>
+ <script type="text/javascript" src="../src/store.js"></script>
+
+ <script type="text/javascript" src="../src/deferred.js"></script>
+ <script type="text/javascript" src="../src/cache-source.js"></script>
+ <script type="text/javascript" src="../src/cache.js"></script>
+
+ <script type="text/javascript" src="common/djstest.js"></script>
+ <script type="text/javascript" src="common/CacheOracle.js"></script>
+ <script type="text/javascript" src="common/ObservableHttpClient.js"></script>
+ <script type="text/javascript" src="common/ODataReadOracle.js"></script>
+ <script type="text/javascript" src="odata-cache-functional-tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">datajs.cache tests against local in-memory service</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/olingo-odata3-js/blob/9aa185d4/JSLib/tests/odata-cache-functional-tests.js
----------------------------------------------------------------------
diff --git a/JSLib/tests/odata-cache-functional-tests.js b/JSLib/tests/odata-cache-functional-tests.js
new file mode 100644
index 0000000..90f436e
--- /dev/null
+++ b/JSLib/tests/odata-cache-functional-tests.js
@@ -0,0 +1,613 @@
+/// <reference path="../src/datajs.js" />
+/// <reference path="../src/odata-utils.js" />
+/// <reference path="../src/cache.js" />
+/// <reference path="common/djstest.js" />
+
+(function (window, undefined) {
+ OData.defaultHandler.accept = "application/atomsvc+xml;q=0.9, application/json;odata=verbose;q=0.8, application/json;odata=fullmetadata;q=0.7, application/json;q=0.5, */*;q=0.1";
+ var CustomDataSource = function (baseUri) {
+ this.baseUri = baseUri;
+ };
+
+ CustomDataSource.prototype.read = function (index, count, success, error) {
+ var that = this;
+ var url = this.baseUri + "?$skip=" + index + "&$top=" + count;
+ $(this).triggerHandler("request", { requestUri: url });
+ $.ajax({
+ url: url,
+ dataType: "json",
+ success: function (results) {
+ $(that).triggerHandler("success", { data: { results: results} });
+ success(results);
+ },
+ error: error
+ });
+ };
+
+ CustomDataSource.prototype.count = function (success, error) {
+ $.ajax({
+ url: "./endpoints/CustomDataService.svc/Count",
+ dataType: "json",
+ success: success,
+ error: error
+ });
+ },
+
+ CustomDataSource.prototype.toString = function () {
+ return this.baseUri;
+ }
+
+ var sources = [
+ { source: "./endpoints/FoodStoreDataService.svc/Foods", countSupported: false },
+ { source: "./endpoints/FoodStoreDataServiceV2.svc/Foods", countSupported: true },
+ { source: "./endpoints/FoodStoreDataServiceV3.svc/Foods", countSupported: true },
+ { source: new CustomDataSource("./endpoints/CustomDataService.svc/ReadRange"), countSupported: true }
+ ];
+
+ var itemsInCollection = 16;
+
+ // Cache config variations for single readRange with fixed skip/take that spans the entire collection
+ var pageSizes = [
+ 1,
+ 4, // factor of total, <= server page size
+ 5, // non-factor of total, <= server page size
+ 6, // non-factor of total, > server page size
+ 8, // factor of total, > server page size
+ itemsInCollection,
+ itemsInCollection + 1
+ ];
+
+ var cacheSizes = [
+ -5, // All you can store
+ 0, // Store nothing
+ 1024, // 1 KB
+ 2.5 * 1024, // 2.5 KB
+ 100 * 1024, // 10 KB
+ 512 * 1024, // 512 KB
+ 100 * 1024 * 1024, // 100 MB
+ undefined // Default to 1 MB
+ ];
+
+ // Skip/take variations for single readRange with fixed cache config
+ var fixedPageSize = 6;
+
+ var skipValues = [
+ 0,
+ fixedPageSize - 1,
+ fixedPageSize,
+ fixedPageSize + 1,
+ fixedPageSize * 2,
+ itemsInCollection + 1,
+ itemsInCollection + fixedPageSize + 1
+ ];
+
+ var takeValues = [
+ 0,
+ fixedPageSize - 1,
+ fixedPageSize,
+ fixedPageSize + 1,
+ fixedPageSize * 2,
+ itemsInCollection + 1
+ ];
+
+ // Skip/take variations for multiple readRanges with fixed cache config
+ var multipleReads = [
+ { skip: 1, take: 2 }, // page 1
+ {skip: 2, take: 7 }, // page 1, 2
+ {skip: 3, take: 10 }, // page 1, 2, 3
+ {skip: 6, take: 2} // page 2
+ ];
+
+ var invalidSkipValues = [-5, NaN, undefined, Infinity, "not a valid value"];
+ var invalidTakeValues = [-5, NaN, undefined, Infinity, "not a valid value"];
+ var invalidPageSizes = [-5, NaN, Infinity, 0, "not a valid value"];
+
+ // Prefetchsize variations for a single readRange
+ var prefetchSizes = [
+ -5,
+ 1,
+ 5,
+ itemsInCollection,
+ itemsInCollection + 1
+ ];
+
+ var expectException = function (cache) {
+ djstest.assert(false, "We should not get here because the an exception is expected.");
+ djstest.destroyCacheAndDone(cache);
+ };
+
+ var makeUnexpectedErrorHandler = function (cache) {
+ return function (err) {
+ djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+ if (cache) {
+ djstest.destroyCacheAndDone(cache);
+ } else {
+ djstest.done();
+ }
+ };
+ };
+
+ var validateExpectedRange = function (cache, data, source, skipValue, takeValue, finished) {
+ /// <summary>Validates the data returned by readRange</summary>
+ /// <param name="cache" type="Object">The cache object</param>
+ /// <param name="data" type="Object">The data returned by the cache</param>
+ /// <param name="source" type="Object">The base URI of the feed, or the custom data source</param>
+ /// <param name="skipValue type="Integer">The skip value</param>
+ /// <param name="takeValue" type="Integer">The take value</param>
+ /// <param name="finished" type="Function">Callback function called after data is verified</param>
+ var assertData = function (expectedData) {
+ djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
+ finished();
+ };
+
+ if (typeof source === "string") {
+ var expectedRangeUrl = source + "?$skip=" + skipValue + "&$top=" + takeValue;
+ window.ODataReadOracle.readJsonAcrossServerPages(expectedRangeUrl, assertData);
+ } else {
+ source.read(skipValue, takeValue, assertData);
+ }
+ };
+
+ var onidleValidation = function () {
+ djstest.assert(true, "expected call to onidle");
+ djstest.done();
+ };
+
+ var createSingleReadTestName = function (params) {
+ return "Testing readRange of " + params.source + " [skip " + params.skip + " take " + params.take + "] with pageSize " +
+ params.pageSize + ", prefetch " + params.prefetchSize + " and cacheSize " + params.cacheSize;
+ };
+
+ var createMultipleReadTestName = function (params) {
+ return "Testing readRange of " + params.source + " [skip " + params.firstSkip + " take " + params.firstTake + ", " +
+ (params.destroyCacheBetweenReads ? "cache.destroy(), " : "") +
+ "skip " + params.secondSkip + " take " + params.secondTake + "] with pageSize " +
+ params.pageSize + ", prefetch " + params.prefetchSize + " and cacheSize " + params.cacheSize;
+ };
+
+ var dataCacheSingleReadRangeTest = function (params) {
+ djstest.assertsExpected(2);
+ var options = { name: "cache" + new Date().valueOf(), source: params.source, pageSize: params.pageSize, prefetchSize: params.prefetchSize, cacheSize: params.cacheSize };
+
+ if (params.mechanism) {
+ options.mechanism = params.mechanism;
+ }
+
+ var cache = this.createAndAddCache(options);
+ var session = typeof params.source === "string" ? this.observableHttpClient.newSession() : new Session(params.source);
+ var cacheOracle = new CacheOracle(params.source, params.pageSize, itemsInCollection, params.cacheSize);
+ cache.readRange(params.skip, params.take).then(function (data) {
+ cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "readRange requests");
+ validateExpectedRange(cache, data, params.source, params.skip, params.take, function () {
+ djstest.destroyCacheAndDone(cache);
+ });
+ }, makeUnexpectedErrorHandler(cache));
+ };
+
+ var dataCacheParallelReadRangeTest = function (params) {
+ djstest.assertsExpected(2);
+ var options = { name: "cache" + new Date().valueOf(), source: params.source, pageSize: params.pageSize, prefetchSize: params.prefetchSize, cacheSize: params.cacheSize };
+
+ var cache = this.createAndAddCache(options);
+
+ var firstReadRange = function (finished) {
+ cache.readRange(params.firstSkip, params.firstTake).then(function (data) {
+ validateExpectedRange(cache, data, params.source, params.firstSkip, params.firstTake, finished);
+ }, makeUnexpectedErrorHandler(cache));
+ }
+ var secondReadRange = function (finished) {
+ cache.readRange(params.secondSkip, params.secondTake).then(function (data) {
+ validateExpectedRange(cache, data, params.source, params.secondSkip, params.secondTake, finished);
+ }, makeUnexpectedErrorHandler(cache));
+ }
+
+ djstest.asyncDo([firstReadRange, secondReadRange], function () {
+ djstest.destroyCacheAndDone(cache);
+ });
+ };
+
+ var dataCacheSerialReadRangeTest = function (params) {
+ djstest.assertsExpected(4);
+ var options = { name: "cache" + new Date().valueOf(), source: params.source, pageSize: params.pageSize, prefetchSize: params.prefetchSize, cacheSize: params.cacheSize };
+
+ var cacheOracle = new CacheOracle(params.source, params.pageSize, itemsInCollection, params.cacheSize);
+ var secondRead = function () {
+ session.clear();
+ cache.readRange(params.secondSkip, params.secondTake).then(function (data) {
+ cacheOracle.verifyRequests(session.requests, session.responses, params.secondSkip, params.secondTake, "Second readRange requests");
+ validateExpectedRange(cache, data, params.source, params.secondSkip, params.secondTake, djstest.done);
+ }, makeUnexpectedErrorHandler(cache));
+ }
+
+ var cache = this.createAndAddCache(options);
+ var session = typeof params.source === "string" ? this.observableHttpClient.newSession() : new Session(params.source);
+ cache.readRange(params.firstSkip, params.firstTake).then(function (data) {
+ cacheOracle.verifyRequests(session.requests, session.responses, params.firstSkip, params.firstTake, "First readRange requests");
+ validateExpectedRange(cache, data, params.source, params.firstSkip, params.firstTake, function () {
+ if (params.destroyCacheBetweenReads === true) {
+ cache.clear().then(function () {
+ cacheOracle.clear();
+ secondRead();
+ }, function (err) {
+ djstest.fail("Error destroying the cache: " + djstest.toString(err));
+ });
+ } else {
+ secondRead();
+ }
+ });
+ }, makeUnexpectedErrorHandler(cache));
+ };
+
+ var dataCachePrefetchTest = function (params) {
+ djstest.assertsExpected(2);
+ var options = {
+ name: "cache" + new Date().valueOf(),
+ source: params.source,
+ pageSize: params.pageSize,
+ prefetchSize: params.prefetchSize,
+ cacheSize: params.cacheSize,
+ user: params.user,
+ password: params.password
+ };
+
+ var cache = this.createAndAddCache(options);
+ var session = typeof params.source === "string" ? this.observableHttpClient.newSession() : new Session(params.source);
+ var cacheOracle = new CacheOracle(params.source, params.pageSize, itemsInCollection, params.cacheSize);
+
+ cache.readRange(params.skip, params.take).then(function (data) {
+ cacheOracle.verifyRequests(session.requests, session.responses, params.skip, params.take, "readRange requests");
+ session.clear();
+ }, makeUnexpectedErrorHandler(cache));
+
+ cache.onidle = function () {
+ var prefetchSize = params.prefetchSize < 0 ? itemsInCollection : params.prefetchSize;
+ cacheOracle.verifyRequests(session.requests, session.responses, params.skip + params.take, prefetchSize, "prefetch requests", false, true);
+ cache.onidle = false;
+ djstest.destroyCacheAndDone(cache);
+ };
+ };
+
+ var cleanDomStorage = function (done) {
+ /// <summary>Cleans all the data saved in the browser's DOM Storage. Needs to be called asynchronously in the
+ /// setup and teardown methods to be consistent with indexedDb's cleanup method.</summary>
+ /// <param name="done" type="Function">Function to be called after DOM storage is cleared.</param>
+ if (window.localStorage) {
+ window.localStorage.clear();
+ }
+ done();
+ };
+
+ var cleanIndexedDb = function (done) {
+ /// <summary>Cleans all the data saved in the browser's IndexedDb Storage.</summary>
+ /// <param name="done" type="Function">Function to be called after indexedDb is cleared.</param>
+ var caches = this.caches;
+
+ djstest.cleanStoreOnIndexedDb(caches, done);
+ };
+
+ var cleanupAllStorage = function (done) {
+ /// <summary>Cleans up all available storage mechanisms in the browser.</summary>
+ /// <param name="done" type="Function">Function to be called by each cleanup function after storage is cleared.</param>
+ var that = this;
+ var storeCleanup = [];
+
+ $.each(CacheOracle.mechanisms, function (_, mechanism) {
+ if (CacheOracle.isMechanismAvailable(mechanism)) {
+ storeCleanup.push(function (done) {
+ if(storageMechanisms[mechanism]){
+ storageMechanisms[mechanism].cleanup.call(that, done);
+ } else {
+ done();
+ }
+ });
+ }
+ });
+
+ djstest.asyncDo(storeCleanup, done);
+ }
+
+ var storageMechanisms = {
+ indexeddb: { cleanup: cleanIndexedDb },
+ dom: { cleanup: cleanDomStorage },
+ memory: { cleanup: function (done) { done(); } },
+ best: { cleanup: function (done) { done(); } }
+ };
+
+ module("Functional", {
+ setup: function () {
+ this.createAndAddCache = function (options) {
+ /// <summary>Returns a cache created from the options object and </summary>
+ /// <param name="options" type="Object">Object to create a cache from.</param>
+ var cache = datajs.createDataCache(options);
+ this.caches.push({ name: options.name, cache: cache });
+ return cache;
+ }
+
+ this.observableHttpClient = new ObservableHttpClient();
+ OData.defaultHttpClient = this.observableHttpClient;
+ this.caches = [];
+ var that = this;
+
+ djstest.wait(function (done) {
+ cleanupAllStorage.call(that, done);
+ });
+ },
+
+ teardown: function () {
+ OData.defaultHttpClient = this.observableHttpClient.provider;
+ var clearActions = [];
+ var that = this;
+
+ $.each(this.caches, function (_, cacheObject) {
+ cacheObject.cache.onidle = undefined;
+
+ clearActions.push(function (done) {
+ cacheObject.cache.clear().then(function () {
+ done();
+ },
+ function (err) {
+ djstest.assert(false, "Unexpected call to error handler while attempting to clear with error: " + djstest.toString(err));
+ })
+ });
+ });
+
+ djstest.wait(function (done) {
+ djstest.asyncDo(clearActions, function () {
+ cleanupAllStorage.call(that, function () {
+ that.caches = [];
+ done();
+ });
+ });
+ });
+ }
+ });
+
+ $.each(CacheOracle.mechanisms, function (_, mechanism) {
+ var parameters = { mechanism: mechanism, source: sources[1].source, take: 5, skip: 0, pageSize: 5, prefetchSize: 5 };
+ if (CacheOracle.isMechanismAvailable(mechanism)) {
+ djstest.addTest(dataCacheSingleReadRangeTest, "Specified mechanism: " + parameters.mechanism + createSingleReadTestName(parameters), parameters);
+ }
+ else {
+ djstest.addTest(function (params) {
+ djstest.assertsExpected(1);
+ var options = { name: "cache" + new Date().valueOf(), mechanism: params.mechanism, source: params.source };
+ try {
+ var cache = this.createAndAddCache(options);
+ expectException(cache);
+ }
+ catch (e) {
+ if (mechanism === "indexeddb") {
+ djstest.assertAreEqual(e.message, "IndexedDB is not supported on this browser", "Validating expected error");
+ } else if (mechanism === "dom") {
+ djstest.assertAreEqual(e.message, "Web Storage not supported by the browser", "Validating expected error");
+ } else {
+ djstest.fail("Creating cache with mechanism " + mechanism + " should not fail: " + djstest.toString(e));
+ }
+
+ djstest.done();
+ }
+ }, "Invalid mechanism for browser: " + parameters.mechanism + createSingleReadTestName(parameters), parameters);
+ }
+ });
+
+ $.each(sources, function (_, sourceObject) {
+ $.each(pageSizes, function (_, pageSizeValue) {
+ $.each(cacheSizes, function (_, cacheSizeValue) {
+ var parameters = { source: sourceObject.source, skip: 0, take: itemsInCollection, pageSize: pageSizeValue, prefetchSize: 0, cacheSize: cacheSizeValue };
+ djstest.addTest(dataCacheSingleReadRangeTest, createSingleReadTestName(parameters), parameters);
+ });
+ });
+
+ $.each(skipValues, function (_, skipValue) {
+ $.each(takeValues, function (_, takeValue) {
+ var parameters = { source: sourceObject.source, take: takeValue, skip: skipValue, pageSize: 4, prefetchSize: 0, cacheSize: 0 };
+ djstest.addTest(dataCacheSingleReadRangeTest, createSingleReadTestName(parameters), parameters);
+ });
+ });
+
+ $.each(multipleReads, function (_, firstRange) {
+ $.each(multipleReads, function (_, secondRange) {
+ var parallelReadParams = { source: sourceObject.source, firstTake: firstRange.take, firstSkip: firstRange.skip, secondTake: secondRange.take, secondSkip: secondRange.skip, pageSize: 5, prefetchSize: 0, cacheSize: 0 };
+ djstest.addTest(dataCacheParallelReadRangeTest, "Parallel: " + createMultipleReadTestName(parallelReadParams), parallelReadParams);
+
+ $.each([false, true], function (_, destroyCacheBetweenReads) {
+ var serialReadParams = $.extend({}, parallelReadParams, { destroyCacheBetweenReads: destroyCacheBetweenReads });
+ djstest.addTest(dataCacheSerialReadRangeTest, "Serial: " + createMultipleReadTestName(serialReadParams), serialReadParams);
+ });
+ });
+ });
+
+ var getInvalidValueErrorMessage = function (invalidValue, parameterName) {
+ /// <summary>Returns the expected error message for the specified invalid value.</summary>
+ /// <param name="invalidValue type="Object">invalid value (anything other than zero or positive integer) to determine the error message from.</param>
+ /// <param name="parameterName" type="String">The name of the parameter being verified.</param>
+ /// <returns type="String">Error message expected.</returns>
+ return (invalidValue === undefined || typeof invalidValue !== "number") ?
+ "'" + parameterName + "' must be a number." :
+ "'" + parameterName + "' must be greater than or equal to zero.";
+ };
+
+ $.each(invalidSkipValues, function (_, invalidSkipValue) {
+ var parameters = { source: sourceObject.source, skip: invalidSkipValue, take: 1 };
+ djstest.addTest(function (params) {
+ djstest.assertsExpected(1);
+ var options = { name: "cache" + new Date().valueOf(), source: params.source };
+ var cache = this.createAndAddCache(options);
+ try {
+ cache.readRange(params.skip, params.take);
+ expectException(cache);
+ } catch (e) {
+ djstest.assertAreEqual(e.message, getInvalidValueErrorMessage(invalidSkipValue, "index"), "Error message validation");
+ djstest.destroyCacheAndDone(cache);
+ }
+ }, "Invalid skip: " + createSingleReadTestName(parameters), parameters);
+ });
+
+ $.each(invalidTakeValues, function (_, invalidTakeValue) {
+ var parameters = { source: sourceObject.source, skip: 0, take: invalidTakeValue };
+ djstest.addTest(function (params) {
+ djstest.assertsExpected(1);
+ var options = { name: "cache" + new Date().valueOf(), source: params.source };
+ var cache = this.createAndAddCache(options);
+ try {
+ cache.readRange(params.skip, params.take);
+ expectException(cache);
+ } catch (e) {
+ djstest.assertAreEqual(e.message, getInvalidValueErrorMessage(invalidTakeValue, "count"), "Error message validation");
+ djstest.destroyCacheAndDone(cache);
+ }
+ }, "Invalid take: " + createSingleReadTestName(parameters), parameters);
+ });
+
+ $.each(invalidPageSizes, function (_, invalidPageSize) {
+ var parameters = { source: sourceObject.source, skip: 0, take: 5, pageSize: invalidPageSize };
+ djstest.addTest(function (params) {
+ var options = { name: "cache", source: params.source, pageSize: params.pageSize };
+ try {
+ var cache = this.createAndAddCache(options);
+ expectException(cache);
+ } catch (e) {
+ var expectedError = typeof invalidPageSize === "number" ? "'pageSize' must be greater than zero." : getInvalidValueErrorMessage(invalidPageSize, "pageSize");
+ djstest.assertAreEqual(e.message, expectedError, "Error message validation");
+ }
+ djstest.done();
+ }, "Invalid pageSize: " + createSingleReadTestName(parameters), parameters);
+ });
+
+ $.each(pageSizes, function (_, pageSize) {
+ $.each(cacheSizes, function (_, cacheSize) {
+ var parameters = { source: sourceObject.source, skip: 0, take: pageSize, pageSize: pageSize, prefetchSize: -1, cacheSize: cacheSize };
+ djstest.addTest(dataCachePrefetchTest, "Prefetch: " + createSingleReadTestName(parameters), parameters);
+ });
+ });
+
+ $.each(skipValues, function (_, skipValue) {
+ var parameters = { source: sourceObject.source, skip: skipValue, take: fixedPageSize, pageSize: fixedPageSize, prefetchSize: -1, cacheSize: -1 };
+ djstest.addTest(dataCachePrefetchTest, "Prefetch: " + createSingleReadTestName(parameters), parameters);
+ });
+
+ $.each(takeValues, function (_, takeValue) {
+ var parameters = { source: sourceObject.source, skip: 0, take: takeValue, pageSize: fixedPageSize, prefetchSize: -1, cacheSize: -1 };
+ djstest.addTest(dataCachePrefetchTest, "Prefetch: " + createSingleReadTestName(parameters), parameters);
+ });
+
+ $.each(prefetchSizes, function (_, prefetchSize) {
+ var parameters = { source: sourceObject.source, skip: 0, take: fixedPageSize, pageSize: fixedPageSize, prefetchSize: prefetchSize, cacheSize: -1 };
+ djstest.addTest(dataCachePrefetchTest, "Prefetch: " + createSingleReadTestName(parameters), parameters);
+ });
+
+ var fixedPrefetchSize = 5;
+
+ djstest.addTest(function (params) {
+ djstest.assertsExpected(1);
+ var cache = this.createAndAddCache({
+ name: "cache" + new Date().valueOf(),
+ source: params.source,
+ prefetchSize: fixedPrefetchSize,
+ idle: onidleValidation,
+ pageSize: 2,
+ mechanism: "memory"
+ });
+ cache.readRange(0, 5);
+
+ }, "onidle in constructor, prefetch size = " + fixedPrefetchSize + " on " + sourceObject.source, { source: sourceObject.source });
+
+ djstest.addTest(function (params) {
+ djstest.assertsExpected(1);
+ var cache = this.createAndAddCache({
+ name: "cache" + new Date().valueOf(),
+ source: params.source,
+ prefetchSize: fixedPrefetchSize,
+ pageSize: 2,
+ mechanism: "memory"
+ });
+ cache.onidle = onidleValidation;
+ cache.readRange(0, 5);
+ }, "onidle, prefetch size = " + fixedPrefetchSize + " on " + sourceObject.source, { source: sourceObject.source });
+
+ djstest.addTest(function (params) {
+ djstest.assertsExpected(1);
+ var cache = this.createAndAddCache({
+ name: "cache" + new Date().valueOf(),
+ source: params.source,
+ prefetchSize: fixedPrefetchSize,
+ idle: function () { djstest.assert(false, "unexpected onidle call") },
+ pageSize: 2,
+ mechanism: "memory"
+ });
+ cache.onidle = onidleValidation;
+ cache.readRange(0, 5);
+ }, "onidle override, prefetch size = " + fixedPrefetchSize + " on " + sourceObject.source, { source: sourceObject.source });
+
+ djstest.addTest(function (params) {
+ var cache = this.createAndAddCache({ name: "cache" + new Date().valueOf(), source: params.source, pageSize: 1, prefetchSize: -1 });
+ var observableSource = typeof params.source === "string" ? this.observableHttpClient : params.source;
+ cache.readRange(0, 1).then(function (data) {
+ // Let one prefetch request go out, to make sure the prefetcher is started, and then destroy the cache
+ $(observableSource).one("success", function () {
+ var session = new Session(observableSource);
+ cache.clear().then(function () {
+ setTimeout(function () {
+ djstest.assertAreEqualDeep(session.requests, [], "Verify no prefetch requests are sent out after cache.clear() callback");
+ djstest.done();
+ }, 1000);
+ }, function (err) {
+ djstest.fail("Error destroying the cache: " + djstest.toString(err));
+ });
+ });
+ });
+ }, "Testing cache.clear() halts the prefetcher" + sourceObject.source, { source: sourceObject.source });
+
+ djstest.addTest(function (params) {
+ var cache = this.createAndAddCache({ name: "cache" + new Date().valueOf(), source: params.source });
+ if (params.countSupported) {
+ cache.count().then(function (count) {
+ djstest.assertAreEqual(count, itemsInCollection, "All items accounted for");
+ djstest.destroyCacheAndDone(cache);
+ }, makeUnexpectedErrorHandler(cache));
+ }
+ else {
+ cache.count().then(function (count) {
+ djstest.assert(false, "Success should not be called, count not supported");
+ djstest.destroyCacheAndDone(cache);
+ }, function (err) {
+ djstest.assertAreEqual(err.message, "HTTP request failed", "Validating expected error");
+ djstest.destroyCacheAndDone(cache);
+ });
+ }
+ }, "Testing cache.count() on " + sourceObject.source, { source: sourceObject.source, countSupported: sourceObject.countSupported });
+
+ djstest.addTest(function (params) {
+ var cache = this.createAndAddCache({ name: "cache" + new Date().valueOf(), source: params.source, pageSize: 1, prefetchSize: 0 });
+ var session = typeof params.source === "string" ? this.observableHttpClient.newSession() : new Session(params.source);
+ cache.readRange(0, 1).cancel();
+ setTimeout(function () {
+ djstest.assertAreEqualDeep(session.requests, [], "Verify no requests are sent out after readRange is cancelled");
+ djstest.done();
+ }, 1000);
+ }, "Testing cancel()" + sourceObject.source, { source: sourceObject.source });
+
+ djstest.addTest(function (params) {
+ djstest.assertsExpected(1);
+ var cache = this.createAndAddCache({ name: "cache" + new Date().valueOf(), source: params.source, pageSize: 1, prefetchSize: 0 });
+ cache.clear().then(function () {
+ cache.clear().then(function () {
+ djstest.pass("Second clear succeeded");
+ djstest.done();
+ }, makeUnexpectedErrorHandler(cache));
+ }, makeUnexpectedErrorHandler(cache));
+ }, "Testing .clear().then(cache.clear())" + sourceObject.source, { source: sourceObject.source });
+ });
+
+ var params = {
+ source: "./endpoints/BasicAuthDataService.svc/Customers",
+ skip: 0,
+ take: 5,
+ pageSize: 5,
+ prefetchSize: -1,
+ cacheSize: -1,
+ user: "djsUser",
+ password: "djsPassword"
+ };
+ djstest.addTest(dataCachePrefetchTest, createSingleReadTestName(params), params);
+})(this);
http://git-wip-us.apache.org/repos/asf/olingo-odata3-js/blob/9aa185d4/JSLib/tests/odata-cache-rx-functional-tests.html
----------------------------------------------------------------------
diff --git a/JSLib/tests/odata-cache-rx-functional-tests.html b/JSLib/tests/odata-cache-rx-functional-tests.html
new file mode 100644
index 0000000..8635ec3
--- /dev/null
+++ b/JSLib/tests/odata-cache-rx-functional-tests.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>>datajs.cache toObservable() tests</title>
+ <meta http-equiv="cache-control" content="no-cache"/>
+ <meta http-equiv="pragma" content="no-cache"/>
+ <meta http-equiv="expires" content="-1"/>
+
+ <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+ <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
+ <script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.10.0.js"></script>
+ <script type="text/javascript" src="common/TestSynchronizerClient.js"></script>
+ <script type="text/javascript">
+ window.TestSynchronizer.init(QUnit);
+ </script>
+
+ <script type="text/javascript" src="../src/datajs.js"></script>
+ <script type="text/javascript" src="../src/utils.js"></script>
+ <script type="text/javascript" src="../src/xml.js"></script>
+
+ <script type="text/javascript" src="../src/odata-utils.js"></script>
+ <script type="text/javascript" src="../src/odata-handler.js"></script>
+ <script type="text/javascript" src="../src/odata-gml.js"></script>
+ <script type="text/javascript" src="../src/odata-xml.js"></script>
+ <script type="text/javascript" src="../src/odata-net.js"></script>
+ <script type="text/javascript" src="../src/odata-json-light.js"></script>
+ <script type="text/javascript" src="../src/odata-json.js"></script>
+ <script type="text/javascript" src="../src/odata-atom.js"></script>
+ <script type="text/javascript" src="../src/odata-metadata.js"></script>
+ <script type="text/javascript" src="../src/odata-batch.js"></script>
+ <script type="text/javascript" src="../src/odata.js"></script>
+
+ <script type="text/javascript" src="../src/store-dom.js"></script>
+ <script type="text/javascript" src="../src/store-indexeddb.js"></script>
+ <script type="text/javascript" src="../src/store-memory.js"></script>
+ <script type="text/javascript" src="../src/store.js"></script>
+
+ <script type="text/javascript" src="../src/deferred.js"></script>
+ <script type="text/javascript" src="../src/cache-source.js"></script>
+ <script type="text/javascript" src="../src/cache.js"></script>
+
+ <script type="text/javascript" src="common/djstest.js"></script>
+ <script type="text/javascript" src="common/ODataReadOracle.js"></script>
+ <script type="text/javascript" src="common/rx.js"></script>
+ <script type="text/javascript" src="odata-cache-rx-functional-tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">datajs.cache toObservable() tests</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/olingo-odata3-js/blob/9aa185d4/JSLib/tests/odata-cache-rx-functional-tests.js
----------------------------------------------------------------------
diff --git a/JSLib/tests/odata-cache-rx-functional-tests.js b/JSLib/tests/odata-cache-rx-functional-tests.js
new file mode 100644
index 0000000..5958abc
--- /dev/null
+++ b/JSLib/tests/odata-cache-rx-functional-tests.js
@@ -0,0 +1,76 @@
+/// <reference path="../src/datajs.js" />
+/// <reference path="../src/odata-utils.js" />
+/// <reference path="../src/cache.js" />
+/// <reference path="common/djstest.js" />
+/// <reference path="common/ODataReadOracle.js" />
+/// <reference path="common/rx.js" />
+
+(function (window, undefined) {
+ OData.defaultHandler.accept = "application/atomsvc+xml;q=0.9, application/json;odata=verbose;q=0.8, application/json;odata=fullmetadata;q=0.7, application/json;q=0.5, */*;q=0.1";
+ var feeds = [
+ { uri: "./endpoints/FoodStoreDataService.svc/Foods" },
+ { uri: "./endpoints/FoodStoreDataServiceV2.svc/Foods" },
+ { uri: "./endpoints/FoodStoreDataServiceV3.svc/Foods" }
+ ];
+
+ var itemsInCollection = 16;
+ var pageSizes = [
+ 1,
+ 4, // factor of total, <= server page size
+ 5, // non-factor of total, <= server page size
+ 6, // non-factor of total, > server page size
+ 8, // factor of total, > server page size
+ itemsInCollection,
+ itemsInCollection + 1
+ ];
+
+ var operatorTests = [
+ function (observable) { return observable.Take(0); },
+ function (observable) { return observable.Take(1); },
+ function (observable) { return observable.Skip(1); },
+ function (observable) { return observable.Skip(2).Take(4); },
+ function (observable) { return observable.Select(function (item) { return item.Name; }); },
+ function (observable) { return observable.Where(function (item) { return item.FoodID % 2 === 1; }); }
+ ];
+
+ var assertObservables = function (actual, expected, done) {
+ /// <summary>Asserts two finite observables generate the same sequence</summary>
+ /// <param name="actual" type="IObservable">The actual observable</param>
+ /// <param name="expected" type="IObservable">The expected observable</param>
+ /// <param name="done" type="Function">The callback function when asserts are done</param>
+ var toArray = function (observable, callback) {
+ var arr = [];
+ observable.Subscribe(
+ function (item) { arr.push(item); },
+ function (err) { arr.push({ "__error__": err }); },
+ function () { callback(arr); });
+ };
+
+ toArray(actual, function (actualSequence) {
+ toArray(expected, function (expectedSequence) {
+ djstest.assertAreEqualDeep(actualSequence, expectedSequence, "Verify observable sequence");
+ done();
+ });
+ });
+ };
+
+ module("Functional");
+ $.each(feeds, function (_, feed) {
+ $.each(pageSizes, function (_, pageSize) {
+ $.each(operatorTests, function (_, operator) {
+ var params = { feedUri: feed.uri, pageSize: pageSize, operator: operator };
+ djstest.addTest(function (params) {
+ djstest.assertsExpected(1);
+ var options = { name: "cache" + new Date().valueOf(), source: params.feedUri, pageSize: params.pageSize, prefetchSize: 0 };
+ var cache = datajs.createDataCache(options);
+
+ ODataReadOracle.readJsonAcrossServerPages(params.feedUri, function (collection) {
+ assertObservables(params.operator(cache.toObservable()), params.operator(window.Rx.Observable.FromArray(collection)), function () {
+ djstest.destroyCacheAndDone(cache);
+ });
+ });
+ }, "feed: " + params.feedUri + ", pageSize: " + params.pageSize + ", operator: " + params.operator.toString(), params);
+ });
+ });
+ });
+})(this);