From c7a2e1210b179ba37149776a03190170023b212f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Kn=C3=B6pfle?= Date: Wed, 11 Jan 2023 11:09:53 +0100 Subject: [PATCH 1/3] Update workflows --- .formatter.exs | 4 + .github/workflows/ci.yml | 43 +++---- config/config.exs | 31 +---- lib/sshkit.ex | 16 ++- lib/sshkit/context.ex | 15 ++- lib/sshkit/scp/download.ex | 13 ++- lib/sshkit/scp/upload.ex | 50 +++++--- lib/sshkit/ssh.ex | 41 ++++--- lib/sshkit/ssh/channel.ex | 8 +- lib/sshkit/ssh/connection.ex | 7 +- lib/sshkit/utils.ex | 3 + mix.exs | 46 ++++---- mix.lock | 22 ++-- test/sshkit/context_test.exs | 3 +- test/sshkit/scp/command_test.exs | 3 +- test/sshkit/scp/upload_test.exs | 34 ++++-- test/sshkit/scp_functional_test.exs | 40 +++---- test/sshkit/ssh/channel_test.exs | 113 +++++++++++-------- test/sshkit/ssh/connection_test.exs | 106 +++++++++-------- test/sshkit/ssh_test.exs | 70 ++++++------ test/sshkit/utils_test.exs | 6 +- test/sshkit_functional_test.exs | 12 +- test/support/functional_assertion_helpers.ex | 42 ++++--- test/support/functional_case.ex | 2 +- test/support/functional_case_helpers.ex | 6 +- test/support/mocks.ex | 15 ++- test/test_helper.exs | 14 ++- 27 files changed, 431 insertions(+), 334 deletions(-) create mode 100644 .formatter.exs diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 00000000..d2cda26e --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9478f482..371a4e5a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,20 +14,14 @@ jobs: - name: Install OTP and Elixir uses: erlef/setup-beam@v1 with: - otp-version: "23.0" - elixir-version: "1.11.2" + otp-version: "25.0" + elixir-version: "1.14.2" - name: Install dependencies run: mix deps.get - # TODO: Enable in next release - # - # At the moment, we still have pending PRs etc. - # and introducing auto-formatting now would cause - # a ton of conflicts. - # - # - name: Check mix format - # run: mix format --check-formatted + - name: Check mix format + run: mix format --check-formatted - name: Compile with warnings as errors run: mix compile --warnings-as-errors @@ -41,8 +35,8 @@ jobs: - name: Install OTP and Elixir uses: erlef/setup-beam@v1 with: - otp-version: "23.0" - elixir-version: "1.11.2" + otp-version: "25.0" + elixir-version: "1.14.2" - name: Install dependencies run: mix deps.get @@ -57,27 +51,18 @@ jobs: fail-fast: false matrix: include: + - erlang: "24.2" + elixir: "1.12.3" + os: "ubuntu-22.04" + - erlang: "24.2" + elixir: "1.13.4" + os: "ubuntu-22.04" - erlang: "23.0" elixir: "1.11.2" - os: "ubuntu-latest" + os: "ubuntu-20.04" - erlang: "23.0" elixir: "1.10.3" - os: "ubuntu-latest" - - erlang: "22.3" - elixir: "1.9.4" - os: "ubuntu-latest" - - erlang: "21.3" - elixir: "1.8.2" - os: "ubuntu-latest" - - erlang: "20.3.1" - elixir: "1.7.4" - os: "ubuntu-latest" - - erlang: "19.3" - elixir: "1.6.6" - os: "ubuntu-18.04" - - erlang: "18.3" - elixir: "1.5.3" - os: "ubuntu-18.04" + os: "ubuntu-20.04" steps: - uses: actions/checkout@v1 diff --git a/config/config.exs b/config/config.exs index 2f3560ba..becde769 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,30 +1 @@ -# This file is responsible for configuring your application -# and its dependencies with the aid of the Mix.Config module. -use Mix.Config - -# This configuration is loaded before any dependency and is restricted -# to this project. If another project depends on this project, this -# file won't be loaded nor affect the parent project. For this reason, -# if you want to provide default values for your application for -# 3rd-party users, it should be done in your "mix.exs" file. - -# You can configure for your application as: -# -# config :sshkit, key: :value -# -# And access this configuration in your application as: -# -# Application.get_env(:sshkit, :key) -# -# Or configure a 3rd-party app: -# -# config :logger, level: :info -# - -# It is also possible to import configuration files, relative to this -# directory. For example, you can emulate configuration per environment -# by uncommenting the line below and defining dev.exs, test.exs and such. -# Configuration from the imported file will override the ones defined -# here (which is why it is important to import them last). -# -# import_config "#{Mix.env}.exs" +import Config diff --git a/lib/sshkit.ex b/lib/sshkit.ex index 568bb860..718a40e8 100644 --- a/lib/sshkit.ex +++ b/lib/sshkit.ex @@ -357,9 +357,11 @@ defmodule SSHKit do target = Keyword.get(options, :as, Path.basename(source)) run = fn host -> - {:ok, res} = SSH.connect host.name, host.options, fn conn -> - SCP.upload(conn, source, target, options) - end + {:ok, res} = + SSH.connect(host.name, host.options, fn conn -> + SCP.upload(conn, source, target, options) + end) + res end @@ -403,9 +405,11 @@ defmodule SSHKit do target = Keyword.get(options, :as, Path.basename(source)) run = fn host -> - {:ok, res} = SSH.connect host.name, host.options, fn conn -> - SCP.download(conn, source, target, options) - end + {:ok, res} = + SSH.connect(host.name, host.options, fn conn -> + SCP.download(conn, source, target, options) + end) + res end diff --git a/lib/sshkit/context.ex b/lib/sshkit/context.ex index 2c85fcd7..0a4b6ca2 100644 --- a/lib/sshkit/context.ex +++ b/lib/sshkit/context.ex @@ -15,7 +15,7 @@ defmodule SSHKit.Context do import SSHKit.Utils - defstruct [hosts: [], env: nil, path: nil, umask: nil, user: nil, group: nil] + defstruct hosts: [], env: nil, path: nil, umask: nil, user: nil, group: nil @doc """ Compiles an executable command string for running the given `command` @@ -38,12 +38,19 @@ defmodule SSHKit.Context do end defp sudo(command, nil, nil), do: command - defp sudo(command, username, nil), do: "sudo -H -n -u #{username} -- sh -c #{shellquote(command)}" - defp sudo(command, nil, groupname), do: "sudo -H -n -g #{groupname} -- sh -c #{shellquote(command)}" - defp sudo(command, username, groupname), do: "sudo -H -n -u #{username} -g #{groupname} -- sh -c #{shellquote(command)}" + + defp sudo(command, username, nil), + do: "sudo -H -n -u #{username} -- sh -c #{shellquote(command)}" + + defp sudo(command, nil, groupname), + do: "sudo -H -n -g #{groupname} -- sh -c #{shellquote(command)}" + + defp sudo(command, username, groupname), + do: "sudo -H -n -u #{username} -g #{groupname} -- sh -c #{shellquote(command)}" defp export(command, nil), do: command defp export(command, env) when env == %{}, do: command + defp export(command, env) do exports = Enum.map_join(env, " ", fn {name, value} -> "#{name}=\"#{value}\"" end) "(export #{exports} && #{command})" diff --git a/lib/sshkit/scp/download.ex b/lib/sshkit/scp/download.ex index a0323624..a11607df 100644 --- a/lib/sshkit/scp/download.ex +++ b/lib/sshkit/scp/download.ex @@ -28,7 +28,7 @@ defmodule SSHKit.SCP.Download do defp start(connection, source, target, options) do timeout = Keyword.get(options, :timeout, :infinity) - map_cmd = Keyword.get(options, :map_cmd, &(&1)) + map_cmd = Keyword.get(options, :map_cmd, & &1) command = map_cmd.(Command.build(:download, source, options)) handler = connection_handler(options) @@ -41,10 +41,13 @@ defmodule SSHKit.SCP.Download do case message do {:data, _, 0, data} -> process_data(state, data, options) + {:exit_status, _, status} -> exited(options, state, status) + {:eof, _} -> eof(options, state) + {:closed, _} -> closed(options, state) end @@ -55,6 +58,7 @@ defmodule SSHKit.SCP.Download do case state do {:next, path, stack, attrs, buffer} -> next(options, path, stack, attrs, buffer <> data) + {:read, path, stack, attrs, buffer} -> read(options, path, stack, attrs, buffer <> data) end @@ -193,7 +197,7 @@ defmodule SSHKit.SCP.Download do atime = :calendar.gregorian_seconds_to_datetime(@epoch + atime) mtime = :calendar.gregorian_seconds_to_datetime(@epoch + mtime) {:ok, file_info} = File.stat(path) - :ok = File.write_stat(path, %{file_info| mtime: mtime, atime: atime}, [:posix]) + :ok = File.write_stat(path, %{file_info | mtime: mtime, atime: atime}, [:posix]) end @tfmt ~S"(T)(0|[1-9]\d*) (0|[1-9]\d{0,5}) (0|[1-9]\d*) (0|[1-9]\d{0,5})" @@ -206,14 +210,19 @@ defmodule SSHKit.SCP.Download do case Regex.run(@dfmt, value, capture: :all_but_first) do ["T", mtime, mtus, atime, atus] -> {"T", dec(mtime), dec(mtus), dec(atime), dec(atus)} + [chr, _, _, name] when chr in ["C", "D"] and name in ["/", "..", "."] -> nil + ["C", mode, len, name] -> {"C", oct(mode), dec(len), name} + ["D", mode, len, name] -> {"D", oct(mode), dec(len), name} + ["E"] -> {"E"} + nil -> nil end diff --git a/lib/sshkit/scp/upload.ex b/lib/sshkit/scp/upload.ex index 0aef0194..2939000f 100644 --- a/lib/sshkit/scp/upload.ex +++ b/lib/sshkit/scp/upload.ex @@ -81,7 +81,7 @@ defmodule SSHKit.SCP.Upload do defp start(%{target: target, state: state, handler: handler, options: options}, connection) do timeout = Keyword.get(options, :timeout, :infinity) - map_cmd = Keyword.get(options, :map_cmd, &(&1)) + map_cmd = Keyword.get(options, :map_cmd, & &1) command = map_cmd.(Command.build(:upload, target, options)) ssh = Keyword.get(options, :ssh, SSH) ssh.run(connection, command, timeout: timeout, acc: {:cont, state}, fun: handler) @@ -93,25 +93,43 @@ defmodule SSHKit.SCP.Upload do defp connection_handler(options) do fn message, state -> case message do - {:data, _, 0, <<@warning, data :: binary>>} -> warning(options, state, data) - {:data, _, 0, <<@fatal, data :: binary>>} -> fatal(options, state, data) + {:data, _, 0, <<@warning, data::binary>>} -> + warning(options, state, data) + + {:data, _, 0, <<@fatal, data::binary>>} -> + fatal(options, state, data) + {:data, _, 0, <<@normal>>} -> handle_data(state, options) + {:data, _, 0, data} -> handle_error_data(state, options, data) - {:exit_status, _, status} -> exited(options, state, status) - {:eof, _} -> eof(options, state) - {:closed, _} -> closed(options, state) + + {:exit_status, _, status} -> + exited(options, state, status) + + {:eof, _} -> + eof(options, state) + + {:closed, _} -> + closed(options, state) end end end defp handle_data(state, options) do case state do - {:next, cwd, stack, errs} -> next(options, cwd, stack, errs) - {:directory, name, stat, cwd, stack, errs} -> directory(options, name, stat, cwd, stack, errs) - {:regular, name, stat, cwd, stack, errs} -> regular(options, name, stat, cwd, stack, errs) - {:write, name, stat, cwd, stack, errs} -> write(options, name, stat, cwd, stack, errs) + {:next, cwd, stack, errs} -> + next(options, cwd, stack, errs) + + {:directory, name, stat, cwd, stack, errs} -> + directory(options, name, stat, cwd, stack, errs) + + {:regular, name, stat, cwd, stack, errs} -> + regular(options, name, stat, cwd, stack, errs) + + {:write, name, stat, cwd, stack, errs} -> + write(options, name, stat, cwd, stack, errs) end end @@ -134,10 +152,11 @@ defmodule SSHKit.SCP.Upload do path = Path.join(cwd, name) stat = File.stat!(path, time: :posix) - stack = case stat.type do - :directory -> [File.ls!(path) | [rest | dirs]] - :regular -> [rest | dirs] - end + stack = + case stat.type do + :directory -> [File.ls!(path) | [rest | dirs]] + :regular -> [rest | dirs] + end if Keyword.get(options, :preserve, false) do time(options, stat.type, name, stat, cwd, stack, errs) @@ -174,7 +193,8 @@ defmodule SSHKit.SCP.Upload do end defp exited(_, {_, _, _, errs}, status) do - {:halt, {:error, "SCP exited before completing the transfer (#{status}): #{Enum.join(errs, ", ")}"}} + {:halt, + {:error, "SCP exited before completing the transfer (#{status}): #{Enum.join(errs, ", ")}"}} end defp eof(_, state) do diff --git a/lib/sshkit/ssh.ex b/lib/sshkit/ssh.ex index 443bc14e..0f03cc09 100644 --- a/lib/sshkit/ssh.ex +++ b/lib/sshkit/ssh.ex @@ -40,7 +40,7 @@ defmodule SSHKit.SSH do {:ok, conn} = SSHKit.SSH.connect("eg.io", port: 2222, user: "me", timeout: 1000) ``` """ - @callback connect(binary(), keyword() | fun()) :: {:ok, Connection.t} | {:error, any()} + @callback connect(binary(), keyword() | fun()) :: {:ok, Connection.t()} | {:error, any()} def connect(host, options_or_function \\ []) def connect(host, function) when is_function(function), do: connect(host, [], function) def connect(host, options) when is_list(options), do: Connection.open(host, options) @@ -73,7 +73,9 @@ defmodule SSHKit.SSH do after :ok = close(conn) end - other -> other + + other -> + other end end @@ -88,7 +90,7 @@ defmodule SSHKit.SSH do :ok = SSHKit.SSH.close(conn) ``` """ - @callback close(Connection.t) :: :ok + @callback close(Connection.t()) :: :ok def close(connection) do Connection.close(connection) end @@ -121,7 +123,7 @@ defmodule SSHKit.SSH do IO.inspect(output) ``` """ - @callback run(Connection.t, binary(), keyword()) :: any() + @callback run(Connection.t(), binary(), keyword()) :: any() def run(connection, command, options \\ []) do {acc, options} = Keyword.pop(options, :acc, {:cont, {[], nil}}) {fun, options} = Keyword.pop(options, :fun, &capture/2) @@ -134,8 +136,10 @@ defmodule SSHKit.SSH do channel |> Channel.loop(timeout, acc, fun) |> elem(1) + :failure -> {:error, :failure} + err -> err end @@ -143,18 +147,23 @@ defmodule SSHKit.SSH do end defp capture(message, acc = {buffer, status}) do - next = case message do - {:data, _, 0, data} -> - {[{:stdout, data} | buffer], status} - {:data, _, 1, data} -> - {[{:stderr, data} | buffer], status} - {:exit_status, _, code} -> - {buffer, code} - {:closed, _} -> - {:ok, Enum.reverse(buffer), status} - _ -> - acc - end + next = + case message do + {:data, _, 0, data} -> + {[{:stdout, data} | buffer], status} + + {:data, _, 1, data} -> + {[{:stderr, data} | buffer], status} + + {:exit_status, _, code} -> + {buffer, code} + + {:closed, _} -> + {:ok, Enum.reverse(buffer), status} + + _ -> + acc + end {:cont, next} end diff --git a/lib/sshkit/ssh/channel.ex b/lib/sshkit/ssh/channel.ex index e0dc0f5e..aea8954a 100644 --- a/lib/sshkit/ssh/channel.ex +++ b/lib/sshkit/ssh/channel.ex @@ -120,8 +120,8 @@ defmodule SSHKit.SSH.Channel do def send(channel, type, data, timeout) do Enum.reduce_while(data, :ok, fn - (datum, :ok) -> {:cont, send(channel, type, datum, timeout)} - (_, err) -> {:halt, err} + datum, :ok -> {:cont, send(channel, type, datum, timeout)} + _, err -> {:halt, err} end) end @@ -265,7 +265,9 @@ defmodule SSHKit.SSH.Channel do :ok = ljust(channel, msg) loop(channel, timeout, fun.(msg, acc), fun) end - err -> halt(channel, err) + + err -> + halt(channel, err) end end diff --git a/lib/sshkit/ssh/connection.ex b/lib/sshkit/ssh/connection.ex index 539bb623..ae87d946 100644 --- a/lib/sshkit/ssh/connection.ex +++ b/lib/sshkit/ssh/connection.ex @@ -38,18 +38,21 @@ defmodule SSHKit.SSH.Connection do Returns `{:ok, conn}` on success, `{:error, reason}` otherwise. """ def open(host, options \\ []) + def open(nil, _) do {:error, "No host given."} end + def open(host, options) when is_binary(host) do open(to_charlist(host), options) end + def open(host, options) do {details, opts} = extract(options) - port = details[:port] + port = details[:port] timeout = details[:timeout] - impl = details[:impl] + impl = details[:impl] case impl.connect(host, port, opts, timeout) do {:ok, ref} -> {:ok, build(host, port, opts, ref, impl)} diff --git a/lib/sshkit/utils.ex b/lib/sshkit/utils.ex index 2c9f6ed6..6d039941 100644 --- a/lib/sshkit/utils.ex +++ b/lib/sshkit/utils.ex @@ -8,15 +8,18 @@ defmodule SSHKit.Utils do def charlistify(value) when is_list(value) do Enum.map(value, &charlistify/1) end + def charlistify(value) when is_tuple(value) do value |> Tuple.to_list() |> charlistify() |> List.to_tuple() end + def charlistify(value) when is_binary(value) do to_charlist(value) end + def charlistify(value) do value end diff --git a/mix.exs b/mix.exs index c03448ec..973bb025 100644 --- a/mix.exs +++ b/mix.exs @@ -5,18 +5,20 @@ defmodule SSHKit.Mixfile do @source "https://github.com/bitcrowd/sshkit.ex" def project do - [app: :sshkit, - name: "sshkit", - version: @version, - elixir: "~> 1.5", - elixirc_paths: elixirc_paths(Mix.env), - build_embedded: Mix.env == :prod, - start_permanent: Mix.env == :prod, - source_url: @source, - docs: [source_ref: "v#{@version}", main: "readme", extras: ["README.md"]], - description: description(), - deps: deps(), - package: package()] + [ + app: :sshkit, + name: "sshkit", + version: @version, + elixir: "~> 1.5", + elixirc_paths: elixirc_paths(Mix.env()), + build_embedded: Mix.env() == :prod, + start_permanent: Mix.env() == :prod, + source_url: @source, + docs: [source_ref: "v#{@version}", main: "readme", extras: ["README.md"]], + description: description(), + deps: deps(), + package: package() + ] end def application do @@ -24,10 +26,12 @@ defmodule SSHKit.Mixfile do end defp deps do - [{:credo, "~> 0.7", runtime: false, only: [:dev, :test]}, - {:ex_doc, "~> 0.21.2", runtime: false, only: [:dev]}, - {:inch_ex, "~> 1.0", runtime: false, only: [:dev, :test]}, - {:mox, "~> 0.3", only: :test}] + [ + {:credo, "~> 0.7", runtime: false, only: [:dev, :test]}, + {:ex_doc, "~> 0.21.2", runtime: false, only: [:dev]}, + {:inch_ex, "~> 1.0", runtime: false, only: [:dev, :test]}, + {:mox, "~> 0.3", only: :test} + ] end defp description do @@ -35,11 +39,13 @@ defmodule SSHKit.Mixfile do end defp package do - [maintainers: ["bitcrowd", "Paul Meinhardt", "Paulo Diniz", "Philipp Tessenow"], - licenses: ["MIT"], - links: %{"GitHub" => @source}] + [ + maintainers: ["bitcrowd", "Paul Meinhardt", "Paulo Diniz", "Philipp Tessenow"], + licenses: ["MIT"], + links: %{"GitHub" => @source} + ] end defp elixirc_paths(:test), do: ["lib", "test/support"] - defp elixirc_paths(_), do: ["lib"] + defp elixirc_paths(_), do: ["lib"] end diff --git a/mix.lock b/mix.lock index 74cf0026..c92088d8 100644 --- a/mix.lock +++ b/mix.lock @@ -1,13 +1,13 @@ %{ - "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, - "credo": {:hex, :credo, "0.10.2", "03ad3a1eff79a16664ed42fc2975b5e5d0ce243d69318060c626c34720a49512", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, - "earmark": {:hex, :earmark, "1.4.2", "3aa0bd23bc4c61cf2f1e5d752d1bb470560a6f8539974f767a38923bb20e1d7f", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.21.2", "caca5bc28ed7b3bdc0b662f8afe2bee1eedb5c3cf7b322feeeb7c6ebbde089d6", [:mix], [{:earmark, "~> 1.3.3 or ~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, - "inch_ex": {:hex, :inch_ex, "1.0.1", "1f0af1a83cec8e56f6fc91738a09c838e858db3d78ef5f2ec040fe4d5a62dabf", [:mix], [{:poison, "~> 1.5 or ~> 2.0 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"}, - "jason": {:hex, :jason, "1.1.1", "d3ccb840dfb06f2f90a6d335b536dd074db748b3e7f5b11ab61d239506585eb2", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, - "makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, - "mox": {:hex, :mox, "0.4.0", "7f120840f7d626184a3d65de36189ca6f37d432e5d63acd80045198e4c5f7e6e", [:mix], [], "hexpm"}, - "nimble_parsec": {:hex, :nimble_parsec, "0.5.1", "c90796ecee0289dbb5ad16d3ad06f957b0cd1199769641c961cfe0b97db190e0", [:mix], [], "hexpm"}, - "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}, + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, + "credo": {:hex, :credo, "0.10.2", "03ad3a1eff79a16664ed42fc2975b5e5d0ce243d69318060c626c34720a49512", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "539596b6774069260d5938aa73042a2f5157e1c0215aa35f5a53d83889546d14"}, + "earmark": {:hex, :earmark, "1.4.2", "3aa0bd23bc4c61cf2f1e5d752d1bb470560a6f8539974f767a38923bb20e1d7f", [:mix], [], "hexpm", "5e8806285d8a3a8999bd38e4a73c58d28534c856bc38c44818e5ba85bbda16fb"}, + "ex_doc": {:hex, :ex_doc, "0.21.2", "caca5bc28ed7b3bdc0b662f8afe2bee1eedb5c3cf7b322feeeb7c6ebbde089d6", [:mix], [{:earmark, "~> 1.3.3 or ~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f1155337ae17ff7a1255217b4c1ceefcd1860b7ceb1a1874031e7a861b052e39"}, + "inch_ex": {:hex, :inch_ex, "1.0.1", "1f0af1a83cec8e56f6fc91738a09c838e858db3d78ef5f2ec040fe4d5a62dabf", [:mix], [{:poison, "~> 1.5 or ~> 2.0 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm", "08fd8a9205d3e1aefad9d7cb2a7f6b346e4a3e6ff09e139f6ec978f3a479ba14"}, + "jason": {:hex, :jason, "1.1.1", "d3ccb840dfb06f2f90a6d335b536dd074db748b3e7f5b11ab61d239506585eb2", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "639645cfac325e34938167b272bae0791fea3a34cf32c29525abf1d323ed4c18"}, + "makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "a10c6eb62cca416019663129699769f0c2ccf39428b3bb3c0cb38c718a0c186d"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "d4b316c7222a85bbaa2fd7c6e90e37e953257ad196dc229505137c5e505e9eff"}, + "mox": {:hex, :mox, "0.4.0", "7f120840f7d626184a3d65de36189ca6f37d432e5d63acd80045198e4c5f7e6e", [:mix], [], "hexpm", "64fca8aca4699cc1acf7db19237ce781cfa46683082a440e9f4e1ac29e290d89"}, + "nimble_parsec": {:hex, :nimble_parsec, "0.5.1", "c90796ecee0289dbb5ad16d3ad06f957b0cd1199769641c961cfe0b97db190e0", [:mix], [], "hexpm", "00e3ebdc821fb3a36957320d49e8f4bfa310d73ea31c90e5f925dc75e030da8f"}, + "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"}, } diff --git a/test/sshkit/context_test.exs b/test/sshkit/context_test.exs index b185255b..5317a58a 100644 --- a/test/sshkit/context_test.exs +++ b/test/sshkit/context_test.exs @@ -92,7 +92,8 @@ defmodule SSHKit.ContextTest do |> Map.put(:env, %{"HOME" => "/home/me"}) |> Context.build("cp $HOME/conf .") - assert command == ~S{cd /app && umask 007 && sudo -H -n -u me -g crew -- sh -c '(export HOME="/home/me" && /usr/bin/env cp $HOME/conf .)'} + assert command == + ~S{cd /app && umask 007 && sudo -H -n -u me -g crew -- sh -c '(export HOME="/home/me" && /usr/bin/env cp $HOME/conf .)'} end end end diff --git a/test/sshkit/scp/command_test.exs b/test/sshkit/scp/command_test.exs index b0908cc3..6a6a17a6 100644 --- a/test/sshkit/scp/command_test.exs +++ b/test/sshkit/scp/command_test.exs @@ -63,7 +63,8 @@ defmodule SSHKit.SCP.CommandTest do end test "constructs preserving and recursive download commands" do - assert build(:download, @path, preserve: true, recursive: true) == "scp -f -p -r #{@escaped}" + assert build(:download, @path, preserve: true, recursive: true) == + "scp -f -p -r #{@escaped}" end end end diff --git a/test/sshkit/scp/upload_test.exs b/test/sshkit/scp/upload_test.exs index f5c5e706..3e3ea26d 100644 --- a/test/sshkit/scp/upload_test.exs +++ b/test/sshkit/scp/upload_test.exs @@ -40,9 +40,11 @@ defmodule SSHKit.SCP.UploadTest do end test "allows modifying the executed scp command", %{conn: conn} do - upload = Upload.init(@source, @target, map_cmd: &"(( #{&1} ))", ssh: SSHMock, recursive: true) + upload = + Upload.init(@source, @target, map_cmd: &"(( #{&1} ))", ssh: SSHMock, recursive: true) - SSHMock |> expect(:run, fn (_, command, _) -> + SSHMock + |> expect(:run, fn _, command, _ -> assert command == "(( #{Command.build(:upload, upload.target, recursive: true)} ))" {:ok, :success} end) @@ -58,7 +60,8 @@ defmodule SSHKit.SCP.UploadTest do test "uses the provided timeout option", %{conn: conn} do upload = Upload.init(@source, @target, recursive: true, timeout: 55, ssh: SSHMock) - SSHMock |> expect(:run, fn (_, _, timeout: timeout, acc: {:cont, _}, fun: _) -> + SSHMock + |> expect(:run, fn _, _, timeout: timeout, acc: {:cont, _}, fun: _ -> assert timeout == 55 {:ok, :success} end) @@ -69,7 +72,12 @@ defmodule SSHKit.SCP.UploadTest do test "performs an upload", %{conn: conn} do upload = Upload.init(@source, @target, recursive: true, ssh: SSHMock) - SSHMock |> expect(:run, fn (connection, command, timeout: timeout, acc: {:cont, state}, fun: handler) -> + SSHMock + |> expect(:run, fn connection, + command, + timeout: timeout, + acc: {:cont, state}, + fun: handler -> assert connection == conn assert command == SSHKit.SCP.Command.build(:upload, upload.target, upload.options) assert timeout == :infinity @@ -93,13 +101,17 @@ defmodule SSHKit.SCP.UploadTest do %Upload{handler: handler, state: {:next, cwd, [["local_dir"]], []} = state} = upload next_path = Path.join(cwd, "local_dir") - assert {:cont, 'D0755 0 local_dir\n', {:next, ^next_path, [["other.txt"], []], []}} = handler.(ack, state) + assert {:cont, 'D0755 0 local_dir\n', {:next, ^next_path, [["other.txt"], []], []}} = + handler.(ack, state) end test "create files in the current directory", %{upload: %Upload{handler: handler}, ack: ack} do source_expanded = @source |> Path.expand() state = {:next, source_expanded, [["other.txt"], []], []} - assert {:cont, 'C0644 61 other.txt\n', {:write, "other.txt", %File.Stat{}, ^source_expanded, [[], []], []}} = handler.(ack, state) + + assert {:cont, 'C0644 61 other.txt\n', + {:write, "other.txt", %File.Stat{}, ^source_expanded, [[], []], []}} = + handler.(ack, state) end test "writes files in the current directory", %{upload: %Upload{handler: handler}, ack: ack} do @@ -138,7 +150,10 @@ defmodule SSHKit.SCP.UploadTest do assert {:cont, :ok} == handler.(closed_msg, eof_state) end - test "aggregates warnings in the state", %{upload: %Upload{handler: handler, state: state}, channel: channel} do + test "aggregates warnings in the state", %{ + upload: %Upload{handler: handler, state: state}, + channel: channel + } do error_msg = "error part 1 error part 2 error part 3" {name, cwd, stack, _errs} = state @@ -154,7 +169,10 @@ defmodule SSHKit.SCP.UploadTest do assert {:cont, {name, cwd, stack, [error_msg]}} == handler.(msg3, state2) end - test "aggregates connection errors in the state and halts", %{upload: %Upload{handler: handler, state: state}, channel: channel} do + test "aggregates connection errors in the state and halts", %{ + upload: %Upload{handler: handler, state: state}, + channel: channel + } do error_msg = "error part 1 error part 2 error part 3" msg1 = {:data, channel, 0, <<2, "error part 1 ">>} diff --git a/test/sshkit/scp_functional_test.exs b/test/sshkit/scp_functional_test.exs index d93ac2a5..4ded22d0 100644 --- a/test/sshkit/scp_functional_test.exs +++ b/test/sshkit/scp_functional_test.exs @@ -12,10 +12,10 @@ defmodule SSHKit.SCPFunctionalTest do local = "test/fixtures/local.txt" remote = "file.txt" - SSH.connect host.name, host.options, fn conn -> + SSH.connect(host.name, host.options, fn conn -> assert :ok = SCP.upload(conn, local, remote) assert verify_transfer(conn, local, remote) - end + end) end @tag boot: [@bootconf] @@ -23,10 +23,10 @@ defmodule SSHKit.SCPFunctionalTest do local = "test/fixtures" remote = "/home/#{host.options[:user]}/destination" - SSH.connect host.name, host.options, fn conn -> + SSH.connect(host.name, host.options, fn conn -> assert :ok = SCP.upload(conn, local, remote, recursive: true) assert verify_transfer(conn, local, remote) - end + end) end @tag boot: [@bootconf] @@ -34,11 +34,11 @@ defmodule SSHKit.SCPFunctionalTest do local = "test/fixtures/local.txt" remote = "file.txt" - SSH.connect host.name, host.options, fn conn -> + SSH.connect(host.name, host.options, fn conn -> assert :ok = SCP.upload(conn, local, remote, preserve: true) assert verify_mode(conn, local, remote) assert verify_mtime(conn, local, remote) - end + end) end @tag boot: [@bootconf] @@ -46,11 +46,11 @@ defmodule SSHKit.SCPFunctionalTest do local = "test/fixtures/" remote = "/home/#{host.options[:user]}/destination" - SSH.connect host.name, host.options, fn conn -> + SSH.connect(host.name, host.options, fn conn -> assert :ok = SCP.upload(conn, local, remote, recursive: true, preserve: true) assert verify_mode(conn, local, remote) assert verify_mtime(conn, local, remote) - end + end) end end @@ -59,52 +59,52 @@ defmodule SSHKit.SCPFunctionalTest do test "gets a file", %{hosts: [host]} do remote = "/fixtures/remote.txt" local = create_local_tmp_path() - on_exit fn -> File.rm(local) end + on_exit(fn -> File.rm(local) end) - SSH.connect host.name, host.options, fn conn -> + SSH.connect(host.name, host.options, fn conn -> assert :ok = SCP.download(conn, remote, local) assert verify_transfer(conn, local, remote) - end + end) end @tag boot: [@bootconf] test "recursive: true", %{hosts: [host]} do remote = "/fixtures" local = create_local_tmp_path() - on_exit fn -> File.rm_rf(local) end + on_exit(fn -> File.rm_rf(local) end) - SSH.connect host.name, host.options, fn conn -> + SSH.connect(host.name, host.options, fn conn -> assert :ok = SCP.download(conn, remote, local, recursive: true) assert verify_transfer(conn, local, remote) - end + end) end @tag boot: [@bootconf] test "preserve: true", %{hosts: [host]} do remote = "/fixtures/remote.txt" local = create_local_tmp_path() - on_exit fn -> File.rm(local) end + on_exit(fn -> File.rm(local) end) - SSH.connect host.name, host.options, fn conn -> + SSH.connect(host.name, host.options, fn conn -> assert :ok = SCP.download(conn, remote, local, preserve: true) assert verify_mode(conn, local, remote) assert verify_atime(conn, local, remote) assert verify_mtime(conn, local, remote) - end + end) end @tag boot: [@bootconf] test "recursive: true, preserve: true", %{hosts: [host]} do remote = "/fixtures" local = create_local_tmp_path() - on_exit fn -> File.rm_rf(local) end + on_exit(fn -> File.rm_rf(local) end) - SSH.connect host.name, host.options, fn conn -> + SSH.connect(host.name, host.options, fn conn -> assert :ok = SCP.download(conn, remote, local, recursive: true, preserve: true) assert verify_mode(conn, local, remote) assert verify_atime(conn, local, remote) assert verify_mtime(conn, local, remote) - end + end) end end end diff --git a/test/sshkit/ssh/channel_test.exs b/test/sshkit/ssh/channel_test.exs index cee05c02..f5bdf264 100644 --- a/test/sshkit/ssh/channel_test.exs +++ b/test/sshkit/ssh/channel_test.exs @@ -8,7 +8,7 @@ defmodule SSHKit.SSH.ChannelTest do alias SSHKit.SSH.Connection setup do - Mox.verify_on_exit! + Mox.verify_on_exit!() conn = %Connection{ref: :test_connection, impl: Connection.ImplMock} chan = %Channel{connection: conn, type: :session, id: 1, impl: Channel.ImplMock} @@ -18,7 +18,8 @@ defmodule SSHKit.SSH.ChannelTest do describe "open/2" do test "opens a channel on a connection", %{conn: conn, impl: impl} do - impl |> expect(:session_channel, fn (connection_ref, ini_window_size, max_packet_size, timeout) -> + impl + |> expect(:session_channel, fn connection_ref, ini_window_size, max_packet_size, timeout -> assert connection_ref == conn.ref assert ini_window_size == 128 * 1024 assert max_packet_size == 32 * 1024 @@ -29,15 +30,16 @@ defmodule SSHKit.SSH.ChannelTest do {:ok, chan} = open(conn, impl: impl) assert chan == %Channel{ - connection: conn, - type: :session, - id: 0, - impl: impl - } + connection: conn, + type: :session, + id: 0, + impl: impl + } end test "opens a channel with a specific timeout", %{conn: conn, impl: impl} do - impl |> expect(:session_channel, fn (_, _, _, timeout) -> + impl + |> expect(:session_channel, fn _, _, _, timeout -> assert timeout == 3000 {:ok, 0} end) @@ -46,17 +48,18 @@ defmodule SSHKit.SSH.ChannelTest do end test "returns an error if channel cannot be opened", %{conn: conn, impl: impl} do - impl |> expect(:session_channel, fn (_, _, _, _) -> {:error, :timeout} end) + impl |> expect(:session_channel, fn _, _, _, _ -> {:error, :timeout} end) assert open(conn, impl: impl) == {:error, :timeout} end end describe "subsystem/3" do test "requests a subsystem", %{chan: chan, impl: impl} do - impl |> expect(:subsystem, fn (connection_ref, channel_id, subsystem, timeout) -> + impl + |> expect(:subsystem, fn connection_ref, channel_id, subsystem, timeout -> assert connection_ref == chan.connection.ref assert channel_id == chan.id - assert subsystem == 'example-subsystem' + assert subsystem == 'example-subsystem' assert timeout == :infinity :success end) @@ -64,8 +67,9 @@ defmodule SSHKit.SSH.ChannelTest do :success = subsystem(chan, "example-subsystem", impl: impl) end - test "requests a subsystem with a specific timeout", %{chan: chan, impl: impl} do - impl |> expect(:subsystem, fn (_, _, _, timeout) -> + test "requests a subsystem with a specific timeout", %{chan: chan, impl: impl} do + impl + |> expect(:subsystem, fn _, _, _, timeout -> assert timeout == 3000 :success end) @@ -74,7 +78,8 @@ defmodule SSHKit.SSH.ChannelTest do end test "returns a failure if the subsystem could not be initialized", %{chan: chan, impl: impl} do - impl |> expect(:subsystem, fn (_, _, _, _) -> + impl + |> expect(:subsystem, fn _, _, _, _ -> :failure end) @@ -82,7 +87,8 @@ defmodule SSHKit.SSH.ChannelTest do end test "returns an error if the initialization times out", %{chan: chan, impl: impl} do - impl |> expect(:subsystem, fn (_, _, _, _) -> + impl + |> expect(:subsystem, fn _, _, _, _ -> {:error, :timeout} end) @@ -92,7 +98,8 @@ defmodule SSHKit.SSH.ChannelTest do describe "close/1" do test "closes the channel", %{chan: chan, impl: impl} do - impl |> expect(:close, fn (connection_ref, channel_id) -> + impl + |> expect(:close, fn connection_ref, channel_id -> assert connection_ref == chan.connection.ref assert channel_id == chan.id :ok @@ -104,7 +111,8 @@ defmodule SSHKit.SSH.ChannelTest do describe "exec/3" do test "executes a command (binary) over a channel", %{chan: chan, impl: impl} do - impl |> expect(:exec, fn (connection_ref, channel_id, command, timeout) -> + impl + |> expect(:exec, fn connection_ref, channel_id, command, timeout -> assert connection_ref == chan.connection.ref assert channel_id == chan.id assert command == 'cmd arg1 arg2' @@ -116,7 +124,8 @@ defmodule SSHKit.SSH.ChannelTest do end test "executes a command (charlist) over a channel", %{chan: chan, impl: impl} do - impl |> expect(:exec, fn (connection_ref, channel_id, command, timeout) -> + impl + |> expect(:exec, fn connection_ref, channel_id, command, timeout -> assert connection_ref == chan.connection.ref assert channel_id == chan.id assert command == 'cmd arg1 arg2' @@ -128,7 +137,8 @@ defmodule SSHKit.SSH.ChannelTest do end test "executes a command with a specific timeout", %{chan: chan, impl: impl} do - impl |> expect(:exec, fn (_, _, _, timeout) -> + impl + |> expect(:exec, fn _, _, _, timeout -> assert timeout == 4000 {:ok, 0} end) @@ -137,19 +147,20 @@ defmodule SSHKit.SSH.ChannelTest do end test "executes a failing command", %{chan: chan, impl: impl} do - impl |> expect(:exec, fn (_, _, _, _) -> :failure end) + impl |> expect(:exec, fn _, _, _, _ -> :failure end) assert exec(chan, "cmd") == :failure end test "returns an error if command cannot be executed", %{chan: chan, impl: impl} do - impl |> expect(:exec, fn (_, _, _, _) -> {:error, :closed} end) + impl |> expect(:exec, fn _, _, _, _ -> {:error, :closed} end) assert exec(chan, "cmd") == {:error, :closed} end end describe "ptty/4" do test "allocates ptty", %{chan: chan, impl: impl} do - impl |> expect(:ptty_alloc, fn (connection_ref, channel_id, options, timeout) -> + impl + |> expect(:ptty_alloc, fn connection_ref, channel_id, options, timeout -> assert connection_ref == chan.connection.ref assert channel_id == chan.id assert options == [] @@ -194,19 +205,20 @@ defmodule SSHKit.SSH.ChannelTest do end test "returns an error when channel not open", %{chan: chan, impl: impl} do - impl |> expect(:send, fn (_, _, _, _, _) -> {:error, :closed} end) + impl |> expect(:send, fn _, _, _, _, _ -> {:error, :closed} end) assert Channel.send(chan, "data") == {:error, :closed} end test "returns an error when channel times out", %{chan: chan, impl: impl} do - impl |> expect(:send, fn (_, _, _, _, _) -> {:error, :timeout} end) + impl |> expect(:send, fn _, _, _, _, _ -> {:error, :timeout} end) assert Channel.send(chan, "data") == {:error, :timeout} end end describe "eof/1" do test "sends EOF to open channel", %{chan: chan, impl: impl} do - impl |> expect(:send_eof, fn (connection_ref, channel_id) -> + impl + |> expect(:send_eof, fn connection_ref, channel_id -> assert connection_ref == chan.connection.ref assert channel_id == chan.id :ok @@ -216,7 +228,7 @@ defmodule SSHKit.SSH.ChannelTest do end test "returns an error when channel not open", %{chan: chan, impl: impl} do - impl |> expect(:send_eof, fn (_, _) -> {:error, :closed} end) + impl |> expect(:send_eof, fn _, _ -> {:error, :closed} end) assert eof(chan) == {:error, :closed} end end @@ -266,7 +278,8 @@ defmodule SSHKit.SSH.ChannelTest do end test "adjusts the window size", %{chan: chan, impl: impl} do - impl |> expect(:adjust_window, fn (connection_ref, channel_id, size) -> + impl + |> expect(:adjust_window, fn connection_ref, channel_id, size -> assert connection_ref == chan.connection.ref assert channel_id == chan.id assert size == 4096 @@ -279,7 +292,8 @@ defmodule SSHKit.SSH.ChannelTest do describe "shell/2" do test "set shell to server side", %{chan: chan, impl: impl} do - impl |> expect(:shell, fn (connection_ref, channel_id) -> + impl + |> expect(:shell, fn connection_ref, channel_id -> assert connection_ref == chan.connection.ref assert channel_id == chan.id :ok @@ -291,13 +305,13 @@ defmodule SSHKit.SSH.ChannelTest do describe "loop/4" do test "loops over channel messages until channel is closed", %{conn: conn, chan: chan} do - Enum.each(0..2, &(Kernel.send(self(), {:ssh_cm, conn.ref, {:msg, chan.id, &1}}))) + Enum.each(0..2, &Kernel.send(self(), {:ssh_cm, conn.ref, {:msg, chan.id, &1}})) Kernel.send(self(), {:ssh_cm, conn.ref, {:closed, chan.id}}) assert Enum.count(messages(self())) == 4 fun = fn - ({:msg, _, index}, _) -> {:cont, index} - ({:closed, _}, acc) -> {:cont, acc} + {:msg, _, index}, _ -> {:cont, index} + {:closed, _}, acc -> {:cont, acc} end assert loop(chan, 0, {:cont, -1}, fun) == {:done, 2} @@ -306,19 +320,19 @@ defmodule SSHKit.SSH.ChannelTest do test "allows sending messages to the remote", %{conn: conn, chan: chan, impl: impl} do impl - |> expect(:send_eof, fn (_, _) -> :ok end) + |> expect(:send_eof, fn _, _ -> :ok end) |> expect(:send, sends(chan, 0, "plain", 200, :ok)) |> expect(:send, sends(chan, 0, "normal", 200, :ok)) |> expect(:send, sends(chan, 1, "error", 200, :ok)) - Enum.each(0..4, &(Kernel.send(self(), {:ssh_cm, conn.ref, {:msg, chan.id, &1}}))) + Enum.each(0..4, &Kernel.send(self(), {:ssh_cm, conn.ref, {:msg, chan.id, &1}})) Kernel.send(self(), {:ssh_cm, conn.ref, {:closed, chan.id}}) msgs = [nil, :eof, "plain", {0, "normal"}, {1, "error"}] fun = fn - ({:msg, _, index}, _) -> {:cont, Enum.at(msgs, index), index} - ({:closed, _}, acc) -> {:cont, acc} + {:msg, _, index}, _ -> {:cont, Enum.at(msgs, index), index} + {:closed, _}, acc -> {:cont, acc} end assert loop(chan, 200, {:cont, -1}, fun) == {:done, 4} @@ -326,13 +340,13 @@ defmodule SSHKit.SSH.ChannelTest do end test "allows suspending the loop", %{conn: conn, chan: chan} do - Enum.each(0..1, &(Kernel.send(self(), {:ssh_cm, conn.ref, {:msg, chan.id, &1}}))) + Enum.each(0..1, &Kernel.send(self(), {:ssh_cm, conn.ref, {:msg, chan.id, &1}})) Kernel.send(self(), {:ssh_cm, conn.ref, {:closed, chan.id}}) fun = fn - ({:msg, _, _}, acc) when acc < 5 -> {:suspend, acc + 1} - ({:msg, _, _}, acc) -> {:cont, acc * 3} - ({:closed, _}, acc) -> {:cont, acc} + {:msg, _, _}, acc when acc < 5 -> {:suspend, acc + 1} + {:msg, _, _}, acc -> {:cont, acc * 3} + {:closed, _}, acc -> {:cont, acc} end {:suspended, 1, continue} = loop(chan, 0, {:cont, 0}, fun) @@ -342,38 +356,39 @@ defmodule SSHKit.SSH.ChannelTest do end test "allows halting the loop", %{conn: conn, chan: chan, impl: impl} do - impl |> expect(:close, fn (_, _) -> :ok end) + impl |> expect(:close, fn _, _ -> :ok end) - Enum.each(0..5, &(Kernel.send(self(), {:ssh_cm, conn.ref, {:msg, chan.id, &1}}))) + Enum.each(0..5, &Kernel.send(self(), {:ssh_cm, conn.ref, {:msg, chan.id, &1}})) fun = fn - (_, acc) when acc < 2 -> {:cont, acc + 1} - (_, acc) -> {:halt, acc} + _, acc when acc < 2 -> {:cont, acc + 1} + _, acc -> {:halt, acc} end assert loop(chan, 0, {:cont, 0}, fun) == {:halted, 2} - assert messages(self()) == [] # remaining messages flushed + # remaining messages flushed + assert messages(self()) == [] end test "returns an error if next message is not received in time", %{chan: chan, impl: impl} do - impl |> expect(:close, fn (_, _) -> :ok end) - res = loop(chan, 0, {:cont, []}, &([&1 | &2])) + impl |> expect(:close, fn _, _ -> :ok end) + res = loop(chan, 0, {:cont, []}, &[&1 | &2]) assert res == {:halted, {:error, :timeout}} end test "returns an error if message sending fails", %{chan: chan, impl: impl} do impl |> expect(:send, sends(chan, 0, "data", 100, {:error, :timeout})) - |> expect(:close, fn (_, _) -> :ok end) + |> expect(:close, fn _, _ -> :ok end) - res = loop(chan, 100, {:cont, "data", []}, &([&1 | &2])) + res = loop(chan, 100, {:cont, "data", []}, &[&1 | &2]) assert res == {:halted, {:error, :timeout}} end end defp sends(chan, expected_type, expected_data, expected_timeout, res) do - fn (connection_ref, channel_id, type, data, timeout) -> + fn connection_ref, channel_id, type, data, timeout -> assert connection_ref == chan.connection.ref assert channel_id == chan.id assert type == expected_type diff --git a/test/sshkit/ssh/connection_test.exs b/test/sshkit/ssh/connection_test.exs index d67a251a..0cfdc203 100644 --- a/test/sshkit/ssh/connection_test.exs +++ b/test/sshkit/ssh/connection_test.exs @@ -8,13 +8,14 @@ defmodule SSHKit.SSH.ConnectionTest do alias SSHKit.SSH.Connection.ImplMock setup do - Mox.verify_on_exit! + Mox.verify_on_exit!() {:ok, impl: ImplMock} end describe "open/2" do test "opens a connection", %{impl: impl} do - impl |> expect(:connect, fn (host, port, opts, timeout) -> + impl + |> expect(:connect, fn host, port, opts, timeout -> assert host == 'test.io' assert port == 22 assert opts == [user_interaction: false] @@ -25,16 +26,17 @@ defmodule SSHKit.SSH.ConnectionTest do {:ok, conn} = open("test.io", impl: impl) assert conn == %Connection{ - host: 'test.io', - port: 22, - options: [user_interaction: false], - ref: :connection_ref, - impl: impl - } + host: 'test.io', + port: 22, + options: [user_interaction: false], + ref: :connection_ref, + impl: impl + } end test "opens a connection on a different port with user and password", %{impl: impl} do - impl |> expect(:connect, fn (_, port, opts, _) -> + impl + |> expect(:connect, fn _, port, opts, _ -> assert port == 666 assert opts[:user] == 'me' assert opts[:password] == 'secret' @@ -45,16 +47,17 @@ defmodule SSHKit.SSH.ConnectionTest do {:ok, conn} = open("test.io", port: 666, user: "me", password: "secret", impl: impl) assert conn == %Connection{ - host: 'test.io', - port: 666, - options: [user_interaction: false, user: 'me', password: 'secret'], - ref: :ref_with_port_user_pass, - impl: impl - } + host: 'test.io', + port: 666, + options: [user_interaction: false, user: 'me', password: 'secret'], + ref: :ref_with_port_user_pass, + impl: impl + } end test "opens a connection with user interaction option set to true", %{impl: impl} do - impl |> expect(:connect, fn (_, _, opts, _) -> + impl + |> expect(:connect, fn _, _, opts, _ -> assert opts[:user] == 'me' assert opts[:password] == 'secret' assert opts[:user_interaction] == true @@ -66,16 +69,17 @@ defmodule SSHKit.SSH.ConnectionTest do {:ok, conn} = open("test.io", options) assert conn == %Connection{ - host: 'test.io', - options: [user: 'me', password: 'secret', user_interaction: true], - port: 22, - ref: :ref_with_user_interaction, - impl: impl - } + host: 'test.io', + options: [user: 'me', password: 'secret', user_interaction: true], + port: 22, + ref: :ref_with_user_interaction, + impl: impl + } end test "opens a connection with a specific timeout", %{impl: impl} do - impl |> expect(:connect, fn (_, _, _, timeout) -> + impl + |> expect(:connect, fn _, _, _, timeout -> assert timeout == 3000 {:ok, :ref} end) @@ -84,7 +88,8 @@ defmodule SSHKit.SSH.ConnectionTest do end test "removes options irrelevant for connect/4", %{impl: impl} do - impl |> expect(:connect, fn (_, _, opts, _) -> + impl + |> expect(:connect, fn _, _, opts, _ -> option_keys = Keyword.keys(opts) refute :port in option_keys @@ -100,7 +105,8 @@ defmodule SSHKit.SSH.ConnectionTest do end test "converts host to charlist", %{impl: impl} do - impl |> expect(:connect, fn (host, _, _, _) -> + impl + |> expect(:connect, fn host, _, _, _ -> assert host == 'test.io' {:ok, :ref} end) @@ -109,7 +115,8 @@ defmodule SSHKit.SSH.ConnectionTest do end test "converts option values to charlists", %{impl: impl} do - impl |> expect(:connect, fn (_, _, opts, _) -> + impl + |> expect(:connect, fn _, _, opts, _ -> assert {:user, 'me'} in opts assert {:password, 'secret'} in opts {:ok, :ref} @@ -119,7 +126,8 @@ defmodule SSHKit.SSH.ConnectionTest do end test "returns an error when connection cannot be opened", %{impl: impl} do - impl |> expect(:connect, fn (_, _, _, _) -> + impl + |> expect(:connect, fn _, _, _, _ -> {:error, :failed} end) @@ -133,17 +141,18 @@ defmodule SSHKit.SSH.ConnectionTest do describe "close/1" do test "closes a connection", %{impl: impl} do - impl |> expect(:close, fn ref -> + impl + |> expect(:close, fn ref -> assert ref == :connection_ref :ok end) conn = %Connection{ - host: 'foo.io', - port: 22, + host: 'foo.io', + port: 22, options: [user_interaction: false], - ref: :connection_ref, - impl: impl + ref: :connection_ref, + impl: impl } assert close(conn) == :ok @@ -153,14 +162,15 @@ defmodule SSHKit.SSH.ConnectionTest do describe "reopen/2" do test "opens a new connection with the same options as the existing connection", %{impl: impl} do conn = %Connection{ - host: 'test.io', - port: 22, + host: 'test.io', + port: 22, options: [user_interaction: false, user: 'me'], - ref: :connection_ref, - impl: impl + ref: :connection_ref, + impl: impl } - impl |> expect(:connect, fn (host, port, opts, _) -> + impl + |> expect(:connect, fn host, port, opts, _ -> assert host == conn.host assert port == conn.port assert opts == conn.options @@ -174,14 +184,15 @@ defmodule SSHKit.SSH.ConnectionTest do test "reopens a connection on new port", %{impl: impl} do conn = %Connection{ - host: 'test.io', - port: 22, + host: 'test.io', + port: 22, options: [user_interaction: false, user: 'me'], - ref: :connection_ref, - impl: impl + ref: :connection_ref, + impl: impl } - impl |> expect(:connect, fn (_, port, _, _) -> + impl + |> expect(:connect, fn _, port, _, _ -> assert port == 666 {:ok, :new_connection_ref} end) @@ -193,14 +204,15 @@ defmodule SSHKit.SSH.ConnectionTest do test "errors when unable to open connection", %{impl: impl} do conn = %Connection{ - host: 'test.io', - port: 22, + host: 'test.io', + port: 22, options: [user_interaction: false], - ref: :sandbox, - impl: impl + ref: :sandbox, + impl: impl } - impl |> expect(:connect, fn (_, _, _, _) -> + impl + |> expect(:connect, fn _, _, _, _ -> {:error, :failed} end) diff --git a/test/sshkit/ssh_test.exs b/test/sshkit/ssh_test.exs index ddc9324c..1e85d0ac 100644 --- a/test/sshkit/ssh_test.exs +++ b/test/sshkit/ssh_test.exs @@ -11,7 +11,7 @@ defmodule SSHKit.SSHTest do @user "me" setup do - Mox.verify_on_exit! + Mox.verify_on_exit!() end describe "connect/2" do @@ -20,7 +20,8 @@ defmodule SSHKit.SSHTest do end test "opens a connection with the given options and keeps it open", %{impl: impl} do - impl |> expect(:connect, fn (host, port, opts, timeout) -> + impl + |> expect(:connect, fn host, port, opts, timeout -> assert host == 'test.io' assert port == 2222 assert opts == [user_interaction: false, user: 'me'] @@ -31,16 +32,16 @@ defmodule SSHKit.SSHTest do {:ok, conn} = connect(@host, user: @user, port: 2222, impl: impl) assert conn == %Connection{ - host: 'test.io', - options: [user_interaction: false, user: 'me'], - port: 2222, - ref: :connection_ref, - impl: impl - } + host: 'test.io', + options: [user_interaction: false, user: 'me'], + port: 2222, + ref: :connection_ref, + impl: impl + } end test "returns an error if connection cannot be opened", %{impl: impl} do - impl |> expect(:connect, fn (_, _, _, _) -> {:error, :timeout} end) + impl |> expect(:connect, fn _, _, _, _ -> {:error, :timeout} end) assert connect(@host, impl: impl) == {:error, :timeout} end @@ -61,7 +62,7 @@ defmodule SSHKit.SSHTest do test "executes function on open connection", %{impl: impl} do impl - |> expect(:connect, fn (_, _, _, _) -> {:ok, :opened_connection_ref} end) + |> expect(:connect, fn _, _, _, _ -> {:ok, :opened_connection_ref} end) |> expect(:close, fn :opened_connection_ref -> :ok end) fun = fn conn -> @@ -74,7 +75,7 @@ defmodule SSHKit.SSHTest do test "closes connection although function errored", %{impl: impl} do impl - |> expect(:connect, fn (_, _, _, _) -> {:ok, :opened_connection_ref} end) + |> expect(:connect, fn _, _, _, _ -> {:ok, :opened_connection_ref} end) |> expect(:close, fn :opened_connection_ref -> :ok end) fun = fn _ -> raise(RuntimeError, message: "error") end @@ -85,8 +86,8 @@ defmodule SSHKit.SSHTest do end test "returns connection errors", %{impl: impl} do - impl |> expect(:connect, fn (_, _, _, _) -> {:error, :timeout} end) - fun = fn _ -> flunk "should never be called" end + impl |> expect(:connect, fn _, _, _, _ -> {:error, :timeout} end) + fun = fn _ -> flunk("should never be called") end assert connect(@host, [impl: impl], fun) == {:error, :timeout} end end @@ -98,14 +99,15 @@ defmodule SSHKit.SSHTest do test "closes the connection", %{impl: impl} do conn = %SSHKit.SSH.Connection{ - host: 'test.io', - port: 22, + host: 'test.io', + port: 22, options: [user_interaction: false], - ref: :connection_ref, - impl: impl + ref: :connection_ref, + impl: impl } - impl |> expect(:close, fn ref -> + impl + |> expect(:close, fn ref -> assert ref == conn.ref :ok end) @@ -122,9 +124,9 @@ defmodule SSHKit.SSHTest do test "captures output and exit status by default", %{conn: conn, impl: impl} do impl - |> expect(:session_channel, fn (:cref, _, _, :infinity) -> {:ok, 11} end) - |> expect(:exec, fn (:cref, 11, 'try', :infinity) -> :success end) - |> expect(:adjust_window, 2, fn (:cref, 11, _) -> :ok end) + |> expect(:session_channel, fn :cref, _, _, :infinity -> {:ok, 11} end) + |> expect(:exec, fn :cref, 11, 'try', :infinity -> :success end) + |> expect(:adjust_window, 2, fn :cref, 11, _ -> :ok end) send(self(), {:ssh_cm, conn.ref, {:data, 11, 0, "out"}}) send(self(), {:ssh_cm, conn.ref, {:data, 11, 1, "err"}}) @@ -136,17 +138,17 @@ defmodule SSHKit.SSHTest do test "accepts a custom handler function and accumulator", %{conn: conn, impl: impl} do impl - |> expect(:session_channel, fn (:cref, _, _, _) -> {:ok, 31} end) - |> expect(:exec, fn (:cref, 31, 'cmd', _) -> :success end) - |> expect(:send, fn (:cref, 31, 0, "PING", _) -> :ok end) - |> expect(:adjust_window, fn (:cref, 31, _) -> :ok end) - |> expect(:close, fn (:cref, 31) -> :ok end) + |> expect(:session_channel, fn :cref, _, _, _ -> {:ok, 31} end) + |> expect(:exec, fn :cref, 31, 'cmd', _ -> :success end) + |> expect(:send, fn :cref, 31, 0, "PING", _ -> :ok end) + |> expect(:adjust_window, fn :cref, 31, _ -> :ok end) + |> expect(:close, fn :cref, 31 -> :ok end) send(self(), {:ssh_cm, conn.ref, {:data, 31, 0, "PONG"}}) ini = {:cont, "PING", ["START"]} - fun = fn (msg, acc) -> + fun = fn msg, acc -> case msg do {:data, _, 0, data} -> {:halt, [data | acc]} _ -> {:cont, "NOPE", ["FAILED" | acc]} @@ -158,10 +160,10 @@ defmodule SSHKit.SSHTest do test "accepts a timeout value", %{conn: conn, impl: impl} do impl - |> expect(:session_channel, fn (_, _, _, 500) -> {:ok, 61} end) - |> expect(:exec, fn (_, _, _, 500) -> :success end) - |> expect(:send, fn (_, _, _, _, 500) -> {:error, :timeout} end) - |> expect(:close, fn (_, _) -> :ok end) + |> expect(:session_channel, fn _, _, _, 500 -> {:ok, 61} end) + |> expect(:exec, fn _, _, _, 500 -> :success end) + |> expect(:send, fn _, _, _, _, 500 -> {:error, :timeout} end) + |> expect(:close, fn _, _ -> :ok end) acc = {:cont, "INIT", {[], nil}} @@ -169,14 +171,14 @@ defmodule SSHKit.SSHTest do end test "returns an error if channel cannot be opened", %{conn: conn, impl: impl} do - impl |> expect(:session_channel, fn (_, _, _, _) -> {:error, :timeout} end) + impl |> expect(:session_channel, fn _, _, _, _ -> {:error, :timeout} end) assert run(conn, "uptime", impl: impl) == {:error, :timeout} end test "returns an error if command fails to execute", %{conn: conn, impl: impl} do impl - |> expect(:session_channel, fn (_, _, _, _) -> {:ok, 13} end) - |> expect(:exec, fn (_, _, _, _) -> :failure end) + |> expect(:session_channel, fn _, _, _, _ -> {:ok, 13} end) + |> expect(:exec, fn _, _, _, _ -> :failure end) assert run(conn, "uptime", impl: impl) == {:error, :failure} end diff --git a/test/sshkit/utils_test.exs b/test/sshkit/utils_test.exs index 26d60176..7caf93f9 100644 --- a/test/sshkit/utils_test.exs +++ b/test/sshkit/utils_test.exs @@ -17,18 +17,18 @@ defmodule SSHKit.UtilsTest do end test "converts binaries in keywords" do - assert Utils.charlistify([inet: :inet6, user: "me"]) == [inet: :inet6, user: 'me'] + assert Utils.charlistify(inet: :inet6, user: "me") == [inet: :inet6, user: 'me'] end test "converts binaries in nested lists" do - actual = Utils.charlistify([pref_public_key_algs: ["ssh-rsa", "ssh-dss"]]) + actual = Utils.charlistify(pref_public_key_algs: ["ssh-rsa", "ssh-dss"]) expected = [pref_public_key_algs: ['ssh-rsa', 'ssh-dss']] assert actual == expected end test "converts binaries in nested keywords" do ciphers = [client2server: ["aes128-ctr"], server2client: ["aes128-cbc", "3des-cbc"]] - actual = Utils.charlistify([preferred_algorithms: [cipher: ciphers]]) + actual = Utils.charlistify(preferred_algorithms: [cipher: ciphers]) expected = [preferred_algorithms: [cipher: Utils.charlistify(ciphers)]] assert actual == expected end diff --git a/test/sshkit_functional_test.exs b/test/sshkit_functional_test.exs index 4cbc2c60..4027c48d 100644 --- a/test/sshkit_functional_test.exs +++ b/test/sshkit_functional_test.exs @@ -195,14 +195,17 @@ defmodule SSHKitFunctionalTest do test "with context", %{hosts: hosts} do local = "test/fixtures" - remote = "target" # path relative to context path + # path relative to context path + remote = "target" context = hosts |> SSHKit.context() |> SSHKit.path("/tmp") - assert [:ok, :ok] = SSHKit.upload(context, local, recursive: true, preserve: true, as: remote) + assert [:ok, :ok] = + SSHKit.upload(context, local, recursive: true, preserve: true, as: remote) + assert verify_transfer(context, local, Path.join(context.path, remote)) assert verify_mode(context, local, Path.join(context.path, remote)) assert verify_mtime(context, local, Path.join(context.path, remote)) @@ -216,7 +219,7 @@ defmodule SSHKitFunctionalTest do tmpdir = create_local_tmp_path() :ok = File.mkdir!(tmpdir) - on_exit fn -> File.rm_rf(tmpdir) end + on_exit(fn -> File.rm_rf(tmpdir) end) {:ok, tmpdir: tmpdir} end @@ -266,7 +269,8 @@ defmodule SSHKitFunctionalTest do end test "with context", %{hosts: hosts, tmpdir: tmpdir} do - remote = "fixtures" # path relative to context path + # path relative to context path + remote = "fixtures" local = Path.join(tmpdir, "fixtures") context = diff --git a/test/support/functional_assertion_helpers.ex b/test/support/functional_assertion_helpers.ex index 6e54a4be..9e8fd66f 100644 --- a/test/support/functional_assertion_helpers.ex +++ b/test/support/functional_assertion_helpers.ex @@ -8,47 +8,57 @@ defmodule SSHKit.FunctionalAssertionHelpers do def verify_transfer(conn, local, remote) do command = &"find #{&1} -type f -exec #{&2} {} \\; | sort | awk '{print $1}' | xargs" - compare_command_output(conn, + + compare_command_output( + conn, command.(local, SystemCommands.shasum_cmd()), command.(remote, "sha1sum") - ) + ) end def verify_mode(conn, local, remote) do command = &"find #{&1} -type f -exec ls -l {} + | awk '{print $1 $5}' | sort |xargs" - compare_command_output(conn, + + compare_command_output( + conn, command.(local), command.(remote) - ) + ) end def verify_atime(conn, local, remote) do command = &"env find #{&1} -type f -exec #{&2} {} \\; | cut -f1,2 | sort | xargs" - compare_command_output(conn, - command.(local, SystemCommands.stat_cmd()), - command.(remote, "stat -c '%s\t%X\t%Y'") - ) + + compare_command_output( + conn, + command.(local, SystemCommands.stat_cmd()), + command.(remote, "stat -c '%s\t%X\t%Y'") + ) end def verify_mtime(conn, local, remote) do command = &"env find #{&1} -type f -exec #{&2} {} \\; | cut -f1,3 | sort | xargs" - compare_command_output(conn, + + compare_command_output( + conn, command.(local, SystemCommands.stat_cmd()), command.(remote, "stat -c '%s\t%X\t%Y'") - ) + ) end def compare_command_output(context = %Context{}, local, remote) do - Enum.map(context.hosts, - fn(h) -> - SSH.connect h.name, h.options, fn(conn) -> + Enum.map( + context.hosts, + fn h -> + SSH.connect(h.name, h.options, fn conn -> compare_command_output(conn, local, remote) - end - end) + end) + end + ) end def compare_command_output(conn, local, remote) do - local_output = local |> String.to_charlist |> :os.cmd |> to_string + local_output = local |> String.to_charlist() |> :os.cmd() |> to_string {:ok, [stdout: remote_output], 0} = SSH.run(conn, remote) assert local_output == remote_output end diff --git a/test/support/functional_case.ex b/test/support/functional_case.ex index 174daea5..be29e97d 100644 --- a/test/support/functional_case.ex +++ b/test/support/functional_case.ex @@ -64,7 +64,7 @@ defmodule SSHKit.FunctionalCase do end def kill!(hosts) do - running = Enum.map(hosts, &(Map.get(&1, :id))) + running = Enum.map(hosts, &Map.get(&1, :id)) killed = Docker.kill!(running) diff = running -- killed if Enum.empty?(diff), do: :ok, else: {:error, diff} diff --git a/test/support/functional_case_helpers.ex b/test/support/functional_case_helpers.ex index 1aae89bb..047f3025 100644 --- a/test/support/functional_case_helpers.ex +++ b/test/support/functional_case_helpers.ex @@ -23,7 +23,11 @@ defmodule SSHKit.FunctionalCaseHelpers do end def keygen!(host, username) do - exec!(host, "sh", ["-c", "ssh-keygen -b 1024 -f /tmp/#{username} -N '' -C \"#{username}@$(hostname)\""]) + exec!(host, "sh", [ + "-c", + "ssh-keygen -b 1024 -f /tmp/#{username} -N '' -C \"#{username}@$(hostname)\"" + ]) + exec!(host, "sh", ["-c", "cat /tmp/#{username}.pub > /home/#{username}/.ssh/authorized_keys"]) end end diff --git a/test/support/mocks.ex b/test/support/mocks.ex index 42be2eea..af25536a 100644 --- a/test/support/mocks.ex +++ b/test/support/mocks.ex @@ -15,12 +15,17 @@ defmodule SSHKit.SSH.Channel.Impl do @type conn :: any() @type chan :: integer() - @callback session_channel(conn, integer(), integer(), timeout()) :: {:ok, chan} | {:error, any()} - @callback subsystem(conn, chan, charlist(), keyword()) :: :success | :failure | {:error, :timeout} | {:error, :closed} + @callback session_channel(conn, integer(), integer(), timeout()) :: + {:ok, chan} | {:error, any()} + @callback subsystem(conn, chan, charlist(), keyword()) :: + :success | :failure | {:error, :timeout} | {:error, :closed} @callback close(conn, chan) :: :ok - @callback exec(conn, chan, binary(), timeout()) :: :success | :failure | {:error, :timeout} | {:error, :closed} - @callback ptty_alloc(conn, chan, keyword(), timeout()) :: :success | :failure | {:error, :timeout} | {:error, :closed} - @callback send(conn, chan, 0..1, binary(), timeout()) :: :ok | {:error, :timeout} | {:error, :closed} + @callback exec(conn, chan, binary(), timeout()) :: + :success | :failure | {:error, :timeout} | {:error, :closed} + @callback ptty_alloc(conn, chan, keyword(), timeout()) :: + :success | :failure | {:error, :timeout} | {:error, :closed} + @callback send(conn, chan, 0..1, binary(), timeout()) :: + :ok | {:error, :timeout} | {:error, :closed} @callback send_eof(conn, chan) :: :ok | {:error, :closed} @callback adjust_window(conn, chan, integer()) :: :ok @callback shell(conn, chan) :: :ok | {:error, :closed} diff --git a/test/test_helper.exs b/test/test_helper.exs index a4294785..1b890505 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,9 +1,9 @@ excluded = Application.get_env(:ex_unit, :exclude) included = Application.get_env(:ex_unit, :include) -unless (:functional in excluded) && !(:functional in included) do - unless Docker.ready? do - IO.puts """ +unless :functional in excluded && !(:functional in included) do + unless Docker.ready?() do + IO.puts(""" It seems like Docker isn't running? Please check: @@ -11,7 +11,7 @@ unless (:functional in excluded) && !(:functional in included) do 1. Docker is installed: `docker version` 2. On OS X and Windows: `docker-machine start` 3. Environment is set up: `eval $(docker-machine env)` - """ + """) exit({:shutdown, 1}) end @@ -20,16 +20,18 @@ unless (:functional in excluded) && !(:functional in included) do end shasum_command = SystemCommands.shasum_cmd() + try do System.cmd(shasum_command, ["--version"]) rescue error in ErlangError -> - IO.puts """ + IO.puts(""" An error happened while executing #{shasum_command} (#{error.original}). It seems like the `#{shasum_command}` command isn't available? Please check that #{shasum_command} is installed: `which #{shasum_command}` - """ + """) + exit({:shutdown, 1}) end From 4ada4ae7967eba14471aab3ad7bcb3262187898b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Kn=C3=B6pfle?= Date: Wed, 11 Jan 2023 11:31:17 +0100 Subject: [PATCH 2/3] Update dev dependencies --- .credo.exs | 146 -------------------------------- lib/sshkit/scp/download.ex | 4 +- lib/sshkit/scp/upload.ex | 4 +- lib/sshkit/ssh/connection.ex | 2 +- mix.exs | 14 +-- mix.lock | 21 +++-- test/support/functional_case.ex | 1 + 7 files changed, 29 insertions(+), 163 deletions(-) delete mode 100644 .credo.exs diff --git a/.credo.exs b/.credo.exs deleted file mode 100644 index 667dbe6a..00000000 --- a/.credo.exs +++ /dev/null @@ -1,146 +0,0 @@ -# This file contains the configuration for Credo and you are probably reading -# this after creating it with `mix credo.gen.config`. -# -# If you find anything wrong or unclear in this file, please report an -# issue on GitHub: https://github.com/rrrene/credo/issues -# -%{ - # - # You can have as many configs as you like in the `configs:` field. - configs: [ - %{ - # - # Run any exec using `mix credo -C `. If no exec name is given - # "default" is used. - # - name: "default", - # - # These are the files included in the analysis: - files: %{ - # - # You can give explicit globs or simply directories. - # In the latter case `**/*.{ex,exs}` will be used. - # - included: ["lib/", "src/", "web/", "apps/"], - excluded: [~r"/_build/", ~r"/deps/"] - }, - # - # If you create your own checks, you must specify the source files for - # them here, so they can be loaded by Credo before running the analysis. - # - requires: [], - # - # If you want to enforce a style guide and need a more traditional linting - # experience, you can change `strict` to `true` below: - # - strict: true, - # - # If you want to use uncolored output by default, you can change `color` - # to `false` below: - # - color: true, - # - # You can customize the parameters of any check by adding a second element - # to the tuple. - # - # To disable a check put `false` as second element: - # - # {Credo.Check.Design.DuplicatedCode, false} - # - checks: [ - {Credo.Check.Consistency.ExceptionNames}, - {Credo.Check.Consistency.LineEndings}, - {Credo.Check.Consistency.ParameterPatternMatching}, - {Credo.Check.Consistency.SpaceAroundOperators}, - {Credo.Check.Consistency.SpaceInParentheses}, - {Credo.Check.Consistency.TabsOrSpaces}, - - # You can customize the priority of any check - # Priority values are: `low, normal, high, higher` - # - {Credo.Check.Design.AliasUsage, priority: :low}, - - # For some checks, you can also set other parameters - # - # If you don't want the `setup` and `test` macro calls in ExUnit tests - # or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just - # set the `excluded_macros` parameter to `[:schema, :setup, :test]`. - # - {Credo.Check.Design.DuplicatedCode, excluded_macros: []}, - - # You can also customize the exit_status of each check. - # If you don't want TODO comments to cause `mix credo` to fail, just - # set this value to 0 (zero). - # - {Credo.Check.Design.TagTODO, exit_status: 2}, - {Credo.Check.Design.TagFIXME}, - - {Credo.Check.Readability.FunctionNames}, - {Credo.Check.Readability.LargeNumbers}, - {Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 120}, - {Credo.Check.Readability.ModuleAttributeNames}, - {Credo.Check.Readability.ModuleDoc}, - {Credo.Check.Readability.ModuleNames}, - {Credo.Check.Readability.ParenthesesOnZeroArityDefs}, - {Credo.Check.Readability.ParenthesesInCondition}, - {Credo.Check.Readability.PredicateFunctionNames}, - {Credo.Check.Readability.PreferImplicitTry}, - {Credo.Check.Readability.RedundantBlankLines}, - {Credo.Check.Readability.StringSigils}, - {Credo.Check.Readability.TrailingBlankLine}, - {Credo.Check.Readability.TrailingWhiteSpace}, - {Credo.Check.Readability.VariableNames}, - {Credo.Check.Readability.Semicolons}, - {Credo.Check.Readability.SpaceAfterCommas}, - - {Credo.Check.Refactor.DoubleBooleanNegation}, - {Credo.Check.Refactor.CondStatements}, - {Credo.Check.Refactor.CyclomaticComplexity}, - {Credo.Check.Refactor.FunctionArity, max_arity: 7}, - {Credo.Check.Refactor.LongQuoteBlocks}, - {Credo.Check.Refactor.MatchInCondition}, - {Credo.Check.Refactor.NegatedConditionsInUnless}, - {Credo.Check.Refactor.NegatedConditionsWithElse}, - {Credo.Check.Refactor.Nesting}, - {Credo.Check.Refactor.PipeChainStart}, - {Credo.Check.Refactor.UnlessWithElse}, - - {Credo.Check.Warning.BoolOperationOnSameValues}, - {Credo.Check.Warning.ExpensiveEmptyEnumCheck}, - {Credo.Check.Warning.IExPry}, - {Credo.Check.Warning.IoInspect}, - {Credo.Check.Warning.LazyLogging}, - {Credo.Check.Warning.OperationOnSameValues}, - {Credo.Check.Warning.OperationWithConstantResult}, - {Credo.Check.Warning.UnusedEnumOperation}, - {Credo.Check.Warning.UnusedFileOperation}, - {Credo.Check.Warning.UnusedKeywordOperation}, - {Credo.Check.Warning.UnusedListOperation}, - {Credo.Check.Warning.UnusedPathOperation}, - {Credo.Check.Warning.UnusedRegexOperation}, - {Credo.Check.Warning.UnusedStringOperation}, - {Credo.Check.Warning.UnusedTupleOperation}, - {Credo.Check.Warning.RaiseInsideRescue}, - - # Controversial and experimental checks (opt-in, just remove `, false`) - # - {Credo.Check.Refactor.ABCSize, false}, - {Credo.Check.Refactor.AppendSingleItem, false}, - {Credo.Check.Refactor.VariableRebinding, false}, - {Credo.Check.Warning.MapGetUnsafePass, false}, - {Credo.Check.Consistency.MultiAliasImportRequireUse, false}, - - # Deprecated checks (these will be deleted after a grace period) - # - {Credo.Check.Readability.Specs, false}, - {Credo.Check.Warning.NameRedeclarationByAssignment, false}, - {Credo.Check.Warning.NameRedeclarationByCase, false}, - {Credo.Check.Warning.NameRedeclarationByDef, false}, - {Credo.Check.Warning.NameRedeclarationByFn, false}, - - # Custom checks can be created using `mix credo.gen.check`. - # - ] - } - ] -} diff --git a/lib/sshkit/scp/download.ex b/lib/sshkit/scp/download.ex index a11607df..516a760c 100644 --- a/lib/sshkit/scp/download.ex +++ b/lib/sshkit/scp/download.ex @@ -1,5 +1,7 @@ defmodule SSHKit.SCP.Download do - @moduledoc false + @moduledoc """ + Helper module used by SSHKit.SCP.download/4. + """ require Bitwise diff --git a/lib/sshkit/scp/upload.ex b/lib/sshkit/scp/upload.ex index 2939000f..f48059b8 100644 --- a/lib/sshkit/scp/upload.ex +++ b/lib/sshkit/scp/upload.ex @@ -1,5 +1,7 @@ defmodule SSHKit.SCP.Upload do - @moduledoc false + @moduledoc """ + Helper module used by SSHKit.SCP.upload/4. + """ require Bitwise diff --git a/lib/sshkit/ssh/connection.ex b/lib/sshkit/ssh/connection.ex index ae87d946..0e15b3ec 100644 --- a/lib/sshkit/ssh/connection.ex +++ b/lib/sshkit/ssh/connection.ex @@ -97,7 +97,7 @@ defmodule SSHKit.SSH.Connection do The timeout value of the original connection is discarded. Other connection options are reused and may be overridden. - Uses `SSHKit.SSH.open/2`. + Uses `open/2`. Returns `{:ok, conn}` or `{:error, reason}`. """ diff --git a/mix.exs b/mix.exs index 973bb025..1b06f818 100644 --- a/mix.exs +++ b/mix.exs @@ -14,7 +14,11 @@ defmodule SSHKit.Mixfile do build_embedded: Mix.env() == :prod, start_permanent: Mix.env() == :prod, source_url: @source, - docs: [source_ref: "v#{@version}", main: "readme", extras: ["README.md"]], + docs: [ + source_ref: "v#{@version}", + main: "readme", + extras: ["README.md", "CHANGELOG.md", "LICENSE"] + ], description: description(), deps: deps(), package: package() @@ -27,10 +31,10 @@ defmodule SSHKit.Mixfile do defp deps do [ - {:credo, "~> 0.7", runtime: false, only: [:dev, :test]}, - {:ex_doc, "~> 0.21.2", runtime: false, only: [:dev]}, - {:inch_ex, "~> 1.0", runtime: false, only: [:dev, :test]}, - {:mox, "~> 0.3", only: :test} + {:credo, "~> 1.6", runtime: false, only: [:dev, :test]}, + {:ex_doc, "~> 0.27", runtime: false, only: [:dev]}, + {:inch_ex, "~> 2.0", runtime: false, only: [:dev, :test]}, + {:mox, "~> 1.0", only: :test} ] end diff --git a/mix.lock b/mix.lock index c92088d8..e24146b2 100644 --- a/mix.lock +++ b/mix.lock @@ -1,13 +1,16 @@ %{ - "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, - "credo": {:hex, :credo, "0.10.2", "03ad3a1eff79a16664ed42fc2975b5e5d0ce243d69318060c626c34720a49512", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "539596b6774069260d5938aa73042a2f5157e1c0215aa35f5a53d83889546d14"}, + "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, + "credo": {:hex, :credo, "1.6.7", "323f5734350fd23a456f2688b9430e7d517afb313fbd38671b8a4449798a7854", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "41e110bfb007f7eda7f897c10bf019ceab9a0b269ce79f015d54b0dcf4fc7dd3"}, "earmark": {:hex, :earmark, "1.4.2", "3aa0bd23bc4c61cf2f1e5d752d1bb470560a6f8539974f767a38923bb20e1d7f", [:mix], [], "hexpm", "5e8806285d8a3a8999bd38e4a73c58d28534c856bc38c44818e5ba85bbda16fb"}, - "ex_doc": {:hex, :ex_doc, "0.21.2", "caca5bc28ed7b3bdc0b662f8afe2bee1eedb5c3cf7b322feeeb7c6ebbde089d6", [:mix], [{:earmark, "~> 1.3.3 or ~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f1155337ae17ff7a1255217b4c1ceefcd1860b7ceb1a1874031e7a861b052e39"}, - "inch_ex": {:hex, :inch_ex, "1.0.1", "1f0af1a83cec8e56f6fc91738a09c838e858db3d78ef5f2ec040fe4d5a62dabf", [:mix], [{:poison, "~> 1.5 or ~> 2.0 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm", "08fd8a9205d3e1aefad9d7cb2a7f6b346e4a3e6ff09e139f6ec978f3a479ba14"}, - "jason": {:hex, :jason, "1.1.1", "d3ccb840dfb06f2f90a6d335b536dd074db748b3e7f5b11ab61d239506585eb2", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "639645cfac325e34938167b272bae0791fea3a34cf32c29525abf1d323ed4c18"}, - "makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "a10c6eb62cca416019663129699769f0c2ccf39428b3bb3c0cb38c718a0c186d"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "d4b316c7222a85bbaa2fd7c6e90e37e953257ad196dc229505137c5e505e9eff"}, - "mox": {:hex, :mox, "0.4.0", "7f120840f7d626184a3d65de36189ca6f37d432e5d63acd80045198e4c5f7e6e", [:mix], [], "hexpm", "64fca8aca4699cc1acf7db19237ce781cfa46683082a440e9f4e1ac29e290d89"}, - "nimble_parsec": {:hex, :nimble_parsec, "0.5.1", "c90796ecee0289dbb5ad16d3ad06f957b0cd1199769641c961cfe0b97db190e0", [:mix], [], "hexpm", "00e3ebdc821fb3a36957320d49e8f4bfa310d73ea31c90e5f925dc75e030da8f"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"}, + "ex_doc": {:hex, :ex_doc, "0.29.1", "b1c652fa5f92ee9cf15c75271168027f92039b3877094290a75abcaac82a9f77", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "b7745fa6374a36daf484e2a2012274950e084815b936b1319aeebcf7809574f6"}, + "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, + "inch_ex": {:hex, :inch_ex, "2.0.0", "24268a9284a1751f2ceda569cd978e1fa394c977c45c331bb52a405de544f4de", [:mix], [{:bunt, "~> 0.2", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "96d0ec5ecac8cf63142d02f16b7ab7152cf0f0f1a185a80161b758383c9399a8"}, + "jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"}, + "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"}, + "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, + "mox": {:hex, :mox, "1.0.2", "dc2057289ac478b35760ba74165b4b3f402f68803dd5aecd3bfd19c183815d64", [:mix], [], "hexpm", "f9864921b3aaf763c8741b5b8e6f908f44566f1e427b2630e89e9a73b981fef2"}, + "nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"}, "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"}, } diff --git a/test/support/functional_case.ex b/test/support/functional_case.ex index be29e97d..eae15632 100644 --- a/test/support/functional_case.ex +++ b/test/support/functional_case.ex @@ -19,6 +19,7 @@ defmodule SSHKit.FunctionalCase do end defmodule Host do + @moduledoc false defstruct [:id, :name, options: []] end From 2b9abd6fe787fe8f5429f97ef17b127d5d7b6059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Kn=C3=B6pfle?= Date: Wed, 11 Jan 2023 11:35:25 +0100 Subject: [PATCH 3/3] Fix credo --- test/sshkit/scp/upload_test.exs | 2 +- test/sshkit/ssh/channel_functional_test.exs | 10 ++++++---- test/sshkit/ssh_test.exs | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/test/sshkit/scp/upload_test.exs b/test/sshkit/scp/upload_test.exs index 3e3ea26d..8ac5ff29 100644 --- a/test/sshkit/scp/upload_test.exs +++ b/test/sshkit/scp/upload_test.exs @@ -79,7 +79,7 @@ defmodule SSHKit.SCP.UploadTest do acc: {:cont, state}, fun: handler -> assert connection == conn - assert command == SSHKit.SCP.Command.build(:upload, upload.target, upload.options) + assert command == Command.build(:upload, upload.target, upload.options) assert timeout == :infinity assert state == upload.state assert handler == upload.handler diff --git a/test/sshkit/ssh/channel_functional_test.exs b/test/sshkit/ssh/channel_functional_test.exs index d4cf6b6d..c8a8544f 100644 --- a/test/sshkit/ssh/channel_functional_test.exs +++ b/test/sshkit/ssh/channel_functional_test.exs @@ -3,25 +3,27 @@ defmodule SSHKit.SSH.ChannelFunctionalTest do use SSHKit.FunctionalCase, async: true + alias SSHKit.SSH.Channel + @bootconf [user: "me", password: "pass"] describe "Channel.subsystem/3" do @tag boot: [@bootconf] test "with user", %{hosts: [host]} do {:ok, conn} = SSHKit.SSH.connect(host.name, host.options) - {:ok, channel} = SSHKit.SSH.Channel.open(conn) - :success = SSHKit.SSH.Channel.subsystem(channel, "greeting-subsystem") + {:ok, channel} = Channel.open(conn) + :success = Channel.subsystem(channel, "greeting-subsystem") assert readline(channel) == "Hello, who am I talking to?\n" - :ok = SSHKit.SSH.Channel.send(channel, "Lorem\n") + :ok = Channel.send(channel, "Lorem\n") assert readline(channel) == "It's nice to meet you Lorem\n" end end defp readline(channel, message \\ "") do - {:ok, {:data, _channel, _type, next_line}} = SSHKit.SSH.Channel.recv(channel) + {:ok, {:data, _channel, _type, next_line}} = Channel.recv(channel) if String.ends_with?(next_line, "\n") do "#{message}#{next_line}" diff --git a/test/sshkit/ssh_test.exs b/test/sshkit/ssh_test.exs index 1e85d0ac..9c3fb66c 100644 --- a/test/sshkit/ssh_test.exs +++ b/test/sshkit/ssh_test.exs @@ -4,8 +4,8 @@ defmodule SSHKit.SSHTest do import SSHKit.SSH - alias SSHKit.SSH.Connection alias SSHKit.SSH.Channel + alias SSHKit.SSH.Connection @host "test.io" @user "me"