File size: 4,710 Bytes
c9c49ab | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | defmodule Plausible.Shield.HostnameRuleCacheTest do
use Plausible.DataCase, async: true
alias Plausible.Shield.HostnameRule
alias Plausible.Shield.HostnameRuleCache
alias Plausible.Shields
describe "public cache interface" do
test "cache caches hostname rules", %{test: test} do
cache_opts = [force?: true, cache_name: test]
{:ok, _} =
Supervisor.start_link(
[
{HostnameRuleCache,
[cache_name: test, child_id: :hostname_rules_cache_id, ets_options: [:bag]]}
],
strategy: :one_for_one,
name: :"cache_supervisor_#{test}"
)
site1 = insert(:site)
site2 = insert(:site)
{:ok, %{id: rid1}} = Shields.add_hostname_rule(site1, %{"hostname" => "1.example.com"})
{:ok, %{id: rid2}} = Shields.add_hostname_rule(site1, %{"hostname" => "2.example.com"})
{:ok, %{id: rid3}} = Shields.add_hostname_rule(site2, %{"hostname" => "3.example.com"})
:ok = HostnameRuleCache.refresh_all(cache_name: test)
:ok = Shields.remove_hostname_rule(site1, rid1)
# cache is stale
assert HostnameRuleCache.size(test) == 3
# the rule order should be deterministic, but with 1s timestamp sorting precision
# race conditions may happen during tests
assert rules = HostnameRuleCache.get(site1.domain, cache_opts)
rule_ids = Enum.map(rules, & &1.id)
assert rid1 in rule_ids
assert rid2 in rule_ids
assert length(rules) == 2
assert %HostnameRule{from_cache?: true, id: ^rid3} =
HostnameRuleCache.get(site2.domain, cache_opts)
refute HostnameRuleCache.get("rogue.example.com", cache_opts)
end
test "hostname path patterns are already compiled when fetched from cache", %{test: test} do
site = insert(:site)
{:ok, _} = start_test_cache(test)
cache_opts = [force?: true, cache_name: test]
{:ok, _} = Shields.add_hostname_rule(site, %{"hostname" => "*example.com"})
:ok = HostnameRuleCache.refresh_all(cache_name: test)
assert regex = HostnameRuleCache.get(site.domain, cache_opts).hostname_pattern
assert Regex.source(regex) == "^.*example\\.com$"
end
test "cache allows lookups for hostname paths on sites with changed domain", %{test: test} do
{:ok, _} = start_test_cache(test)
cache_opts = [force?: true, cache_name: test]
site = insert(:site, domain: "new.example.com", domain_changed_from: "old.example.com")
{:ok, _} = Shields.add_hostname_rule(site, %{"hostname" => "#{test}"})
:ok = HostnameRuleCache.refresh_all(cache_name: test)
assert HostnameRuleCache.get("old.example.com", cache_opts)
assert HostnameRuleCache.get("new.example.com", cache_opts)
refute HostnameRuleCache.get("rogue.example.com", cache_opts)
end
test "refreshes only recently added hostnames rules", %{test: test} do
{:ok, _} = start_test_cache(test)
domain = "site1.example.com"
site = insert(:site, domain: domain)
cache_opts = [cache_name: test, force?: true]
yesterday =
NaiveDateTime.utc_now()
|> NaiveDateTime.add(-1 * 60 * 60 * 24)
|> NaiveDateTime.truncate(:second)
{:ok, r1} = Plausible.Shields.add_hostname_rule(site, %{"hostname" => "test1.example.com"})
Ecto.Changeset.change(r1, inserted_at: yesterday, updated_at: yesterday) |> Repo.update!()
{:ok, _} = Plausible.Shields.add_hostname_rule(site, %{"hostname" => "test2.example.com"})
assert HostnameRuleCache.get(domain, cache_opts) == nil
assert :ok = HostnameRuleCache.refresh_updated_recently(cache_opts)
assert %{hostname_pattern: hostname_pattern} =
HostnameRuleCache.get(domain, cache_opts)
assert Regex.source(hostname_pattern) == "^test2\\.example\\.com$"
assert :ok = HostnameRuleCache.refresh_all(cache_opts)
assert [_, _] = HostnameRuleCache.get(domain, cache_opts)
end
end
test "get_from_source", %{test: test} do
{:ok, _} = start_test_cache(test)
domain = "site1.example.com"
site = insert(:site, domain: domain)
cache_opts = [cache_name: test, force?: true]
{:ok, _} = Shields.add_hostname_rule(site, %{"hostname" => "#{test}"})
{:ok, _} = Shields.add_hostname_rule(site, %{"hostname" => "#{test}*"})
:ok = HostnameRuleCache.refresh_all(cache_opts)
assert length(HostnameRuleCache.get(domain, cache_opts)) ==
length(HostnameRuleCache.get_from_source(domain))
end
defp start_test_cache(cache_name) do
%{start: {m, f, a}} =
HostnameRuleCache.child_spec(cache_name: cache_name, ets_options: [:bag])
apply(m, f, a)
end
end
|