mirror of https://github.com/qwc/backive.git
A bunch of tests and mocking
This commit is contained in:
parent
8ca9615541
commit
9c5feeb672
14
backup.go
14
backup.go
|
@ -13,8 +13,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mockings
|
// Mockings
|
||||||
var mock_exec_Command = exec.Command
|
var mockExecCommand = exec.Command
|
||||||
var mock_cmd_Run = func(c *exec.Cmd) error {
|
var mockCmdRun = func(c *exec.Cmd) error {
|
||||||
return c.Run()
|
return c.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +81,8 @@ 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 := mock_exec_Command("chown", "-R", b.ExeUser, backupPath)
|
cmd := mockExecCommand("chown", "-R", b.ExeUser, backupPath)
|
||||||
err = mock_cmd_Run(cmd)
|
err = mockCmdRun(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
|
||||||
|
@ -107,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 := mock_exec_Command("/usr/bin/sh", b.ScriptPath)
|
cmd := mockExecCommand("/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 = mock_exec_Command("sudo", "-E", "-u", b.ExeUser, "/usr/bin/sh", b.ScriptPath)
|
cmd = mockExecCommand("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)
|
||||||
|
@ -129,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 := mock_cmd_Run(cmd)
|
err := mockCmdRun(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
|
||||||
|
|
|
@ -14,12 +14,6 @@ func getCurrentFilePath() string {
|
||||||
return file
|
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{}
|
||||||
|
|
||||||
|
@ -119,7 +113,7 @@ func setupNewTestEnv(subdir string) {
|
||||||
func TestPrepareRun(t *testing.T) {
|
func TestPrepareRun(t *testing.T) {
|
||||||
setupNewTestEnv("preparerun")
|
setupNewTestEnv("preparerun")
|
||||||
|
|
||||||
mock_cmd_Run = func(c *exec.Cmd) error {
|
mockCmdRun = func(c *exec.Cmd) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var testBkp = Backup{
|
var testBkp = Backup{
|
||||||
|
@ -142,7 +136,7 @@ func TestRun(t *testing.T) {
|
||||||
config.Devices["mytarget"].Name = "mytarget"
|
config.Devices["mytarget"].Name = "mytarget"
|
||||||
config.Devices["mytarget"].UUID = "123-456-789-abc-def"
|
config.Devices["mytarget"].UUID = "123-456-789-abc-def"
|
||||||
|
|
||||||
mock_cmd_Run = func(c *exec.Cmd) error {
|
mockCmdRun = func(c *exec.Cmd) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var testBkp = Backup{
|
var testBkp = Backup{
|
||||||
|
@ -167,7 +161,7 @@ func TestRun(t *testing.T) {
|
||||||
t.Logf("Error which should not occur: %s", err)
|
t.Logf("Error which should not occur: %s", err)
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
mock_cmd_Run = func(c *exec.Cmd) error {
|
mockCmdRun = func(c *exec.Cmd) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,9 @@ import (
|
||||||
"path"
|
"path"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var mockOsWriteFile = os.WriteFile
|
||||||
|
var mockOsReadFile = os.ReadFile
|
||||||
|
|
||||||
// Database is a simple string to string mapping, where arbitrary strings can be stored and safed to disk or loaded
|
// Database is a simple string to string mapping, where arbitrary strings can be stored and safed to disk or loaded
|
||||||
type Database struct {
|
type Database struct {
|
||||||
data map[string]string
|
data map[string]string
|
||||||
|
@ -23,7 +26,7 @@ func (d *Database) Save() {
|
||||||
log.Printf("Writing database output to file: %s", jsonstr)
|
log.Printf("Writing database output to file: %s", jsonstr)
|
||||||
saveDir, _ := path.Split(dbPath)
|
saveDir, _ := path.Split(dbPath)
|
||||||
CreateDirectoryIfNotExists(saveDir)
|
CreateDirectoryIfNotExists(saveDir)
|
||||||
err := os.WriteFile(dbPath, []byte(jsonstr), 0644)
|
err := mockOsWriteFile(dbPath, []byte(jsonstr), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +35,7 @@ func (d *Database) Save() {
|
||||||
// Load loads the database
|
// Load loads the database
|
||||||
func (d *Database) Load() {
|
func (d *Database) Load() {
|
||||||
if _, err := os.Stat(dbPath); err == nil {
|
if _, err := os.Stat(dbPath); err == nil {
|
||||||
data, rferr := os.ReadFile(dbPath)
|
data, rferr := mockOsReadFile(dbPath)
|
||||||
if rferr != nil {
|
if rferr != nil {
|
||||||
panic(rferr)
|
panic(rferr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package backive
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/fs"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDatabase(t *testing.T) {
|
||||||
|
mockOsStat = func(p string) (fs.FileInfo, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
db := new(Database)
|
||||||
|
mockOsReadFile = func(p string) ([]byte, error) {
|
||||||
|
return []byte("{}"), nil
|
||||||
|
}
|
||||||
|
db.Load()
|
||||||
|
|
||||||
|
mockOsWriteFile = func(p string, data []byte, rights fs.FileMode) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
db.Save()
|
||||||
|
}
|
|
@ -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 := mock_cmd_Run(cmd)
|
err := mockCmdRun(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 := mock_cmd_Run(sync)
|
syncErr := mockCmdRun(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 := mock_cmd_Run(cmd)
|
err := mockCmdRun(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package backive
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDevice(t *testing.T) {
|
||||||
|
testDevice := new(Device)
|
||||||
|
testDevice.Name = "Testdevice"
|
||||||
|
testDevice.UUID = "123-456-789-abc-def"
|
||||||
|
mockCmdRun = func(c *exec.Cmd) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err := testDevice.Mount()
|
||||||
|
if err != nil {
|
||||||
|
t.Log("Should not fail, is mocked.")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if !testDevice.IsMounted() {
|
||||||
|
t.Log("Should return true.")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
err = testDevice.Unmount()
|
||||||
|
if err != nil {
|
||||||
|
t.Log("Should not fail, is mocked.")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if testDevice.IsMounted() {
|
||||||
|
t.Log("Should return false.")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
29
events.go
29
events.go
|
@ -14,10 +14,12 @@ type EventHandler struct {
|
||||||
ls net.Listener
|
ls net.Listener
|
||||||
//done <-chan struct{}
|
//done <-chan struct{}
|
||||||
callbacks []func(map[string]string)
|
callbacks []func(map[string]string)
|
||||||
|
stop chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes the unix socket.
|
// Init initializes the unix socket.
|
||||||
func (eh *EventHandler) Init(socketPath string) {
|
func (eh *EventHandler) Init(socketPath string) {
|
||||||
|
eh.stop = make(chan bool)
|
||||||
log.Println("Initializing EventHandler...")
|
log.Println("Initializing EventHandler...")
|
||||||
var err error
|
var err error
|
||||||
dir, _ := path.Split(socketPath)
|
dir, _ := path.Split(socketPath)
|
||||||
|
@ -29,13 +31,28 @@ func (eh *EventHandler) Init(socketPath string) {
|
||||||
eh.callbacks = make([]func(map[string]string), 3)
|
eh.callbacks = make([]func(map[string]string), 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (eh *EventHandler) Stop() {
|
||||||
|
log.Println("Closing EventHandler")
|
||||||
|
eh.stop <- true
|
||||||
|
err := eh.ls.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Error closing the listener")
|
||||||
|
}
|
||||||
|
log.Println("Closed EventHandler")
|
||||||
|
}
|
||||||
|
|
||||||
// Listen starts the event loop.
|
// Listen starts the event loop.
|
||||||
func (eh *EventHandler) Listen() {
|
func (eh *EventHandler) Listen() {
|
||||||
log.Println("Running eventloop")
|
log.Println("Running eventloop")
|
||||||
func() {
|
func() {
|
||||||
for {
|
for {
|
||||||
|
select {
|
||||||
|
case <-eh.stop:
|
||||||
|
return
|
||||||
|
default:
|
||||||
eh.process()
|
eh.process()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,8 +66,14 @@ func (eh *EventHandler) process() {
|
||||||
client, err := eh.ls.Accept()
|
client, err := eh.ls.Accept()
|
||||||
log.Println("Accepted client")
|
log.Println("Accepted client")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
select {
|
||||||
|
case <-eh.stop:
|
||||||
|
return
|
||||||
|
default:
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
data := make([]byte, 2048)
|
data := make([]byte, 2048)
|
||||||
for {
|
for {
|
||||||
buf := make([]byte, 512)
|
buf := make([]byte, 512)
|
||||||
|
@ -67,15 +90,15 @@ func (eh *EventHandler) process() {
|
||||||
//log.Println(sdata)
|
//log.Println(sdata)
|
||||||
var message map[string]interface{}
|
var message map[string]interface{}
|
||||||
errjson := json.Unmarshal([]byte(sdata), &message)
|
errjson := json.Unmarshal([]byte(sdata), &message)
|
||||||
|
if errjson != nil {
|
||||||
|
log.Fatal(errjson)
|
||||||
|
}
|
||||||
var env = map[string]string{}
|
var env = map[string]string{}
|
||||||
if message["request"] == "udev" {
|
if message["request"] == "udev" {
|
||||||
for k, v := range message["data"].(map[string]interface{}) {
|
for k, v := range message["data"].(map[string]interface{}) {
|
||||||
env[k] = v.(string)
|
env[k] = v.(string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if errjson != nil {
|
|
||||||
log.Fatal(errjson)
|
|
||||||
}
|
|
||||||
for _, v := range eh.callbacks {
|
for _, v := range eh.callbacks {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
v(env)
|
v(env)
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
package backive
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEventhandler(t *testing.T) {
|
||||||
|
t.Skip("Do not get it to work...")
|
||||||
|
eh := new(EventHandler)
|
||||||
|
eh.Init("./backive.socket")
|
||||||
|
defer func() {
|
||||||
|
eh.Stop()
|
||||||
|
err := os.Remove("./backive.socket")
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
t.Log("Initialized test")
|
||||||
|
go eh.Listen()
|
||||||
|
t.Log("eh is listening")
|
||||||
|
var hasBeenCalled = make(chan bool)
|
||||||
|
eh.RegisterCallback(
|
||||||
|
func(m map[string]string) {
|
||||||
|
hasBeenCalled <- true
|
||||||
|
},
|
||||||
|
)
|
||||||
|
t.Log("registered callback")
|
||||||
|
beenCalled := false
|
||||||
|
var counter = 0
|
||||||
|
env := map[string]string{}
|
||||||
|
env["test"] = "test"
|
||||||
|
message := map[string]interface{}{}
|
||||||
|
message["request"] = "udev"
|
||||||
|
message["data"] = env
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case data := <-hasBeenCalled:
|
||||||
|
t.Log("receiving message")
|
||||||
|
beenCalled = data
|
||||||
|
if !beenCalled {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
t.Log("received message")
|
||||||
|
eh.Stop()
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
t.Logf("Waiting for callback %d", counter)
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
if counter == 2 {
|
||||||
|
sendDataToSocket("./backive.socket", message)
|
||||||
|
t.Log("sent message")
|
||||||
|
}
|
||||||
|
if counter < 10 {
|
||||||
|
counter++
|
||||||
|
} else {
|
||||||
|
t.Log("Stopping with Fail")
|
||||||
|
eh.Stop()
|
||||||
|
t.Fail()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendDataToSocket(socket string, message map[string]interface{}) {
|
||||||
|
c, err := net.Dial("unix", socket)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Could not instantiate unix socket. Aborting")
|
||||||
|
}
|
||||||
|
jsonstr, err := json.Marshal(message)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Could not convert to json. Aborting")
|
||||||
|
}
|
||||||
|
c.Write(jsonstr)
|
||||||
|
defer c.Close()
|
||||||
|
}
|
7
utils.go
7
utils.go
|
@ -5,12 +5,15 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var mockOsStat = os.Stat
|
||||||
|
var mockOsMkdirAll = os.MkdirAll
|
||||||
|
|
||||||
// CreateDirectoryIfNotExists Checks for a directory string and creates the directory if it does not exist, must be a absolute path.
|
// CreateDirectoryIfNotExists Checks for a directory string and creates the directory if it does not exist, must be a absolute path.
|
||||||
func CreateDirectoryIfNotExists(dir string) {
|
func CreateDirectoryIfNotExists(dir string) {
|
||||||
if _, err := os.Stat(dir); err == nil {
|
if _, err := mockOsStat(dir); err == nil {
|
||||||
//ignore
|
//ignore
|
||||||
} else if os.IsNotExist(err) {
|
} else if os.IsNotExist(err) {
|
||||||
os.MkdirAll(dir, 0755)
|
mockOsMkdirAll(dir, 0755)
|
||||||
} else {
|
} else {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue