Skip to content

Commit

Permalink
Update how we set up mocking
Browse files Browse the repository at this point in the history
Remove `:impl` option from calls. Instead configure the module to use
- implementation or mock - in the application environment.
  • Loading branch information
pmeinhardt committed Dec 22, 2020
1 parent 01beb8f commit b682d33
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 206 deletions.
7 changes: 7 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use Mix.Config

if Mix.env() == :test do
config :sshkit, :ssh, MockErlangSsh
config :sshkit, :ssh_connection, MockErlangSshConnection
config :sshkit, :ssh_sftp, MockErlangSshSftp
end
28 changes: 15 additions & 13 deletions lib/sshkit/channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ defmodule SSHKit.Channel do
* `id` - the unique channel id
"""

defstruct [:connection, :type, :id, impl: :ssh_connection]
defstruct [:connection, :type, :id]

@type t() :: %__MODULE__{}

# credo:disable-for-next-line
@core Application.get_env(:sshkit, :ssh_connection, :ssh_connection)

@doc """
Opens a channel on an SSH connection.
Expand All @@ -31,15 +34,14 @@ defmodule SSHKit.Channel do
timeout = Keyword.get(options, :timeout, :infinity)
ini_window_size = Keyword.get(options, :initial_window_size, 128 * 1024)
max_packet_size = Keyword.get(options, :max_packet_size, 32 * 1024)
impl = Keyword.get(options, :impl, :ssh_connection)

with {:ok, id} <- impl.session_channel(conn.ref, ini_window_size, max_packet_size, timeout) do
{:ok, new(conn, id, impl)}
with {:ok, id} <- @core.session_channel(conn.ref, ini_window_size, max_packet_size, timeout) do
{:ok, new(conn, id)}
end
end

defp new(conn, id, impl) do
%__MODULE__{connection: conn, type: :session, id: id, impl: impl}
defp new(conn, id) do
%__MODULE__{connection: conn, type: :session, id: id}
end

