diff options
Diffstat (limited to 'test/elixir/test/auth_cache_test.exs')
-rw-r--r-- | test/elixir/test/auth_cache_test.exs | 212 |
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 |