feat: initial public version
This commit is contained in:
31
execy/execy.go
Normal file
31
execy/execy.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// Package execy runs external commands.
|
||||
package execy
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
var runner = Runner(&osRunner{})
|
||||
|
||||
// Runner executes external commands.
|
||||
type Runner interface {
|
||||
Run(cmd *exec.Cmd) error
|
||||
}
|
||||
|
||||
// osRunner runs OS programs.
|
||||
type osRunner struct{}
|
||||
|
||||
func (r *osRunner) Run(cmd *exec.Cmd) error {
|
||||
return cmd.Run()
|
||||
}
|
||||
|
||||
func Run(cmd *exec.Cmd) error {
|
||||
return runner.Run(cmd)
|
||||
}
|
||||
|
||||
// CmdOut represents the result of the command run.
|
||||
type CmdOut struct {
|
||||
Stdout string
|
||||
Stderr string
|
||||
Err error
|
||||
}
|
||||
29
execy/execy_test.go
Normal file
29
execy/execy_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package execy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRunner(t *testing.T) {
|
||||
const want = "hello world"
|
||||
ctx := context.Background()
|
||||
cmd := exec.CommandContext(ctx, "echo", "-n", want)
|
||||
outb := new(strings.Builder)
|
||||
errb := new(strings.Builder)
|
||||
cmd.Stdout = outb
|
||||
cmd.Stderr = errb
|
||||
|
||||
err := Run(cmd)
|
||||
if err != nil {
|
||||
t.Fatalf("Err: expected nil, got %v", err)
|
||||
}
|
||||
if outb.String() != want {
|
||||
t.Errorf("Stdout: expected %q, got %q", want, outb.String())
|
||||
}
|
||||
if errb.String() != "" {
|
||||
t.Errorf("Stderr: expected %q, got %q", "", errb.String())
|
||||
}
|
||||
}
|
||||
44
execy/mock.go
Normal file
44
execy/mock.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package execy
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/nalgeon/codapi/logx"
|
||||
)
|
||||
|
||||
// Mock installs mock outputs for given commands.
|
||||
func Mock(commands map[string]CmdOut) *logx.Memory {
|
||||
if commands != nil {
|
||||
mockCommands = commands
|
||||
}
|
||||
mem := logx.NewMemory("exec")
|
||||
runner = &mockRunner{mem}
|
||||
return mem
|
||||
}
|
||||
|
||||
// mockRunner returns mock outputs
|
||||
// without running OS programs.
|
||||
type mockRunner struct {
|
||||
mem *logx.Memory
|
||||
}
|
||||
|
||||
// Run returns a mock output from the registry
|
||||
// that matches the given command name and argument.
|
||||
func (r *mockRunner) Run(cmd *exec.Cmd) error {
|
||||
cmdStr := strings.Join(cmd.Args, " ")
|
||||
r.mem.WriteString(cmdStr)
|
||||
|
||||
key := cmd.Args[0] + " " + cmd.Args[1]
|
||||
out, ok := mockCommands[key]
|
||||
if !ok {
|
||||
// command is not in the registry,
|
||||
// so let's return an empty "success" result
|
||||
out = CmdOut{}
|
||||
}
|
||||
_, _ = cmd.Stdout.Write([]byte(out.Stdout))
|
||||
_, _ = cmd.Stderr.Write([]byte(out.Stderr))
|
||||
return out.Err
|
||||
}
|
||||
|
||||
var mockCommands map[string]CmdOut = map[string]CmdOut{}
|
||||
33
execy/mock_test.go
Normal file
33
execy/mock_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package execy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMock(t *testing.T) {
|
||||
const want = "hello world"
|
||||
out := CmdOut{Stdout: want, Stderr: "", Err: nil}
|
||||
mem := Mock(map[string]CmdOut{"echo -n": out})
|
||||
|
||||
ctx := context.Background()
|
||||
cmd := exec.CommandContext(ctx, "echo", "-n", want)
|
||||
outb := new(strings.Builder)
|
||||
errb := new(strings.Builder)
|
||||
cmd.Stdout = outb
|
||||
cmd.Stderr = errb
|
||||
|
||||
err := Run(cmd)
|
||||
if err != nil {
|
||||
t.Fatalf("Err: expected nil, got %v", err)
|
||||
}
|
||||
if outb.String() != want {
|
||||
t.Errorf("Stdout: expected %q, got %q", want, outb.String())
|
||||
}
|
||||
if errb.String() != "" {
|
||||
t.Errorf("Stderr: expected %q, got %q", "", errb.String())
|
||||
}
|
||||
mem.MustHave(t, "echo -n hello world")
|
||||
}
|
||||
Reference in New Issue
Block a user