autorestic/internal/lock_test.go

173 lines
3.5 KiB
Go

package internal
import (
"os"
"os/exec"
"path"
"strconv"
"sync"
"testing"
"github.com/cupcakearmy/autorestic/internal/flags"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
)
// All tests must share the same lock file as it is only initialized once
func setup(t *testing.T) {
t.Helper()
cleanup := func() {
flags.LOCKFILE_PATH = ""
config = nil
once = sync.Once{}
viper.Reset()
}
cleanup()
d := t.TempDir()
viper.SetConfigFile(d + "/.autorestic.yml")
viper.Set("version", 2)
viper.WriteConfig()
t.Cleanup(cleanup)
}
func TestGetLockfilePath(t *testing.T) {
t.Run("user specified", func(t *testing.T) {
testCases := []struct {
name string
flag string
config string
expected string
}{
{
name: "flag and config",
flag: "/flag.lock.yml",
config: "/config.lock.yml",
expected: "/flag.lock.yml",
},
{
name: "flag only",
flag: "/flag.lock.yml",
config: "",
expected: "/flag.lock.yml",
},
{
name: "config only",
flag: "",
config: "/config.lock.yml",
expected: "/config.lock.yml",
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
setup(t)
flags.LOCKFILE_PATH = testCase.flag
if testCase.config != "" {
viper.Set("lockfile", testCase.config)
err := viper.WriteConfig()
assert.NoError(t, err)
}
p := getLockfilePath()
assert.Equal(t, testCase.expected, p)
})
}
})
t.Run("default", func(t *testing.T) {
setup(t)
configPath := viper.ConfigFileUsed()
expectedLockfile := path.Join(path.Dir(configPath), ".autorestic.lock.yml")
p := getLockfilePath()
assert.Equal(t, expectedLockfile, p)
})
}
func TestLock(t *testing.T) {
setup(t)
t.Run("getLock", func(t *testing.T) {
result := getLock().GetBool(RUNNING)
if result {
t.Errorf("got %v, want %v", result, false)
}
})
t.Run("lock", func(t *testing.T) {
lock, err := setLockValue(RUNNING, true)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
result := lock.GetBool(RUNNING)
if !result {
t.Errorf("got %v, want %v", result, true)
}
})
t.Run("unlock", func(t *testing.T) {
lock, err := setLockValue(RUNNING, false)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
result := lock.GetBool(RUNNING)
if result {
t.Errorf("got %v, want %v", result, false)
}
})
// locking a locked instance exits the instance
// this trick to capture os.Exit(1) is discussed here:
// https://talks.golang.org/2014/testing.slide#23
t.Run("lock twice", func(t *testing.T) {
if os.Getenv("CRASH") == "1" {
err := Lock()
if err != nil {
t.Errorf("unexpected error: %v", err)
}
// should fail
Lock()
}
cmd := exec.Command(os.Args[0], "-test.run=TestLock/lock_twice")
cmd.Env = append(os.Environ(), "CRASH=1")
err := cmd.Run()
err, ok := err.(*exec.ExitError)
if !ok {
t.Error("unexpected error")
}
expected := "exit status 1"
if err.Error() != expected {
t.Errorf("got %q, want %q", err.Error(), expected)
}
})
t.Run("set cron", func(t *testing.T) {
expected := int64(5)
SetCron("foo", expected)
result, err := strconv.ParseInt(getLock().GetString("cron.foo"), 10, 64)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if result != expected {
t.Errorf("got %d, want %d", result, expected)
}
})
t.Run("get cron", func(t *testing.T) {
expected := int64(5)
result := GetCron("foo")
if result != expected {
t.Errorf("got %d, want %d", result, expected)
}
})
}