blob: 59a695bea97c908536094ace92cbd73f322b2b0c [file] [log] [blame]
// 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.
// CacheOracle.js
// This object verifies the operation of the cache.
// Internally it maintains a simple model of the cache implemented using a lookup array of the expected cached pages.
(function (window, undefined) {
var CacheOracle = function (baseUri, pageSize, total) {
/// <summary>Creates a new CacheOracle</summary>
/// <param name="baseUri" type="String">The base URI of the collection</param>
/// <param name="pageSize" type="Integer">The page size used in the cache</param>
/// <param name="total" type="Integer">The total number of items in the collection</param>
this.baseUri = baseUri;
this.pageSize = pageSize;
this.total = total;
this.cachedPages = [];
};
CacheOracle.mechanisms = {
memory: "memory",
indexeddb: "indexeddb",
dom: "dom",
best: "best"
};
CacheOracle.isMechanismAvailable = function (mechanism) {
/// <summary>Determines if the specified local storage mechanism is available</summary>
/// <param name="mechanism">The name of the mechanism</param>
/// <returns>Whether the mechanism is available</returns>
switch (mechanism) {
case CacheOracle.mechanisms.indexeddb:
if (window.mozIndexedDB) {
return true;
}
else {
return false;
}
break;
case CacheOracle.mechanisms.dom:
if (window.localStorage) {
return true;
}
else {
return false;
}
break;
case CacheOracle.mechanisms.memory:
case CacheOracle.mechanisms.best:
case undefined:
return true;
default:
return false;
}
}
CacheOracle.prototype.clear = function () {
/// <summary>Clears the cache in the oracle</summary>
this.cachedPages = [];
}
CacheOracle.prototype.verifyRequests = function (requests, responses, index, count, description) {
/// <summary>Verifies the HTTP requests for a single data request, and updates the oracle with cached pages</summary>
/// <param name="requests" type="Array">The sequence of request objects (from OData.defaultHttpClient)</param>
/// <param name="responses" type="Array">The sequence of response objects (from OData.defaultHttpClient)</param>
/// <param name="index" type="Integer">The starting index of the read</param>
/// <param name="count" type="Integer">The count of items in the read</param>
/// <param name="description" type="String">The description of the requests being verified</param>
var that = this;
var pageIndex = function (index) {
/// <summary>Returns the page index that the given item index belongs to</summary>
/// <param name="index" type="Integer">The item index</param>
/// <returns>The page index</returns>
return Math.floor(index / that.pageSize);
}
var minPage = pageIndex(index);
var maxPage = Math.min(pageIndex(index + count - 1), pageIndex(that.total));
// Workaround for Bug 2055: Calling readRange with count = 0 still fires a single HTTP request
maxPage = Math.max(minPage, maxPage);
var expectedUris = [];
var responseIndex = 0;
for (var page = minPage; page <= maxPage; page++) {
if (!this.cachedPages[page]) {
expectedUris.push(that.baseUri + "?$skip=" + page * that.pageSize + "&$top=" + (that.pageSize));
// Handle server paging skipToken requests
while (responses[responseIndex] && responses[responseIndex].data && responses[responseIndex].data.__next) {
expectedUris.push(responses[responseIndex].data.__next);
responseIndex++;
}
responseIndex++;
this.cachedPages[page] = true;
}
}
var actualUris = $.map(requests, function (r) { return r.requestUri; });
djstest.assertAreEqualDeep(actualUris, expectedUris, description);
};
window.CacheOracle = CacheOracle;
})(this);