text: // 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 has become very flaky - needs complete rewrite
  couchTests.skip = true;
  couchTests.stats = function(debug) {
  
    function newDb(doSetup) {
      var db_name = get_random_db_name();
      var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});
      if(doSetup) {
        db.createDb();
      }
      return db;
    };
  
    function getStat(path) {
      var stat = CouchDB.requestStats(path, true);
      return stat ? stat.value : null;
    };
  
    function doView(db) {
      var designDoc = {
        _id:"_design/test", // turn off couch.js id escaping?
        language: "javascript",
        views: {
          all_docs: {map: "function(doc) {emit(doc.integer, null);}"}
        }
      };
      db.save(designDoc);
      db.view("test/all_docs");
    };
  
    function runTest(path, funcs) {
      var db = newDb(true);
      if(funcs.setup) funcs.setup(db);
      var before = getStat(path);
      if(funcs.run) funcs.run(db);
      var after = getStat(path);
      if(funcs.test) funcs.test(before, after);
      db.deleteDb();
    }
  
    if (debug) debugger;
  
    /* Need to delete _users and _replicator or background activity
       will mess with the results of this entire suite. */
    (function() {
      var users = new CouchDB("_users");
      users.deleteDb();
      var replicator = new CouchDB("_replicator");
      replicator.deleteDb();
    })();
  
    (function() {
      var db = newDb(false);
      db.deleteDb();
  
      var before = getStat(["couchdb", "open_databases"]);
      db.createDb();
      var after = getStat(["couchdb", "open_databases"]);
      TEquals(before+8, after, "Creating a db increments open db count.");
      db.deleteDb();
    })();
  
    runTest(["couchdb", "open_databases"], {
      setup: function() {restartServer();},
      run: function(db) {db.open("123");},
      test: function(before, after) {
        T(before<after, "Opening a db increases open db count.");
      }
    });
  
    runTest(["couchdb", "open_databases"], {
      setup: function(db) {restartServer(); db.open("123");},
      run: function(db) {db.deleteDb();},
      test: function(before, after) {
        T(before>after, "Deleting a db decrements open db count.");
      }
    });
  
    /* Improvements in LRU has made this test difficult...
    (function() {
      restartServer();
      var max = 5;
  
      var testFun = function() {
        var pre_dbs = getStat(["couchdb", "open_databases"]) || 0;
        var pre_files = getStat(["couchdb", "open_os_files"]) || 0;
  
        var triggered = false;
        var db = null;
        var dbs = [];
        for(var i = 0; i < max*2; i++) {
          while (true) {
              try {
                db = newDb(true);
                dbs.push(db);
                break;
              } catch(e) {
                  // all_dbs_active error!
                triggered = true;
              }
          }
  
          // Trigger a delayed commit
          db.save({"a": "1"});
        }
        T(triggered, "We managed to force a all_dbs_active error.");
  
        var open_dbs = getStat(["couchdb", "open_databases"]);
        TEquals(open_dbs > 0, true, "We actually opened some dbs.");
        TEquals(max, open_dbs, "We only have max db's open.");
  
        for (var i = 0; i < dbs.length; i++) {
          dbs[i].deleteDb();
        }
  
        var post_dbs = getStat(["couchdb", "open_databases"]);
        var post_files = getStat(["couchdb", "open_os_files"]);
        TEquals(pre_dbs, post_dbs, "We have the same number of open dbs.");
        TEquals(pre_files, post_files, "We have the same number of open files.");
        for (var ctr = 0; ctr < dbs.length; ctr++) {
          dbs[ctr].deleteDb();
        }
      };
  
      run_on_modified_server(
        [{section: "couchdb", key: "max_dbs_open", value: "40"}],
        testFun
      );
    })();
    */
  
    // Just fetching the before value is the extra +1 in test
    runTest(["couchdb", "httpd", "requests"], {
      run: function() {CouchDB.request("GET", "/");},
      test: function(before, after) {
        TEquals(before+2, after, "Request counts are incremented properly.");
      }
    });
  
    runTest(["couchdb", "database_reads"], {
      setup: function(db) {db.save({"_id": "test"});},
      run: function(db) {db.open("test");},
      test: function(before, after) {
        T(before<after, "Reading a doc increments docs reads.");
      }
    });
  
    runTest(["couchdb", "database_reads"], {
      setup: function(db) {db.save({"_id": "test"});},
      run: function(db) {db.request("GET", "/");},
      test: function(before, after) {
        TEquals(before, after, "Only doc reads increment doc reads.");
      }
    });
  
    runTest(["couchdb", "database_reads"], {
      setup: function(db) {db.save({"_id": "test"});},
      run: function(db) {db.open("test", {"open_revs": "all"});},
      test: function(before, after) {
        T(before<after, "Reading doc revs increments docs reads.");
      }
    });
  
    runTest(["couchdb", "database_writes"], {
      run: function(db) {db.save({"a": "1"});},
      test: function(before, after) {
        T(before<after, "Saving docs incrememnts doc writes.");
      }
    });
  
    runTest(["couchdb", "database_writes"], {
      run: function(db) {
        CouchDB.request("POST", "/" + db.name + "", {
          headers: {"Content-Type": "application/json"},
          body: '{"a": "1"}'
        });
      },
      test: function(before, after) {
        T(before<after, "POST'ing new docs increments doc writes.");
      }
    });
  
    runTest(["couchdb", "database_writes"], {
      setup: function(db) {db.save({"_id": "test"});},
      run: function(db) {var doc = db.open("test"); db.save(doc);},
      test: function(before, after) {
        T(before<after, "Updating docs incrememnts doc writes.");
      }
    });
  
    runTest(["couchdb", "database_writes"], {
      setup: function(db) {db.save({"_id": "test"});},
      run: function(db) {var doc = db.open("test"); db.deleteDoc(doc);},
      test: function(before, after) {
        T(before<after, "Deleting docs increments doc writes.");
      }
    });
  
    runTest(["couchdb", "database_writes"], {
      setup: function(db) {db.save({"_id": "test"});},
      run: function(db) {
        CouchDB.request("COPY", "/" + db.name + "/test", {
          headers: {"Destination": "copy_of_test"}
        });
      },
      test: function(before, after) {
        T(before<after, "Copying docs increments doc writes.");
      }
    });
  
    runTest(["couchdb", "database_writes"], {
      run: function(db) {
        CouchDB.request("PUT", "/" + db.name + "/bin_doc2/foo2.txt", {
          body: "This is no base64 encoded test",
          headers: {"Content-Type": "text/plain;charset=utf-8"}
        });
      },
      test: function(before, after) {
        T(before<after, "Create with attachment increments doc writes.");
      }
    });
  
    runTest(["couchdb", "database_writes"], {
      setup: function(db) {db.save({"_id": "test"});},
      run: function(db) {
        var doc = db.open("test");
        CouchDB.request("PUT", "/" + db.name + "/test/foo2.txt?rev=" + doc._rev, {
          body: "This is no base64 encoded text",
          headers: {"Content-Type": "text/plainn;charset=utf-8"}
        });
      },
      test: function(before, after) {
        T(before<after, "Adding attachment increments doc writes.");
      }
    });
  
    runTest(["couchdb", "httpd", "bulk_requests"], {
      run: function(db) {db.bulkSave(makeDocs(5));},
      test: function(before, after) {
        TEquals(before+1, after, "The bulk_requests counter is incremented.");
      }
    });
  
    runTest(["couchdb", "httpd", "view_reads"], {
      run: function(db) {doView(db);},
      test: function(before, after) {
        T(before<after, "Reading a view increments view reads.");
      }
    });
  
    runTest(["couchdb", "httpd", "view_reads"], {
      setup: function(db) {db.save({"_id": "test"});},
      run: function(db) {db.open("test");},
      test: function(before, after) {
        TEquals(before, after, "Reading a doc doesn't increment view reads.");
      }
    });
  
    // Relies on getting the stats values being GET requests.
    runTest(["couchdb", "httpd_request_methods", "GET"], {
      test: function(before, after) {
        TEquals(before+1, after, "Get requests are incremented properly.");
      }
    });
  
    runTest(["couchdb", "httpd_request_methods", "GET"], {
      run: function() {CouchDB.request("POST", "/");},
      test: function(before, after) {
        TEquals(before+1, after, "POST requests don't affect GET counter.");
      }
    });
  
    runTest(["couchdb", "httpd_request_methods", "POST"], {
      run: function() {CouchDB.request("POST", "/");},
      test: function(before, after) {
        TEquals(before+1, after, "POST requests are incremented properly.");
      }
    });
  
    runTest(["couchdb", "httpd_status_codes", "404"], {
      run: function() {CouchDB.request("GET", "/nonexistant_db");},
      test: function(before, after) {
        TEquals(before+1, after, "Increments 404 counter on db not found.");
      }
    });
  
    runTest(["couchdb", "httpd_status_codes", "404"], {
      run: function() {CouchDB.request("GET", "/");},
      test: function(before, after) {
        TEquals(before, after, "Getting DB info doesn't increment 404's");
      }
    });
  
    var test_metric = function(metric, expected_fields) {
      for (var k in metric) {
        T(expected_fields.indexOf(k) >= 0, "Unknown property name: " + k);
      }
      for (var k in expected_fields) {
        T(metric[expected_fields[k]] !== undefined, "Missing required property: " + k);
      }
    };
  
    var test_histogram = function(histo) {
      test_metric(histo, ["value", "type", "desc"]);
      test_metric(histo.value, ["min", "max", "arithmetic_mean",
        "geometric_mean", "harmonic_mean", "median", "variance",
         "standard_deviation", "skewness", "kurtosis", "percentile",
         "histogram", "n"]);
    };
  
    var test_counter = function(counter) {
      test_metric(counter, ["value", "desc", "type"]);
    };
  
    var test_metrics = function(metrics) {
      if (metrics.type === "counter") {
        test_counter(metrics);
      } else if (metrics.type === "gauge") {
        test_counter(metrics);
      } else if (metrics.type === "histogram") {
        test_histogram(metrics);
      } else if (metrics.type === undefined) {
        for (var k in metrics) {
          test_metrics(metrics[k]);
        }
      }
    };
  
    (function() {
      var summary = JSON.parse(CouchDB.request("GET", "/_node/node1@127.0.0.1/_stats", {
        headers: {"Accept": "application/json"}
      }).responseText);
      T(typeof(summary) === 'object');
      test_metrics(summary);
    })();
  
    // cleanup
    /* Recreate the deleted _users and _replicator dbs */
    (function() {
      var users = new CouchDB("_users");
      users.createDb();
      var replicator = new CouchDB("_replicator");
      replicator.createDb();
    })();
  
  };
  