@doc """
Expand All @@ -53,7 +55,7 @@ defmodule SSHKit.Channel do
:success | :failure | {:error, reason :: String.t()}
def subsystem(channel, subsystem, options \\ []) do
timeout = Keyword.get(options, :timeout, :infinity)
channel.impl.subsystem(channel.connection.ref, channel.id, to_charlist(subsystem), timeout)
@core.subsystem(channel.connection.ref, channel.id, to_charlist(subsystem), timeout)
end

@doc """
Expand All @@ -64,7 +66,7 @@ defmodule SSHKit.Channel do
For more details, see [`:ssh_connection.close/2`](http://erlang.org/doc/man/ssh_connection.html#close-2).
"""
def close(channel) do
channel.impl.close(channel.connection.ref, channel.id)
@core.close(channel.connection.ref, channel.id)
end

@doc """
Expand All @@ -86,7 +88,7 @@ defmodule SSHKit.Channel do
end

def exec(channel, command, timeout) do
channel.impl.exec(channel.connection.ref, channel.id, command, timeout)
@core.exec(channel.connection.ref, channel.id, command, timeout)
end

@doc """
Expand All @@ -97,7 +99,7 @@ defmodule SSHKit.Channel do
For more details, see [`:ssh_connection.ptty_alloc/4`](http://erlang.org/doc/man/ssh_connection.html#ptty_alloc-4).
"""
def ptty(channel, options \\ [], timeout \\ :infinity) do
channel.impl.ptty_alloc(channel.connection.ref, channel.id, options, timeout)
@core.ptty_alloc(channel.connection.ref, channel.id, options, timeout)
end

@doc """
Expand All @@ -112,7 +114,7 @@ defmodule SSHKit.Channel do
def send(channel, type \\ 0, data, timeout \\ :infinity)

def send(channel, type, data, timeout) when is_binary(data) or is_list(data) do
channel.impl.send(channel.connection.ref, channel.id, type, data, timeout)
@core.send(channel.connection.ref, channel.id, type, data, timeout)
end

def send(channel, type, data, timeout) do
Expand All @@ -130,7 +132,7 @@ defmodule SSHKit.Channel do
For more details, see [`:ssh_connection.send_eof/2`](http://erlang.org/doc/man/ssh_connection.html#send_eof-2).
"""
def eof(channel) do
channel.impl.send_eof(channel.connection.ref, channel.id)
@core.send_eof(channel.connection.ref, channel.id)
end

@doc """
Expand Down Expand Up @@ -190,6 +192,6 @@ defmodule SSHKit.Channel do
For more details, see [`:ssh_connection.adjust_window/3`](http://erlang.org/doc/man/ssh_connection.html#adjust_window-3).
"""
def adjust(channel, size) when is_integer(size) do
channel.impl.adjust_window(channel.connection.ref, channel.id, size)
@core.adjust_window(channel.connection.ref, channel.id, size)
end
end
31 changes: 16 additions & 15 deletions lib/sshkit/connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ defmodule SSHKit.Connection do
alias SSHKit.Utils

# TODO: Add :tag allowing arbitrary data to be attached?
defstruct [:host, :port, :options, :ref, impl: :ssh]
defstruct [:host, :port, :options, :ref]

@type t() :: %__MODULE__{}

@default_impl_options [user_interaction: false]
@default_connect_options [port: 22, timeout: :infinity, impl: :ssh]
# credo:disable-for-next-line
@core Application.get_env(:sshkit, :ssh, :ssh)

@default_ssh_options [user_interaction: false]
@default_connect_options [port: 22, timeout: :infinity]

@doc """
Opens a connection to an SSH server.
Expand Down Expand Up @@ -52,32 +55,31 @@ defmodule SSHKit.Connection do

port = details[:port]
timeout = details[:timeout]
impl = details[:impl]

case impl.connect(host, port, opts, timeout) do
{:ok, ref} -> {:ok, new(host, port, opts, ref, impl)}
case @core.connect(host, port, opts, timeout) do
{:ok, ref} -> {:ok, new(host, port, opts, ref)}
err -> err
end
end

defp extract(options) do
connect_option_keys = Keyword.keys(@default_connect_options)
{connect_options, impl_options} = Keyword.split(options, connect_option_keys)
{connect_options, ssh_options} = Keyword.split(options, connect_option_keys)

connect_options =
@default_connect_options
|> Keyword.merge(connect_options)

impl_options =
@default_impl_options
|> Keyword.merge(impl_options)
ssh_options =
@default_ssh_options
|> Keyword.merge(ssh_options)
|> Utils.charlistify()

{connect_options, impl_options}
{connect_options, ssh_options}
end

defp new(host, port, options, ref, impl) do
%__MODULE__{host: host, port: port, options: options, ref: ref, impl: impl}
defp new(host, port, options, ref) do
%__MODULE__{host: host, port: port, options: options, ref: ref}
end

@doc """
Expand All @@ -88,7 +90,7 @@ defmodule SSHKit.Connection do
For details, see [`:ssh.close/1`](http://erlang.org/doc/man/ssh.html#close-1).
"""
def close(conn) do
conn.impl.close(conn.ref)
@core.close(conn.ref)
end

@doc """
Expand All @@ -105,7 +107,6 @@ defmodule SSHKit.Connection do
options =
conn.options
|> Keyword.put(:port, conn.port)
|> Keyword.put(:impl, conn.impl)
|> Keyword.merge(options)

open(conn.host, options)
Expand Down
2 changes: 1 addition & 1 deletion lib/sshkit/context.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ defmodule SSHKit.Context do

import SSHKit.Utils

defstruct env: nil, path: nil, umask: nil, user: nil, group: nil
defstruct [:env, :path, :umask, :user, :group]

@type t() :: %__MODULE__{}

Expand Down
25 changes: 13 additions & 12 deletions lib/sshkit/sftp/channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,48 @@ defmodule SSHKit.SFTP.Channel do

alias SSHKit.Connection

defstruct [:connection, :id, impl: :ssh_sftp]
defstruct [:connection, :id]

@type t() :: %__MODULE__{}
@type handle() :: term()

# credo:disable-for-next-line
@core Application.get_env(:sshkit, :ssh_sftp, :ssh_sftp)

@spec start(Connection.t(), keyword()) :: {:ok, t()} | {:error, term()}
def start(conn, options \\ []) do
{impl, options} = Keyword.pop(options, :impl, :ssh_sftp)

with {:ok, id} <- impl.start_channel(conn.ref, options) do
{:ok, new(conn, id, impl)}
with {:ok, id} <- @core.start_channel(conn.ref, options) do
{:ok, new(conn, id)}
end
end

defp new(conn, id, impl) do
%__MODULE__{connection: conn, id: id, impl: impl}
defp new(conn, id) do
%__MODULE__{connection: conn, id: id}
end

@spec stop(t()) :: :ok
def stop(chan) do
chan.impl.stop_channel(chan.id)
@core.stop_channel(chan.id)
end

@spec mkdir(t(), binary(), timeout()) :: :ok | {:error, term()}
def mkdir(chan, name, timeout \\ :infinity) do
chan.impl.make_dir(chan.id, name, timeout)
@core.make_dir(chan.id, name, timeout)
end

@spec open(t(), binary(), [:read | :write | :append | :binary | :raw], timeout()) ::
{:ok, handle()} | {:error, term()}
def open(chan, name, mode, timeout \\ :infinity) do
chan.impl.open(chan.id, name, mode, timeout)
@core.open(chan.id, name, mode, timeout)
end

@spec close(t(), handle(), timeout()) :: :ok | {:error, term()}
def close(chan, handle, timeout \\ :infinity) do
chan.impl.close(chan.id, handle, timeout)
@core.close(chan.id, handle, timeout)
end

@spec write(t(), handle(), iodata(), timeout()) :: :ok | {:error, term()}
def write(chan, handle, data, timeout \\ :infinity) do
chan.impl.write(chan.id, handle, data, timeout)
@core.write(chan.id, handle, data, timeout)
end
end
Loading

0 comments on commit b682d33

Please sign in to comment.