Mocking exec.Cmd.Run() and new tests

This commit is contained in:
Marcel Otte 2022-01-10 23:03:14 +01:00
parent 5b14065b29
commit 8ca9615541
5 changed files with 98 additions and 17 deletions

View File

@ -12,6 +12,12 @@ import (
"time" "time"
) )
// Mockings
var mock_exec_Command = exec.Command
var mock_cmd_Run = func(c *exec.Cmd) error {
return c.Run()
}
// Backup contains all necessary information for executing a configured backup. // Backup contains all necessary information for executing a configured backup.
type Backup struct { type Backup struct {
Name string `mapstructure:",omitempty"` Name string `mapstructure:",omitempty"`
@ -75,12 +81,13 @@ func (b *Backup) PrepareRun() error {
} }
writer := io.MultiWriter(logfile) writer := io.MultiWriter(logfile)
b.logger = log.New(writer, b.Name, log.LstdFlags) b.logger = log.New(writer, b.Name, log.LstdFlags)
cmd := exec.Command("chown", "-R", b.ExeUser, backupPath) cmd := mock_exec_Command("chown", "-R", b.ExeUser, backupPath)
err = cmd.Run() err = mock_cmd_Run(cmd)
if err != nil { if err != nil {
b.logger.Printf("chown for backup directory failed: %s", err) b.logger.Printf("chown for backup directory failed: %s", err)
return err return err
} }
b.logger.Printf("Backup %s prepared.", b.Name)
return nil return nil
} }
@ -92,6 +99,7 @@ func (b *Backup) Run() error {
log.Printf("Device found: %s (%s).", dev.Name, dev.UUID) log.Printf("Device found: %s (%s).", dev.Name, dev.UUID)
} else { } else {
log.Printf("Device %s not found", b.TargetDevice) log.Printf("Device %s not found", b.TargetDevice)
return fmt.Errorf("device %s not found", b.TargetDevice)
} }
if ok && dev.IsMounted() { if ok && dev.IsMounted() {
if !strings.ContainsAny(b.ScriptPath, "/") || strings.HasPrefix(b.ScriptPath, ".") { if !strings.ContainsAny(b.ScriptPath, "/") || strings.HasPrefix(b.ScriptPath, ".") {
@ -99,10 +107,10 @@ func (b *Backup) Run() error {
log.Printf("ERROR: Script path is relative, aborting.") log.Printf("ERROR: Script path is relative, aborting.")
return fmt.Errorf("script path is relative, aborting") return fmt.Errorf("script path is relative, aborting")
} }
cmd := exec.Command("/usr/bin/sh", b.ScriptPath) cmd := mock_exec_Command("/usr/bin/sh", b.ScriptPath)
if b.ExeUser != "" { if b.ExeUser != "" {
// setup script environment including user to use // setup script environment including user to use
cmd = exec.Command("sudo", "-E", "-u", b.ExeUser, "/usr/bin/sh", b.ScriptPath) cmd = mock_exec_Command("sudo", "-E", "-u", b.ExeUser, "/usr/bin/sh", b.ScriptPath)
} }
b.logger.Printf("Running backup script of '%s'", b.Name) b.logger.Printf("Running backup script of '%s'", b.Name)
b.logger.Printf("Script is: %s", b.ScriptPath) b.logger.Printf("Script is: %s", b.ScriptPath)
@ -121,7 +129,7 @@ func (b *Backup) Run() error {
log.Printf("About to run: %s", cmd.String()) log.Printf("About to run: %s", cmd.String())
// run script // run script
err := cmd.Run() err := mock_cmd_Run(cmd)
if err != nil { if err != nil {
log.Printf("Backup '%s' run failed", b.Name) log.Printf("Backup '%s' run failed", b.Name)
return err return err

View File

@ -1,6 +1,24 @@
package backive package backive
import "testing" import (
"fmt"
"os/exec"
"path"
"runtime"
"testing"
)
func getCurrentFilePath() string {
pc, file, line, ok := runtime.Caller(1)
fmt.Printf("pc: %d, file: %s, line: %d, ok: %v\n", pc, file, line, ok)
return file
}
type MockCmd struct{}
func (c *MockCmd) Run() error {
return nil
}
func TestFindBackupsForDevice(t *testing.T) { func TestFindBackupsForDevice(t *testing.T) {
var testBackups = Backups{} var testBackups = Backups{}
@ -89,12 +107,67 @@ func TestCanRun(t *testing.T) {
} }
} }
func testPrepareRun() { func setupNewTestEnv(subdir string) {
/* file := getCurrentFilePath()
Need to mock: dir, _ := path.Split(file)
- config.Settings.SystemMountPoint (to local test directory) dir = path.Join(dir, "test", "_workarea", subdir)
- config.Settings.LogLocation (to local test directory) config.Settings.SystemMountPoint = path.Join(dir, "mnt")
- exec.Command! (to NOT really execute something) config.Settings.LogLocation = path.Join(dir, "log")
fmt.Printf("SystemMountPoint: %s, LogLocation: %s\n", config.Settings.SystemMountPoint, config.Settings.LogLocation)
*/ }
func TestPrepareRun(t *testing.T) {
setupNewTestEnv("preparerun")
mock_cmd_Run = func(c *exec.Cmd) error {
return nil
}
var testBkp = Backup{
Name: "testbkp",
TargetDevice: "mytarget",
TargetPath: "mypath",
}
err := testBkp.PrepareRun()
if err != nil {
t.Log("When this fails, something's fishy...")
t.Fail()
}
}
func TestRun(t *testing.T) {
setupNewTestEnv("run")
config.Devices = map[string]*Device{
"mytarget": new(Device),
}
config.Devices["mytarget"].Name = "mytarget"
config.Devices["mytarget"].UUID = "123-456-789-abc-def"
mock_cmd_Run = func(c *exec.Cmd) error {
return nil
}
var testBkp = Backup{
Name: "testbkp",
TargetDevice: "mytargets",
TargetPath: "mypath",
ScriptPath: "/dev/null",
SourcePath: "/dev/random",
}
err := testBkp.Run()
if err == nil || err.Error() != "device mytargets not found" {
if err != nil {
t.Logf("The error should be 'device mytargets not found', but is '%s'", err.Error())
t.Fail()
}
}
testBkp.TargetDevice = "mytarget"
config.Devices["mytarget"].Mount()
err = testBkp.PrepareRun()
err = testBkp.Run()
if err != nil {
t.Logf("Error which should not occur: %s", err)
t.Fail()
}
mock_cmd_Run = func(c *exec.Cmd) error {
return nil
}
} }

View File

@ -35,7 +35,7 @@ func (d *Device) Mount() error {
cmd.Stdout = log.Writer() cmd.Stdout = log.Writer()
cmd.Stderr = log.Writer() cmd.Stderr = log.Writer()
log.Printf("Command to execute: %s", cmd.String()) log.Printf("Command to execute: %s", cmd.String())
err := cmd.Run() err := mock_cmd_Run(cmd)
if err != nil { if err != nil {
log.Printf("Mounting failed with error %v", err) log.Printf("Mounting failed with error %v", err)
return err return err
@ -49,7 +49,7 @@ func (d *Device) Unmount() error {
if d.isMounted { if d.isMounted {
log.Printf("Unmounting %s", d.Name) log.Printf("Unmounting %s", d.Name)
sync := exec.Command("sync") sync := exec.Command("sync")
syncErr := sync.Run() syncErr := mock_cmd_Run(sync)
if syncErr != nil { if syncErr != nil {
log.Println(syncErr) log.Println(syncErr)
return syncErr return syncErr
@ -59,7 +59,7 @@ func (d *Device) Unmount() error {
path.Join(config.Settings.SystemMountPoint, d.Name), path.Join(config.Settings.SystemMountPoint, d.Name),
) )
log.Printf("About to run: %s", cmd.String()) log.Printf("About to run: %s", cmd.String())
err := cmd.Run() err := mock_cmd_Run(cmd)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
return err return err

0
test/_scripts/.keep Normal file
View File

View File