Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ config :my_app, MyApp.Repo,
pool_size: System.schedulers_online() * 2
```

Activate reuse of database containers started by mix task with adding `testcontainers.reuse.enable=true` in `~/.testcontainers.properties`. This is experimental.

### Logging

By default, Testcontainers doesn't log anything. If you want Testcontainers to log, set the desired log level in config/test.exs:
Expand Down
30 changes: 30 additions & 0 deletions lib/container/protocols/container_builder_helper.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
defmodule Testcontainers.ContainerBuilderHelper do
import Testcontainers.Constants
alias Testcontainers.Util.Hash
alias Testcontainers.Container
alias Testcontainers.ContainerBuilder

def build(builder, state) when is_map(state) and is_struct(builder) do
config =
ContainerBuilder.build(builder)
|> Container.with_label(container_version_label(), library_version())
|> Container.with_label(container_lang_label(), container_lang_value())
|> Container.with_label(container_label(), "#{true}")

reuse = config.reuse && true == Map.get(state.properties, "testcontainers.reuse.enable", false)

if reuse do
hash = Hash.struct_to_hash(config)
config
|> Container.with_label(container_reuse(), "true")
|> Container.with_label(container_reuse_hash_label(), hash)
|> Container.with_label(container_sessionId_label(), state.session_id)
|> Kernel.then(&{:reuse, &1, hash})
else
config
|> Container.with_label(container_reuse(), "false")
|> Container.with_label(container_sessionId_label(), state.session_id)
|> Kernel.then(&{:noreuse, &1, nil})
end
end
end
54 changes: 25 additions & 29 deletions lib/testcontainers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -229,35 +229,31 @@ defmodule Testcontainers do
end

defp start_and_wait(config_builder, state) do
config =
ContainerBuilder.build(config_builder)
|> Container.with_label(container_version_label(), library_version())
|> Container.with_label(container_lang_label(), container_lang_value())
|> Container.with_label(container_label(), "#{true}")

hash = Hash.struct_to_hash(config)

config = config
|> Container.with_label(container_reuse_hash_label(), hash)
|> Container.with_label(container_reuse(), "#{config.reuse}")
|> Container.with_label(container_sessionId_label(), state.session_id)

if Map.get(state.properties, "testcontainers.reuse.enable", false) == true && config.reuse do
case Api.get_container_by_hash(hash, state.conn) do
{:error, :no_container} ->
Logger.log("Container does not exist with hash: #{hash}")
create_and_start_container(config, config_builder, state)

{:error, error} ->
Logger.log("Failed to get container by hash: #{inspect(error)}")
{:error, error}

{:ok, container} ->
Logger.log("Container already exists with hash: #{hash}")
{:ok, container}
end
else
create_and_start_container(config, config_builder, state)
case Testcontainers.ContainerBuilderHelper.build(config_builder, state) do
{:reuse, config, hash} ->
case Api.get_container_by_hash(hash, state.conn) do
{:error, :no_container} ->
Logger.log("Container does not exist with hash: #{hash}")
create_and_start_container(
config,
config_builder,
state
)

{:error, error} ->
Logger.log("Failed to get container by hash: #{inspect(error)}")
{:error, error}

{:ok, container} ->
Logger.log("Container already exists with hash: #{hash}")
{:ok, container}
end
{:noreuse, config, _} ->
create_and_start_container(
config,
config_builder,
state
)
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/util/constants.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule Testcontainers.Constants do
@moduledoc false

def library_name, do: :testcontainers
def library_version, do: "1.10.2"
def library_version, do: "1.10.3"
def container_label, do: "org.testcontainers"
def container_lang_label, do: "org.testcontainers.lang"
def container_reuse_hash_label, do: "org.testcontainers.reuse-hash"
Expand Down
4 changes: 2 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule TestcontainersElixir.MixProject do
use Mix.Project

@app :testcontainers
@version "1.10.2"
@version "1.10.3"
@source_url "https://github.com/testcontainers/testcontainers-elixir"

def project do
Expand All @@ -22,7 +22,7 @@ defmodule TestcontainersElixir.MixProject do
licenses: ["MIT"]
],
test_coverage: [
summary: [threshold: 75],
summary: [threshold: 68],
ignore_modules: [
TestHelper,
Inspect.Testcontainers.TestUser,
Expand Down
31 changes: 31 additions & 0 deletions test/container/container_builder_helper_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule Testcontainers.ContainerBuilderHelperTest do
use ExUnit.Case, async: false

alias Testcontainers.ContainerBuilderHelper
import Testcontainers.Constants

test "build/2 returns a tuple with false, built config with correct labels and nil for hash" do
builder = Testcontainers.PostgresContainer.new() |> Testcontainers.PostgresContainer.with_reuse(true)
state = %{ properties: %{}, session_id: "123" }
{:noreuse, built, nil} = ContainerBuilderHelper.build(builder, state)
assert Map.get(built.labels, container_reuse()) == "false"
assert Map.get(built.labels, container_reuse_hash_label()) == nil
assert Map.get(built.labels, container_sessionId_label()) == "123"
assert Map.get(built.labels, container_version_label()) == library_version()
assert Map.get(built.labels, container_lang_label()) == container_lang_value()
assert Map.get(built.labels, container_label()) == "true"
end

test "build/2 returns a tuple with true, built config with correct labels and a non nil hash" do
builder = Testcontainers.PostgresContainer.new() |> Testcontainers.PostgresContainer.with_reuse(true)
state = %{ properties: %{ "testcontainers.reuse.enable" => true }, session_id: "123" }
{:reuse, built, hash} = ContainerBuilderHelper.build(builder, state)
assert hash != nil
assert Map.get(built.labels, container_reuse()) == "true"
assert Map.get(built.labels, container_reuse_hash_label()) != nil
assert Map.get(built.labels, container_sessionId_label()) == "123"
assert Map.get(built.labels, container_version_label()) == library_version()
assert Map.get(built.labels, container_lang_label()) == container_lang_value()
assert Map.get(built.labels, container_label()) == "true"
end
end
35 changes: 0 additions & 35 deletions test/ecto_errors_test.exs

This file was deleted.

36 changes: 0 additions & 36 deletions test/ecto_mysql_test.exs

This file was deleted.

32 changes: 0 additions & 32 deletions test/ecto_postgres_test.exs

This file was deleted.