Skip to content
This repository has been archived by the owner on May 15, 2024. It is now read-only.

refactor #101

Merged
merged 4 commits into from
Oct 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions pkg/backend/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const (
Arch
)

func DetectOS(execIF exec.Interface, fs afero.Fs) OS {
if darwin := DetectDarwin(execIF); darwin {
func DetectOS(exc exec.Interface, fs afero.Fs) OS {
if darwin := DetectDarwin(exc); darwin {
return Darwin
}
if manjaro := DetectArchLinux(fs); manjaro {
Expand All @@ -25,8 +25,8 @@ func DetectOS(execIF exec.Interface, fs afero.Fs) OS {
return Unknown
}

func DetectDarwin(execIF exec.Interface) bool {
out, err := execIF.Command("uname", "-a").Output()
func DetectDarwin(exc exec.Interface) bool {
out, err := exc.Command("uname", "-a").Output()
if err != nil {
return false
}
Expand Down
15 changes: 8 additions & 7 deletions pkg/exec/mock_exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package exec

import (
"context"
"syscall"
"io"
"syscall"

mock "github.com/stretchr/testify/mock"
)

Expand Down Expand Up @@ -83,7 +84,7 @@ type InterfaceCommandContextArgs struct {
}

type InterfaceCommandContextReturns struct {
Cmd func()Cmd
Cmd func() Cmd
}

type InterfaceCommandContextExpectation struct {
Expand Down Expand Up @@ -148,7 +149,7 @@ type InterfaceLookPathArgs struct {

type InterfaceLookPathReturns struct {
Path string
Err error
Err error
}

type InterfaceLookPathExpectation struct {
Expand Down Expand Up @@ -199,7 +200,7 @@ type MockCmd struct {

type CmdCombinedOutputReturns struct {
Output []byte
Err error
Err error
}

type CmdCombinedOutputExpectation struct {
Expand Down Expand Up @@ -241,7 +242,7 @@ func (_m *MockCmd) CombinedOutput() ([]byte, error) {

type CmdOutputReturns struct {
Output []byte
Err error
Err error
}

type CmdOutputExpectation struct {
Expand Down Expand Up @@ -521,7 +522,7 @@ func (_m *MockCmd) Start() error {

type CmdStderrPipeReturns struct {
Output io.ReadCloser
Err error
Err error
}

type CmdStderrPipeExpectation struct {
Expand Down Expand Up @@ -564,7 +565,7 @@ func (_m *MockCmd) StderrPipe() (io.ReadCloser, error) {

type CmdStdoutPipeReturns struct {
Output io.ReadCloser
Err error
Err error
}

type CmdStdoutPipeExpectation struct {
Expand Down
26 changes: 26 additions & 0 deletions pkg/operations/arch/handlers/check_install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//go:generate mockery -outpkg=mocks -case=snake -name=CheckInstallHandler

package handlers

import (
"context"

"github.com/raba-jp/primus/pkg/exec"
)

type CheckInstallHandler interface {
Run(ctx context.Context, name string) (ok bool)
}

type CheckInstallHandlerFunc func(ctx context.Context, name string) bool

func (f CheckInstallHandlerFunc) Run(ctx context.Context, name string) bool {
return f(ctx, name)
}

func NewCheckInstall(exc exec.Interface) CheckInstallHandler {
return CheckInstallHandlerFunc(func(ctx context.Context, name string) bool {
err := exc.CommandContext(ctx, "pacman", "-Qg", name).Run()
return err == nil
})
}
52 changes: 52 additions & 0 deletions pkg/operations/arch/handlers/check_install_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package handlers_test

import (
"context"
"testing"

"github.com/raba-jp/primus/pkg/exec"
"github.com/raba-jp/primus/pkg/operations/arch/handlers"
"github.com/stretchr/testify/assert"
)

func TestNewCheckInstall(t *testing.T) {
tests := []struct {
name string
mock exec.InterfaceCommandContextExpectation
want bool
}{
{
name: "success",
mock: exec.InterfaceCommandContextExpectation{
Args: exec.InterfaceCommandContextArgs{
CtxAnything: true,
Cmd: "pacman",
Args: []string{"-Qg", "base-devel"},
},
Returns: exec.InterfaceCommandContextReturns{
Cmd: func() exec.Cmd {
cmd := new(exec.MockCmd)
cmd.ApplyRunExpectation(exec.CmdRunExpectation{
Returns: exec.CmdRunReturns{
Err: nil,
},
})
return cmd
},
},
},
want: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
exc := new(exec.MockInterface)
exc.ApplyCommandContextExpectation(tt.mock)

checkInstall := handlers.NewCheckInstall(exc)
res := checkInstall.Run(context.Background(), "base-devel")
assert.Equal(t, tt.want, res)
})
}
}
50 changes: 50 additions & 0 deletions pkg/operations/arch/handlers/install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//go:generate mockery -outpkg=mocks -case=snake -name=InstallHandler

package handlers

import (
"context"
"time"

"github.com/raba-jp/primus/pkg/cli/ui"
"github.com/raba-jp/primus/pkg/exec"
"golang.org/x/xerrors"
)

const installTimeout = 5 * time.Minute

type InstallParams struct {
Name string
Option string
Cmd string
}

type InstallHandler interface {
Run(ctx context.Context, dryrun bool, p *InstallParams) (err error)
}

type InstallHandlerFunc func(ctx context.Context, dryrun bool, p *InstallParams) error

func (f InstallHandlerFunc) Run(ctx context.Context, dryrun bool, p *InstallParams) error {
return f(ctx, dryrun, p)
}

func NewInstall(checkInstall CheckInstallHandler, exc exec.Interface) InstallHandler {
return InstallHandlerFunc(func(ctx context.Context, dryrun bool, p *InstallParams) error {
if dryrun {
ui.Printf("pacman -S --noconfirm %s %s\n", p.Option, p.Name)
return nil
}

if installed := checkInstall.Run(ctx, p.Name); installed {
return nil
}

ctx, cancel := context.WithTimeout(ctx, installTimeout)
defer cancel()
if err := exc.CommandContext(ctx, "pacman", "-S", "--noconfirm", p.Option, p.Name).Run(); err != nil {
return xerrors.Errorf("Install package failed: %s: %w", p.Name, err)
}
return nil
})
}
140 changes: 140 additions & 0 deletions pkg/operations/arch/handlers/install_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package handlers_test

import (
"bytes"
"context"
"testing"

"github.com/raba-jp/primus/pkg/operations/arch/handlers"
"github.com/raba-jp/primus/pkg/operations/arch/handlers/mocks"

"github.com/raba-jp/primus/pkg/cli/ui"
"github.com/raba-jp/primus/pkg/exec"
"github.com/stretchr/testify/assert"
"golang.org/x/xerrors"
)

func TestNewInstall(t *testing.T) {
checkInstallArgs := mocks.CheckInstallHandlerRunArgs{
CtxAnything: true,
NameAnything: true,
}

tests := []struct {
name string
checkInstall mocks.CheckInstallHandlerRunExpectation
mock *exec.InterfaceCommandContextExpectation
errAssert assert.ErrorAssertionFunc
}{
{
name: "success",
checkInstall: mocks.CheckInstallHandlerRunExpectation{
Args: checkInstallArgs,
Returns: mocks.CheckInstallHandlerRunReturns{Ok: false},
},
mock: &exec.InterfaceCommandContextExpectation{
Args: exec.InterfaceCommandContextArgs{
CtxAnything: true,
Cmd: "pacman",
Args: []string{"-S", "--noconfirm", "options", "base-devel"},
},
Returns: exec.InterfaceCommandContextReturns{
Cmd: func() exec.Cmd {
cmd := new(exec.MockCmd)
cmd.ApplyRunExpectation(exec.CmdRunExpectation{
Returns: exec.CmdRunReturns{
Err: nil,
},
})
return cmd
},
},
},
errAssert: assert.NoError,
},
{
name: "success: already installed",
checkInstall: mocks.CheckInstallHandlerRunExpectation{
Args: checkInstallArgs,
Returns: mocks.CheckInstallHandlerRunReturns{Ok: true},
},
mock: nil,
errAssert: assert.NoError,
},
{
name: "error: install failed",
checkInstall: mocks.CheckInstallHandlerRunExpectation{
Args: checkInstallArgs,
Returns: mocks.CheckInstallHandlerRunReturns{Ok: false},
},
mock: &exec.InterfaceCommandContextExpectation{
Args: exec.InterfaceCommandContextArgs{
CtxAnything: true,
Cmd: "pacman",
Args: []string{"-S", "--noconfirm", "options", "base-devel"},
},
Returns: exec.InterfaceCommandContextReturns{
Cmd: func() exec.Cmd {
cmd := new(exec.MockCmd)
cmd.ApplyRunExpectation(exec.CmdRunExpectation{
Returns: exec.CmdRunReturns{
Err: xerrors.New("dummy"),
},
})
return cmd
},
},
},
errAssert: assert.Error,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
exc := new(exec.MockInterface)
if tt.mock != nil {
exc.ApplyCommandContextExpectation(*tt.mock)
}

handler := new(mocks.CheckInstallHandler)
handler.ApplyRunExpectation(tt.checkInstall)

install := handlers.NewInstall(handler, exc)
err := install.Run(context.Background(), false, &handlers.InstallParams{
Name: "base-devel",
Option: "options",
})
tt.errAssert(t, err)
})
}
}

func TestNewInstall__dryrun(t *testing.T) {
tests := []struct {
name string
params *handlers.InstallParams
want string
}{
{
name: "success",
params: &handlers.InstallParams{
Name: "pkg",
Option: "option",
},
want: "pacman -S --noconfirm option pkg\n",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
buf := new(bytes.Buffer)
ui.SetDefaultUI(&ui.CommandLine{Out: buf, Errout: buf})

handler := handlers.NewInstall(nil, nil)
err := handler.Run(context.Background(), true, tt.params)

assert.NoError(t, err)
assert.Equal(t, tt.want, buf.String())
})
}
}
Loading