summaryrefslogtreecommitdiff
path: root/test/elixir/test/auth_cache_test.exs
diff options
context:
space:
mode:
Diffstat (limited to 'test/elixir/test/auth_cache_test.exs')
-rw-r--r--test/elixir/test/auth_cache_test.exs212
1 files changed, 212 insertions, 0 deletions
diff --git a/test/elixir/test/auth_cache_test.exs b/test/elixir/test/auth_cache_test.exs
new file mode 100644
index 000000000..2ba396de7
--- /dev/null
+++ b/test/elixir/test/auth_cache_test.exs
@@ -0,0 +1,212 @@
+defmodule AuthCacheTest do
+ use CouchTestCase
+
+ @moduletag :authentication
+
+ @tag :pending
+ @tag :with_db
+ test "auth cache management", context do
+ db_name = context[:db_name]
+
+ server_config = [
+ %{
+ :section => "chttpd_auth",
+ :key => "authentication_db",
+ :value => db_name
+ },
+ %{
+ :section => "chttpd_auth",
+ :key => "auth_cache_size",
+ :value => "3"
+ },
+ %{
+ :section => "httpd",
+ :key => "authentication_handlers",
+ :value => "{couch_httpd_auth, default_authentication_handler}"
+ },
+ %{
+ :section => "chttpd_auth",
+ :key => "secret",
+ :value => generate_secret(64)
+ }
+ ]
+
+ run_on_modified_server(server_config, fn -> test_fun(db_name) end)
+ end
+
+ defp generate_secret(len) do
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+ |> String.splitter("", trim: true)
+ |> Enum.take_random(len)
+ |> Enum.join("")
+ end
+
+ defp hits() do
+ hits = request_stats(["couchdb", "auth_cache_hits"], true)
+ hits["value"] || 0
+ end
+
+ defp misses() do
+ misses = request_stats(["couchdb", "auth_cache_misses"], true)
+ misses["value"] || 0
+ end
+
+ defp logout(session) do
+ assert Couch.Session.logout(session).body["ok"]
+ end
+
+ defp login_fail(user, password) do
+ resp = Couch.login(user, password, :fail)
+ assert resp.error, "Login error is expected."
+ end
+
+ defp login(user, password) do
+ sess = Couch.login(user, password)
+ assert sess.cookie, "Login correct is expected"
+ sess
+ end
+
+ defp wait_until_compact_complete(db_name) do
+ retry_until(
+ fn -> Map.get(info(db_name), "compact_running") == false end,
+ 200,
+ 10_000
+ )
+ end
+
+ defp assert_cache(event, user, password, expect \\ :expect_login_success) do
+ hits_before = hits()
+ misses_before = misses()
+
+ session =
+ case expect do
+ :expect_login_success -> login(user, password)
+ :expect_login_fail -> login_fail(user, password)
+ _ -> assert false
+ end
+
+ hits_after = hits()
+ misses_after = misses()
+
+ if expect == :expect_success do
+ logout(session)
+ end
+
+ case event do
+ :expect_miss ->
+ assert misses_after == misses_before + 1,
+ "Cache miss is expected for #{user} after login"
+
+ assert hits_after == hits_before,
+ "No cache hit is expected for #{user} after login"
+
+ :expect_hit ->
+ assert misses_after == misses_before,
+ "No cache miss is expected for #{user} after login"
+
+ assert hits_after == hits_before + 1,
+ "Cache hit is expected for #{user} after login"
+
+ _ ->
+ assert false
+ end
+ end
+
+ defp compact(db_name) do
+ resp = Couch.post("/#{db_name}/_compact")
+ assert resp.status_code == 202
+ resp.body
+ end
+
+ def save_doc(db_name, body) do
+ resp = Couch.put("/#{db_name}/#{body["_id"]}", body: body)
+ assert resp.status_code in [201, 202]
+ assert resp.body["ok"]
+ Map.put(body, "_rev", resp.body["rev"])
+ end
+
+ def delete_doc(db_name, body) do
+ resp = Couch.delete("/#{db_name}/#{body["_id"]}", query: [rev: body["_rev"]])
+ assert resp.status_code in [200, 202]
+ assert resp.body["ok"]
+ {:ok, resp}
+ end
+
+ defp test_fun(db_name) do
+ fdmanana =
+ prepare_user_doc([
+ {:name, "fdmanana"},
+ {:password, "qwerty"},
+ {:roles, ["dev"]}
+ ])
+
+ {:ok, resp} = create_doc(db_name, fdmanana)
+ fdmanana = Map.put(fdmanana, "_rev", resp.body["rev"])
+
+ chris =
+ prepare_user_doc([
+ {:name, "chris"},
+ {:password, "the_god_father"},
+ {:roles, ["dev", "mafia", "white_costume"]}
+ ])
+
+ create_doc(db_name, chris)
+
+ joe =
+ prepare_user_doc([
+ {:name, "joe"},
+ {:password, "functional"},
+ {:roles, ["erlnager"]}
+ ])
+
+ create_doc(db_name, joe)
+
+ johndoe =
+ prepare_user_doc([
+ {:name, "johndoe"},
+ {:password, "123456"},
+ {:roles, ["user"]}
+ ])
+
+ create_doc(db_name, johndoe)
+
+ assert_cache(:expect_miss, "fdmanana", "qwerty")
+ assert_cache(:expect_hit, "fdmanana", "qwerty")
+ assert_cache(:expect_miss, "chris", "the_god_father")
+ assert_cache(:expect_miss, "joe", "functional")
+ assert_cache(:expect_miss, "johndoe", "123456")
+
+ # It's a MRU cache, joe was removed from cache to add johndoe
+ # BUGGED assert_cache(:expect_miss, "joe", "functional")
+
+ assert_cache(:expect_hit, "fdmanana", "qwerty")
+
+ fdmanana = Map.replace!(fdmanana, "password", "foobar")
+ fdmanana = save_doc(db_name, fdmanana)
+
+ # Cache was refreshed
+ # BUGGED
+ # assert_cache(:expect_hit, "fdmanana", "qwerty", :expect_login_fail)
+ # assert_cache(:expect_hit, "fdmanana", "foobar")
+
+ # and yet another update
+ fdmanana = Map.replace!(fdmanana, "password", "javascript")
+ fdmanana = save_doc(db_name, fdmanana)
+
+ # Cache was refreshed
+ # BUGGED
+ # assert_cache(:expect_hit, "fdmanana", "foobar", :expect_login_fail)
+ # assert_cache(:expect_hit, "fdmanana", "javascript")
+
+ delete_doc(db_name, fdmanana)
+
+ assert_cache(:expect_hit, "fdmanana", "javascript", :expect_login_fail)
+
+ # login, compact authentication DB, login again and verify that
+ # there was a cache hit
+ assert_cache(:expect_hit, "johndoe", "123456")
+ compact(db_name)
+ wait_until_compact_complete(db_name)
+ assert_cache(:expect_hit, "johndoe", "123456")
+ end
+end