You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ju...@apache.org on 2020/04/14 07:14:34 UTC

[couchdb] branch 3.x updated (cf5f963 -> a4f240c)

This is an automated email from the ASF dual-hosted git repository.

juanjo pushed a change to branch 3.x
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


    from cf5f963  Improve test initialization
     new 013f107  Port recreate docs test
     new a4f240c  Port reduce_false.js and reduce_builtin.js to Elixir (#2541)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 test/elixir/README.md                    |   6 +-
 test/elixir/test/recreate_doc_test.exs   | 165 ++++++++++++++++++
 test/elixir/test/reduce_builtin_test.exs | 282 +++++++++++++++++++++++++++++++
 test/elixir/test/reduce_false_test.exs   |  50 ++++++
 test/javascript/tests/recreate_doc.js    |   1 +
 5 files changed, 501 insertions(+), 3 deletions(-)
 create mode 100644 test/elixir/test/recreate_doc_test.exs
 create mode 100644 test/elixir/test/reduce_builtin_test.exs
 create mode 100644 test/elixir/test/reduce_false_test.exs


[couchdb] 02/02: Port reduce_false.js and reduce_builtin.js to Elixir (#2541)

Posted by ju...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

juanjo pushed a commit to branch 3.x
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit a4f240c82df7c4dbaa26d9081d3ad3bd183350a7
Author: Leonardo Pires <le...@gmail.com>
AuthorDate: Thu Feb 13 07:13:23 2020 -0300

    Port reduce_false.js and reduce_builtin.js to Elixir (#2541)
    
    Port reduce_false.js and reduce_builtin.js to Elixir
---
 test/elixir/README.md                    |   4 +-
 test/elixir/test/reduce_builtin_test.exs | 282 +++++++++++++++++++++++++++++++
 test/elixir/test/reduce_false_test.exs   |  50 ++++++
 3 files changed, 334 insertions(+), 2 deletions(-)

diff --git a/test/elixir/README.md b/test/elixir/README.md
index 5ba79a8..07ad010 100644
--- a/test/elixir/README.md
+++ b/test/elixir/README.md
@@ -64,8 +64,8 @@ X means done, - means partially
   - [X] Port purge.js
   - [ ] Port reader_acl.js
   - [X] Port recreate_doc.js
-  - [ ] Port reduce_builtin.js
-  - [ ] Port reduce_false.js
+  - [X] Port reduce_builtin.js
+  - [X] Port reduce_false.js
   - [ ] Port reduce_false_temp.js
   - [X] Port reduce.js
   - [X] Port replication.js
diff --git a/test/elixir/test/reduce_builtin_test.exs b/test/elixir/test/reduce_builtin_test.exs
new file mode 100644
index 0000000..d13ada1
--- /dev/null
+++ b/test/elixir/test/reduce_builtin_test.exs
@@ -0,0 +1,282 @@
+defmodule ReduceBuiltinTest do
+  use CouchTestCase
+
+  @moduletag :views
+
+  @moduledoc """
+  Test CouchDB view builtin reduce functions
+  This is a port of the reduce_builtin.js suite
+  """
+
+  def random_ddoc(db_name) do
+    "/#{db_name}/_design/#{:erlang.monotonic_time()}"
+  end
+
+  def summate(n) do
+    (n + 1) * n / 2
+  end
+
+  def sumsqr(n) do
+    1..n |> Enum.reduce(0, fn i, acc -> acc + i * i end)
+  end
+
+  def check_approx_distinct(expected, estimated) do
+    # see https://en.wikipedia.org/wiki/HyperLogLog
+    err = 1.04 / :math.sqrt(:math.pow(2, 11 - 1))
+    abs(expected - estimated) < expected * err
+  end
+
+  def query_rows(ddoc_url, builtin_fun, query \\ nil) do
+    http_opts = if query, do: [query: query], else: []
+    Couch.get("#{ddoc_url}/_view/builtin#{builtin_fun}", http_opts).body["rows"]
+  end
+
+  def query_value(ddoc_url, builtin_fun, query \\ nil) do
+    hd(query_rows(ddoc_url, builtin_fun, query))["value"]
+  end
+
+  @tag :with_db
+  test "Builtin reduce functions", context do
+    db_name = context[:db_name]
+    num_docs = 500
+
+    docs = make_docs(1..num_docs)
+
+    resp = Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => docs}, query: %{w: 3})
+    assert resp.status_code in [201, 202]
+
+    ddoc_url = random_ddoc(db_name)
+
+    map = ~s"""
+    function (doc) {
+      emit(doc.integer, doc.integer);
+      emit(doc.integer, doc.integer);
+    };
+    """
+
+    design_doc = %{
+      :views => %{
+        :builtin_sum => %{:map => map, :reduce => "_sum"},
+        :builtin_count => %{:map => map, :reduce => "_count"},
+        :builtin_stats => %{:map => map, :reduce => "_stats"},
+        :builtin_approx_count_distinct => %{
+          :map => map,
+          :reduce => "_approx_count_distinct"
+        }
+      }
+    }
+
+    assert Couch.put(ddoc_url, body: design_doc).body["ok"]
+
+    value = ddoc_url |> query_value("_sum")
+    assert value == 2 * summate(num_docs)
+    value = ddoc_url |> query_value("_count")
+    assert value == 1000
+    value = ddoc_url |> query_value("_stats")
+    assert value["sum"] == 2 * summate(num_docs)
+    assert value["count"] == 1000
+    assert value["min"] == 1
+    assert value["max"] == 500
+    assert value["sumsqr"] == 2 * sumsqr(num_docs)
+    value = ddoc_url |> query_value("_approx_count_distinct")
+    assert check_approx_distinct(num_docs, value)
+
+    value = ddoc_url |> query_value("_sum", %{startkey: 4, endkey: 4})
+    assert value == 8
+    value = ddoc_url |> query_value("_count", %{startkey: 4, endkey: 4})
+    assert value == 2
+    value = ddoc_url |> query_value("_approx_count_distinct", %{startkey: 4, endkey: 4})
+    assert check_approx_distinct(1, value)
+
+    value = ddoc_url |> query_value("_sum", %{startkey: 4, endkey: 5})
+    assert value == 18
+    value = ddoc_url |> query_value("_count", %{startkey: 4, endkey: 5})
+    assert value == 4
+    value = ddoc_url |> query_value("_approx_count_distinct", %{startkey: 4, endkey: 5})
+    assert check_approx_distinct(2, value)
+
+    value = ddoc_url |> query_value("_sum", %{startkey: 4, endkey: 6})
+    assert value == 30
+    value = ddoc_url |> query_value("_count", %{startkey: 4, endkey: 6})
+    assert value == 6
+    value = ddoc_url |> query_value("_approx_count_distinct", %{startkey: 4, endkey: 6})
+    assert check_approx_distinct(3, value)
+
+    assert [row0, row1, row2] = ddoc_url |> query_rows("_sum", %{group: true, limit: 3})
+    assert row0["value"] == 2
+    assert row1["value"] == 4
+    assert row2["value"] == 6
+
+    assert [row0, row1, row2] =
+             ddoc_url |> query_rows("_approx_count_distinct", %{group: true, limit: 3})
+
+    assert check_approx_distinct(1, row0["value"])
+    assert check_approx_distinct(1, row1["value"])
+    assert check_approx_distinct(1, row2["value"])
+
+    1..div(500, 2)
+    |> Enum.take_every(30)
+    |> Enum.each(fn i ->
+      value = ddoc_url |> query_value("_sum", %{startkey: i, endkey: num_docs - i})
+      assert value == 2 * (summate(num_docs - i) - summate(i - 1))
+    end)
+  end
+
+  @tag :with_db
+  test "Builtin reduce functions with trailings", context do
+    db_name = context[:db_name]
+    num_docs = 500
+
+    docs = make_docs(1..num_docs)
+
+    resp = Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => docs}, query: %{w: 3})
+    assert resp.status_code in [201, 202]
+
+    # test for trailing characters after builtin functions, desired behaviour
+    # is to disregard any trailing characters
+    # I think the behavior should be a prefix test, so that even "_statsorama"
+    # or "_stats\nare\awesome" should work just as "_stats" does. - JChris
+    ["\n", "orama", "\nare\nawesome", " ", "     \n  "]
+    |> Enum.each(fn trailing ->
+      ddoc_url = random_ddoc(db_name)
+
+      map = ~s"""
+      function (doc) {
+        emit(doc.integer, doc.integer);
+        emit(doc.integer, doc.integer);
+      };
+      """
+
+      design_doc = %{
+        :views => %{
+          :builtin_sum => %{:map => map, :reduce => "_sum#{trailing}"},
+          :builtin_count => %{:map => map, :reduce => "_count#{trailing}"},
+          :builtin_stats => %{:map => map, :reduce => "_stats#{trailing}"},
+          :builtin_approx_count_distinct => %{
+            :map => map,
+            :reduce => "_approx_count_distinct#{trailing}"
+          }
+        }
+      }
+
+      assert Couch.put(ddoc_url, body: design_doc).body["ok"]
+
+      value = ddoc_url |> query_value("_sum")
+      assert value == 2 * summate(num_docs)
+      value = ddoc_url |> query_value("_count")
+      assert value == 1000
+      value = ddoc_url |> query_value("_stats")
+      assert value["sum"] == 2 * summate(num_docs)
+      assert value["count"] == 1000
+      assert value["min"] == 1
+      assert value["max"] == 500
+      assert value["sumsqr"] == 2 * sumsqr(num_docs)
+    end)
+  end
+
+  @tag :with_db
+  test "Builtin count and sum reduce for key as array", context do
+    db_name = context[:db_name]
+
+    ddoc_url = random_ddoc(db_name)
+
+    map_one = ~s"""
+    function (doc) {
+      emit(doc.keys, 1);
+    };
+    """
+
+    map_ones_array = ~s"""
+    function (doc) {
+      emit(doc.keys, [1, 1]);
+    };
+    """
+
+    design_doc = %{
+      :views => %{
+        :builtin_one_sum => %{:map => map_one, :reduce => "_sum"},
+        :builtin_one_count => %{:map => map_one, :reduce => "_count"},
+        :builtin_ones_array_sum => %{:map => map_ones_array, :reduce => "_sum"}
+      }
+    }
+
+    assert Couch.put(ddoc_url, body: design_doc).body["ok"]
+
+    for i <- 1..5 do
+      for j <- 0..9 do
+        docs = [
+          %{keys: ["a"]},
+          %{keys: ["a"]},
+          %{keys: ["a", "b"]},
+          %{keys: ["a", "b"]},
+          %{keys: ["a", "b", "c"]},
+          %{keys: ["a", "b", "d"]},
+          %{keys: ["a", "c", "d"]},
+          %{keys: ["d"]},
+          %{keys: ["d", "a"]},
+          %{keys: ["d", "b"]},
+          %{keys: ["d", "c"]}
+        ]
+
+        resp = Couch.post("/#{db_name}/_bulk_docs", body: %{docs: docs}, query: %{w: 3})
+        assert resp.status_code in [201, 202]
+
+        total_docs = 1 + (i - 1) * 10 * 11 + (j + 1) * 11
+        assert Couch.get("/#{db_name}").body["doc_count"] == total_docs
+      end
+
+      ["_sum", "_count"]
+      |> Enum.each(fn builtin ->
+        builtin = "_one#{builtin}"
+
+        # group by exact key match
+        rows = query_rows(ddoc_url, builtin, %{group: true})
+        assert Enum.at(rows, 0) == %{"key" => ["a"], "value" => 20 * i}
+        assert Enum.at(rows, 1) == %{"key" => ["a", "b"], "value" => 20 * i}
+        assert Enum.at(rows, 2) == %{"key" => ["a", "b", "c"], "value" => 10 * i}
+        assert Enum.at(rows, 3) == %{"key" => ["a", "b", "d"], "value" => 10 * i}
+
+        # make sure group reduce and limit params provide valid json
+        assert [row0, _] = query_rows(ddoc_url, builtin, %{group: true, limit: 2})
+        assert row0 == %{"key" => ["a"], "value" => 20 * i}
+
+        # group by the first element in the key array
+        rows = query_rows(ddoc_url, builtin, %{group_level: 1})
+        assert Enum.at(rows, 0) == %{"key" => ["a"], "value" => 70 * i}
+        assert Enum.at(rows, 1) == %{"key" => ["d"], "value" => 40 * i}
+
+        # group by the first 2 elements in the key array
+        rows = query_rows(ddoc_url, builtin, %{group_level: 2})
+        assert Enum.at(rows, 0) == %{"key" => ["a"], "value" => 20 * i}
+        assert Enum.at(rows, 1) == %{"key" => ["a", "b"], "value" => 40 * i}
+        assert Enum.at(rows, 2) == %{"key" => ["a", "c"], "value" => 10 * i}
+        assert Enum.at(rows, 3) == %{"key" => ["d"], "value" => 10 * i}
+        assert Enum.at(rows, 4) == %{"key" => ["d", "a"], "value" => 10 * i}
+        assert Enum.at(rows, 5) == %{"key" => ["d", "b"], "value" => 10 * i}
+        assert Enum.at(rows, 6) == %{"key" => ["d", "c"], "value" => 10 * i}
+      end)
+
+      rows = query_rows(ddoc_url, "_ones_array_sum", %{group: true})
+      assert Enum.at(rows, 0) == %{"key" => ["a"], "value" => [20 * i, 20 * i]}
+      assert Enum.at(rows, 1) == %{"key" => ["a", "b"], "value" => [20 * i, 20 * i]}
+      assert Enum.at(rows, 2) == %{"key" => ["a", "b", "c"], "value" => [10 * i, 10 * i]}
+      assert Enum.at(rows, 3) == %{"key" => ["a", "b", "d"], "value" => [10 * i, 10 * i]}
+
+      assert [row0, _] = query_rows(ddoc_url, "_ones_array_sum", %{group: true, limit: 2})
+      assert row0 == %{"key" => ["a"], "value" => [20 * i, 20 * i]}
+
+      rows = query_rows(ddoc_url, "_ones_array_sum", %{group_level: 1})
+      assert Enum.at(rows, 0) == %{"key" => ["a"], "value" => [70 * i, 70 * i]}
+      assert Enum.at(rows, 1) == %{"key" => ["d"], "value" => [40 * i, 40 * i]}
+
+      rows = query_rows(ddoc_url, "_ones_array_sum", %{group_level: 2})
+      assert Enum.at(rows, 0) == %{"key" => ["a"], "value" => [20 * i, 20 * i]}
+      assert Enum.at(rows, 1) == %{"key" => ["a", "b"], "value" => [40 * i, 40 * i]}
+      assert Enum.at(rows, 2) == %{"key" => ["a", "c"], "value" => [10 * i, 10 * i]}
+      assert Enum.at(rows, 3) == %{"key" => ["d"], "value" => [10 * i, 10 * i]}
+      assert Enum.at(rows, 4) == %{"key" => ["d", "a"], "value" => [10 * i, 10 * i]}
+      assert Enum.at(rows, 5) == %{"key" => ["d", "b"], "value" => [10 * i, 10 * i]}
+      assert Enum.at(rows, 6) == %{"key" => ["d", "c"], "value" => [10 * i, 10 * i]}
+    end
+  end
+end
diff --git a/test/elixir/test/reduce_false_test.exs b/test/elixir/test/reduce_false_test.exs
new file mode 100644
index 0000000..675c11d
--- /dev/null
+++ b/test/elixir/test/reduce_false_test.exs
@@ -0,0 +1,50 @@
+defmodule ReduceFalseTest do
+  use CouchTestCase
+
+  @moduletag :views
+
+  @moduledoc """
+  Test CouchDB view without reduces
+  This is a port of the reduce_false.js suite
+  """
+
+  def summate(n) do
+    (n + 1) * n / 2
+  end
+
+  @tag :with_db
+  test "Basic reduce functions", context do
+    db_name = context[:db_name]
+    view_url = "/#{db_name}/_design/foo/_view/summate"
+    num_docs = 5
+
+    map = ~s"""
+    function (doc) {
+      emit(doc.integer, doc.integer);
+    };
+    """
+
+    reduce = "function (keys, values) { return sum(values); };"
+    red_doc = %{:views => %{:summate => %{:map => map, :reduce => reduce}}}
+    assert Couch.put("/#{db_name}/_design/foo", body: red_doc).body["ok"]
+
+    docs = make_docs(1..num_docs)
+    resp = Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => docs}, query: %{w: 3})
+    assert resp.status_code in [201, 202]
+
+    # Test that the reduce works
+    rows = Couch.get(view_url).body["rows"]
+    assert length(rows) == 1
+    assert hd(rows)["value"] == summate(num_docs)
+
+    # Test that we got our docs back
+    rows = Couch.get(view_url, query: %{reduce: false}).body["rows"]
+    assert length(rows) == 5
+
+    rows
+    |> Enum.with_index(1)
+    |> Enum.each(fn {row, i} ->
+      assert i == row["value"]
+    end)
+  end
+end


