Packages
testcontainers
0.9.0
2.3.1
2.3.0
2.2.0
2.1.0
2.1.0-rc1
2.0.0
2.0.0-rc3
2.0.0-rc2
2.0.0-rc
1.14.1
1.14.0
1.13.5
1.13.4
1.13.3
1.13.2
1.13.1
1.13.0
1.12.0
1.11.8
1.11.7
1.11.6
1.11.5
1.11.4
1.11.3
1.11.2
1.11.1
1.11.0
1.10.5
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
1.9.0
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.7.0
1.6.0
1.5.1
1.5.0
1.4.2
1.4.1
1.4.0
1.3.1
1.3.0
1.2.11
1.2.10
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-beta.1
1.0.0-beta
0.9.3
0.9.2
0.9.1
0.9.0
Testcontainers is an Elixir library that supports ExUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.
Current section
Files
Jump to
Current section
Files
lib/wait_strategy/command_wait_strategy.ex
# SPDX-License-Identifier: MIT
# Original by: Marco Dallagiacoma @ 2023 in https://github.com/dallagi/excontainers
# Modified by: Jarl André Hübenthal @ 2023
defmodule Testcontainers.WaitStrategy.CommandWaitStrategy do
@moduledoc """
Considers container as ready as soon as a command runs successfully inside the container.
"""
defstruct [:command]
@doc """
Creates a new CommandWaitStrategy to wait until the given command executes successfully inside the container.
"""
def new(command), do: %__MODULE__{command: command}
end
defimpl Testcontainers.WaitStrategy,
for: Testcontainers.WaitStrategy.CommandWaitStrategy do
alias Testcontainers.Docker.Exec
def wait_until_container_is_ready(wait_strategy, id_or_name) do
case exec_and_wait(id_or_name, wait_strategy.command) do
{:ok, {0, _stdout}} ->
:ok
_ ->
:timer.sleep(100)
wait_until_container_is_ready(wait_strategy, id_or_name)
end
end
def exec_and_wait(container_id, command, options \\ []) do
timeout_ms = options[:timeout_ms]
{:ok, exec_id} = exec(container_id, command)
case wait_for_exec_result(exec_id, timeout_ms) do
{:ok, exec_info} -> {:ok, {exec_info.exit_code, ""}}
{:error, :timeout} -> {:error, :timeout}
end
end
def exec(container_id, command) do
{:ok, exec_id} = Exec.create(container_id, command)
:ok = Exec.start(exec_id)
{:ok, exec_id}
end
defp wait_for_exec_result(exec_id, timeout_ms, started_at \\ monotonic_time()) do
case Exec.inspect(exec_id) do
{:ok, %{running: true}} -> do_wait_unless_timed_out(exec_id, timeout_ms, started_at)
{:ok, finished_exec_status} -> {:ok, finished_exec_status}
end
end
defp do_wait_unless_timed_out(exec_id, timeout_ms, started_at) do
if out_of_time(started_at, timeout_ms) do
{:error, :timeout}
else
:timer.sleep(100)
wait_for_exec_result(exec_id, timeout_ms, started_at)
end
end
defp monotonic_time, do: System.monotonic_time(:millisecond)
defp out_of_time(started_at, timeout_ms), do: monotonic_time() - started_at > timeout_ms
end