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/05/26 22:25:30 UTC

[couchdb] branch 3.x updated (ef160d6 -> 70512e5)

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 ef160d6  Quit test run without checking that couchdb is running
     new dbed92e  Port rev_stemming into elixir
     new 70512e5  move compact and replicate functions into CouchTestCase shared module

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                          |   2 +-
 test/elixir/lib/couch/db_test.ex               |  56 ++++++++-
 test/elixir/test/auth_cache_test.exs           |  15 ---
 test/elixir/test/compact_test.exs              |  12 --
 test/elixir/test/partition_size_limit_test.exs |  12 --
 test/elixir/test/purge_test.exs                |  20 +---
 test/elixir/test/replication_test.exs          |  38 ------
 test/elixir/test/rev_stemming_test.exs         | 157 +++++++++++++++++++++++++
 test/elixir/test/users_db_test.exs             |  22 ----
 test/javascript/tests/rev_stemming.js          |   1 +
 10 files changed, 215 insertions(+), 120 deletions(-)
 create mode 100644 test/elixir/test/rev_stemming_test.exs


[couchdb] 01/02: Port rev_stemming into elixir

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 dbed92e2431ca646aff8da39223a34c4891d75bc
Author: Juanjo Rodriguez <ju...@apache.org>
AuthorDate: Sat May 9 20:31:15 2020 +0200

    Port rev_stemming into elixir
---
 test/elixir/README.md                  |   2 +-
 test/elixir/test/rev_stemming_test.exs | 193 +++++++++++++++++++++++++++++++++
 test/javascript/tests/rev_stemming.js  |   1 +
 3 files changed, 195 insertions(+), 1 deletion(-)

diff --git a/test/elixir/README.md b/test/elixir/README.md
index 07ad010..8d73cda 100644
--- a/test/elixir/README.md
+++ b/test/elixir/README.md
@@ -87,7 +87,7 @@ X means done, - means partially
   - [ ] Port replicator_db_update_security.js
   - [ ] Port replicator_db_user_ctx.js
   - [ ] Port replicator_db_write_auth.js
-  - [ ] Port rev_stemming.js
+  - [X] Port rev_stemming.js
   - [X] Port rewrite.js
   - [ ] Port rewrite_js.js
   - [X] Port security_validation.js
