Skip to content

Commit ac06d72

Browse files
committed
Add first integration test using containers
1 parent abc59d2 commit ac06d72

File tree

7 files changed

+231
-4
lines changed

7 files changed

+231
-4
lines changed

.github/workflows/integration.yml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
name: CI Checks
2+
3+
on:
4+
pull_request: []
5+
6+
jobs:
7+
dependencies:
8+
name: check | setup dependencies
9+
runs-on: ubuntu-20.04
10+
env:
11+
MIX_ENV: dev
12+
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
13+
strategy:
14+
matrix:
15+
elixir: ['1.12.3']
16+
otp: ['24.3.4']
17+
18+
steps:
19+
- name: Cancel previous runs
20+
uses: styfle/[email protected]
21+
with:
22+
access_token: ${{ github.token }}
23+
24+
- name: Checkout Github repo
25+
uses: actions/checkout@v2
26+
27+
- name: Setup elixir & erlang environment
28+
uses: erlef/setup-beam@v1
29+
with:
30+
elixir-version: ${{matrix.elixir}} # Define the elixir version [required]
31+
otp-version: ${{matrix.otp}} # Define the OTP version [required]
32+
experimental-otp: true # More info https://github.com/actions/setup-elixir/issues/31
33+
34+
- name: Retrieve Cached Dependencies
35+
uses: actions/cache@v2
36+
id: mix-cache
37+
with:
38+
path: |
39+
deps
40+
_build
41+
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('mix.lock') }}
42+
43+
- name: Install Dependencies
44+
if: steps.mix-cache.outputs.cache-hit != 'true'
45+
run: |
46+
mkdir -p priv/plts
47+
mix local.rebar --force
48+
mix local.hex --force
49+
mix deps.get
50+
mix deps.compile
51+
52+
integration_test:
53+
name: Integration Test
54+
runs-on: ubuntu-20.04
55+
needs: [dependencies]
56+
env:
57+
MIX_ENV: dev
58+
59+
strategy:
60+
fail-fast: false
61+
matrix:
62+
elixir: ['1.12.3']
63+
otp: ['24.3.4']
64+
65+
steps:
66+
- name: Cancel Previous Runs
67+
uses: styfle/[email protected]
68+
with:
69+
access_token: ${{ github.token }}
70+
71+
- name: Checkout
72+
uses: actions/checkout@v2
73+
with:
74+
fetch-depth: 0
75+
76+
- name: Setup elixir & erlang environment
77+
uses: erlef/setup-beam@v1
78+
with:
79+
elixir-version: ${{matrix.elixir}} # Define the elixir version [required]
80+
otp-version: ${{matrix.otp}} # Define the OTP version [required]
81+
experimental-otp: true # More info https://github.com/actions/setup-elixir/issues/31
82+
83+
- name: Retrieve Cached Dependencies
84+
uses: actions/cache@v2
85+
id: mix-cache
86+
with:
87+
path: |
88+
deps
89+
_build
90+
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-${{ hashFiles('mix.lock') }}
91+
92+
- name: Run Test
93+
run: mix test.integration

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,4 @@ jobs:
107107
key: ${{ runner.os }}-${{ matrix.pair.otp }}-${{ matrix.pair.elixir }}-mix-deps-compile-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}
108108

109109
- name: Run unit tests
110-
run: mix test
110+
run: mix test.all

config/test.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
config :testcontainers, enabled: true

