summaryrefslogtreecommitdiff
path: root/test/elixir/test/rev_stemming_test.exs
diff options
context:
space:
mode:
Diffstat (limited to 'test/elixir/test/rev_stemming_test.exs')
-rw-r--r--test/elixir/test/rev_stemming_test.exs157
1 files changed, 157 insertions, 0 deletions
diff --git a/test/elixir/test/rev_stemming_test.exs b/test/elixir/test/rev_stemming_test.exs
new file mode 100644
index 000000000..9a16d481d
--- /dev/null
+++ b/test/elixir/test/rev_stemming_test.exs
@@ -0,0 +1,157 @@
+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)
+
+ # 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
+
+ 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
+
+end