diff --git a/test/elixir/test/rev_stemming_test.exs b/test/elixir/test/rev_stemming_test.exs
new file mode 100644
index 0000000..51e959b
--- /dev/null
+++ b/test/elixir/test/rev_stemming_test.exs
@@ -0,0 +1,193 @@
+defmodule RevStemmingTest do
+  use CouchTestCase
+
+  @moduletag :revs
+
+  @moduledoc """
+  This is a port of the rev_stemming.js suite
+  """
+
+  @new_limit 5
+
+  @tag :with_db
+  test "revs limit update", context do
+    db_name = context[:db_name]
+
+    resp = Couch.get("/#{db_name}/_revs_limit")
+    assert resp.body == 1000
+
+    create_rev_doc(db_name, "foo", @new_limit + 1)
+    resp = Couch.get("/#{db_name}/foo?revs=true")
+    assert length(resp.body["_revisions"]["ids"]) == @new_limit + 1
+
+    resp =
+      Couch.put("/#{db_name}/_revs_limit",
+        body: "#{@new_limit}",
+        headers: ["Content-type": "application/json"]
+      )
+
+    assert resp.status_code == 200
+
+    create_rev_doc(db_name, "foo", @new_limit + 1)
+    resp = Couch.get("/#{db_name}/foo?revs=true")
+    assert length(resp.body["_revisions"]["ids"]) == @new_limit
+  end
+
+  @tag :with_db
+  test "revs limit produces replication conflict ", context do
+    db_name = context[:db_name]
+
+    db_name_b = "#{db_name}_b"
+    create_db(db_name_b)
+    delete_db_on_exit([db_name_b])
+
+    resp =
+      Couch.put("/#{db_name}/_revs_limit",
+        body: "#{@new_limit}",
+        headers: ["Content-type": "application/json"]
+      )
+
+    assert resp.status_code == 200
+
+    create_rev_doc(db_name, "foo", @new_limit + 1)
+    resp = Couch.get("/#{db_name}/foo?revs=true")
+    assert length(resp.body["_revisions"]["ids"]) == @new_limit
+
+    # If you replicate after you make more edits than the limit, you'll
+    # cause a spurious edit conflict.
+    replicate(db_name, db_name_b)
+    resp = Couch.get("/#{db_name_b}/foo?conflicts=true")
+    assert not Map.has_key?(resp.body, "_conflicts")
+
+    create_rev_doc(db_name, "foo", @new_limit - 1)
+
+    # one less edit than limit, no conflict
+    replicate(db_name, db_name_b)
+    resp = Couch.get("/#{db_name_b}/foo?conflicts=true")
+    assert not Map.has_key?(resp.body, "_conflicts")
+    prev_conflicted_rev = resp.body["_rev"]
+
+    # now we hit the limit
+    create_rev_doc(db_name, "foo", @new_limit + 1)
+
+    replicate(db_name, db_name_b)
+    resp = Couch.get("/#{db_name_b}/foo?conflicts=true")
+    assert Map.has_key?(resp.body, "_conflicts")
+
+    conflicted_rev =
+      resp.body["_conflicts"]
+      |> Enum.at(0)
+
+    # we have a conflict, but the previous replicated rev is always the losing
+    # conflict
+    assert conflicted_rev == prev_conflicted_rev
+  end
+
+  @tag :with_db
+  test "revs limit is kept after compaction", context do
+    db_name = context[:db_name]
+
+    create_rev_doc(db_name, "bar", @new_limit + 1)
+    resp = Couch.get("/#{db_name}/bar?revs=true")
+    assert length(resp.body["_revisions"]["ids"]) == @new_limit + 1
+
+    resp =
+      Couch.put("/#{db_name}/_revs_limit",
+        body: "#{@new_limit}",
+        headers: ["Content-type": "application/json"]
+      )
+
+    assert resp.status_code == 200
+
+    # We having already updated bar before setting the limit, so it's still got
+    # a long rev history. compact to stem the revs.
+    resp = Couch.get("/#{db_name}/bar?revs=true")
+    assert length(resp.body["_revisions"]["ids"]) == @new_limit
+
+    compact(db_name)
+    wait_until_compact_complete(db_name)
+
+    # force reload because ETags don't honour compaction
+    resp =
+      Couch.get("/#{db_name}/bar?revs=true",
+        headers: ["if-none-match": "pommes"]
+      )
+
+    assert length(resp.body["_revisions"]["ids"]) == @new_limit
+  end
+
+  # function to create a doc with multiple revisions
+  defp create_rev_doc(db_name, id, num_revs) do
+    resp = Couch.get("/#{db_name}/#{id}")
+
+    doc =
+      if resp.status_code == 200 do
+        resp.body
+      else
+        %{_id: id, count: 0}
+      end
+
+    {: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
+
+  defp build_uri(db_name) do
+    username = System.get_env("EX_USERNAME") || "adm"
+    password = System.get_env("EX_PASSWORD") || "pass"
+
+    "/#{db_name}"
+    |> Couch.process_url()
+    |> URI.parse()
+    |> Map.put(:userinfo, "#{username}:#{password}")
+    |> URI.to_string()
+  end
+
+  defp replicate(src, tgt) do
+    src_uri = build_uri(src)
+    tgt_uri = build_uri(tgt)
+
+    body = %{source: src_uri, target: tgt_uri}
+
+    resp = Couch.post("/_replicate", body: body)
+    assert resp.status_code == 200
+    resp.body
+  end
+
+  def delete_db_on_exit(db_names) when is_list(db_names) do
+    on_exit(fn ->
+      Enum.each(db_names, fn name ->
+        delete_db(name)
+      end)
+    end)
+  end
+
+  defp compact(db_name) do
+    resp = Couch.post("/#{db_name}/_compact")
+    assert resp.status_code == 202
+    resp.body
+  end
+
+  defp wait_until_compact_complete(db_name) do
+    retry_until(
+      fn -> Map.get(info(db_name), "compact_running") == false end,
+      200,
+      10_000
+    )
+  end
+end
diff --git a/test/javascript/tests/rev_stemming.js b/test/javascript/tests/rev_stemming.js
index 238868f..725c0f1 100644
--- a/test/javascript/tests/rev_stemming.js
+++ b/test/javascript/tests/rev_stemming.js
@@ -10,6 +10,7 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
+couchTests.elixir = true;
 couchTests.rev_stemming = function(debug) {
 
   var db_name_orig = get_random_db_name();


[couchdb] 02/02: move compact and replicate functions into CouchTestCase shared module

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 70512e57649ac69312beffdc8243a2bf263f7611
Author: Juanjo Rodriguez <ju...@apache.org>
AuthorDate: Mon May 25 08:11:45 2020 +0200

    move compact and replicate functions into CouchTestCase shared module
---
 test/elixir/lib/couch/db_test.ex               | 56 +++++++++++++++++++++++++-
 test/elixir/test/auth_cache_test.exs           | 15 -------
 test/elixir/test/compact_test.exs              | 12 ------
 test/elixir/test/partition_size_limit_test.exs | 12 ------
 test/elixir/test/purge_test.exs                | 20 +--------
 test/elixir/test/replication_test.exs          | 38 -----------------
 test/elixir/test/rev_stemming_test.exs         | 36 -----------------
 test/elixir/test/users_db_test.exs             | 22 ----------
 8 files changed, 56 insertions(+), 155 deletions(-)

diff --git a/test/elixir/lib/couch/db_test.ex b/test/elixir/lib/couch/db_test.ex
index e3f32f8..a61db14 100644
--- a/test/elixir/lib/couch/db_test.ex
+++ b/test/elixir/lib/couch/db_test.ex
@@ -278,6 +278,60 @@ defmodule Couch.DBTest do
     resp.body
   end
 
+  def compact(db_name) do
+    resp = Couch.post("/#{db_name}/_compact")
+    assert resp.status_code == 202
+
+    retry_until(
+      fn -> Map.get(info(db_name), "compact_running") == false end,
+      200,
+      10_000
+    )
+
+    resp.body
+  end
+
+  def replicate(src, tgt, options \\ []) do
+    username = System.get_env("EX_USERNAME") || "adm"
+    password = System.get_env("EX_PASSWORD") || "pass"
+
+    {userinfo, options} = Keyword.pop(options, :userinfo)
+
+    userinfo =
+      if userinfo == nil do
+        "#{username}:#{password}"
+      else
+        userinfo
+      end
+
+    src = set_user(src, userinfo)
+    tgt = set_user(tgt, userinfo)
+
+    defaults = [headers: [], body: %{}, timeout: 30_000]
+    options = defaults |> Keyword.merge(options) |> Enum.into(%{})
+
+    %{body: body} = options
+    body = [source: src, target: tgt] |> Enum.into(body)
+    options = Map.put(options, :body, body)
+
+    resp = Couch.post("/_replicate", Enum.to_list(options))
+    assert HTTPotion.Response.success?(resp), "#{inspect(resp)}"
+    resp.body
+  end
+
+  defp set_user(uri, userinfo) do
+    case URI.parse(uri) do
+      %{scheme: nil} ->
+        uri
+
+      %{userinfo: nil} = uri ->
+        URI.to_string(Map.put(uri, :userinfo, userinfo))
+
+      _ ->
+        uri
+    end
+  end
+
   def view(db_name, view_name, options \\ nil, keys \\ nil) do
     [view_root, view_name] = String.split(view_name, "/")
 
@@ -423,7 +477,7 @@ defmodule Couch.DBTest do
         Enum.each(setting.nodes, fn node_value ->
           node = elem(node_value, 0)
           value = elem(node_value, 1)
-          
+
           if value == ~s(""\\n) or value == "" or value == nil do
             resp =
               Couch.delete(
diff --git a/test/elixir/test/auth_cache_test.exs b/test/elixir/test/auth_cache_test.exs
index 2ba396d..8b7c29c 100644
--- a/test/elixir/test/auth_cache_test.exs
+++ b/test/elixir/test/auth_cache_test.exs
@@ -66,14 +66,6 @@ defmodule AuthCacheTest do
     sess
   end
 
-  defp wait_until_compact_complete(db_name) do
-    retry_until(
-      fn -> Map.get(info(db_name), "compact_running") == false end,
-      200,
-      10_000
-    )
-  end
-
   defp assert_cache(event, user, password, expect \\ :expect_login_success) do
     hits_before = hits()
     misses_before = misses()
@@ -112,12 +104,6 @@ defmodule AuthCacheTest do
     end
   end
 
-  defp compact(db_name) do
-    resp = Couch.post("/#{db_name}/_compact")
-    assert resp.status_code == 202
-    resp.body
-  end
-
   def save_doc(db_name, body) do
     resp = Couch.put("/#{db_name}/#{body["_id"]}", body: body)
     assert resp.status_code in [201, 202]
@@ -206,7 +192,6 @@ defmodule AuthCacheTest do
     # there was a cache hit
     assert_cache(:expect_hit, "johndoe", "123456")
     compact(db_name)
-    wait_until_compact_complete(db_name)
     assert_cache(:expect_hit, "johndoe", "123456")
   end
 end
diff --git a/test/elixir/test/compact_test.exs b/test/elixir/test/compact_test.exs
index d99a7a7..461a1d3 100644
--- a/test/elixir/test/compact_test.exs
+++ b/test/elixir/test/compact_test.exs
@@ -82,18 +82,6 @@ defmodule CompactTest do
     assert Couch.post("/#{db}/_ensure_full_commit").body["ok"] == true
   end
 
-  defp compact(db) do
-    assert Couch.post("/#{db}/_compact").status_code == 202
-
-    retry_until(
-      fn ->
-        Couch.get("/#{db}").body["compact_running"] == false
-      end,
-      200,
-      20_000
-    )
-  end
-
   defp get_info(db) do
     Couch.get("/#{db}").body
   end
diff --git a/test/elixir/test/partition_size_limit_test.exs b/test/elixir/test/partition_size_limit_test.exs
index 5141d0d..6ef6866 100644
--- a/test/elixir/test/partition_size_limit_test.exs
+++ b/test/elixir/test/partition_size_limit_test.exs
@@ -68,18 +68,6 @@ defmodule PartitionSizeLimitTest do
     assert resp.status_code in [201, 202]
   end
 
-  defp compact(db) do
-    assert Couch.post("/#{db}/_compact").status_code == 202
-
-    retry_until(
-      fn ->
-        Couch.get("/#{db}").body["compact_running"] == false
-      end,
-      200,
-      20_000
-    )
-  end
-
   test "fill partition manually", context do
     db_name = context[:db_name]
     partition = "foo"
diff --git a/test/elixir/test/purge_test.exs b/test/elixir/test/purge_test.exs
index 3920b3f..5fc03f1 100644
--- a/test/elixir/test/purge_test.exs
+++ b/test/elixir/test/purge_test.exs
@@ -53,12 +53,7 @@ defmodule PurgeTest do
     test_all_docs_twice(db_name, num_docs, 0, 2)
 
     # purge sequences are preserved after compaction (COUCHDB-1021)
-    resp = Couch.post("/#{db_name}/_compact")
-    assert resp.status_code == 202
-
-    retry_until(fn ->
-      info(db_name)["compact_running"] == false
-    end)
+    compact(db_name)
 
     compacted_info = info(db_name)
     assert compacted_info["purge_seq"] == purged_info["purge_seq"]
@@ -127,19 +122,6 @@ defmodule PurgeTest do
     delete_db(db_name_b)
   end
 
-  def replicate(src, tgt, options \\ []) do
-    defaults = [headers: [], body: %{}, timeout: 30_000]
-    options = defaults |> Keyword.merge(options) |> Enum.into(%{})
-
-    %{body: body} = options
-    body = [source: src, target: tgt] |> Enum.into(body)
-    options = Map.put(options, :body, body)
-
-    resp = Couch.post("/_replicate", Enum.to_list(options))
-    assert HTTPotion.Response.success?(resp), "#{inspect(resp)}"
-    resp.body
-  end
-
   defp open_doc(db_name, id, expect \\ 200) do
     resp = Couch.get("/#{db_name}/#{id}")
     assert resp.status_code == expect
diff --git a/test/elixir/test/replication_test.exs b/test/elixir/test/replication_test.exs
index bdd683e..075f65b 100644
--- a/test/elixir/test/replication_test.exs
+++ b/test/elixir/test/replication_test.exs
@@ -7,7 +7,6 @@ defmodule ReplicationTest do
   """
 
   # TODO: Parameterize these
-  @admin_account "adm:pass"
   @db_pairs_prefixes [
     {"remote-to-remote", "http://127.0.0.1:15984/", "http://127.0.0.1:15984/"}
   ]
@@ -1584,30 +1583,6 @@ defmodule ReplicationTest do
     resp.body
   end
 
-  def replicate(src, tgt, options \\ []) do
-    {userinfo, options} = Keyword.pop(options, :userinfo)
-
-    userinfo =
-      if userinfo == nil do
-        @admin_account
-      else
-        userinfo
-      end
-
-    src = set_user(src, userinfo)
-    tgt = set_user(tgt, userinfo)
-
-    defaults = [headers: [], body: %{}, timeout: 30_000]
-    options = defaults |> Keyword.merge(options) |> Enum.into(%{})
-
-    %{body: body} = options
-    body = [source: src, target: tgt] |> Enum.into(body)
-    options = Map.put(options, :body, body)
-
-    resp = Couch.post("/_replicate", Enum.to_list(options))
-    assert HTTPotion.Response.success?(resp), "#{inspect(resp)}"
-    resp.body
-  end
 
   def cancel_replication(src, tgt) do
     body = %{:cancel => true}
@@ -1737,19 +1712,6 @@ defmodule ReplicationTest do
     end)
   end
 
-  def set_user(uri, userinfo) do
-    case URI.parse(uri) do
-      %{scheme: nil} ->
-        uri
-
-      %{userinfo: nil} = uri ->
-        URI.to_string(Map.put(uri, :userinfo, userinfo))
-
-      _ ->
-        uri
-    end
-  end
-
   def get_att1_data do
     File.read!(Path.expand("data/lorem.txt", __DIR__))
   end
diff --git a/test/elixir/test/rev_stemming_test.exs b/test/elixir/test/rev_stemming_test.exs
index 51e959b..9a16d48 100644
--- a/test/elixir/test/rev_stemming_test.exs
+++ b/test/elixir/test/rev_stemming_test.exs
@@ -105,7 +105,6 @@ defmodule RevStemmingTest do
     assert length(resp.body["_revisions"]["ids"]) == @new_limit
 
     compact(db_name)
-    wait_until_compact_complete(db_name)
 
     # force reload because ETags don't honour compaction
     resp =
@@ -147,28 +146,6 @@ defmodule RevStemmingTest do
     end
   end
 
-  defp build_uri(db_name) do
-    username = System.get_env("EX_USERNAME") || "adm"
-    password = System.get_env("EX_PASSWORD") || "pass"
-
-    "/#{db_name}"
-    |> Couch.process_url()
-    |> URI.parse()
-    |> Map.put(:userinfo, "#{username}:#{password}")
-    |> URI.to_string()
-  end
-
-  defp replicate(src, tgt) do
-    src_uri = build_uri(src)
-    tgt_uri = build_uri(tgt)
-
-    body = %{source: src_uri, target: tgt_uri}
-
-    resp = Couch.post("/_replicate", body: body)
-    assert resp.status_code == 200
-    resp.body
-  end
-
   def delete_db_on_exit(db_names) when is_list(db_names) do
     on_exit(fn ->
       Enum.each(db_names, fn name ->
@@ -177,17 +154,4 @@ defmodule RevStemmingTest do
     end)
   end
 
-  defp compact(db_name) do
-    resp = Couch.post("/#{db_name}/_compact")
-    assert resp.status_code == 202
-    resp.body
-  end
-
-  defp wait_until_compact_complete(db_name) do
-    retry_until(
-      fn -> Map.get(info(db_name), "compact_running") == false end,
-      200,
-      10_000
-    )
-  end
 end
diff --git a/test/elixir/test/users_db_test.exs b/test/elixir/test/users_db_test.exs
index 1d34d8c..62877d5 100644
--- a/test/elixir/test/users_db_test.exs
+++ b/test/elixir/test/users_db_test.exs
@@ -50,28 +50,6 @@ defmodule UsersDbTest do
     create_db(@users_db_name)
   end
 
-  defp replicate(source, target, rep_options \\ []) do
-    headers = Keyword.get(rep_options, :headers, [])
-    body = Keyword.get(rep_options, :body, %{})
-
-    body =
-      body
-      |> Map.put("source", source)
-      |> Map.put("target", target)
-
-    retry_until(
-      fn ->
-        resp = Couch.post("/_replicate", headers: headers, body: body, timeout: 10_000)
-        assert HTTPotion.Response.success?(resp)
-        assert resp.status_code == 200
-        assert resp.body["ok"]
-        resp
-      end,
-      500,
-      20_000
-    )
-  end
-
   defp save_as(db_name, doc, options) do
     session = Keyword.get(options, :use_session)
     expect_response = Keyword.get(options, :expect_response, [201, 202])