diff options
author | Joan Touzet <wohali@users.noreply.github.com> | 2018-11-27 23:30:09 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-27 23:30:09 -0500 |
commit | 45eba6ee925c253cc99653a0d0fc3707b4d74417 (patch) | |
tree | 821d4f46d2bb7cb62c918b74c282d3416a1f555a | |
parent | fd03aa409a5a040f98eb934df3c4cd5d5bf1acd9 (diff) | |
parent | 7ace576b83003ecdd5d77a8c2f314978de305d3f (diff) | |
download | couchdb-45eba6ee925c253cc99653a0d0fc3707b4d74417.tar.gz |
Merge pull request #1767 from van-mronov/mix-format
Check code format before running elixir test suite
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | Makefile.win | 5 | ||||
-rw-r--r-- | test/elixir/.formatter.exs | 6 | ||||
-rw-r--r-- | test/elixir/lib/couch.ex | 120 | ||||
-rw-r--r-- | test/elixir/mix.exs | 2 | ||||
-rw-r--r-- | test/elixir/test/all_docs_test.exs | 28 | ||||
-rw-r--r-- | test/elixir/test/basics_test.exs | 71 | ||||
-rw-r--r-- | test/elixir/test/batch_save_test.exs | 8 | ||||
-rw-r--r-- | test/elixir/test/bulk_docs_test.exs | 63 | ||||
-rw-r--r-- | test/elixir/test/compact_test.exs | 27 | ||||
-rw-r--r-- | test/elixir/test/config_test.exs | 49 | ||||
-rw-r--r-- | test/elixir/test/conflicts_test.exs | 27 | ||||
-rw-r--r-- | test/elixir/test/helper_test.exs | 19 | ||||
-rw-r--r-- | test/elixir/test/lots_of_docs_test.exs | 199 | ||||
-rw-r--r-- | test/elixir/test/reduce_test.exs | 164 | ||||
-rw-r--r-- | test/elixir/test/replication_test.exs | 334 | ||||
-rw-r--r-- | test/elixir/test/rewrite_test.exs | 17 | ||||
-rw-r--r-- | test/elixir/test/security_validation_test.exs | 45 | ||||
-rw-r--r-- | test/elixir/test/test_helper.exs | 87 | ||||
-rw-r--r-- | test/elixir/test/uuids_test.exs | 16 | ||||
-rw-r--r-- | test/elixir/test/view_collation_test.exs | 21 |
21 files changed, 807 insertions, 507 deletions
@@ -172,10 +172,14 @@ soak-eunit: couch while [ $$? -eq 0 ] ; do $(REBAR) -r eunit $(EUNIT_OPTS) ; done .PHONY: elixir -elixir: +elixir: elixir-check-formatted @rm -rf dev/lib @dev/run -a adm:pass --no-eval test/elixir/run +.PHONY: elixir-check-formatted +elixir-check-formatted: + @cd test/elixir/ && mix format --check-formatted + .PHONY: javascript # target: javascript - Run JavaScript test suites or specific ones defined by suites option javascript: devclean diff --git a/Makefile.win b/Makefile.win index 6b62ba9fd..e57763b72 100644 --- a/Makefile.win +++ b/Makefile.win @@ -144,10 +144,13 @@ just-eunit: .PHONY: elixir -elixir: +elixir: elixir-check-formatted @del /s/q dev\lib 2> nul @dev\run -a adm:pass --no-eval test\elixir\run.cmd +.PHONY: elixir-check-formatted +elixir-check-formatted: + @cd test\elixir && mix format --check-formatted .PHONY: test-cluster-with-quorum test-cluster-with-quorum: devclean diff --git a/test/elixir/.formatter.exs b/test/elixir/.formatter.exs new file mode 100644 index 000000000..c79a3c2f9 --- /dev/null +++ b/test/elixir/.formatter.exs @@ -0,0 +1,6 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"], + line_length: 120, + rename_deprecated_at: "1.5.0" +] diff --git a/test/elixir/lib/couch.ex b/test/elixir/lib/couch.ex index 3d38cfee3..6801fd558 100644 --- a/test/elixir/lib/couch.ex +++ b/test/elixir/lib/couch.ex @@ -8,10 +8,11 @@ defmodule Couch.Session do def logout(sess) do headers = [ - "Content-Type": "application/x-www-form-urlencoded", - "X-CouchDB-WWW-Authenticate": "Cookie", - "Cookie": sess.cookie - ] + "Content-Type": "application/x-www-form-urlencoded", + "X-CouchDB-WWW-Authenticate": "Cookie", + Cookie: sess.cookie + ] + Couch.delete!("/_session", headers: headers) end @@ -28,17 +29,16 @@ defmodule Couch.Session do # if the need arises. def go(%Couch.Session{} = sess, method, url, opts) do - opts = Keyword.merge(opts, [cookie: sess.cookie]) + opts = Keyword.merge(opts, cookie: sess.cookie) Couch.request(method, url, opts) end def go!(%Couch.Session{} = sess, method, url, opts) do - opts = Keyword.merge(opts, [cookie: sess.cookie]) + opts = Keyword.merge(opts, cookie: sess.cookie) Couch.request!(method, url, opts) end end - defmodule Couch do use HTTPotion.Base @@ -52,24 +52,27 @@ defmodule Couch do def process_request_headers(headers, options) do headers = Keyword.put(headers, :"User-Agent", "couch-potion") - headers = if headers[:"Content-Type"] do - headers - else - Keyword.put(headers, :"Content-Type", "application/json") - end - case Keyword.get options, :cookie do + + headers = + if headers[:"Content-Type"] do + headers + else + Keyword.put(headers, :"Content-Type", "application/json") + end + + case Keyword.get(options, :cookie) do nil -> headers + cookie -> - Keyword.put headers, :"Cookie", cookie + Keyword.put(headers, :Cookie, cookie) end end - def process_options(options) do - if Keyword.get(options, :cookie) == nil do headers = Keyword.get(options, :headers, []) + if headers[:basic_auth] != nil or headers[:authorization] != nil do options else @@ -90,21 +93,21 @@ defmodule Couch do def process_response_body(headers, body) do if String.match?(headers[:"Content-Type"], ~r/application\/json/) do - body |> IO.iodata_to_binary |> :jiffy.decode([:return_maps]) + body |> IO.iodata_to_binary() |> :jiffy.decode([:return_maps]) else process_response_body(body) end end def login(userinfo) do - [user, pass] = String.split(userinfo, ":", [parts: 2]) + [user, pass] = String.split(userinfo, ":", parts: 2) login(user, pass) end def login(user, pass) do resp = Couch.post("/_session", body: %{:username => user, :password => pass}) true = resp.body["ok"] - cookie = resp.headers[:'set-cookie'] + cookie = resp.headers[:"set-cookie"] [token | _] = String.split(cookie, ";") %Couch.Session{cookie: token} end @@ -113,57 +116,74 @@ defmodule Couch do # https://github.com/myfreeweb/httpotion/commit/f3fa2f0bc3b9b400573942b3ba4628b48bc3c614 def handle_response(response) do case response do - { :ok, status_code, headers, body, _ } -> + {:ok, status_code, headers, body, _} -> processed_headers = process_response_headers(headers) + %HTTPotion.Response{ status_code: process_status_code(status_code), headers: processed_headers, body: process_response_body(processed_headers, body) } - { :ok, status_code, headers, body } -> + + {:ok, status_code, headers, body} -> processed_headers = process_response_headers(headers) + %HTTPotion.Response{ status_code: process_status_code(status_code), headers: processed_headers, body: process_response_body(processed_headers, body) } - { :ibrowse_req_id, id } -> - %HTTPotion.AsyncResponse{ id: id } - { :error, { :conn_failed, { :error, reason }}} -> - %HTTPotion.ErrorResponse{ message: error_to_string(reason)} - { :error, :conn_failed } -> - %HTTPotion.ErrorResponse{ message: "conn_failed"} - { :error, reason } -> - %HTTPotion.ErrorResponse{ message: error_to_string(reason)} + + {:ibrowse_req_id, id} -> + %HTTPotion.AsyncResponse{id: id} + + {:error, {:conn_failed, {:error, reason}}} -> + %HTTPotion.ErrorResponse{message: error_to_string(reason)} + + {:error, :conn_failed} -> + %HTTPotion.ErrorResponse{message: "conn_failed"} + + {:error, reason} -> + %HTTPotion.ErrorResponse{message: error_to_string(reason)} end end # Anther HACK: Until we can get process_request_headers/2 merged # upstream. - @spec process_arguments(atom, String.t, [{atom(), any()}]) :: %{} + @spec process_arguments(atom, String.t(), [{atom(), any()}]) :: %{} defp process_arguments(method, url, options) do - options = process_options(options) - - body = Keyword.get(options, :body, "") - headers = Keyword.merge Application.get_env(:httpotion, :default_headers, []), Keyword.get(options, :headers, []) - timeout = Keyword.get(options, :timeout, Application.get_env(:httpotion, :default_timeout, 5000)) - ib_options = Keyword.merge Application.get_env(:httpotion, :default_ibrowse, []), Keyword.get(options, :ibrowse, []) - follow_redirects = Keyword.get(options, :follow_redirects, Application.get_env(:httpotion, :default_follow_redirects, false)) - - ib_options = if stream_to = Keyword.get(options, :stream_to), do: Keyword.put(ib_options, :stream_to, spawn(__MODULE__, :transformer, [stream_to, method, url, options])), else: ib_options - ib_options = if user_password = Keyword.get(options, :basic_auth) do - {user, password} = user_password - Keyword.put(ib_options, :basic_auth, { to_charlist(user), to_charlist(password) }) - else - ib_options - end + options = process_options(options) + + body = Keyword.get(options, :body, "") + headers = Keyword.merge(Application.get_env(:httpotion, :default_headers, []), Keyword.get(options, :headers, [])) + timeout = Keyword.get(options, :timeout, Application.get_env(:httpotion, :default_timeout, 5000)) + + ib_options = + Keyword.merge(Application.get_env(:httpotion, :default_ibrowse, []), Keyword.get(options, :ibrowse, [])) + + follow_redirects = + Keyword.get(options, :follow_redirects, Application.get_env(:httpotion, :default_follow_redirects, false)) + + ib_options = + if stream_to = Keyword.get(options, :stream_to), + do: Keyword.put(ib_options, :stream_to, spawn(__MODULE__, :transformer, [stream_to, method, url, options])), + else: ib_options + + ib_options = + if user_password = Keyword.get(options, :basic_auth) do + {user, password} = user_password + Keyword.put(ib_options, :basic_auth, {to_charlist(user), to_charlist(password)}) + else + ib_options + end %{ - method: method, - url: url |> to_string |> process_url(options) |> to_charlist, - body: body |> process_request_body, - headers: headers |> process_request_headers(options) |> Enum.map(fn ({k, v}) -> { to_charlist(k), to_charlist(v) } end), - timeout: timeout, + method: method, + url: url |> to_string |> process_url(options) |> to_charlist, + body: body |> process_request_body, + headers: + headers |> process_request_headers(options) |> Enum.map(fn {k, v} -> {to_charlist(k), to_charlist(v)} end), + timeout: timeout, ib_options: ib_options, follow_redirects: follow_redirects } diff --git a/test/elixir/mix.exs b/test/elixir/mix.exs index f6a493888..e9ab98c7e 100644 --- a/test/elixir/mix.exs +++ b/test/elixir/mix.exs @@ -6,7 +6,7 @@ defmodule Foo.Mixfile do app: :foo, version: "0.1.0", elixir: "~> 1.5", - start_permanent: Mix.env == :prod, + start_permanent: Mix.env() == :prod, deps: deps() ] end diff --git a/test/elixir/test/all_docs_test.exs b/test/elixir/test/all_docs_test.exs index 2fd608dc6..b34f05470 100644 --- a/test/elixir/test/all_docs_test.exs +++ b/test/elixir/test/all_docs_test.exs @@ -14,10 +14,10 @@ defmodule AllDocsTest do @tag :with_db test "All Docs tests", context do db_name = context[:db_name] - resp1 = Couch.post("/#{db_name}", [body: %{:_id => "0", :a => 1, :b => 1}]).body - resp2 = Couch.post("/#{db_name}", [body: %{:_id => "3", :a => 4, :b => 16}]).body - resp3 = Couch.post("/#{db_name}", [body: %{:_id => "1", :a => 2, :b => 4}]).body - resp4 = Couch.post("/#{db_name}", [body: %{:_id => "2", :a => 3, :b => 9}]).body + resp1 = Couch.post("/#{db_name}", body: %{:_id => "0", :a => 1, :b => 1}).body + resp2 = Couch.post("/#{db_name}", body: %{:_id => "3", :a => 4, :b => 16}).body + resp3 = Couch.post("/#{db_name}", body: %{:_id => "1", :a => 2, :b => 4}).body + resp4 = Couch.post("/#{db_name}", body: %{:_id => "2", :a => 3, :b => 9}).body assert resp1["ok"] assert resp2["ok"] @@ -30,6 +30,7 @@ defmodule AllDocsTest do resp = Couch.get("/#{db_name}/_all_docs").body rows = resp["rows"] assert resp["total_rows"] == length(rows) + Enum.each(rows, fn row -> assert row["id"] >= "0" && row["id"] <= "4" end) @@ -44,14 +45,19 @@ defmodule AllDocsTest do assert resp["offset"] == 2 # Confirm that queries may assume raw collation - resp = Couch.get("/#{db_name}/_all_docs", query: %{ - :startkey => "\"org.couchdb.user:\"", - :endkey => "\"org.couchdb.user;\"" - }) + resp = + Couch.get("/#{db_name}/_all_docs", + query: %{ + :startkey => "\"org.couchdb.user:\"", + :endkey => "\"org.couchdb.user;\"" + } + ) + assert length(resp.body["rows"]) == 0 # Check that all docs show up in the changes feed; order can vary resp = Couch.get("/#{db_name}/_changes").body + Enum.each(resp["results"], fn row -> assert Enum.member?(revs, hd(row["changes"])["rev"]), "doc #{row["id"]} should be in changes" end) @@ -103,7 +109,11 @@ defmodule AllDocsTest do assert Couch.put("/#{db_name}/3", query: %{:new_edits => false}, body: conflicted_doc2).body["ok"] win_rev = Couch.get("/#{db_name}/3").body - changes = Couch.get("/#{db_name}/_changes", query: %{:include_docs => true, :conflicts => true, :style => "all_docs"}).body["results"] + + changes = + Couch.get("/#{db_name}/_changes", query: %{:include_docs => true, :conflicts => true, :style => "all_docs"}).body[ + "results" + ] doc3 = Enum.find(changes, fn row -> row["id"] == "3" end) assert doc3["id"] == "3" diff --git a/test/elixir/test/basics_test.exs b/test/elixir/test/basics_test.exs index c71d05e6b..828e9f7d0 100644 --- a/test/elixir/test/basics_test.exs +++ b/test/elixir/test/basics_test.exs @@ -62,7 +62,7 @@ defmodule BasicsTest do @tag :with_db test "Create a document and save it to the database", context do - resp = Couch.post("/#{context[:db_name]}", [body: %{:_id => "0", :a => 1, :b => 1}]) + resp = Couch.post("/#{context[:db_name]}", body: %{:_id => "0", :a => 1, :b => 1}) assert resp.status_code == 201, "Should be 201 created" assert resp.body["id"], "Id should be present" assert resp.body["rev"], "Rev should be present" @@ -76,7 +76,7 @@ defmodule BasicsTest do test "Revs info status is good", context do db_name = context[:db_name] {:ok, _} = create_doc(db_name, sample_doc_foo()) - resp = Couch.get("/#{db_name}/foo", [query: %{:revs_info => true}]) + resp = Couch.get("/#{db_name}/foo", query: %{:revs_info => true}) assert hd(resp.body["_revs_info"])["status"] == "available", "Revs info is available" end @@ -84,16 +84,17 @@ defmodule BasicsTest do test "Make sure you can do a seq=true option", context do db_name = context[:db_name] {:ok, _} = create_doc(db_name, sample_doc_foo()) - resp = Couch.get("/#{db_name}/foo", [query: %{:local_seq => true}]) + resp = Couch.get("/#{db_name}/foo", query: %{:local_seq => true}) assert resp.body["_local_seq"] == 1, "Local seq value == 1" end @tag :with_db test "Can create several documents", context do db_name = context[:db_name] - assert Couch.post("/#{db_name}", [body: %{:_id => "1", :a => 2, :b => 4}]).body["ok"] - assert Couch.post("/#{db_name}", [body: %{:_id => "2", :a => 3, :b => 9}]).body["ok"] - assert Couch.post("/#{db_name}", [body: %{:_id => "3", :a => 4, :b => 16}]).body["ok"] + assert Couch.post("/#{db_name}", body: %{:_id => "1", :a => 2, :b => 4}).body["ok"] + assert Couch.post("/#{db_name}", body: %{:_id => "2", :a => 3, :b => 9}).body["ok"] + assert Couch.post("/#{db_name}", body: %{:_id => "3", :a => 4, :b => 16}).body["ok"] + retry_until(fn -> Couch.get("/#{db_name}").body["doc_count"] == 3 end) @@ -105,20 +106,20 @@ defmodule BasicsTest do db_name = context[:db_name] doc = %{:_id => "COUCHDB-954", :a => 1} - resp1 = Couch.post("/#{db_name}", [body: doc]) + resp1 = Couch.post("/#{db_name}", body: doc) assert resp1.body["ok"] old_rev = resp1.body["rev"] doc = Map.put(doc, :_rev, old_rev) - resp2 = Couch.post("/#{db_name}", [body: doc]) + resp2 = Couch.post("/#{db_name}", body: doc) assert resp2.body["ok"] _new_rev = resp2.body["rev"] # TODO: enable chunked encoding - #resp3 = Couch.get("/#{db_name}/COUCHDB-954", [query: %{:open_revs => "[#{old_rev}, #{new_rev}]"}]) - #assert length(resp3.body) == 2, "Should get two revisions back" - #resp3 = Couch.get("/#{db_name}/COUCHDB-954", [query: %{:open_revs => "[#{old_rev}]", :latest => true}]) - #assert resp3.body["_rev"] == new_rev + # resp3 = Couch.get("/#{db_name}/COUCHDB-954", [query: %{:open_revs => "[#{old_rev}, #{new_rev}]"}]) + # assert length(resp3.body) == 2, "Should get two revisions back" + # resp3 = Couch.get("/#{db_name}/COUCHDB-954", [query: %{:open_revs => "[#{old_rev}]", :latest => true}]) + # assert resp3.body["_rev"] == new_rev end @tag :with_db @@ -130,12 +131,12 @@ defmodule BasicsTest do red_doc = %{:views => %{:baz => %{:map => map_fun, :reduce => red_fun}}} # Bootstrap database and ddoc - assert Couch.post("/#{db_name}", [body: %{:_id => "0", :a => 1, :b => 1}]).body["ok"] - assert Couch.post("/#{db_name}", [body: %{:_id => "1", :a => 2, :b => 4}]).body["ok"] - assert Couch.post("/#{db_name}", [body: %{:_id => "2", :a => 3, :b => 9}]).body["ok"] - assert Couch.post("/#{db_name}", [body: %{:_id => "3", :a => 4, :b => 16}]).body["ok"] - assert Couch.put("/#{db_name}/_design/foo", [body: map_doc]).body["ok"] - assert Couch.put("/#{db_name}/_design/bar", [body: red_doc]).body["ok"] + assert Couch.post("/#{db_name}", body: %{:_id => "0", :a => 1, :b => 1}).body["ok"] + assert Couch.post("/#{db_name}", body: %{:_id => "1", :a => 2, :b => 4}).body["ok"] + assert Couch.post("/#{db_name}", body: %{:_id => "2", :a => 3, :b => 9}).body["ok"] + assert Couch.post("/#{db_name}", body: %{:_id => "3", :a => 4, :b => 16}).body["ok"] + assert Couch.put("/#{db_name}/_design/foo", body: map_doc).body["ok"] + assert Couch.put("/#{db_name}/_design/bar", body: red_doc).body["ok"] assert Couch.get("/#{db_name}").body["doc_count"] == 6 # Initial view query test @@ -146,17 +147,20 @@ defmodule BasicsTest do # Modified doc and test for updated view results doc0 = Couch.get("/#{db_name}/0").body doc0 = Map.put(doc0, :a, 4) - assert Couch.put("/#{db_name}/0", [body: doc0]).body["ok"] + assert Couch.put("/#{db_name}/0", body: doc0).body["ok"] + retry_until(fn -> Couch.get("/#{db_name}/_design/foo/_view/baz").body["total_rows"] == 2 end) # Write 2 more docs and test for updated view results - assert Couch.post("/#{db_name}", [body: %{:a => 3, :b => 9}]).body["ok"] - assert Couch.post("/#{db_name}", [body: %{:a => 4, :b => 16}]).body["ok"] + assert Couch.post("/#{db_name}", body: %{:a => 3, :b => 9}).body["ok"] + assert Couch.post("/#{db_name}", body: %{:a => 4, :b => 16}).body["ok"] + retry_until(fn -> Couch.get("/#{db_name}/_design/foo/_view/baz").body["total_rows"] == 3 end) + assert Couch.get("/#{db_name}").body["doc_count"] == 8 # Test reduce function @@ -166,9 +170,11 @@ defmodule BasicsTest do # Delete doc and test for updated view results doc0 = Couch.get("/#{db_name}/0").body assert Couch.delete("/#{db_name}/0?rev=#{doc0["_rev"]}").body["ok"] + retry_until(fn -> Couch.get("/#{db_name}/_design/foo/_view/baz").body["total_rows"] == 2 end) + assert Couch.get("/#{db_name}").body["doc_count"] == 7 assert Couch.get("/#{db_name}/0").status_code == 404 refute Couch.get("/#{db_name}/0?rev=#{doc0["_rev"]}").status_code == 404 @@ -177,7 +183,7 @@ defmodule BasicsTest do @tag :with_db test "POST doc response has a Location header", context do db_name = context[:db_name] - resp = Couch.post("/#{db_name}", [body: %{:foo => :bar}]) + resp = Couch.post("/#{db_name}", body: %{:foo => :bar}) assert resp.body["ok"] loc = resp.headers["Location"] assert loc, "should have a Location header" @@ -189,7 +195,7 @@ defmodule BasicsTest do @tag :with_db test "POST doc with an _id field isn't overwritten by uuid", context do db_name = context[:db_name] - resp = Couch.post("/#{db_name}", [body: %{:_id => "oppossum", :yar => "matey"}]) + resp = Couch.post("/#{db_name}", body: %{:_id => "oppossum", :yar => "matey"}) assert resp.body["ok"] assert resp.body["id"] == "oppossum" assert Couch.get("/#{db_name}/oppossum").body["yar"] == "matey" @@ -199,7 +205,7 @@ defmodule BasicsTest do @tag :with_db test "PUT doc has a Location header", context do db_name = context[:db_name] - resp = Couch.put("/#{db_name}/newdoc", [body: %{:a => 1}]) + resp = Couch.put("/#{db_name}/newdoc", body: %{:a => 1}) assert String.ends_with?(resp.headers["location"], "/#{db_name}/newdoc") # TODO: make protocol check use defined protocol value assert String.starts_with?(resp.headers["location"], "http") @@ -214,6 +220,7 @@ defmodule BasicsTest do @tag :with_db test "Check for invalid document members", context do db_name = context[:db_name] + bad_docs = [ {:goldfish, %{:_zing => 4}}, {:zebrafish, %{:_zoom => "hello"}}, @@ -222,11 +229,11 @@ defmodule BasicsTest do ] Enum.each(bad_docs, fn {id, doc} -> - resp = Couch.put("/#{db_name}/#{id}", [body: doc]) + resp = Couch.put("/#{db_name}/#{id}", body: doc) assert resp.status_code == 400 assert resp.body["error"] == "doc_validation" - resp = Couch.post("/#{db_name}", [body: doc]) + resp = Couch.post("/#{db_name}", body: doc) assert resp.status_code == 400 assert resp.body["error"] == "doc_validation" end) @@ -235,7 +242,7 @@ defmodule BasicsTest do @tag :with_db test "PUT error when body not an object", context do db_name = context[:db_name] - resp = Couch.put("/#{db_name}/bar", [body: "[]"]) + resp = Couch.put("/#{db_name}/bar", body: "[]") assert resp.status_code == 400 assert resp.body["error"] == "bad_request" assert resp.body["reason"] == "Document must be a JSON object" @@ -244,7 +251,7 @@ defmodule BasicsTest do @tag :with_db test "_bulk_docs POST error when body not an object", context do db_name = context[:db_name] - resp = Couch.post("/#{db_name}/_bulk_docs", [body: "[]"]) + resp = Couch.post("/#{db_name}/_bulk_docs", body: "[]") assert resp.status_code == 400 assert resp.body["error"] == "bad_request" assert resp.body["reason"] == "Request body must be a JSON object" @@ -253,12 +260,12 @@ defmodule BasicsTest do @tag :with_db test "_all_docs POST error when multi-get is not a {'key': [...]} structure", context do db_name = context[:db_name] - resp = Couch.post("/#{db_name}/_all_docs", [body: "[]"]) + resp = Couch.post("/#{db_name}/_all_docs", body: "[]") assert resp.status_code == 400 assert resp.body["error"] == "bad_request" assert resp.body["reason"] == "Request body must be a JSON object" - resp = Couch.post("/#{db_name}/_all_docs", [body: %{:keys => 1}]) + resp = Couch.post("/#{db_name}/_all_docs", body: %{:keys => 1}) assert resp.status_code == 400 assert resp.body["error"] == "bad_request" assert resp.body["reason"] == "`keys` body member must be an array." @@ -270,7 +277,9 @@ defmodule BasicsTest do resp = Couch.delete("/#{db_name}/?rev=foobarbaz") assert resp.status_code == 400, "should return a bad request" assert resp.body["error"] == "bad_request" - assert resp.body["reason"] == "You tried to DELETE a database with a ?=rev parameter. Did you mean to DELETE a document instead?" + + assert resp.body["reason"] == + "You tried to DELETE a database with a ?=rev parameter. Did you mean to DELETE a document instead?" end @tag :pending diff --git a/test/elixir/test/batch_save_test.exs b/test/elixir/test/batch_save_test.exs index 4863a8d03..030fcdfba 100644 --- a/test/elixir/test/batch_save_test.exs +++ b/test/elixir/test/batch_save_test.exs @@ -12,19 +12,19 @@ defmodule BatchSaveTest do @tag :with_db test "batch put", context do - path_fun = &("/#{&1}/#{&2}") + path_fun = &"/#{&1}/#{&2}" run(&Couch.put/2, path_fun, context[:db_name], @doc_count) end @tag :with_db test "batch post", context do - path_fun = fn(db_name, _) -> "/#{db_name}" end + path_fun = fn db_name, _ -> "/#{db_name}" end run(&Couch.post/2, path_fun, context[:db_name], @doc_count) end @tag :with_db test "batch put with identical doc ids", context do - path_fun = fn(db_name, _) -> "/#{db_name}/foo" end + path_fun = fn db_name, _ -> "/#{db_name}/foo" end run(&Couch.put/2, path_fun, context[:db_name], 1) end @@ -34,9 +34,9 @@ defmodule BatchSaveTest do resp = req_fun.(path_fun.(db_name, i), opts) assert resp.body["ok"] and resp.status_code == 202 end + retry_until(fn -> Couch.get("/#{db_name}").body["doc_count"] == expected_doc_count end) end - end diff --git a/test/elixir/test/bulk_docs_test.exs b/test/elixir/test/bulk_docs_test.exs index f6676a6b8..c2e3eedd6 100644 --- a/test/elixir/test/bulk_docs_test.exs +++ b/test/elixir/test/bulk_docs_test.exs @@ -18,27 +18,29 @@ defmodule BulkDocsTest do assert revs_start_with(resp.body, "1-") docs = rev(docs, resp.body) # Modify each doc's `string` field and re-post - docs = Enum.map(docs, fn(doc = %{string: string}) -> - %{doc | string: string <> ".00"} - end) + docs = + Enum.map(docs, fn doc = %{string: string} -> + %{doc | string: string <> ".00"} + end) + resp = bulk_post(docs, db) assert revs_start_with(resp.body, "2-") docs = rev(docs, resp.body) # Confirm changes were applied for each doc - assert Enum.all?(docs, fn(doc) -> - String.ends_with?( - Couch.get("/#{db}/#{doc._id}").body["string"], ".00") - end) + assert Enum.all?(docs, fn doc -> + String.ends_with?(Couch.get("/#{db}/#{doc._id}").body["string"], ".00") + end) + docs = Enum.map(docs, &Map.put(&1, :_deleted, true)) resp = bulk_post(docs, db) assert revs_start_with(resp.body, "3-") # Confirm docs were deleted - assert Enum.all?(docs, fn(doc) -> - resp = Couch.get("/#{db}/#{doc._id}") - assert resp.status_code == 404 - assert resp.body["error"] == "not_found" - assert resp.body["reason"] == "deleted" - end) + assert Enum.all?(docs, fn doc -> + resp = Couch.get("/#{db}/#{doc._id}") + assert resp.status_code == 404 + assert resp.body["error"] == "not_found" + assert resp.body["reason"] == "deleted" + end) end @tag :with_db @@ -50,10 +52,10 @@ defmodule BulkDocsTest do docs = rev(docs, resp.body) # Update just the first doc to create a conflict in subsequent bulk update doc = hd(docs) - resp = Couch.put("/#{db}/#{doc._id}", [body: doc]) + resp = Couch.put("/#{db}/#{doc._id}", body: doc) assert resp.status_code == 201 # Attempt to delete all docs - docs = Enum.map(docs, fn(doc) -> Map.put(doc, :_deleted, true) end) + docs = Enum.map(docs, fn doc -> Map.put(doc, :_deleted, true) end) resp = bulk_post(docs, db) # Confirm first doc not updated, and result has no rev field res = hd(resp.body) @@ -85,26 +87,25 @@ defmodule BulkDocsTest do test "bulk docs raises conflict error for combined update & delete", ctx do db = ctx[:db_name] doc = %{_id: "id", val: "val"} - resp = Couch.put("/#{db}/#{doc._id}", [body: doc]) + resp = Couch.put("/#{db}/#{doc._id}", body: doc) doc = rev(doc, resp.body) update = %{doc | val: "newval"} delete = Map.put(doc, :_deleted, true) body = bulk_post([update, delete], db).body assert Enum.count(body, &(Map.get(&1, "error") == "conflict")) == 1 - assert Enum.count(body, &(Map.get(&1, "rev"))) == 1 + assert Enum.count(body, &Map.get(&1, "rev")) == 1 end @tag :with_db test "bulk docs raises error for missing `docs` parameter", ctx do docs = [%{foo: "bar"}] - resp = Couch.post("/#{ctx[:db_name]}/_bulk_docs", [body: %{doc: docs}]) + resp = Couch.post("/#{ctx[:db_name]}/_bulk_docs", body: %{doc: docs}) assert_bad_request(resp, "POST body must include `docs` parameter.") end @tag :with_db test "bulk docs raises error for invlaid `docs` parameter", ctx do - resp = Couch.post( - "/#{ctx[:db_name]}/_bulk_docs", [body: %{docs: "foo"}]) + resp = Couch.post("/#{ctx[:db_name]}/_bulk_docs", body: %{docs: "foo"}) assert_bad_request(resp, "`docs` parameter must be an array.") end @@ -117,30 +118,27 @@ defmodule BulkDocsTest do @tag :with_db test "bulk docs emits conflict error for duplicate doc `_id`s", ctx do - docs = [ - %{_id: "0", a: 0}, - %{_id: "1", a: 1}, - %{_id: "1", a: 2}, - %{_id: "3", a: 3}] + docs = [%{_id: "0", a: 0}, %{_id: "1", a: 1}, %{_id: "1", a: 2}, %{_id: "3", a: 3}] rows = bulk_post(docs, ctx[:db_name]).body assert Enum.at(rows, 1)["id"] == "1" assert Enum.at(rows, 1)["ok"] assert Enum.at(rows, 2)["error"] == "conflict" end - defp bulk_post(docs, db) do - resp = Couch.post("/#{db}/_bulk_docs", [body: %{docs: docs}]) + resp = Couch.post("/#{db}/_bulk_docs", body: %{docs: docs}) + assert resp.status_code == 201 and length(resp.body) == length(docs), - """ - Expected 201 and the same number of response rows as in request, but got - #{pretty_inspect resp} - """ + """ + Expected 201 and the same number of response rows as in request, but got + #{pretty_inspect(resp)} + """ + resp end defp revs_start_with(rows, prefix) do - Enum.all?(rows, fn(%{"rev" => rev}) -> String.starts_with?(rev, prefix) end) + Enum.all?(rows, fn %{"rev" => rev} -> String.starts_with?(rev, prefix) end) end defp assert_bad_request(resp, reason) do @@ -148,5 +146,4 @@ defmodule BulkDocsTest do assert resp.body["error"] == "bad_request" assert resp.body["reason"] == reason end - end diff --git a/test/elixir/test/compact_test.exs b/test/elixir/test/compact_test.exs index 8ee20fa61..293f99a81 100644 --- a/test/elixir/test/compact_test.exs +++ b/test/elixir/test/compact_test.exs @@ -38,7 +38,6 @@ defmodule CompactTest do assert final_data_size < deleted_data_size end - defp assert_attachment_available(db) do resp = Couch.get("/#{db}/#{@att_doc_id}/#{@att_name}") assert resp.body == @att_plaintext @@ -48,36 +47,40 @@ defmodule CompactTest do defp populate(db) do docs = create_docs(0..19) - resp = Couch.post("/#{db}/_bulk_docs", [body: %{docs: docs}]) + resp = Couch.post("/#{db}/_bulk_docs", body: %{docs: docs}) assert resp.status_code == 201 docs = rev(docs, resp.body) + doc = %{ _id: "#{@att_doc_id}", - _attachments: %{ - "#{@att_name}": %{ - content_type: "text/plain", - data: Base.encode64(@att_plaintext)}}} - resp = Couch.put("/#{db}/#{doc._id}", [body: doc]) + _attachments: %{"#{@att_name}": %{content_type: "text/plain", data: Base.encode64(@att_plaintext)}} + } + + resp = Couch.put("/#{db}/#{doc._id}", body: doc) assert resp.status_code == 201 docs end defp delete(db, docs) do docs = Enum.map(docs, &Map.put(&1, :_deleted, true)) - resp = Couch.post("/#{db}/_bulk_docs", [body: %{docs: docs}]) + resp = Couch.post("/#{db}/_bulk_docs", body: %{docs: docs}) assert resp.status_code == 201 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) + + 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 - end diff --git a/test/elixir/test/config_test.exs b/test/elixir/test/config_test.exs index c0e347b22..649a25b81 100644 --- a/test/elixir/test/config_test.exs +++ b/test/elixir/test/config_test.exs @@ -24,9 +24,11 @@ defmodule ConfigTest do url = "#{context[:config_url]}/#{section}/#{key}" headers = ["X-Couch-Persist": "false"] resp = Couch.put(url, headers: headers, body: :jiffy.encode(val)) + if status_assert do assert resp.status_code == status_assert end + resp.body end @@ -39,15 +41,19 @@ defmodule ConfigTest do end def get_config(context, section, key, status_assert) do - url = if key do - "#{context[:config_url]}/#{section}/#{key}" - else - "#{context[:config_url]}/#{section}" - end + url = + if key do + "#{context[:config_url]}/#{section}/#{key}" + else + "#{context[:config_url]}/#{section}" + end + resp = Couch.get(url) + if status_assert do assert resp.status_code == status_assert end + resp.body end @@ -58,6 +64,7 @@ defmodule ConfigTest do def delete_config(context, section, key, status_assert) do url = "#{context[:config_url]}/#{section}/#{key}" resp = Couch.delete(url) + if status_assert do assert resp.status_code == status_assert end @@ -73,7 +80,7 @@ defmodule ConfigTest do end test "Settings can be altered with undefined whitelist allowing any change", context do - refute context["config"]["httpd"]["config_whitelist"], "Default whitelist is empty" + refute context["config"]["httpd"]["config_whitelist"], "Default whitelist is empty" set_config(context, "test", "foo", "bar") assert get_config(context, "test")["foo"] == "bar" assert get_config(context, "test", "foo") == "bar" @@ -115,7 +122,9 @@ defmodule ConfigTest do end test "Non-2-tuples in the whitelist are ignored", context do - val = "[{httpd,config_whitelist}, these, {are}, {nOt, 2, tuples}, [so], [they, will], [all, become, noops], {test,foo}]" + val = + "[{httpd,config_whitelist}, these, {are}, {nOt, 2, tuples}, [so], [they, will], [all, become, noops], {test,foo}]" + set_config(context, "httpd", "config_whitelist", val) assert val == get_config(context, "httpd", "config_whitelist") set_config(context, "test", "foo", "PUT to whitelisted config variable") @@ -124,21 +133,35 @@ defmodule ConfigTest do test "Atoms, binaries, and strings suffice as whitelist sections and keys.", context do vals = ["{test,foo}", "{\"test\",\"foo\"}", "{<<\"test\">>,<<\"foo\">>}"] + Enum.each(vals, fn pair -> set_config(context, "httpd", "config_whitelist", "[{httpd,config_whitelist}, #{pair}") - pair_format = case String.at(pair, 1) do - "t" -> "tuple" - "\"" -> "string" - "<" -> "binary" - end + + pair_format = + case String.at(pair, 1) do + "t" -> "tuple" + "\"" -> "string" + "<" -> "binary" + end + set_config(context, "test", "foo", "PUT with #{pair_format}") delete_config(context, "test", "foo") end) + delete_config(context, "httpd", "config_whitelist") end test "Blacklist is functional", context do - sections = ["daemons", "external", "httpd_design_handlers", "httpd_db_handlers", "native_query_servers", "os_daemons", "query_servers"] + sections = [ + "daemons", + "external", + "httpd_design_handlers", + "httpd_db_handlers", + "native_query_servers", + "os_daemons", + "query_servers" + ] + Enum.each(sections, fn section -> set_config(context, section, "wohali", "rules", 403) end) diff --git a/test/elixir/test/conflicts_test.exs b/test/elixir/test/conflicts_test.exs index a27bd6fb6..5f54f11cc 100644 --- a/test/elixir/test/conflicts_test.exs +++ b/test/elixir/test/conflicts_test.exs @@ -20,24 +20,25 @@ defmodule RevisionTest do 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]) + # doc and doc2 have same _rev + doc2 = %{doc | a: 2, b: 2} + # doc updated with new _rev + _doc = rev(doc, put(db, doc)) + 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])) + 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" + 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 @@ -68,19 +69,18 @@ defmodule RevisionTest do expected = %{ "_id" => "doc", "_rev" => r3._rev, - "_revisions" => %{ - "ids" => (for r <- [r3._rev, r2._rev, r1._rev], do: suffix(r)), - "start" => 3}, - "val" => r2.val} + "_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 + Couch.put("/#{db}/#{doc._id}", body: doc).body end defp suffix(rev) do @@ -98,5 +98,4 @@ defmodule RevisionTest do assert resp.body["error"] == "bad_request" assert resp.body["reason"] == reason end - end diff --git a/test/elixir/test/helper_test.exs b/test/elixir/test/helper_test.exs index e2070c457..19d70eac8 100644 --- a/test/elixir/test/helper_test.exs +++ b/test/elixir/test/helper_test.exs @@ -6,23 +6,26 @@ defmodule HelperTest do """ test "retry_until handles boolean conditions", _context do - retry_until fn -> + retry_until(fn -> true - end + end) end test "retry_until handles assertions", _context do - retry_until fn -> + retry_until(fn -> assert true - end + end) end test "retry_until times out", _context do assert_raise RuntimeError, ~r/^timed out after \d+ ms$/, fn -> - retry_until fn -> - assert false - end, 1, 5 + retry_until( + fn -> + assert false + end, + 1, + 5 + ) end end - end diff --git a/test/elixir/test/lots_of_docs_test.exs b/test/elixir/test/lots_of_docs_test.exs index 4115f1c78..57e45afcd 100644 --- a/test/elixir/test/lots_of_docs_test.exs +++ b/test/elixir/test/lots_of_docs_test.exs @@ -1,95 +1,108 @@ defmodule LotsOfDocsTest do - use CouchTestCase - - @moduletag :lots_of_docs - @docs_range 0..499 - - @moduledoc """ - Test saving a semi-large quanitity of documents and do some view queries. - This is a port of the lots_of_docs.js suite - """ - - @tag :with_db - test "lots of docs with _all_docs", context do - db_name = context[:db_name] - @docs_range - |> create_docs() - |> Enum.chunk_every(100) - |> Enum.each(fn(docs) -> bulk_post(docs, db_name) end) - - %{"rows" => rows, "total_rows" => total_rows} = Couch.get("/#{db_name}/_all_docs").body - assert total_rows === Enum.count(@docs_range) - assert total_rows === Enum.count(rows) - @docs_range - |> Enum.map(fn(i) -> Integer.to_string(i) end) - |> Enum.sort() - |> Enum.with_index() - |> Enum.each(fn({value, index}) -> - assert Map.fetch!(Enum.at(rows, index), "key") === value - end) - - %{"rows" => desc_rows, "total_rows" => desc_total_rows} = Couch.get( - "/#{db_name}/_all_docs", - query: %{:descending => true} - ).body - assert desc_total_rows === Enum.count(@docs_range) - assert desc_total_rows === Enum.count(desc_rows) - @docs_range - |> Enum.map(fn(i) -> Integer.to_string(i) end) - |> Enum.sort() - |> Enum.reverse() - |> Enum.with_index() - |> Enum.each(fn({value, index}) -> - assert Map.fetch!(Enum.at(desc_rows, index), "key") === value - end) - end - - @tag :with_db - test "lots of docs with a regular view", context do - db_name = context[:db_name] - @docs_range - |> create_docs() - |> Enum.chunk_every(100) - |> Enum.each(fn(docs) -> bulk_post(docs, db_name) end) - - %{"rows" => rows, "total_rows" => total_rows} = query_view(db_name) - assert total_rows === Enum.count(rows) - assert total_rows === Enum.count(@docs_range) - Enum.each(@docs_range, fn(i) -> - assert Map.fetch!(Enum.at(rows, i), "key") === i - end) - - %{"rows" => desc_rows, "total_rows" => desc_total_rows} = query_view(db_name, "descending") - assert desc_total_rows === Enum.count(desc_rows) - assert desc_total_rows === Enum.count(@docs_range) - @docs_range - |> Enum.reverse() - |> Enum.with_index() - |> Enum.each(fn({value, index}) -> - assert Map.fetch!(Enum.at(desc_rows, index), "key") === value - end) - end - - defp query_view(db_name, sorting \\ "ascending") do - descending = if(sorting === "descending", do: true, else: false) - map_fun = "function(doc) { emit(doc.integer, null); }" - map_doc = %{:views => %{:view => %{:map => map_fun}}} - %{"rev" => rev} = Couch.put("/#{db_name}/_design/tempddoc", body: map_doc).body - response = Couch.get( - "/#{db_name}/_design/tempddoc/_view/view", - query: %{:descending => descending} - ).body - Couch.delete("/#{db_name}/_design/tempddoc?rev=#{rev}") - response - end - - defp bulk_post(docs, db) do - resp = Couch.post("/#{db}/_bulk_docs", [body: %{docs: docs}]) - assert resp.status_code == 201 and length(resp.body) == length(docs), - """ - Expected 201 and the same number of response rows as in request, but got - #{pretty_inspect resp} - """ - resp + use CouchTestCase + + @moduletag :lots_of_docs + @docs_range 0..499 + + @moduledoc """ + Test saving a semi-large quanitity of documents and do some view queries. + This is a port of the lots_of_docs.js suite + """ + + @tag :with_db + test "lots of docs with _all_docs", context do + db_name = context[:db_name] + + @docs_range + |> create_docs() + |> Enum.chunk_every(100) + |> Enum.each(fn docs -> bulk_post(docs, db_name) end) + + %{"rows" => rows, "total_rows" => total_rows} = Couch.get("/#{db_name}/_all_docs").body + assert total_rows === Enum.count(@docs_range) + assert total_rows === Enum.count(rows) + + @docs_range + |> Enum.map(fn i -> Integer.to_string(i) end) + |> Enum.sort() + |> Enum.with_index() + |> Enum.each(fn {value, index} -> + assert Map.fetch!(Enum.at(rows, index), "key") === value + end) + + %{"rows" => desc_rows, "total_rows" => desc_total_rows} = + Couch.get( + "/#{db_name}/_all_docs", + query: %{:descending => true} + ).body + + assert desc_total_rows === Enum.count(@docs_range) + assert desc_total_rows === Enum.count(desc_rows) + + @docs_range + |> Enum.map(fn i -> Integer.to_string(i) end) + |> Enum.sort() + |> Enum.reverse() + |> Enum.with_index() + |> Enum.each(fn {value, index} -> + assert Map.fetch!(Enum.at(desc_rows, index), "key") === value + end) + end + + @tag :with_db + test "lots of docs with a regular view", context do + db_name = context[:db_name] + + @docs_range + |> create_docs() + |> Enum.chunk_every(100) + |> Enum.each(fn docs -> bulk_post(docs, db_name) end) + + %{"rows" => rows, "total_rows" => total_rows} = query_view(db_name) + assert total_rows === Enum.count(rows) + assert total_rows === Enum.count(@docs_range) + + Enum.each(@docs_range, fn i -> + assert Map.fetch!(Enum.at(rows, i), "key") === i + end) + + %{"rows" => desc_rows, "total_rows" => desc_total_rows} = query_view(db_name, "descending") + assert desc_total_rows === Enum.count(desc_rows) + assert desc_total_rows === Enum.count(@docs_range) + + @docs_range + |> Enum.reverse() + |> Enum.with_index() + |> Enum.each(fn {value, index} -> + assert Map.fetch!(Enum.at(desc_rows, index), "key") === value + end) + end + + defp query_view(db_name, sorting \\ "ascending") do + descending = if(sorting === "descending", do: true, else: false) + map_fun = "function(doc) { emit(doc.integer, null); }" + map_doc = %{:views => %{:view => %{:map => map_fun}}} + %{"rev" => rev} = Couch.put("/#{db_name}/_design/tempddoc", body: map_doc).body + + response = + Couch.get( + "/#{db_name}/_design/tempddoc/_view/view", + query: %{:descending => descending} + ).body + + Couch.delete("/#{db_name}/_design/tempddoc?rev=#{rev}") + response + end + + defp bulk_post(docs, db) do + resp = Couch.post("/#{db}/_bulk_docs", body: %{docs: docs}) + + assert resp.status_code == 201 and length(resp.body) == length(docs), + """ + Expected 201 and the same number of response rows as in request, but got + #{pretty_inspect(resp)} + """ + + resp end -end
\ No newline at end of file +end diff --git a/test/elixir/test/reduce_test.exs b/test/elixir/test/reduce_test.exs index bba1658e3..5c90a2542 100644 --- a/test/elixir/test/reduce_test.exs +++ b/test/elixir/test/reduce_test.exs @@ -17,18 +17,20 @@ defmodule ReduceTest do db_name = context[:db_name] view_url = "/#{db_name}/_design/foo/_view/bar" num_docs = 500 + map = ~s""" function (doc) { emit(doc.integer, doc.integer); emit(doc.integer, doc.integer); }; """ + reduce = "function (keys, values) { return sum(values); };" red_doc = %{:views => %{:bar => %{:map => map, :reduce => reduce}}} - assert Couch.put("/#{db_name}/_design/foo", [body: red_doc]).body["ok"] + assert Couch.put("/#{db_name}/_design/foo", body: red_doc).body["ok"] docs = make_docs(1..num_docs) - assert Couch.post("/#{db_name}/_bulk_docs", [body: %{:docs => docs}, query: %{w: 3}]).status_code == 201 + assert Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => docs}, query: %{w: 3}).status_code == 201 rows = Couch.get(view_url).body["rows"] assert hd(rows)["value"] == 2 * summate(num_docs) @@ -53,6 +55,7 @@ defmodule ReduceTest do half_num_docs = Integer.floor_div(num_docs, 2) max = Integer.floor_div(num_docs, 30) + 1 + for i <- 1..max, i * 30 + 1 < half_num_docs do i = i * 30 + 1 query = %{:startkey => i, :endkey => num_docs - i} @@ -69,7 +72,8 @@ defmodule ReduceTest do reduce = "function (keys, values) { return sum(values); };" red_doc = %{:views => %{bar: %{map: map, reduce: reduce}}} - assert Couch.put("/#{db_name}/_design/foo", [body: red_doc]).body["ok"] + assert Couch.put("/#{db_name}/_design/foo", body: red_doc).body["ok"] + for i <- 1..5 do for j <- 0..9 do docs = [ @@ -85,8 +89,9 @@ defmodule ReduceTest do %{keys: ["d", "b"]}, %{keys: ["d", "c"]} ] - assert Couch.post("/#{db_name}/_bulk_docs", [body: %{docs: docs}, query: %{w: 3}]).status_code == 201 - total_docs = 1 + ((i - 1) * 10 * 11) + ((j + 1) * 11); + + assert Couch.post("/#{db_name}/_bulk_docs", body: %{docs: docs}, query: %{w: 3}).status_code == 201 + total_docs = 1 + (i - 1) * 10 * 11 + (j + 1) * 11 assert Couch.get("/#{db_name}").body["doc_count"] == total_docs end @@ -109,29 +114,29 @@ defmodule ReduceTest do # test group by the first element in the key array query = %{group_level: 2} rows = Couch.get(view_url, query: query).body["rows"] - assert Enum.at(rows, 0) == %{"key" => ["a"], "value" => 20*i} - assert Enum.at(rows, 1) == %{"key" => ["a","b"], "value" => 40*i} - assert Enum.at(rows, 2) == %{"key" => ["a","c"], "value" => 10*i} - assert Enum.at(rows, 3) == %{"key" => ["d"], "value" => 10*i} - assert Enum.at(rows, 4) == %{"key" => ["d","a"], "value" => 10*i} - assert Enum.at(rows, 5) == %{"key" => ["d","b"], "value" => 10*i} - assert Enum.at(rows, 6) == %{"key" => ["d","c"], "value" => 10*i} + assert Enum.at(rows, 0) == %{"key" => ["a"], "value" => 20 * i} + assert Enum.at(rows, 1) == %{"key" => ["a", "b"], "value" => 40 * i} + assert Enum.at(rows, 2) == %{"key" => ["a", "c"], "value" => 10 * i} + assert Enum.at(rows, 3) == %{"key" => ["d"], "value" => 10 * i} + assert Enum.at(rows, 4) == %{"key" => ["d", "a"], "value" => 10 * i} + assert Enum.at(rows, 5) == %{"key" => ["d", "b"], "value" => 10 * i} + assert Enum.at(rows, 6) == %{"key" => ["d", "c"], "value" => 10 * i} # test endkey with inclusive_end=true query = %{group_level: 2, endkey: ~s(["d"]), inclusive_end: true} rows = Couch.get(view_url, query: query).body["rows"] - assert Enum.at(rows, 0) == %{"key" => ["a"], "value" => 20*i} - assert Enum.at(rows, 1) == %{"key" => ["a","b"], "value" => 40*i} - assert Enum.at(rows, 2) == %{"key" => ["a","c"], "value" => 10*i} - assert Enum.at(rows, 3) == %{"key" => ["d"], "value" => 10*i} + assert Enum.at(rows, 0) == %{"key" => ["a"], "value" => 20 * i} + assert Enum.at(rows, 1) == %{"key" => ["a", "b"], "value" => 40 * i} + assert Enum.at(rows, 2) == %{"key" => ["a", "c"], "value" => 10 * i} + assert Enum.at(rows, 3) == %{"key" => ["d"], "value" => 10 * i} assert length(rows) == 4 # test endkey with inclusive_end=false query = %{group_level: 2, endkey: ~s(["d"]), inclusive_end: false} rows = Couch.get(view_url, query: query).body["rows"] - assert Enum.at(rows, 0) == %{"key" => ["a"], "value" => 20*i} - assert Enum.at(rows, 1) == %{"key" => ["a","b"], "value" => 40*i} - assert Enum.at(rows, 2) == %{"key" => ["a","c"], "value" => 10*i} + assert Enum.at(rows, 0) == %{"key" => ["a"], "value" => 20 * i} + assert Enum.at(rows, 1) == %{"key" => ["a", "b"], "value" => 40 * i} + assert Enum.at(rows, 2) == %{"key" => ["a", "c"], "value" => 10 * i} assert length(rows) == 3 end end @@ -141,6 +146,7 @@ defmodule ReduceTest do db_name = context[:db_name] view_url = "/#{db_name}/_design/foo/_view/bar" map = "function (doc) { emit(doc.val, doc.val); };" + reduce = ~s""" function (keys, values, rereduce) { // This computes the standard deviation of the mapped results @@ -178,11 +184,11 @@ defmodule ReduceTest do """ red_doc = %{:views => %{:bar => %{:map => map, :reduce => reduce}}} - assert Couch.put("/#{db_name}/_design/foo", [body: red_doc]).body["ok"] + assert Couch.put("/#{db_name}/_design/foo", body: red_doc).body["ok"] Enum.each(1..10, fn _ -> docs = for i <- 1..10, do: %{val: i * 10} - assert Couch.post("/#{db_name}/_bulk_docs", [body: %{:docs => docs}, query: %{w: 3}]).status_code == 201 + assert Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => docs}, query: %{w: 3}).status_code == 201 end) rows = Couch.get(view_url).body["rows"] @@ -193,6 +199,7 @@ defmodule ReduceTest do test "Reduce pagination", context do db_name = context[:db_name] view_url = "/#{db_name}/_design/foo/_view/bar" + ddoc = %{ _id: "_design/foo", language: "javascript", @@ -210,11 +217,11 @@ defmodule ReduceTest do } } - assert Couch.put("/#{db_name}/_design/foo", [body: ddoc]).body["ok"] + assert Couch.put("/#{db_name}/_design/foo", body: ddoc).body["ok"] docs = for i <- 0..1122, do: %{_id: Integer.to_string(i), int: i} - assert Couch.post("/#{db_name}/_bulk_docs", [body: %{:docs => docs}, query: %{w: 3}]).status_code == 201 + assert Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => docs}, query: %{w: 3}).status_code == 201 - rand_val = fn -> :rand.uniform(100000000) end + rand_val = fn -> :rand.uniform(100_000_000) end # ?group=false tests query = %{startkey: 400, endkey: 402, foobar: rand_val.()} @@ -255,21 +262,48 @@ defmodule ReduceTest do query = %{startkey: 402, endkey: 400, foobar: rand_val.(), endkey_docid: "398", descending: true} rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 9 - query = %{startkey: 402, endkey: 400, foobar: rand_val.(), endkey_docid: "398", descending: true, inclusive_end: false} + + query = %{ + startkey: 402, + endkey: 400, + foobar: rand_val.(), + endkey_docid: "398", + descending: true, + inclusive_end: false + } + rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 8 query = %{startkey: 402, endkey: 400, foobar: rand_val.(), endkey_docid: "399", descending: true} rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 8 - query = %{startkey: 402, endkey: 400, foobar: rand_val.(), endkey_docid: "399", descending: true, inclusive_end: false} + + query = %{ + startkey: 402, + endkey: 400, + foobar: rand_val.(), + endkey_docid: "399", + descending: true, + inclusive_end: false + } + rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 7 query = %{startkey: 402, endkey: 400, foobar: rand_val.(), endkey_docid: "400", descending: true} rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 7 - query = %{startkey: 402, endkey: 400, foobar: rand_val.(), endkey_docid: "400", descending: true, inclusive_end: false} + + query = %{ + startkey: 402, + endkey: 400, + foobar: rand_val.(), + endkey_docid: "400", + descending: true, + inclusive_end: false + } + rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 6 @@ -277,7 +311,15 @@ defmodule ReduceTest do rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 7 - query = %{startkey: 402, endkey: 400, foobar: rand_val.(), startkey_docid: "401", descending: true, inclusive_end: false} + query = %{ + startkey: 402, + endkey: 400, + foobar: rand_val.(), + startkey_docid: "401", + descending: true, + inclusive_end: false + } + rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 5 @@ -358,7 +400,16 @@ defmodule ReduceTest do assert Enum.at(rows, 2)["key"] == 400 assert Enum.at(rows, 2)["value"] == 3 - query = %{:group => true, startkey: 402, endkey: 400, foobar: rand_val.(), startkey_docid: "401", descending: true, inclusive_end: false} + query = %{ + :group => true, + startkey: 402, + endkey: 400, + foobar: rand_val.(), + startkey_docid: "401", + descending: true, + inclusive_end: false + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 2 assert Enum.at(rows, 0)["key"] == 402 @@ -366,7 +417,16 @@ defmodule ReduceTest do assert Enum.at(rows, 1)["key"] == 401 assert Enum.at(rows, 1)["value"] == 3 - query = %{:group => true, startkey: 402, endkey: 400, foobar: rand_val.(), startkey_docid: "400", descending: true, inclusive_end: false} + query = %{ + :group => true, + startkey: 402, + endkey: 400, + foobar: rand_val.(), + startkey_docid: "400", + descending: true, + inclusive_end: false + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 2 assert Enum.at(rows, 0)["key"] == 402 @@ -374,7 +434,16 @@ defmodule ReduceTest do assert Enum.at(rows, 1)["key"] == 401 assert Enum.at(rows, 1)["value"] == 3 - query = %{:group => true, startkey: 402, endkey: 400, foobar: rand_val.(), endkey_docid: "398", descending: true, inclusive_end: true} + query = %{ + :group => true, + startkey: 402, + endkey: 400, + foobar: rand_val.(), + endkey_docid: "398", + descending: true, + inclusive_end: true + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 3 assert Enum.at(rows, 0)["key"] == 402 @@ -384,7 +453,16 @@ defmodule ReduceTest do assert Enum.at(rows, 2)["key"] == 400 assert Enum.at(rows, 2)["value"] == 3 - query = %{:group => true, startkey: 402, endkey: 400, foobar: rand_val.(), endkey_docid: "399", descending: true, inclusive_end: true} + query = %{ + :group => true, + startkey: 402, + endkey: 400, + foobar: rand_val.(), + endkey_docid: "399", + descending: true, + inclusive_end: true + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 3 assert Enum.at(rows, 0)["key"] == 402 @@ -394,7 +472,16 @@ defmodule ReduceTest do assert Enum.at(rows, 2)["key"] == 400 assert Enum.at(rows, 2)["value"] == 2 - query = %{:group => true, startkey: 402, endkey: 400, foobar: rand_val.(), endkey_docid: "399", descending: true, inclusive_end: false} + query = %{ + :group => true, + startkey: 402, + endkey: 400, + foobar: rand_val.(), + endkey_docid: "399", + descending: true, + inclusive_end: false + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 3 assert Enum.at(rows, 0)["key"] == 402 @@ -404,7 +491,16 @@ defmodule ReduceTest do assert Enum.at(rows, 2)["key"] == 400 assert Enum.at(rows, 2)["value"] == 1 - query = %{:group => true, startkey: 402, endkey: 400, foobar: rand_val.(), endkey_docid: "400", descending: true, inclusive_end: false} + query = %{ + :group => true, + startkey: 402, + endkey: 400, + foobar: rand_val.(), + endkey_docid: "400", + descending: true, + inclusive_end: false + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 2 assert Enum.at(rows, 0)["key"] == 402 diff --git a/test/elixir/test/replication_test.exs b/test/elixir/test/replication_test.exs index 44426889a..fa1b64b62 100644 --- a/test/elixir/test/replication_test.exs +++ b/test/elixir/test/replication_test.exs @@ -48,7 +48,7 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) doc = %{"_id" => "doc1"} [doc] = save_docs(src_db_name, [doc]) @@ -61,16 +61,20 @@ defmodule ReplicationTest do assert history["docs_read"] == 1 assert history["doc_write_failures"] == 0 - doc = Map.put(doc, "_attachments", %{ - "hello.txt" => %{ - "content_type" => "text/plain", - "data" => "aGVsbG8gd29ybGQ=" # base64:encode("hello world") - }, - "foo.dat" => %{ - "content_type" => "not/compressible", - "data" => "aSBhbSBub3QgZ3ppcGVk" # base64:encode("i am not gziped") - } - }) + doc = + Map.put(doc, "_attachments", %{ + "hello.txt" => %{ + "content_type" => "text/plain", + # base64:encode("hello world") + "data" => "aGVsbG8gd29ybGQ=" + }, + "foo.dat" => %{ + "content_type" => "not/compressible", + # base64:encode("i am not gziped") + "data" => "aSBhbSBub3QgZ3ppcGVk" + } + }) + [doc] = save_docs(src_db_name, [doc]) result = replicate(src_db_name, "http://127.0.0.1:15984/" <> tgt_db_name) @@ -89,12 +93,13 @@ defmodule ReplicationTest do :attachments => true, :att_encoding_info => true } - opts = [headers: ["Accept": "application/json"], query: query] + + opts = [headers: [Accept: "application/json"], query: query] resp = Couch.get("/#{tgt_db_name}/#{doc["_id"]}", opts) - assert HTTPotion.Response.success? resp + assert HTTPotion.Response.success?(resp) assert is_map(resp.body) - refute Map.has_key? resp.body, "_conflicts" - refute Map.has_key? resp.body, "_deleted_conflicts" + refute Map.has_key?(resp.body, "_conflicts") + refute Map.has_key?(resp.body, "_deleted_conflicts") atts = resp.body["_attachments"] @@ -104,7 +109,7 @@ defmodule ReplicationTest do assert atts["foo.dat"]["content_type"] == "not/compressible" assert atts["foo.dat"]["data"] == "aSBhbSBub3QgZ3ppcGVk" - refute Map.has_key? atts["foo.dat"], "encoding" + refute Map.has_key?(atts["foo.dat"], "encoding") end test "replication cancellation" do @@ -114,7 +119,7 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) save_docs(src_db_name, make_docs(1..6)) @@ -130,16 +135,18 @@ defmodule ReplicationTest do assert is_map(task) assert task["replication_id"] == repl_id + repl_body = %{ "replication_id" => repl_id, cancel: true } + result = Couch.post("/_replicate", body: repl_body) assert result.status_code == 200 wait_for_repl_stop(repl_id) - assert get_task(repl_id, 0) == :nil + assert get_task(repl_id, 0) == nil result = Couch.post("/_replicate", body: repl_body) assert result.status_code == 404 @@ -153,7 +160,7 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) save_docs(src_db_name, make_docs(1..6)) @@ -177,6 +184,7 @@ defmodule ReplicationTest do "replication_id" => repl_id, cancel: true } + resp = Couch.Session.post(sess, "/_replicate", body: repl_body) assert resp.status_code == 401 assert resp.body["error"] == "unauthorized" @@ -224,9 +232,9 @@ defmodule ReplicationTest do end @tag config: [ - {"attachments", "compression_level", "8"}, - {"attachments", "compressible_types", "text/*"} - ] + {"attachments", "compression_level", "8"}, + {"attachments", "compressible_types", "text/*"} + ] test "compressed attachment replication - #{name}" do run_compressed_att_repl(@src_prefix, @tgt_prefix) end @@ -249,7 +257,7 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) att1_data = get_att1_data() att2_data = get_att2_data() @@ -259,16 +267,18 @@ defmodule ReplicationTest do "language" => "javascript", "value" => "ddoc" } + docs = make_docs(1..20) ++ [ddoc] docs = save_docs(src_db_name, docs) - docs = for doc <- docs do - if doc["integer"] >= 10 and doc["integer"] < 15 do - add_attachment(src_db_name, doc, body: att1_data) - else - doc + docs = + for doc <- docs do + if doc["integer"] >= 10 and doc["integer"] < 15 do + add_attachment(src_db_name, doc, body: att1_data) + else + doc + end end - end result = replicate(src_prefix <> src_db_name, tgt_prefix <> tgt_db_name) assert result["ok"] @@ -314,15 +324,16 @@ defmodule ReplicationTest do new_doc = %{"_id" => "foo666", "value" => "d"} [new_doc] = save_docs(src_db_name, [new_doc]) - docs = for doc <- docs do - if doc["integer"] >= 10 and doc["integer"] < 15 do - ctype = "application/binary" - opts = [name: "data.dat", body: att2_data, content_type: ctype] - add_attachment(src_db_name, doc, opts) - else - doc + docs = + for doc <- docs do + if doc["integer"] >= 10 and doc["integer"] < 15 do + ctype = "application/binary" + opts = [name: "data.dat", body: att2_data, content_type: ctype] + add_attachment(src_db_name, doc, opts) + else + doc + end end - end result = replicate(src_prefix <> src_db_name, tgt_prefix <> tgt_db_name) assert result["ok"] @@ -383,6 +394,7 @@ defmodule ReplicationTest do "_rev" => Enum.at(docs, 0)["_rev"], "_deleted" => true } + [del_doc] = save_docs(src_db_name, [del_doc]) result = replicate(src_prefix <> src_db_name, tgt_prefix <> tgt_db_name) @@ -503,6 +515,7 @@ defmodule ReplicationTest do %{"_id" => "foo2", "value" => 222}, %{"_id" => "foo3", "value" => 333} ] + save_docs(src_db_name, src_docs) save_docs(tgt_db_name, Enum.filter(src_docs, &(&1["_id"] != "foo2"))) @@ -527,6 +540,7 @@ defmodule ReplicationTest do %{"_id" => "foo4", "value" => 444}, %{"_id" => "foo5", "value" => 555} ] + save_docs(src_db_name, docs) save_docs(tgt_db_name, docs) @@ -562,7 +576,7 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) docs = make_docs(1..5) docs = save_docs(src_db_name, docs) @@ -572,9 +586,11 @@ defmodule ReplicationTest do # TODO: In JS we re-fetch _changes with since_seq, is that # really necessary? - expected_ids = for change <- Enum.drop(changes, 3) do - change["id"] - end + expected_ids = + for change <- Enum.drop(changes, 3) do + change["id"] + end + assert length(expected_ids) == 2 cancel_replication(repl_src, repl_tgt) @@ -592,6 +608,7 @@ defmodule ReplicationTest do Enum.each(docs, fn doc -> result = Couch.get("/#{tgt_db_name}/#{doc["_id"]}") + if Enum.member?(expected_ids, doc["_id"]) do assert result.status_code < 300 assert cmp_json(doc, result.body) @@ -610,21 +627,25 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) docs = make_docs(1..7) - docs = for doc <- docs do - if doc["integer"] == 2 do - Map.put(doc, "_attachments", %{ - "hello.txt" => %{ - :content_type => "text/plain", - :data => "aGVsbG8gd29ybGQ=" # base64:encode("hello world") - } - }) - else - doc + + docs = + for doc <- docs do + if doc["integer"] == 2 do + Map.put(doc, "_attachments", %{ + "hello.txt" => %{ + :content_type => "text/plain", + # base64:encode("hello world") + :data => "aGVsbG8gd29ybGQ=" + } + }) + else + doc + end end - end + docs = save_docs(src_db_name, docs) ddoc = %{ @@ -638,6 +659,7 @@ defmodule ReplicationTest do } """ } + [_] = save_docs(tgt_db_name, [ddoc]) result = replicate(repl_src, repl_tgt) @@ -653,6 +675,7 @@ defmodule ReplicationTest do for doc <- docs do result = Couch.get("/#{tgt_db_name}/#{doc["_id"]}") + if rem(doc["integer"], 2) == 0 do assert result.status_code < 300 assert result.body["integer"] == doc["integer"] @@ -670,7 +693,7 @@ defmodule ReplicationTest do repl_tgt = tgt_prefix <> tgt_db_name create_db(src_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) # tgt_db_name is created by the replication docs = make_docs(1..2) @@ -697,9 +720,10 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) docs = make_docs(1..30) + ddoc = %{ "_id" => "_design/mydesign", "language" => "javascript", @@ -729,6 +753,7 @@ defmodule ReplicationTest do Enum.each(docs, fn doc -> resp = Couch.get!("/#{tgt_db_name}/#{doc["_id"]}") + if(rem(doc["integer"], 2) == 0 || doc["string"] == "7") do assert resp.status_code < 300 assert cmp_json(doc, resp.body) @@ -778,6 +803,7 @@ defmodule ReplicationTest do Enum.each(new_docs, fn doc -> resp = Couch.get!("/#{tgt_db_name}/#{doc["_id"]}") + if(rem(doc["integer"], 2) == 0) do assert resp.status_code < 300 assert cmp_json(doc, resp.body) @@ -806,7 +832,7 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) filter_fun_1 = """ function(doc, req) { @@ -830,6 +856,7 @@ defmodule ReplicationTest do %{"_id" => "foo3", :value => 3}, %{"_id" => "foo4", :value => 4} ] + ddoc = %{ "_id" => "_design/mydesign", :language => "javascript", @@ -846,6 +873,7 @@ defmodule ReplicationTest do :maxvalue => "3" } } + result = replicate(repl_src, repl_tgt, body: repl_body) assert result["ok"] @@ -952,9 +980,10 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) docs = make_docs(1..10) + ddoc = %{ "_id" => "_design/foo", :language => "javascript", @@ -962,9 +991,12 @@ defmodule ReplicationTest do } doc_ids = test_data[:initial] - num_missing = Enum.count(doc_ids, fn doc_id -> - String.starts_with?(doc_id, "foo_") - end) + + num_missing = + Enum.count(doc_ids, fn doc_id -> + String.starts_with?(doc_id, "foo_") + end) + total_replicated = length(doc_ids) - num_missing [_ | docs] = save_docs(src_db_name, [ddoc | docs]) @@ -1002,7 +1034,8 @@ defmodule ReplicationTest do Enum.each(docs, fn doc -> encoded_id = URI.encode_www_form(doc["_id"]) copy = Couch.get!("/#{tgt_db_name}/#{doc["_id"]}") - is_doc_id = &(Enum.member?(doc_ids, &1)) + is_doc_id = &Enum.member?(doc_ids, &1) + if(is_doc_id.(doc["_id"]) or is_doc_id.(encoded_id)) do assert HTTPotion.Response.success?(copy) else @@ -1014,15 +1047,18 @@ defmodule ReplicationTest do assert tgt_info["doc_count"] == total_replicated doc_ids_after = test_data[:after] - num_missing_after = Enum.count(doc_ids_after, fn doc_id -> - String.starts_with?(doc_id, "foo_") - end) + + num_missing_after = + Enum.count(doc_ids_after, fn doc_id -> + String.starts_with?(doc_id, "foo_") + end) repl_body = %{:doc_ids => doc_ids_after} result = replicate(repl_src, repl_tgt, body: repl_body) assert result["ok"] total_replicated_after = length(doc_ids_after) - num_missing_after + if(total_replicated_after == 0) do assert result["no_changes"] else @@ -1049,10 +1085,12 @@ defmodule ReplicationTest do # Be absolutely sure that other docs were not replicated all_doc_ids = doc_ids ++ doc_ids_after + Enum.each(docs, fn doc -> encoded_id = URI.encode_www_form(doc["_id"]) copy = Couch.get!("/#{tgt_db_name}/#{doc["_id"]}") - is_doc_id = &(Enum.member?(all_doc_ids, &1)) + is_doc_id = &Enum.member?(all_doc_ids, &1) + if(is_doc_id.(doc["_id"]) or is_doc_id.(encoded_id)) do assert HTTPotion.Response.success?(copy) else @@ -1061,8 +1099,9 @@ defmodule ReplicationTest do end) tgt_info = get_db_info(tgt_db_name) + assert tgt_info["doc_count"] == total_replicated + total_replicated_after, - "#{inspect test_data}" + "#{inspect(test_data)}" # Update a source document and re-replicate (no conflict introduced) conflict_id = test_data[:conflict_id] @@ -1076,11 +1115,13 @@ defmodule ReplicationTest do body: get_att1_data(), content_type: "text/plain" ] + att2 = [ name: "data.dat", body: get_att2_data(), content_type: "application/binary" ] + doc = add_attachment(src_db_name, doc, att1) doc = add_attachment(src_db_name, doc, att2) @@ -1152,7 +1193,7 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) ddoc = %{ "_id" => "_design/mydesign", @@ -1161,18 +1202,20 @@ defmodule ReplicationTest do "myfilter" => "function(doc, req) { return true; }" } } + docs = make_docs(1..25) docs = save_docs(src_db_name, docs ++ [ddoc]) att1_data = get_att1_data() - docs = for doc <- docs do - if doc["integer"] >= 10 and doc["integer"] < 15 do - add_attachment(src_db_name, doc) - else - doc + docs = + for doc <- docs do + if doc["integer"] >= 10 and doc["integer"] < 15 do + add_attachment(src_db_name, doc) + else + doc + end end - end repl_body = %{:continuous => true} result = replicate(repl_src, repl_tgt, body: repl_body) @@ -1212,26 +1255,31 @@ defmodule ReplicationTest do assert tgt_info["doc_count"] == src_info["doc_count"] # Add attachments to more source docs - docs = for doc <- docs do - is_ddoc = String.starts_with?(doc["_id"], "_design/") - case doc["integer"] do - n when n >= 10 and n < 15 -> - ctype = "application/binary" - opts = [name: "data.dat", body: att1_data, content_type: ctype] - add_attachment(src_db_name, doc, opts) - _ when is_ddoc -> - add_attachment(src_db_name, doc) - _ -> - doc + docs = + for doc <- docs do + is_ddoc = String.starts_with?(doc["_id"], "_design/") + + case doc["integer"] do + n when n >= 10 and n < 15 -> + ctype = "application/binary" + opts = [name: "data.dat", body: att1_data, content_type: ctype] + add_attachment(src_db_name, doc, opts) + + _ when is_ddoc -> + add_attachment(src_db_name, doc) + + _ -> + doc + end end - end wait_for_repl(src_db_name, repl_id, 32) Enum.each(docs, fn doc -> is_ddoc = String.starts_with?(doc["_id"], "_design/") + case doc["integer"] do - N when N >= 10 and N < 15 or is_ddoc -> + N when (N >= 10 and N < 15) or is_ddoc -> resp = Couch.get!("/#{tgt_db_name}/#{doc["_id"]}") atts = resp.body["_attachments"] assert is_map(atts) @@ -1256,6 +1304,7 @@ defmodule ReplicationTest do assert String.length(resp.body) == String.length(att1_data) assert resp.body == att1_data end + _ -> :ok end @@ -1338,9 +1387,11 @@ defmodule ReplicationTest do changes = get_db_changes(tgt_db_name, %{:since => tgt_info["update_seq"]}) # quite unfortunately, there is no way on relying on ordering in a cluster # but we can assume a length of 2 - changes = for change <- changes["results"] do - {change["id"], change["deleted"]} - end + changes = + for change <- changes["results"] do + {change["id"], change["deleted"]} + end + assert Enum.sort(changes) == [{doc1["_id"], true}, {doc2["_id"], true}] # Cancel the replication @@ -1367,18 +1418,20 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) doc = %{"_id" => "foobar"} [doc] = save_docs(src_db_name, [doc]) att1_data = get_att1_data() num_copies = 1 + round(128 * 1024 / String.length(att1_data)) - big_att = List.foldl(Enum.to_list(1..num_copies), "", fn _, acc -> - acc <> att1_data - end) - doc = add_attachment(src_db_name, doc, [body: big_att]) + big_att = + List.foldl(Enum.to_list(1..num_copies), "", fn _, acc -> + acc <> att1_data + end) + + doc = add_attachment(src_db_name, doc, body: big_att) # Disable attachment compression set_config_raw("attachments", "compression_level", "0") @@ -1415,13 +1468,14 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) set_security(tgt_db_name, %{ - :admins => %{ - :names => ["superman"], - :roles => ["god"] - }}) + :admins => %{ + :names => ["superman"], + :roles => ["god"] + } + }) docs = make_docs(1..6) ddoc = %{"_id" => "_design/foo", "language" => "javascript"} @@ -1436,6 +1490,7 @@ defmodule ReplicationTest do userinfo: ctx[:userinfo], headers: [cookie: sess.cookie] ] + result = replicate(repl_src, repl_tgt, opts) assert Couch.Session.logout(sess).body["ok"] @@ -1443,11 +1498,14 @@ defmodule ReplicationTest do assert result["ok"] history = Enum.at(result["history"], 0) assert history["docs_read"] == length(docs) - assert history["docs_written"] == length(docs) - 1 # ddoc write failed - assert history["doc_write_failures"] == 1 # ddoc write failed + # ddoc write failed + assert history["docs_written"] == length(docs) - 1 + # ddoc write failed + assert history["doc_write_failures"] == 1 Enum.each(docs, fn doc -> resp = Couch.get("/#{tgt_db_name}/#{doc["_id"]}") + if String.starts_with?(doc["_id"], "_design/") do assert resp.status_code == 404 else @@ -1466,18 +1524,18 @@ defmodule ReplicationTest do create_db(src_db_name) create_db(tgt_db_name) - delete_on_exit [src_db_name, tgt_db_name] + delete_on_exit([src_db_name, tgt_db_name]) set_security(tgt_db_name, %{ - :admins => %{ - :names => ["superman"], - :roles => ["god"] - }, - :readers => %{ - :names => ["john"], - :roles => ["secret"] - } - }) + :admins => %{ + :names => ["superman"], + :roles => ["god"] + }, + :readers => %{ + :names => ["john"], + :roles => ["secret"] + } + }) docs = make_docs(1..6) ddoc = %{"_id" => "_design/foo", "language" => "javascript"} @@ -1492,7 +1550,8 @@ defmodule ReplicationTest do userinfo: ctx[:userinfo], headers: [cookie: sess.cookie] ] - assert_raise(ExUnit.AssertionError, fn() -> + + assert_raise(ExUnit.AssertionError, fn -> replicate(repl_src, repl_tgt, opts) end) @@ -1512,11 +1571,13 @@ defmodule ReplicationTest do def replicate(src, tgt, options \\ []) do {userinfo, options} = Keyword.pop(options, :userinfo) - userinfo = if userinfo == nil do - @admin_account - else - userinfo - end + + userinfo = + if userinfo == nil do + @admin_account + else + userinfo + end src = set_user(src, userinfo) tgt = set_user(tgt, userinfo) @@ -1528,13 +1589,14 @@ defmodule ReplicationTest do 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 = 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} + try do replicate(src, tgt, body: body) rescue @@ -1544,7 +1606,7 @@ defmodule ReplicationTest do def get_db_changes(db_name, query \\ %{}) do resp = Couch.get("/#{db_name}/_changes", query: query) - assert HTTPotion.Response.success?(resp), "#{inspect resp}" + assert HTTPotion.Response.success?(resp), "#{inspect(resp)}" resp.body end @@ -1553,6 +1615,7 @@ defmodule ReplicationTest do body = %{docs: docs} resp = Couch.post("/#{db_name}/_bulk_docs", query: query, body: body) assert HTTPotion.Response.success?(resp) + for {doc, resp} <- Enum.zip(docs, resp.body) do assert resp["ok"], "Error saving doc: #{doc["_id"]}" Map.put(doc, "_rev", resp["rev"]) @@ -1571,14 +1634,18 @@ defmodule ReplicationTest do body: <<"some text">>, content_type: "text/plain" ] + att = Keyword.merge(defaults, att) |> Enum.into(%{}) uri = "/#{db_name}/#{URI.encode(doc["_id"])}/#{att[:name]}" headers = ["Content-Type": att[:content_type]] - params = if doc["_rev"] do - %{:w => 3, :rev => doc["_rev"]} - else - %{:w => 3} - end + + params = + if doc["_rev"] do + %{:w => 3, :rev => doc["_rev"]} + else + %{:w => 3} + end + resp = Couch.put(uri, headers: headers, query: params, body: att[:body]) assert HTTPotion.Response.success?(resp) Map.put(doc, "_rev", resp.body["rev"]) @@ -1597,10 +1664,12 @@ defmodule ReplicationTest do through_seq = task["through_seq"] revs_checked = task["revisions_checked"] changes = get_db_changes(src_db_name, %{:since => through_seq}) + if length(changes["results"]) > 0 or revs_checked < expect_revs_checked do :timer.sleep(500) wait_for_repl(src_db_name, repl_id, expect_revs_checked, wait_left - 500) end + task end @@ -1614,6 +1683,7 @@ defmodule ReplicationTest do def wait_for_repl_stop(repl_id, wait_left) do task = get_task(repl_id, 0) + if is_map(task) do :timer.sleep(500) wait_for_repl_stop(repl_id, wait_left - 500) @@ -1633,6 +1703,7 @@ defmodule ReplicationTest do case try_get_task(repl_id) do result when is_map(result) -> result + _ -> :timer.sleep(500) get_task(repl_id, delay - 500) @@ -1643,7 +1714,8 @@ defmodule ReplicationTest do resp = Couch.get("/_active_tasks") assert HTTPotion.Response.success?(resp) assert is_list(resp.body) - Enum.find(resp.body, :nil, fn task -> + + Enum.find(resp.body, nil, fn task -> task["replication_id"] == repl_id end) end @@ -1652,8 +1724,10 @@ defmodule ReplicationTest do case URI.parse(uri) do %{scheme: nil} -> uri + %{userinfo: nil} = uri -> URI.to_string(Map.put(uri, :userinfo, userinfo)) + _ -> uri end @@ -1673,11 +1747,11 @@ defmodule ReplicationTest do if cmp_json(v, rhs[k]) do {:cont, true} else - Logger.error "#{inspect lhs} != #{inspect rhs}" + Logger.error("#{inspect(lhs)} != #{inspect(rhs)}") {:halt, false} end else - Logger.error "#{inspect lhs} != #{inspect rhs}" + Logger.error("#{inspect(lhs)} != #{inspect(rhs)}") {:halt, false} end end) @@ -1698,8 +1772,8 @@ defmodule ReplicationTest do def delete_on_exit(db_names) when is_list(db_names) do on_exit(fn -> - Enum.each(db_names, fn(name) -> - delete_db name + Enum.each(db_names, fn name -> + delete_db(name) end) end) end diff --git a/test/elixir/test/rewrite_test.exs b/test/elixir/test/rewrite_test.exs index 7db9d36bc..c27f92659 100644 --- a/test/elixir/test/rewrite_test.exs +++ b/test/elixir/test/rewrite_test.exs @@ -11,11 +11,12 @@ defmodule RewriteTest do Enum.each(["test_rewrite_suite_db", "test_rewrite_suite_db%2Fwith_slashes"], fn db_name -> @tag with_random_db: db_name @tag config: [ - {"httpd", "authentication_handlers", "{couch_httpd_auth, special_test_authentication_handler}"}, - {"httpd", "WWW-Authenticate", "X-Couch-Test-Auth"} - ] + {"httpd", "authentication_handlers", "{couch_httpd_auth, special_test_authentication_handler}"}, + {"httpd", "WWW-Authenticate", "X-Couch-Test-Auth"} + ] test "Test basic rewrites on #{db_name}", context do db_name = context[:db_name] + ddoc = ~S""" { "_id": "_design/test", @@ -261,9 +262,11 @@ defmodule RewriteTest do } } """ + ddoc = String.replace(ddoc, ~r/[\r\n]+/, "") docs1 = make_docs(0..9) + docs2 = [ %{"a" => 1, "b" => 1, "string" => "doc 1", "type" => "complex"}, %{"a" => 1, "b" => 2, "string" => "doc 2", "type" => "complex"}, @@ -272,9 +275,9 @@ defmodule RewriteTest do %{"a" => %{"c" => 1}, "b" => "", "string" => "doc 5", "type" => "complex"} ] - assert Couch.put("/#{db_name}/_design/test", [body: ddoc]).body["ok"] - assert Couch.post("/#{db_name}/_bulk_docs", [body: %{:docs => docs1}, query: %{w: 3}]).status_code == 201 - assert Couch.post("/#{db_name}/_bulk_docs", [body: %{:docs => docs2}, query: %{w: 3}]).status_code == 201 + assert Couch.put("/#{db_name}/_design/test", body: ddoc).body["ok"] + assert Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => docs1}, query: %{w: 3}).status_code == 201 + assert Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => docs2}, query: %{w: 3}).status_code == 201 # Test simple rewriting resp = Couch.get("/#{db_name}/_design/test/_rewrite/foo") @@ -286,7 +289,7 @@ defmodule RewriteTest do assert resp.headers["Content-Type"] == "text/plain" # Test POST, hello update world - resp = Couch.post("/#{db_name}", [body: %{"word" => "plankton", "name" => "Rusty"}]).body + resp = Couch.post("/#{db_name}", body: %{"word" => "plankton", "name" => "Rusty"}).body assert resp["ok"] doc_id = resp["id"] assert doc_id diff --git a/test/elixir/test/security_validation_test.exs b/test/elixir/test/security_validation_test.exs index 526f06b2a..a020c507c 100644 --- a/test/elixir/test/security_validation_test.exs +++ b/test/elixir/test/security_validation_test.exs @@ -10,13 +10,16 @@ defmodule SecurityValidationTest do @auth_headers %{ jerry: [ - authorization: "Basic amVycnk6bW91c2U=" # jerry:mouse + # jerry:mouse + authorization: "Basic amVycnk6bW91c2U=" ], tom: [ - authorization: "Basic dG9tOmNhdA==" # tom:cat + # tom:cat + authorization: "Basic dG9tOmNhdA==" ], spike_cat: [ - authorization: "Basic c3Bpa2U6Y2F0" # spike:cat - which is wrong + # spike:cat - which is wrong + authorization: "Basic c3Bpa2U6Y2F0" ] } @@ -50,10 +53,12 @@ defmodule SecurityValidationTest do on_exit(fn -> delete_db(auth_db_name) end) configs = [ - {"httpd", "authentication_handlers", "{couch_httpd_auth, cookie_authentication_handler}, {couch_httpd_auth, default_authentication_handler}"}, + {"httpd", "authentication_handlers", + "{couch_httpd_auth, cookie_authentication_handler}, {couch_httpd_auth, default_authentication_handler}"}, {"couch_httpd_auth", "authentication_db", auth_db_name}, {"chttpd_auth", "authentication_db", auth_db_name} ] + Enum.each(configs, &set_config/1) # port of comment from security_validation.js @@ -63,6 +68,7 @@ defmodule SecurityValidationTest do # btw: this needs to be INSIDE configured server to propagate correctly ;-) # At least they'd run in the build, though users = [{"tom", "cat"}, {"jerry", "mouse"}, {"spike", "dog"}] + Enum.each(users, fn {name, pass} -> doc = %{ :_id => "org.couchdb.user:#{name}", @@ -70,6 +76,7 @@ defmodule SecurityValidationTest do :roles => [], :password => pass } + assert Couch.post("/#{auth_db_name}", body: doc).body["ok"] end) @@ -78,15 +85,17 @@ defmodule SecurityValidationTest do @tag :with_db_name test "Saving document using the wrong credentials", context do - headers = @auth_headers[:spike_cat] # spike:cat - which is wrong - resp = Couch.post("/#{context[:db_name]}", [body: %{foo: 1}, headers: headers]) + # spike:cat - which is wrong + headers = @auth_headers[:spike_cat] + resp = Couch.post("/#{context[:db_name]}", body: %{foo: 1}, headers: headers) assert resp.body["error"] == "unauthorized" assert resp.status_code == 401 end test "Force basic login" do - headers = @auth_headers[:spike_cat] # spike:cat - which is wrong - resp = Couch.get("/_session", [query: %{basic: true}, headers: headers]) + # spike:cat - which is wrong + headers = @auth_headers[:spike_cat] + resp = Couch.get("/_session", query: %{basic: true}, headers: headers) assert resp.status_code == 401 assert resp.body["error"] == "unauthorized" end @@ -103,7 +112,7 @@ defmodule SecurityValidationTest do @tag :with_db test "Non-admin user cannot save a ddoc", context do headers = @auth_headers[:jerry] - resp = Couch.post("/#{context[:db_name]}", [body: @ddoc, headers: headers]) + resp = Couch.post("/#{context[:db_name]}", body: @ddoc, headers: headers) assert resp.status_code == 403 assert resp.body["error"] == "forbidden" end @@ -120,7 +129,7 @@ defmodule SecurityValidationTest do ddoc = Map.put(@ddoc, :_rev, new_rev) |> Map.put(:foo, "bar") headers = @auth_headers[:tom] # attempt to save doc in replication context, eg ?new_edits=false - resp = Couch.put("/#{db_name}/#{ddoc[:_id]}", [body: ddoc, headers: headers, query: %{new_edits: false}]) + resp = Couch.put("/#{db_name}/#{ddoc[:_id]}", body: ddoc, headers: headers, query: %{new_edits: false}) assert resp.status_code == 403 assert resp.body["error"] == "forbidden" end @@ -143,18 +152,18 @@ defmodule SecurityValidationTest do assert Couch.put("/#{db_name}/_security", body: sec_obj).body["ok"] assert Couch.post("/#{db_name}", body: @ddoc).body["ok"] - resp = Couch.put("/#{db_name}/test_doc", [body: %{foo: 1}, headers: jerry]) + resp = Couch.put("/#{db_name}/test_doc", body: %{foo: 1}, headers: jerry) assert resp.status_code == 403 assert resp.body["error"] == "forbidden" assert resp.body["reason"] == "Documents must have an author field" # Jerry can write the document - assert Couch.put("/#{db_name}/test_doc", [body: %{foo: 1, author: "jerry"}, headers: jerry]).body["ok"] + assert Couch.put("/#{db_name}/test_doc", body: %{foo: 1, author: "jerry"}, headers: jerry).body["ok"] test_doc = Couch.get("/#{db_name}/test_doc").body # Tom cannot write the document - resp = Couch.post("/#{db_name}", [body: %{foo: 1}, headers: tom]) + resp = Couch.post("/#{db_name}", body: %{foo: 1}, headers: tom) assert resp.status_code == 403 assert resp.body["error"] == "forbidden" @@ -169,12 +178,12 @@ defmodule SecurityValidationTest do # Now Tom can update the document test_doc = Map.put(test_doc, "foo", "asdf") - resp = Couch.put("/#{db_name}/test_doc", [body: test_doc, headers: tom]) + resp = Couch.put("/#{db_name}/test_doc", body: test_doc, headers: tom) assert resp.body["ok"] test_doc = Map.put(test_doc, "_rev", resp.body["rev"]) # Jerry can't delete it - retry_until(fn() -> + retry_until(fn -> opts = [headers: jerry] resp = Couch.delete("/#{db_name}/test_doc?rev=#{test_doc["_rev"]}", opts) resp.status_code == 401 and resp.body["error"] == "unauthorized" @@ -213,7 +222,7 @@ end # # # // now all or nothing with a failure - no more available on cluster -#/* var docs = [{_id:"booboo",author:"Damien Katz",foo:"bar"},{_id:"foofoo",foo:"baz"}]; +# /* var docs = [{_id:"booboo",author:"Damien Katz",foo:"bar"},{_id:"foofoo",foo:"baz"}]; # # // Create the docs # var results = db.bulkSave(docs, {all_or_nothing:true}); @@ -222,7 +231,7 @@ end # T(results.errors[0].error == "forbidden"); # T(db.open("booboo") == null); # T(db.open("foofoo") == null); -#*/ +# */ # # // Now test replication # var AuthHeaders = {"Authorization": "Basic c3Bpa2U6ZG9n"}; // spike @@ -307,4 +316,4 @@ end # req.open("DELETE", "http://127.0.0.1:15986/" + authDb_name, false); # req.send(""); # CouchDB.maybeThrowError(req); -#}; +# }; diff --git a/test/elixir/test/test_helper.exs b/test/elixir/test/test_helper.exs index d0d9d923b..e08229f82 100644 --- a/test/elixir/test/test_helper.exs +++ b/test/elixir/test/test_helper.exs @@ -15,31 +15,40 @@ defmodule CouchTestCase do &set_config_context/1, &set_user_context/1 ] - context = Enum.reduce(setup_funs, context, fn setup_fun, acc -> - setup_fun.(acc) - end) + + context = + Enum.reduce(setup_funs, context, fn setup_fun, acc -> + setup_fun.(acc) + end) + {:ok, context} end def set_db_context(context) do - context = case context do - %{:with_db_name => true} -> - Map.put(context, :db_name, random_db_name()) - %{:with_db_name => db_name} when is_binary(db_name) -> - Map.put(context, :db_name, db_name) - %{:with_random_db => db_name} when is_binary(db_name) -> - context - |> Map.put(:db_name, random_db_name(db_name)) - |> Map.put(:with_db, true) - %{:with_db => true} -> - Map.put(context, :db_name, random_db_name()) - %{:with_db => db_name} when is_binary(db_name) -> - Map.put(context, :db_name, db_name) - _ -> - context - end + context = + case context do + %{:with_db_name => true} -> + Map.put(context, :db_name, random_db_name()) + + %{:with_db_name => db_name} when is_binary(db_name) -> + Map.put(context, :db_name, db_name) - if Map.has_key? context, :with_db do + %{:with_random_db => db_name} when is_binary(db_name) -> + context + |> Map.put(:db_name, random_db_name(db_name)) + |> Map.put(:with_db, true) + + %{:with_db => true} -> + Map.put(context, :db_name, random_db_name()) + + %{:with_db => db_name} when is_binary(db_name) -> + Map.put(context, :db_name, db_name) + + _ -> + context + end + + if Map.has_key?(context, :with_db) do {:ok, _} = create_db(context[:db_name]) on_exit(fn -> delete_db(context[:db_name]) end) end @@ -53,6 +62,7 @@ defmodule CouchTestCase do set_config(cfg) end) end + context end @@ -60,13 +70,16 @@ defmodule CouchTestCase do case Map.get(context, :user) do nil -> context + user when is_list(user) -> user = create_user(user) + on_exit(fn -> query = %{:rev => user["_rev"]} resp = Couch.delete("/_users/#{user["_id"]}", query: query) - assert HTTPotion.Response.success? resp + assert HTTPotion.Response.success?(resp) end) + context = Map.put(context, :user, user) userinfo = user["name"] <> ":" <> user["password"] Map.put(context, :userinfo, userinfo) @@ -85,6 +98,7 @@ defmodule CouchTestCase do def set_config({section, key, value}) do existing = set_config_raw(section, key, value) + on_exit(fn -> Enum.each(existing, fn {node, prev_value} -> if prev_value != "" do @@ -105,6 +119,7 @@ defmodule CouchTestCase do def set_config_raw(section, key, value) do resp = Couch.get("/_membership") + Enum.map(resp.body["all_nodes"], fn node -> url = "/_node/#{node}/_config/#{section}/#{key}" headers = ["X-Couch-Persist": "false"] @@ -117,6 +132,7 @@ defmodule CouchTestCase do def create_user(user) do required = [:name, :password, :roles] + Enum.each(required, fn key -> assert Keyword.has_key?(user, key), "User missing key: #{key}" end) @@ -128,6 +144,7 @@ defmodule CouchTestCase do assert is_binary(name), "User name must be a string" assert is_binary(password), "User password must be a string" assert is_list(roles), "Roles must be a list of strings" + Enum.each(roles, fn role -> assert is_binary(role), "Roles must be a list of strings" end) @@ -139,15 +156,20 @@ defmodule CouchTestCase do "roles" => roles, "password" => password } + resp = Couch.get("/_users/#{user_doc["_id"]}") - user_doc = case resp.status_code do - 404 -> - user_doc - sc when sc >= 200 and sc < 300 -> - Map.put(user_doc, "_rev", resp.body["_rev"]) - end + + user_doc = + case resp.status_code do + 404 -> + user_doc + + sc when sc >= 200 and sc < 300 -> + Map.put(user_doc, "_rev", resp.body["_rev"]) + end + resp = Couch.post("/_users", body: user_doc) - assert HTTPotion.Response.success? resp + assert HTTPotion.Response.success?(resp) assert resp.body["ok"] Map.put(user_doc, "_rev", resp.body["rev"]) end @@ -167,7 +189,7 @@ defmodule CouchTestCase do end def create_doc(db_name, body) do - resp = Couch.post("/#{db_name}", [body: body]) + resp = Couch.post("/#{db_name}", body: body) assert resp.status_code == 201 assert resp.body["ok"] {:ok, resp} @@ -201,6 +223,7 @@ defmodule CouchTestCase do defp retry_until(condition, start, sleep, timeout) do now = now(:ms) + if now > start + timeout do raise "timed out after #{now - start} ms" else @@ -219,7 +242,7 @@ defmodule CouchTestCase do end defp now(:ms) do - div(:erlang.system_time, 1000000) + div(:erlang.system_time(), 1_000_000) end @spec rev(map(), map()) :: map() @@ -233,11 +256,9 @@ defmodule CouchTestCase do end def pretty_inspect(resp) do - opts = [ - pretty: true, width: 20, limit: :infinity, printable_limit: :infinity] + opts = [pretty: true, width: 20, limit: :infinity, printable_limit: :infinity] inspect(resp, opts) end - end end end diff --git a/test/elixir/test/uuids_test.exs b/test/elixir/test/uuids_test.exs index 3eda45824..bb9369b80 100644 --- a/test/elixir/test/uuids_test.exs +++ b/test/elixir/test/uuids_test.exs @@ -45,11 +45,12 @@ defmodule UUIDsTest do end @tag config: [ - {"uuids", "algorithm", "sequential"} - ] + {"uuids", "algorithm", "sequential"} + ] test "sequential uuids are sequential" do resp = Couch.get("/_uuids", query: %{:count => 1000}) assert resp.status_code == 200 + Enum.reduce(resp.body["uuids"], fn curr, acc -> assert String.length(curr) == 32 assert acc < curr @@ -58,8 +59,8 @@ defmodule UUIDsTest do end @tag config: [ - {"uuids", "algorithm", "utc_random"} - ] + {"uuids", "algorithm", "utc_random"} + ] test "utc_random uuids are roughly random" do resp = Couch.get("/_uuids", query: %{:count => 1000}) assert resp.status_code == 200 @@ -78,12 +79,13 @@ defmodule UUIDsTest do @utc_id_suffix "frog" @tag config: [ - {"uuids", "algorithm", "utc_id"}, - {"uuids", "utc_id_suffix", @utc_id_suffix} - ] + {"uuids", "algorithm", "utc_id"}, + {"uuids", "utc_id_suffix", @utc_id_suffix} + ] test "utc_id uuids are correct" do resp = Couch.get("/_uuids", query: %{:count => 10}) assert resp.status_code == 200 + Enum.reduce(resp.body["uuids"], fn curr, acc -> assert String.length(curr) == 14 + String.length(@utc_id_suffix) assert String.slice(curr, 14..-1) == @utc_id_suffix diff --git a/test/elixir/test/view_collation_test.exs b/test/elixir/test/view_collation_test.exs index 10aec2f22..bf30031e0 100644 --- a/test/elixir/test/view_collation_test.exs +++ b/test/elixir/test/view_collation_test.exs @@ -9,8 +9,8 @@ defmodule ViewCollationTest do @values [ # Special values sort before all other types :null, - :false, - :true, + false, + true, # Then numbers 1, @@ -52,12 +52,14 @@ defmodule ViewCollationTest do {:ok, _} = create_db(db_name) on_exit(fn -> delete_db(db_name) end) - {docs, _} = Enum.flat_map_reduce(@values, 1, fn value, idx -> - doc = %{:_id => Integer.to_string(idx), :foo => value} - {[doc], idx + 1} - end) + {docs, _} = + Enum.flat_map_reduce(@values, 1, fn value, idx -> + doc = %{:_id => Integer.to_string(idx), :foo => value} + {[doc], idx + 1} + end) + resp = Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => docs}) - Enum.each(resp.body, &(assert &1["ok"])) + Enum.each(resp.body, &assert(&1["ok"])) map_fun = "function(doc) { emit(doc.foo, null); }" map_doc = %{:views => %{:foo => %{:map => map_fun}}} @@ -70,6 +72,7 @@ defmodule ViewCollationTest do test "ascending collation order", context do resp = Couch.get(url(context)) pairs = Enum.zip(resp.body["rows"], @values) + Enum.each(pairs, fn {row, value} -> assert row["key"] == convert(value) end) @@ -78,6 +81,7 @@ defmodule ViewCollationTest do test "descending collation order", context do resp = Couch.get(url(context), query: %{"descending" => "true"}) pairs = Enum.zip(resp.body["rows"], Enum.reverse(@values)) + Enum.each(pairs, fn {row, value} -> assert row["key"] == convert(value) end) @@ -115,6 +119,7 @@ defmodule ViewCollationTest do :endkey_docid => 11, :inclusive_end => false } + resp = Couch.get(url(context), query: query) assert Enum.at(resp.body["rows"], -1)["key"] == "aa" @@ -130,4 +135,4 @@ defmodule ViewCollationTest do def convert(value) do :jiffy.decode(:jiffy.encode(value), [:return_maps]) end -end
\ No newline at end of file +end |