This is an automated email from the ASF dual-hosted git repository.

garren pushed a commit to branch elixir-suite
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/elixir-suite by this push:
     new 96f79d6  Port conflicts.js (#1487)
96f79d6 is described below

commit 96f79d6113611b79465676a216b8372dce3b2754
Author: Jay Doane <[email protected]>
AuthorDate: Tue Aug 14 02:50:43 2018 -0700

    Port conflicts.js (#1487)
---
 test/elixir/test/conflicts_test.exs | 108 ++++++++++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/test/elixir/test/conflicts_test.exs 
b/test/elixir/test/conflicts_test.exs
new file mode 100644
index 0000000..d744cf7
--- /dev/null
+++ b/test/elixir/test/conflicts_test.exs
@@ -0,0 +1,108 @@
+defmodule RevisionTest do
+  use CouchTestCase
+
+  @moduletag :conflicts
+
+  @moduledoc """
+  Test CouchDB conflicts
+  This is a port of conflicts.js
+  (but is arguably more focused on revisions than conflicts)
+  """
+
+  setup context do
+    # Generate a doc with _rev field for each test
+    doc = %{_id: "doc-1", a: 1, b: 1}
+    doc = rev(doc, put(context[:db_name], doc))
+    %{doc: doc}
+  end
+
+  @tag :with_db
+  test "multiple updates with same _rev raise conflict errors", context do
+    db = context[:db_name]
+    doc = context[:doc]
+    doc2 = %{doc | a: 2, b: 2} # doc and doc2 have same _rev
+    _doc = rev(doc, put(db, doc)) # doc updated with new _rev
+    assert_conflict Couch.put("/#{db}/#{doc2._id}", [body: doc2])
+
+    resp = Couch.get("/#{db}/_changes")
+    assert length(resp.body["results"]) == 1
+
+    doc2 = Map.delete(doc2, :_rev)
+    assert_conflict(Couch.put("/#{db}/#{doc2._id}", [body: doc2]))
+  end
+
+  @tag :with_db
+  test "mismatched rev in body and query string returns error", context do
+    db = context[:db_name]
+    doc = context[:doc]
+    resp = Couch.put("/#{db}/#{doc._id}?rev=1-foobar", [body: doc])
+    expected_reason = "Document rev from request body and query string " <>
+      "have different values"
+    assert_bad_request(resp, expected_reason)
+  end
+
+  @tag :with_db
+  test "mismatched rev in body and etag returns error", context do
+    opts = [body: context[:doc], headers: [{:"If-Match", "1-foobar"}]]
+    resp = Couch.put("/#{context[:db_name]}/foobar", opts)
+    expected_reason = "Document rev and etag have different values"
+    assert_bad_request(resp, expected_reason)
+  end
+
+  @tag :with_db
+  test "`new_edits: false` prevents bulk updates (COUCHDB-1178)", context do
+    db = context[:db_name]
+
+    ddoc = %{_id: "_design/couchdb-1178", validate_doc_update: "function(){}"}
+    assert put(db, ddoc)["ok"] == true
+
+    r0 = %{_id: "doc", val: "r0"}
+    r1 = %{_id: "doc", val: "r1", _rev: "1-47f3268e7546965196b57572099f4372"}
+    r2 = %{_id: "doc", val: "r2", _rev: "2-1d8171ab3a91475cfece749291e6f897"}
+    r3 = %{_id: "doc", val: "r3", _rev: "3-3fb0a342d2ce092fdcc77856dbe8a2ef"}
+    assert put(db, r0)["ok"] == true
+    assert put(db, r1)["ok"] == true
+    assert put(db, r2)["ok"] == true
+    # N.b. that we *do not* put r3
+
+    expected = %{
+      "_id" => "doc",
+      "_rev" => r3._rev,
+      "_revisions" => %{
+        "ids" => (for r <- [r3._rev, r2._rev, r1._rev], do: suffix(r)),
+        "start" => 3},
+      "val" => r2.val}
+    assert Couch.get("/#{db}/doc?revs=true").body == expected
+
+    opts = [body: %{docs: [r3, r2, r1], new_edits: false}]
+    assert Couch.post("/#{db}/_bulk_docs", opts).body == []
+  end
+
+
+  defp put(db, doc) do
+    Couch.put("/#{db}/#{doc._id}", [body: doc]).body
+  end
+
+  # Update doc's _rev entry with request result
+  @spec rev(map(), map()) :: map()
+  defp rev(doc = %{_id: id}, %{"id" => id, "rev" => rev}) do
+    Map.put(doc, :_rev, rev)
+  end
+
+  defp suffix(rev) do
+    hd(tl(String.split(rev, "-")))
+  end
+
+  defp assert_conflict(resp) do
+    assert resp.status_code == 409
+    assert resp.body["error"] == "conflict"
+    assert resp.body["reason"] == "Document update conflict."
+  end
+
+  defp assert_bad_request(resp, reason) do
+    assert resp.status_code == 400
+    assert resp.body["error"] == "bad_request"
+    assert resp.body["reason"] == reason
+  end
+
+end

Reply via email to