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/15 03:09:42 UTC
[08/10] [OLINGO-276] Check in the missing test source codes.
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/48761e07/JSLib/tests/endpoints/EpmDataService.svc
----------------------------------------------------------------------
diff --git a/JSLib/tests/endpoints/EpmDataService.svc b/JSLib/tests/endpoints/EpmDataService.svc
new file mode 100644
index 0000000..ba90c23
--- /dev/null
+++ b/JSLib/tests/endpoints/EpmDataService.svc
@@ -0,0 +1,315 @@
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+ Service="DataJS.Tests.EpmDataService" %>
+
+namespace DataJS.Tests
+{
+ using System;
+ using System.Collections.Generic;
+ using Microsoft.OData.Service;
+ using Microsoft.OData.Service.Common;
+ using System.Linq;
+ using System.ServiceModel.Web;
+
+ /// <summary>
+ /// A data service that uses EPM
+ /// </summary>
+ [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+ public class EpmDataService : DataService<EpmDataSource>
+ {
+ // This method is called only once to initialize service-wide policies.
+ public static void InitializeService(DataServiceConfiguration config)
+ {
+ config.SetEntitySetAccessRule("*", EntitySetRights.All);
+ config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
+ config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V4;
+ config.UseVerboseErrors = true;
+
+ }
+
+ [WebInvoke]
+ public void ResetData()
+ {
+ this.CurrentDataSource.ResetData();
+ }
+ }
+
+ public class EpmDataSource : ReflectionDataContext, IUpdatable
+ {
+ private static bool dataInitialized;
+
+ public IQueryable<MappedEntry> MappedEntries
+ {
+ get { return this.GetResourceSetEntities<MappedEntry>("MappedEntries").AsQueryable(); }
+ }
+
+ public IQueryable<ReplicatedEntry> ReplicatedEntries
+ {
+ get { return this.GetResourceSetEntities<ReplicatedEntry>("ReplicatedEntries").AsQueryable(); }
+ }
+
+ public IQueryable<BaseEntry> HierarchicalEntries
+ {
+ get { return this.GetResourceSetEntities<BaseEntry>("HierarchicalEntries").AsQueryable(); }
+ }
+
+ public void ResetData()
+ {
+ this.ClearData();
+
+ MappedEntry[] mappedEntries = new MappedEntry[]
+ {
+ new MappedEntry
+ {
+ ID = 0,
+ UnmappedField = "Unmapped0",
+ Author = new Author
+ {
+ Email = "AuthorEmail0",
+ Name = "AuthorName0",
+ Uri = "http://www.example.com/AuthorUri",
+ Contributor = new Contributor
+ {
+ Email = "ContributorEmail0",
+ Name = "ContributorName0",
+ Uri = "http://www.example.com/ContributorUri",
+ },
+ },
+ Published = "2000-01-01T00:00:00-08:00",
+ Rights = "Rights0",
+ Summary = "<xmlElement xmlns=\"http://www.example.org/dummy\" attr=\"value0\">Summary0</xmlElement>",
+ Title = "Title<b>0</b>",
+ Updated = "2000-01-01T00:00:00-08:00",
+ CustomElement = "CustomElement0",
+ CustomAttribute = "CustomAttribute0",
+ NestedElement1 = "NestedElement1_0",
+ NestedElement2 = "NestedElement2_0",
+ CommonAttribute1 = "CommonAttribute1_0",
+ CommonAttribute2 = "CommonAttribute2_0",
+ Location = new Location
+ {
+ Lat = 3.14f,
+ Long = 2.72f
+ }
+ },
+
+ new MappedEntry
+ {
+ ID = 1,
+ UnmappedField = null,
+ Author = new Author
+ {
+ Email = null,
+ Name = string.Empty,
+ Uri = "http://www.example.com/AuthorUri1",
+ Contributor = new Contributor
+ {
+ Email = null,
+ Name = string.Empty,
+ Uri = "http://www.example.com/ContributorUri1",
+ },
+ },
+ Published = "2000-01-01T00:00:00-08:00",
+ Rights = null,
+ Summary = "",
+ Title = "Title<i>1</i>",
+ Updated = "2111-01-01T00:00:00-08:00",
+ CustomElement = null,
+ NestedElement1 = string.Empty,
+ NestedElement2 = "NestedElement2_1",
+ CustomAttribute = null,
+ CommonAttribute1 = string.Empty,
+ CommonAttribute2 = "CommonAttribute2_1",
+ Location = new Location
+ {
+ Lat = float.MaxValue,
+ Long = float.MinValue
+ }
+ },
+
+ new MappedEntry
+ {
+ ID = 2,
+ UnmappedField = "Unmapped2",
+ Author = new Author
+ {
+ Email = "AuthorEmail2",
+ Name = "AuthorName2",
+ Uri = "http://www.example.com/AuthorUri2",
+ Contributor = null
+ },
+ Published = "2000-01-01T00:00:00-08:00",
+ Rights = "Rights2",
+ Summary = "Summary2",
+ Title = "Title2",
+ Updated = "2000-01-01T00:00:00-08:00",
+ CustomElement = "CustomElement2",
+ CustomAttribute = "CustomAttribute2",
+ NestedElement1 = "NestedElement1_2",
+ NestedElement2 = "NestedElement2_2",
+ CommonAttribute1 = "CommonAttribute1_2",
+ CommonAttribute2 = "CommonAttribute2_2",
+ Location = null
+ },
+ };
+ Array.ForEach(mappedEntries, (item) => this.GetResourceSetEntities<MappedEntry>("MappedEntries").Add(item));
+
+ Array.ForEach(mappedEntries, (item) => this.GetResourceSetEntities<ReplicatedEntry>("ReplicatedEntries").Add(new ReplicatedEntry
+ {
+ ID = item.ID,
+ UnmappedField = item.UnmappedField,
+ Author = item.Author == null ? null : new Author2
+ {
+ Email = item.Author.Email,
+ Name = item.Author.Name,
+ Uri = item.Author.Uri,
+ Contributor = item.Author.Contributor == null ? null : new Contributor2
+ {
+ Name = item.Author.Contributor.Name,
+ Email = item.Author.Contributor.Email,
+ Uri = item.Author.Contributor.Uri
+ },
+ },
+ Published = item.Published,
+ Rights = item.Rights,
+ Summary = item.Summary,
+ Title = item.Title,
+ Updated = item.Updated,
+ CustomElement = item.CustomElement,
+ CustomAttribute = item.CustomAttribute,
+ NestedElement1 = item.NestedElement1,
+ NestedElement2 = item.NestedElement2,
+ CommonAttribute1 = item.CommonAttribute1,
+ CommonAttribute2 = item.CommonAttribute2,
+ Location = item.Location == null ? null : new Location2
+ {
+ Lat = item.Location.Lat,
+ Long = item.Location.Long
+ }
+ }));
+
+ BaseEntry[] hierarchicalEntries = new BaseEntry[]
+ {
+ new BaseEntry
+ {
+ ID = 0,
+ MappedField = "MappedField0",
+ MappedInDerivedField = "MappedInDerivedField0",
+ UnmappedField = "UnmappedField0"
+ },
+ new DerivedEntry
+ {
+ ID = 1,
+ MappedField = "MappedField1",
+ MappedInDerivedField = "MappedInDerivedField1",
+ UnmappedField = "UnmappedField1",
+ MappedConcreteField = "MappedConcreteField1",
+ UnmappedConcreteField = "UnmappedConcreteField1"
+ },
+ };
+ Array.ForEach(hierarchicalEntries, (item) => this.GetResourceSetEntities<BaseEntry>("HierarchicalEntries").Add(item));
+ }
+
+ protected override void EnsureDataIsInitialized()
+ {
+ if (!dataInitialized)
+ {
+ this.ResetData();
+ dataInitialized = true;
+ }
+ }
+ }
+
+ public class Author
+ {
+ public string Email { get; set; }
+ public string Name { get; set; }
+ public string Uri { get; set; }
+ public Contributor Contributor { get; set; }
+ }
+
+ public class Contributor
+ {
+ public string Email { get; set; }
+ public string Name { get; set; }
+ public string Uri { get; set; }
+ }
+
+ public class Location
+ {
+ public float Lat { get; set; }
+ public float Long { get; set; }
+ }
+
+ public class Author2
+ {
+ public string Email { get; set; }
+ public string Name { get; set; }
+ public string Uri { get; set; }
+ public Contributor2 Contributor { get; set; }
+ }
+
+ public class Contributor2
+ {
+ public string Email { get; set; }
+ public string Name { get; set; }
+ public string Uri { get; set; }
+ }
+
+ public class Location2
+ {
+ public float Lat { get; set; }
+ public float Long { get; set; }
+ }
+
+ public class MappedEntry
+ {
+ public int ID { get; set; }
+ public string UnmappedField { get; set; }
+ public Author Author { get; set; }
+ public string Published { get; set; }
+ public string Rights { get; set; }
+ public string Summary { get; set; }
+ public string Title { get; set; }
+ public string Updated { get; set; }
+ public string CustomElement { get; set; }
+ public string CustomAttribute { get; set; }
+ public string NestedElement1 { get; set; }
+ public string NestedElement2 { get; set; }
+ public string CommonAttribute1 { get; set; }
+ public string CommonAttribute2 { get; set; }
+ public Location Location { get; set; }
+ }
+
+ public class ReplicatedEntry
+ {
+ public int ID { get; set; }
+ public string UnmappedField { get; set; }
+ public Author2 Author { get; set; }
+ public string Published { get; set; }
+ public string Rights { get; set; }
+ public string Summary { get; set; }
+ public string Title { get; set; }
+ public string Updated { get; set; }
+ public string CustomElement { get; set; }
+ public string CustomAttribute { get; set; }
+ public string NestedElement1 { get; set; }
+ public string NestedElement2 { get; set; }
+ public string CommonAttribute1 { get; set; }
+ public string CommonAttribute2 { get; set; }
+ public Location2 Location { get; set; }
+ }
+
+ public class BaseEntry
+ {
+ public int ID { get; set; }
+ public string UnmappedField { get; set; }
+ public string MappedInDerivedField { get; set; }
+ public string MappedField { get; set; }
+ }
+
+ public class DerivedEntry : BaseEntry
+ {
+ public string UnmappedConcreteField { get; set; }
+ public string MappedConcreteField { get; set; }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/48761e07/JSLib/tests/endpoints/ErrorDataService.svc
----------------------------------------------------------------------
diff --git a/JSLib/tests/endpoints/ErrorDataService.svc b/JSLib/tests/endpoints/ErrorDataService.svc
new file mode 100644
index 0000000..d25e30e
--- /dev/null
+++ b/JSLib/tests/endpoints/ErrorDataService.svc
@@ -0,0 +1,56 @@
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+ Service="DataJS.Tests.ErrorDataService" %>
+
+namespace DataJS.Tests
+{
+ using System;
+ using System.Collections.Generic;
+ using Microsoft.OData.Service;
+ using Microsoft.OData.Service.Common;
+ using System.Linq;
+
+ /// <summary>
+ /// A data service that contains in-stream errors
+ /// </summary>
+ public class ErrorDataService : DataService<ErrorDataSource>
+ {
+ // This method is called only once to initialize service-wide policies.
+ public static void InitializeService(DataServiceConfiguration config)
+ {
+ config.SetEntitySetAccessRule("*", EntitySetRights.All);
+ config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V4;
+ }
+ }
+
+ public class ErrorDataSource
+ {
+ public IQueryable<ErrorType> Entities
+ {
+ get
+ {
+ ErrorType[] entities = new ErrorType[]
+ {
+ new ErrorType(() => 0),
+ new ErrorType(() => { throw new ApplicationException(); })
+ };
+
+ return entities.AsQueryable();
+ }
+ }
+ }
+
+ public class ErrorType
+ {
+ Func<int> generateID;
+
+ public ErrorType(Func<int> generateID)
+ {
+ this.generateID = generateID;
+ }
+
+ public int ID
+ {
+ get { return this.generateID(); }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/48761e07/JSLib/tests/endpoints/LargeCollectionService.svc
----------------------------------------------------------------------
diff --git a/JSLib/tests/endpoints/LargeCollectionService.svc b/JSLib/tests/endpoints/LargeCollectionService.svc
new file mode 100644
index 0000000..122d045
--- /dev/null
+++ b/JSLib/tests/endpoints/LargeCollectionService.svc
@@ -0,0 +1,93 @@
+<%@ ServiceHost Language="C#" Factory="Microsoft.OData.Service.DataServiceHostFactory, Microsoft.OData.Service, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
+ Service="DataJS.Tests.LargeCollectionService" %>
+
+namespace DataJS.Tests
+{
+ using System;
+ using System.Collections.Generic;
+ using Microsoft.OData.Service;
+ using Microsoft.OData.Service.Common;
+ using System.Linq;
+ using System.ServiceModel;
+ using System.ServiceModel.Web;
+ using System.Web;
+
+ [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
+ public class LargeCollectionService : DataService<LargeCollection>
+ {
+ // 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.UseVerboseErrors = true;
+ }
+
+ [WebInvoke]
+ public void ResetData()
+ {
+ this.CurrentDataSource.ResetData();
+ }
+ }
+
+ public class LargeCollection : ReflectionDataContext, IUpdatable
+ {
+ private static bool dataInitialized;
+
+ public IQueryable<Customer> Customers
+ {
+ get { return this.GetResourceSetEntities<Customer>("Customers").AsQueryable(); }
+ }
+
+ public IQueryable<Supplier> Suppliers
+ {
+ get { return this.GetResourceSetEntities<Supplier>("Suppliers").AsQueryable(); }
+ }
+
+ public void ResetData()
+ {
+ this.ClearData();
+
+ IList<Customer> customers = this.GetResourceSetEntities<Customer>("Customers");
+ foreach (int i in Enumerable.Range(1, 2 * 1024 * 1024))
+ {
+ customers.Add(new Customer()
+ {
+ ID = i,
+ Name = "Customer " + i
+ });
+ }
+
+ IList<Supplier> suppliers = this.GetResourceSetEntities<Supplier>("Suppliers");
+ foreach (int i in Enumerable.Range(1, 5000))
+ {
+ suppliers.Add(new Supplier()
+ {
+ ID = i,
+ Name = "Supplier " + i
+ });
+ }
+ }
+
+ protected override void EnsureDataIsInitialized()
+ {
+ if (!dataInitialized)
+ {
+ this.ResetData();
+ dataInitialized = true;
+ }
+ }
+ }
+
+ public class Customer
+ {
+ public int ID { get; set; }
+ public string Name { get; set; }
+ }
+
+ public class Supplier
+ {
+ public int ID { get; set; }
+ public string Name { get; set; }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/48761e07/JSLib/tests/odata-batch-functional-tests.html
----------------------------------------------------------------------
diff --git a/JSLib/tests/odata-batch-functional-tests.html b/JSLib/tests/odata-batch-functional-tests.html
new file mode 100644
index 0000000..c2c3759
--- /dev/null
+++ b/JSLib/tests/odata-batch-functional-tests.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>batch tests</title>
+ <meta http-equiv="cache-control" content="no-cache" />
+ <meta http-equiv="pragma" content="no-cache" />
+ <meta http-equiv="expires" content="-1" />
+ <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+ <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+ <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js"></script>
+ <script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.10.0.js"></script>
+ <script type="text/javascript" src="common/ODataReadOracle.js"></script>
+ <script type="text/javascript" src="common/TestSynchronizerClient.js"></script>
+ <script type="text/javascript">
+ window.TestSynchronizer.init(QUnit);
+ </script>
+
+ <script type="text/javascript" src="../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="common/djstest.js"></script>
+ <script type="text/javascript" src="odata-batch-functional-tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">batch tests</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/48761e07/JSLib/tests/odata-batch-functional-tests.js
----------------------------------------------------------------------
diff --git a/JSLib/tests/odata-batch-functional-tests.js b/JSLib/tests/odata-batch-functional-tests.js
new file mode 100644
index 0000000..b30e52c
--- /dev/null
+++ b/JSLib/tests/odata-batch-functional-tests.js
@@ -0,0 +1,270 @@
+/// <reference path="common/djstest.js" />
+/// <reference path="../src/odata.js" />
+/// <reference path="../src/odata-batch.js" />
+/// <reference path="common/ODataReadOracle.js" />
+
+(function (window, undefined) {
+ OData.defaultHandler.accept = "application/json;q=0.9, application/atomsvc+xml;q=0.8, */*;q=0.1";
+
+ var unexpectedErrorHandler = function (err) {
+ djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+ djstest.done();
+ };
+
+ var determineExpected = function (batchRequests) {
+ var expected = 0;
+ $.each(batchRequests, function (_, batchRequest) {
+ // 2 assertions per request: response code and data
+ if (batchRequest.__changeRequests) {
+ expected += batchRequest.__changeRequests.length * 2;
+ } else {
+ expected += 2;
+ }
+ });
+
+ // 2 more assertions than the number of requests in batch: response code and batch response length
+ return expected + 2;
+ };
+
+ var verifyBatchRequest = function(serviceRoot, batchRequests, elementTypes, done) {
+ OData.request({ requestUri: serviceRoot + "/$batch", method: "POST", data: { __batchRequests: batchRequests } },
+ function(data, response) {
+ djstest.assertAreEqual(response.statusCode, httpStatusCode.accepted, "Verify response code");
+ djstest.assertAreEqual(data.__batchResponses.length, batchRequests.length, "Verify batch response count");
+ verifyBatchResponses(batchRequests, elementTypes, serviceRoot, data.__batchResponses, done);
+ },
+ unexpectedErrorHandler, OData.batchHandler);
+ };
+
+ var verifyBatchResponses = function (batchRequests, elementTypes, serviceRoot, batchResponses, done) {
+ forEachAsync(batchRequests, function (index, batchRequest, doneOne) {
+ if (batchRequest.requestUri) {
+ var readFeedOrEntry = elementTypes[index] == "feed" ? ODataReadOracle.readFeed : ODataReadOracle.readEntry;
+ djstest.assertAreEqual(batchResponses[index].statusCode, httpStatusCode.ok, "Verify response code for: GET " + batchRequest.requestUri);
+ readFeedOrEntry(serviceRoot + "/" + batchRequest.requestUri, function (expectedData) {
+ djstest.assertAreEqualDeep(batchResponses[index].data, expectedData, "Verify data for: GET " + batchRequest.requestUri);
+ doneOne();
+ }, batchRequests[index].headers.Accept);
+ }
+ else if (batchRequest.__changeRequests) {
+ verifyChangeResponses(batchRequest.__changeRequests, batchResponses[index].__changeResponses, function () { doneOne(); });
+ }
+ }, done);
+ }
+
+ var verifyChangeResponses = function (changeRequests, changeResponses, done) {
+ forEachAsync(changeRequests, function (index, changeRequest, doneOne) {
+ var httpOperation = changeRequest.method + " " + changeRequest.requestUri;
+ var changeResponse = changeResponses[index];
+
+ if (changeRequest.method == "POST") {
+ djstest.assertAreEqual(changeResponse.statusCode, httpStatusCode.created, "Verify response code for: " + httpOperation);
+ ODataReadOracle.readEntry(changeResponse.headers["Location"], function (expectedData) {
+ djstest.assertAreEqualDeep(changeResponse.data, expectedData, "Verify response data for: " + httpOperation);
+ doneOne();
+ }, changeRequest.headers.Accept);
+ }
+ else if (changeRequest.method == "PUT") {
+ djstest.assertAreEqual(changeResponse.statusCode, httpStatusCode.noContent, "Verify response code for: " + httpOperation);
+ djstest.assertAreEqual(changeResponse.body, "", "Verify empty body for: " + httpOperation);
+ doneOne();
+ }
+ else if (changeRequest.method == "DELETE") {
+ djstest.assertAreEqual(changeResponse.statusCode, httpStatusCode.noContent, "Verify response code for: " + httpOperation);
+ djstest.assertAreEqual(changeResponse.body, "", "Verify empty body for: " + httpOperation);
+ doneOne();
+ }
+ }, done);
+ }
+
+ var forEachAsync = function (array, callback, done) {
+ var count = 0;
+ var doneOne = function () {
+ count++;
+ if (count == array.length) {
+ done();
+ }
+ }
+
+ $.each(array, function (index, element) { callback(index, element, doneOne); });
+ };
+
+ var service = "./endpoints/FoodStoreDataServiceV4.svc";
+ var batchUri = service + "/$batch";
+
+ var httpStatusCode = {
+ ok: 200,
+ created: 201,
+ accepted: 202,
+ noContent: 204
+ };
+
+ var mimeTypes = [undefined, /*"application/atom+xml",*/ "application/json;odata.metadata=minimal"];
+
+ module("Functional", {
+ setup: function () {
+ djstest.wait(function (done) {
+ $.post(service + "/ResetData", done);
+ });
+ }
+ });
+
+ $.each(mimeTypes, function (_, mimeType) {
+ var acceptHeaders = mimeType ? { Accept: mimeType} : undefined;
+ var mimeHeaders = mimeType ? { "Content-Type": mimeType, Accept: mimeType} : undefined;
+
+ djstest.addTest(function multipleRetrieves(acceptHeaders) {
+ var uriSegments = ["Foods(0)", "Foods?$filter=FoodID eq 1", "Foods?$top=2"];
+ var elementTypes = ["entry", "feed", "feed"];
+
+ var batchRequests = $.map(uriSegments, function (uriSegment) {
+ return { requestUri: uriSegment, method: "GET", headers: acceptHeaders }
+ });
+
+ djstest.assertsExpected(determineExpected(batchRequests));
+ verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
+ }, "Multiple retrieves: mimeType = " + mimeType, acceptHeaders);
+
+ djstest.addTest(function multipleChangesets(params) {
+ var batchRequests = [
+ {
+ __changeRequests: [
+ { requestUri: "Categories", method: "POST", headers: djstest.clone(params.mimeHeaders), data:
+ { CategoryID: 42, Name: "New Category" }
+ }
+ ]
+ },
+ {
+ __changeRequests: [
+ { requestUri: "Categories(1)", method: "PUT", headers: djstest.clone(params.mimeHeaders), data:
+ { CategoryID: 1, Name: "Updated Category" }
+ },
+ { requestUri: "Categories(0)", method: "DELETE", headers: djstest.clone(params.acceptHeaders) }
+ ]
+ }
+ ];
+ var elementTypes = [null, null];
+
+ djstest.assertsExpected(determineExpected(batchRequests));
+ verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
+ }, "Multiple changesets: mimeType = " + mimeType, { acceptHeaders: acceptHeaders, mimeHeaders: mimeHeaders });
+
+ djstest.addTest(function multipleRetrievesAndChangesets(params) {
+ // Header needs to be cloned because it is mutable; this means that after processing one request in the batch
+ // the header object will be modified
+ var batchRequests = [
+ { requestUri: "Foods(0)", method: "GET", headers: djstest.clone(params.acceptHeaders) },
+ { requestUri: "Foods?$filter=FoodID eq 1", method: "GET", headers: djstest.clone(params.acceptHeaders) },
+ {
+ __changeRequests: [
+ { requestUri: "Categories", method: "POST", headers: djstest.clone(params.mimeHeaders), data:
+ { CategoryID: 42, Name: "New Category" }
+ }
+ ]
+ },
+ { requestUri: "Foods?$top=2", method: "GET", headers: djstest.clone(params.acceptHeaders) },
+ {
+ __changeRequests: [
+ { requestUri: "Categories(1)", method: "PUT", headers: djstest.clone(params.mimeHeaders), data:
+ { CategoryID: 1, Name: "Updated Category" }
+ },
+ { requestUri: "Categories(0)", method: "DELETE", headers: djstest.clone(params.acceptHeaders) }
+ ]
+ }
+ ];
+ var elementTypes = ["entry", "feed", null, "feed", null];
+
+ djstest.assertsExpected(determineExpected(batchRequests));
+ verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
+ }, "Multiple retrieves and changesets: mimeType = " + mimeType, { acceptHeaders: acceptHeaders, mimeHeaders: mimeHeaders });
+
+ djstest.addTest(function singleRetrieve(acceptHeaders) {
+ var batchRequests = [{ requestUri: "Foods(2)", method: "GET", headers: acceptHeaders}];
+ var elementTypes = ["entry"];
+
+ djstest.assertsExpected(determineExpected(batchRequests));
+ verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
+ }, "Single retrieve: mimeType = " + mimeType, acceptHeaders);
+
+ djstest.addTest(function singleChangeset(params) {
+ var batchRequests = [
+ {
+ __changeRequests: [
+ { requestUri: "Categories", method: "POST", headers: djstest.clone(params.mimeHeaders), data:
+ { CategoryID: 42, Name: "New Category" }
+ },
+ { requestUri: "Categories(1)", method: "PUT", headers: djstest.clone(params.mimeHeaders), data:
+ { CategoryID: 1, Name: "Updated Category" }
+ }
+ ]
+ }
+ ];
+ var elementTypes = [null];
+
+ djstest.assertsExpected(determineExpected(batchRequests));
+ verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
+ }, "Single changeset: mimeType = " + mimeType, { acceptHeaders: acceptHeaders, mimeHeaders: mimeHeaders });
+
+ djstest.addTest(function singleRetrieveAndChangeset(params) {
+ var batchRequests = [
+ { requestUri: "Foods(0)", method: "GET", headers: djstest.clone(params.acceptHeaders) },
+ {
+ __changeRequests: [
+ { requestUri: "Categories", method: "POST", headers: djstest.clone(params.mimeHeaders), data:
+ { CategoryID: 42, Name: "New Category" }
+ },
+ { requestUri: "Categories(1)", method: "PUT", headers: djstest.clone(params.mimeHeaders), data:
+ { CategoryID: 1, Name: "Updated Category" }
+ }
+ ]
+ }
+ ];
+ var elementTypes = ["entry", null];
+
+ djstest.assertsExpected(determineExpected(batchRequests));
+ verifyBatchRequest(service, batchRequests, elementTypes, function () { djstest.done(); });
+ }, "Single retrieve and changeset: mimeType = " + mimeType, { acceptHeaders: acceptHeaders, mimeHeaders: mimeHeaders });
+ });
+
+ djstest.addTest(function updateOutsideChangeset() {
+ var batchRequests = [{ requestUri: "Categories", method: "POST", data: { CategoryID: 42, Name: "New Category"}}];
+
+ djstest.assertsExpected(1);
+ OData.request({ requestUri: batchUri, method: "POST", data: { __batchRequests: batchRequests} },
+ function (data, response) {
+ djstest.assert(response.body.indexOf("An error occurred while processing this request.") > -1, "Verify response error message");
+ djstest.done();
+ }, unexpectedErrorHandler, OData.batchHandler
+ );
+ }, "Update outside changeset");
+
+ djstest.addTest(function retrieveInsideChangeset() {
+
+ var batchRequests = [
+ { requestUri: "Foods(0)", method: "GET" },
+ { __changeRequests: [
+ { requestUri: "Categories", method: "POST", data: { CategoryID: 42, Name: "New Category"} },
+ { requestUri: "Categories(1)", method: "PUT", data: { CategoryID: 1, Name: "Updated Category"} }
+ ]
+ },
+ { requestUri: "Foods(1)", method: "GET" },
+ { __changeRequests: [
+ { requestUri: "Categories", method: "POST", data: { CategoryID: 42, Name: "New Category"} },
+ { requestUri: "Categories(1)", method: "PUT", data: { CategoryID: 1, Name: "Updated Category"} },
+ { requestUri: "Foods", method: "GET" }
+ ]
+ }
+ ];
+
+ OData.request({ requestUri: batchUri, method: "POST", data: { __batchRequests: batchRequests} },
+ function (data, response) {
+ var batchResponses = data.__batchResponses;
+ var error = batchResponses[3].__changeResponses[0];
+ djstest.assert(error.response.body.indexOf("An error occurred while processing this request.") > -1, "Response contains expected message");
+ // Verify that the responses prior to the error are the expected ones.
+ batchRequests.splice(3, 1);
+ batchResponses.splice(3, 1);
+ verifyBatchResponses(batchRequests, ["entry", null], service, batchResponses, function () { djstest.done(); });
+ }, unexpectedErrorHandler, OData.batchHandler);
+ }, "Retrieve inside changeset");
+})(this);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/48761e07/JSLib/tests/odata-batch-tests.js
----------------------------------------------------------------------
diff --git a/JSLib/tests/odata-batch-tests.js b/JSLib/tests/odata-batch-tests.js
new file mode 100644
index 0000000..9aeb033
--- /dev/null
+++ b/JSLib/tests/odata-batch-tests.js
@@ -0,0 +1,551 @@
+/// <reference path="../src/odata-net.js" />
+/// <reference path="../src/odata.js" />
+/// <reference path="common/djstest.js" />
+/// <reference path="common/mockHttpClient.js" />
+
+// odata-batch-tests.js
+
+(function (window, undefined) {
+ // DATAJS INTERNAL START
+ var defaultAcceptString = "application/json;q=0.9, application/atomsvc+xml;q=0.8, */*;q=0.1";
+
+ var testPayload = {
+ CategoryID : 42,
+ Name: "New Category",
+ ID : "odata",
+ version: "4.0"
+ };
+
+ // to do: test Atom payload
+ // var atomPayload = OData.atomSerializer(OData.atomHandler, testPayload, { "OData-Version": "4.0" });
+ var jsonPayload = OData.jsonSerializer(OData.jsonHandler, testPayload, { "OData-Version": "4.0" });
+
+ djstest.addTest(function writeRequestTest() {
+ var request = {
+ headers: { "Content-Type": "plain/text; charset=utf-8", Accept: "*/*", "OData-Version": "2.0" },
+ requestUri: "http://temp.org",
+ method: "GET",
+ body: "test request"
+ };
+ var expected = "GET http://temp.org HTTP/1.1\r\n" +
+ "Content-Type: plain/text; charset=utf-8\r\n" +
+ "Accept: */*\r\n" +
+ "OData-Version: 2.0\r\n" +
+ "\r\n" +
+ "test request";
+
+ var actual = OData.writeRequest(request);
+ djstest.assertAreEqual(actual, expected, "WriteRequest serializes a request properly");
+ djstest.done();
+ });
+
+ djstest.addTest(function serializeSimpleBatchTest() {
+
+ var request = {
+ requestUri: "http://temp.org",
+ method: "POST",
+ data: { __batchRequests: [
+ { requestUri: "http://feed(1)", headers: {} },
+ { requestUri: "http://feed(2)", headers: { "Accept": "application/json;odata.metadata=minimal" }, method: "GET" }
+ ]
+ }
+ };
+
+ var template = "\r\n--<batchBoundary>\r\n" +
+ "Content-Type: application/http\r\n" +
+ "Content-Transfer-Encoding: binary\r\n" +
+ "\r\n" +
+ "GET http://feed(1) HTTP/1.1\r\n" +
+ "Accept: " + defaultAcceptString + "\r\n" +
+ "OData-MaxVersion: 4.0\r\n" +
+ "\r\n" +
+ "\r\n--<batchBoundary>\r\n" +
+ "Content-Type: application/http\r\n" +
+ "Content-Transfer-Encoding: binary\r\n" +
+ "\r\n" +
+ "GET http://feed(2) HTTP/1.1\r\n" +
+ "Accept: application/json;odata.metadata=minimal\r\n" +
+ "OData-MaxVersion: 4.0\r\n" +
+ "\r\n" +
+ "\r\n--<batchBoundary>--\r\n";
+
+ MockHttpClient.clear().addRequestVerifier(request.requestUri, function (request) {
+ var cType = OData.contentType(request.headers["Content-Type"]);
+ var boundary = cType.properties["boundary"];
+ var expected = template.replace(/<batchBoundary>/g, boundary);
+
+ djstest.assert(boundary, "Request content type has its boundary set");
+ djstest.assertAreEqual(request.body, expected, "Request body is serialized properly");
+ djstest.done();
+ });
+
+ OData.request(request, null, null, OData.batchHandler, MockHttpClient);
+ });
+
+ djstest.addTest(function serializeComplexBatchTest() {
+
+ var request = {
+ requestUri: "http://temp.org",
+ method: "POST",
+ data: { __batchRequests: [
+ { requestUri: "http://feed(1)", headers: {} },
+ { requestUri: "http://feed(2)", headers: { "Accept": "application/json;odata.metadata=minimal" }, method: "GET" },
+ { __changeRequests: [
+ { requestUri: "http://feed(1)", headers: {}, method: "POST", data: testPayload }
+ // to do: test atom payload
+// { requestUri: "http://feed(2)", headers: { "Content-Type": "application/atom+xml", "OData-Version": "4.0" }, method: "PUT", data: testPayload }//
+ ]
+ },
+ { requestUri: "http://feed(1)", headers: {} }
+ ]
+ }
+ };
+
+ //
+ var template = "\r\n--<batchBoundary>\r\n" +
+ "Content-Type: application/http\r\n" +
+ "Content-Transfer-Encoding: binary\r\n" +
+ "\r\n" +
+ "GET http://feed(1) HTTP/1.1\r\n" +
+ "Accept: " + defaultAcceptString + "\r\n" +
+ "OData-MaxVersion: 4.0\r\n" +
+ "\r\n" +
+ "\r\n--<batchBoundary>\r\n" +
+ "Content-Type: application/http\r\n" +
+ "Content-Transfer-Encoding: binary\r\n" +
+ "\r\n" +
+ "GET http://feed(2) HTTP/1.1\r\n" +
+ "Accept: application/json;odata.metadata=minimal\r\n" +
+ "OData-MaxVersion: 4.0\r\n" +
+ "\r\n" +
+ "\r\n--<batchBoundary>\r\n" +
+ "Content-Type: multipart/mixed; boundary=<changesetBoundary>\r\n" +
+ "\r\n--<changesetBoundary>\r\n" +
+ "Content-Type: application/http\r\n" +
+ "Content-Transfer-Encoding: binary\r\n" +
+ "\r\n" +
+ "POST http://feed(1) HTTP/1.1\r\n" +
+ "Accept: " + defaultAcceptString + "\r\n" +
+ "OData-Version: 4.0\r\n" +
+ "Content-Type: application/json\r\n" +
+ "OData-MaxVersion: 4.0\r\n" +
+ "\r\n" +
+ jsonPayload +
+ "\r\n--<changesetBoundary>--\r\n" +
+ "\r\n--<batchBoundary>\r\n" +
+ "Content-Type: application/http\r\n" +
+ "Content-Transfer-Encoding: binary\r\n" +
+ "\r\n" +
+ "GET http://feed(1) HTTP/1.1\r\n" +
+ "Accept: " + defaultAcceptString + "\r\n" +
+ "OData-MaxVersion: 4.0\r\n" +
+ "\r\n" +
+ "\r\n--<batchBoundary>--\r\n";
+
+ MockHttpClient.clear().addRequestVerifier(request.requestUri, function (request) {
+ // Get the boundaries from the request.
+ var start = request.body.indexOf("multipart/mixed");
+ var end = request.body.indexOf("\r\n", start);
+
+ var csetBoundary = OData.contentType(request.body.substring(start, end)).properties["boundary"];
+ var batchBoundary = OData.contentType(request.headers["Content-Type"]).properties["boundary"];
+
+ var expected = template.replace(/<batchBoundary>/g, batchBoundary);
+ expected = expected.replace(/<changesetBoundary>/g, csetBoundary);
+
+ djstest.assert(batchBoundary, "Request content type has its boundary set");
+ djstest.assert(csetBoundary, "Changeset content type has its boundary set");
+ djstest.assertAreEqual(request.body, expected, "Request body is serialized properly");
+ djstest.done();
+ });
+
+ OData.request(request, null, null, OData.batchHandler, MockHttpClient);
+ });
+
+ djstest.addTest(function serializeChangeSetTest() {
+ var request = {
+ requestUri: "http://temp.org",
+ method: "POST",
+ data: {
+ __batchRequests: [
+ { __changeRequests: [
+ { requestUri: "http://feed(1)", headers: {}, method: "POST", data: testPayload }
+// { requestUri: "http://feed(2)", headers: { "Content-Type": "application/atom+xml", "OData-Version": "4.0" }, method: "PUT", data: testPayload }
+ ]
+ }
+ ]
+ }
+ };
+
+ // To do: test atom payload
+ var template = "\r\n--<batchBoundary>\r\n" +
+ "Content-Type: multipart/mixed; boundary=<changesetBoundary>\r\n" +
+ "\r\n--<changesetBoundary>\r\n" +
+ "Content-Type: application/http\r\n" +
+ "Content-Transfer-Encoding: binary\r\n" +
+ "\r\n" +
+ "POST http://feed(1) HTTP/1.1\r\n" +
+ "Accept: " + defaultAcceptString + "\r\n" +
+ "OData-Version: 4.0\r\n" +
+ "Content-Type: application/json\r\n" +
+ "OData-MaxVersion: 4.0\r\n" +
+ "\r\n" +
+ jsonPayload +
+ "\r\n--<changesetBoundary>--\r\n" +
+ "\r\n--<batchBoundary>--\r\n";
+
+ MockHttpClient.clear().addRequestVerifier(request.requestUri, function (request) {
+ // Get the boundaries from the request.
+ var start = request.body.indexOf("multipart/mixed");
+ var end = request.body.indexOf("\r\n", start);
+
+ var csetBoundary = OData.contentType(request.body.substring(start, end)).properties["boundary"];
+ var batchBoundary = OData.contentType(request.headers["Content-Type"]).properties["boundary"];
+
+ var expected = template.replace(/<batchBoundary>/g, batchBoundary);
+ expected = expected.replace(/<changesetBoundary>/g, csetBoundary);
+
+ djstest.assert(batchBoundary, "Request content type has its boundary set");
+ djstest.assert(csetBoundary, "Changeset content type has its boundary set");
+ djstest.assertAreEqual(request.body, expected, "Request body is serialized properly");
+ djstest.done();
+ });
+
+ OData.request(request, null, null, OData.batchHandler, MockHttpClient);
+ });
+
+ djstest.addTest(function serializeNestedChangeSetsTest() {
+ var request = {
+ requestUri: "http://temp.org",
+ method: "POST",
+ data: testPayload
+ };
+
+ djstest.expectException(function () {
+ OData.request(request, null, null, OData.batchHandler);
+ });
+
+ djstest.done();
+ });
+
+ djstest.addTest(function serializeNonBatchObjectTest() {
+ var request = {
+ requestUri: "http://temp.org",
+ method: "POST",
+ data: {
+ __batchRequests: [
+ { __changeRequests: [
+ { __changeRequests: [
+ { requestUri: "http://feed(2)", headers: { "Content-Type": "application/json", "OData-Version": "4.0" }, method: "PUT", data: testPayload }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ };
+
+ djstest.expectException(function () {
+ OData.request(request, null, null, OData.batchHandler);
+ });
+
+ djstest.done();
+ });
+
+ djstest.addTest(function readSimpleBatchTest() {
+ var response = {
+ statusCode: 202,
+ statusText: "Accepted",
+ headers: {
+ "Content-Type": "multipart/mixed; boundary=batchresponse_b61ab173-39c7-45ea-ade4-941efae85ab9"
+ },
+ body: "--batchresponse_b61ab173-39c7-45ea-ade4-941efae85ab9\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 201 Created\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+Location: http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(42)\r\n\
+\r\n\
+{\"@odata.context\":\"http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":42,\"Name\":\"New Category\"}\r\n\
+--batchresponse_b61ab173-39c7-45ea-ade4-941efae85ab9\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 201 Created\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+Location: http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(43)\r\n\
+\r\n\
+{\"@odata.context\":\"http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":43,\"Name\":\"New Category\"}\r\n\
+--batchresponse_b61ab173-39c7-45ea-ade4-941efae85ab9--\r\n\
+"
+ };
+
+ MockHttpClient.clear().addResponse("http://testuri.org", response);
+ OData.read("http://testuri.org", function (data, response) {
+ djstest.assert(data.__batchResponses, "data.__batchResponses is defined");
+ djstest.assertAreEqual(data.__batchResponses[0].headers["Location"], "http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(42)", "part 1 of the response was read");
+ djstest.assertAreEqual(data.__batchResponses[1].headers["Location"], "http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(43)", "part 2 of the response was read");
+ djstest.assertAreEqual(data.__batchResponses[0].data["CategoryID"], 42, "part 1 data of the response was read");
+ djstest.assertAreEqual(data.__batchResponses[1].data["CategoryID"], 43, "part 2 data of the response was read");
+ djstest.done();
+ }, null, OData.batchHandler, MockHttpClient);
+ });
+
+ djstest.addTest(function readBatchWithChangesetTest() {
+ var response = {
+ statusCode: 202,
+ statusText: "Accepted",
+ headers: {
+ "Content-Type": "multipart/mixed; boundary=batchresponse_fb681875-73dc-4e62-9898-a0af89021341"
+ },
+ body: "--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
+Content-Type: multipart/mixed; boundary=changesetresponse_905a1494-fd76-4846-93f9-a3431f0bf5a2\r\n\
+\r\n\
+--changesetresponse_905a1494-fd76-4846-93f9-a3431f0bf5a2\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 201 OK\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+Location: http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(42)\r\n\
+\r\n\
+{\"@odata.context\":\"http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":42,\"Name\":\"New Category\"}\r\n\
+--changesetresponse_905a1494-fd76-4846-93f9-a3431f0bf5a2\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 204 No Content\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+OData-Version: 4.0;\r\n\
+\r\n\
+\r\n\
+--changesetresponse_905a1494-fd76-4846-93f9-a3431f0bf5a2--\r\n\
+--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 201 Created\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+Location: http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(41)\r\n\
+\r\n\
+{\"@odata.context\":\"http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":41,\"Name\":\"New Category\"}\r\n\
+--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
+Content-Type: multipart/mixed; boundary=changesetresponse_92cc2ae8-a5f2-47fc-aaa3-1ff9e7453b07\r\n\
+\r\n\
+--changesetresponse_92cc2ae8-a5f2-47fc-aaa3-1ff9e7453b07\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 201 OK\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+Location: http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(43)\r\n\
+\r\n\
+{\"@odata.context\":\"http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata#Categories/$entity\",\"Icon@odata.mediaContentType\":\"image/gif\",\"CategoryID\":43,\"Name\":\"New Category\"}\r\n\
+--changesetresponse_92cc2ae8-a5f2-47fc-aaa3-1ff9e7453b07\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 204 No Content\r\n\
+X-Content-Type-Options: nosniff\r\n\
+Cache-Control: no-cache\r\n\
+OData-Version: 4.0;\r\n\
+\r\n\
+\r\n\
+--changesetresponse_92cc2ae8-a5f2-47fc-aaa3-1ff9e7453b07--\r\n\
+--batchresponse_fb681875-73dc-4e62-9898-a0af89021341--\r\n\
+"
+ };
+
+ MockHttpClient.clear().addResponse("http://testuri.org", response);
+ OData.read("http://testuri.org", function (data, response) {
+
+ var batchResponses = data.__batchResponses;
+ djstest.assert(batchResponses, "data contains the batch responses");
+
+ var changesetResponses = batchResponses[0].__changeResponses;
+ djstest.assert(changesetResponses, "batch response 1 contains the change set responses");
+ var changesetResponses3 = batchResponses[2].__changeResponses;
+ djstest.assert(changesetResponses3, "batch response 3 contains the change set responses");
+
+ djstest.assertAreEqual(batchResponses[0].data, undefined, "No data defined for batch response 1");
+ djstest.assertAreEqual(changesetResponses[0].headers["Location"], "http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(42)", "part 1 of the changeset response of the response 1 was read");
+ djstest.assertAreEqual(changesetResponses[0].data["CategoryID"], 42, "part 1 data of the changeset response of the response 1 was read");
+ djstest.assertAreEqual(changesetResponses[1].data, undefined, "No data defined for no content only response in part 2 of the changeset response of the response 1");
+
+ djstest.assertAreEqual(batchResponses[1].headers["Location"], "http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(41)", "response 2 was read");
+ djstest.assertAreEqual(batchResponses[1].data["CategoryID"], 41, "response 2 data was read");
+
+ djstest.assertAreEqual(batchResponses[2].data, undefined, "No data defined for");
+ djstest.assertAreEqual(changesetResponses3[0].headers["Location"], "http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(43)", "part 1 of the changeset response of the response 3 was read");
+ djstest.assertAreEqual(changesetResponses3[0].data["CategoryID"], 43, "part 1 data of the changeset response of the response 3 was read");
+ djstest.assertAreEqual(changesetResponses3[1].data, undefined, "No data defined for no content only response in part 2 of the changeset response of the response 3");
+ djstest.done();
+ }, null, OData.batchHandler, MockHttpClient);
+ });
+
+ djstest.addTest(function readBatchWithErrorPartTest() {
+ var response = {
+ statusCode: 202,
+ statusText: "Accepted",
+ headers: {
+ "Content-Type": "multipart/mixed; boundary=batchresponse_9402a3ab-260f-4fa4-af01-0b30db397c8d"
+ },
+ body: "--batchresponse_9402a3ab-260f-4fa4-af01-0b30db397c8d\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 200 OK\r\n\
+Cache-Control: no-cache\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;charset=utf-8\r\n\
+Location: http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(1)\r\n\
+\r\n\
+{\"error\":{\"code\":\"\",\"message\":\"Resource not found for the segment 'Categories(1)'.\"}}\r\n\
+--batchresponse_9402a3ab-260f-4fa4-af01-0b30db397c8d\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 400 Bad Request\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json\r\n\
+{\"error\":{\"code\":\"\",\"message\":\"Error processing request stream.'.\"}}\r\n\
+--batchresponse_9402a3ab-260f-4fa4-af01-0b30db397c8d--\r\n\
+"
+ };
+
+ MockHttpClient.clear().addResponse("http://testuri.org", response);
+ OData.read("http://testuri.org", function (data, response) {
+ var batchResponses = data.__batchResponses;
+ djstest.assert(batchResponses, "data.__batchResponses is defined");
+ djstest.assertAreEqual(batchResponses.length, 2, "batch contains two responses");
+ djstest.assertAreEqual(batchResponses[0].headers["Location"], "http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(1)", "part 1 of the response was read");
+ djstest.assert(batchResponses[1].response, "part 2 of the response was read");
+ djstest.done();
+ }, null, OData.batchHandler, MockHttpClient);
+ });
+
+
+ djstest.addTest(function readMalformedMultipartResponseThrowsException() {
+ var response = {
+ statusCode: 202,
+ statusText: "Accepted",
+ headers: {
+ "Content-Type": "multipart/mixed; boundary=batchresponse_fb681875-73dc-4e62-9898-a0af89021341"
+ },
+ body: "--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 200 OK\r\n\
+Cache-Control: no-cache\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;charset=utf-8\r\n\
+Location: http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(1)\r\n\
+\r\n\
+{\"error\":{\"code\":\"\",\"message\":\"Resource not found for the segment 'Categories(1)'.\"}}\r\n\
+--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n\
+Content-Type: multipart/mixed; boundary=changesetresponse_2f9c6ba7-b330-4e7c-bf2a-db521996c243\r\n\
+\r\n\
+--changesetresponse_2f9c6ba7-b330-4e7c-bf2a-db521996c243\r\n\
+Content-Type: application/http\r\n\
+Content-Transfer-Encoding: binary\r\n\
+\r\n\
+HTTP/1.1 404 Not Found\r\n\
+X-Content-Type-Options: nosniff\r\n\
+OData-Version: 4.0;\r\n\
+Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8\r\n\
+\r\n\
+{\"error\":{\"code\":\"\",\"message\":\GET operation cannot be specified in a change set. Only PUT, POST and DELETE operations can be specified in a change set..'.\"}}\r\n\
+--changesetresponse_2f9c6ba7-b330-4e7c-bf2a-db521996c243--\r\n\
+--batchresponse_fb681875-73dc-4e62-9898-a0af89021341--\r\n\
+"
+ };
+
+ MockHttpClient.clear().addResponse("http://testuri.org", response);
+ OData.read("http://testuri.org", function (data, response) {
+ var batchResponses = data.__batchResponses;
+ djstest.assert(batchResponses, "data.__batchResponses is defined");
+ djstest.assertAreEqual(batchResponses.length, 2, "batch contains two responses");
+ djstest.assertAreEqual(batchResponses[0].headers["Location"], "http://localhost:46541/tests/endpoints/FoodStoreDataServiceV4.svc/Categories(1)", "part 1 of the response was read");
+
+ var error = batchResponses[1].__changeResponses[0];
+ djstest.assert(error.response.body.indexOf("GET operation cannot be specified in a change set") > -1, "Response contains expected message");
+ djstest.done();
+ }, null, OData.batchHandler, MockHttpClient);
+ djstest.done();
+ });
+
+ djstest.addTest(function batchRequestContextIsPushedToThePartsHandlersTest() {
+ var testHandler = {
+ read: function (response, context) {
+ djstest.assert(context.recognizeDates, "Recognize dates was set properly on the part request context");
+ },
+ write: function (request, context) {
+ djstest.assert(context.recognizeDates, "Recognize dates was set properly on the part request context");
+ }
+ };
+
+ var batch = {
+ headers: {},
+ __batchRequests: [
+ { requestUri: "http://someUri" },
+ { __changeRequests: [
+ { requestUri: "http://someUri", method: "POST", data: { p1: 500} }
+ ]
+ }
+ ]
+ };
+
+ var request = { requestUri: "http://someuri", headers: {}, data: batch };
+ var response = {
+ statusCode: 202,
+ statusText: "Accepted",
+ headers: {
+ "Content-Type": "multipart/mixed; boundary=batchresponse_fb681875-73dc-4e62-9898-a0af89021341"
+ },
+ body: '--batchresponse_fb681875-73dc-4e62-9898-a0af89021341\r\n' +
+ 'Content-Type: application/http\r\n' +
+ 'Content-Transfer-Encoding: binary\r\n' +
+ '\r\n' +
+ 'HTTP/1.1 200 OK\r\n' +
+ 'Cache-Control: no-cache\r\n' +
+ 'OData-Version: 1.0;\r\n' +
+ 'Content-Type: application/json\r\n' +
+ '\r\n' +
+ '{ "p1": 500 }\r\n' +
+ '\r\n' +
+ '--batchresponse_fb681875-73dc-4e62-9898-a0af89021341--\r\n'
+ };
+
+ var oldPartHandler = OData.batchHandler.partHandler;
+
+ OData.batchHandler.partHandler = testHandler;
+
+ OData.batchHandler.write(request, { recognizeDates: true });
+ OData.batchHandler.read(response, { recognizeDates: true });
+
+ OData.batchHandler.partHandler = oldPartHandler;
+
+ djstest.done();
+ });
+
+
+ // DATAJS INTERNAL END
+})(this);
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/48761e07/JSLib/tests/odata-cache-filter-functional-tests.html
----------------------------------------------------------------------
diff --git a/JSLib/tests/odata-cache-filter-functional-tests.html b/JSLib/tests/odata-cache-filter-functional-tests.html
new file mode 100644
index 0000000..9c5da7e
--- /dev/null
+++ b/JSLib/tests/odata-cache-filter-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>datajs.cache filter functional 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/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-filter-functional-tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">datajs.cache filter functional tests</h1>
+ <h2 id="qunit-banner"></h2>
+ <h2 id="qunit-userAgent"></h2>
+ <ol id="qunit-tests"></ol>
+</body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/48761e07/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..b11cad3
--- /dev/null
+++ b/JSLib/tests/odata-cache-filter-functional-tests.js
@@ -0,0 +1,416 @@
+/// <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/json;q=0.9, application/atomsvc+xml;q=0.8, */*;q=0.1";
+ var feeds = [
+ { feed: "./endpoints/FoodStoreDataServiceV4.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 (count < 0) {
+ count = itemsInCollection;
+ }
+
+ if (index < 0) {
+ index = 0;
+ }
+
+ window.ODataReadOracle.readJsonAcrossServerPages(feed, function (expectData) {
+ if (backwards) {
+ cache.filterBack(index, count, predicate).then(function (actualResults) {
+ var expectedResults = CacheOracle.getExpectedFilterResults(expectData, 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 = 0;
+ if (expectedResults.value.length != 0) {
+ firstIndex = (expectedResults.value.length < count) ? 0 : expectedResults.value[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(expectData, index, count, predicate, backwards)
+ djstest.assertAreEqualDeep(actualResults, expectedResults, "results for " + "filterForward requests");
+
+ if (session && cacheOracle) {
+ if (expectedResults.value.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.value.length < count) ? itemsInCollection : expectedResults.value[expectedResults.value.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[0].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[0].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[0].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[0].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[0].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);