summaryrefslogtreecommitdiff
path: root/share
diff options
context:
space:
mode:
authorJan Lehnardt <jan@apache.org>2009-02-25 16:39:55 +0000
committerJan Lehnardt <jan@apache.org>2009-02-25 16:39:55 +0000
commit8a5b0c697a6fdb3169afe82391368c26bec86978 (patch)
tree00b4b6a482fb8e6af481c8f5a52fb24655554ef7 /share
parent0fb2f9696d8005eb46d5efeac1ae217fe0fb6a04 (diff)
add js test suite for stats, enable access for a previously internal metric
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@747852 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'share')
-rw-r--r--share/Makefile.am1
-rw-r--r--share/www/script/couch.js17
-rw-r--r--share/www/script/couch_tests.js1
-rw-r--r--share/www/script/test/stats.js463
4 files changed, 470 insertions, 12 deletions
diff --git a/share/Makefile.am b/share/Makefile.am
index 476aa675..0f8daaab 100644
--- a/share/Makefile.am
+++ b/share/Makefile.am
@@ -112,4 +112,5 @@ nobase_dist_localdata_DATA = \
www/script/test/purge.js \
www/script/test/config.js \
www/script/test/security_validation.js \
+ www/script/test/stats.js \
www/style/layout.css
diff --git a/share/www/script/couch.js b/share/www/script/couch.js
index 7bec5e32..8a0d3d23 100644
--- a/share/www/script/couch.js
+++ b/share/www/script/couch.js
@@ -312,20 +312,13 @@ CouchDB.request = function(method, uri, options) {
return req;
}
-CouchDB.requestStats = function(module, key, aggregate, options) {
- var options, optionsOrLast = Array.prototype.pop.apply(arguments);
- if (typeof optionsOrLast == "string") {
- options = null;
- Array.prototype.push.apply(arguments, [optionsOrLast]);
- } else {
- options = optionsOrLast;
+CouchDB.requestStats = function(module, key, test) {
+ var query_arg = "";
+ if(test !== null) {
+ query_arg = "?flush=true";
}
- var request_options = {};
- request_options.headers = {"Content-Type": "application/json"};
-
- var stat = CouchDB.request("GET", "/_stats/" + Array.prototype.join.apply(arguments,["/"]) + (options ?
- ("?" + CouchDB.params(options)) : ""), request_options).responseText;
+ var stat = CouchDB.request("GET", "/_stats/" + module + "/" + key + query_arg).responseText;
return JSON.parse(stat)[module][key];
}
diff --git a/share/www/script/couch_tests.js b/share/www/script/couch_tests.js
index a6195cf0..67c3baed 100644
--- a/share/www/script/couch_tests.js
+++ b/share/www/script/couch_tests.js
@@ -66,6 +66,7 @@ loadTest("compact.js");
loadTest("purge.js");
loadTest("config.js");
loadTest("security_validation.js");
+loadTest("stats.js");
function makeDocs(start, end, templateDoc) {
var templateDocSrc = templateDoc ? JSON.stringify(templateDoc) : "{}"
diff --git a/share/www/script/test/stats.js b/share/www/script/test/stats.js
new file mode 100644
index 00000000..db0c6573
--- /dev/null
+++ b/share/www/script/test/stats.js
@@ -0,0 +1,463 @@
+// 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.stats = function(debug) {
+ if (debug) debugger;
+
+ var open_databases_tests = {
+ 'should increment the number of open databases when creating a db': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ var open_databases = requestStatsTest("couchdb", "open_databases").current;
+ db.createDb();
+
+ var new_open_databases = requestStatsTest("couchdb", "open_databases").current;
+ TEquals(open_databases + 1, new_open_databases, name);
+ },
+ 'should increment the number of open databases when opening a db': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ restartServer();
+
+ var open_databases = requestStatsTest("couchdb", "open_databases").current;
+
+ db.open("123");
+
+ var new_open_databases = requestStatsTest("couchdb", "open_databases").current;
+ TEquals(open_databases + 1, new_open_databases, name);
+ },
+ 'should decrement the number of open databases when deleting': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ var open_databases = requestStatsTest("couchdb", "open_databases").current;
+
+ db.deleteDb();
+ var new_open_databases = requestStatsTest("couchdb", "open_databases").current;
+ TEquals(open_databases - 1, new_open_databases, name);
+ },
+ 'should keep the same number of open databases when reaching the max_dbs_open limit': function(name) {
+ restartServer();
+ var max = 5;
+ run_on_modified_server(
+ [{section: "couchdb",
+ key: "max_dbs_open",
+ value: max.toString()}],
+
+ function () {
+ for(var i=0; i<max+1; i++) {
+ var db = new CouchDB("test_suite_db" + i);
+ db.deleteDb();
+ db.createDb();
+ }
+
+ var open_databases = requestStatsTest("couchdb", "open_databases").max;
+ T(max >= open_databases, name);
+
+ // not needed for the test but cleanup is nice
+ for(var i=0; i<max+1; i++) {
+ var db = new CouchDB("test_suite_db" + i);
+ db.deleteDb();
+ }
+ })
+ },
+ };
+
+ var request_count_tests = {
+ 'should increase the request count for every request': function(name) {
+ var requests = requestStatsTest("httpd", "requests").current + 1;
+
+ CouchDB.request("GET", "/");
+
+ var new_requests = requestStatsTest("httpd", "requests").current;
+
+ TEquals(requests + 1, new_requests, name);
+ }
+ };
+
+ var document_read_count_tests = {
+ 'should increase read document counter when a document is read': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ db.save({"_id":"test"});
+
+ var reads = requestStatsTest("httpd", "document_reads").current;
+ db.open("test");
+ var new_reads = requestStatsTest("httpd", "document_reads").current;
+
+ TEquals(reads + 1 , new_reads, name);
+ },
+ 'should not increase read document counter when a non-document is read': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ db.save({"_id":"test"});
+
+ var reads = requestStatsTest("httpd", "document_reads").current;
+ CouchDB.request("GET", "/");
+ var new_reads = requestStatsTest("httpd", "document_reads").current;
+
+ TEquals(reads, new_reads, name);
+ },
+ 'should increase read document counter when a document\'s revisions are read': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ db.save({"_id":"test"});
+
+ var reads = requestStatsTest("httpd", "document_reads").current;
+ db.open("test", {"open_revs":"all"});
+ var new_reads = requestStatsTest("httpd", "document_reads").current;
+
+ TEquals(reads + 1 , new_reads, name);
+ }
+ };
+
+ var view_read_count_tests = {
+ 'should increase the permanent view read counter': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var reads = requestStatsTest("httpd", "view_reads").current;
+ createAndRequestView(db);
+ var new_reads = requestStatsTest("httpd", "view_reads").current;
+
+ TEquals(reads + 1 , new_reads, name);
+ },
+ 'should not increase the permanent view read counter when a document is read': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+ db.save({"_id":"test"});
+
+ var reads = requestStatsTest("httpd", "view_reads").current;
+ db.open("test");
+ var new_reads = requestStatsTest("httpd", "view_reads").current;
+
+ TEquals(reads, new_reads, name);
+ },
+ 'should not increase the permanent view read counter when a temporary view is read': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var reads = requestStatsTest("httpd", "view_reads").current;
+ db.query(function(doc) { emit(doc._id)});
+ var new_reads = requestStatsTest("httpd", "view_reads").current;
+
+ TEquals(reads, new_reads, name);
+ },
+ 'should increase the temporary view read counter': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var reads = requestStatsTest("httpd", "temporary_view_reads").current;
+ db.query(function(doc) { emit(doc._id)});
+ var new_reads = requestStatsTest("httpd", "temporary_view_reads").current;
+
+ TEquals(reads + 1, new_reads, name);
+ },
+ 'should increase the temporary view read counter when querying a permanent view': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var reads = requestStatsTest("httpd", "view_reads").current;
+ createAndRequestView(db);
+ var new_reads = requestStatsTest("httpd", "view_reads").current;
+
+ TEquals(reads + 1 , new_reads, name);
+ }
+ };
+
+ var http_requests_by_method_tests = {
+ 'should count GET requests': function(name) {
+ var requests = requestStatsTest("httpd", "get_requests").current;
+ var new_requests = requestStatsTest("httpd", "get_requests").current;
+
+ TEquals(requests + 1, new_requests, name);
+ },
+ 'should not count GET requests for POST request': function(name) {
+ var requests = requestStatsTest("httpd", "get_requests").current;
+ CouchDB.request("POST", "/");
+ var new_requests = requestStatsTest("httpd", "get_requests").current;
+
+ TEquals(requests + 1, new_requests, name);
+ },
+ 'should count POST requests': function(name) {
+ var requests = requestStatsTest("httpd", "post_requests").current;
+ CouchDB.request("POST", "/");
+ var new_requests = requestStatsTest("httpd", "post_requests").current;
+
+ TEquals(requests + 1, new_requests, name);
+ }
+ };
+
+ var document_write_count_tests = {
+ 'should increment counter for document creates': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var creates = requestStatsTest("httpd", "document_creates").current;
+ db.save({"a":"1"});
+ var new_creates = requestStatsTest("httpd", "document_creates").current;
+
+ TEquals(creates + 1, new_creates, name);
+ },
+ 'should not increment counter for document creates when updating a doc': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var doc = {"_id":"test"};
+ db.save(doc);
+
+ var creates = requestStatsTest("httpd", "document_creates").current;
+ db.save(doc);
+ var new_creates = requestStatsTest("httpd", "document_creates").current;
+
+ TEquals(creates, new_creates, name);
+ },
+ 'should increment counter for document updates': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var doc = {"_id":"test"};
+ db.save(doc);
+
+ var updates = requestStatsTest("httpd", "document_updates").current;
+ db.save(doc);
+ var new_updates = requestStatsTest("httpd", "document_updates").current;
+
+ TEquals(updates + 1, new_updates, name);
+ },
+ 'should not increment counter for document updates when creating a document': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var updates = requestStatsTest("httpd", "document_updates").current;
+ db.save({"a":"1"});
+ var new_updates = requestStatsTest("httpd", "document_updates").current;
+
+ TEquals(updates, new_updates, name);
+ },
+ 'should increment counter for document deletes': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var doc = {"_id":"test"};
+ db.save(doc);
+
+ var deletes = requestStatsTest("httpd", "document_deletes").current;
+ db.deleteDoc(doc);
+ var new_deletes = requestStatsTest("httpd", "document_deletes").current;
+
+ TEquals(deletes + 1, new_deletes, name);
+ },
+ 'should increment the copy counter': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var doc = {"_id":"test"};
+ db.save(doc);
+
+ var copies = requestStatsTest("httpd", "document_copies").current;
+ CouchDB.request("COPY", "/test_suite_db/test", {
+ headers: {"Destination":"copy_of_test"}
+ });
+ var new_copies = requestStatsTest("httpd", "document_copies").current;
+
+ TEquals(copies + 1, new_copies, name);
+ },
+ 'should increment the move counter': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var doc = {"_id":"test"};
+ db.save(doc);
+
+ var moves = requestStatsTest("httpd", "document_moves").current;
+ CouchDB.request("MOVE", "/test_suite_db/test?rev=" + doc._rev, {
+ headers: {"Destination":"move_of_test"}
+ });
+ var new_moves = requestStatsTest("httpd", "document_moves").current;
+
+ TEquals(moves + 1, new_moves, name);
+ },
+ 'should increase the bulk doc counter': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var bulks = requestStatsTest("httpd", "bulk_requests").current;
+
+ var docs = makeDocs(5);
+ db.bulkSave(docs);
+
+ var new_bulks = requestStatsTest("httpd", "bulk_requests").current;
+
+ TEquals(bulks + 1, new_bulks, name);
+ },
+ 'should increment counter for document creates using POST': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var creates = requestStatsTest("httpd", "document_creates").current;
+ CouchDB.request("POST", "/test_suite_db", {body:'{"a":"1"}'});
+ var new_creates = requestStatsTest("httpd", "document_creates").current;
+
+ TEquals(creates + 1, new_creates, name);
+ },
+ 'should increment document create counter when adding attachment': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var creates = requestStatsTest("httpd", "document_creates").current;
+ CouchDB.request("PUT", "/test_suite_db/bin_doc2/foo2.txt", {
+ body:"This is no base64 encoded text",
+ headers:{"Content-Type": "text/plain;charset=utf-8"}
+ });
+ var new_creates = requestStatsTest("httpd", "document_creates").current;
+ TEquals(creates + 1, new_creates, name);
+ },
+ 'should increment document update counter when adding attachment to existing doc': function(name) {
+ var db = new CouchDB("test_suite_db");
+ db.deleteDb();
+ db.createDb();
+
+ var doc = {_id:"test"};
+ db.save(doc);
+
+ var updates = requestStatsTest("httpd", "document_updates").current;
+ CouchDB.request("PUT", "/test_suite_db/test/foo2.txt?rev=" + doc._rev, {
+ body:"This is no base64 encoded text",
+ headers:{"Content-Type": "text/plain;charset=utf-8"}
+ });
+ var new_updates = requestStatsTest("httpd", "document_updates").current;
+ TEquals(updates + 1, new_updates, name);
+ }
+
+ };
+ var response_codes_tests = {
+ 'should increment the response code counter': function(name) {
+ var db = new CouchDB("nonexistant_db");
+ db.deleteDb();
+
+ var not_founds = requestStatsTest("http_status_codes", "404").current;
+ CouchDB.request("GET", "/nonexistant_db");
+ var new_not_founds = requestStatsTest("http_status_codes", "404").current;
+
+ TEquals(not_founds + 1, new_not_founds, name);
+ },
+ 'should not increment respinse code counter for other response code': function(name) {
+ var not_founds = requestStatsTest("http_status_codes", "404").current;
+ CouchDB.request("GET", "/");
+ var new_not_founds = requestStatsTest("http_status_codes", "404").current;
+
+ TEquals(not_founds, new_not_founds, name);
+ }
+ };
+
+ var aggregation_tests = {
+ 'should return the mean': function(name) {
+ CouchDB.request("GET", "/");
+
+ var mean = requestStatsTest("httpd", "requests").mean;
+
+ T(mean >= 0, name);
+ },
+ 'should return the maximum': function(name) {
+ CouchDB.request("GET", "/");
+
+ var maximum = requestStatsTest("httpd", "requests").max;
+
+ T(maximum >= 0, name);
+ },
+ 'should return the minimum': function(name) {
+ CouchDB.request("GET", "/");
+
+ var minimum = requestStatsTest("httpd", "requests", "min").min;
+
+ T(minimum >= 0, name);
+ },
+ 'should return the stddev': function(name) {
+ CouchDB.request("GET", "/");
+
+ var stddev = requestStatsTest("httpd", "stddev_requests").current;
+
+ T(stddev >= 0, name);
+ }
+ };
+
+ var summary_tests = {
+ 'should show a summary of all counters with aggregated values': function(name) {
+ var options = {};
+ options.headers = {"Accept": "application/json"};
+ var summary = JSON.parse(CouchDB.request("GET", "/_stats", options).responseText);
+ var aggregates = ["mean", "min", "max", "stddev",
+ "current", "resolution"];
+
+ for(var i in aggregates) {
+ T(summary.httpd.requests[aggregates[i]] >= 0, aggregates[i] + " >= 0", name);
+ }
+ }
+ };
+
+ var tests = [
+ open_databases_tests,
+ request_count_tests,
+ document_read_count_tests,
+ view_read_count_tests,
+ http_requests_by_method_tests,
+ document_write_count_tests,
+ response_codes_tests,
+ aggregation_tests,
+ summary_tests
+ ];
+
+ for(var testGroup in tests) {
+ for(var test in tests[testGroup]) {
+ tests[testGroup][test](test);
+ }
+ };
+
+ function createAndRequestView(db) {
+ var designDoc = {
+ _id:"_design/test", // turn off couch.js id escaping?
+ language: "javascript",
+ views: {
+ all_docs_twice: {map: "function(doc) { emit(doc.integer, null); emit(doc.integer, null) }"},
+ }
+ };
+ db.save(designDoc);
+
+ db.view("test/all_docs_twice");
+ }
+
+ function requestStatsTest(module, key) {
+ return CouchDB.requestStats(module, key, true);
+ }
+}
+ \ No newline at end of file