You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by jc...@apache.org on 2009/02/16 00:59:39 UTC
svn commit: r744782 [4/4] - in /couchdb/trunk: share/www/ share/www/script/
share/www/script/test/ test/
Added: couchdb/trunk/share/www/script/test/reduce_false.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/reduce_false.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/reduce_false.js (added)
+++ couchdb/trunk/share/www/script/test/reduce_false.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,45 @@
+// Licensed 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.
+
+couchTests.reduce_false = function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ var numDocs = 5;
+ var docs = makeDocs(1,numDocs + 1);
+ T(db.bulkSave(docs).ok);
+ var summate = function(N) {return (N+1)*N/2;};
+
+ var designDoc = {
+ _id:"_design/test",
+ language: "javascript",
+ views: {
+ summate: {map:"function (doc) {emit(doc.integer, doc.integer)};",
+ reduce:"function (keys, values) { return sum(values); };"},
+ }
+ };
+ T(db.save(designDoc).ok);
+
+ // Test that the reduce works
+ var res = db.view('test/summate');
+ T(res.rows.length == 1 && res.rows[0].value == summate(5));
+
+ //Test that we get our docs back
+ res = db.view('test/summate', {reduce: false});
+ T(res.rows.length == 5);
+ for(var i=0; i<5; i++)
+ {
+ T(res.rows[i].value == i+1);
+ }
+};
Propchange: couchdb/trunk/share/www/script/test/reduce_false.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/replication.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/replication.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/replication.js (added)
+++ couchdb/trunk/share/www/script/test/replication.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,207 @@
+// Licensed 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.
+
+couchTests.replication = function(debug) {
+ if (debug) debugger;
+ var host = CouchDB.host;
+ var dbPairs = [
+ {source:"test_suite_db_a",
+ target:"test_suite_db_b"},
+ {source:"test_suite_db_a",
+ target:"http://" + host + "/test_suite_db_b"},
+ {source:"http://" + host + "/test_suite_db_a",
+ target:"test_suite_db_b"},
+ {source:"http://" + host + "/test_suite_db_a",
+ target:"http://" + host + "/test_suite_db_b"}
+ ]
+ var dbA = new CouchDB("test_suite_db_a");
+ var dbB = new CouchDB("test_suite_db_b");
+ var numDocs = 10;
+ var xhr;
+ for (var testPair = 0; testPair < dbPairs.length; testPair++) {
+ var A = dbPairs[testPair].source
+ var B = dbPairs[testPair].target
+
+ dbA.deleteDb();
+ dbA.createDb();
+ dbB.deleteDb();
+ dbB.createDb();
+
+ var repTests = {
+ // copy and paste and put your code in. delete unused steps.
+ test_template: new function () {
+ this.init = function(dbA, dbB) {
+ // before anything has happened
+ }
+ this.afterAB1 = function(dbA, dbB) {
+ // called after replicating src=A tgt=B first time.
+ };
+ this.afterBA1 = function(dbA, dbB) {
+ // called after replicating src=B tgt=A first time.
+ };
+ this.afterAB2 = function(dbA, dbB) {
+ // called after replicating src=A tgt=B second time.
+ };
+ this.afterBA2 = function(dbA, dbB) {
+ // etc...
+ };
+ },
+
+ simple_test: new function () {
+ this.init = function(dbA, dbB) {
+ var docs = makeDocs(0, numDocs);
+ T(dbA.bulkSave(docs).ok);
+ };
+
+ this.afterAB1 = function(dbA, dbB) {
+ for (var j = 0; j < numDocs; j++) {
+ var docA = dbA.open("" + j);
+ var docB = dbB.open("" + j);
+ T(docA._rev == docB._rev);
+ }
+ };
+ },
+
+ deletes_test: new function () {
+ this.init = function(dbA, dbB) {
+ T(dbA.save({_id:"foo1",value:"a"}).ok);
+ };
+
+ this.afterAB1 = function(dbA, dbB) {
+ var docA = dbA.open("foo1");
+ var docB = dbB.open("foo1");
+ T(docA._rev == docB._rev);
+
+ dbA.deleteDoc(docA);
+ };
+
+ this.afterAB2 = function(dbA, dbB) {
+ T(dbA.open("foo1") == null);
+ T(dbB.open("foo1") == null);
+ };
+ },
+
+ slashes_in_ids_test: new function () {
+ // make sure docs with slashes in id replicate properly
+ this.init = function(dbA, dbB) {
+ dbA.save({ _id:"abc/def", val:"one" });
+ };
+
+ this.afterAB1 = function(dbA, dbB) {
+ var docA = dbA.open("abc/def");
+ var docB = dbB.open("abc/def");
+ T(docA._rev == docB._rev);
+ };
+ },
+
+ design_docs_test: new function() {
+ // make sure design docs replicate properly
+ this.init = function(dbA, dbB) {
+ dbA.save({ _id:"_design/test" });
+ };
+
+ this.afterAB1 = function() {
+ var docA = dbA.open("_design/test");
+ var docB = dbB.open("_design/test");
+ T(docA._rev == docB._rev);
+ };
+ },
+
+ attachments_test: new function () {
+ // Test attachments
+ this.init = function(dbA, dbB) {
+ dbA.save({
+ _id:"bin_doc",
+ _attachments:{
+ "foo.txt": {
+ "type":"base64",
+ "data": "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
+ }
+ }
+ });
+ };
+
+ this.afterAB1 = function(dbA, dbB) {
+ var xhr = CouchDB.request("GET", "/test_suite_db_a/bin_doc/foo.txt");
+ T(xhr.responseText == "This is a base64 encoded text")
+
+ xhr = CouchDB.request("GET", "/test_suite_db_b/bin_doc/foo.txt");
+ T(xhr.responseText == "This is a base64 encoded text")
+ };
+ },
+
+ conflicts_test: new function () {
+ // test conflicts
+ this.init = function(dbA, dbB) {
+ dbA.save({_id:"foo",value:"a"});
+ dbB.save({_id:"foo",value:"b"});
+ };
+
+ this.afterBA1 = function(dbA, dbB) {
+ var docA = dbA.open("foo", {conflicts: true});
+ var docB = dbB.open("foo", {conflicts: true});
+
+ // make sure the same rev is in each db
+ T(docA._rev === docB._rev);
+
+ // make sure the conflicts are the same in each db
+ T(docA._conflicts[0] === docB._conflicts[0]);
+
+ // delete a conflict.
+ dbA.deleteDoc({_id:"foo", _rev:docA._conflicts[0]});
+ };
+
+ this.afterBA2 = function(dbA, dbB) {
+ // open documents and include the conflict meta data
+ var docA = dbA.open("foo", {conflicts: true});
+ var docB = dbB.open("foo", {conflicts: true});
+
+ // We should have no conflicts this time
+ T(docA._conflicts === undefined)
+ T(docB._conflicts === undefined);
+ };
+ }
+ };
+
+ var test;
+ for(test in repTests) {
+ if(repTests[test].init) {
+ repTests[test].init(dbA, dbB);
+ }
+ }
+
+ T(CouchDB.replicate(A, B).ok);
+
+ for(test in repTests) {
+ if(repTests[test].afterAB1) repTests[test].afterAB1(dbA, dbB);
+ }
+
+ T(CouchDB.replicate(B, A).ok);
+
+ for(test in repTests) {
+ if(repTests[test].afterBA1) repTests[test].afterBA1(dbA, dbB);
+ }
+
+ T(CouchDB.replicate(A, B).ok);
+
+ for(test in repTests) {
+ if(repTests[test].afterAB2) repTests[test].afterAB2(dbA, dbB);
+ }
+
+ T(CouchDB.replicate(B, A).ok);
+
+ for(test in repTests) {
+ if(repTests[test].afterBA2) repTests[test].afterBA2(dbA, dbB);
+ }
+
+ }
+};
Propchange: couchdb/trunk/share/www/script/test/replication.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/security_validation.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/security_validation.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/security_validation.js (added)
+++ couchdb/trunk/share/www/script/test/security_validation.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,154 @@
+// Licensed 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.
+
+couchTests.security_validation = function(debug) {
+ // This tests couchdb's security and validation features. This does
+ // not test authentication, except to use test authentication code made
+ // specifically for this testing. It is a WWWW-Authenticate scheme named
+ // X-Couch-Test-Auth, and the user names and passwords are hard coded
+ // on the server-side.
+ //
+ // We could have used Basic authentication, however the XMLHttpRequest
+ // implementation for Firefox and Safari, and probably other browsers are
+ // broken (Firefox always prompts the user on 401 failures, Safari gives
+ // odd security errors when using different name/passwords, perhaps due
+ // to cross site scripting prevention). These problems essentially make Basic
+ // authentication testing in the browser impossible. But while hard to
+ // test automated in the browser, Basic auth may still useful for real
+ // world use where these bugs/behaviors don't matter.
+ //
+ // So for testing purposes we are using this custom X-Couch-Test-Auth.
+ // It's identical to Basic auth, except it doesn't even base64 encode
+ // the "username:password" string, it's sent completely plain text.
+ // Firefox and Safari both deal with this correctly (which is to say
+ // they correctly do nothing special).
+
+
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ run_on_modified_server(
+ [{section: "httpd",
+ key: "authentication_handler",
+ value: "{couch_httpd, special_test_authentication_handler}"},
+ {section:"httpd",
+ key: "WWW-Authenticate",
+ value: "X-Couch-Test-Auth"}],
+
+ function () {
+
+ // try saving document usin the wrong credentials
+ var wrongPasswordDb = new CouchDB("test_suite_db",
+ {"WWW-Authenticate": "X-Couch-Test-Auth Damien Katz:foo"}
+ );
+
+ try {
+ wrongPasswordDb.save({foo:1,author:"Damien Katz"});
+ T(false && "Can't get here. Should have thrown an error 1");
+ } catch (e) {
+ T(e.error == "unauthorized");
+ T(wrongPasswordDb.last_req.status == 401);
+ }
+
+
+ // Create the design doc that will run custom validation code
+ var designDoc = {
+ _id:"_design/test",
+ language: "javascript",
+ validate_doc_update: "(" + (function (newDoc, oldDoc, userCtx) {
+ // docs should have an author field.
+ if (!newDoc._deleted && !newDoc.author) {
+ throw {forbidden:
+ "Documents must have an author field"};
+ }
+ if (oldDoc && oldDoc.author != userCtx.name) {
+ throw {unauthorized:
+ "You are not the author of this document. You jerk."};
+ }
+ }).toString() + ")"
+ }
+
+ // Save a document normally
+ var userDb = new CouchDB("test_suite_db",
+ {"WWW-Authenticate": "X-Couch-Test-Auth Damien Katz:pecan pie"}
+ );
+
+ T(userDb.save({_id:"testdoc", foo:1, author:"Damien Katz"}).ok);
+
+ // Attempt to save the design as a non-admin
+ try {
+ userDb.save(designDoc);
+ T(false && "Can't get here. Should have thrown an error on design doc");
+ } catch (e) {
+ T(e.error == "unauthorized");
+ T(userDb.last_req.status == 401);
+ }
+
+ // add user as admin
+ db.setAdmins(["Damien Katz"]);
+
+ T(userDb.save(designDoc).ok);
+
+ // update the document
+ var doc = userDb.open("testdoc");
+ doc.foo=2;
+ T(userDb.save(doc).ok);
+
+ // Save a document that's missing an author field.
+ try {
+ userDb.save({foo:1});
+ T(false && "Can't get here. Should have thrown an error 2");
+ } catch (e) {
+ T(e.error == "forbidden");
+ T(userDb.last_req.status == 403);
+ }
+
+ // Now attempt to update the document as a different user, Jan
+ var user2Db = new CouchDB("test_suite_db",
+ {"WWW-Authenticate": "X-Couch-Test-Auth Jan Lehnardt:apple"}
+ );
+
+ var doc = user2Db.open("testdoc");
+ doc.foo=3;
+ try {
+ user2Db.save(doc);
+ T(false && "Can't get here. Should have thrown an error 3");
+ } catch (e) {
+ T(e.error == "unauthorized");
+ T(user2Db.last_req.status == 401);
+ }
+
+ // Now have Damien change the author to Jan
+ doc = userDb.open("testdoc");
+ doc.author="Jan Lehnardt";
+ T(userDb.save(doc).ok);
+
+ // Now update the document as Jan
+ doc = user2Db.open("testdoc");
+ doc.foo = 3;
+ T(user2Db.save(doc).ok);
+
+ // Damien can't delete it
+ try {
+ userDb.deleteDoc(doc);
+ T(false && "Can't get here. Should have thrown an error 4");
+ } catch (e) {
+ T(e.error == "unauthorized");
+ T(userDb.last_req.status == 401);
+ }
+
+ // Now delete document
+ T(user2Db.deleteDoc(doc).ok);
+ });
+};
Propchange: couchdb/trunk/share/www/script/test/security_validation.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/show_documents.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/show_documents.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/show_documents.js (added)
+++ couchdb/trunk/share/www/script/test/show_documents.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,282 @@
+// Licensed 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.
+
+
+couchTests.show_documents = function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ var designDoc = {
+ _id:"_design/template",
+ language: "javascript",
+ shows: {
+ "hello" : stringFun(function(doc) {
+ if (doc) {
+ return "Hello World";
+ } else {
+ return "Empty World";
+ }
+ }),
+ "just-name" : stringFun(function(doc, req) {
+ return {
+ body : "Just " + doc.name
+ };
+ }),
+ "req-info" : stringFun(function(doc, req) {
+ return {
+ json : req
+ }
+ }),
+ "xml-type" : stringFun(function(doc, req) {
+ return {
+ "headers" : {
+ "Content-Type" : "application/xml"
+ },
+ "body" : new XML('<xml><node foo="bar"/></xml>')
+ }
+ }),
+ "no-set-etag" : stringFun(function(doc, req) {
+ return {
+ headers : {
+ "Etag" : "skipped"
+ },
+ "body" : "something"
+ }
+ }),
+ "accept-switch" : stringFun(function(doc, req) {
+ if (req.headers["Accept"].match(/image/)) {
+ return {
+ // a 16x16 px version of the CouchDB logo
+ "base64" :
+["iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAsV",
+"BMVEUAAAD////////////////////////5ur3rEBn////////////////wDBL/",
+"AADuBAe9EB3IEBz/7+//X1/qBQn2AgP/f3/ilpzsDxfpChDtDhXeCA76AQH/v7",
+"/84eLyWV/uc3bJPEf/Dw/uw8bRWmP1h4zxSlD6YGHuQ0f6g4XyQkXvCA36MDH6",
+"wMH/z8/yAwX64ODeh47BHiv/Ly/20dLQLTj98PDXWmP/Pz//39/wGyJ7Iy9JAA",
+"AADHRSTlMAbw8vf08/bz+Pv19jK/W3AAAAg0lEQVR4Xp3LRQ4DQRBD0QqTm4Y5",
+"zMxw/4OleiJlHeUtv2X6RbNO1Uqj9g0RMCuQO0vBIg4vMFeOpCWIWmDOw82fZx",
+"vaND1c8OG4vrdOqD8YwgpDYDxRgkSm5rwu0nQVBJuMg++pLXZyr5jnc1BaH4GT",
+"LvEliY253nA3pVhQqdPt0f/erJkMGMB8xucAAAAASUVORK5CYII="].join(''),
+ headers : {
+ "Content-Type" : "image/png",
+ "Vary" : "Accept" // we set this for proxy caches
+ }
+ };
+ } else {
+ return {
+ "body" : "accepting text requests",
+ headers : {
+ "Content-Type" : "text/html",
+ "Vary" : "Accept"
+ }
+ };
+ }
+ }),
+ "respondWith" : stringFun(function(doc, req) {
+ registerType("foo", "application/foo","application/x-foo");
+ return respondWith(req, {
+ html : function() {
+ return {
+ body:"Ha ha, you said \"" + doc.word + "\"."
+ };
+ },
+ xml : function() {
+ var xml = new XML('<xml><node/></xml>');
+ // Becase Safari can't stand to see that dastardly
+ // E4X outside of a string. Outside of tests you
+ // can just use E4X literals.
+ this.eval('xml.node.@foo = doc.word');
+ return {
+ body: xml
+ };
+ },
+ foo : function() {
+ return {
+ body: "foofoo"
+ };
+ },
+ fallback : "html"
+ });
+ })
+ }
+ };
+ T(db.save(designDoc).ok);
+
+ var doc = {"word":"plankton", "name":"Rusty"}
+ var resp = db.save(doc);
+ T(resp.ok);
+ var docid = resp.id;
+
+ // show error
+ var xhr = CouchDB.request("GET", "/test_suite_db/_show/");
+ T(xhr.status == 404);
+ T(JSON.parse(xhr.responseText).reason == "Invalid path.");
+
+ // hello template world
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/hello/"+docid);
+ T(xhr.responseText == "Hello World");
+
+ // hello template world (no docid)
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/hello");
+ T(xhr.responseText == "Empty World");
+
+
+ // show with doc
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid);
+ T(xhr.responseText == "Just Rusty");
+
+ // show with missing doc
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/missingdoc");
+ T(xhr.status == 404);
+ var resp = JSON.parse(xhr.responseText);
+ T(resp.error == "not_found");
+ T(resp.reason == "missing");
+
+ // show with missing func
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/missing/"+docid);
+ T(xhr.status == 404);
+
+ // missing design doc
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/missingdoc/just-name/"+docid);
+ T(xhr.status == 404);
+ var resp = JSON.parse(xhr.responseText);
+ T(resp.error == "not_found");
+
+ // query parameters
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/req-info/"+docid+"?foo=bar", {
+ headers: {
+ "Accept": "text/html;text/plain;*/*",
+ "X-Foo" : "bar"
+ }
+ });
+ var resp = JSON.parse(xhr.responseText);
+ T(equals(resp.headers["X-Foo"], "bar"));
+ T(equals(resp.query, {foo:"bar"}));
+ T(equals(resp.verb, "GET"));
+ T(equals(resp.path[4], docid));
+ T(equals(resp.info.db_name, "test_suite_db"));
+
+ // returning a content-type
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/xml-type/"+docid);
+ T("application/xml" == xhr.getResponseHeader("Content-Type"));
+ T("Accept" == xhr.getResponseHeader("Vary"));
+
+ // accept header switching
+ // different mime has different etag
+
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/accept-switch/"+docid, {
+ headers: {"Accept": "text/html;text/plain;*/*"}
+ });
+ T("text/html" == xhr.getResponseHeader("Content-Type"));
+ T("Accept" == xhr.getResponseHeader("Vary"));
+ var etag = xhr.getResponseHeader("etag");
+
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/accept-switch/"+docid, {
+ headers: {"Accept": "image/png;*/*"}
+ });
+ T(xhr.responseText.match(/PNG/))
+ T("image/png" == xhr.getResponseHeader("Content-Type"));
+ var etag2 = xhr.getResponseHeader("etag");
+ T(etag2 != etag);
+
+ // proper etags
+ // show with doc
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid);
+ // extract the ETag header values
+ etag = xhr.getResponseHeader("etag");
+ // get again with etag in request
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid, {
+ headers: {"if-none-match": etag}
+ });
+ // should be 304
+ T(xhr.status == 304);
+
+ // update the doc
+ doc.name = "Crusty";
+ resp = db.save(doc);
+ T(resp.ok);
+ // req with same etag
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid, {
+ headers: {"if-none-match": etag}
+ });
+ // status is 200
+ T(xhr.status == 200);
+
+ // get new etag and request again
+ etag = xhr.getResponseHeader("etag");
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid, {
+ headers: {"if-none-match": etag}
+ });
+ // should be 304
+ T(xhr.status == 304);
+
+ // update design doc (but not function)
+ designDoc.isChanged = true;
+ T(db.save(designDoc).ok);
+
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid, {
+ headers: {"if-none-match": etag}
+ });
+ // should be 304
+ T(xhr.status == 304);
+
+ // update design doc function
+ designDoc.shows["just-name"] = (function(doc, req) {
+ return {
+ body : "Just old " + doc.name
+ };
+ }).toString();
+ T(db.save(designDoc).ok);
+
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid, {
+ headers: {"if-none-match": etag}
+ });
+ // status is 200
+ T(xhr.status == 200);
+
+
+ // JS can't set etag
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/no-set-etag/"+docid);
+ // extract the ETag header values
+ etag = xhr.getResponseHeader("etag");
+ T(etag != "skipped")
+
+ // test the respondWith mime matcher
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/respondWith/"+docid, {
+ headers: {
+ "Accept": 'text/html,application/atom+xml; q=0.9'
+ }
+ });
+ T(xhr.getResponseHeader("Content-Type") == "text/html");
+ T(xhr.responseText == "Ha ha, you said \"plankton\".");
+
+ // now with xml
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/respondWith/"+docid, {
+ headers: {
+ "Accept": 'application/xml'
+ }
+ });
+ T(xhr.getResponseHeader("Content-Type") == "application/xml");
+ T(xhr.responseText.match(/node/));
+ T(xhr.responseText.match(/plankton/));
+
+ // registering types works
+ xhr = CouchDB.request("GET", "/test_suite_db/_show/template/respondWith/"+docid, {
+ headers: {
+ "Accept": "application/x-foo"
+ }
+ });
+ T(xhr.getResponseHeader("Content-Type") == "application/x-foo");
+ T(xhr.responseText.match(/foofoo/));
+};
Propchange: couchdb/trunk/share/www/script/test/show_documents.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/utf8.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/utf8.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/utf8.js (added)
+++ couchdb/trunk/share/www/script/test/utf8.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,41 @@
+// Licensed 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.
+
+couchTests.utf8 = function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ var texts = [];
+
+ texts[0] = "1. Ascii: hello"
+ texts[1] = "2. Russian: Ðа беÑÐµÐ³Ñ Ð¿ÑÑÑÑннÑÑ
волн"
+ texts[2] = "3. Math: â® Eâ
da = Q, n â â, â f(i) = â g(i),"
+ texts[3] = "4. Geek: STARGÎÌTE SG-1"
+ texts[4] = "5. Braille: â¡â â §â â ¼â â â¡â â â ⠹⠰â â¡£â â "
+
+ // check that we can save a reload with full fidelity
+ for (var i=0; i<texts.length; i++) {
+ T(db.save({_id:i.toString(), text:texts[i]}).ok);
+ }
+
+ for (var i=0; i<texts.length; i++) {
+ T(db.open(i.toString()).text == texts[i]);
+ }
+
+ // check that views and key collation don't blow up
+ var rows = db.query(function(doc) { emit(null, doc.text) }).rows;
+ for (var i=0; i<texts.length; i++) {
+ T(rows[i].value == texts[i]);
+ }
+};
Propchange: couchdb/trunk/share/www/script/test/utf8.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/uuids.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/uuids.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/uuids.js (added)
+++ couchdb/trunk/share/www/script/test/uuids.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,62 @@
+// Licensed 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.
+
+couchTests.uuids = function(debug) {
+ var testHashBustingHeaders = function(xhr) {
+ T(xhr.getResponseHeader("Cache-Control").match(/no-cache/));
+ T(xhr.getResponseHeader("Pragma") == "no-cache");
+
+ var currentTime = new Date();
+ var expiresHeader = Date.parse(xhr.getResponseHeader("Expires"));
+ var dateHeader = Date.parse(xhr.getResponseHeader("Date"));
+
+ T(expiresHeader < currentTime);
+ T(currentTime - dateHeader < 3000);
+ };
+
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ // a single UUID without an explicit count
+ var xhr = CouchDB.request("GET", "/_uuids");
+ T(xhr.status == 200);
+ var result = JSON.parse(xhr.responseText);
+ T(result.uuids.length == 1);
+ var first = result.uuids[0];
+ testHashBustingHeaders(xhr);
+
+ // a single UUID with an explicit count
+ xhr = CouchDB.request("GET", "/_uuids?count=1");
+ T(xhr.status == 200);
+ result = JSON.parse(xhr.responseText);
+ T(result.uuids.length == 1);
+ var second = result.uuids[0];
+ T(first != second);
+
+ // no collisions with 1,000 UUIDs
+ xhr = CouchDB.request("GET", "/_uuids?count=1000");
+ T(xhr.status == 200);
+ result = JSON.parse(xhr.responseText);
+ T( result.uuids.length == 1000 );
+ var seen = {};
+ for(var i in result.uuids) {
+ var id = result.uuids[i];
+ T(seen[id] === undefined);
+ seen[id] = 1;
+ }
+
+ // ensure we return a 405 on POST
+ xhr = CouchDB.request("POST", "/_uuids?count=1000");
+ T(xhr.status == 405);
+};
Propchange: couchdb/trunk/share/www/script/test/uuids.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/view_collation.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/view_collation.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/view_collation.js (added)
+++ couchdb/trunk/share/www/script/test/view_collation.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,88 @@
+// Licensed 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.
+
+couchTests.view_collation = function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ // NOTE, the values are already in their correct sort order. Consider this
+ // a specification of collation of json types.
+
+ var values = [];
+
+ // special values sort before all other types
+ values.push(null);
+ values.push(false);
+ values.push(true);
+
+ // then numbers
+ values.push(1);
+ values.push(2);
+ values.push(3.0);
+ values.push(4);
+
+ // then text, case sensitive
+ values.push("a");
+ values.push("A");
+ values.push("aa");
+ values.push("b");
+ values.push("B");
+ values.push("ba");
+ values.push("bb");
+
+ // then arrays. compared element by element until different.
+ // Longer arrays sort after their prefixes
+ values.push(["a"]);
+ values.push(["b"]);
+ values.push(["b","c"]);
+ values.push(["b","c", "a"]);
+ values.push(["b","d"]);
+ values.push(["b","d", "e"]);
+
+ // then object, compares each key value in the list until different.
+ // larger objects sort after their subset objects.
+ values.push({a:1});
+ values.push({a:2});
+ values.push({b:1});
+ values.push({b:2});
+ values.push({b:2, a:1}); // Member order does matter for collation.
+ // CouchDB preserves member order
+ // but doesn't require that clients will.
+ // (this test might fail if used with a js engine
+ // that doesn't preserve order)
+ values.push({b:2, c:2});
+
+ for (var i=0; i<values.length; i++) {
+ db.save({_id:(i).toString(), foo:values[i]});
+ }
+
+ var queryFun = function(doc) { emit(doc.foo, null); };
+ var rows = db.query(queryFun).rows;
+ for (i=0; i<values.length; i++) {
+ T(equals(rows[i].key, values[i]));
+ }
+
+ // everything has collated correctly. Now to check the descending output
+ rows = db.query(queryFun, null, {descending: true}).rows;
+ for (i=0; i<values.length; i++) {
+ T(equals(rows[i].key, values[values.length - 1 -i]));
+ }
+
+ // now check the key query args
+ for (i=1; i<values.length; i++) {
+ var queryOptions = {key:values[i]};
+ rows = db.query(queryFun, null, queryOptions).rows;
+ T(rows.length == 1 && equals(rows[0].key, values[i]));
+ }
+};
Propchange: couchdb/trunk/share/www/script/test/view_collation.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/view_conflicts.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/view_conflicts.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/view_conflicts.js (added)
+++ couchdb/trunk/share/www/script/test/view_conflicts.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,49 @@
+// Licensed 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.
+
+couchTests.view_conflicts = function(debug) {
+ var dbA = new CouchDB("test_suite_db_a");
+ dbA.deleteDb();
+ dbA.createDb();
+ var dbB = new CouchDB("test_suite_db_b");
+ dbB.deleteDb();
+ dbB.createDb();
+ if (debug) debugger;
+
+ var docA = {_id: "foo", bar: 42};
+ T(dbA.save(docA).ok);
+ CouchDB.replicate(dbA.name, dbB.name);
+
+ var docB = dbB.open("foo");
+ docB.bar = 43;
+ dbB.save(docB);
+ docA.bar = 41;
+ dbA.save(docA);
+ CouchDB.replicate(dbA.name, dbB.name);
+
+ var doc = dbB.open("foo", {conflicts: true});
+ T(doc._conflicts.length == 1);
+ var conflictRev = doc._conflicts[0];
+ if (doc.bar == 41) { // A won
+ T(conflictRev == docB._rev);
+ } else { // B won
+ T(doc.bar == 43);
+ T(conflictRev == docA._rev);
+ }
+
+ var results = dbB.query(function(doc) {
+ if (doc._conflicts) {
+ emit(doc._id, doc._conflicts);
+ }
+ });
+ T(results.rows[0].value[0] == conflictRev);
+};
Propchange: couchdb/trunk/share/www/script/test/view_conflicts.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/view_errors.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/view_errors.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/view_errors.js (added)
+++ couchdb/trunk/share/www/script/test/view_errors.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,43 @@
+// Licensed 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.
+
+couchTests.view_errors = function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ var doc = {integer: 1, string: "1", array: [1, 2, 3]};
+ T(db.save(doc).ok);
+
+ // emitting a key value that is undefined should result in that row not
+ // being included in the view results
+ var results = db.query(function(doc) {
+ emit(doc.undef, null);
+ });
+ T(results.total_rows == 0);
+
+ // if a view function throws an exception, its results are not included in
+ // the view index, but the view does not itself raise an error
+ var results = db.query(function(doc) {
+ doc.undef(); // throws an error
+ });
+ T(results.total_rows == 0);
+
+ // if a view function includes an undefined value in the emitted key or
+ // value, an error is logged and the result is not included in the view
+ // index, and the view itself does not raise an error
+ var results = db.query(function(doc) {
+ emit([doc._id, doc.undef], null);
+ });
+ T(results.total_rows == 0);
+};
Propchange: couchdb/trunk/share/www/script/test/view_errors.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/view_include_docs.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/view_include_docs.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/view_include_docs.js (added)
+++ couchdb/trunk/share/www/script/test/view_include_docs.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,111 @@
+// Licensed 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.
+
+couchTests.view_include_docs = function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ var docs = makeDocs(0, 100);
+ T(db.bulkSave(docs).ok);
+
+ var designDoc = {
+ _id:"_design/test",
+ language: "javascript",
+ views: {
+ all_docs: {
+ map: "function(doc) { emit(doc.integer, doc.string) }"
+ },
+ with_prev: {
+ map: "function(doc){if(doc.prev) emit(doc._id,{'_rev':doc.prev}); else emit(doc._id,{'_rev':doc._rev});}"
+ },
+ summate: {
+ map:"function (doc) {emit(doc.integer, doc.integer)};",
+ reduce:"function (keys, values) { return sum(values); };"
+ }
+ }
+ }
+ T(db.save(designDoc).ok);
+
+ var resp = db.view('test/all_docs', {include_docs: true, limit: 2});
+ T(resp.rows.length == 2);
+ T(resp.rows[0].id == "0");
+ T(resp.rows[0].doc._id == "0");
+ T(resp.rows[1].id == "1");
+ T(resp.rows[1].doc._id == "1");
+
+ resp = db.view('test/all_docs', {include_docs: true}, [29, 74]);
+ T(resp.rows.length == 2);
+ T(resp.rows[0].doc._id == "29");
+ T(resp.rows[1].doc.integer == 74);
+
+ resp = db.allDocs({limit: 2, skip: 1, include_docs: true});
+ T(resp.rows.length == 2);
+ T(resp.rows[0].doc.integer == 1);
+ T(resp.rows[1].doc.integer == 10);
+
+ resp = db.allDocs({include_docs: true}, ['not_a_doc']);
+ T(resp.rows.length == 1);
+ T(!resp.rows[0].doc);
+
+ resp = db.allDocs({include_docs: true}, ["1", "foo"]);
+ T(resp.rows.length == 2);
+ T(resp.rows[0].doc.integer == 1);
+ T(!resp.rows[1].doc);
+
+ resp = db.allDocs({include_docs: true, limit: 0});
+ T(resp.rows.length == 0);
+
+ // No reduce support
+ try {
+ resp = db.view('test/summate', {include_docs: true});
+ alert(JSON.stringify(resp));
+ T(0==1);
+ } catch (e) {
+ T(e.error == 'query_parse_error');
+ }
+
+ // Reduce support when reduce=false
+ resp = db.view('test/summate', {reduce: false, include_docs: true});
+ T(resp.rows.length == 100);
+
+ // Check emitted _rev controls things
+ resp = db.allDocs({include_docs: true}, ["0"]);
+ var before = resp.rows[0].doc;
+ var after = db.open("0");
+ after.integer = 100
+ after.prev = after._rev;
+ db.save(after);
+ after = db.open("0");
+ T(after._rev != after.prev);
+ T(after.integer == 100);
+
+ // should emit the previous revision
+ resp = db.view("test/with_prev", {include_docs: true}, ["0"]);
+ T(resp.rows[0].doc._id == "0");
+ T(resp.rows[0].doc._rev == before._rev);
+ T(!resp.rows[0].doc.prev);
+ T(resp.rows[0].doc.integer == 0);
+
+ var xhr = CouchDB.request("POST", "/test_suite_db/_compact");
+ T(xhr.status == 202)
+ while (db.info().compact_running) {}
+
+ resp = db.view("test/with_prev", {include_docs: true}, ["0", "23"]);
+ T(resp.rows.length == 2);
+ T(resp.rows[0].key == "0");
+ T(resp.rows[0].id == "0");
+ T(!resp.rows[0].doc);
+ T(resp.rows[0].error == "missing");
+ T(resp.rows[1].doc.integer == 23);
+};
Propchange: couchdb/trunk/share/www/script/test/view_include_docs.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/view_multi_key_all_docs.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/view_multi_key_all_docs.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/view_multi_key_all_docs.js (added)
+++ couchdb/trunk/share/www/script/test/view_multi_key_all_docs.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,54 @@
+// Licensed 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.
+
+couchTests.view_multi_key_all_docs = function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ var docs = makeDocs(0, 100);
+ T(db.bulkSave(docs).ok);
+
+ var keys = ["10","15","30","37","50"];
+ var rows = db.allDocs({},keys).rows;
+ T(rows.length == keys.length);
+ for(var i=0; i<rows.length; i++)
+ T(rows[i].id == keys[i]);
+
+ rows = db.allDocs({limit: 1}, keys).rows;
+ T(rows.length == 1);
+ T(rows[0].id == keys[0]);
+
+ rows = db.allDocs({skip: 2}, keys).rows;
+ T(rows.length == 3);
+ for(var i=0; i<rows.length; i++)
+ T(rows[i].id == keys[i+2]);
+
+ rows = db.allDocs({descending: "true"}, keys).rows;
+ T(rows.length == keys.length);
+ for(var i=0; i<rows.length; i++)
+ T(rows[i].id == keys[keys.length-i-1]);
+
+ rows = db.allDocs({descending: "true", skip: 3, limit:1}, keys).rows;
+ T(rows.length == 1);
+ T(rows[0].id == keys[1]);
+
+ // Check we get invalid rows when the key doesn't exist
+ rows = db.allDocs({}, [1, "i_dont_exist", "0"]).rows;
+ T(rows.length == 3);
+ T(rows[0].error == "not_found");
+ T(!rows[0].id);
+ T(rows[1].error == "not_found");
+ T(!rows[1].id);
+ T(rows[2].id == rows[2].key && rows[2].key == "0");
+};
Propchange: couchdb/trunk/share/www/script/test/view_multi_key_all_docs.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/view_multi_key_design.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/view_multi_key_design.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/view_multi_key_design.js (added)
+++ couchdb/trunk/share/www/script/test/view_multi_key_design.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,138 @@
+// Licensed 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.
+
+couchTests.view_multi_key_design = function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ var docs = makeDocs(0, 100);
+ T(db.bulkSave(docs).ok);
+
+ var designDoc = {
+ _id:"_design/test",
+ language: "javascript",
+ views: {
+ all_docs: {
+ map: "function(doc) { emit(doc.integer, doc.string) }"
+ },
+ multi_emit: {
+ map: "function(doc) {for(var i = 0 ; i < 3 ; i++) { emit(i, doc.integer) ; } }"
+ },
+ summate: {
+ map:"function (doc) {emit(doc.integer, doc.integer)};",
+ reduce:"function (keys, values) { return sum(values); };"
+ }
+ }
+ }
+ T(db.save(designDoc).ok);
+
+ // Test that missing keys work too
+ var keys = [101,30,15,37,50]
+ var reduce = db.view("test/summate",{group:true},keys).rows;
+ T(reduce.length == keys.length-1); // 101 is missing
+ for(var i=0; i<reduce.length; i++) {
+ T(keys.indexOf(reduce[i].key) != -1);
+ T(reduce[i].key == reduce[i].value);
+ }
+
+ // First, the goods:
+ var keys = [10,15,30,37,50];
+ var rows = db.view("test/all_docs",{},keys).rows;
+ for(var i=0; i<rows.length; i++) {
+ T(keys.indexOf(rows[i].key) != -1);
+ T(rows[i].key == rows[i].value);
+ }
+
+ var reduce = db.view("test/summate",{group:true},keys).rows;
+ T(reduce.length == keys.length);
+ for(var i=0; i<reduce.length; i++) {
+ T(keys.indexOf(reduce[i].key) != -1);
+ T(reduce[i].key == reduce[i].value);
+ }
+
+ // Test that invalid parameter combinations get rejected
+ var badargs = [{startkey:0}, {endkey:0}, {key: 0}, {group_level: 2}];
+ for(var i in badargs)
+ {
+ try {
+ db.view("test/all_docs",badargs[i],keys);
+ T(0==1);
+ } catch (e) {
+ T(e.error == "query_parse_error");
+ }
+ }
+
+ try {
+ db.view("test/summate",{},keys);
+ T(0==1);
+ } catch (e) {
+ T(e.error == "query_parse_error");
+ }
+
+ // Test that a map & reduce containing func support keys when reduce=false
+ resp = db.view("test/summate", {reduce: false}, keys);
+ T(resp.rows.length == 5);
+
+ // Check that limiting by startkey_docid and endkey_docid get applied
+ // as expected.
+ var curr = db.view("test/multi_emit", {startkey_docid: 21, endkey_docid: 23}, [0, 2]).rows;
+ var exp_key = [ 0, 0, 0, 2, 2, 2] ;
+ var exp_val = [21, 22, 23, 21, 22, 23] ;
+ T(curr.length == 6);
+ for( var i = 0 ; i < 6 ; i++)
+ {
+ T(curr[i].key == exp_key[i]);
+ T(curr[i].value == exp_val[i]);
+ }
+
+ // Check limit works
+ curr = db.view("test/all_docs", {limit: 1}, keys).rows;
+ T(curr.length == 1);
+ T(curr[0].key == 10);
+
+ // Check offset works
+ curr = db.view("test/multi_emit", {skip: 1}, [0]).rows;
+ T(curr.length == 99);
+ T(curr[0].value == 1);
+
+ // Check that dir works
+ curr = db.view("test/multi_emit", {descending: "true"}, [1]).rows;
+ T(curr.length == 100);
+ T(curr[0].value == 99);
+ T(curr[99].value == 0);
+
+ // Check a couple combinations
+ curr = db.view("test/multi_emit", {descending: "true", skip: 3, limit: 2}, [2]).rows;
+ T(curr.length, 2);
+ T(curr[0].value == 96);
+ T(curr[1].value == 95);
+
+ curr = db.view("test/multi_emit", {skip: 2, limit: 3, startkey_docid: "13"}, [0]).rows;
+ T(curr.length == 3);
+ T(curr[0].value == 15);
+ T(curr[1].value == 16);
+ T(curr[2].value == 17);
+
+ curr = db.view("test/multi_emit",
+ {skip: 1, limit: 5, startkey_docid: "25", endkey_docid: "27"}, [1]).rows;
+ T(curr.length == 2);
+ T(curr[0].value == 26);
+ T(curr[1].value == 27);
+
+ curr = db.view("test/multi_emit",
+ {skip: 1, limit: 5, startkey_docid: "28", endkey_docid: "26", descending: "true"}, [1]).rows;
+ T(curr.length == 2);
+ T(curr[0].value == 27);
+ T(curr[1].value == 26);
+};
Propchange: couchdb/trunk/share/www/script/test/view_multi_key_design.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/view_multi_key_temp.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/view_multi_key_temp.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/view_multi_key_temp.js (added)
+++ couchdb/trunk/share/www/script/test/view_multi_key_temp.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,37 @@
+// Licensed 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.
+
+couchTests.view_multi_key_temp = function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ var docs = makeDocs(0, 100);
+ T(db.bulkSave(docs).ok);
+
+ var queryFun = function(doc) { emit(doc.integer, doc.integer) };
+ var reduceFun = function (keys, values) { return sum(values); };
+
+ var keys = [10,15,30,37,50];
+ var rows = db.query(queryFun, null, {}, keys).rows;
+ for(var i=0; i<rows.length; i++) {
+ T(keys.indexOf(rows[i].key) != -1);
+ T(rows[i].key == rows[i].value);
+ }
+
+ var reduce = db.query(queryFun, reduceFun, {group:true}, keys).rows;
+ for(var i=0; i<reduce.length; i++) {
+ T(keys.indexOf(reduce[i].key) != -1);
+ T(reduce[i].key == reduce[i].value);
+ }
+};
Propchange: couchdb/trunk/share/www/script/test/view_multi_key_temp.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/view_pagination.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/view_pagination.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/view_pagination.js (added)
+++ couchdb/trunk/share/www/script/test/view_pagination.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,122 @@
+// Licensed 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.
+
+couchTests.view_pagination = function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ var docs = makeDocs(0, 100);
+ T(db.bulkSave(docs).ok);
+
+ var queryFun = function(doc) { emit(doc.integer, null) };
+ var i;
+
+ // page through the view ascending
+ for (i = 0; i < docs.length; i += 10) {
+ var queryResults = db.query(queryFun, null, {
+ startkey: i,
+ startkey_docid: i,
+ limit: 10
+ });
+ T(queryResults.rows.length == 10)
+ T(queryResults.total_rows == docs.length)
+ T(queryResults.offset == i)
+ var j;
+ for (j = 0; j < 10;j++) {
+ T(queryResults.rows[j].key == i + j);
+ }
+ }
+
+ // page through the view descending
+ for (i = docs.length - 1; i >= 0; i -= 10) {
+ var queryResults = db.query(queryFun, null, {
+ startkey: i,
+ startkey_docid: i,
+ descending: true,
+ limit: 10
+ });
+ T(queryResults.rows.length == 10)
+ T(queryResults.total_rows == docs.length)
+ T(queryResults.offset == docs.length - i - 1)
+ var j;
+ for (j = 0; j < 10; j++) {
+ T(queryResults.rows[j].key == i - j);
+ }
+ }
+
+ // ignore decending=false. CouchDB should just ignore that.
+ for (i = 0; i < docs.length; i += 10) {
+ var queryResults = db.query(queryFun, null, {
+ startkey: i,
+ startkey_docid: i,
+ descending: false,
+ limit: 10
+ });
+ T(queryResults.rows.length == 10)
+ T(queryResults.total_rows == docs.length)
+ T(queryResults.offset == i)
+ var j;
+ for (j = 0; j < 10;j++) {
+ T(queryResults.rows[j].key == i + j);
+ }
+ }
+
+ // test endkey_docid
+ var queryResults = db.query(function(doc) { emit(null, null);}, null, {
+ startkey: null,
+ startkey_docid: 1,
+ endkey: null,
+ endkey_docid: 40
+ });
+
+ T(queryResults.rows.length == 35)
+ T(queryResults.total_rows == docs.length)
+ T(queryResults.offset == 1)
+ T(queryResults.rows[0].id == "1");
+ T(queryResults.rows[1].id == "10");
+ T(queryResults.rows[2].id == "11");
+ T(queryResults.rows[3].id == "12");
+ T(queryResults.rows[4].id == "13");
+ T(queryResults.rows[5].id == "14");
+ T(queryResults.rows[6].id == "15");
+ T(queryResults.rows[7].id == "16");
+ T(queryResults.rows[8].id == "17");
+ T(queryResults.rows[9].id == "18");
+ T(queryResults.rows[10].id == "19");
+ T(queryResults.rows[11].id == "2");
+ T(queryResults.rows[12].id == "20");
+ T(queryResults.rows[13].id == "21");
+ T(queryResults.rows[14].id == "22");
+ T(queryResults.rows[15].id == "23");
+ T(queryResults.rows[16].id == "24");
+ T(queryResults.rows[17].id == "25");
+ T(queryResults.rows[18].id == "26");
+ T(queryResults.rows[19].id == "27");
+ T(queryResults.rows[20].id == "28");
+ T(queryResults.rows[21].id == "29");
+ T(queryResults.rows[22].id == "3");
+ T(queryResults.rows[23].id == "30");
+ T(queryResults.rows[24].id == "31");
+ T(queryResults.rows[25].id == "32");
+ T(queryResults.rows[26].id == "33");
+ T(queryResults.rows[27].id == "34");
+ T(queryResults.rows[28].id == "35");
+ T(queryResults.rows[29].id == "36");
+ T(queryResults.rows[30].id == "37");
+ T(queryResults.rows[31].id == "38");
+ T(queryResults.rows[32].id == "39");
+ T(queryResults.rows[33].id == "4");
+ T(queryResults.rows[34].id == "40");
+
+ };
Propchange: couchdb/trunk/share/www/script/test/view_pagination.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/view_sandboxing.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/view_sandboxing.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/view_sandboxing.js (added)
+++ couchdb/trunk/share/www/script/test/view_sandboxing.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,52 @@
+// Licensed 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.
+
+couchTests.view_sandboxing = function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ var doc = {integer: 1, string: "1", array: [1, 2, 3]};
+ T(db.save(doc).ok);
+/*
+ // make sure that attempting to change the document throws an error
+ var results = db.query(function(doc) {
+ doc.integer = 2;
+ emit(null, doc);
+ });
+ T(results.total_rows == 0);
+
+ var results = db.query(function(doc) {
+ doc.array[0] = 0;
+ emit(null, doc);
+ });
+ T(results.total_rows == 0);
+*/
+ // make sure that a view cannot invoke interpreter internals such as the
+ // garbage collector
+ var results = db.query(function(doc) {
+ gc();
+ emit(null, doc);
+ });
+ T(results.total_rows == 0);
+
+ // make sure that a view cannot access the map_funs array defined used by
+ // the view server
+ var results = db.query(function(doc) { map_funs.push(1); emit(null, doc) });
+ T(results.total_rows == 0);
+
+ // make sure that a view cannot access the map_results array defined used by
+ // the view server
+ var results = db.query(function(doc) { map_results.push(1); emit(null, doc) });
+ T(results.total_rows == 0);
+};
Propchange: couchdb/trunk/share/www/script/test/view_sandboxing.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: couchdb/trunk/share/www/script/test/view_xml.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/view_xml.js?rev=744782&view=auto
==============================================================================
--- couchdb/trunk/share/www/script/test/view_xml.js (added)
+++ couchdb/trunk/share/www/script/test/view_xml.js Sun Feb 15 23:59:38 2009
@@ -0,0 +1,39 @@
+// Licensed 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.
+
+couchTests.view_xml = function(debug) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ if (debug) debugger;
+
+ db.save({content: "<doc><title id='xml'>Testing XML</title></doc>"});
+ db.save({content: "<doc><title id='e4x'>Testing E4X</title></doc>"});
+
+ var results = db.query(
+ "function(doc) {\n" +
+ " var xml = new XML(doc.content);\n" +
+ " emit(xml.title.text(), null);\n" +
+ "}");
+ T(results.total_rows == 2);
+ T(results.rows[0].key == "Testing E4X");
+ T(results.rows[1].key == "Testing XML");
+
+ var results = db.query(
+ "function(doc) {\n" +
+ " var xml = new XML(doc.content);\n" +
+ " emit(xml.title.@id, null);\n" +
+ "}");
+ T(results.total_rows == 2);
+ T(results.rows[0].key == "e4x");
+ T(results.rows[1].key == "xml");
+};
Propchange: couchdb/trunk/share/www/script/test/view_xml.js
------------------------------------------------------------------------------
svn:eol-style = native
Modified: couchdb/trunk/test/runner.sh
URL: http://svn.apache.org/viewvc/couchdb/trunk/test/runner.sh?rev=744782&r1=744781&r2=744782&view=diff
==============================================================================
--- couchdb/trunk/test/runner.sh (original)
+++ couchdb/trunk/test/runner.sh Sun Feb 15 23:59:38 2009
@@ -4,4 +4,4 @@
erl -noshell -pa ../src/couchdb -pa ../src/mochiweb -eval "runner:run()"
-cat ../share/www/script/couch.js ../share/www/script/couch_test_runner.js ../share/www/script/couch_tests.js test.js | ../src/couchdb/couchjs -
+cat ../share/www/script/couch.js ../share/www/script/couch_test_runner.js ../share/www/script/couch_tests.js ../share/www/script/test/* test.js | ../src/couchdb/couchjs -
Modified: couchdb/trunk/test/test.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/test/test.js?rev=744782&r1=744781&r2=744782&view=diff
==============================================================================
--- couchdb/trunk/test/test.js (original)
+++ couchdb/trunk/test/test.js Sun Feb 15 23:59:38 2009
@@ -194,14 +194,14 @@
function runAllTestsConsole() {
var numTests = 0;
var debug = false;
- for (var t in tests) {
+ for (var t in couchTests) {
p(t);
if (t == "utf8") {
p("We skip the utf8 test because it fails due to problems in couch_js.c");
p("Run the in-browser tests to verify utf8.\n");
} else {
numTests += 1;
- var testFun = tests[t];
+ var testFun = couchTests[t];
runTestConsole(testFun, debug);
}
}