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/09/24 08:34:27 UTC

[couchdb] branch 3.x updated: Port view_conflicts.js, view_errors.js and view_include_docs.js into elixir·

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


The following commit(s) were added to refs/heads/3.x by this push:
     new 7bc5d4e  Port view_conflicts.js, view_errors.js and view_include_docs.js into elixir·
7bc5d4e is described below

commit 7bc5d4eda9550195b3d82ca9cddb56e6729de093
Author: Juanjo Rodriguez <ju...@apache.org>
AuthorDate: Wed Jul 15 23:12:47 2020 +0200

    Port view_conflicts.js, view_errors.js and view_include_docs.js into elixir·
---
 test/elixir/README.md                       |   6 +-
 test/elixir/test/view_conflicts_test.exs    |  74 +++++++
 test/elixir/test/view_errors_test.exs       | 300 ++++++++++++++++++++++++++++
 test/elixir/test/view_include_docs_test.exs | 263 ++++++++++++++++++++++++
 test/javascript/tests/view_conflicts.js     |   1 +
 test/javascript/tests/view_errors.js        |   1 +
 test/javascript/tests/view_include_docs.js  |   1 +
 7 files changed, 643 insertions(+), 3 deletions(-)

diff --git a/test/elixir/README.md b/test/elixir/README.md
index f260102..e303809 100644
--- a/test/elixir/README.md
+++ b/test/elixir/README.md
@@ -101,9 +101,9 @@ X means done, - means partially
   - [X] Port view_collation.js
   - [X] Port view_collation_raw.js
   - [X] Port view_compaction.js
-  - [ ] Port view_conflicts.js
-  - [ ] Port view_errors.js
-  - [ ] Port view_include_docs.js
+  - [X] Port view_conflicts.js
+  - [X] Port view_errors.js
+  - [X] Port view_include_docs.js
   - [X] Port view_multi_key_all_docs.js
   - [X] Port view_multi_key_design.js
   - [ ] ~~Port view_multi_key_temp.js~~
