http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a4893aa/share/www/script/test/view_conflicts.js ---------------------------------------------------------------------- diff --git a/share/www/script/test/view_conflicts.js b/share/www/script/test/view_conflicts.js deleted file mode 100644 index 96f97d5..0000000 --- a/share/www/script/test/view_conflicts.js +++ /dev/null @@ -1,49 +0,0 @@ -// 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", {"X-Couch-Full-Commit":"false"}); - dbA.deleteDb(); - dbA.createDb(); - var dbB = new CouchDB("test_suite_db_b", {"X-Couch-Full-Commit":"false"}); - 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); -};
http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a4893aa/share/www/script/test/view_errors.js ---------------------------------------------------------------------- diff --git a/share/www/script/test/view_errors.js b/share/www/script/test/view_errors.js deleted file mode 100644 index e8bd08e..0000000 --- a/share/www/script/test/view_errors.js +++ /dev/null @@ -1,189 +0,0 @@ -// 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", {"X-Couch-Full-Commit":"true"}); - db.deleteDb(); - db.createDb(); - if (debug) debugger; - - run_on_modified_server( - [{section: "couchdb", - key: "os_process_timeout", - value: "500"}], - function() { - 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 - // being included in the view results as null - var results = db.query(function(doc) { - emit(doc.undef, null); - }); - T(results.total_rows == 1); - T(results.rows[0].key == null); - - // 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, it is treated as null - var results = db.query(function(doc) { - emit([doc._id, doc.undef], null); - }); - T(results.total_rows == 1); - T(results.rows[0].key[1] == null); - - // querying a view with invalid params should give a resonable error message - var xhr = CouchDB.request("POST", "/test_suite_db/_temp_view?startkey=foo", { - headers: {"Content-Type": "application/json"}, - body: JSON.stringify({language: "javascript", - map : "function(doc){emit(doc.integer)}" - }) - }); - T(JSON.parse(xhr.responseText).error == "bad_request"); - - // content type must be json - var xhr = CouchDB.request("POST", "/test_suite_db/_temp_view", { - headers: {"Content-Type": "application/x-www-form-urlencoded"}, - body: JSON.stringify({language: "javascript", - map : "function(doc){}" - }) - }); - T(xhr.status == 415); - - var map = function (doc) {emit(doc.integer, doc.integer);}; - - try { - db.query(map, null, {group: true}); - T(0 == 1); - } catch(e) { - T(e.error == "query_parse_error"); - } - - var designDoc = { - _id:"_design/test", - language: "javascript", - views: { - "no_reduce": {map:"function(doc) {emit(doc._id, null);}"}, - "with_reduce": { - map:"function (doc) {emit(doc.integer, doc.integer)};", - reduce:"function (keys, values) { return sum(values); };"} - } - }; - T(db.save(designDoc).ok); - - var designDoc2 = { - _id:"_design/testbig", - language: "javascript", - views: { - "reduce_too_big" : { - map:"function (doc) {emit(doc.integer, doc.integer)};", - reduce:"function (keys, values) { var chars = []; for (var i=0; i < 1000; i++) {chars.push('wazzap');};return chars; };"} - } - }; - T(db.save(designDoc2).ok); - - try { - db.view("test/no_reduce", {group: true}); - T(0 == 1); - } catch(e) { - T(db.last_req.status == 400); - T(e.error == "query_parse_error"); - } - - try { - db.view("test/no_reduce", {group_level: 1}); - T(0 == 1); - } catch(e) { - T(db.last_req.status == 400); - T(e.error == "query_parse_error"); - } - - try { - db.view("test/no_reduce", {reduce: true}); - T(0 == 1); - } catch(e) { - T(db.last_req.status == 400); - T(e.error == "query_parse_error"); - } - - db.view("test/no_reduce", {reduce: false}); - TEquals(200, db.last_req.status, "reduce=false for map views (without" - + " group or group_level) is allowed"); - - try { - db.view("test/with_reduce", {group: true, reduce: false}); - T(0 == 1); - } catch(e) { - T(db.last_req.status == 400); - T(e.error == "query_parse_error"); - } - - try { - db.view("test/with_reduce", {group_level: 1, reduce: false}); - T(0 == 1); - } catch(e) { - T(db.last_req.status == 400); - T(e.error == "query_parse_error"); - } - - var designDoc3 = { - _id:"_design/infinite", - language: "javascript", - views: { - "infinite_loop" :{map:"function(doc) {while(true){emit(doc,doc);}};"} - } - }; - T(db.save(designDoc3).ok); - - try { - db.view("infinite/infinite_loop"); - T(0 == 1); - } catch(e) { - T(e.error == "os_process_error"); - } - - // Check error responses for invalid multi-get bodies. - var path = "/test_suite_db/_design/test/_view/no_reduce"; - var xhr = CouchDB.request("POST", path, {body: "[]"}); - T(xhr.status == 400); - result = JSON.parse(xhr.responseText); - T(result.error == "bad_request"); - T(result.reason == "Request body must be a JSON object"); - var data = "{\"keys\": 1}"; - xhr = CouchDB.request("POST", path, {body:data}); - T(xhr.status == 400); - result = JSON.parse(xhr.responseText); - T(result.error == "bad_request"); - T(result.reason == "`keys` member must be a array."); - - // if the reduce grows to fast, throw an overflow error - var path = "/test_suite_db/_design/testbig/_view/reduce_too_big"; - xhr = CouchDB.request("GET", path); - T(xhr.status == 500); - result = JSON.parse(xhr.responseText); - T(result.error == "reduce_overflow_error"); - - try { - db.query(function() {emit(null, null)}, null, {startkey: 2, endkey:1}); - T(0 == 1); - } catch(e) { - T(e.error == "query_parse_error"); - T(e.reason.match(/no rows can match/i)); - } - }); -}; http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a4893aa/share/www/script/test/view_include_docs.js ---------------------------------------------------------------------- diff --git a/share/www/script/test/view_include_docs.js b/share/www/script/test/view_include_docs.js deleted file mode 100644 index dab79b8..0000000 --- a/share/www/script/test/view_include_docs.js +++ /dev/null @@ -1,192 +0,0 @@ -// 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", {"X-Couch-Full-Commit":"false"}); - db.deleteDb(); - db.createDb(); - if (debug) debugger; - - var docs = makeDocs(0, 100); - db.bulkSave(docs); - - 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});}" - }, - with_id: { - map: "function(doc) {if(doc.link_id) { var value = {'_id':doc.link_id}; if (doc.link_rev) {value._rev = doc.link_rev}; emit(doc._id, value);}};" - }, - summate: { - map:"function (doc) { if (typeof doc.integer === 'number') {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); - - // Not an error with include_docs=false&reduce=true - resp = db.view('test/summate', {reduce: true, include_docs: false}); - T(resp.rows.length == 1); - T(resp.rows[0].value == 4950); - - T(db.save({ - "_id": "link-to-10", - "link_id" : "10" - }).ok); - - // you can link to another doc from a value. - resp = db.view("test/with_id", {key:"link-to-10"}); - T(resp.rows[0].key == "link-to-10"); - T(resp.rows[0].value["_id"] == "10"); - - resp = db.view("test/with_id", {key:"link-to-10",include_docs: true}); - T(resp.rows[0].key == "link-to-10"); - T(resp.rows[0].value["_id"] == "10"); - T(resp.rows[0].doc._id == "10"); - - // 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; - resp = db.save(after) - T(resp.ok); - - var after = db.open("0"); - TEquals(resp.rev, after._rev, "fails with firebug running"); - T(after._rev != after.prev, "passes"); - TEquals(100, after.integer, "fails with firebug running"); - - // 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].doc == null); - T(resp.rows[1].doc.integer == 23); - - // COUCHDB-549 - include_docs=true with conflicts=true - - var dbA = new CouchDB("test_suite_db_a", {"X-Couch-Full-Commit":"false"}); - var dbB = new CouchDB("test_suite_db_b", {"X-Couch-Full-Commit":"false"}); - - dbA.deleteDb(); - dbA.createDb(); - dbB.deleteDb(); - dbB.createDb(); - - var ddoc = { - _id: "_design/mydesign", - language : "javascript", - views : { - myview : { - map: (function(doc) { - emit(doc.value, 1); - }).toString() - } - } - }; - TEquals(true, dbA.save(ddoc).ok); - - var doc1a = {_id: "foo", value: 1, str: "1"}; - TEquals(true, dbA.save(doc1a).ok); - - var doc1b = {_id: "foo", value: 1, str: "666"}; - TEquals(true, dbB.save(doc1b).ok); - - var doc2 = {_id: "bar", value: 2, str: "2"}; - TEquals(true, dbA.save(doc2).ok); - - TEquals(true, CouchDB.replicate(dbA.name, dbB.name).ok); - - doc1b = dbB.open("foo", {conflicts: true}); - TEquals(true, doc1b._conflicts instanceof Array); - TEquals(1, doc1b._conflicts.length); - var conflictRev = doc1b._conflicts[0]; - - doc2 = dbB.open("bar", {conflicts: true}); - TEquals("undefined", typeof doc2._conflicts); - - resp = dbB.view("mydesign/myview", {include_docs: true, conflicts: true}); - - TEquals(2, resp.rows.length); - TEquals(true, resp.rows[0].doc._conflicts instanceof Array); - TEquals(1, resp.rows[0].doc._conflicts.length); - TEquals(conflictRev, resp.rows[0].doc._conflicts[0]); - TEquals("undefined", typeof resp.rows[1].doc._conflicts); - - // cleanup - dbA.deleteDb(); - dbB.deleteDb(); -}; http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a4893aa/share/www/script/test/view_multi_key_all_docs.js ---------------------------------------------------------------------- diff --git a/share/www/script/test/view_multi_key_all_docs.js b/share/www/script/test/view_multi_key_all_docs.js deleted file mode 100644 index 7c7f6f8..0000000 --- a/share/www/script/test/view_multi_key_all_docs.js +++ /dev/null @@ -1,95 +0,0 @@ -// 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", {"X-Couch-Full-Commit":"false"}); - db.deleteDb(); - db.createDb(); - if (debug) debugger; - - var docs = makeDocs(0, 100); - db.bulkSave(docs); - - 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]); - - // keys in GET parameters - rows = db.allDocs({keys:keys}, null).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]); - - // keys in GET parameters - rows = db.allDocs({limit: 1, keys: keys}, null).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]); - - // keys in GET parameters - rows = db.allDocs({skip: 2, keys: keys}, null).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]); - - // keys in GET parameters - rows = db.allDocs({descending: "true", keys: keys}, null).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]); - - // keys in GET parameters - rows = db.allDocs({descending: "true", skip: 3, limit:1, keys: keys}, null).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"); - - // keys in GET parameters - rows = db.allDocs({keys: [1, "i_dont_exist", "0"]}, null).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"); - - // empty keys - rows = db.allDocs({keys: []}, null).rows; - T(rows.length == 0); -}; http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a4893aa/share/www/script/test/view_multi_key_design.js ---------------------------------------------------------------------- diff --git a/share/www/script/test/view_multi_key_design.js b/share/www/script/test/view_multi_key_design.js deleted file mode 100644 index a84d07a..0000000 --- a/share/www/script/test/view_multi_key_design.js +++ /dev/null @@ -1,220 +0,0 @@ -// 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", {"X-Couch-Full-Commit":"false"}); - db.deleteDb(); - db.createDb(); - if (debug) debugger; - - var docs = makeDocs(0, 100); - db.bulkSave(docs); - - 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); - } - - // with GET keys - rows = db.view("test/all_docs",{keys:keys},null).rows; - for(var i=0;i<rows.length; i++) { - T(keys.indexOf(rows[i].key) != -1); - T(rows[i].key == rows[i].value); - } - - // with empty keys - rows = db.view("test/all_docs",{keys:[]},null).rows; - T(rows.length == 0); - - 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); - } - - // with GET keys - reduce = db.view("test/summate",{group:true,keys:keys},null).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}]; - var getbadargs = [{startkey:0, keys:keys}, {endkey:0, keys:keys}, - {key:0, keys:keys}, {group_level: 2, keys:keys}]; - 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/all_docs",getbadargs[i],null); - 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"); - } - - try { - db.view("test/summate",{keys:keys},null); - T(0==1); - } catch (e) { - T(e.error == "query_parse_error"); - } - - // Test that a map & reduce containing func support keys when reduce=false - var resp = db.view("test/summate", {reduce: false}, keys); - T(resp.rows.length == 5); - - resp = db.view("test/summate", {reduce: false, keys: keys}, null); - 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]); - } - - curr = db.view("test/multi_emit", {startkey_docid: 21, endkey_docid: 23, keys: [0, 2]}, null).rows; - 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); - - curr = db.view("test/all_docs", {limit: 1, keys: keys}, null).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); - - curr = db.view("test/multi_emit", {skip: 1, keys: [0]}, null).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); - - curr = db.view("test/multi_emit", {descending: "true", keys: [1]}, null).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", {descending: "true", skip: 3, limit: 2, keys: [2]}, null).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: 2, limit: 3, startkey_docid: "13", keys: [0]}, null).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: "25", endkey_docid: "27", keys: [1]}, null).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); - - curr = db.view("test/multi_emit", - {skip: 1, limit: 5, startkey_docid: "28", endkey_docid: "26", descending: "true", keys: [1]}, null).rows; - T(curr.length == 2); - T(curr[0].value == 27); - T(curr[1].value == 26); -}; http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a4893aa/share/www/script/test/view_multi_key_temp.js ---------------------------------------------------------------------- diff --git a/share/www/script/test/view_multi_key_temp.js b/share/www/script/test/view_multi_key_temp.js deleted file mode 100644 index 3c05409..0000000 --- a/share/www/script/test/view_multi_key_temp.js +++ /dev/null @@ -1,40 +0,0 @@ -// 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", {"X-Couch-Full-Commit":"false"}); - db.deleteDb(); - db.createDb(); - if (debug) debugger; - - var docs = makeDocs(0, 100); - db.bulkSave(docs); - - 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); - } - - rows = db.query(queryFun, null, {}, []).rows; - T(rows.length == 0); -}; http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a4893aa/share/www/script/test/view_offsets.js ---------------------------------------------------------------------- diff --git a/share/www/script/test/view_offsets.js b/share/www/script/test/view_offsets.js deleted file mode 100644 index 464a1ae..0000000 --- a/share/www/script/test/view_offsets.js +++ /dev/null @@ -1,108 +0,0 @@ -// 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_offsets = function(debug) { - if (debug) debugger; - - var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"}); - db.deleteDb(); - db.createDb(); - - var designDoc = { - _id : "_design/test", - views : { - offset : { - map : "function(doc) { emit([doc.letter, doc.number], doc); }", - } - } - }; - T(db.save(designDoc).ok); - - var docs = [ - {_id : "a1", letter : "a", number : 1, foo: "bar"}, - {_id : "a2", letter : "a", number : 2, foo: "bar"}, - {_id : "a3", letter : "a", number : 3, foo: "bar"}, - {_id : "b1", letter : "b", number : 1, foo: "bar"}, - {_id : "b2", letter : "b", number : 2, foo: "bar"}, - {_id : "b3", letter : "b", number : 3, foo: "bar"}, - {_id : "b4", letter : "b", number : 4, foo: "bar"}, - {_id : "b5", letter : "b", number : 5, foo: "bar"}, - {_id : "c1", letter : "c", number : 1, foo: "bar"}, - {_id : "c2", letter : "c", number : 2, foo: "bar"}, - ]; - db.bulkSave(docs); - - var check = function(startkey, offset) { - var opts = {startkey: startkey, descending: true}; - T(db.view("test/offset", opts).offset == offset); - }; - - [ - [["c", 2], 0], - [["c", 1], 1], - [["b", 5], 2], - [["b", 4], 3], - [["b", 3], 4], - [["b", 2], 5], - [["b", 1], 6], - [["a", 3], 7], - [["a", 2], 8], - [["a", 1], 9] - ].forEach(function(row){ check(row[0], row[1]);}); - - var runTest = function () { - var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"}); - db.deleteDb(); - db.createDb(); - - var designDoc = { - _id : "_design/test", - views : { - offset : { - map : "function(doc) { emit([doc.letter, doc.number], doc);}", - } - } - }; - T(db.save(designDoc).ok); - - var docs = [ - {_id : "a1", letter : "a", number : 1, foo : "bar"}, - {_id : "a2", letter : "a", number : 2, foo : "bar"}, - {_id : "a3", letter : "a", number : 3, foo : "bar"}, - {_id : "b1", letter : "b", number : 1, foo : "bar"}, - {_id : "b2", letter : "b", number : 2, foo : "bar"}, - {_id : "b3", letter : "b", number : 3, foo : "bar"}, - {_id : "b4", letter : "b", number : 4, foo : "bar"}, - {_id : "b5", letter : "b", number : 5, foo : "bar"}, - {_id : "c1", letter : "c", number : 1, foo : "bar"}, - {_id : "c2", letter : "c", number : 2, foo : "bar"} - ]; - db.bulkSave(docs); - - var res1 = db.view("test/offset", { - startkey: ["b",4], startkey_docid: "b4", endkey: ["b"], - limit: 2, descending: true, skip: 1 - }) - - var res2 = db.view("test/offset", {startkey: ["c", 3]}); - var res3 = db.view("test/offset", { - startkey: ["b", 6], - endkey: ["b", 7] - }); - - return res1.offset == 4 && res2.offset == docs.length && res3.offset == 8; - - }; - - for(var i = 0; i < 15; i++) T(runTest()); -} - http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a4893aa/share/www/script/test/view_pagination.js ---------------------------------------------------------------------- diff --git a/share/www/script/test/view_pagination.js b/share/www/script/test/view_pagination.js deleted file mode 100644 index ed3a7ee..0000000 --- a/share/www/script/test/view_pagination.js +++ /dev/null @@ -1,147 +0,0 @@ -// 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", {"X-Couch-Full-Commit":"false"}); - db.deleteDb(); - db.createDb(); - if (debug) debugger; - - var docs = makeDocs(0, 100); - db.bulkSave(docs); - - 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); - } - - // test aliases start_key and start_key_doc_id - queryResults = db.query(queryFun, null, { - start_key: i, - start_key_doc_id: i, - limit: 10 - }); - T(queryResults.rows.length == 10); - T(queryResults.total_rows == docs.length); - T(queryResults.offset == i); - 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); - } - } - - function testEndkeyDocId(queryResults) { - 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"); - } - - // test endkey_docid - var queryResults = db.query(function(doc) { emit(null, null); }, null, { - startkey: null, - startkey_docid: 1, - endkey: null, - endkey_docid: 40 - }); - testEndkeyDocId(queryResults); - - // test aliases end_key_doc_id and end_key - queryResults = db.query(function(doc) { emit(null, null); }, null, { - start_key: null, - start_key_doc_id: 1, - end_key: null, - end_key_doc_id: 40 - }); - testEndkeyDocId(queryResults); - - }; http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a4893aa/share/www/script/test/view_sandboxing.js ---------------------------------------------------------------------- diff --git a/share/www/script/test/view_sandboxing.js b/share/www/script/test/view_sandboxing.js deleted file mode 100644 index 5c73c5a..0000000 --- a/share/www/script/test/view_sandboxing.js +++ /dev/null @@ -1,140 +0,0 @@ -// 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", {"X-Couch-Full-Commit":"false"}); - 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); - - // test for COUCHDB-925 - // altering 'doc' variable in map function affects other map functions - var ddoc = { - _id: "_design/foobar", - language: "javascript", - views: { - view1: { - map: - (function(doc) { - if (doc.values) { - doc.values = [666]; - } - if (doc.tags) { - doc.tags.push("qwerty"); - } - if (doc.tokens) { - doc.tokens["c"] = 3; - } - }).toString() - }, - view2: { - map: - (function(doc) { - if (doc.values) { - emit(doc._id, doc.values); - } - if (doc.tags) { - emit(doc._id, doc.tags); - } - if (doc.tokens) { - emit(doc._id, doc.tokens); - } - }).toString() - } - } - }; - var doc1 = { - _id: "doc1", - values: [1, 2, 3] - }; - var doc2 = { - _id: "doc2", - tags: ["foo", "bar"], - tokens: {a: 1, b: 2} - }; - - db.deleteDb(); - db.createDb(); - T(db.save(ddoc).ok); - T(db.save(doc1).ok); - T(db.save(doc2).ok); - - var view1Results = db.view( - "foobar/view1", {bypass_cache: Math.round(Math.random() * 1000)}); - var view2Results = db.view( - "foobar/view2", {bypass_cache: Math.round(Math.random() * 1000)}); - - TEquals(0, view1Results.rows.length, "view1 has 0 rows"); - TEquals(3, view2Results.rows.length, "view2 has 3 rows"); - - TEquals(doc1._id, view2Results.rows[0].key); - TEquals(doc2._id, view2Results.rows[1].key); - TEquals(doc2._id, view2Results.rows[2].key); - - // https://bugzilla.mozilla.org/show_bug.cgi?id=449657 - TEquals(3, view2Results.rows[0].value.length, - "Warning: installed SpiderMonkey version doesn't allow sealing of arrays"); - if (view2Results.rows[0].value.length === 3) { - TEquals(1, view2Results.rows[0].value[0]); - TEquals(2, view2Results.rows[0].value[1]); - TEquals(3, view2Results.rows[0].value[2]); - } - - TEquals(1, view2Results.rows[1].value["a"]); - TEquals(2, view2Results.rows[1].value["b"]); - TEquals('undefined', typeof view2Results.rows[1].value["c"], - "doc2.tokens object was not sealed"); - - TEquals(2, view2Results.rows[2].value.length, - "Warning: installed SpiderMonkey version doesn't allow sealing of arrays"); - if (view2Results.rows[2].value.length === 2) { - TEquals("foo", view2Results.rows[2].value[0]); - TEquals("bar", view2Results.rows[2].value[1]); - } - - // cleanup - db.deleteDb(); -}; http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a4893aa/share/www/script/test/view_update_seq.js ---------------------------------------------------------------------- diff --git a/share/www/script/test/view_update_seq.js b/share/www/script/test/view_update_seq.js deleted file mode 100644 index df92b11..0000000 --- a/share/www/script/test/view_update_seq.js +++ /dev/null @@ -1,106 +0,0 @@ -// 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_update_seq = function(debug) { - var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"true"}); - db.deleteDb(); - db.createDb(); - if (debug) debugger; - - T(db.info().update_seq == 0); - - var resp = db.allDocs({update_seq:true}); - - T(resp.rows.length == 0); - T(resp.update_seq == 0); - - var designDoc = { - _id:"_design/test", - language: "javascript", - views: { - all_docs: { - map: "function(doc) { emit(doc.integer, doc.string) }" - }, - summate: { - map:"function (doc) { if (typeof doc.integer === 'number') { emit(doc.integer, doc.integer)}; }", - reduce:"function (keys, values) { return sum(values); };" - } - } - }; - T(db.save(designDoc).ok); - - T(db.info().update_seq == 1); - - resp = db.allDocs({update_seq:true}); - - T(resp.rows.length == 1); - T(resp.update_seq == 1); - - var docs = makeDocs(0, 100); - db.bulkSave(docs); - - resp = db.allDocs({limit: 1}); - T(resp.rows.length == 1); - T(!resp.update_seq, "all docs"); - - resp = db.allDocs({limit: 1, update_seq:true}); - T(resp.rows.length == 1); - T(resp.update_seq == 101); - - resp = db.view('test/all_docs', {limit: 1, update_seq:true}); - T(resp.rows.length == 1); - T(resp.update_seq == 101); - - resp = db.view('test/all_docs', {limit: 1, update_seq:false}); - T(resp.rows.length == 1); - T(!resp.update_seq, "view"); - - resp = db.view('test/summate', {update_seq:true}); - T(resp.rows.length == 1); - T(resp.update_seq == 101); - - db.save({"id":"0", "integer": 1}); - resp = db.view('test/all_docs', {limit: 1,stale: "ok", update_seq:true}); - T(resp.rows.length == 1); - T(resp.update_seq == 101); - - db.save({"id":"00", "integer": 2}); - resp = db.view('test/all_docs', - {limit: 1, stale: "update_after", update_seq: true}); - T(resp.rows.length == 1); - T(resp.update_seq == 101); - - // wait 5 seconds for the next assertions to pass in very slow machines - var t0 = new Date(), t1; - do { - CouchDB.request("GET", "/"); - t1 = new Date(); - } while ((t1 - t0) < 5000); - - resp = db.view('test/all_docs', {limit: 1, stale: "ok", update_seq: true}); - T(resp.rows.length == 1); - T(resp.update_seq == 103); - - resp = db.view('test/all_docs', {limit: 1, update_seq:true}); - T(resp.rows.length == 1); - T(resp.update_seq == 103); - - resp = db.view('test/all_docs',{update_seq:true},["0","1"]); - T(resp.update_seq == 103); - - resp = db.view('test/all_docs',{update_seq:true},["0","1"]); - T(resp.update_seq == 103); - - resp = db.view('test/summate',{group:true, update_seq:true},[0,1]); - TEquals(103, resp.update_seq); - -}; http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a4893aa/test/javascript/couch.js ---------------------------------------------------------------------- diff --git a/test/javascript/couch.js b/test/javascript/couch.js new file mode 100644 index 0000000..7e4eeed --- /dev/null +++ b/test/javascript/couch.js @@ -0,0 +1,520 @@ +// 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. + +// A simple class to represent a database. Uses XMLHttpRequest to interface with +// the CouchDB server. + +function CouchDB(name, httpHeaders) { + this.name = name; + this.uri = "/" + encodeURIComponent(name) + "/"; + + // The XMLHttpRequest object from the most recent request. Callers can + // use this to check result http status and headers. + this.last_req = null; + + this.request = function(method, uri, requestOptions) { + requestOptions = requestOptions || {}; + requestOptions.headers = combine(requestOptions.headers, httpHeaders); + return CouchDB.request(method, uri, requestOptions); + }; + + // Creates the database on the server + this.createDb = function() { + this.last_req = this.request("PUT", this.uri); + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + // Deletes the database on the server + this.deleteDb = function() { + this.last_req = this.request("DELETE", this.uri + "?sync=true"); + if (this.last_req.status == 404) { + return false; + } + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + // Save a document to the database + this.save = function(doc, options, http_headers) { + if (doc._id == undefined) { + doc._id = CouchDB.newUuids(1)[0]; + } + http_headers = http_headers || {}; + this.last_req = this.request("PUT", this.uri + + encodeURIComponent(doc._id) + encodeOptions(options), + {body: JSON.stringify(doc), headers: http_headers}); + CouchDB.maybeThrowError(this.last_req); + var result = JSON.parse(this.last_req.responseText); + doc._rev = result.rev; + return result; + }; + + // Open a document from the database + this.open = function(docId, url_params, http_headers) { + this.last_req = this.request("GET", this.uri + encodeURIComponent(docId) + + encodeOptions(url_params), {headers:http_headers}); + if (this.last_req.status == 404) { + return null; + } + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + // Deletes a document from the database + this.deleteDoc = function(doc) { + this.last_req = this.request("DELETE", this.uri + encodeURIComponent(doc._id) + + "?rev=" + doc._rev); + CouchDB.maybeThrowError(this.last_req); + var result = JSON.parse(this.last_req.responseText); + doc._rev = result.rev; //record rev in input document + doc._deleted = true; + return result; + }; + + // Deletes an attachment from a document + this.deleteDocAttachment = function(doc, attachment_name) { + this.last_req = this.request("DELETE", this.uri + encodeURIComponent(doc._id) + + "/" + attachment_name + "?rev=" + doc._rev); + CouchDB.maybeThrowError(this.last_req); + var result = JSON.parse(this.last_req.responseText); + doc._rev = result.rev; //record rev in input document + return result; + }; + + this.bulkSave = function(docs, options) { + // first prepoulate the UUIDs for new documents + var newCount = 0; + for (var i=0; i<docs.length; i++) { + if (docs[i]._id == undefined) { + newCount++; + } + } + var newUuids = CouchDB.newUuids(newCount); + var newCount = 0; + for (var i=0; i<docs.length; i++) { + if (docs[i]._id == undefined) { + docs[i]._id = newUuids.pop(); + } + } + var json = {"docs": docs}; + // put any options in the json + for (var option in options) { + json[option] = options[option]; + } + this.last_req = this.request("POST", this.uri + "_bulk_docs", { + body: JSON.stringify(json) + }); + if (this.last_req.status == 417) { + return {errors: JSON.parse(this.last_req.responseText)}; + } + else { + CouchDB.maybeThrowError(this.last_req); + var results = JSON.parse(this.last_req.responseText); + for (var i = 0; i < docs.length; i++) { + if(results[i] && results[i].rev && results[i].ok) { + docs[i]._rev = results[i].rev; + } + } + return results; + } + }; + + this.ensureFullCommit = function() { + this.last_req = this.request("POST", this.uri + "_ensure_full_commit"); + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + // Applies the map function to the contents of database and returns the results. + this.query = function(mapFun, reduceFun, options, keys, language) { + var body = {language: language || "javascript"}; + if(keys) { + body.keys = keys ; + } + if (typeof(mapFun) != "string") { + mapFun = mapFun.toSource ? mapFun.toSource() : "(" + mapFun.toString() + ")"; + } + body.map = mapFun; + if (reduceFun != null) { + if (typeof(reduceFun) != "string") { + reduceFun = reduceFun.toSource ? + reduceFun.toSource() : "(" + reduceFun.toString() + ")"; + } + body.reduce = reduceFun; + } + if (options && options.options != undefined) { + body.options = options.options; + delete options.options; + } + this.last_req = this.request("POST", this.uri + "_temp_view" + + encodeOptions(options), { + headers: {"Content-Type": "application/json"}, + body: JSON.stringify(body) + }); + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + this.view = function(viewname, options, keys) { + var viewParts = viewname.split('/'); + var viewPath = this.uri + "_design/" + viewParts[0] + "/_view/" + + viewParts[1] + encodeOptions(options); + if(!keys) { + this.last_req = this.request("GET", viewPath); + } else { + this.last_req = this.request("POST", viewPath, { + headers: {"Content-Type": "application/json"}, + body: JSON.stringify({keys:keys}) + }); + } + if (this.last_req.status == 404) { + return null; + } + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + // gets information about the database + this.info = function() { + this.last_req = this.request("GET", this.uri); + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + // gets information about a design doc + this.designInfo = function(docid) { + this.last_req = this.request("GET", this.uri + docid + "/_info"); + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + this.allDocs = function(options,keys) { + if(!keys) { + this.last_req = this.request("GET", this.uri + "_all_docs" + + encodeOptions(options)); + } else { + this.last_req = this.request("POST", this.uri + "_all_docs" + + encodeOptions(options), { + headers: {"Content-Type": "application/json"}, + body: JSON.stringify({keys:keys}) + }); + } + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + this.designDocs = function() { + return this.allDocs({startkey:"_design", endkey:"_design0"}); + }; + + this.changes = function(options) { + this.last_req = this.request("GET", this.uri + "_changes" + + encodeOptions(options)); + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + this.compact = function() { + this.last_req = this.request("POST", this.uri + "_compact"); + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + this.viewCleanup = function() { + this.last_req = this.request("POST", this.uri + "_view_cleanup"); + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + this.setDbProperty = function(propId, propValue) { + this.last_req = this.request("PUT", this.uri + propId,{ + body:JSON.stringify(propValue) + }); + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + this.getDbProperty = function(propId) { + this.last_req = this.request("GET", this.uri + propId); + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + this.setSecObj = function(secObj) { + this.last_req = this.request("PUT", this.uri + "_security",{ + body:JSON.stringify(secObj) + }); + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + this.getSecObj = function() { + this.last_req = this.request("GET", this.uri + "_security"); + CouchDB.maybeThrowError(this.last_req); + return JSON.parse(this.last_req.responseText); + }; + + // Convert a options object to an url query string. + // ex: {key:'value',key2:'value2'} becomes '?key="value"&key2="value2"' + function encodeOptions(options) { + var buf = []; + if (typeof(options) == "object" && options !== null) { + for (var name in options) { + if (!options.hasOwnProperty(name)) { continue; }; + var value = options[name]; + if (name == "key" || name == "keys" || name == "startkey" || name == "endkey" || (name == "open_revs" && value !== "all")) { + value = toJSON(value); + } + buf.push(encodeURIComponent(name) + "=" + encodeURIComponent(value)); + } + } + if (!buf.length) { + return ""; + } + return "?" + buf.join("&"); + } + + function toJSON(obj) { + return obj !== null ? JSON.stringify(obj) : null; + } + + function combine(object1, object2) { + if (!object2) { + return object1; + } + if (!object1) { + return object2; + } + + for (var name in object2) { + object1[name] = object2[name]; + } + return object1; + } + +} + +// this is the XMLHttpRequest object from last request made by the following +// CouchDB.* functions (except for calls to request itself). +// Use this from callers to check HTTP status or header values of requests. +CouchDB.last_req = null; +CouchDB.urlPrefix = ''; + +CouchDB.login = function(name, password) { + CouchDB.last_req = CouchDB.request("POST", "/_session", { + headers: {"Content-Type": "application/x-www-form-urlencoded", + "X-CouchDB-WWW-Authenticate": "Cookie"}, + body: "name=" + encodeURIComponent(name) + "&password=" + + encodeURIComponent(password) + }); + return JSON.parse(CouchDB.last_req.responseText); +} + +CouchDB.logout = function() { + CouchDB.last_req = CouchDB.request("DELETE", "/_session", { + headers: {"Content-Type": "application/x-www-form-urlencoded", + "X-CouchDB-WWW-Authenticate": "Cookie"} + }); + return JSON.parse(CouchDB.last_req.responseText); +}; + +CouchDB.session = function(options) { + options = options || {}; + CouchDB.last_req = CouchDB.request("GET", "/_session", options); + CouchDB.maybeThrowError(CouchDB.last_req); + return JSON.parse(CouchDB.last_req.responseText); +}; + +CouchDB.allDbs = function() { + CouchDB.last_req = CouchDB.request("GET", "/_all_dbs"); + CouchDB.maybeThrowError(CouchDB.last_req); + return JSON.parse(CouchDB.last_req.responseText); +}; + +CouchDB.allDesignDocs = function() { + var ddocs = {}, dbs = CouchDB.allDbs(); + for (var i=0; i < dbs.length; i++) { + var db = new CouchDB(dbs[i]); + ddocs[dbs[i]] = db.designDocs(); + }; + return ddocs; +}; + +CouchDB.getVersion = function() { + CouchDB.last_req = CouchDB.request("GET", "/"); + CouchDB.maybeThrowError(CouchDB.last_req); + return JSON.parse(CouchDB.last_req.responseText).version; +}; + +CouchDB.reloadConfig = function() { + CouchDB.last_req = CouchDB.request("POST", "/_config/_reload"); + CouchDB.maybeThrowError(CouchDB.last_req); + return JSON.parse(CouchDB.last_req.responseText); +}; + +CouchDB.replicate = function(source, target, rep_options) { + rep_options = rep_options || {}; + var headers = rep_options.headers || {}; + var body = rep_options.body || {}; + body.source = source; + body.target = target; + CouchDB.last_req = CouchDB.request("POST", "/_replicate", { + headers: headers, + body: JSON.stringify(body) + }); + CouchDB.maybeThrowError(CouchDB.last_req); + return JSON.parse(CouchDB.last_req.responseText); +}; + +CouchDB.newXhr = function() { + if (typeof(XMLHttpRequest) != "undefined") { + return new XMLHttpRequest(); + } else if (typeof(ActiveXObject) != "undefined") { + return new ActiveXObject("Microsoft.XMLHTTP"); + } else { + throw new Error("No XMLHTTPRequest support detected"); + } +}; + +CouchDB.xhrbody = function(xhr) { + if (xhr.responseText) { + return xhr.responseText; + } else if (xhr.body) { + return xhr.body + } else { + throw new Error("No XMLHTTPRequest support detected"); + } +} + +CouchDB.xhrheader = function(xhr, header) { + if(xhr.getResponseHeader) { + return xhr.getResponseHeader(header); + } else if(xhr.headers) { + return xhr.headers[header] || null; + } else { + throw new Error("No XMLHTTPRequest support detected"); + } +} + +CouchDB.proxyUrl = function(uri) { + if(uri.substr(0, CouchDB.protocol.length) != CouchDB.protocol) { + uri = CouchDB.urlPrefix + uri; + } + return uri; +} + +CouchDB.request = function(method, uri, options) { + options = typeof(options) == 'object' ? options : {}; + options.headers = typeof(options.headers) == 'object' ? options.headers : {}; + options.headers["Content-Type"] = options.headers["Content-Type"] || options.headers["content-type"] || "application/json"; + options.headers["Accept"] = options.headers["Accept"] || options.headers["accept"] || "application/json"; + var req = CouchDB.newXhr(); + uri = CouchDB.proxyUrl(uri); + req.open(method, uri, false); + if (options.headers) { + var headers = options.headers; + for (var headerName in headers) { + if (!headers.hasOwnProperty(headerName)) { continue; } + req.setRequestHeader(headerName, headers[headerName]); + } + } + req.send(options.body || ""); + return req; +}; + +CouchDB.requestStats = function(path, test) { + var query_arg = ""; + if(test !== null) { + query_arg = "?flush=true"; + } + + var url = "/_stats/" + path.join("/") + query_arg; + var stat = CouchDB.request("GET", url).responseText; + return JSON.parse(stat); +}; + +CouchDB.uuids_cache = []; + +CouchDB.newUuids = function(n, buf) { + buf = buf || 100; + if (CouchDB.uuids_cache.length >= n) { + var uuids = CouchDB.uuids_cache.slice(CouchDB.uuids_cache.length - n); + if(CouchDB.uuids_cache.length - n == 0) { + CouchDB.uuids_cache = []; + } else { + CouchDB.uuids_cache = + CouchDB.uuids_cache.slice(0, CouchDB.uuids_cache.length - n); + } + return uuids; + } else { + CouchDB.last_req = CouchDB.request("GET", "/_uuids?count=" + (buf + n)); + CouchDB.maybeThrowError(CouchDB.last_req); + var result = JSON.parse(CouchDB.last_req.responseText); + CouchDB.uuids_cache = + CouchDB.uuids_cache.concat(result.uuids.slice(0, buf)); + return result.uuids.slice(buf); + } +}; + +CouchDB.maybeThrowError = function(req) { + if (req.status >= 400) { + try { + var result = JSON.parse(req.responseText); + } catch (ParseError) { + var result = {error:"unknown", reason:req.responseText}; + } + + throw (new CouchError(result)); + } +} + +CouchDB.params = function(options) { + options = options || {}; + var returnArray = []; + for(var key in options) { + var value = options[key]; + returnArray.push(key + "=" + value); + } + return returnArray.join("&"); +}; +// Used by replication test +if (typeof window == 'undefined' || !window) { + var hostRE = RegExp("https?://([^\/]+)"); + var getter = function () { + return (new CouchHTTP).base_url.match(hostRE)[1]; + }; + if(Object.defineProperty) { + Object.defineProperty(CouchDB, "host", { + get : getter, + enumerable : true + }); + } else { + CouchDB.__defineGetter__("host", getter); + } + CouchDB.protocol = "http://"; + CouchDB.inBrowser = false; +} else { + CouchDB.host = window.location.host; + CouchDB.inBrowser = true; + CouchDB.protocol = window.location.protocol + "//"; +} + +// Turns an {error: ..., reason: ...} response into an Error instance +function CouchError(error) { + var inst = new Error(error.reason); + inst.name = 'CouchError'; + inst.error = error.error; + inst.reason = error.reason; + return inst; +} +CouchError.prototype.constructor = CouchError; http://git-wip-us.apache.org/repos/asf/couchdb/blob/6a4893aa/test/javascript/couch_test_runner.js ---------------------------------------------------------------------- diff --git a/test/javascript/couch_test_runner.js b/test/javascript/couch_test_runner.js new file mode 100644 index 0000000..efc4dc2 --- /dev/null +++ b/test/javascript/couch_test_runner.js @@ -0,0 +1,465 @@ +// 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. + +// *********************** Test Framework of Sorts ************************* // + + +function loadScript(url) { + // disallow loading remote URLs + var re = /^[a-z0-9_]+(\/[a-z0-9_]+)*\.js#?$/; + if (!re.test(url)) { + throw "Not loading remote test scripts"; + } + if (typeof document != "undefined") document.write('<script src="'+url+'"></script>'); +}; + +function patchTest(fun) { + var source = fun.toString(); + var output = ""; + var i = 0; + var testMarker = "T("; + while (i < source.length) { + var testStart = source.indexOf(testMarker, i); + if (testStart == -1) { + output = output + source.substring(i, source.length); + break; + } + var testEnd = source.indexOf(");", testStart); + var testCode = source.substring(testStart + testMarker.length, testEnd); + output += source.substring(i, testStart) + "T(" + testCode + "," + JSON.stringify(testCode); + i = testEnd; + } + try { + return eval("(" + output + ")"); + } catch (e) { + return null; + } +} + +function runAllTests() { + var rows = $("#tests tbody.content tr"); + $("td", rows).text(""); + $("td.status", rows).removeClass("error").removeClass("failure").removeClass("success").text("not run"); + var offset = 0; + function runNext() { + if (offset < rows.length) { + var row = rows.get(offset); + runTest($("th button", row).get(0), function() { + offset += 1; + setTimeout(runNext, 100); + }, false, true); + } else { + saveTestReport(); + } + } + runNext(); +} + +var numFailures = 0; +var currentRow = null; + +function runTest(button, callback, debug, noSave) { + + // offer to save admins + if (currentRow != null) { + alert("Can not run multiple tests simultaneously."); + return; + } + var row = currentRow = $(button).parents("tr").get(0); + $("td.status", row).removeClass("error").removeClass("failure").removeClass("success"); + $("td", row).text(""); + $("#toolbar li.current").text("Running: "+row.id); + var testFun = couchTests[row.id]; + function run() { + numFailures = 0; + var start = new Date().getTime(); + try { + if (debug == undefined || !debug) { + testFun = patchTest(testFun) || testFun; + } + testFun(debug); + var status = numFailures > 0 ? "failure" : "success"; + } catch (e) { + var status = "error"; + if ($("td.details ol", row).length == 0) { + $("<ol></ol>").appendTo($("td.details", row)); + } + $("<li><b>Exception raised:</b> <code class='error'></code></li>") + .find("code").text(JSON.stringify(e)).end() + .appendTo($("td.details ol", row)); + if (debug) { + currentRow = null; + throw e; + } + } + if ($("td.details ol", row).length) { + $("<a href='#'>Run with debugger</a>").click(function() { + runTest(this, undefined, true); + }).prependTo($("td.details ol", row)); + } + var duration = new Date().getTime() - start; + $("td.status", row).removeClass("running").addClass(status).text(status); + $("td.duration", row).text(duration + "ms"); + $("#toolbar li.current").text("Finished: "+row.id); + updateTestsFooter(); + currentRow = null; + if (callback) callback(); + if (!noSave) saveTestReport(); + } + $("td.status", row).addClass("running").text("runningâ¦"); + setTimeout(run, 100); +} + +function showSource(cell) { + var name = $(cell).text(); + var win = window.open("", name, "width=700,height=500,resizable=yes,scrollbars=yes"); + win.document.location = "script/test/" + name + ".js"; +} + +var readyToRun; +function setupAdminParty(fun) { + if (readyToRun) { + fun(); + } else { + function removeAdmins(confs, doneFun) { + // iterate through the config and remove current user last + // current user is at front of list + var remove = confs.pop(); + if (remove) { + $.couch.config({ + success : function() { + removeAdmins(confs, doneFun); + } + }, "admins", remove[0], null); + } else { + doneFun(); + } + }; + $.couch.session({ + success : function(resp) { + var userCtx = resp.userCtx; + if (userCtx.name && userCtx.roles.indexOf("_admin") != -1) { + // admin but not admin party. dialog offering to make admin party + $.showDialog("dialog/_admin_party.html", { + submit: function(data, callback) { + $.couch.config({ + success : function(conf) { + var meAdmin, adminConfs = []; + for (var name in conf) { + if (name == userCtx.name) { + meAdmin = [name, conf[name]]; + } else { + adminConfs.push([name, conf[name]]); + } + } + adminConfs.unshift(meAdmin); + removeAdmins(adminConfs, function() { + callback(); + $.futon.session.sidebar(); + readyToRun = true; + setTimeout(fun, 500); + }); + } + }, "admins"); + } + }); + } else if (userCtx.roles.indexOf("_admin") != -1) { + // admin party! + readyToRun = true; + fun(); + } else { + // not an admin + alert("Error: You need to be an admin to run the tests."); + }; + } + }); + } +}; + +function updateTestsListing() { + for (var name in couchTests) { + var testFunction = couchTests[name]; + var row = $("<tr><th></th><td></td><td></td><td></td></tr>") + .find("th").text(name).attr("title", "Show source").click(function() { + showSource(this); + }).end() + .find("td:nth(0)").addClass("status").text("not run").end() + .find("td:nth(1)").addClass("duration").end() + .find("td:nth(2)").addClass("details").end(); + $("<button type='button' class='run' title='Run test'></button>").click(function() { + this.blur(); + var self = this; + // check for admin party + setupAdminParty(function() { + runTest(self); + }); + return false; + }).prependTo(row.find("th")); + row.attr("id", name).appendTo("#tests tbody.content"); + } + $("#tests tr").removeClass("odd").filter(":odd").addClass("odd"); + updateTestsFooter(); +} + +function updateTestsFooter() { + var tests = $("#tests tbody.content tr td.status"); + var testsRun = tests.filter(".success, .error, .failure"); + var testsFailed = testsRun.not(".success"); + var totalDuration = 0; + $("#tests tbody.content tr td.duration:contains('ms')").each(function() { + var text = $(this).text(); + totalDuration += parseInt(text.substr(0, text.length - 2), 10); + }); + $("#tests tbody.footer td").html("<span>"+testsRun.length + " of " + tests.length + + " test(s) run, " + testsFailed.length + " failures (" + + totalDuration + " ms)</span> "); +} + +// make report and save to local db +// display how many reports need replicating to the mothership +// have button to replicate them + +function saveTestReport(report) { + var report = makeTestReport(); + if (report) { + var db = $.couch.db("test_suite_reports"); + var saveReport = function(db_info) { + report.db = db_info; + $.couch.info({success : function(node_info) { + report.node = node_info; + db.saveDoc(report); + }}); + }; + var createDb = function() { + db.create({success: function() { + db.info({success:saveReport}); + }}); + }; + db.info({error: createDb, success:saveReport}); + } +}; + +function makeTestReport() { + var report = {}; + report.summary = $("#tests tbody.footer td").text(); + report.platform = testPlatform(); + var date = new Date(); + report.timestamp = date.getTime(); + report.timezone = date.getTimezoneOffset(); + report.tests = []; + $("#tests tbody.content tr").each(function() { + var status = $("td.status", this).text(); + if (status != "not run") { + var test = {}; + test.name = this.id; + test.status = status; + test.duration = parseInt($("td.duration", this).text()); + test.details = []; + $("td.details li", this).each(function() { + test.details.push($(this).text()); + }); + if (test.details.length == 0) { + delete test.details; + } + report.tests.push(test); + } + }); + if (report.tests.length > 0) return report; +}; + +function testPlatform() { + var b = $.browser; + var bs = ["mozilla", "msie", "opera", "safari"]; + for (var i=0; i < bs.length; i++) { + if (b[bs[i]]) { + return {"browser" : bs[i], "version" : b.version}; + } + }; + return {"browser" : "undetected"}; +} + + +function reportTests() { + // replicate the database to couchdb.couchdb.org +} + +// Use T to perform a test that returns false on failure and if the test fails, +// display the line that failed. +// Example: +// T(MyValue==1); +function T(arg1, arg2, testName) { + if (!arg1) { + if (currentRow) { + if ($("td.details ol", currentRow).length == 0) { + $("<ol></ol>").appendTo($("td.details", currentRow)); + } + var message = (arg2 != null ? arg2 : arg1).toString(); + $("<li><b>Assertion " + (testName ? "'" + testName + "'" : "") + " failed:</b> <code class='failure'></code></li>") + .find("code").text(message).end() + .appendTo($("td.details ol", currentRow)); + } + numFailures += 1; + } +} + +function TIsnull(actual, testName) { + T(actual === null, "expected 'null', got '" + + repr(actual) + "'", testName); +} + +function TEquals(expected, actual, testName) { + T(equals(expected, actual), "expected '" + repr(expected) + + "', got '" + repr(actual) + "'", testName); +} + +function TEqualsIgnoreCase(expected, actual, testName) { + T(equals(expected.toUpperCase(), actual.toUpperCase()), "expected '" + repr(expected) + + "', got '" + repr(actual) + "'", testName); +} + +function equals(a,b) { + if (a === b) return true; + try { + return repr(a) === repr(b); + } catch (e) { + return false; + } +} + +function repr(val) { + if (val === undefined) { + return null; + } else if (val === null) { + return "null"; + } else { + return JSON.stringify(val); + } +} + +function makeDocs(start, end, templateDoc) { + var templateDocSrc = templateDoc ? JSON.stringify(templateDoc) : "{}"; + if (end === undefined) { + end = start; + start = 0; + } + var docs = []; + for (var i = start; i < end; i++) { + var newDoc = eval("(" + templateDocSrc + ")"); + newDoc._id = (i).toString(); + newDoc.integer = i; + newDoc.string = (i).toString(); + docs.push(newDoc); + } + return docs; +} + +function run_on_modified_server(settings, fun) { + try { + // set the settings + for(var i=0; i < settings.length; i++) { + var s = settings[i]; + var xhr = CouchDB.request("PUT", "/_config/" + s.section + "/" + s.key, { + body: JSON.stringify(s.value), + headers: {"X-Couch-Persist": "false"} + }); + CouchDB.maybeThrowError(xhr); + s.oldValue = xhr.responseText; + } + // run the thing + fun(); + } finally { + // unset the settings + for(var j=0; j < i; j++) { + var s = settings[j]; + if(s.oldValue == "\"\"\n") { // unset value + CouchDB.request("DELETE", "/_config/" + s.section + "/" + s.key, { + headers: {"X-Couch-Persist": "false"} + }); + } else { + CouchDB.request("PUT", "/_config/" + s.section + "/" + s.key, { + body: s.oldValue, + headers: {"X-Couch-Persist": "false"} + }); + } + } + } +} + +function stringFun(fun) { + var string = fun.toSource ? fun.toSource() : "(" + fun.toString() + ")"; + return string; +} + +function waitForSuccess(fun, tag) { + var start = new Date(); + while(true) { + if (new Date() - start > 5000) { + throw("timeout: "+tag); + } else { + try { + fun(); + break; + } catch (e) {} + // sync http req allow async req to happen + try { + CouchDB.request("GET", "/test_suite_db/?tag="+encodeURIComponent(tag)); + } catch (e) {} + } + } +} + +function getCurrentToken() { + var xhr = CouchDB.request("GET", "/_restart/token"); + return JSON.parse(xhr.responseText).token; +}; + + +function restartServer() { + var token = getCurrentToken(); + var token_changed = false; + var tDelta = 5000; + var t0 = new Date(); + var t1; + + CouchDB.request("POST", "/_restart"); + + do { + try { + if(token != getCurrentToken()) { + token_changed = true; + } + } catch (e) { + // Ignore errors while the server restarts + } + t1 = new Date(); + } while(((t1 - t0) <= tDelta) && !token_changed); + + if(!token_changed) { + throw("Server restart failed"); + } +} + +// legacy functions for CouchDB < 1.2.0 +// we keep them to make sure we keep BC +CouchDB.user_prefix = "org.couchdb.user:"; + +CouchDB.prepareUserDoc = function(user_doc, new_password) { + user_doc._id = user_doc._id || CouchDB.user_prefix + user_doc.name; + if (new_password) { + user_doc.password = new_password; + } + user_doc.type = "user"; + if (!user_doc.roles) { + user_doc.roles = []; + } + return user_doc; +};
