diff options
author | Alessio Biancalana <dottorblaster@gmail.com> | 2018-12-07 21:58:39 +0100 |
---|---|---|
committer | Joan Touzet <wohali@users.noreply.github.com> | 2018-12-07 15:58:39 -0500 |
commit | f9354ea21d2f5161e0403fbded404506405a5d70 (patch) | |
tree | 67f8ce38ba6c49b57e44c6bfef9c7aad54e2703a | |
parent | 33d4f6d02715a204ef2dd7ddc4795aed5c1b72ce (diff) | |
download | couchdb-f9354ea21d2f5161e0403fbded404506405a5d70.tar.gz |
Add Credo to Elixir test suite (#1769)
This PR adds Credo as the static code analysis tool of choice for the Elixir test suite.
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | Makefile.win | 8 | ||||
-rw-r--r-- | test/elixir/.credo.exs | 153 | ||||
-rw-r--r-- | test/elixir/.formatter.exs | 2 | ||||
-rw-r--r-- | test/elixir/lib/couch.ex | 41 | ||||
-rw-r--r-- | test/elixir/mix.exs | 3 | ||||
-rw-r--r-- | test/elixir/mix.lock | 3 | ||||
-rw-r--r-- | test/elixir/test/all_docs_test.exs | 61 | ||||
-rw-r--r-- | test/elixir/test/basics_test.exs | 19 | ||||
-rw-r--r-- | test/elixir/test/coffee_test.exs | 10 | ||||
-rw-r--r-- | test/elixir/test/compact_test.exs | 4 | ||||
-rw-r--r-- | test/elixir/test/config_test.exs | 12 | ||||
-rw-r--r-- | test/elixir/test/conflicts_test.exs | 10 | ||||
-rw-r--r-- | test/elixir/test/lots_of_docs_test.exs | 8 | ||||
-rw-r--r-- | test/elixir/test/reduce_test.exs | 158 | ||||
-rw-r--r-- | test/elixir/test/replication_test.exs | 28 | ||||
-rw-r--r-- | test/elixir/test/rewrite_test.exs | 609 | ||||
-rw-r--r-- | test/elixir/test/security_validation_test.exs | 29 |
18 files changed, 790 insertions, 376 deletions
@@ -194,13 +194,19 @@ python-black-update: .venv/bin/black . dev/run rel/overlay/bin/couchup test/javascript/run .PHONY: elixir -elixir: elixir-check-formatted devclean +elixir: elixir-check-formatted elixir-credo devclean @dev/run -a adm:pass --no-eval test/elixir/run .PHONY: elixir-check-formatted elixir-check-formatted: @cd test/elixir/ && mix format --check-formatted +# Credo is a static code analysis tool for Elixir. +# We use it in our tests +.PHONY: elixir-credo +elixir-credo: + @cd test/elixir/ && mix deps.get && mix credo + .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 2b74e455e..a42ec7027 100644 --- a/Makefile.win +++ b/Makefile.win @@ -165,13 +165,19 @@ python-black-update: .venv/bin/black . dev\run rel\overlay\bin\couchup test\javascript\run .PHONY: elixir -elixir: elixir-check-formatted devclean +elixir: elixir-check-formatted elixir-credo devclean @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 +# Credo is a static code analysis tool for Elixir. +# We use it in our tests +.PHONY: elixir-credo +elixir-credo: + @cd test/elixir/ && mix deps.get && mix credo + .PHONY: test-cluster-with-quorum test-cluster-with-quorum: devclean -@mkdir share\www\script\test diff --git a/test/elixir/.credo.exs b/test/elixir/.credo.exs new file mode 100644 index 000000000..48ae45224 --- /dev/null +++ b/test/elixir/.credo.exs @@ -0,0 +1,153 @@ +# This file contains the configuration for Credo and you are probably reading +# this after creating it with `mix credo.gen.config`. +# +# If you find anything wrong or unclear in this file, please report an +# issue on GitHub: https://github.com/rrrene/credo/issues +# +%{ + # + # You can have as many configs as you like in the `configs:` field. + configs: [ + %{ + # + # Run any exec using `mix credo -C <name>`. If no exec name is given + # "default" is used. + # + name: "default", + # + # These are the files included in the analysis: + files: %{ + # + # You can give explicit globs or simply directories. + # In the latter case `**/*.{ex,exs}` will be used. + # + included: ["lib/", "src/", "test/", "web/", "apps/"], + excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/"] + }, + # + # If you create your own checks, you must specify the source files for + # them here, so they can be loaded by Credo before running the analysis. + # + requires: [], + # + # If you want to enforce a style guide and need a more traditional linting + # experience, you can change `strict` to `true` below: + # + strict: false, + # + # If you want to use uncolored output by default, you can change `color` + # to `false` below: + # + color: true, + # + # You can customize the parameters of any check by adding a second element + # to the tuple. + # + # To disable a check put `false` as second element: + # + # {Credo.Check.Design.DuplicatedCode, false} + # + checks: [ + # + ## Consistency Checks + # + {Credo.Check.Consistency.ExceptionNames, []}, + {Credo.Check.Consistency.LineEndings, []}, + {Credo.Check.Consistency.ParameterPatternMatching, false}, + {Credo.Check.Consistency.SpaceAroundOperators, []}, + {Credo.Check.Consistency.SpaceInParentheses, []}, + {Credo.Check.Consistency.TabsOrSpaces, []}, + + # + ## Design Checks + # + # You can customize the priority of any check + # Priority values are: `low, normal, high, higher` + # + {Credo.Check.Design.AliasUsage, + [priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 0]}, + # You can also customize the exit_status of each check. + # If you don't want TODO comments to cause `mix credo` to fail, just + # set this value to 0 (zero). + # + {Credo.Check.Design.TagTODO, [exit_status: 0]}, + {Credo.Check.Design.TagFIXME, []}, + + # + ## Readability Checks + # + {Credo.Check.Readability.AliasOrder, []}, + {Credo.Check.Readability.FunctionNames, []}, + {Credo.Check.Readability.LargeNumbers, []}, + {Credo.Check.Readability.MaxLineLength, [priority: :normal, max_length: 90]}, + {Credo.Check.Readability.ModuleAttributeNames, []}, + {Credo.Check.Readability.ModuleDoc, []}, + {Credo.Check.Readability.ModuleNames, []}, + {Credo.Check.Readability.ParenthesesInCondition, []}, + {Credo.Check.Readability.ParenthesesOnZeroArityDefs, []}, + {Credo.Check.Readability.PredicateFunctionNames, []}, + {Credo.Check.Readability.PreferImplicitTry, []}, + {Credo.Check.Readability.RedundantBlankLines, []}, + {Credo.Check.Readability.Semicolons, []}, + {Credo.Check.Readability.SpaceAfterCommas, []}, + {Credo.Check.Readability.StringSigils, []}, + {Credo.Check.Readability.TrailingBlankLine, []}, + {Credo.Check.Readability.TrailingWhiteSpace, []}, + {Credo.Check.Readability.VariableNames, []}, + + # + ## Refactoring Opportunities + # + {Credo.Check.Refactor.CondStatements, []}, + {Credo.Check.Refactor.CyclomaticComplexity, false}, + {Credo.Check.Refactor.FunctionArity, []}, + {Credo.Check.Refactor.LongQuoteBlocks, false}, + {Credo.Check.Refactor.MapInto, []}, + {Credo.Check.Refactor.MatchInCondition, []}, + {Credo.Check.Refactor.NegatedConditionsInUnless, []}, + {Credo.Check.Refactor.NegatedConditionsWithElse, []}, + {Credo.Check.Refactor.Nesting, false}, + {Credo.Check.Refactor.PipeChainStart, + [excluded_argument_types: [:atom, :binary, :fn, :keyword], excluded_functions: []]}, + {Credo.Check.Refactor.UnlessWithElse, []}, + + # + ## Warnings + # + {Credo.Check.Warning.BoolOperationOnSameValues, []}, + {Credo.Check.Warning.ExpensiveEmptyEnumCheck, []}, + {Credo.Check.Warning.IExPry, []}, + {Credo.Check.Warning.IoInspect, []}, + {Credo.Check.Warning.LazyLogging, []}, + {Credo.Check.Warning.OperationOnSameValues, []}, + {Credo.Check.Warning.OperationWithConstantResult, []}, + {Credo.Check.Warning.RaiseInsideRescue, []}, + {Credo.Check.Warning.UnusedEnumOperation, []}, + {Credo.Check.Warning.UnusedFileOperation, []}, + {Credo.Check.Warning.UnusedKeywordOperation, []}, + {Credo.Check.Warning.UnusedListOperation, []}, + {Credo.Check.Warning.UnusedPathOperation, []}, + {Credo.Check.Warning.UnusedRegexOperation, []}, + {Credo.Check.Warning.UnusedStringOperation, []}, + {Credo.Check.Warning.UnusedTupleOperation, []}, + + # + # Controversial and experimental checks (opt-in, just remove `, false`) + # + {Credo.Check.Consistency.MultiAliasImportRequireUse, false}, + {Credo.Check.Design.DuplicatedCode, false}, + {Credo.Check.Readability.Specs, false}, + {Credo.Check.Refactor.ABCSize, false}, + {Credo.Check.Refactor.AppendSingleItem, false}, + {Credo.Check.Refactor.DoubleBooleanNegation, false}, + {Credo.Check.Refactor.VariableRebinding, false}, + {Credo.Check.Warning.MapGetUnsafePass, false}, + {Credo.Check.Warning.UnsafeToAtom, false} + + # + # Custom checks can be created using `mix credo.gen.check`. + # + ] + } + ] +} diff --git a/test/elixir/.formatter.exs b/test/elixir/.formatter.exs index c79a3c2f9..742e82394 100644 --- a/test/elixir/.formatter.exs +++ b/test/elixir/.formatter.exs @@ -1,6 +1,6 @@ # Used by "mix format" [ inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"], - line_length: 120, + line_length: 90, rename_deprecated_at: "1.5.0" ] diff --git a/test/elixir/lib/couch.ex b/test/elixir/lib/couch.ex index 6801fd558..302b8276a 100644 --- a/test/elixir/lib/couch.ex +++ b/test/elixir/lib/couch.ex @@ -1,4 +1,8 @@ defmodule Couch.Session do + @moduledoc """ + CouchDB session helpers. + """ + @enforce_keys [:cookie] defstruct [:cookie] @@ -155,18 +159,41 @@ defmodule Couch 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)) + + 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, [])) + 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)) + 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])), + do: + Keyword.put( + ib_options, + :stream_to, + spawn(__MODULE__, :transformer, [stream_to, method, url, options]) + ), else: ib_options ib_options = @@ -182,7 +209,9 @@ defmodule Couch do 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), + 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 e9ab98c7e..86f4c7aa0 100644 --- a/test/elixir/mix.exs +++ b/test/elixir/mix.exs @@ -23,7 +23,8 @@ defmodule Foo.Mixfile do [ # {:dep_from_hexpm, "~> 0.3.0"}, {:httpotion, "~> 3.0"}, - {:jiffy, "~> 0.15.2"} + {:jiffy, "~> 0.15.2"}, + {:credo, "~> 1.0.0", only: [:dev, :test], runtime: false} # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}, ] end diff --git a/test/elixir/mix.lock b/test/elixir/mix.lock index abbea1df0..0585a17be 100644 --- a/test/elixir/mix.lock +++ b/test/elixir/mix.lock @@ -1,5 +1,8 @@ %{ + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, + "credo": {:hex, :credo, "1.0.0", "aaa40fdd0543a0cf8080e8c5949d8c25f0a24e4fc8c1d83d06c388f5e5e0ea42", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "httpotion": {:hex, :httpotion, "3.1.0", "14d20d9b0ce4e86e253eb91e4af79e469ad949f57a5d23c0a51b2f86559f6589", [:mix], [{:ibrowse, "~> 4.4", [hex: :ibrowse, repo: "hexpm", optional: false]}], "hexpm"}, "ibrowse": {:hex, :ibrowse, "4.4.1", "2b7d0637b0f8b9b4182de4bd0f2e826a4da2c9b04898b6e15659ba921a8d6ec2", [:rebar3], [], "hexpm"}, + "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, "jiffy": {:hex, :jiffy, "0.15.2", "de266c390111fd4ea28b9302f0bc3d7472468f3b8e0aceabfbefa26d08cd73b7", [:rebar3], [], "hexpm"}, } diff --git a/test/elixir/test/all_docs_test.exs b/test/elixir/test/all_docs_test.exs index b34f05470..21dcb616b 100644 --- a/test/elixir/test/all_docs_test.exs +++ b/test/elixir/test/all_docs_test.exs @@ -53,13 +53,14 @@ defmodule AllDocsTest do } ) - assert length(resp.body["rows"]) == 0 + assert Enum.empty?(resp.body["rows"]) # 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" + assert Enum.member?(revs, hd(row["changes"])["rev"]), + "doc #{row["id"]} should be in changes" end) # Check that deletions also show up right @@ -78,14 +79,17 @@ defmodule AllDocsTest do doc3 = Map.put(doc3, :updated, "totally") assert Couch.put("/#{db_name}/3", body: doc3).body["ok"] - # The update should make doc id 3 have another seq num (not nec. higher or the last though) + # The update should make doc id 3 have another seq num + # (not nec. higher or the last though) changes = Couch.get("/#{db_name}/_changes").body["results"] assert length(changes) == 4 updated_doc = Enum.find(changes, fn row -> row["id"] == "3" end) assert orig_doc["seq"] != updated_doc["seq"], "seq num should be different" # Ok, now let's see what happens with include docs - changes = Couch.get("/#{db_name}/_changes", query: %{:include_docs => true}).body["results"] + changes = + Couch.get("/#{db_name}/_changes", query: %{:include_docs => true}).body["results"] + assert length(changes) == 4 updated_doc = Enum.find(changes, fn row -> row["id"] == doc3["_id"] end) assert updated_doc["doc"]["updated"] == "totally" @@ -94,7 +98,12 @@ defmodule AllDocsTest do assert deleted_doc["doc"]["_deleted"] # Test _all_docs with keys - rows = Couch.post("/#{db_name}/_all_docs", query: %{:include_docs => true}, body: %{:keys => ["1"]}).body["rows"] + rows = + Couch.post("/#{db_name}/_all_docs", + query: %{:include_docs => true}, + body: %{:keys => ["1"]} + ).body["rows"] + row = hd(rows) assert length(rows) == 1 assert row["key"] == "1" @@ -103,17 +112,32 @@ defmodule AllDocsTest do assert row["doc"] == :null # Add conflicts - conflicted_doc1 = %{:_id => "3", :_rev => "2-aa01552213fafa022e6167113ed01087", :value => "X"} - conflicted_doc2 = %{:_id => "3", :_rev => "2-ff01552213fafa022e6167113ed01087", :value => "Z"} - assert Couch.put("/#{db_name}/3", query: %{:new_edits => false}, body: conflicted_doc1).body["ok"] - assert Couch.put("/#{db_name}/3", query: %{:new_edits => false}, body: conflicted_doc2).body["ok"] + conflicted_doc1 = %{ + :_id => "3", + :_rev => "2-aa01552213fafa022e6167113ed01087", + :value => "X" + } + + conflicted_doc2 = %{ + :_id => "3", + :_rev => "2-ff01552213fafa022e6167113ed01087", + :value => "Z" + } + + assert Couch.put("/#{db_name}/3", query: %{:new_edits => false}, body: conflicted_doc1).body[ + "ok" + ] + + 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" - ] + 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" @@ -122,7 +146,11 @@ defmodule AllDocsTest do assert is_list(doc3["doc"]["_conflicts"]) assert length(doc3["doc"]["_conflicts"]) == 2 - rows = Couch.get("/#{db_name}/_all_docs", query: %{:include_docs => true, :conflicts => true}).body["rows"] + rows = + Couch.get("/#{db_name}/_all_docs", + query: %{:include_docs => true, :conflicts => true} + ).body["rows"] + assert length(rows) == 3 change = hd(tl(tl(rows))) assert change["key"] == "3" @@ -136,7 +164,12 @@ defmodule AllDocsTest do # Test that _all_docs collates sanely assert Couch.post("/#{db_name}", body: %{:_id => "Z", :foo => "Z"}).body["ok"] assert Couch.post("/#{db_name}", body: %{:_id => "a", :foo => "a"}).body["ok"] - rows = Couch.get("/#{db_name}/_all_docs", query: %{:startkey => "\"Z\"", :endkey => "\"Z\""}).body["rows"] + + rows = + Couch.get("/#{db_name}/_all_docs", + query: %{:startkey => "\"Z\"", :endkey => "\"Z\""} + ).body["rows"] + assert length(rows) == 1 end end diff --git a/test/elixir/test/basics_test.exs b/test/elixir/test/basics_test.exs index 828e9f7d0..98b7e63cb 100644 --- a/test/elixir/test/basics_test.exs +++ b/test/elixir/test/basics_test.exs @@ -9,9 +9,9 @@ defmodule BasicsTest do """ test "Session contains adm context" do - userCtx = Couch.get("/_session").body["userCtx"] - assert userCtx["name"] == "adm", "Should have adm user context" - assert userCtx["roles"] == ["_admin"], "Should have _admin role" + user_ctx = Couch.get("/_session").body["userCtx"] + assert user_ctx["name"] == "adm", "Should have adm user context" + assert user_ctx["roles"] == ["_admin"], "Should have _admin role" end test "Welcome endpoint" do @@ -36,7 +36,8 @@ defmodule BasicsTest do end @tag :with_db_name - test "Creating a new DB with slashes should return Location header (COUCHDB-411)", context do + test "Creating a new DB with slashes should return Location header (COUCHDB-411)", + context do db_name = context[:db_name] <> "%2Fwith_slashes" {:ok, resp} = create_db(db_name) msg = "Should return Location header for new db" @@ -47,7 +48,9 @@ defmodule BasicsTest do @tag :with_db test "Created database has appropriate db info name", context do db_name = context[:db_name] - assert Couch.get("/#{db_name}").body["db_name"] == db_name, "Get correct database name" + + assert Couch.get("/#{db_name}").body["db_name"] == db_name, + "Get correct database name" end @tag :with_db @@ -57,7 +60,8 @@ defmodule BasicsTest do @tag :with_db test "Empty database should have zero docs", context do - assert Couch.get("/#{context[:db_name]}").body["doc_count"] == 0, "Empty doc count in empty db" + assert Couch.get("/#{context[:db_name]}").body["doc_count"] == 0, + "Empty doc count in empty db" end @tag :with_db @@ -284,7 +288,8 @@ defmodule BasicsTest do @tag :pending @tag :with_db - test "On restart, a request for creating an already existing db can not override", _context do + test "On restart, a request for creating an already existing db can not override", + _context do # TODO assert true end diff --git a/test/elixir/test/coffee_test.exs b/test/elixir/test/coffee_test.exs index 19b1e6987..82a027297 100644 --- a/test/elixir/test/coffee_test.exs +++ b/test/elixir/test/coffee_test.exs @@ -32,7 +32,8 @@ defmodule CoffeeTest do :views => %{ :myview => %{ :map => "(doc) -> if doc.foo\n emit(doc.foo, 1)", - :reduce => "(keys, values, rereduce) ->\n sum = 0\n for x in values\n sum = sum + x\n sum" + :reduce => + "(keys, values, rereduce) ->\n sum = 0\n for x in values\n sum = sum + x\n sum" } }, :shows => %{ @@ -58,10 +59,13 @@ defmodule CoffeeTest do assert Couch.get("/#{db_name}/_design/coffee/_show/myshow/a").body === "Foo 100" - %{"resp" => list_output} = Couch.get("/#{db_name}/_design/coffee/_list/mylist/myview").body + %{"resp" => list_output} = + Couch.get("/#{db_name}/_design/coffee/_list/mylist/myview").body + assert list_output === "Foo 5" - %{"results" => changes_results} = Couch.get("/#{db_name}/_changes", query: %{"filter" => "coffee/filter"}).body + %{"results" => changes_results} = + Couch.get("/#{db_name}/_changes", query: %{"filter" => "coffee/filter"}).body assert length(changes_results) === 5 end diff --git a/test/elixir/test/compact_test.exs b/test/elixir/test/compact_test.exs index 293f99a81..5efeee670 100644 --- a/test/elixir/test/compact_test.exs +++ b/test/elixir/test/compact_test.exs @@ -53,7 +53,9 @@ defmodule CompactTest do doc = %{ _id: "#{@att_doc_id}", - _attachments: %{"#{@att_name}": %{content_type: "text/plain", data: Base.encode64(@att_plaintext)}} + _attachments: %{ + "#{@att_name}": %{content_type: "text/plain", data: Base.encode64(@att_plaintext)} + } } resp = Couch.put("/#{db}/#{doc._id}", body: doc) diff --git a/test/elixir/test/config_test.exs b/test/elixir/test/config_test.exs index 649a25b81..2b2d71414 100644 --- a/test/elixir/test/config_test.exs +++ b/test/elixir/test/config_test.exs @@ -91,7 +91,10 @@ defmodule ConfigTest do set_config(context, "admins", "administrator", plain_pass) assert Couch.login("administrator", plain_pass) hash_pass = get_config(context, "admins", "administrator") - assert Regex.match?(~r/^-pbkdf2-/, hash_pass) or Regex.match?(~r/^-hashed-/, hash_pass) + + assert Regex.match?(~r/^-pbkdf2-/, hash_pass) or + Regex.match?(~r/^-hashed-/, hash_pass) + delete_config(context, "admins", "administrator") assert Couch.delete("/_session").body["ok"] end @@ -135,7 +138,12 @@ defmodule ConfigTest do vals = ["{test,foo}", "{\"test\",\"foo\"}", "{<<\"test\">>,<<\"foo\">>}"] Enum.each(vals, fn pair -> - set_config(context, "httpd", "config_whitelist", "[{httpd,config_whitelist}, #{pair}") + set_config( + context, + "httpd", + "config_whitelist", + "[{httpd,config_whitelist}, #{pair}" + ) pair_format = case String.at(pair, 1) do diff --git a/test/elixir/test/conflicts_test.exs b/test/elixir/test/conflicts_test.exs index 5f54f11cc..8344a27d9 100644 --- a/test/elixir/test/conflicts_test.exs +++ b/test/elixir/test/conflicts_test.exs @@ -38,7 +38,10 @@ defmodule RevisionTest 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" + + expected_reason = + "Document rev from request body and query string " <> "have different values" + assert_bad_request(resp, expected_reason) end @@ -69,7 +72,10 @@ defmodule RevisionTest do expected = %{ "_id" => "doc", "_rev" => r3._rev, - "_revisions" => %{"ids" => for(r <- [r3._rev, r2._rev, r1._rev], do: suffix(r)), "start" => 3}, + "_revisions" => %{ + "ids" => for(r <- [r3._rev, r2._rev, r1._rev], do: suffix(r)), + "start" => 3 + }, "val" => r2.val } diff --git a/test/elixir/test/lots_of_docs_test.exs b/test/elixir/test/lots_of_docs_test.exs index 57e45afcd..2c68ca3c4 100644 --- a/test/elixir/test/lots_of_docs_test.exs +++ b/test/elixir/test/lots_of_docs_test.exs @@ -18,7 +18,9 @@ defmodule LotsOfDocsTest do |> 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 + %{"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) @@ -66,7 +68,9 @@ defmodule LotsOfDocsTest do assert Map.fetch!(Enum.at(rows, i), "key") === i end) - %{"rows" => desc_rows, "total_rows" => desc_total_rows} = query_view(db_name, "descending") + %{"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) diff --git a/test/elixir/test/reduce_test.exs b/test/elixir/test/reduce_test.exs index 5c90a2542..21c58d378 100644 --- a/test/elixir/test/reduce_test.exs +++ b/test/elixir/test/reduce_test.exs @@ -30,7 +30,9 @@ defmodule ReduceTest do 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) @@ -90,7 +92,9 @@ defmodule ReduceTest do %{keys: ["d", "c"]} ] - 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 + total_docs = 1 + (i - 1) * 10 * 11 + (j + 1) * 11 assert Couch.get("/#{db_name}").body["doc_count"] == total_docs end @@ -188,7 +192,9 @@ defmodule ReduceTest do 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"] @@ -219,7 +225,9 @@ defmodule ReduceTest do 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(100_000_000) end @@ -234,32 +242,71 @@ defmodule ReduceTest do query = %{startkey: 400, endkey: 402, foobar: rand_val.(), inclusive_end: false} rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 6 - query = %{startkey: 402, endkey: 400, foobar: rand_val.(), inclusive_end: false, descending: true} + + query = %{ + startkey: 402, + endkey: 400, + foobar: rand_val.(), + inclusive_end: false, + descending: true + } + rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 6 query = %{startkey: 400, endkey: 402, foobar: rand_val.(), endkey_docid: "400"} rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 7 - query = %{startkey: 400, endkey: 402, foobar: rand_val.(), endkey_docid: "400", inclusive_end: false} + + query = %{ + startkey: 400, + endkey: 402, + foobar: rand_val.(), + endkey_docid: "400", + inclusive_end: false + } + rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 6 query = %{startkey: 400, endkey: 402, foobar: rand_val.(), endkey_docid: "401"} rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 8 - query = %{startkey: 400, endkey: 402, foobar: rand_val.(), endkey_docid: "401", inclusive_end: false} + + query = %{ + startkey: 400, + endkey: 402, + foobar: rand_val.(), + endkey_docid: "401", + inclusive_end: false + } + rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 7 query = %{startkey: 400, endkey: 402, foobar: rand_val.(), endkey_docid: "402"} rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 9 - query = %{startkey: 400, endkey: 402, foobar: rand_val.(), endkey_docid: "402", inclusive_end: false} + + query = %{ + startkey: 400, + endkey: 402, + foobar: rand_val.(), + endkey_docid: "402", + 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: "398", descending: true} + 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 @@ -275,7 +322,14 @@ defmodule ReduceTest do 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} + 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 @@ -291,7 +345,14 @@ 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.(), endkey_docid: "400", descending: true} + 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 @@ -307,7 +368,14 @@ defmodule ReduceTest do rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 6 - query = %{startkey: 402, endkey: 400, foobar: rand_val.(), startkey_docid: "400", descending: true} + query = %{ + startkey: 402, + endkey: 400, + foobar: rand_val.(), + startkey_docid: "400", + descending: true + } + rows = Couch.get(view_url, query: query).body["rows"] assert hd(rows)["value"] == 7 @@ -334,7 +402,14 @@ defmodule ReduceTest do assert Enum.at(rows, 2)["key"] == 402 assert Enum.at(rows, 2)["value"] == 3 - query = %{:group => true, startkey: 402, endkey: 400, foobar: rand_val.(), descending: true} + query = %{ + :group => true, + startkey: 402, + endkey: 400, + foobar: rand_val.(), + descending: true + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 3 assert Enum.at(rows, 0)["key"] == 402 @@ -344,7 +419,14 @@ defmodule ReduceTest do assert Enum.at(rows, 2)["key"] == 400 assert Enum.at(rows, 2)["value"] == 3 - query = %{:group => true, startkey: 400, endkey: 402, foobar: rand_val.(), inclusive_end: false} + query = %{ + :group => true, + startkey: 400, + endkey: 402, + foobar: rand_val.(), + inclusive_end: false + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 2 assert Enum.at(rows, 0)["key"] == 400 @@ -352,7 +434,15 @@ 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.(), inclusive_end: false, descending: true} + query = %{ + :group => true, + startkey: 402, + endkey: 400, + foobar: rand_val.(), + inclusive_end: false, + descending: true + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 2 assert Enum.at(rows, 0)["key"] == 402 @@ -360,7 +450,14 @@ defmodule ReduceTest do assert Enum.at(rows, 1)["key"] == 401 assert Enum.at(rows, 1)["value"] == 3 - query = %{:group => true, startkey: 400, endkey: 402, foobar: rand_val.(), endkey_docid: "401"} + query = %{ + :group => true, + startkey: 400, + endkey: 402, + foobar: rand_val.(), + endkey_docid: "401" + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 3 assert Enum.at(rows, 0)["key"] == 400 @@ -370,7 +467,14 @@ defmodule ReduceTest do assert Enum.at(rows, 2)["key"] == 402 assert Enum.at(rows, 2)["value"] == 2 - query = %{:group => true, startkey: 400, endkey: 402, foobar: rand_val.(), endkey_docid: "400"} + query = %{ + :group => true, + startkey: 400, + endkey: 402, + foobar: rand_val.(), + endkey_docid: "400" + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 3 assert Enum.at(rows, 0)["key"] == 400 @@ -380,7 +484,15 @@ defmodule ReduceTest do assert Enum.at(rows, 2)["key"] == 402 assert Enum.at(rows, 2)["value"] == 1 - query = %{:group => true, startkey: 402, endkey: 400, foobar: rand_val.(), startkey_docid: "401", descending: true} + query = %{ + :group => true, + startkey: 402, + endkey: 400, + foobar: rand_val.(), + startkey_docid: "401", + descending: true + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 3 assert Enum.at(rows, 0)["key"] == 402 @@ -390,7 +502,15 @@ 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: "400", descending: true} + query = %{ + :group => true, + startkey: 402, + endkey: 400, + foobar: rand_val.(), + startkey_docid: "400", + descending: true + } + rows = Couch.get(view_url, query: query).body["rows"] assert length(rows) == 3 assert Enum.at(rows, 0)["key"] == 402 diff --git a/test/elixir/test/replication_test.exs b/test/elixir/test/replication_test.exs index fa1b64b62..70db01ebc 100644 --- a/test/elixir/test/replication_test.exs +++ b/test/elixir/test/replication_test.exs @@ -754,7 +754,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 + if rem(doc["integer"], 2) == 0 || doc["string"] == "7" do assert resp.status_code < 300 assert cmp_json(doc, resp.body) else @@ -804,7 +804,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 + if rem(doc["integer"], 2) == 0 do assert resp.status_code < 300 assert cmp_json(doc, resp.body) else @@ -1005,7 +1005,7 @@ defmodule ReplicationTest do result = replicate(repl_src, repl_tgt, body: repl_body) assert result["ok"] - if(total_replicated == 0) do + if total_replicated == 0 do assert result["no_changes"] else assert is_binary(result["start_time"]) @@ -1020,7 +1020,7 @@ defmodule ReplicationTest do orig = Couch.get!("/#{src_db_name}/#{doc_id}") copy = Couch.get!("/#{tgt_db_name}/#{doc_id}") - if(String.starts_with?(doc_id, "foo_")) do + if String.starts_with?(doc_id, "foo_") do assert orig.status_code == 404 assert copy.status_code == 404 else @@ -1036,7 +1036,7 @@ defmodule ReplicationTest do copy = Couch.get!("/#{tgt_db_name}/#{doc["_id"]}") is_doc_id = &Enum.member?(doc_ids, &1) - if(is_doc_id.(doc["_id"]) or is_doc_id.(encoded_id)) do + if is_doc_id.(doc["_id"]) or is_doc_id.(encoded_id) do assert HTTPotion.Response.success?(copy) else assert copy.status_code == 404 @@ -1059,7 +1059,7 @@ defmodule ReplicationTest do total_replicated_after = length(doc_ids_after) - num_missing_after - if(total_replicated_after == 0) do + if total_replicated_after == 0 do assert result["no_changes"] else assert is_binary(result["start_time"]) @@ -1073,7 +1073,7 @@ defmodule ReplicationTest do orig = Couch.get!("/#{src_db_name}/#{doc_id}") copy = Couch.get!("/#{tgt_db_name}/#{doc_id}") - if(String.starts_with?(doc_id, "foo_")) do + if String.starts_with?(doc_id, "foo_") do assert orig.status_code == 404 assert copy.status_code == 404 else @@ -1091,7 +1091,7 @@ defmodule ReplicationTest do copy = Couch.get!("/#{tgt_db_name}/#{doc["_id"]}") is_doc_id = &Enum.member?(all_doc_ids, &1) - if(is_doc_id.(doc["_id"]) or is_doc_id.(encoded_id)) do + if is_doc_id.(doc["_id"]) or is_doc_id.(encoded_id) do assert HTTPotion.Response.success?(copy) else assert copy.status_code == 404 @@ -1224,7 +1224,7 @@ defmodule ReplicationTest do assert is_binary(result["_local_id"]) repl_id = result["_local_id"] - task = get_task(repl_id, 30000) + task = get_task(repl_id, 30_000) assert is_map(task), "Error waiting for replication to start" wait_for_repl(src_db_name, repl_id, 26) @@ -1403,7 +1403,7 @@ defmodule ReplicationTest do doc = %{"_id" => "foobar", "value" => 666} [doc] = save_docs(src_db_name, [doc]) - wait_for_repl_stop(repl_id, 30000) + wait_for_repl_stop(repl_id, 30_000) resp = Couch.get("/#{tgt_db_name}/#{doc["_id"]}") assert resp.status_code == 404 @@ -1583,7 +1583,7 @@ defmodule ReplicationTest do tgt = set_user(tgt, userinfo) defaults = [headers: [], body: %{}, timeout: 30_000] - options = Keyword.merge(defaults, options) |> Enum.into(%{}) + options = defaults |> Keyword.merge(options) |> Enum.into(%{}) %{body: body} = options body = [source: src, target: tgt] |> Enum.into(body) @@ -1635,7 +1635,7 @@ defmodule ReplicationTest do content_type: "text/plain" ] - att = Keyword.merge(defaults, att) |> Enum.into(%{}) + att = defaults |> Keyword.merge(att) |> Enum.into(%{}) uri = "/#{db_name}/#{URI.encode(doc["_id"])}/#{att[:name]}" headers = ["Content-Type": att[:content_type]] @@ -1652,7 +1652,7 @@ defmodule ReplicationTest do end def wait_for_repl(src_db_name, repl_id, expect_revs_checked) do - wait_for_repl(src_db_name, repl_id, expect_revs_checked, 30000) + wait_for_repl(src_db_name, repl_id, expect_revs_checked, 30_000) end def wait_for_repl(_, _, _, wait_left) when wait_left <= 0 do @@ -1674,7 +1674,7 @@ defmodule ReplicationTest do end def wait_for_repl_stop(repl_id) do - wait_for_repl_stop(repl_id, 30000) + wait_for_repl_stop(repl_id, 30_000) end def wait_for_repl_stop(repl_id, wait_left) when wait_left <= 0 do diff --git a/test/elixir/test/rewrite_test.exs b/test/elixir/test/rewrite_test.exs index c27f92659..250eb53d7 100644 --- a/test/elixir/test/rewrite_test.exs +++ b/test/elixir/test/rewrite_test.exs @@ -8,335 +8,354 @@ defmodule RewriteTest do This is a port of the rewrite.js suite """ - 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"} - ] - test "Test basic rewrites on #{db_name}", context do - db_name = context[:db_name] + 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"} + ] + test "Test basic rewrites on #{db_name}", context do + db_name = context[:db_name] - ddoc = ~S""" - { - "_id": "_design/test", - "language": "javascript", - "_attachments": { - "foo.txt": { - "content_type":"text/plain", - "data": "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=" - } - }, - "rewrites": [ - { - "from": "foo", - "to": "foo.txt" - }, - { - "from": "foo2", - "to": "foo.txt", - "method": "GET" - }, - { - "from": "hello/:id", - "to": "_update/hello/:id", - "method": "PUT" - }, - { - "from": "/welcome", - "to": "_show/welcome" - }, - { - "from": "/welcome/:name", - "to": "_show/welcome", - "query": { - "name": ":name" - } - }, - { - "from": "/welcome2", - "to": "_show/welcome", - "query": { - "name": "user" - } - }, - { - "from": "/welcome3/:name", - "to": "_update/welcome2/:name", - "method": "PUT" - }, - { - "from": "/welcome3/:name", - "to": "_show/welcome2/:name", - "method": "GET" - }, - { - "from": "/welcome4/*", - "to" : "_show/welcome3", - "query": { - "name": "*" + ddoc = ~S""" + { + "_id": "_design/test", + "language": "javascript", + "_attachments": { + "foo.txt": { + "content_type":"text/plain", + "data": "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=" } }, - { - "from": "/welcome5/*", - "to" : "_show/*", - "query": { - "name": "*" - } - }, - { - "from": "basicView", - "to": "_view/basicView" - }, - { - "from": "simpleForm/basicView", - "to": "_list/simpleForm/basicView" - }, - { - "from": "simpleForm/basicViewFixed", - "to": "_list/simpleForm/basicView", - "query": { - "startkey": 3, - "endkey": 8 - } - }, - { - "from": "simpleForm/basicViewPath/:start/:end", - "to": "_list/simpleForm/basicView", - "query": { - "startkey": ":start", - "endkey": ":end" + "rewrites": [ + { + "from": "foo", + "to": "foo.txt" }, - "formats": { - "start": "int", - "end": "int" - } - }, - { - "from": "simpleForm/complexView", - "to": "_list/simpleForm/complexView", - "query": { - "key": [1, 2] - } - }, - { - "from": "simpleForm/complexView2", - "to": "_list/simpleForm/complexView", - "query": { - "key": ["test", {}] - } - }, - { - "from": "simpleForm/complexView3", - "to": "_list/simpleForm/complexView", - "query": { - "key": ["test", ["test", "essai"]] - } - }, - { - "from": "simpleForm/complexView4", - "to": "_list/simpleForm/complexView2", - "query": { - "key": {"c": 1} - } - }, - { - "from": "simpleForm/complexView5/:a/:b", - "to": "_list/simpleForm/complexView3", - "query": { - "key": [":a", ":b"] - } - }, - { - "from": "simpleForm/complexView6", - "to": "_list/simpleForm/complexView3", - "query": { - "key": [":a", ":b"] - } - }, - { - "from": "simpleForm/complexView7/:a/:b", - "to": "_view/complexView3", - "query": { - "key": [":a", ":b"], - "include_docs": ":doc" + { + "from": "foo2", + "to": "foo.txt", + "method": "GET" }, - "format": { - "doc": "bool" - } - - }, - { - "from": "/", - "to": "_view/basicView" - }, - { - "from": "/db/*", - "to": "../../*" - } - ], - "lists": { - "simpleForm": "function(head, req) { - log(\"simpleForm\"); - send(\"<ul>\"); - var row, row_number = 0, prevKey, firstKey = null; - while (row = getRow()) { - row_number += 1; - if (!firstKey) firstKey = row.key; - prevKey = row.key; - send(\"\\n<li>Key: \"+row.key - +\" Value: \"+row.value - +\" LineNo: \"+row_number+\"</li>\"); - } - return \"</ul><p>FirstKey: \"+ firstKey + \" LastKey: \"+ prevKey+\"</p>\"; - }" - }, - "shows": { - "welcome": "(function(doc,req) { - return \"Welcome \" + req.query[\"name\"]; - })", - "welcome2": "(function(doc, req) { - return \"Welcome \" + doc.name; - })", - "welcome3": "(function(doc,req) { - return \"Welcome \" + req.query[\"name\"]; - })" - }, - "updates": { - "hello" : "(function(doc, req) { - if (!doc) { - if (req.id) { - return [{ - _id : req.id - }, \"New World\"] + { + "from": "hello/:id", + "to": "_update/hello/:id", + "method": "PUT" + }, + { + "from": "/welcome", + "to": "_show/welcome" + }, + { + "from": "/welcome/:name", + "to": "_show/welcome", + "query": { + "name": ":name" } - return [null, \"Empty World\"]; - } - doc.world = \"hello\"; - doc.edited_by = req.userCtx; - return [doc, \"hello doc\"]; - })", - "welcome2": "(function(doc, req) { - if (!doc) { - if (req.id) { - return [{ - _id: req.id, - name: req.id - }, \"New World\"] + }, + { + "from": "/welcome2", + "to": "_show/welcome", + "query": { + "name": "user" } - return [null, \"Empty World\"]; - } - return [doc, \"hello doc\"]; - })" - }, - "views" : { - "basicView" : { - "map" : "(function(doc) { - if (doc.integer) { - emit(doc.integer, doc.string); + }, + { + "from": "/welcome3/:name", + "to": "_update/welcome2/:name", + "method": "PUT" + }, + { + "from": "/welcome3/:name", + "to": "_show/welcome2/:name", + "method": "GET" + }, + { + "from": "/welcome4/*", + "to" : "_show/welcome3", + "query": { + "name": "*" + } + }, + { + "from": "/welcome5/*", + "to" : "_show/*", + "query": { + "name": "*" + } + }, + { + "from": "basicView", + "to": "_view/basicView" + }, + { + "from": "simpleForm/basicView", + "to": "_list/simpleForm/basicView" + }, + { + "from": "simpleForm/basicViewFixed", + "to": "_list/simpleForm/basicView", + "query": { + "startkey": 3, + "endkey": 8 + } + }, + { + "from": "simpleForm/basicViewPath/:start/:end", + "to": "_list/simpleForm/basicView", + "query": { + "startkey": ":start", + "endkey": ":end" + }, + "formats": { + "start": "int", + "end": "int" + } + }, + { + "from": "simpleForm/complexView", + "to": "_list/simpleForm/complexView", + "query": { + "key": [1, 2] + } + }, + { + "from": "simpleForm/complexView2", + "to": "_list/simpleForm/complexView", + "query": { + "key": ["test", {}] + } + }, + { + "from": "simpleForm/complexView3", + "to": "_list/simpleForm/complexView", + "query": { + "key": ["test", ["test", "essai"]] + } + }, + { + "from": "simpleForm/complexView4", + "to": "_list/simpleForm/complexView2", + "query": { + "key": {"c": 1} + } + }, + { + "from": "simpleForm/complexView5/:a/:b", + "to": "_list/simpleForm/complexView3", + "query": { + "key": [":a", ":b"] + } + }, + { + "from": "simpleForm/complexView6", + "to": "_list/simpleForm/complexView3", + "query": { + "key": [":a", ":b"] + } + }, + { + "from": "simpleForm/complexView7/:a/:b", + "to": "_view/complexView3", + "query": { + "key": [":a", ":b"], + "include_docs": ":doc" + }, + "format": { + "doc": "bool" } - })" - }, - "complexView": { - "map": "(function(doc) { - if (doc.type == \"complex\") { - emit([doc.a, doc.b], doc.string); + }, + { + "from": "/", + "to": "_view/basicView" + }, + { + "from": "/db/*", + "to": "../../*" + } + ], + "lists": { + "simpleForm": "function(head, req) { + log(\"simpleForm\"); + send(\"<ul>\"); + var row, row_number = 0, prevKey, firstKey = null; + while (row = getRow()) { + row_number += 1; + if (!firstKey) firstKey = row.key; + prevKey = row.key; + send(\"\\n<li>Key: \"+row.key + +\" Value: \"+row.value + +\" LineNo: \"+row_number+\"</li>\"); } - })" + return \"</ul><p>FirstKey: \"+ firstKey + \" LastKey: \"+ prevKey+\"</p>\"; + }" }, - "complexView2": { - "map": "(function(doc) { - if (doc.type == \"complex\") { - emit(doc.a, doc.string); - } + "shows": { + "welcome": "(function(doc,req) { + return \"Welcome \" + req.query[\"name\"]; + })", + "welcome2": "(function(doc, req) { + return \"Welcome \" + doc.name; + })", + "welcome3": "(function(doc,req) { + return \"Welcome \" + req.query[\"name\"]; })" }, - "complexView3": { - "map": "(function(doc) { - if (doc.type == \"complex\") { - emit(doc.b, doc.string); + "updates": { + "hello" : "(function(doc, req) { + if (!doc) { + if (req.id) { + return [{ + _id : req.id + }, \"New World\"] + } + return [null, \"Empty World\"]; + } + doc.world = \"hello\"; + doc.edited_by = req.userCtx; + return [doc, \"hello doc\"]; + })", + "welcome2": "(function(doc, req) { + if (!doc) { + if (req.id) { + return [{ + _id: req.id, + name: req.id + }, \"New World\"] + } + return [null, \"Empty World\"]; } + return [doc, \"hello doc\"]; })" + }, + "views" : { + "basicView" : { + "map" : "(function(doc) { + if (doc.integer) { + emit(doc.integer, doc.string); + } + + })" + }, + "complexView": { + "map": "(function(doc) { + if (doc.type == \"complex\") { + emit([doc.a, doc.b], doc.string); + } + })" + }, + "complexView2": { + "map": "(function(doc) { + if (doc.type == \"complex\") { + emit(doc.a, doc.string); + } + })" + }, + "complexView3": { + "map": "(function(doc) { + if (doc.type == \"complex\") { + emit(doc.b, doc.string); + } + })" + } } } - } - """ + """ + + 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"}, + %{"a" => "test", "b" => %{}, "string" => "doc 3", "type" => "complex"}, + %{ + "a" => "test", + "b" => ["test", "essai"], + "string" => "doc 4", + "type" => "complex" + }, + %{"a" => %{"c" => 1}, "b" => "", "string" => "doc 5", "type" => "complex"} + ] - ddoc = String.replace(ddoc, ~r/[\r\n]+/, "") + assert Couch.put("/#{db_name}/_design/test", body: ddoc).body["ok"] - docs1 = make_docs(0..9) + assert Couch.post("/#{db_name}/_bulk_docs", + body: %{:docs => docs1}, + query: %{w: 3} + ).status_code == 201 - docs2 = [ - %{"a" => 1, "b" => 1, "string" => "doc 1", "type" => "complex"}, - %{"a" => 1, "b" => 2, "string" => "doc 2", "type" => "complex"}, - %{"a" => "test", "b" => %{}, "string" => "doc 3", "type" => "complex"}, - %{"a" => "test", "b" => ["test", "essai"], "string" => "doc 4", "type" => "complex"}, - %{"a" => %{"c" => 1}, "b" => "", "string" => "doc 5", "type" => "complex"} - ] + 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") + assert resp.body == "This is a base64 encoded text" + assert resp.headers["Content-Type"] == "text/plain" - # Test simple rewriting - resp = Couch.get("/#{db_name}/_design/test/_rewrite/foo") - assert resp.body == "This is a base64 encoded text" - assert resp.headers["Content-Type"] == "text/plain" + resp = Couch.get("/#{db_name}/_design/test/_rewrite/foo2") + assert resp.body == "This is a base64 encoded text" + assert resp.headers["Content-Type"] == "text/plain" - resp = Couch.get("/#{db_name}/_design/test/_rewrite/foo2") - assert resp.body == "This is a base64 encoded text" - assert resp.headers["Content-Type"] == "text/plain" + # Test POST, hello update world + resp = + Couch.post("/#{db_name}", body: %{"word" => "plankton", "name" => "Rusty"}).body - # Test POST, hello update world - resp = Couch.post("/#{db_name}", body: %{"word" => "plankton", "name" => "Rusty"}).body - assert resp["ok"] - doc_id = resp["id"] - assert doc_id + assert resp["ok"] + doc_id = resp["id"] + assert doc_id - resp = Couch.put("/#{db_name}/_design/test/_rewrite/hello/#{doc_id}") - assert resp.status_code == 201 - assert resp.body == "hello doc" - assert String.match?(resp.headers["Content-Type"], ~r/charset=utf-8/) + resp = Couch.put("/#{db_name}/_design/test/_rewrite/hello/#{doc_id}") + assert resp.status_code == 201 + assert resp.body == "hello doc" + assert String.match?(resp.headers["Content-Type"], ~r/charset=utf-8/) - assert Couch.get("/#{db_name}/#{doc_id}").body["world"] == "hello" + assert Couch.get("/#{db_name}/#{doc_id}").body["world"] == "hello" - resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome?name=user") - assert resp.body == "Welcome user" + resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome?name=user") + assert resp.body == "Welcome user" - resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome/user") - assert resp.body == "Welcome user" + resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome/user") + assert resp.body == "Welcome user" - resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome2") - assert resp.body == "Welcome user" + resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome2") + assert resp.body == "Welcome user" - resp = Couch.put("/#{db_name}/_design/test/_rewrite/welcome3/test") - assert resp.status_code == 201 - assert resp.body == "New World" - assert String.match?(resp.headers["Content-Type"], ~r/charset=utf-8/) + resp = Couch.put("/#{db_name}/_design/test/_rewrite/welcome3/test") + assert resp.status_code == 201 + assert resp.body == "New World" + assert String.match?(resp.headers["Content-Type"], ~r/charset=utf-8/) - resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome3/test") - assert resp.body == "Welcome test" + resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome3/test") + assert resp.body == "Welcome test" - # TODO: port the two "bugged" tests from rewrite.js + # TODO: port the two "bugged" tests from rewrite.js - resp = Couch.get("/#{db_name}/_design/test/_rewrite/basicView") - assert resp.status_code == 200 - assert resp.body["total_rows"] == 9 + resp = Couch.get("/#{db_name}/_design/test/_rewrite/basicView") + assert resp.status_code == 200 + assert resp.body["total_rows"] == 9 - resp = Couch.get("/#{db_name}/_design/test/_rewrite") - assert resp.status_code == 200 - assert resp.body["total_rows"] == 9 + resp = Couch.get("/#{db_name}/_design/test/_rewrite") + assert resp.status_code == 200 + assert resp.body["total_rows"] == 9 - # TODO: port _list function tests and everything below in rewrite.js - # This is currently broken because _list funcitons default to application/json - # response bodies and my attempts to change the content-type from within the - # _list function have not yet succeeded. - # - # Test GET with query params - # resp = Couch.get("/#{db_name}/_design/test/_rewrite/simpleForm/basicView", query: %{startkey: 3, endkey: 8}) - # Logger.error("GOT RESP: #{inspect resp.body}") - # assert resp.status_code == 200 + # TODO: port _list function tests and everything below in rewrite.js + # This is currently broken because _list funcitons default to application/json + # response bodies and my attempts to change the content-type from within the + # _list function have not yet succeeded. + # + # Test GET with query params + # resp = Couch.get("/#{db_name}/_design/test/_rewrite/simpleForm/basicView", query: %{startkey: 3, endkey: 8}) + # Logger.error("GOT RESP: #{inspect resp.body}") + # assert resp.status_code == 200 + end end - end) + ) end diff --git a/test/elixir/test/security_validation_test.exs b/test/elixir/test/security_validation_test.exs index a020c507c..5f4ddba8c 100644 --- a/test/elixir/test/security_validation_test.exs +++ b/test/elixir/test/security_validation_test.exs @@ -126,10 +126,16 @@ defmodule SecurityValidationTest do assert Couch.post("/#{db_name}", body: @ddoc).body["ok"] new_rev = "2-642e20f96624a0aae6025b4dba0c6fb2" - ddoc = Map.put(@ddoc, :_rev, new_rev) |> Map.put(:foo, "bar") + ddoc = @ddoc |> Map.put(:_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 @@ -158,7 +164,10 @@ defmodule SecurityValidationTest do 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 @@ -168,7 +177,9 @@ defmodule SecurityValidationTest do assert resp.body["error"] == "forbidden" # Enable admin override for changing author values - assert Couch.put("/#{db_name}/_security", body: %{sec_obj | admin_override: true}).body["ok"] + assert Couch.put("/#{db_name}/_security", body: %{sec_obj | admin_override: true}).body[ + "ok" + ] # Change owner to Tom test_doc = Map.put(test_doc, "author", "tom") @@ -222,7 +233,9 @@ 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}); @@ -239,7 +252,8 @@ end # adminDbB = new CouchDB("" + db_name + "_b", {"X-Couch-Full-Commit":"false"}); # var dbA = new CouchDB("" + db_name + "_a", AuthHeaders); # var dbB = new CouchDB("" + db_name + "_b", AuthHeaders); -# // looping does not really add value as the scenario is the same anyway (there's nothing 2 be gained from it) +# // looping does not really add value as the scenario is the same anyway +# // (there's nothing 2 be gained from it) # var A = CouchDB.protocol + CouchDB.host + "/" + db_name + "_a"; # var B = CouchDB.protocol + CouchDB.host + "/" + db_name + "_b"; # @@ -287,7 +301,8 @@ end # foo2.value = "b"; # T(dbB.save(foo2).ok); # -# var results = CouchDB.replicate({"url": B, "headers": AuthHeaders}, {"url": A, "headers": AuthHeaders}, {headers:AuthHeaders}); +# var results = CouchDB.replicate({"url": B, "headers": AuthHeaders}, +# {"url": A, "headers": AuthHeaders}, {headers:AuthHeaders}); # T(results.ok); # TEquals(1, results.history[0].docs_written); # TEquals(2, results.history[0].doc_write_failures); |