diff options
author | Juanjo Rodriguez <juanjo@apache.org> | 2020-05-09 20:31:15 +0200 |
---|---|---|
committer | Juanjo Rodriguez <jjrodrig@gmail.com> | 2020-05-26 22:40:11 +0200 |
commit | 08a0c6b6ff39045c0df7f40b57777afb6dbbd89f (patch) | |
tree | a8066ef158cf98fd05c980e2ec93b98c23179fdd | |
parent | 474cb720695e807eeee405947d2ed1f45bb78a65 (diff) | |
download | couchdb-08a0c6b6ff39045c0df7f40b57777afb6dbbd89f.tar.gz |
Port rev_stemming into elixir
-rw-r--r-- | test/elixir/README.md | 2 | ||||
-rw-r--r-- | test/elixir/test/rev_stemming_test.exs | 193 | ||||
-rw-r--r-- | test/javascript/tests/rev_stemming.js | 1 |
3 files changed, 195 insertions, 1 deletions
diff --git a/test/elixir/README.md b/test/elixir/README.md index bb9b4d2da..dfa4c62b3 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 000000000..51e959b48 --- /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 238868f60..725c0f1c9 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(); |