Skip to content

Commit

Permalink
Add docs/tests for CommandRunner
Browse files Browse the repository at this point in the history
  • Loading branch information
fhunleth committed May 14, 2019
1 parent 3c57f2b commit ec4d780
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 1 deletion.
33 changes: 32 additions & 1 deletion lib/vintage_net/interface/command_runner.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
defmodule VintageNet.Interface.CommandRunner do
alias VintageNet.Interface.RawConfig
@moduledoc """
The CommandRunner module runs commands specified in RawConfigs
See the `RawConfig` documentation for where lists of commands
are specified. The following commands are supported:
* `{:run, command, args}` - Run a system command
* `{:run_ignore_exit, command, args}` - Same as `:run`, but without the exit status check
* `{:fun, fun}` - Run an function
CommandRunner also implements RawConfig's file creation and
cleanup logic.
"""
require Logger
alias VintageNet.Interface.RawConfig

@doc """
Run a list of commands
Expand All @@ -19,6 +31,11 @@ defmodule VintageNet.Interface.CommandRunner do
end
end

@doc """
Run a command
Non-zero exit status will return an error.
"""
def run({:run, command, args}) do
case MuonTrap.cmd(command, args) do
{_, 0} ->
Expand All @@ -30,16 +47,29 @@ defmodule VintageNet.Interface.CommandRunner do
end
end

@doc """
Run a command and ignore its exit code
"""
def run({:run_ignore_errors, command, args}) do
_ = MuonTrap.cmd(command, args)
:ok
end

@doc """
Run an arbitrary function
In general, try to avoid using this. VintageNet's unit test strategy is
to verify configurations rather than verify the execution of the configurations.
Functions can't be checked that they were created correctly.
Functions must return `:ok` or `{:error, reason}`.
"""
def run({:fun, fun}) do
fun.()
end

@doc """
Create a list of files
"""
@spec create_files([RawConfig.file_contents()]) :: :ok
def create_files(file_contents) do
Expand All @@ -54,6 +84,7 @@ defmodule VintageNet.Interface.CommandRunner do
end

@doc """
Remove a list of files
"""
@spec remove_files([RawConfig.file_contents()]) :: :ok
def remove_files(file_contents) do
Expand Down
68 changes: 68 additions & 0 deletions test/vintage_net/interface/command_runner_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
defmodule VintageNet.Interface.CommandRunnerTest do
use VintageNetTest.Case
alias VintageNet.Interface.CommandRunner

test "creates and deletes files", context do
in_tmp(context.test, fn ->
file_list = [{"testing", "Hello, world"}]
:ok = CommandRunner.create_files(file_list)

assert File.exists?("testing")
assert File.read!("testing") == "Hello, world"

:ok = CommandRunner.remove_files(file_list)
refute File.exists?("testing")
end)
end

test "creates subdirectories if needed", context do
in_tmp(context.test, fn ->
file_list = [{"one/two/three/testing", "Hello, world"}]
:ok = CommandRunner.create_files(file_list)

assert File.exists?("one/two/three/testing")
assert File.read!("one/two/three/testing") == "Hello, world"

:ok = CommandRunner.remove_files(file_list)
refute File.exists?("one/two/three/testing")
end)
end

test "runs commands", context do
in_tmp(context.test, fn ->
:ok = CommandRunner.run([{:run, "touch", ["testing"]}, {:run, "touch", ["testing2"]}])

assert File.exists?("testing")
assert File.exists?("testing2")
end)
end

test "failed command stops list", context do
in_tmp(context.test, fn ->
{:error, _reason} = CommandRunner.run([{:run, "false", []}, {:run, "touch", ["testing"]}])

refute File.exists?("testing")
end)
end

test "can ignore failed commands", context do
in_tmp(context.test, fn ->
:ok = CommandRunner.run([{:run_ignore_errors, "false", []}, {:run, "touch", ["testing"]}])

assert File.exists?("testing")
end)
end

test "can run functions", context do
:ok =
CommandRunner.run([
{:fun,
fn ->
send(self(), :hello)
:ok
end}
])

assert_received :hello
end
end

0 comments on commit ec4d780

Please sign in to comment.