Skip to content

Commit a2df4d8

Browse files
authored
Measure :ets tables (#125)
* 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
1 parent 99e6942 commit a2df4d8

File tree

6 files changed

+140
-20
lines changed

6 files changed

+140
-20
lines changed

.github/workflows/ci.yaml

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ jobs:
1313
timeout-minutes: 30
1414
name: Internal Typespecs
1515
env:
16-
OTP: "25.3"
17-
ELIXIR: "1.13"
16+
OTP: "26.2"
17+
ELIXIR: "1.14"
1818
steps:
1919
- uses: actions/checkout@v2
2020
- uses: erlef/setup-beam@v1
@@ -50,8 +50,8 @@ jobs:
5050
runs-on: ubuntu-20.04
5151
name: Code Style
5252
env:
53-
OTP: "25.3"
54-
ELIXIR: "1.13"
53+
OTP: "26.2"
54+
ELIXIR: "1.14"
5555
steps:
5656
- uses: actions/checkout@v2
5757
- uses: erlef/setup-beam@v1
@@ -78,8 +78,8 @@ jobs:
7878
runs-on: ubuntu-20.04
7979
name: Code Formatting
8080
env:
81-
OTP: "25.3"
82-
ELIXIR: "1.13"
81+
OTP: "26.2"
82+
ELIXIR: "1.14"
8383
steps:
8484
- uses: actions/checkout@v2
8585
- uses: erlef/setup-beam@v1
@@ -107,8 +107,8 @@ jobs:
107107
timeout-minutes: 30
108108
name: External Typespecs
109109
env:
110-
OTP: "25.3"
111-
ELIXIR: "1.13"
110+
OTP: "26.2"
111+
ELIXIR: "1.14"
112112
steps:
113113
- uses: actions/checkout@v2
114114
- uses: erlef/setup-beam@v1
@@ -151,11 +151,9 @@ jobs:
151151
# NOTE: We are going to support 4 version from the official list of 5
152152
# https://hexdocs.pm/elixir/compatibility-and-deprecations.html
153153
matrix:
154-
otp: ["25.3"]
155-
elixir: ["1.13.4"]
154+
otp: ["26.2"]
155+
elixir: ["1.14.5"]
156156
include:
157-
- otp: "26.2"
158-
elixir: "1.14.5"
159157
- otp: "26.2"
160158
elixir: "1.15.8"
161159
- otp: "26.2"

config/config.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ config :avrora,
99
convert_null_values: true,
1010
names_cache_ttl: :infinity
1111

12-
config :logger, :console, format: "$time $metadata[$level] $levelpad$message\n"
12+
config :logger, :console, format: "$time $metadata[$level] $message\n"

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ defmodule Avrora.MixProject do
77
[
88
app: :avrora,
99
version: @version,
10-
elixir: "~> 1.12",
10+
elixir: "~> 1.14",
1111
description: description(),
1212
package: package(),
1313
docs: docs(),

test/avrora/storage/file_test.exs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ defmodule Avrora.Storage.FileTest do
22
use ExUnit.Case, async: true
33
doctest Avrora.Storage.File
44

5+
import Mox
56
import Support.Config
67
import ExUnit.CaptureLog
78
alias Avrora.Storage.File
@@ -45,6 +46,16 @@ defmodule Avrora.Storage.FileTest do
4546
assert output =~ "schema file with version is not allowed"
4647
end
4748

49+
test "when references reuse same ets table" do
50+
_ = start_link_supervised!(Support.AvroSchemaStore)
51+
stub(Avrora.ConfigMock, :ets_lib, fn -> Support.AvroSchemaStore end)
52+
53+
existing_ets_tables = Support.AvroSchemaStore.count()
54+
{:ok, _} = File.get("io.acme.PaymentHistory")
55+
56+
assert Support.AvroSchemaStore.count() - existing_ets_tables == 1
57+
end
58+
4859
test "when schema file contains invalid json" do
4960
assert File.get("io.acme.Wrong") == {:error, "argument error"}
5061
end

test/avrora/storage/registry_test.exs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
defmodule Avrora.Storage.RegistryTest do
2-
# NOTE: Remove when Elixir 1.6 support ends
3-
use ExUnit.Case
4-
# use ExUnit.Case, async: true
2+
use ExUnit.Case, async: true
53
doctest Avrora.Storage.Registry
64

75
import Mox
86
import Support.Config
97
import ExUnit.CaptureLog
108
alias Avrora.Storage.Registry
119

12-
# NOTE: Remove when Elixir 1.6 support ends
13-
setup :set_mox_from_context
14-
1510
setup :verify_on_exit!
1611
setup :support_config
1712

@@ -283,6 +278,51 @@ defmodule Avrora.Storage.RegistryTest do
283278

284279
assert Registry.get("anything") == {:error, :unconfigured_registry_url}
285280
end
281+
282+
@tag skip: "This test will fail because Registry creates new table on each reference"
283+
test "when references reuse same ets table" do
284+
_ = start_link_supervised!(Support.AvroSchemaStore)
285+
stub(Avrora.ConfigMock, :ets_lib, fn -> Support.AvroSchemaStore end)
286+
287+
existing_ets_tables = Support.AvroSchemaStore.count()
288+
289+
Avrora.HTTPClientMock
290+
|> expect(:get, fn url, _ ->
291+
assert url == "http://reg.loc/schemas/ids/43"
292+
293+
{
294+
:ok,
295+
%{
296+
"subject" => "io.acme.Account",
297+
"id" => 43,
298+
"version" => 1,
299+
"schema" => json_schema_with_reference(),
300+
"references" => [
301+
%{"name" => "io.acme.User", "subject" => "io.acme.User", "version" => 1}
302+
]
303+
}
304+
}
305+
end)
306+
307+
Avrora.HTTPClientMock
308+
|> expect(:get, fn url, _ ->
309+
assert url == "http://reg.loc/subjects/io.acme.User/versions/1"
310+
311+
{
312+
:ok,
313+
%{
314+
"subject" => "io.acme.User",
315+
"id" => 44,
316+
"version" => 1,
317+
"schema" => json_schema_referenced()
318+
}
319+
}
320+
end)
321+
322+
{:ok, _} = Registry.get(43)
323+
324+
assert Support.AvroSchemaStore.count() - existing_ets_tables == 1
325+
end
286326
end
287327

288328
describe "put/2" do

test/support/avro_schema_store.ex

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
defmodule Support.AvroSchemaStore do
2+
@moduledoc """
3+
A host process and a wrapper for :avro_schema_store produced tables.
4+
Used only in tests
5+
6+
See more: `Avrora.AvroSchemaStore`
7+
8+
## Examples:
9+
10+
test "when we need test schema store creation" do
11+
{:ok, _} = start_link_supervised!(Support.AvroSchemaStore)
12+
stub(Avrora.ConfigMock, :ets_lib, fn -> Support.AvroSchemaStore end)
13+
14+
assert Support.AvroSchemaStore.count() == 0
15+
16+
Support.AvroSchemaStore.new()
17+
assert Support.AvroSchemaStore.count() == 1
18+
end
19+
"""
20+
21+
@prefix "avrora__test"
22+
23+
use GenServer
24+
25+
def start_link(opts \\ []) do
26+
{name_opts, _} = Keyword.split(opts, [:name])
27+
opts = Keyword.merge([name: __MODULE__], name_opts)
28+
29+
GenServer.start_link(__MODULE__, [], opts)
30+
end
31+
32+
@impl true
33+
def init(_state \\ []), do: {:ok, []}
34+
35+
@impl true
36+
def handle_call({:new}, _from, state),
37+
do: {:reply, :avro_schema_store.new(name: String.to_atom("#{@prefix}-#{rand()}")), state}
38+
39+
def handle_call({:count}, _from, state),
40+
do: {:reply, Enum.count(:ets.all(), &is_test_store/1), state}
41+
42+
@doc """
43+
Creates a new Erlang Term Store.
44+
45+
## Examples:
46+
47+
iex> {:ok, _} = Support.AvroSchemaStore.start_link()
48+
iex> Support.AvroSchemaStore.new() |> :ets.info() |> Keyword.get(:size)
49+
0
50+
"""
51+
@spec new() :: reference()
52+
def new, do: GenServer.call(__MODULE__, {:new})
53+
54+
@doc """
55+
Returns a number of `:ets` tables matching the test prefix.
56+
57+
## Examples:
58+
59+
iex> {:ok, _} = Support.AvroSchemaStore.start_link()
60+
iex> Support.AvroSchemaStore.count()
61+
0
62+
iex> Support.AvroSchemaStore.new()
63+
iex> Support.AvroSchemaStore.count()
64+
1
65+
"""
66+
@spec count() :: non_neg_integer()
67+
def count, do: GenServer.call(__MODULE__, {:count})
68+
69+
defp rand, do: :rand.uniform(1_000_000) + System.os_time()
70+
defp is_test_store(id), do: !is_reference(id) && Atom.to_string(id) =~ @prefix
71+
end

0 commit comments

Comments
 (0)