Skip to content

Commit

Permalink
fix json_set in sandbox (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
CorneliaKelinske committed May 31, 2023
1 parent ee2925a commit 748da66
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 4 deletions.
15 changes: 14 additions & 1 deletion lib/cache/redis/global.ex
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,22 @@ defmodule Cache.Redis.Global do

defp handle_response({:ok, "OK"}), do: :ok
defp handle_response({:ok, _} = res), do: res

defp handle_response({:error, %Redix.ConnectionError{reason: reason}}) do
{:error, ErrorMessage.service_unavailable("redis connection errored because: #{reason}")}
end

defp handle_response({:error, _} = res), do: res
defp handle_response({:error, %Redix.Error{message: "ERR Path" <> _rest = message}}) do
{:error, ErrorMessage.not_found(message)}
end

defp handle_response(
{:error, %Redix.Error{message: "ERR new objects must be created at the root" = message}}
) do
{:error, ErrorMessage.bad_request(message)}
end

defp handle_response({:error, error}) do
{:error, ErrorMessage.internal_server_error("Internal server error", %{error: inspect(error)})}
end
end
17 changes: 15 additions & 2 deletions lib/cache/sandbox.ex
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,29 @@ defmodule Cache.Sandbox do

def json_get(cache_name, key, path, _opts) do
Agent.get(cache_name, fn state ->
{:ok, get_in(state, [key, String.split(path, ".")])}
case get_in(state, [key | String.split(path, ".")]) do
nil -> {:error, ErrorMessage.not_found("ERR Path '$.#{path}' does not exist")}
value -> {:ok, value}
end
end)
end

def json_set(cache_name, key, path, value, _opts) do
Agent.update(cache_name, fn state ->
Map.put(state, key, put_in(state, [String.split(path, ".")], value))
put_in(state, add_defaults([key | String.split(path, ".")]), value)
end)
end

defp add_defaults([key | keys]) do
[Access.key(key, key_default(key)) | add_defaults(keys)]
end

defp add_defaults(keys), do: keys

defp key_default(key) do
if Regex.match?(~r/\d+/, key), do: [], else: %{}
end

def json_incr(cache_name, key, path, incr \\ 1, _opts) do
Agent.update(cache_name, fn state ->
Map.update(state, key, nil, fn value ->
Expand Down
38 changes: 37 additions & 1 deletion test/cache/redis_json_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule Cache.RedisJSONTest do
some_integer: 1234,
some_array: [1, 2, 3, 4],
some_empty_array: [],
some_map: %{one: 1, two: 2, three: 3, four: 4},
some_map: %{one: 1, two: 2, three: 3, four: 4}
}

defmodule RedisCache do
Expand Down Expand Up @@ -44,6 +44,15 @@ defmodule Cache.RedisJSONTest do
assert {:ok, @test_value.some_map.one} === RedisCache.json_get(key, [:some_map, :one])
assert {:ok, Enum.at(@test_value.some_array, 0)} === RedisCache.json_get(key, [:some_array, 0])
end

test "returns :error tuple if path not found", %{key: key} do
assert {:error,
%ErrorMessage{
message: "ERR Path '$.non_existing.path' does not exist",
code: :not_found,
details: nil
}} === RedisCache.json_get(key, [:non_existing, :path])
end
end

describe "&json_set/2" do
Expand All @@ -58,6 +67,33 @@ defmodule Cache.RedisJSONTest do
assert :ok = RedisCache.json_set(key, [:some_map, :one], 4)
assert {:ok, 4} = RedisCache.json_get(key, [:some_map, :one])
end

test "returns error tuple if key does not exist" do
assert {:error,
%ErrorMessage{
message: "ERR new objects must be created at the root",
code: :bad_request,
details: nil
}} === RedisCache.json_set("non_existing", [:some_map, :one], 4)
end

test "returns :ok and nil if key exists but not the path", %{key: key} do
assert {:ok, nil} = RedisCache.json_set(key, [:some_other_map, :two], 4)

assert {:ok,
%{
"some_integer" => 1234,
"some_array" => [1, 2, 3, 4],
"some_empty_array" => [],
"some_map" => %{"one" => 1, "two" => 2, "three" => 3, "four" => 4}
}} === RedisCache.json_get(key)
end

test "ignores'.' as path", %{key: key} do
assert :ok = RedisCache.json_set(key, ["."], "some value")
assert {:ok, "some value"} === RedisCache.json_get(key)
assert {:ok, "some value"} === RedisCache.json_get(key, ["."])
end
end

describe "&json_delete/2" do
Expand Down
12 changes: 12 additions & 0 deletions test/cache_sandbox_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ defmodule CacheSandboxTest do

@cache_key "SomeKey"
@cache_value 1234
@cache_path "a.b"

setup do
Cache.SandboxRegistry.start(TestCache)
Expand All @@ -27,5 +28,16 @@ defmodule CacheSandboxTest do
test "works to seperate caches between tests" do
assert {:ok, nil} = TestCache.get(@cache_key)
end

test "works with json commands" do
assert {:error,
%ErrorMessage{
message: "ERR Path '$.c.d' does not exist",
code: :not_found,
details: nil
}} === TestCache.json_get(@cache_key, "c.d")
assert :ok = TestCache.json_set(@cache_key, @cache_path, @cache_value)
assert {:ok, @cache_value} = TestCache.json_get(@cache_key, @cache_path)
end
end
end

0 comments on commit 748da66

Please sign in to comment.