Skip to content

Commit

Permalink
Measure :ets tables (#125)
Browse files Browse the repository at this point in the history
* Add tests for File and Registry storage
* Add test wrapper for :avro_schma_store
* Update CI setup and remove extra version check
* Bump elixir version of project to 1.14
* Improve test support documentation
  • Loading branch information
Strech authored Aug 8, 2024
1 parent 99e6942 commit a2df4d8
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 20 deletions.
22 changes: 10 additions & 12 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ jobs:
timeout-minutes: 30
name: Internal Typespecs
env:
OTP: "25.3"
ELIXIR: "1.13"
OTP: "26.2"
ELIXIR: "1.14"
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
Expand Down Expand Up @@ -50,8 +50,8 @@ jobs:
runs-on: ubuntu-20.04
name: Code Style
env:
OTP: "25.3"
ELIXIR: "1.13"
OTP: "26.2"
ELIXIR: "1.14"
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
Expand All @@ -78,8 +78,8 @@ jobs:
runs-on: ubuntu-20.04
name: Code Formatting
env:
OTP: "25.3"
ELIXIR: "1.13"
OTP: "26.2"
ELIXIR: "1.14"
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
Expand Down Expand Up @@ -107,8 +107,8 @@ jobs:
timeout-minutes: 30
name: External Typespecs
env:
OTP: "25.3"
ELIXIR: "1.13"
OTP: "26.2"
ELIXIR: "1.14"
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
Expand Down Expand Up @@ -151,11 +151,9 @@ jobs:
# NOTE: We are going to support 4 version from the official list of 5
# https://hexdocs.pm/elixir/compatibility-and-deprecations.html
matrix:
otp: ["25.3"]
elixir: ["1.13.4"]
otp: ["26.2"]
elixir: ["1.14.5"]
include:
- otp: "26.2"
elixir: "1.14.5"
- otp: "26.2"
elixir: "1.15.8"
- otp: "26.2"
Expand Down
2 changes: 1 addition & 1 deletion config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ config :avrora,
convert_null_values: true,
names_cache_ttl: :infinity

config :logger, :console, format: "$time $metadata[$level] $levelpad$message\n"
config :logger, :console, format: "$time $metadata[$level] $message\n"
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ defmodule Avrora.MixProject do
[
app: :avrora,
version: @version,
elixir: "~> 1.12",
elixir: "~> 1.14",
description: description(),
package: package(),
docs: docs(),
Expand Down
11 changes: 11 additions & 0 deletions test/avrora/storage/file_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule Avrora.Storage.FileTest do
use ExUnit.Case, async: true
doctest Avrora.Storage.File

import Mox
import Support.Config
import ExUnit.CaptureLog
alias Avrora.Storage.File
Expand Down Expand Up @@ -45,6 +46,16 @@ defmodule Avrora.Storage.FileTest do
assert output =~ "schema file with version is not allowed"
end

test "when references reuse same ets table" do
_ = start_link_supervised!(Support.AvroSchemaStore)
stub(Avrora.ConfigMock, :ets_lib, fn -> Support.AvroSchemaStore end)

existing_ets_tables = Support.AvroSchemaStore.count()
{:ok, _} = File.get("io.acme.PaymentHistory")

assert Support.AvroSchemaStore.count() - existing_ets_tables == 1
end

test "when schema file contains invalid json" do
assert File.get("io.acme.Wrong") == {:error, "argument error"}
end
Expand Down
52 changes: 46 additions & 6 deletions test/avrora/storage/registry_test.exs
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
defmodule Avrora.Storage.RegistryTest do
# NOTE: Remove when Elixir 1.6 support ends
use ExUnit.Case
# use ExUnit.Case, async: true
use ExUnit.Case, async: true
doctest Avrora.Storage.Registry

import Mox
import Support.Config
import ExUnit.CaptureLog
alias Avrora.Storage.Registry

# NOTE: Remove when Elixir 1.6 support ends
setup :set_mox_from_context

setup :verify_on_exit!
setup :support_config

Expand Down Expand Up @@ -283,6 +278,51 @@ defmodule Avrora.Storage.RegistryTest do

assert Registry.get("anything") == {:error, :unconfigured_registry_url}
end

@tag skip: "This test will fail because Registry creates new table on each reference"
test "when references reuse same ets table" do
_ = start_link_supervised!(Support.AvroSchemaStore)
stub(Avrora.ConfigMock, :ets_lib, fn -> Support.AvroSchemaStore end)

existing_ets_tables = Support.AvroSchemaStore.count()

Avrora.HTTPClientMock
|> expect(:get, fn url, _ ->
assert url == "http://reg.loc/schemas/ids/43"

{
:ok,
%{
"subject" => "io.acme.Account",
"id" => 43,
"version" => 1,
"schema" => json_schema_with_reference(),
"references" => [
%{"name" => "io.acme.User", "subject" => "io.acme.User", "version" => 1}
]
}
}
end)

Avrora.HTTPClientMock
|> expect(:get, fn url, _ ->
assert url == "http://reg.loc/subjects/io.acme.User/versions/1"

{
:ok,
%{
"subject" => "io.acme.User",
"id" => 44,
"version" => 1,
"schema" => json_schema_referenced()
}
}
end)

{:ok, _} = Registry.get(43)

assert Support.AvroSchemaStore.count() - existing_ets_tables == 1
end
end

describe "put/2" do
Expand Down
71 changes: 71 additions & 0 deletions test/support/avro_schema_store.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
defmodule Support.AvroSchemaStore do
@moduledoc """
A host process and a wrapper for :avro_schema_store produced tables.
Used only in tests
See more: `Avrora.AvroSchemaStore`
## Examples:
test "when we need test schema store creation" do
{:ok, _} = start_link_supervised!(Support.AvroSchemaStore)
stub(Avrora.ConfigMock, :ets_lib, fn -> Support.AvroSchemaStore end)
assert Support.AvroSchemaStore.count() == 0
Support.AvroSchemaStore.new()
assert Support.AvroSchemaStore.count() == 1
end
"""

@prefix "avrora__test"

use GenServer

def start_link(opts \\ []) do
{name_opts, _} = Keyword.split(opts, [:name])
opts = Keyword.merge([name: __MODULE__], name_opts)

GenServer.start_link(__MODULE__, [], opts)
end

@impl true
def init(_state \\ []), do: {:ok, []}

@impl true
def handle_call({:new}, _from, state),
do: {:reply, :avro_schema_store.new(name: String.to_atom("#{@prefix}-#{rand()}")), state}

def handle_call({:count}, _from, state),
do: {:reply, Enum.count(:ets.all(), &is_test_store/1), state}

@doc """
Creates a new Erlang Term Store.
## Examples:
iex> {:ok, _} = Support.AvroSchemaStore.start_link()
iex> Support.AvroSchemaStore.new() |> :ets.info() |> Keyword.get(:size)
0
"""
@spec new() :: reference()
def new, do: GenServer.call(__MODULE__, {:new})

@doc """
Returns a number of `:ets` tables matching the test prefix.
## Examples:
iex> {:ok, _} = Support.AvroSchemaStore.start_link()
iex> Support.AvroSchemaStore.count()
0
iex> Support.AvroSchemaStore.new()
iex> Support.AvroSchemaStore.count()
1
"""
@spec count() :: non_neg_integer()
def count, do: GenServer.call(__MODULE__, {:count})

defp rand, do: :rand.uniform(1_000_000) + System.os_time()
defp is_test_store(id), do: !is_reference(id) && Atom.to_string(id) =~ @prefix
end

0 comments on commit a2df4d8

Please sign in to comment.