From 8ca9615541e6a59382d589dbdb44c9fa7359359b Mon Sep 17 00:00:00 2001 From: Marcel Otte Date: Mon, 10 Jan 2022 23:03:14 +0100 Subject: [PATCH] Mocking exec.Cmd.Run() and new tests --- backup.go | 18 +++++-- backup_test.go | 91 +++++++++++++++++++++++++++++---- device.go | 6 +-- test/_scripts/.keep | 0 test/_workarea/preparerun/.keep | 0 5 files changed, 98 insertions(+), 17 deletions(-) create mode 100644 test/_scripts/.keep create mode 100644 test/_workarea/preparerun/.keep diff --git a/backup.go b/backup.go index 89763d8..731fbec 100644 --- a/backup.go +++ b/backup.go @@ -12,6 +12,12 @@ import ( "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. type Backup struct { Name string `mapstructure:",omitempty"` @@ -75,12 +81,13 @@ func (b *Backup) PrepareRun() error { } writer := io.MultiWriter(logfile) b.logger = log.New(writer, b.Name, log.LstdFlags) - cmd := exec.Command("chown", "-R", b.ExeUser, backupPath) - err = cmd.Run() + cmd := mock_exec_Command("chown", "-R", b.ExeUser, backupPath) + err = mock_cmd_Run(cmd) if err != nil { b.logger.Printf("chown for backup directory failed: %s", err) return err } + b.logger.Printf("Backup %s prepared.", b.Name) return nil } @@ -92,6 +99,7 @@ func (b *Backup) Run() error { log.Printf("Device found: %s (%s).", dev.Name, dev.UUID) } else { log.Printf("Device %s not found", b.TargetDevice) + return fmt.Errorf("device %s not found", b.TargetDevice) } if ok && dev.IsMounted() { 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.") 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 != "" { // 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("Script is: %s", b.ScriptPath) @@ -121,7 +129,7 @@ func (b *Backup) Run() error { log.Printf("About to run: %s", cmd.String()) // run script - err := cmd.Run() + err := mock_cmd_Run(cmd) if err != nil { log.Printf("Backup '%s' run failed", b.Name) return err diff --git a/backup_test.go b/backup_test.go index 25c2be9..7c7389e 100644 --- a/backup_test.go +++ b/backup_test.go @@ -1,6 +1,24 @@ 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) { var testBackups = Backups{} @@ -89,12 +107,67 @@ func TestCanRun(t *testing.T) { } } -func testPrepareRun() { - /* - Need to mock: - - config.Settings.SystemMountPoint (to local test directory) - - config.Settings.LogLocation (to local test directory) - - exec.Command! (to NOT really execute something) - - */ +func setupNewTestEnv(subdir string) { + file := getCurrentFilePath() + dir, _ := path.Split(file) + dir = path.Join(dir, "test", "_workarea", subdir) + config.Settings.SystemMountPoint = path.Join(dir, "mnt") + 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 + } } diff --git a/device.go b/device.go index dc39c68..1dda358 100644 --- a/device.go +++ b/device.go @@ -35,7 +35,7 @@ func (d *Device) Mount() error { cmd.Stdout = log.Writer() cmd.Stderr = log.Writer() log.Printf("Command to execute: %s", cmd.String()) - err := cmd.Run() + err := mock_cmd_Run(cmd) if err != nil { log.Printf("Mounting failed with error %v", err) return err @@ -49,7 +49,7 @@ func (d *Device) Unmount() error { if d.isMounted { log.Printf("Unmounting %s", d.Name) sync := exec.Command("sync") - syncErr := sync.Run() + syncErr := mock_cmd_Run(sync) if syncErr != nil { log.Println(syncErr) return syncErr @@ -59,7 +59,7 @@ func (d *Device) Unmount() error { path.Join(config.Settings.SystemMountPoint, d.Name), ) log.Printf("About to run: %s", cmd.String()) - err := cmd.Run() + err := mock_cmd_Run(cmd) if err != nil { log.Println(err) return err diff --git a/test/_scripts/.keep b/test/_scripts/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/_workarea/preparerun/.keep b/test/_workarea/preparerun/.keep new file mode 100644 index 0000000..e69de29