blob: 9a16d481dae74d324dca474587062824b5b4cada [file] [log] [blame]
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