You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ko...@apache.org on 2015/02/23 11:11:09 UTC
[02/41] olingo-odata4-js git commit: [OLINGO-541] Move the odatajs
branch one directory up
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/503b4417/tests/odata-tests.js
----------------------------------------------------------------------
diff --git a/tests/odata-tests.js b/tests/odata-tests.js
new file mode 100644
index 0000000..0e6e951
--- /dev/null
+++ b/tests/odata-tests.js
@@ -0,0 +1,322 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// odata-tests.js
+(function (window, undefined) {
+ var northwindService = "http://services.odata.org/Northwind/Northwind.svc/";
+ var localFeed = "./endpoints/FoodStoreDataService.svc/Foods";
+ var northwindFeed = northwindService + "Suppliers";
+
+ var countIFrames = function () {
+ /** Count the number of IFRAMES in the page
+ * @returns {Integer} The number of IFRAMES
+ */
+ return document.getElementsByTagName("IFRAME").length;
+ }
+
+ module("Unit");
+
+ var originalEnableJsonpCallback = OData.defaultHttpClient.enableJsonpCallback;
+
+ var restoreJsonpCallback = function () {
+ /** Restores OData.defaultHttpClient.enableJsonpCallback to the library default.
+ */
+ OData.defaultHttpClient.enableJsonpCallback = originalEnableJsonpCallback;
+ };
+
+ djstest.addTest(function checkApiTest() {
+ var internals = window.odatajs.oData.canUseJSONP !== undefined;
+ if (internals) {
+ // Don't even bother - there is a very long list for inter-module communication.
+ // {targetName: "OData", names: "..." }
+ djstest.pass("Do not test public api's when internals are visible");
+ } else {
+ var apis = [
+ { targetName: "datajs", names: "createDataCache,createStore,defaultStoreMechanism" },
+ { targetName: "OData", names: "batchHandler,defaultError,defaultHandler,defaultHttpClient,defaultMetadata,defaultSuccess,jsonHandler,metadataHandler,read,request,textHandler,xmlHandler,parseMetadata" }
+ ];
+
+ for (var i = 0; i < apis.length; i++) {
+ var target = window[apis[i].targetName];
+
+ var actuals = [];
+ for (var actual in target) {
+ actuals.push(actual);
+ }
+
+ actuals.sort();
+
+ var names = apis[i].names.split(",");
+ names.sort();
+
+ djstest.assertAreEqual(actuals.join(), names.join(), "actual names for " + apis[i].targetName);
+ }
+ }
+
+ djstest.done();
+ });
+
+ djstest.addTest(function simpleLocalReadTest() {
+ odatajs.oData.read(localFeed, function (data, request) {
+ djstest.assert(data !== null, "data !== null");
+ djstest.assert(request !== null, "request !== null");
+ djstest.done();
+ });
+ });
+
+ djstest.addTest(function simpleLocalReadWithRequestTest() {
+ odatajs.oData.read({ requestUri: localFeed, headers: { Accept: "application/json"} }, function (data, response) {
+ djstest.assert(data !== null, "data !== null");
+ djstest.assert(response !== null, "response !== null");
+ djstest.assertAreEqual(data, response.data, "data === response.data");
+
+ // Typically application/json;charset=utf-8, but browser may change the request charset (and thus response).
+ var contentType = response.headers["Content-Type"];
+ contentType = contentType.split(';')[0];
+ djstest.assertAreEqual(contentType, "application/json", 'contentType === "application/json"');
+ djstest.done();
+ });
+ });
+
+ djstest.addTest(function simpleReadTest() {
+ var oldEnableJsonpCallback = OData.defaultHttpClient.enableJsonpCallback;
+ OData.defaultHttpClient.enableJsonpCallback = true;
+
+ var iframesBefore = countIFrames();
+ odatajs.oData.read(northwindService + "Regions", function (data, request) {
+ djstest.assert(data !== null, "data !== null");
+ djstest.assert(request !== null, "request !== null");
+
+ // IFRAME recycling does not work in Opera because as soon as the IFRAME is added to the body, all variables
+ // go out of scope
+ if (!window.opera) {
+ djstest.assertAreEqual(countIFrames() - iframesBefore, 0, "extra IFRAMEs (baseline: " + iframesBefore + ")");
+ }
+
+ OData.defaultHttpClient.enableJsonpCallback = oldEnableJsonpCallback;
+ djstest.done();
+ });
+ });
+
+ djstest.addTest(function simpleReadWithParamsTest() {
+ OData.defaultHttpClient.enableJsonpCallback = true;
+ odatajs.oData.read(northwindFeed + "?$top=3", function (data, request) {
+ djstest.assert(data !== null, "data !== null");
+ djstest.assert(request !== null, "request !== null");
+ restoreJsonpCallback();
+ djstest.done();
+ }, djstest.failAndDoneCallback("Unable to read from " + northwindFeed, restoreJsonpCallback));
+ });
+
+ djstest.addTest(function simpleReadWithNoParamsTest() {
+ OData.defaultHttpClient.enableJsonpCallback = true;
+ odatajs.oData.read(northwindFeed + "?", function (data, request) {
+ djstest.assert(data !== null, "data !== null");
+ djstest.assert(request !== null, "request !== null");
+ restoreJsonpCallback();
+ djstest.done();
+ }, djstest.failAndDoneCallback("Unable to read from " + northwindFeed, restoreJsonpCallback));
+ });
+
+ djstest.addTest(function jsonpTimeoutTest() {
+ // Verifies that JSONP will timeout, and that the
+ // enableJsonpCallback flag can be set on the request itself.
+ var iframesBefore = countIFrames();
+ odatajs.oData.request({
+ requestUri: northwindFeed + "?$fail=true",
+ timeoutMS: 100,
+ enableJsonpCallback: true
+ }, function (data, request) {
+ djstest.fail("expected an error callback");
+ djstest.done();
+ }, function (err) {
+ djstest.assert(err.message.indexOf("timeout") !== 1, "err.message[" + err.message + "].indexOf('timeout') !== 1");
+ djstest.assertAreEqual(countIFrames() - iframesBefore, 0, "extra script tags (baseline: " + iframesBefore + ")");
+ djstest.done();
+ });
+ });
+
+ djstest.addTest(function requestDefaultsTest() {
+ // Save current defaults.
+ var oldError = OData.defaultError;
+ var oldSuccess = OData.defaultSuccess;
+ var oldDefaultHandler = OData.defaultHandler;
+ var oldHttpClient = OData.defaultHttpClient;
+
+ OData.defaultSuccess = function (data, response) {
+ djstest.assertAreEqual(response.statusCode, 299, "success method reached when expected");
+ };
+
+ OData.defaultError = function (error) {
+ var response = error.response;
+ djstest.assertAreEqual(response.statusCode, 500, "error method reached when expected");
+ };
+
+ OData.defaultHandler = {
+ read: function (response) {
+ djstest.assertAreEqual(response.statusCode, 299, "default handler read method reached when expected");
+ },
+ accept: "test accept string"
+ };
+
+ OData.defaultHttpClient = MockHttpClient.clear();
+
+ var testUris = [
+ "requestDefaultsTest/request",
+ "requestDefaultsTest/request1",
+ "requestDefaultsTest/error"
+ ];
+
+ MockHttpClient.addRequestVerifier(testUris[0], function (request) {
+ djstest.assertAreEqual(request.method, "GET", "request.method is GET");
+ djstest.assert(request.headers, "request.headers is defined and not null");
+ djstest.assertAreEqual(request.headers.Accept, "test accept string");
+ });
+
+ MockHttpClient.addResponse(testUris[1], { statusCode: 299, body: "test response" });
+ MockHttpClient.addResponse(testUris[2], { statusCode: 500, body: "error response" });
+
+ try {
+ var i, len;
+ for (i = 0, len = testUris.length; i < len; i++) {
+ odatajs.oData.request({ requestUri: testUris[i] });
+ }
+ }
+ finally {
+ // Restore defaults.
+ OData.defaultError = oldError;
+ OData.defaultSuccess = oldSuccess;
+ OData.defaultHandler = oldDefaultHandler;
+ OData.defaultHttpClient = oldHttpClient;
+ }
+
+ djstest.assertsExpected(6);
+ djstest.done();
+ });
+
+ djstest.addTest(function requestUpdateTest() {
+ // Save current defaults.
+ var testHandler = {
+ read: function (response) {
+ response.data = response.body;
+ },
+ write: function (request) {
+ djstest.assertAreEqual(request.method, "POST", "handler write method, request has the correct method");
+ }
+ };
+
+ var testSuccess = function (data, response) {
+ djstest.assertAreEqual(data, "test response", "success callback has the correct data");
+ djstest.assertAreEqual(response.status, 200, "success method reached when expected");
+ };
+
+ var testError = function (error) {
+ var response = error.response;
+ djstest.assertAreEqual(response.status, 500, "error method reached when expected");
+ };
+
+ MockHttpClient.addResponse("requestUpdateTest", { status: 200, body: "test response" });
+ MockHttpClient.addResponse("requestUpdateTest", { status: 500, body: "error response" });
+
+ odatajs.oData.request({ requestUri: "requestUpdateTest", method: "POST" }, testSuccess, testError, testHandler, MockHttpClient);
+
+ djstest.done();
+ });
+
+ djstest.addTest(function parseMetadataTest() {
+ var metadata = '<?xml version="1.0" encoding="utf-8"?>' +
+ '<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">' +
+ '<edmx:DataServices m:DataServiceVersion="4.0" m:MaxDataServiceVersion="4.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">' +
+ '<Schema Namespace="ODataDemo" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">' +
+ '<EntityType Name="Product">' +
+ '<Key><PropertyRef Name="ID" /></Key>' +
+ '<Property Name="ID" Type="Edm.Int32" Nullable="false" />' +
+ '<Property Name="Name" Type="Edm.String" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="false" />' +
+ '<Property Name="Description" Type="Edm.String" m:FC_TargetPath="SyndicationSummary" m:FC_ContentKind="text" m:FC_KeepInContent="false" />' +
+ '<Property Name="ReleaseDate" Type="Edm.DateTime" Nullable="false" />' +
+ '<Property Name="DiscontinuedDate" Type="Edm.DateTime" />' +
+ '<Property Name="Rating" Type="Edm.Int32" Nullable="false" />' +
+ '<Property Name="Price" Type="Edm.Decimal" Nullable="false" />' +
+ '<NavigationProperty Name="Category" Relationship="ODataDemo.Product_Category_Category_Products" ToRole="Category_Products" FromRole="Product_Category" />' +
+ '</EntityType>' +
+ '<EntityType Name="Category">' +
+ '<Key>' +
+ '<PropertyRef Name="ID" />' +
+ '</Key>' +
+ '<Property Name="ID" Type="Edm.Int32" Nullable="false" />' +
+ '<Property Name="Name" Type="Edm.String" m:FC_TargetPath="SyndicationTitle" m:FC_ContentKind="text" m:FC_KeepInContent="true" />' +
+ '<NavigationProperty Name="Products" Relationship="ODataDemo.Product_Category_Category_Products" ToRole="Product_Category" FromRole="Category_Products" />' +
+ '</EntityType>' +
+ '<Association Name="Product_Category_Category_Products"><End Type="ODataDemo.Category" Role="Category_Products" Multiplicity="0..1" />' +
+ '<End Type="ODataDemo.Product" Role="Product_Category" Multiplicity="*" />' +
+ '</Association>' +
+ '<EntityContainer Name="DemoService" m:IsDefaultEntityContainer="true">' +
+ '<EntitySet Name="Products" EntityType="ODataDemo.Product" />' +
+ '<EntitySet Name="Categories" EntityType="ODataDemo.Category" />' +
+ '<FunctionImport Name="Discount" IsBindable="true" m:IsAlwaysBindable="true">' +
+ '<Parameter Name="product" Type="ODataDemo.Product" />' +
+ '<Parameter Name="discountPercentage" Type="Edm.Int32" Nullable="false" />' +
+ '</FunctionImport>' +
+ '<AssociationSet Name="Products_Category_Categories" Association="ODataDemo.Product_Category_Category_Products">' +
+ '<End Role="Product_Category" EntitySet="Products" />' +
+ '<End Role="Category_Products" EntitySet="Categories" />' +
+ '</AssociationSet>' +
+ '</EntityContainer>' +
+ '</Schema></edmx:DataServices></edmx:Edmx>';
+
+ var parsedMetadata = OData.parseMetadata(metadata);
+ var expected =
+ {
+ "version": "1.0",
+ "dataServices":
+ {
+ "maxDataServiceVersion": "4.0",
+ "dataServiceVersion": "4.0",
+ "schema": [
+ {
+ "namespace": "ODataDemo",
+ "entityType": [
+ {
+ "name": "Product",
+ "key": { "propertyRef": [{ "name": "ID"}] },
+ "property": [
+ { "name": "ID", "nullable": "false", "type": "Edm.Int32" },
+ { "name": "Name", "type": "Edm.String", "FC_KeepInContent": "false", "FC_ContentKind": "text", "FC_TargetPath": "SyndicationTitle" },
+ { "name": "Description", "type": "Edm.String", "FC_KeepInContent": "false", "FC_ContentKind": "text", "FC_TargetPath": "SyndicationSummary" },
+ { "name": "ReleaseDate", "nullable": "false", "type": "Edm.DateTime" }, { "name": "DiscontinuedDate", "type": "Edm.DateTime" },
+ { "name": "Rating", "nullable": "false", "type": "Edm.Int32" }, { "name": "Price", "nullable": "false", "type": "Edm.Decimal"}],
+ "navigationProperty": [
+ { "name": "Category", "fromRole": "Product_Category", "toRole": "Category_Products", "relationship": "ODataDemo.Product_Category_Category_Products" }
+ ]
+ }, {
+ "name": "Category",
+ "key": { "propertyRef": [{ "name": "ID"}] },
+ "property": [{ "name": "ID", "nullable": "false", "type": "Edm.Int32" }, { "name": "Name", "type": "Edm.String", "FC_KeepInContent": "true", "FC_ContentKind": "text", "FC_TargetPath": "SyndicationTitle"}],
+ "navigationProperty": [{ "name": "Products", "fromRole": "Category_Products", "toRole": "Product_Category", "relationship": "ODataDemo.Product_Category_Category_Products"}]
+ }],
+ "association": [{ "name": "Product_Category_Category_Products", "end": [{ "type": "ODataDemo.Category", "multiplicity": "0..1", "role": "Category_Products" }, { "type": "ODataDemo.Product", "multiplicity": "*", "role": "Product_Category"}]}],
+ "entityContainer": [{ "name": "DemoService", "isDefaultEntityContainer": "true", "entitySet": [{ "name": "Products", "entityType": "ODataDemo.Product" }, { "name": "Categories", "entityType": "ODataDemo.Category"}], "functionImport": [{ "name": "Discount", "isAlwaysBindable": "true", "isBindable": "true", "parameter": [{ "name": "product", "type": "ODataDemo.Product" }, { "name": "discountPercentage", "nullable": "false", "type": "Edm.Int32"}]}], "associationSet": [{ "name": "Products_Category_Categories", "association": "ODataDemo.Product_Category_Category_Products", "end": [{ "role": "Product_Category", "entitySet": "Products" }, { "role": "Category_Products", "entitySet": "Categories"}]}]}]
+ }]
+ }
+ };
+ djstest.assertAreEqualDeep(expected, parsedMetadata, "metadata should be parsed to datajs format");
+ djstest.done();
+ });
+
+})(this);
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/503b4417/tests/odata-xml-tests.js
----------------------------------------------------------------------
diff --git a/tests/odata-xml-tests.js b/tests/odata-xml-tests.js
new file mode 100644
index 0000000..465b42b
--- /dev/null
+++ b/tests/odata-xml-tests.js
@@ -0,0 +1,275 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// odata-xml-tests.js
+
+(function (window, undefined) {
+
+ // DATAJS INTERNAL START
+
+ djstest.addTest(function getURIInfoTest() {
+ var tests = [
+ { input: "https://host.com:8080/path1/path2?p1=1&p2=2#fragment", expected: { scheme: "https:", authority: "//host.com:8080", path: "/path1/path2", query: "?p1=1&p2=2", fragment: "#fragment", isAbsolute: true} },
+ { input: "http://host.com:8080/path1/path2?p1=1&p2=2#fragment", expected: { scheme: "http:", authority: "//host.com:8080", path: "/path1/path2", query: "?p1=1&p2=2", fragment: "#fragment", isAbsolute: true} },
+ { input: "https:", expected: { scheme: "https:", isAbsolute: true} },
+ { input: "http:", expected: { scheme: "http:", isAbsolute: true} },
+ { input: "//host.com", expected: { authority: "//host.com", isAbsolute: false} },
+ { input: "path1", expected: { path: "path1", isAbsolute: false} },
+ { input: "?query", expected: { query: "?query", isAbsolute: false} },
+ { input: "#fragment", expected: { fragment: "#fragment", isAbsolute: false} },
+ { input: undefined, expected: { isAbsolute: false} },
+ { input: "", expected: { isAbsolute: false} },
+ { input: null, expected: { isAbsolute: false} }
+ ];
+
+ var i, len;
+ for (i = 0, len = tests.length; i < len; i++) {
+ var actual = odatajs.utils.getURIInfo(tests[i].input);
+ djstest.assertAreEqualDeep(actual, tests[i].expected, "test " + i + "didn't return the expected URI parts");
+ }
+ djstest.done();
+ });
+
+ djstest.addTest(function normalizeURICaseTest() {
+ var tests = [
+ { uri: "hTTp://HOST.com/path1/Path2/PATH3?Query1=x&query2=Y#Fragment", expected: "http://host.com/path1/Path2/PATH3?Query1=x&query2=Y#Fragment" },
+ { uri: "http://fabrikam%20user%3AHisPassWord@www.FaBriKAM.com:5895/Path%3A%201?q1=hi%20%3Ato%20you", expected: "http://fabrikam%20user%3aHisPassWord@www.fabrikam.com:5895/Path%3a%201?q1=hi%20%3ato%20you" },
+ { uri: "/PATH1/PATH2?P1=AbC#fraGment", expected: "/PATH1/PATH2?P1=AbC#fraGment" },
+ { uri: "HttP://" + encodeURIComponent("FTP://www.example.com&story=breaking_news:password@www.HOST.CoM:5678/"), expected: "http://" + encodeURIComponent("FTP://www.example.com&story=breaking_news:password@www.HOST.CoM:5678/").toLowerCase() }
+ ];
+
+ var i, len;
+ for (i = 0, len = tests.length; i < len; i++) {
+ var actual = odatajs.utils.normalizeURICase(tests[i].uri, tests[i].base);
+ djstest.assertAreEqual(actual, tests[i].expected, "test " + i + "didn't return the expected URI");
+ }
+ djstest.done();
+ });
+
+ djstest.addTest(function normalizeURITest() {
+ var tests = [
+ { uri: "http://host.com/path1#fragment", base: "http://base", expected: "http://host.com/path1#fragment" },
+ { uri: "//host.com/path1?p1=0", base: "http://base?p2=1", expected: "http://host.com/path1?p1=0" },
+ { uri: "?p1=0#fragment", base: "http://base/basepath", expected: "http://base/basepath?p1=0#fragment" },
+ { uri: "?p1=0#fragment", base: "http://base/basepath?p2=1", expected: "http://base/basepath?p1=0#fragment" },
+ { uri: "#fragment", base: "http://base/basepath?p2=1", expected: "http://base/basepath?p2=1#fragment" },
+ { uri: "/path1/path2?p1=0", base: "http://base/basePath", expected: "http://base/path1/path2?p1=0" },
+ { uri: "path1/path2?p1=0", base: "http://base/basepath", expected: "http://base/path1/path2?p1=0" },
+ { uri: "path1/path2?p1=0", base: "http://base/basepath/basepath2", expected: "http://base/basepath/path1/path2?p1=0" },
+ { uri: "", base: "http://base/basepath?p1=0#fragment", expected: "http://base/basepath?p1=0" },
+ { uri: "path1/path2?p1=0", base: "", expected: "path1/path2?p1=0" },
+ { uri: "/a/b/c/./../../g", base: "http://base/basepath", expected: "http://base/a/g" },
+ { uri: "a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/basepath/a/g" },
+ { uri: "../a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/a/g" },
+ { uri: "./a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/basepath/a/g" },
+ { uri: "/../a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/a/g" },
+ { uri: "/./a/b/c/././../../g", base: "http://base/basepath/", expected: "http://base/a/g" }
+ ];
+
+ var i, len;
+ for (i = 0, len = tests.length; i < len; i++) {
+ var actual = odatajs.utils.normalizeURI(tests[i].uri, tests[i].base);
+ djstest.assertAreEqual(actual, tests[i].expected, "test " + i + "didn't return the expected normalized URI");
+ }
+ djstest.done();
+ });
+
+ djstest.addTest(function xmlParseTest() {
+ var xml = '<root xmlns:n1="http://namespace1" xml:base="http://base.org" />';
+ var root = odatajs.xml.xmlParse(xml);
+ djstest.assert(root, "xml._parse didn't return a xml dom object");
+ djstest.done();
+ });
+
+ djstest.addTest(function xmlbaseURITest() {
+ var xml = "\
+ <root xmlns:n1=\"http://namespace1\" \r\n\
+ xml:base=\"http://base.org\"> \r\n\
+ <element base=\"this is not a xml base attribute\" /> \r\n\
+ </root>\r\n";
+
+ var doc = odatajs.xml.xmlParse(xml);
+ var root = odatajs.xml.xmlFirstChildElement(doc);
+ var child = odatajs.xml.xmlFirstChildElement(root);
+
+ djstest.assertAreEqual(odatajs.xml.xmlBaseURI(root), "http://base.org", "xml._baseURI didn't return the expected value");
+ djstest.assert(!odatajs.xml.xmlBaseURI(child), "xml._baseURI returned a value when it wasn't expected");
+ djstest.done();
+ });
+
+ djstest.addTest(function xmlAttributeValueTest() {
+ var xml = "\
+ <root xmlns:n1=\"http://namespace1\" \r\n\
+ xml:base=\"http://base.org\"> \r\n\
+ <element attribute=\"value\" n1:nsAttribute=\"nsValue\" /> \r\n\
+ </root> \r\n";
+
+ var doc = odatajs.xml.xmlParse(xml);
+ var root = odatajs.xml.xmlFirstChildElement(doc);
+ var child = odatajs.xml.xmlFirstChildElement(root);
+
+ djstest.assertAreEqual(odatajs.xml.xmlAttributeValue(child, "attribute"), "value", "xml._attribute didn't return the expected value for attribute");
+ djstest.assertAreEqual(odatajs.xml.xmlAttributeValue(child, "nsAttribute", "http://namespace1"), "nsValue", "xml._attribute didn't return the expected value for nsAttribute");
+ djstest.assert(!odatajs.xml.xmlAttributeValue(child, "nsAttribute"), "xml._attribute returned a value for nsAttribute without specifying a namespace");
+
+ djstest.done();
+ });
+
+ djstest.addTest(function xmlLocalNameTest() {
+ var xml = "<root xmlns:n1=\"http://namespace1\" /> \r\n";
+
+ var doc = odatajs.xml.xmlParse(xml);
+ var root = odatajs.xml.xmlFirstChildElement(doc);
+
+ djstest.assertAreEqual(odatajs.xml.xmlLocalName(root), "root", "xml._localName didn't return the expected localName of the root element");
+ djstest.done();
+ });
+
+ djstest.addTest(function xmlFirstChildElement() {
+ var xml = "\
+ <root xmlns:n1=\"http://namespace1\" \r\n\
+ xml:base=\"http://base.org\"> \r\n\
+ <element1 /> \r\n\
+ <element2 /> \r\n\
+ </root>\r\n";
+
+
+ var doc = odatajs.xml.xmlParse(xml);
+ var root = odatajs.xml.xmlFirstChildElement(doc);
+ var child = odatajs.xml.xmlFirstChildElement(root);
+
+ djstest.assertAreEqual(odatajs.xml.xmlLocalName(child), "element1", "xml.firstElement returned didn't return the expected element");
+ djstest.done();
+ });
+
+ djstest.addTest(function xmlChildElementsTest() {
+ var xml = "\
+ <root xmlns:n1=\"http://namespace1\" \r\n\
+ xml:base=\"http://base.org\"> \r\n\
+ <element1 /> \r\n\
+ <element2 xml:base=\"http://otherBase.org\" /> \r\n\
+ <n1:element3 xml:base=\"path1/path2\" /> \r\n\
+ </root>\r\n";
+
+ var expected = [
+ { localName: "element1", nsURI: null },
+ { localName: "element2", nsURI: null },
+ { localName: "element3", nsURI: "http://namespace1" }
+ ];
+
+ var actual = [];
+
+ var doc = odatajs.xml.xmlParse(xml);
+ var root = odatajs.xml.xmlFirstChildElement(doc);
+
+ odatajs.xml.xmlChildElements(root, function (child) {
+ djstest.log("in child elements callback");
+ actual.push({
+ localName: odatajs.xml.xmlLocalName(child),
+ nsURI: odatajs.xml.xmlNamespaceURI(child)
+ });
+ });
+
+ djstest.assertAreEqualDeep(actual, expected, "xml.childElements didn't return the expected elements");
+ djstest.done();
+ });
+
+ djstest.addTest(function xmlAttributesTest() {
+ var xml = "\
+ <root xmlns:n1=\"http://namespace1\" \r\n\
+ xml:base=\"http://base.org\" \r\n\
+ attribute=\"value\" \r\n\
+ n1:nsAttribute=\"nsValue\" />\r\n";
+
+ var expected = {
+ n1: { localName: "n1", nsURI: "http://www.w3.org/2000/xmlns/", value: "http://namespace1" },
+ base: { localName: "base", nsURI: "http://www.w3.org/XML/1998/namespace", value: "http://base.org" },
+ attribute: { localName: "attribute", nsURI: null, value: "value" },
+ nsAttribute: { localName: "nsAttribute", nsURI: "http://namespace1", value: "nsValue" }
+ };
+
+ var actual = {};
+
+ var doc = odatajs.xml.xmlParse(xml);
+ var root = odatajs.xml.xmlFirstChildElement(doc);
+
+ odatajs.xml.xmlAttributes(root, function (attribute) {
+ djstest.log("in child elements callback");
+ var localName = odatajs.xml.xmlLocalName(attribute);
+ actual[localName] = {
+ localName: localName,
+ nsURI: odatajs.xml.xmlNamespaceURI(attribute),
+ value: attribute.value
+ };
+ });
+
+ djstest.assertAreEqualDeep(actual, expected, "xml.attributes returned didn't return the expected attributes");
+ djstest.done();
+ });
+
+ djstest.addTest(function hasLeadingOrTrailingWhitespaceTest() {
+ // tests are in text / expected format.
+ var tests = [
+ { t: "", r: false },
+ { t: " ", r: true },
+ { t: "text", r: false },
+ { t: "text with spaces", r: false },
+ { t: "not \r\n really", r: false },
+ { t: " at start", r: true },
+ { t: "at end ", r: true },
+ { t: "end\r", r: true },
+ { t: "end\n", r: true },
+ { t: "end\r\n", r: true }
+ ];
+
+ var i, len;
+ for (i = 0, len = tests.length; i < len; i++) {
+ var result = odatajs.xml.hasLeadingOrTrailingWhitespace(tests[i].t);
+ djstest.assertAreEqual(result, tests[i].r, "match for " + tests[i].t);
+ }
+
+ djstest.done();
+ });
+
+ djstest.addTest(function xmlInnerTextTest() {
+ // Tests are in test / expected format.
+ var tests = [
+ { t: "<t>text</t>", r: "text" },
+ { t: "<t>text with a <![CDATA[cdata block]]></t>", r: "text with a cdata block" },
+ { t: "<t> text </t>", r: " text " },
+ { t: "<t> </t>", r: null },
+ { t: "<t> <b>text</b> </t>", r: null },
+ { t: "<t> preceding</t>", r: " preceding" },
+ { t: "<t xml:space='preserve'> <b>text</b> </t>", r: " " },
+ { t: "<t xml:space='default'> <b>text</b> </t>", r: null}
+ ];
+
+ var i, len;
+ for (i = 0, len = tests.length; i < len; i++) {
+ var test = tests[i];
+ var doc = odatajs.xml.xmlParse(test.t);
+ var actual = odatajs.xml.xmlInnerText(doc);
+ djstest.assertAreEqual(actual, test.r, "test for [" + test.t + "]");
+ }
+
+ djstest.done();
+ });
+
+ // DATAJS INTERNAL END
+})(this);
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/503b4417/tests/odatajs-cache-large-collection-functional-tests.html
----------------------------------------------------------------------
diff --git a/tests/odatajs-cache-large-collection-functional-tests.html b/tests/odatajs-cache-large-collection-functional-tests.html
new file mode 100644
index 0000000..9415305
--- /dev/null
+++ b/tests/odatajs-cache-large-collection-functional-tests.html
@@ -0,0 +1,53 @@
+<!--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ -->
+<html>
+<head>
+ <title>datajs.cache and datajs.store full local store 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="../build/odatajs-4.0.0-beta-01.js"></script>
+ <!--<script type="text/javascript" src="common/common.js"></script>-->
+
+ <script type="text/javascript" src="common/djstest.js"></script>
+ <script type="text/javascript" src="common/djstest-browser.js"></script>
+ <script type="text/javascript" src="common/CacheVerifier.js"></script>
+ <script type="text/javascript" src="common/ObservableHttpClient.js"></script>
+ <script type="text/javascript" src="common/odataVerifyReader.js"></script>
+
+ <script type="text/javascript" src="odatajs-cache-large-collection-functional-tests.js"></script>
+</head>
+<body>
+ <h1 id="qunit-header">datajs.cache and datajs.store full local store 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/503b4417/tests/odatajs-cache-large-collection-functional-tests.js
----------------------------------------------------------------------
diff --git a/tests/odatajs-cache-large-collection-functional-tests.js b/tests/odatajs-cache-large-collection-functional-tests.js
new file mode 100644
index 0000000..6a18d2d
--- /dev/null
+++ b/tests/odatajs-cache-large-collection-functional-tests.js
@@ -0,0 +1,187 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+(function (window, undefined) {
+ window.odatajs.oData.defaultHandler.accept = "application/json;q=0.9, */*;q=0.1";
+ var largeCollectionFeed = "./endpoints/LargeCollectionService.svc/Customers";
+ var itemsInCollection = 2 * 1024 * 1024;
+
+ var cleanDomStorage = function (done) {
+ /* 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.
+ * @param {Function} done - Function to be called after DOM storage is cleared.
+ */
+ if (window.localStorage) {
+ window.localStorage.clear();
+ }
+ done();
+ };
+
+ var cleanIndexedDb = function (done) {
+ /** Cleans all the data saved in the browser's IndexedDb Storage.
+ * @param {Function} done - Function to be called after DOM storage is cleared.
+ */
+ var caches = this.caches;
+
+ djstest.cleanStoreOnIndexedDb(caches, done);
+ };
+
+ var makeUnexpectedErrorHandler = function () {
+ return function (err) {
+ djstest.assert(false, "Unexpected call to error handler with error: " + djstest.toString(err));
+ };
+ };
+
+ var storageMechanisms = {
+ indexeddb: { cleanup: cleanIndexedDb },
+ dom: { cleanup: cleanDomStorage }
+ };
+
+ var cleanupAllStorage = function(done) {
+ /** Cleans up all available storage mechanisms in the browser.
+ * @param {Function} done - Function to be called by each cleanup function after storage is cleared.
+ */
+ var that = this;
+ var storeCleanup = [];
+
+ $.each(CacheVerifier.mechanisms, function(_, mechanism) {
+ if (CacheVerifier.isMechanismAvailable(mechanism)) {
+ storeCleanup.push(function(done) {
+ if (storageMechanisms[mechanism]) {
+ storageMechanisms[mechanism].cleanup.call(that, done);
+ } else {
+ done();
+ }
+ });
+ }
+ });
+
+ djstest.asyncDo(storeCleanup, done);
+ };
+
+
+ module("Functional", {
+ setup: function () {
+ this.observableHttpClient = new ObservableHttpClient();
+ window.odatajs.oData.net.defaultHttpClient = this.observableHttpClient;
+ this.caches = [];
+ var that = this;
+
+ djstest.wait(function (done) {
+ cleanupAllStorage.call(that, done);
+ });
+ },
+
+ teardown: function () {
+ window.odatajs.oData.net.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(["dom", "indexeddb"], function (_, mechanism) {
+ if (CacheVerifier.isMechanismAvailable(mechanism)) {
+ $.each([-1, 10 * 1024 * 1024, 1024 * 10248], function (_, cacheSize) {
+ var prefetchParameters = { mechanism: mechanism, feed: largeCollectionFeed, skip: 0, take: 5, pageSize: 1024, prefetchSize: -1, cacheSize: cacheSize };
+ djstest.addTest(function (params) {
+
+ djstest.assertsExpected(3);
+ var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize,
+ mechanism: params.mechanism, cacheSize: params.cacheSize
+ };
+
+ var cache = odatajs.cache.createDataCache(options);
+ this.caches.push({ name: options.name,
+ cache: cache
+ });
+
+ cache.onidle = function () {
+ djstest.assert(true, "onidle Called");
+ djstest.done();
+ };
+
+ var cacheVerifier = new CacheVerifier(params.feed, params.pageSize, itemsInCollection);
+ var session = this.observableHttpClient.newSession();
+
+ cache.readRange(params.skip, params.take).then(function (data) {
+ var expectedRangeUrl = params.feed + "?$skip=" + params.skip + "&$top=" + params.take;
+ cacheVerifier.verifyRequests(session.requests, session.responses, params.skip, params.take, "largeCollection requests with prefetch", false, true);
+ window.ODataVerifyReader.readJsonAcrossServerPages(expectedRangeUrl, function (expectedData) {
+ djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
+ });
+ }, function (err) {
+ makeUnexpectedErrorHandler(err)();
+ });
+ }, "readRange and prefetch all to fill store on " + prefetchParameters.mechanism + " with cacheSize=" + prefetchParameters.cacheSize, prefetchParameters, 600000);
+
+ $.each([500, 1024 * 10 /*Test reduced from 100 to 10 to work around slow running script error in IE8 and Safari (bug 2200)*/], function (_, pageSize) {
+ var largeReadParameters = { mechanism: mechanism, feed: largeCollectionFeed, skip: 0, take: 1024, pageSize: pageSize, prefetchSize: 0, cacheSize: cacheSize };
+ djstest.addTest(function (params) {
+
+ djstest.assertsExpected(2);
+ var options = { name: "cache" + new Date().valueOf(), source: params.feed, pageSize: params.pageSize, prefetchSize: params.prefetchSize,
+ mechanism: params.mechanism, cacheSize: params.cacheSize
+ };
+
+ var cache = odatajs.cache.createDataCache(options);
+ this.caches.push({ name: options.name, cache: cache });
+
+ var cacheVerifier = new CacheVerifier(params.feed, params.pageSize, itemsInCollection);
+ var session = this.observableHttpClient.newSession();
+
+ cache.readRange(params.skip, params.take).then(function (data) {
+ var expectedRangeUrl = params.feed + "?$skip=" + params.skip + "&$top=" + params.take;
+ cacheVerifier.verifyRequests(session.requests, session.responses, params.skip, params.take, "largeCollection requests without prefetch", false, false);
+ window.ODataVerifyReader.readJsonAcrossServerPages(expectedRangeUrl, function (expectedData) {
+ djstest.assertAreEqualDeep(data, expectedData, "Verify response data");
+ djstest.done();
+ });
+ }, function (err) {
+ makeUnexpectedErrorHandler(err)();
+ djstest.done();
+ });
+ }, "readRange of skip=" + largeReadParameters.skip + " take=" + largeReadParameters.take + " cacheSize=" + largeReadParameters.cacheSize + " and pageSize=" + largeReadParameters.pageSize +
+ " to fill store on " + largeReadParameters.mechanism, largeReadParameters, 600000);
+ });
+ });
+ }
+ });
+})(this);
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/503b4417/tests/odatajs-cache-long-haul-tests.html
----------------------------------------------------------------------
diff --git a/tests/odatajs-cache-long-haul-tests.html b/tests/odatajs-cache-long-haul-tests.html
new file mode 100644
index 0000000..3e02e32
--- /dev/null
+++ b/tests/odatajs-cache-long-haul-tests.html
@@ -0,0 +1,194 @@
+<!--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <title>OData Long Haul Tests</title>
+ <meta http-equiv="cache-control" content="no-cache" />
+ <meta http-equiv="pragma" content="no-cache" />
+ <meta http-equiv="expires" content="-1" />
+ <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.js"></script>
+ <script type="text/javascript" src="../build/odatajs-4.0.0-beta-01.js"></script>
+ <script type="text/javascript" src="common/common.js"></script>
+ <script type="text/javascript" src="common/djstest.js"></script>
+ <script type="text/javascript" src="common/Instrument.js"></script>
+ <script type="text/javascript">
+ var cache;
+ var clearBetweenReads;
+ var currentRunTimeMS;
+ var failureCount;
+ var hourMS = 60 * 60 * 1000;
+ var goalRunTimeMS = hourMS;
+ var isTotalIncreaseHigh;
+ var itemsInCollection = 16;
+ var iterationsRun;
+ var memoryDelta = 5000000;
+ var getBrowserMemorySize;
+ var startMemorySize;
+ var startTimeMs = 0;
+ var testFeed = "http://odata.netflix.com/Catalog/Titles";
+
+ var makeUnexpectedErrorHandler = function () {
+ return function (err) {
+ failureCount++;
+ if (failureCount < 50) {
+ $("#errors").append("<p>Iteration: " + iterationsRun + " Error reading cache: " + err.message + "<p>");
+ }
+ };
+ };
+
+ var checkMemoryIncrease = function (memorySizeBefore) {
+ getBrowserMemorySize(function (memorySizeAfter) {
+ var incrementalIncreaseInMemory = memorySizeAfter - memorySizeBefore;
+ var totalIncreaseInMemory = memorySizeAfter - startMemorySize;
+ if (incrementalIncreaseInMemory > memoryDelta) {
+ failureCount++;
+ if (failureCount < 50) {
+ $("#errors").append("<p>Iteration: " + iterationsRun + " Memory usage increase in read: " + incrementalIncreaseInMemory + "<p>");
+ }
+ }
+
+ if (totalIncreaseInMemory > memoryDelta && !isTotalIncreaseHigh) {
+ isTotalIncreaseHigh = true;
+ failureCount++;
+ if (failureCount < 50) {
+ $("#errors").append("<p>Iteration: " + iterationsRun + " Total memory usage increase over duration: " + totalIncreaseInMemory + "<p>");
+ }
+ }
+
+ iterationsRun++;
+ nextIteration();
+ });
+ };
+
+ var readRangePrefetchTest = function () {
+ var readPage = 6;
+
+ getBrowserMemorySize(function (memorySizeBefore) {
+ callReadRangeRepeatedly(0, readPage, function () { checkMemoryIncrease(memorySizeBefore) });
+ });
+ };
+
+ var callReadRangeRepeatedly = function (index, count, done) {
+ /** Calls readRange over the whole collection and done when all items have been read.
+ * @param {Integer} index - Index to start the read.
+ * @param {String} count - The count of each readRange.
+ * @param {Function} done - Function to be called when all items in collection have been read.
+ var cacheRead = function () {
+ cache.readRange(index, count).then(function () {
+ if (index < itemsInCollection) {
+ index += count;
+ callReadRangeRepeatedly(index, count, done);
+ }
+ else {
+ done();
+ }
+ }, makeUnexpectedErrorHandler(cache));
+ };
+
+ if (clearBetweenReads) {
+ cache.clear().then(cacheRead(), makeUnexpectedErrorHandler(cache));
+ }
+ else {
+ cacheRead();
+ }
+ }
+
+ function startTest() {
+ var prefetchSize =
+ $('input[name=PrefetchEnabled]').attr('checked') ? -1 : 0;
+ clearBetweenReads = $('input[name=ClearBetweenReads]').attr('checked');
+ var inputHours = parseFloat($('#time').val());
+
+ if (inputHours !== undefined && typeof inputHours === "number" && !isNaN(inputHours) && isFinite(inputHours) && inputHours > 0) {
+ goalRunTimeMS = hourMS * inputHours;
+ }
+ OData.defaultHttpClient.enableJsonpCallback = true;
+ cache = datajs.cache.createDataCache({ name: "cache" + new Date().valueOf(), source: testFeed, pageSize: 5, prefetchSize: prefetchSize });
+ failureCount = 0;
+ iterationsRun = 0;
+ currentRunTimeMS = 0;
+ isTotalIncreaseHigh = false;
+ $("#errors").empty();
+ getBrowserMemorySize = Instrument.getBrowserMemorySize;
+ getBrowserMemorySize(function (memorySizeStart) {
+ startMemorySize = memorySizeStart;
+ $("#starting-memory").text("Starting memory size: " + startMemorySize);
+ });
+ startTimeMs = new Date().getTime();
+
+ nextIteration();
+ }
+
+ function nextIteration() {
+ currentRunTimeMS = new Date().getTime() - startTimeMs;
+ if (currentRunTimeMS > goalRunTimeMS) {
+ getBrowserMemorySize(function (memorySizeAfter) {
+ $("#stress-status").text("Tests complete. Iterations: " + iterationsRun + " Failures: " + failureCount +
+ " Start memory: " + startMemorySize + " End memory: " + memorySizeAfter);
+ });
+
+ cache.clear();
+ return;
+ }
+
+ if (iterationsRun % 100 === 0) {
+ getBrowserMemorySize(function (memorySizeAfter) {
+ var text = "Running tests (iterationsRun=" + iterationsRun;
+ text += ", Time run: " + currentRunTimeMS + "ms";
+ text += ", Remaining time: " + (goalRunTimeMS - currentRunTimeMS) + "ms";
+ text += "). Failures: " + failureCount;
+ text += " Current memory size: " + memorySizeAfter;
+ $("#stress-status").text(text);
+ });
+ }
+
+ readRangePrefetchTest();
+ }
+
+ $(document).ready(function () {
+ $("#start-button").click(startTest);
+ });
+ </script>
+</head>
+<body>
+ <h1>
+ OData Long Haul</h1>
+ <p>
+ Repeatedly runs an action and checks the memory usage.
+ </p>
+ <p>
+ <input name="time" id="time" type="text" />Length of time to run test</p>
+ <p>
+ <input type="checkbox" name="PrefetchEnabled" value="false" />Prefetch Enabled</p>
+ <p>
+ <input type="checkbox" name="ClearBetweenReads" value="false" />Clear Between Reads</p>
+ <button id='start-button'>
+ Start</button>
+ <p id='errors'>
+ </p>
+ <p id='stress-status'>
+ </p>
+ <p id='starting-memory'>
+ </p>
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/503b4417/tests/odatajs-startup-perf-test.html
----------------------------------------------------------------------
diff --git a/tests/odatajs-startup-perf-test.html b/tests/odatajs-startup-perf-test.html
new file mode 100644
index 0000000..f69684a
--- /dev/null
+++ b/tests/odatajs-startup-perf-test.html
@@ -0,0 +1,109 @@
+<!--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<!--
+Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-->
+<head>
+ <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
+ <title>datajs startup perf test</title>
+
+ <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="common/djstest.js"></script>
+ <script type="text/javascript" src="common/Instrument.js"></script>
+
+ <script type="text/javascript">
+ $(window).load(function () {
+ djstest.addTest(function startupTimeAndMemory() {
+ var durationLimit = 500;
+ var memorySizeDeltaLimit = 5000000;
+
+ var filename = "../build/odatajs-4.0.0-beta-01.js";
+ var getBrowserMemorySize = Instrument.getBrowserMemorySize;
+
+ $.ajax({
+ url: "../src/" + filename,
+ dataType: "text",
+ success: function (script) {
+ getBrowserMemorySize(function (memorySizeBefore) {
+ var duration = new Date();
+ eval(script);
+ duration = new Date() - duration;
+ getBrowserMemorySize(function (memorySizeAfter) {
+ var memorySizeDelta = memorySizeAfter - memorySizeBefore;
+ djstest.assert(duration < durationLimit, duration + " ms (limit " + durationLimit + " ms)");
+ djstest.assert(memorySizeDelta < memorySizeDeltaLimit,
+ memorySizeDelta + " bytes (limit " + memorySizeDeltaLimit + " bytes, initial " + memorySizeBefore + " bytes)");
+
+ djstest.done();
+ });
+ });
+ },
+ error: function () {
+ // See if we are running the dev build
+ $.ajax({
+ url: "../src/odata.js",
+ dataType: "text",
+ success: function () {
+ djstest.pass("Running on dev build, no measurement taken");
+ djstest.done();
+ },
+ error: function (jqXHR, textStatus, errorThrown) {
+ djstest.fail("Request failed: " + jqXHR.responseText);
+ djstest.done();
+ }
+ });
+ }
+ });
+ });
+ });
+ </script>
+</head>
+<body>
+ <h1 id="qunit-header">datajs startup perf test</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/503b4417/tests/run-tests.wsf
----------------------------------------------------------------------
diff --git a/tests/run-tests.wsf b/tests/run-tests.wsf
new file mode 100644
index 0000000..263bae0
--- /dev/null
+++ b/tests/run-tests.wsf
@@ -0,0 +1,435 @@
+<!--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+*/
+-->
+<job>
+ <runtime>
+ <description>Test driver for running datajs tests - run from the same directory as the script</description>
+ <comment>
+ Result codes:
+ 0 - success
+ 1 - failed to launch tests
+ 2 - tests failed
+ </comment>
+ </runtime>
+ <script language="JScript" src="test-list.js" />
+ <script language="JScript">
+
+ var exitCode;
+ var fso = WScript.CreateObject("Scripting.FileSystemObject");
+ var shell = WScript.CreateObject("WScript.Shell");
+
+ function attempt(action, interval, maxAttempts) {
+ /// <summary>Attempt an action at an interval, optionally for a maximum number of attempts</summary>
+ /// <param name="action">Action callback; should return boolean whether it succeeded</param>
+ /// <param name="interval">Interval (milliseconds) between attempts</param>
+ /// <param name="maxAttempts">(Optional) Maximum number of attempts. Infinite if undefined.</param>
+ /// <returns>Whether the action succeeded</returns>
+ var done = false;
+ var attempts = 0;
+ while (!done) {
+ var success = action();
+ if (maxAttempts !== undefined) {
+ attempts++;
+ }
+ done = success === true || (maxAttempts !== undefined && attempts >= maxAttempts);
+ if (!done) {
+ WScript.Sleep(interval);
+ }
+ }
+
+ return success;
+ }
+
+ function parseJson(text) {
+ /// <summary>Parses a JSON document, removes the 'd' wrapper.</summary>
+ try {
+ return eval("(" + text + ")").d;
+ } catch (e) {
+ throw { message: "Error parsing JSON: [" + text + "]" };
+ }
+ }
+
+ function SaveTextToFile(content, path) {
+ /// <summary>Saves text content into a file.</summary>
+ /// <param name="content" type="String">Content to save.</param>
+ /// <param name="path" type="String">Path of file to save into.</param>
+ var ForReading = 1, ForWriting = 2;
+ var file = fso.OpenTextFile(path, ForWriting, true, -1 /* open as unicode */);
+ file.Write(content);
+ file.Close();
+ }
+
+ function GetUrlSync(url) {
+ var xhr;
+ xhr = WScript.CreateObject("Msxml2.ServerXMLHTTP.6.0");
+ xhr.open("GET", url, false);
+ xhr.send();
+ return xhr.responseText;
+ }
+
+ function LaunchBrowser(browsers, serviceRoot, followingPages, url, testRunId, outputDirectory) {
+ /// <summary>Launches a browsers and waits until the service tells us the run is complete.</summary>
+ /// <param name="browsers">Browsers to run.</param>
+ /// <param name="serviceRoot" type="String">Root URL of the logging service.</param>
+ /// <param name="followingPages" type="Array">Array of pages that should follow the given url.</param>
+ /// <param name="url" type="String">URL of the page to start the browser on.</param>
+ /// <param name="testRunId" type="String">ID of the test run being monitored.</param>
+ /// <param name="outputDirectory" type="String">Directory in which to output screenshots.</param>
+
+ for (browserName in browsers) {
+ var xhr;
+ var markInProgressUrl = serviceRoot + "MarkInProgress?testRunId=" + testRunId;
+ GetUrlSync(markInProgressUrl);
+
+ // Add all the pages that follow the given URL.
+ if (followingPages && followingPages.length > 0) {
+ var addFilesUrl = serviceRoot + "AddTestPages?testRunId=" + testRunId + "&pages=" + followingPages.join();
+ GetUrlSync(addFilesUrl);
+ }
+
+ var setPrefixUrl = serviceRoot + "SetTestNamePrefix?testRunId=" + testRunId + "&prefix=" + browserName + "-";
+ GetUrlSync(setPrefixUrl);
+
+ exitCode = 0;
+ var response;
+
+ // Only the first location found from the browsers array is used. If none of the listed locations of the browser exist and the browser argument was
+ // explicitly used then an exception is thrown.
+ var browserFound = false;
+ for (var i = 0; i < browsers[browserName].length && !browserFound; i++) {
+ var path = shell.ExpandEnvironmentStrings(browsers[browserName][i]);
+ if (fso.FileExists(path)) {
+ browserFound = true;
+
+ WScript.Echo("Navigating to " + url + " with " + path);
+ var browser = shell.Exec("\"" + path + "\" " + url);
+
+ var checkRunUrl = serviceRoot + "IsTestRunInProgress?testRunId=" + testRunId;
+ WScript.Echo("Monitoring status on " + checkRunUrl);
+
+ var interval = 2000;
+ var maxAttempts = WScript.Arguments.Named.Exists("timeout") ? Math.floor((WScript.Arguments.Named.Item("timeout") / interval) * 1000) : undefined;
+ var success = attempt(function () {
+ return parseJson(GetUrlSync(checkRunUrl)) !== true;
+ }, interval, maxAttempts);
+ if (!success) {
+ WScript.Echo("Timed out waiting for test to complete");
+ exitCode = 2;
+ }
+
+ RunCommand("taskkill.exe /pid " + browser.ProcessID, true);
+ }
+ }
+
+ // If the "/browsers" argument was explicitly used and all location have been checked, then throw an exception.
+ if (!browserFound) {
+ var message = "Unable to find browser at: " + path;
+ if (WScript.Arguments.Named.Exists("browsers")) {
+ throw { message: message };
+ } else {
+ WScript.Echo(message);
+ }
+ }
+ }
+ }
+
+ function WriteTestRunResults(serviceRoot, testRunId, outputDirectory) {
+ /// <summary>Writes the results of the test run to disk and updates the overall status.</summary>
+ /// <param name="serviceRoot" type="String">Root URL of the logging service.</param>
+ /// <param name="testRunId" type="String">ID of the test run being monitored.</param>
+ /// <param name="outputDirectory" type="String">Directory in which to write test result files.</param>
+
+ var getResultsUrl = serviceRoot + "GetTestRunResults?testRunId=" + testRunId;
+ WScript.Echo("Querying " + getResultsUrl);
+
+ var response = GetUrlSync(getResultsUrl);
+
+ var resultsPath = outputDirectory + "\\results.trx";
+ WScript.Echo("Writing results.trx file to " + resultsPath);
+ SaveTextToFile(response, resultsPath);
+
+ var xml = new ActiveXObject("Msxml2.DOMDocument.6.0");
+ xml.loadXML(response);
+ xml.setProperty("SelectionNamespaces", "xmlns:trx='http://microsoft.com/schemas/VisualStudio/TeamTest/2010'");
+ xml.setProperty("SelectionLanguage", "XPath");
+ var resultNode = xml.selectSingleNode("/trx:TestRun/trx:ResultSummary");
+ if (resultNode === null) {
+ throw { message: "Unable to find results summary" };
+ }
+
+ var outcome = resultNode.getAttribute("outcome");
+ if (outcome !== "Passed") {
+ WScript.Echo("Outcome: " + outcome);
+ var failedTests = xml.selectNodes("/trx:TestRun/trx:Results/trx:UnitTestResult[@outcome != 'Passed']/@testName");
+ for (var i = 0; i < failedTests.length; i++) {
+ WScript.Echo(" Failed test: " + failedTests[i].value);
+ }
+ exitCode = 2;
+ } else {
+ WScript.Echo("All tests passed.");
+ }
+ }
+
+ function CheckUrl(url) {
+ var xhr = WScript.CreateObject("Msxml2.ServerXMLHTTP.6.0");
+ xhr.open("GET", url, false);
+ var success = false;
+ try {
+ xhr.send();
+ success = (xhr.status === 200);
+ if (!success) {
+ WScript.Echo("status: " + xhr.status + " - " + xhr.statusText);
+ }
+ } catch (err) {
+ WScript.Echo("error: " + err.message);
+ }
+
+ return success;
+ }
+
+ function ExpandWildcard(path) {
+ var wcRegEx = /\\\*\*?\\/;
+ var wcMatch = wcRegEx.exec(path);
+
+ var paths = [];
+ if (wcMatch !== null) {
+ var recursive = wcMatch[0] === "\\**\\";
+ var basePath = path.substring(0, wcMatch.index);
+ var relativePath = path.substring(wcMatch.index + wcMatch[0].length);
+
+ if (fso.FolderExists(basePath)) {
+ var folder = fso.GetFolder(basePath);
+ var subFolders = new Enumerator(folder.SubFolders);
+
+ paths = paths.concat(ExpandWildcard(basePath + "\\" + relativePath));
+
+ for (; !subFolders.atEnd(); subFolders.moveNext()) {
+ var expandedPath = subFolders.item().Path + "\\"
+ if (recursive) {
+ expandedPath += "**\\";
+ }
+ expandedPath += path.substring(wcMatch.index + wcMatch[0].length);
+ paths = paths.concat(ExpandWildcard(expandedPath));
+ }
+ }
+ } else {
+ paths.push(path);
+ }
+ return paths;
+ }
+
+ function FindFirstPath(candidates) {
+ /// <summary>Finds the first path present from a candidate list.</summary>
+ /// <param name="candidates" type="Array">Array of paths (possibly with environment variables).</param>
+ /// <returns type="String">The first folder on disk found; null if none are present.</returns>
+
+ var paths = [];
+
+ for (var i = 0; i < candidates.length; i++) {
+ var path = shell.ExpandEnvironmentStrings(candidates[i]);
+ paths = paths.concat(ExpandWildcard(path));
+ }
+
+ for (var i = 0; i < paths.length; i++) {
+ if (fso.FolderExists(paths[i]) || fso.FileExists(paths[i])) {
+ return paths[i];
+ }
+ }
+ return null;
+ }
+
+ function RunCommand(command, waitForExit, expectedExitCode) {
+ /// <summary>Runs a command or program</summary>
+ /// <param name="command" type="String">Command to run</param>
+ /// <param name="waitForExit" type="Boolean">Whether to wait for program to exit</param>
+ /// <param name="expectedExitCode" type="Integer">If waitForExit is true, throw if the exit code is not expected</param>
+ /// <returns type="Integer">The exitcode if waitForExit is true; always 0 if waitForExit is false</returns>
+ WScript.Echo("[cmd] " + command);
+ var exitCode = shell.Run(command, 0, waitForExit);
+ if (expectedExitCode !== undefined && exitCode !== expectedExitCode) {
+ throw { message: "Process exited with unexpected exit code. (Expected: " + expectedExitCode + ", Actual: " + exitCode + ")" };
+ } else {
+ return exitCode;
+ }
+ }
+
+ function SetupWebDevServer() {
+ /// <summary>Starts up IIS Express if it's not running.</summary>
+ /// <returns type="String">The URL to the server root.</returns>
+ var siteName = "DataJS Development Site";
+ var appName = "datajs";
+ var port = "8989";
+ var result = "http://" + shell.ExpandEnvironmentStrings("%COMPUTERNAME%").toLowerCase() + ":" + port + "/" + appName + "/";
+ var url = result + "tests/common/TestLogger.svc";
+
+ var success = CheckUrl(url);
+
+ if (!success) {
+ // Assume that we need to launch this.
+ var src = fso.GetAbsolutePathName("..");
+
+ var folder = FindFirstPath([
+ "%ProgramFiles(x86)%\\IIS Express",
+ "%ProgramFiles%\\IIS Express"]);
+
+ if (!folder) {
+ throw { message: "Unable to find path to IIS Express" };
+ }
+
+ var appCmd = "\"" + folder + "\\appcmd.exe\"";
+ var iisExpress = "\"" + folder + "\\iisexpress.exe\"";
+
+ // Delete site if it already exists
+ WScript.Echo("Checking if site '" + siteName + "' already exists...");
+ if (RunCommand(appCmd + " list site \"" + siteName + "\"", true) === 0) {
+ WScript.Echo("Deleting existing site '" + siteName + "'...");
+ RunCommand(appCmd + " delete site \"" + siteName + "\"", true, 0);
+ }
+
+ // Create site and app
+ WScript.Echo("Creating site '" + siteName + "'...");
+ RunCommand(appCmd + " add site /name:\"" + siteName + "\" /bindings:http/*:" + port + ": /physicalPath:%IIS_BIN%\\AppServer\\empty_wwwroot", true, 0);
+
+ WScript.Echo("Creating application '" + appName + "'...");
+ RunCommand(appCmd + " add app /site.name:\"" + siteName + "\" /path:\"/" + appName + "\" /physicalPath:\"" + src + "\"", true, 0);
+
+ // Start the server
+ WScript.Echo("Starting IIS Express server...");
+ RunCommand(iisExpress + " /site:\"" + siteName + "\" /trace:error");
+
+ WScript.Sleep(2 * 1000);
+ success = attempt(function () {
+ WScript.Echo("Waiting for server to come up, looking for " + url + " ...");
+ return CheckUrl(url);
+ }, 5 * 1000, 3);
+
+ if (!success) {
+ throw { message: "Unable to verify the URL at " + url };
+ }
+ }
+ return result;
+ }
+
+ function CreateTestRunId(serviceRoot) {
+ /// <summary>Creates a new test run ID from the service.</summary>
+ /// <param name="serviceRoot" type="String">Root of logger service.</param>
+ /// <returns type="String">The test run ID created.</returns>
+ var xhr = WScript.CreateObject("Msxml2.ServerXMLHTTP.6.0");
+ var url = serviceRoot + "CreateTestRun";
+ xhr.open("GET", url, false);
+ WScript.Echo("URL: " + url);
+ xhr.send();
+
+ var response = xhr.responseText;
+ var result = parseJson(response);
+ return result;
+ }
+
+ function GetBrowsers() {
+ /// <summary>Gets the browsers that should be used for running the tests.</summary>
+ /// <returns type="Object">Dictionary object containing the browser and its executable path as key value pairs.</returns>
+ var localAppData = fso.FolderExists(shell.ExpandEnvironmentStrings("%LOCALAPPDATA%")) ? "%LOCALAPPDATA%" : "%USERPROFILE%\\Local Settings\\Application Data";
+ var programFiles = fso.FolderExists(shell.ExpandEnvironmentStrings("%ProgramFiles(x86)%")) ? "%ProgramFiles(x86)%" : "%ProgramFiles%";
+ var browsers = {
+ IE8: [programFiles + "\\Internet Explorer\\iexplore.exe"],
+ Firefox4: [programFiles + "\\Mozilla Firefox\\firefox.exe"],
+ Chrome: [programFiles + "\\Google\\Chrome\\Application\\chrome.exe", localAppData + "\\Google\\Chrome\\Application\\chrome.exe"],
+ Safari5: [programFiles + "\\Safari\\safari.exe"],
+ Opera: [programFiles + "\\Opera\\opera.exe"]
+ };
+
+ var browsersToRun = {};
+
+ if (WScript.Arguments.Named.Exists("browsers")) {
+ browserNames = WScript.Arguments.Named.Item("browsers").split(',');
+ for (i in browserNames) {
+ var browserName = browserNames[i];
+ if (browsers[browserName]) {
+ browsersToRun[browserName] = browsers[browserName];
+ } else {
+ throw { message: "Unknown browser: " + browserName };
+ }
+ }
+ }
+ else {
+ browsersToRun = browsers;
+ }
+
+ return browsersToRun;
+ }
+
+ function GetTestFilesList() {
+ /// <summary>Gets the list of test files that are going to be executed in the test run.</summary>
+ /// <returns type="Array">The list of test files.</returns>
+ var testFilesList = null;
+ if (WScript.Arguments.Named.Exists("testFiles")) {
+ testFilesList = WScript.Arguments.Named.Item("testFiles").split(',');
+ }
+
+ if (testFilesList === null) {
+ testFilesList = getAllTestFiles();
+ }
+
+ WScript.Echo("Test files to be executed: " + testFilesList.toString());
+ return testFilesList;
+ }
+
+ function GetOutputDirectory() {
+ /// <summary>Gets the test run output directory.</summary>
+ /// <returns type="String">Output directory.</returns>
+ var result;
+ if (WScript.Arguments.Named.Exists("outputDirectory")) {
+ result = WScript.Arguments.Named.Item("outputDirectory");
+ } else {
+ result = shell.ExpandEnvironmentStrings("%DJSOUT%\\JSLib.sln\\tests");
+ }
+
+
+ return result;
+ }
+
+ try {
+ var root = SetupWebDevServer();
+ var serviceRoot = root + "tests/common/TestLogger.svc/";
+ var testRunId = CreateTestRunId(serviceRoot);
+ WScript.Echo("Test Run ID: " + testRunId);
+
+ var testFilesList = GetTestFilesList();
+ var browsers = GetBrowsers();
+ var outputDirectory = GetOutputDirectory();
+
+ if (testFilesList.length > 0) {
+ var url = root + "tests/" + testFilesList[0] + "?testRunId=" + testRunId;
+ LaunchBrowser(browsers, serviceRoot, testFilesList.splice(1, testFilesList.length), url, testRunId, outputDirectory);
+ WriteTestRunResults(serviceRoot, testRunId, outputDirectory);
+ }
+ else {
+ WScript.Echo("No test files specified to run.");
+ }
+ } catch (e) {
+ WScript.Echo("Error running tests");
+ for (var p in e) WScript.Echo(p + ": " + e[p]);
+ exitCode = 1;
+ }
+
+ WScript.Quit(exitCode);
+
+ </script>
+</job>
\ No newline at end of file