Merge remote-tracking branch 'adamlofts/1493-fix-zerobyte-json-parsing'
diff --git a/script/test/changes.js b/script/test/changes.js
index 00944f7..fcd8306 100644
--- a/script/test/changes.js
+++ b/script/test/changes.js
@@ -620,6 +620,32 @@
TEquals(1, resp.results.length);
TEquals(2, resp.results[0].changes.length);
+ // COUCHDB-1852
+ T(db.deleteDb());
+ T(db.createDb());
+
+ // create 4 documents... this assumes the update sequnce will start from 0 and get to 4
+ db.save({"bop" : "foom"});
+ db.save({"bop" : "foom"});
+ db.save({"bop" : "foom"});
+ db.save({"bop" : "foom"});
+
+ // simulate an EventSource request with a Last-Event-ID header
+ req = CouchDB.request("GET", "/test_suite_db/_changes?feed=eventsource&timeout=0&since=0",
+ {"headers": {"Accept": "text/event-stream", "Last-Event-ID": "2"}});
+
+ // "parse" the eventsource response and collect only the "id: ..." lines
+ var changes = req.responseText.split('\n')
+ .map(function (el) {
+ return el.split(":").map(function (el) { return el.trim()});
+ })
+ .filter(function (el) { return (el[0] === "id"); })
+
+ // make sure we only got 2 changes, and they are update_seq=3 and update_seq=4
+ T(changes.length === 2);
+ T(changes[0][1] === "3");
+ T(changes[1][1] === "4");
+
// cleanup
db.deleteDb();
};
diff --git a/script/test/config.js b/script/test/config.js
index 5382778..193aa89 100644
--- a/script/test/config.js
+++ b/script/test/config.js
@@ -72,6 +72,54 @@
config = JSON.parse(xhr.responseText);
T(config == "bar");
+ // Server-side password hashing, and raw updates disabling that.
+ var password_plain = 's3cret';
+ var password_hashed = null;
+
+ xhr = CouchDB.request("PUT", "/_config/admins/administrator",{
+ body : JSON.stringify(password_plain),
+ headers: {"X-Couch-Persist": "false"}
+ });
+ TEquals(200, xhr.status, "Create an admin in the config");
+
+ T(CouchDB.login("administrator", password_plain).ok);
+
+ xhr = CouchDB.request("GET", "/_config/admins/administrator");
+ password_hashed = JSON.parse(xhr.responseText);
+ T(password_hashed.match(/^-pbkdf2-/) || password_hashed.match(/^-hashed-/),
+ "Admin password is hashed");
+
+ xhr = CouchDB.request("PUT", "/_config/admins/administrator?raw=nothanks",{
+ body : JSON.stringify(password_hashed),
+ headers: {"X-Couch-Persist": "false"}
+ });
+ TEquals(400, xhr.status, "CouchDB rejects an invalid 'raw' option");
+
+ xhr = CouchDB.request("PUT", "/_config/admins/administrator?raw=true",{
+ body : JSON.stringify(password_hashed),
+ headers: {"X-Couch-Persist": "false"}
+ });
+ TEquals(200, xhr.status, "Set an raw, pre-hashed admin password");
+
+ xhr = CouchDB.request("PUT", "/_config/admins/administrator?raw=false",{
+ body : JSON.stringify(password_hashed),
+ headers: {"X-Couch-Persist": "false"}
+ });
+ TEquals(200, xhr.status, "Set an admin password with raw=false");
+
+ // The password is literally the string "-pbkdf2-abcd...".
+ T(CouchDB.login("administrator", password_hashed).ok);
+
+ xhr = CouchDB.request("GET", "/_config/admins/administrator");
+ T(password_hashed != JSON.parse(xhr.responseText),
+ "Hashed password was not stored as a raw string");
+
+ xhr = CouchDB.request("DELETE", "/_config/admins/administrator",{
+ headers: {"X-Couch-Persist": "false"}
+ });
+ TEquals(200, xhr.status, "Delete an admin from the config");
+ T(CouchDB.logout().ok);
+
// Non-term whitelist values allow further modification of the whitelist.
xhr = CouchDB.request("PUT", "/_config/httpd/config_whitelist",{
body : JSON.stringify("!This is an invalid Erlang term!"),
diff --git a/script/test/list_views.js b/script/test/list_views.js
index 633afb4..3a6e045 100644
--- a/script/test/list_views.js
+++ b/script/test/list_views.js
@@ -170,6 +170,16 @@
});
send("bad request");
}),
+ allDocs: stringFun(function(head, req){
+ start({'headers': {'Content-Type': 'application/json'}});
+ var resp = head;
+ var rows = [];
+ while(row=getRow()){
+ rows.push(row);
+ }
+ resp.rows = rows;
+ return toJSON(resp);
+ })
}
};
var viewOnlyDesignDoc = {
@@ -492,4 +502,15 @@
T(xhr.status == 400);
T(xhr.getResponseHeader("X-My-Header") == "MyHeader");
T(xhr.responseText.match(/^bad request$/));
+
+ // test handling _all_docs by _list functions. the result should be equal
+ var xhr_lAllDocs = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/allDocs/_all_docs");
+ T(xhr_lAllDocs.status == 200, "standard get should be 200");
+ var xhr_allDocs = CouchDB.request("GET", "/test_suite_db/_all_docs");
+ var allDocs = JSON.parse(xhr_allDocs.responseText);
+ var lAllDocs = JSON.parse(xhr_lAllDocs.responseText);
+ TEquals(allDocs.total_rows, lAllDocs.total_rows, "total_rows mismatch");
+ TEquals(allDocs.offset, lAllDocs.offset, "offset mismatch");
+ TEquals(allDocs.rows.length, lAllDocs.rows.length, "amount of rows mismatch");
+ TEquals(allDocs.rows, lAllDocs.rows, "rows mismatch");
};
diff --git a/script/test/users_db_security.js b/script/test/users_db_security.js
index d439fcb..cdc3f17 100644
--- a/script/test/users_db_security.js
+++ b/script/test/users_db_security.js
@@ -256,6 +256,50 @@
// log in one last time so run_on_modified_server can clean up the admin account
TEquals(true, CouchDB.login("jan", "apple").ok);
});
+
+ run_on_modified_server([
+ {
+ section: "couch_httpd_auth",
+ key: "iterations",
+ value: "1"
+ },
+ {
+ section: "couch_httpd_auth",
+ key: "public_fields",
+ value: "name,type"
+ },
+ {
+ section: "admins",
+ key: "jan",
+ value: "apple"
+ }
+ ], function() {
+ var res = usersDb.open("org.couchdb.user:jchris");
+ TEquals("jchris", res.name);
+ TEquals("user", res.type);
+ TEquals(undefined, res.roles);
+ TEquals(undefined, res.salt);
+ TEquals(undefined, res.password_scheme);
+ TEquals(undefined, res.derived_key);
+
+ // log in one last time so run_on_modified_server can clean up the admin account
+ TEquals(true, CouchDB.login("jan", "apple").ok);
+
+ var all = usersDb.allDocs({ include_docs: true });
+ T(all.rows);
+ if (all.rows) {
+ T(all.rows.every(function(row) {
+ T(row.doc);
+ if (row.doc) {
+ return Object.keys(row.doc).every(function(key) {
+ return key === 'name' || key === 'type';
+ });
+ } else {
+ return false;
+ }
+ }));
+ }
+ });
};
usersDb.deleteDb();