[couchdb] 01/02: Port recreate docs test

Posted by ju...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

juanjo pushed a commit to branch 3.x
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 013f1071a711aba8616902e9d74ba7d3c0299b9a
Author: Juanjo Rodriguez <ju...@apache.org>
AuthorDate: Wed Apr 1 17:10:56 2020 +0200

    Port recreate docs test
---
 test/elixir/README.md                  |   2 +-
 test/elixir/test/recreate_doc_test.exs | 165 +++++++++++++++++++++++++++++++++
 test/javascript/tests/recreate_doc.js  |   1 +
 3 files changed, 167 insertions(+), 1 deletion(-)

diff --git a/test/elixir/README.md b/test/elixir/README.md
index 49a2abd..5ba79a8 100644
--- a/test/elixir/README.md
+++ b/test/elixir/README.md
@@ -63,7 +63,7 @@ X means done, - means partially
   - [X] Port proxyauth.js
   - [X] Port purge.js
   - [ ] Port reader_acl.js
-  - [ ] Port recreate_doc.js
+  - [X] Port recreate_doc.js
   - [ ] Port reduce_builtin.js
   - [ ] Port reduce_false.js
   - [ ] Port reduce_false_temp.js
diff --git a/test/elixir/test/recreate_doc_test.exs b/test/elixir/test/recreate_doc_test.exs
new file mode 100644
index 0000000..08f9229
--- /dev/null
+++ b/test/elixir/test/recreate_doc_test.exs
@@ -0,0 +1,165 @@
+defmodule RecreateDocTest do
+  use CouchTestCase
+
+  @moduletag :recreate_doc
+
+  @moduledoc """
+  Test CouchDB document recreation
+  This is a port of the recreate_doc.js suite
+  """
+
+  @tag :with_db
+  test "recreate document", context do
+    db_name = context[:db_name]
+
+    # First create a new document with the ID "foo", and delete it again
+    doc = %{_id: "foo", a: "bar", b: 42}
+    {:ok, resp} = create_doc(db_name, doc)
+    first_rev = resp.body["rev"]
+
+    resp = Couch.delete("/#{db_name}/foo?rev=#{first_rev}")
+    assert resp.status_code == 200
+
+    # Now create a new document with the same ID, save it, and then modify it
+    doc = %{_id: "foo"}
+
+    for _i <- 0..9 do
+      {:ok, _} = create_doc(db_name, doc)
+      resp = Couch.get("/#{db_name}/foo")
+
+      updated_doc =
+        resp.body
+        |> Map.put("a", "baz")
+
+      resp = Couch.put("/#{db_name}/foo", body: updated_doc)
+      assert resp.status_code == 201
+      rev = resp.body["rev"]
+      resp = Couch.delete("/#{db_name}/foo?rev=#{rev}")
+      assert resp.status_code == 200
+    end
+  end
+
+  @tag :with_db
+  test "COUCHDB-292 - recreate a deleted document", context do
+    db_name = context[:db_name]
+    # First create a new document with the ID "foo", and delete it again
+    doc = %{_id: "foo", a: "bar", b: 42}
+    {:ok, resp} = create_doc(db_name, doc)
+    first_rev = resp.body["rev"]
+
+    resp = Couch.delete("/#{db_name}/foo?rev=#{first_rev}")
+    assert resp.status_code == 200
+
+    # COUCHDB-292 now attempt to save the document with a prev that's since
+    # been deleted and this should generate a conflict exception
+    updated_doc =
+      doc
+      |> Map.put(:_rev, first_rev)
+
+    resp = Couch.put("/#{db_name}/foo", body: updated_doc)
+    assert resp.status_code == 409
+
+    # same as before, but with binary
+    bin_att_doc = %{
+      _id: "foo",
+      _rev: first_rev,
+      _attachments: %{
+        "foo.txt": %{
+          content_type: "text/plain",
+          data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
+        }
+      }
+    }
+
+    resp = Couch.put("/#{db_name}/foo", body: bin_att_doc)
+    assert resp.status_code == 409
+  end
+
+  @tag :with_db
+  test "Recreate a deleted document with non-exsistant rev", context do
+    db_name = context[:db_name]
+
+    doc = %{_id: "foo", a: "bar", b: 42}
+    {:ok, resp} = create_doc(db_name, doc)
+    first_rev = resp.body["rev"]
+
+    resp = Couch.delete("/#{db_name}/foo?rev=#{first_rev}")
+    assert resp.status_code == 200
+
+    # random non-existant prev rev
+    updated_doc =
+      doc
+      |> Map.put(:_rev, "1-asfafasdf")
+
+    resp = Couch.put("/#{db_name}/foo", body: updated_doc)
+    assert resp.status_code == 409
+
+    # random non-existant prev rev with bin
+    bin_att_doc = %{
+      _id: "foo",
+      _rev: "1-aasasfasdf",
+      _attachments: %{
+        "foo.txt": %{
+          content_type: "text/plain",
+          data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
+        }
+      }
+    }
+
+    resp = Couch.put("/#{db_name}/foo", body: bin_att_doc)
+    assert resp.status_code == 409
+  end
+
+  @tag :with_db
+  test "COUCHDB-1265 - changes feed after we try and break the update_seq tree",
+       context do
+    db_name = context[:db_name]
+
+    # Test COUCHDB-1265 - Reinserting an old revision into the revision tree causes
+    # duplicates in the update_seq tree.
+    revs = create_rev_doc(db_name, "a", 3)
+
+    resp =
+      Couch.put("/#{db_name}/a",
+        body: Enum.at(revs, 0),
+        query: [new_edits: false]
+      )
+
+    assert resp.status_code == 201
+
+    resp =
+      Couch.put("/#{db_name}/a",
+        body: Enum.at(revs, -1)
+      )
+
+    assert resp.status_code == 201
+
+    resp = Couch.get("/#{db_name}/_changes")
+    assert resp.status_code == 200
+
+    assert length(resp.body["results"]) == 1
+  end
+
+  # function to create a doc with multiple revisions
+  defp create_rev_doc(db_name, id, num_revs) do
+    doc = %{_id: id, count: 0}
+    {:ok, resp} = create_doc(db_name, doc)
+    create_rev_doc(db_name, id, num_revs, [Map.put(doc, :_rev, resp.body["rev"])])
+  end
+
+  defp create_rev_doc(db_name, id, num_revs, revs) do
+    if length(revs) < num_revs do
+      doc = %{_id: id, _rev: Enum.at(revs, -1)[:_rev], count: length(revs)}
+      {:ok, resp} = create_doc(db_name, doc)
+
+      create_rev_doc(
+        db_name,
+        id,
+        num_revs,
+        revs ++ [Map.put(doc, :_rev, resp.body["rev"])]
+      )
+    else
+      revs
+    end
+  end
+end
diff --git a/test/javascript/tests/recreate_doc.js b/test/javascript/tests/recreate_doc.js
index 154a6e4..1aa44ed 100644
--- a/test/javascript/tests/recreate_doc.js
+++ b/test/javascript/tests/recreate_doc.js
@@ -10,6 +10,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
+couchTests.elixir = true;
 couchTests.recreate_doc = function(debug) {
   var db_name = get_random_db_name();
   var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"}, {"w": 3});