# `Cache.Sandbox`
[🔗](https://github.com/mikaak/elixir_cache/blob/main/lib/cache/sandbox.ex#L1)

Sandbox adapter for isolated testing of applications using ElixirCache.

This module provides a mock implementation of all cache adapters, allowing tests to run in isolation
without interfering with each other's data. The sandbox uses a basic `Agent` to store data in memory
and implements the full range of caching operations supported by all adapters.

## Features

* Isolated cache namespaces for concurrent testing
* Support for all standard cache operations
* Implementation of Redis-specific features like hash and JSON operations
* Implementation of ETS-specific operations for complete testing compatibility
* Lightweight in-memory storage for fast test execution

## Usage

The Sandbox adapter is typically enabled through the `sandbox?` option when defining a cache module:

```elixir
defmodule MyApp.TestCache do
  use Cache,
    adapter: Cache.Redis,  # Original adapter doesn't matter when sandbox is enabled
    name: :test_cache,
    opts: [],
    sandbox?: Mix.env() == :test
end
```

In your tests, use `Cache.SandboxRegistry.start(MyApp.TestCache)` in the setup block to ensure
proper isolation between test cases.

> **Note**: This adapter should not be used in production environments.

## Isolation

Each Agent process keeps state shaped as `%{sandbox_id => %{key => value}}`. The
`sandbox_id` is resolved per-caller via `Cache.SandboxRegistry` BEFORE entering
the Agent callback (so the caller's `self()`/`$callers`/`$ancestors` are used
for lookup, not the Agent's). When no sandbox is registered for the caller we
fall back to `:__unscoped__` — keeping the adapter usable outside of test.

# `all`

# `bchunk`

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `close`

# `command`

# `command!`

# `delete_all_objects`

# `delete_object`

# `delete_table`

# `dirty_get_or_store`

# `file2tab`

# `file2tab`

# `first`

# `first_lookup`

# `foldl`

# `foldr`

# `from_dets`

# `from_ets`

# `get_or_store`

# `give_away`

# `hash_delete`

# `hash_get`

# `hash_get_all`

# `hash_get_many`

# `hash_scan`

# `hash_set`

# `hash_set_many`

# `hash_values`

# `info`

# `info`

# `init_table`

# `insert_new`

# `insert_raw`

# `is_compatible_bchunk_format`

# `is_compiled_ms`

# `is_dets_file`

# `json_array_append`

# `json_clear`

# `json_delete`

# `json_get`

# `json_incr`

# `json_set`

# `last`

# `last_lookup`

# `lookup`

# `lookup_element`

# `lookup_element`

# `match_delete`

# `match_object`

# `match_object`

# `match_pattern`

# `match_pattern`

# `match_spec_compile`

# `match_spec_run`

# `member`

# `native_term_storage?`

The sandbox holds terms in an Agent map. It is never consulted directly to decide
whether to encode — `Cache` resolves that against the adapter the sandbox stands in
for, so a sandboxed cache round-trips values exactly like the real one.

# `next`

# `next_lookup`

# `open_file`

# `open_file`

# `pid2name`

# `pipeline`

# `pipeline!`

# `prev`

# `prev_lookup`

# `rename`

# `repair_continuation`

# `sadd`

# `safe_fixtable`

# `scan`

# `select`

# `select`

# `select_count`

# `select_delete`

# `select_replace`

# `select_reverse`

# `select_reverse`

# `setopts`

# `slot`

# `smembers`

# `sync`

# `tab2file`

# `tab2file`

# `tab2list`

# `tabfile_info`

# `table`

# `table`

# `take`

# `test_ms`

# `to_dets`

# `to_ets`

# `to_ets`

# `traverse`

# `update_counter`

# `update_counter`

# `update_element`

# `update_element`

# `whereis`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
