You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by kx...@apache.org on 2014/12/10 12:08:19 UTC

[12/39] couchdb commit: updated refs/heads/master to 9950caa

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;
+};