diff --git a/test/elixir/test/view_conflicts_test.exs b/test/elixir/test/view_conflicts_test.exs
new file mode 100644
index 0000000..9261b1e
--- /dev/null
+++ b/test/elixir/test/view_conflicts_test.exs
@@ -0,0 +1,74 @@
+defmodule ViewConflictsTest do
+  use CouchTestCase
+
+  @moduletag kind: :single_node
+
+  setup_all do
+    db_name_a = random_db_name()
+    db_name_b = random_db_name()
+
+    {:ok, _} = create_db(db_name_a)
+    {:ok, _} = create_db(db_name_b)
+
+    on_exit(fn -> delete_db(db_name_a) end)
+    on_exit(fn -> delete_db(db_name_b) end)
+    {:ok, [db_name_a: db_name_a, db_name_b: db_name_b]}
+  end
+
+  test "view conflict", context do
+    db_name_a = context[:db_name_a]
+    db_name_b = context[:db_name_b]
+
+    create_doc(db_name_a, %{_id: "foo", bar: 42})
+    replicate(db_name_a, db_name_b)
+
+    resp = Couch.get("/#{db_name_b}/foo")
+
+    docb =
+      resp.body
+      |> Map.put("bar", 43)
+
+    docb = save(db_name_b, docb)
+
+    resp = Couch.get("/#{db_name_a}/foo")
+
+    doca =
+      resp.body
+      |> Map.put("bar", 41)
+
+    doca = save(db_name_a, doca)
+
+    replicate(db_name_a, db_name_b)
+
+    resp = Couch.get("/#{db_name_b}/foo", query: [conflicts: true])
+    doc = resp.body
+    assert length(resp.body["_conflicts"]) == 1
+
+    conflict_rev = Enum.at(resp.body["_conflicts"], 0)
+
+    case doc["bar"] do
+      41 -> assert conflict_rev == docb["_rev"]
+      43 -> assert conflict_rev == doca["_rev"]
+      _ -> assert false
+    end
+
+    map_fun = """
+    function(doc) {
+      if (doc._conflicts) {
+        emit(doc._id, doc._conflicts);
+      }
+    }
+    """
+
+    results = query(db_name_b, map_fun)
+
+    rev =
+      results
+      |> Map.get("rows")
+      |> Enum.at(0)
+      |> Map.get("value")
+      |> Enum.at(0)
+
+    assert conflict_rev == rev
+  end
+end
diff --git a/test/elixir/test/view_errors_test.exs b/test/elixir/test/view_errors_test.exs
new file mode 100644
index 0000000..80067ec
--- /dev/null
+++ b/test/elixir/test/view_errors_test.exs
@@ -0,0 +1,300 @@
+defmodule ViewErrorsTest do
+  use CouchTestCase
+
+  @moduletag kind: :single_node
+
+  @document %{integer: 1, string: "1", array: [1, 2, 3]}
+
+  @tag :with_db
+  test "emit undefined key results as null", context do
+    db_name = context[:db_name]
+    {:ok, _} = create_doc(db_name, @document)
+
+    map_fun = """
+    function(doc) {
+      emit(doc.undef, null);
+    }
+    """
+
+    # emitting a key value that is undefined should result in that row
+    # being included in the view results as null
+    results = query(db_name, map_fun)
+    assert results["total_rows"] == 1
+    assert Enum.at(results["rows"], 0)["key"] == :null
+  end
+
+  @tag :with_db
+  test "exception in map function", context do
+    db_name = context[:db_name]
+    {:ok, _} = create_doc(db_name, @document)
+
+    map_fun = """
+    function(doc) {
+      doc.undef(); // throws an error
+    }
+    """
+
+    # 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
+    results = query(db_name, map_fun)
+    assert results["total_rows"] == 0
+  end
+
+  @tag :with_db
+  test "emit undefined value results as null", context do
+    db_name = context[:db_name]
+    {:ok, _} = create_doc(db_name, @document)
+
+    map_fun = """
+    function(doc) {
+      emit([doc._id, doc.undef], null);
+    }
+    """
+
+    # if a view function includes an undefined value in the emitted key or
+    # value, it is treated as null
+    results = query(db_name, map_fun)
+    assert results["total_rows"] == 1
+
+    key =
+      results["rows"]
+      |> Enum.at(0)
+      |> Map.get("key")
+      |> Enum.at(1)
+
+    assert key == :null
+  end
+
+  @tag :with_db
+  test "query view with invalid params", context do
+    db_name = context[:db_name]
+    {:ok, _} = create_doc(db_name, @document)
+
+    body = %{
+      language: "javascript",
+      map: "function(doc){emit(doc.integer)}"
+    }
+
+    # querying a view with invalid params should give a resonable error message
+    resp =
+      Couch.post("/#{db_name}/_all_docs?startkey=foo",
+        headers: ["Content-Type": "application/json"],
+        body: body
+      )
+
+    assert resp.body["error"] == "bad_request"
+
+    resp =
+      Couch.post("/#{db_name}/_all_docs",
+        headers: ["Content-Type": "application/x-www-form-urlencoded"],
+        body: body
+      )
+
+    assert resp.status_code == 415
+  end
+
+  @tag :with_db
+  test "query parse error", context do
+    db_name = context[:db_name]
+
+    map_fun = """
+    function(doc) {
+      emit(doc.integer, doc.integer);
+    }
+    """
+
+    ddoc_name = create_view(db_name, map_fun)
+
+    resp = Couch.get("/#{db_name}/#{ddoc_name}/_view/view", query: [group: true])
+    assert resp.status_code == 400
+    assert resp.body["error"] == "query_parse_error"
+
+    map_fun = "function() {emit(null, null)}"
+    ddoc_name = create_view(db_name, map_fun)
+
+    resp =
+      Couch.get("/#{db_name}/#{ddoc_name}/_view/view", query: [startkey: 2, endkey: 1])
+
+    assert resp.status_code == 400
+    assert resp.body["error"] == "query_parse_error"
+    assert String.contains?(resp.body["reason"], "No rows can match")
+
+    design_doc = %{
+      _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); };"
+        }
+      }
+    }
+
+    {:ok, _} = create_doc(db_name, design_doc)
+
+    resp = Couch.get("/#{db_name}/_design/test/_view/no_reduce", query: [group: true])
+    assert resp.status_code == 400
+    assert resp.body["error"] == "query_parse_error"
+
+    resp = Couch.get("/#{db_name}/_design/test/_view/no_reduce", query: [group_level: 1])
+    assert resp.status_code == 400
+    assert resp.body["error"] == "query_parse_error"
+
+    resp = Couch.get("/#{db_name}/_design/test/_view/no_reduce", query: [reduce: true])
+    assert resp.status_code == 400
+    assert resp.body["error"] == "query_parse_error"
+
+    resp = Couch.get("/#{db_name}/_design/test/_view/no_reduce", query: [reduce: false])
+    assert resp.status_code == 200
+
+    resp =
+      Couch.get("/#{db_name}/_design/test/_view/with_reduce",
+        query: [group: true, reduce: false]
+      )
+
+    assert resp.status_code == 400
+    assert resp.body["error"] == "query_parse_error"
+
+    resp =
+      Couch.get("/#{db_name}/_design/test/_view/with_reduce",
+        query: [group_level: 1, reduce: false]
+      )
+
+    assert resp.status_code == 400
+    assert resp.body["error"] == "query_parse_error"
+  end
+
+  @tag :with_db
+  test "infinite loop", context do
+    db_name = context[:db_name]
+    {:ok, _} = create_doc(db_name, @document)
+
+    design_doc3 = %{
+      _id: "_design/infinite",
+      language: "javascript",
+      views: %{
+        infinite_loop: %{
+          map: "function(doc) {while(true){emit(doc,doc);}};"
+        }
+      }
+    }
+
+    {:ok, _} = create_doc(db_name, design_doc3)
+
+    resp = Couch.get("/#{db_name}/_design/infinite/_view/infinite_loop")
+    assert resp.status_code == 500
+    # This test has two different races. The first is whether
+    # the while loop exhausts the JavaScript RAM limits before
+    # timing. The second is a race between which of two timeouts
+    # fires first. The first timeout is the couch_os_process
+    # waiting for data back from couchjs. The second is the
+    # gen_server call to couch_os_process.
+    assert resp.body["error"] == "os_process_error" or resp.body["error"] == "timeout"
+  end
+
+  @tag :with_db
+  test "error responses for invalid multi-get bodies", context do
+    db_name = context[:db_name]
+
+    design_doc = %{
+      _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); };"
+        }
+      }
+    }
+
+    {:ok, _} = create_doc(db_name, design_doc)
+
+    resp =
+      Couch.post("/#{db_name}/_design/test/_view/no_reduce",
+        body: "[]"
+      )
+
+    assert resp.status_code == 400
+    assert resp.body["error"] == "bad_request"
+    assert resp.body["reason"] == "Request body must be a JSON object"
+
+    resp =
+      Couch.post("/#{db_name}/_design/test/_view/no_reduce",
+        body: %{keys: 1}
+      )
+
+    assert resp.status_code == 400
+    assert resp.body["error"] == "bad_request"
+    assert resp.body["reason"] == "`keys` member must be an array."
+  end
+
+  @tag :with_db
+  test "reduce overflow error", context do
+    db_name = context[:db_name]
+    {:ok, _} = create_doc(db_name, @document)
+
+    design_doc2 = %{
+      _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; };"
+        }
+      }
+    }
+
+    {:ok, _} = create_doc(db_name, design_doc2)
+
+    resp = Couch.get("/#{db_name}/_design/testbig/_view/reduce_too_big")
+    assert resp.status_code == 200
+    # if the reduce grows to fast, throw an overflow error
+    assert Enum.at(resp.body["rows"], 0)["error"] == "reduce_overflow_error"
+  end
+
+  @tag :with_db
+  test "temporary view should give error message", context do
+    db_name = context[:db_name]
+
+    resp =
+      Couch.post("/#{db_name}/_temp_view",
+        headers: ["Content-Type": "application/json"],
+        body: %{
+          language: "javascript",
+          map: "function(doc){emit(doc.integer)}"
+        }
+      )
+
+    assert resp.status_code == 410
+    assert resp.body["error"] == "gone"
+    assert resp.body["reason"] == "Temporary views are not supported in CouchDB"
+  end
+
+  defp create_view(db_name, map_fun) do
+    ddoc_name = "_design/temp_#{now(:ms)}"
+
+    ddoc = %{
+      _id: ddoc_name,
+      language: "javascript",
+      views: %{
+        view: %{map: map_fun}
+      }
+    }
+
+    {:ok, _} = create_doc(db_name, ddoc)
+    ddoc_name
+  end
+
+  defp now(:ms) do
+    case elem(:os.type(), 0) do
+      :win32 ->
+        div(:erlang.system_time(), 1_000)
+
+      _ ->
+        div(:erlang.system_time(), 1_000_000)
+    end
+  end
+end
diff --git a/test/elixir/test/view_include_docs_test.exs b/test/elixir/test/view_include_docs_test.exs
new file mode 100644
index 0000000..a777530
--- /dev/null
+++ b/test/elixir/test/view_include_docs_test.exs
@@ -0,0 +1,263 @@
+defmodule ViewIncludeDocsTest do
+  use CouchTestCase
+
+  @moduletag kind: :single_node
+
+  @ddoc %{
+    _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); };"
+      }
+    }
+  }
+
+  setup_all do
+    db_name = random_db_name()
+    {:ok, _} = create_db(db_name)
+    on_exit(fn -> delete_db(db_name) end)
+
+    bulk_save(db_name, make_docs(0..99))
+
+    create_doc(db_name, @ddoc)
+
+    {:ok, [db_name: db_name]}
+  end
+
+  test "include docs in view", context do
+    db_name = context[:db_name]
+    resp = view(db_name, "test/all_docs", %{include_docs: true, limit: 2})
+    assert length(resp.body["rows"]) == 2
+    row0 = Enum.at(resp.body["rows"], 0)
+    assert row0["id"] == "0"
+    assert row0["doc"]["_id"] == "0"
+    row1 = Enum.at(resp.body["rows"], 1)
+    assert row1["id"] == "1"
+    assert row1["doc"]["_id"] == "1"
+
+    resp = view(db_name, "test/all_docs", %{include_docs: true}, [29, 74])
+    assert length(resp.body["rows"]) == 2
+    row0 = Enum.at(resp.body["rows"], 0)
+    assert row0["doc"]["_id"] == "29"
+    row1 = Enum.at(resp.body["rows"], 1)
+    assert row1["doc"]["integer"] == 74
+  end
+
+  test "include docs in all_docs", context do
+    db_name = context[:db_name]
+
+    resp =
+      Couch.get("/#{db_name}/_all_docs",
+        query: [limit: 2, skip: 1, include_docs: true]
+      )
+
+    assert length(resp.body["rows"]) == 2
+    row0 = Enum.at(resp.body["rows"], 0)
+    row1 = Enum.at(resp.body["rows"], 1)
+    assert row0["doc"]["integer"] == 1
+    assert row1["doc"]["integer"] == 10
+
+    resp =
+      Couch.post("/#{db_name}/_all_docs",
+        query: [include_docs: true],
+        headers: ["Content-Type": "application/json"],
+        body: %{"keys" => ["not_a_doc"]}
+      )
+
+    assert length(resp.body["rows"]) == 1
+    row0 = Enum.at(resp.body["rows"], 0)
+    assert not Map.has_key?(row0, "doc")
+
+    resp =
+      Couch.post("/#{db_name}/_all_docs",
+        query: [include_docs: true],
+        headers: ["Content-Type": "application/json"],
+        body: %{"keys" => ["1", "foo"]}
+      )
+
+    assert length(resp.body["rows"]) == 2
+    row0 = Enum.at(resp.body["rows"], 0)
+    row1 = Enum.at(resp.body["rows"], 1)
+    assert row0["doc"]["integer"] == 1
+    assert not Map.has_key?(row1, "doc")
+
+    resp =
+      Couch.get("/#{db_name}/_all_docs",
+        query: [limit: 0, include_docs: true]
+      )
+
+    assert Enum.empty?(resp.body["rows"])
+  end
+
+  test "no reduce support", context do
+    db_name = context[:db_name]
+
+    resp =
+      Couch.get("/#{db_name}/_design/test/_view/summate", query: [include_docs: true])
+
+    assert resp.status_code == 400
+    assert resp.body["error"] == "query_parse_error"
+  end
+
+  test "Reduce support when reduce=false", context do
+    db_name = context[:db_name]
+
+    resp =
+      Couch.get("/#{db_name}/_design/test/_view/summate",
+        query: [reduce: false, include_docs: true]
+      )
+
+    assert length(resp.body["rows"]) == 100
+  end
+
+  test "Not an error with include_docs=false&reduce=true", context do
+    db_name = context[:db_name]
+
+    resp =
+      Couch.get("/#{db_name}/_design/test/_view/summate",
+        query: [reduce: true, include_docs: false]
+      )
+
+    assert length(resp.body["rows"]) == 1
+    row0 = Enum.at(resp.body["rows"], 0)
+    assert row0["value"] == 4950
+  end
+
+  @tag :with_db
+  test "link to another doc from a value", context do
+    db_name = context[:db_name]
+
+    bulk_save(db_name, make_docs(0..99))
+    create_doc(db_name, @ddoc)
+
+    doc_link = %{
+      _id: "link-to-10",
+      link_id: "10"
+    }
+
+    {:ok, _} = create_doc(db_name, doc_link)
+    resp = view(db_name, "test/with_id", %{key: ~s("link-to-10")})
+    assert length(resp.body["rows"]) == 1
+    row0 = Enum.at(resp.body["rows"], 0)
+    assert row0["key"] == "link-to-10"
+    assert row0["value"]["_id"] == "10"
+
+    resp = view(db_name, "test/with_id", %{key: ~s("link-to-10"), include_docs: true})
+    assert length(resp.body["rows"]) == 1
+    row0 = Enum.at(resp.body["rows"], 0)
+    assert row0["value"]["_id"] == "10"
+    assert row0["doc"]["_id"] == "10"
+  end
+
+  @tag :with_db
+  test "emitted _rev controls things", context do
+    db_name = context[:db_name]
+
+    bulk_save(db_name, make_docs(0..99))
+    create_doc(db_name, @ddoc)
+
+    resp =
+      Couch.post("/#{db_name}/_all_docs",
+        query: [include_docs: true],
+        headers: ["Content-Type": "application/json"],
+        body: %{"keys" => ["0"]}
+      )
+
+    doc_before = Enum.at(resp.body["rows"], 0)["doc"]
+
+    resp = Couch.get("/#{db_name}/0")
+    assert resp.status_code == 200
+    prev = resp.body["_rev"]
+
+    doc_after =
+      resp.body
+      |> Map.put("integer", 100)
+      |> Map.put("prev", prev)
+
+    saved_doc = save(db_name, doc_after)
+
+    resp = Couch.get("/#{db_name}/0")
+    assert resp.status_code == 200
+    doc_after = resp.body
+    assert doc_after["_rev"] == saved_doc["_rev"]
+    assert doc_after["_rev"] != doc_after["prev"]
+    assert doc_after["integer"] == 100
+
+    resp = view(db_name, "test/with_prev", %{include_docs: true}, ["0"])
+    row0 = Enum.at(resp.body["rows"], 0)["doc"]
+    assert row0["_id"] == "0"
+    assert row0["_rev"] == doc_before["_rev"]
+    assert not Map.has_key?(row0, "prev")
+    assert assert row0["integer"] == 0
+  end
+
+  test "COUCHDB-549 - include_docs=true with conflicts=true" do
+    db_name_a = random_db_name()
+    db_name_b = random_db_name()
+    create_db(db_name_a)
+    create_db(db_name_b)
+    on_exit(fn -> delete_db(db_name_a) end)
+    on_exit(fn -> delete_db(db_name_b) end)
+
+    ddoc = %{
+      _id: "_design/mydesign",
+      language: "javascript",
+      views: %{
+        myview: %{
+          map: """
+           function(doc) {
+            emit(doc.value, 1);
+          }
+          """
+        }
+      }
+    }
+
+    {:ok, _} = create_doc(db_name_a, ddoc)
+
+    doc1a = %{_id: "foo", value: 1, str: "1"}
+    {:ok, _} = create_doc(db_name_a, doc1a)
+
+    doc1b = %{_id: "foo", value: 1, str: "666"}
+    {:ok, _} = create_doc(db_name_b, doc1b)
+
+    doc2 = %{_id: "bar", value: 2, str: "2"}
+    {:ok, _} = create_doc(db_name_a, doc2)
+
+    replicate(db_name_a, db_name_b)
+
+    resp = Couch.get("/#{db_name_b}/foo", query: [conflicts: true])
+    assert resp.status_code == 200
+    doc1b = resp.body
+    assert Map.has_key?(doc1b, "_conflicts")
+    assert length(doc1b["_conflicts"]) == 1
+    conflict_rev = Enum.at(doc1b["_conflicts"], 0)
+
+    resp = Couch.get("/#{db_name_b}/bar", query: [conflicts: true])
+    assert resp.status_code == 200
+    doc2 = resp.body
+    assert not Map.has_key?(doc2, "_conflicts")
+
+    resp = view(db_name_b, "mydesign/myview", %{include_docs: true, conflicts: true})
+    assert length(resp.body["rows"]) == 2
+    row0 = Enum.at(resp.body["rows"], 0)["doc"]
+    assert length(row0["_conflicts"]) == 1
+    assert Enum.at(row0["_conflicts"], 0) == conflict_rev
+    row1 = Enum.at(resp.body["rows"], 1)["doc"]
+    assert not Map.has_key?(row1, "_conflicts")
+  end
+end
diff --git a/test/javascript/tests/view_conflicts.js b/test/javascript/tests/view_conflicts.js
index b1c938c..b1efa23 100644
--- a/test/javascript/tests/view_conflicts.js
+++ b/test/javascript/tests/view_conflicts.js
@@ -10,6 +10,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
+couchTests.elixir = true
 couchTests.view_conflicts = function(debug) {
 
   var db_name_a = get_random_db_name();
diff --git a/test/javascript/tests/view_errors.js b/test/javascript/tests/view_errors.js
index 6b9c754..4774220 100644
--- a/test/javascript/tests/view_errors.js
+++ b/test/javascript/tests/view_errors.js
@@ -10,6 +10,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
+couchTests.elixir = true;
 couchTests.view_errors = function(debug) {
   var db_name = get_random_db_name();
   var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});
diff --git a/test/javascript/tests/view_include_docs.js b/test/javascript/tests/view_include_docs.js
index cefc2cf..b96227d 100644
--- a/test/javascript/tests/view_include_docs.js
+++ b/test/javascript/tests/view_include_docs.js
@@ -10,6 +10,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
+couchTests.elixir = true;
 couchTests.view_include_docs = function(debug) {
   var db_name = get_random_db_name();
   var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});