mix.exs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ defmodule Kayrock.MixProject do
1010
elixir: "~> 1.1",
1111
elixirc_paths: elixirc_paths(Mix.env()),
1212
test_coverage: [tool: ExCoveralls],
13-
preferred_cli_env: [coveralls: :test],
13+
preferred_cli_env: [coveralls: :test, "test.integration": :test],
1414
start_permanent: Mix.env() == :prod,
1515
deps: deps(),
16+
aliases: aliases(),
1617
dialyzer: [
1718
plt_add_apps: [:mix],
1819
flags: [:error_handling, :race_conditions]
@@ -64,10 +65,16 @@ defmodule Kayrock.MixProject do
6465

6566
defp package do
6667
[
67-
maintainers: ["Dan Swain"],
68+
maintainers: ["Dan Swain", "Argonus"],
6869
files: ["lib", "config/config.exs", "mix.exs", "README.md"],
6970
licenses: ["MIT"],
7071
links: %{"GitHub" => @source_url}
7172
]
7273
end
74+
75+
defp aliases do
76+
[
77+
"test.integration": "test --only integration_v2"
78+
]
79+
end
7380
end
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
defmodule Kayrock.Integration.TopicManagementTest do
2+
use ExUnit.Case, async: true
3+
import Kayrock.TestSupport
4+
import Kayrock.Convenience
5+
import Testcontainers.ExUnit
6+
7+
alias Testcontainers.Container
8+
alias Testcontainers.KafkaContainer
9+
10+
container(:kafka, KafkaContainer.new(), shared: true)
11+
12+
@moduletag :integration_v2
13+
describe "topic management API" do
14+
for version <- [0, 1, 2] do
15+
test "v#{version} - allows to manage topic", %{kafka: kafka} do
16+
uris = [{"localhost", Container.mapped_port(kafka, 9092)}]
17+
api_version = unquote(version)
18+
{:ok, client_pid} = Kayrock.Client.start_link(uris)
19+
topic_name = unique_string()
20+
21+
# Get Topics
22+
refute topic_exists?(client_pid, topic_name)
23+
24+
# Creates Topic
25+
create_request = create_topic_request(topic_name, api_version)
26+
{:ok, _} = Kayrock.client_call(client_pid, create_request, :controller)
27+
28+
# Get Topic
29+
topic = get_topic_metadata(client_pid, topic_name)
30+
assert topic.topic == topic_name
31+
assert length(topic.partition_metadata) == 3
32+
33+
# Create Partitions
34+
create_partition_config = create_topic_partition(topic_name, api_version)
35+
{:ok, res} = Kayrock.client_call(client_pid, create_partition_config, :controller)
36+
assert List.first(res.topic_errors).error_code == 0
37+
38+
# Get Updated Topic
39+
topic = get_topic_metadata(client_pid, topic_name)
40+
assert length(topic.partition_metadata) == 5
41+
42+
# Update Topic Config
43+
alter_config = alter_topic_config(topic_name, api_version)
44+
{:ok, res} = Kayrock.client_call(client_pid, alter_config, :controller)
45+
assert List.first(res.resources).error_code == 0
46+
47+
# Get Topic Config
48+
describe_config = describe_config(topic_name, api_version)
49+
{:ok, res} = Kayrock.client_call(client_pid, describe_config, :controller)
50+
resource = List.first(res.resources)
51+
assert resource.error_code == 0
52+
config = List.first(resource.config_entries)
53+
assert config.config_name == "cleanup.policy"
54+
assert config.config_value == "compact"
55+
56+
# Deletes Topic
57+
max_version = min(Kayrock.DeleteTopics.max_vsn(), api_version)
58+
{:ok, _} = Kayrock.delete_topics(client_pid, [topic_name], 1000, max_version)
59+
60+
# Get Topic
61+
refute topic_exists?(client_pid, topic_name)
62+
end
63+
end
64+
end
65+
66+
# Helpers
67+
defp create_topic_request(topic_name, api_version) do
68+
api_version = min(Kayrock.CreateTopics.max_vsn(), api_version)
69+
request = Kayrock.CreateTopics.get_request_struct(api_version)
70+
71+
topic_config = %{
72+
topic: topic_name,
73+
num_partitions: 3,
74+
replication_factor: 1,
75+
replica_assignment: [],
76+
config_entries: []
77+
}
78+
79+
%{request | create_topic_requests: [topic_config], timeout: 1000}
80+
end
81+
82+
defp create_topic_partition(topic_name, api_version) do
83+
api_version = min(Kayrock.CreatePartitions.max_vsn(), api_version)
84+
request = Kayrock.CreatePartitions.get_request_struct(api_version)
85+
partition_config = %{topic: topic_name, new_partitions: %{count: 5, assignment: nil}}
86+
%{request | topic_partitions: [partition_config], timeout: 1000, validate_only: false}
87+
end
88+
89+
defp alter_topic_config(topic_name, api_version) do
90+
api_version = min(Kayrock.AlterConfigs.max_vsn(), api_version)
91+
request = Kayrock.AlterConfigs.get_request_struct(api_version)
92+
config = %{config_name: "cleanup.policy", config_value: "compact"}
93+
94+
%{
95+
request
96+
| resources: [%{resource_type: 2, resource_name: topic_name, config_entries: [config]}],
97+
validate_only: false
98+
}
99+
end
100+
101+
defp describe_config(topic_name, api_version) do
102+
api_version = min(Kayrock.DescribeConfigs.max_vsn(), api_version)
103+
request = Kayrock.DescribeConfigs.get_request_struct(api_version)
104+
105+
%{
106+
request
107+
| resources: [
108+
%{resource_type: 2, resource_name: topic_name, config_names: ["cleanup.policy"]}
109+
]
110+
}
111+
end
112+
113+
def get_topic_metadata(pid, topic) when is_pid(pid) and is_binary(topic) do
114+
{:ok, [topic]} = Kayrock.topics_metadata(pid, [topic])
115+
topic
116+
end
117+
end

test/support/test_support.ex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
defmodule Kayrock.TestSupport do
22
@moduledoc "Support code for tests"
3+
4+
@doc """
5+
Returns a unique string for use in tests.
6+
"""
7+
def unique_string do
8+
"test-topic-#{:erlang.unique_integer([:positive])}"
9+
end
10+
311
def compare_binaries(lhs, rhs) do
412
bytes_per_chunk = 16
513
chunks_lhs = chunk_binary(lhs, bytes_per_chunk)

test/test_helper.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
ExUnit.configure(exclude: :integration)
1+
ExUnit.configure(exclude: [:integration, :integration_v2])
2+
Testcontainers.start_link()
23
ExUnit.start()

0 commit comments

Comments
 (0)