diff --git a/.golangci.yml b/.golangci.yml index 6b9cf9d0..e69de29b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,54 +0,0 @@ -linters-settings: - govet: - check-shadowing: true - gocyclo: - min-complexity: 20 - dupl: - threshold: 100 - goconst: - min-len: 3 - min-occurrences: 3 - lll: - line-length: 160 - nakedret: - max-func-lines: 20 - gocritic: - enabled-tags: - - performance - - style - - diagnostic - disabled-checks: - - dupImport # https://github.com/go-critic/go-critic/issues/845 - settings: - rangeValCopy: - sizeThreshold: 512 - hugeParam: - sizeThreshold: 512 -linters: - enable-all: true - disable: - - interfacer - - scopelint - - golint - - maligned - - godot - - gochecknoglobals - - exhaustivestruct - - wsl - - nestif - - goerr113 - - nlreturn - - wrapcheck - - misspell - - cyclop - - whitespace - - paralleltest - - fast: false - -run: - tests: true - -issues: - exclude-use-default: true - diff --git a/config/mocks/NamedPropertySet.go b/config/mocks/NamedPropertySet.go index dd922974..d2a8fc80 100644 --- a/config/mocks/NamedPropertySet.go +++ b/config/mocks/NamedPropertySet.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/config/mocks/ProfileInfo.go b/config/mocks/ProfileInfo.go index f60e7e12..df08131c 100644 --- a/config/mocks/ProfileInfo.go +++ b/config/mocks/ProfileInfo.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/config/mocks/PropertyInfo.go b/config/mocks/PropertyInfo.go index 0741bfa6..19e15a1b 100644 --- a/config/mocks/PropertyInfo.go +++ b/config/mocks/PropertyInfo.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/config/mocks/SectionInfo.go b/config/mocks/SectionInfo.go index d7ef7ff5..38dd7bc9 100644 --- a/config/mocks/SectionInfo.go +++ b/config/mocks/SectionInfo.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/lock/lock_test.go b/lock/lock_test.go index d45b645e..e50a64ff 100644 --- a/lock/lock_test.go +++ b/lock/lock_test.go @@ -8,33 +8,45 @@ import ( "os/signal" "path/filepath" "regexp" - "runtime" "syscall" "testing" "time" + "github.com/creativeprojects/resticprofile/platform" "github.com/creativeprojects/resticprofile/shell" "github.com/shirou/gopsutil/v3/process" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -const ( +var ( helperBinary = "./locktest" ) -func init() { - if runtime.GOOS == "windows" { - return +func TestMain(m *testing.M) { + if platform.IsWindows() { + helperBinary = `.\locktest.exe` } - // compile helper command cmd := exec.Command("go", "build", "-o", helperBinary, "./test") - cmd.Run() + if err := cmd.Run(); err != nil { + fmt.Fprintf(os.Stderr, "Error building helper binary: %s\n", err) + } + m.Run() + _ = os.Remove(helperBinary) } -func TestLockIsAvailable(t *testing.T) { - tempfile := filepath.Join(os.TempDir(), fmt.Sprintf("%s%d%d.tmp", "TestLockIsAvailable", time.Now().UnixNano(), os.Getpid())) +func getTempfile(t *testing.T) string { + t.Helper() + + tempfile := filepath.Join(t.TempDir(), fmt.Sprintf("%s.tmp", t.Name())) t.Log("Using temporary file", tempfile) + return tempfile +} + +func TestLockIsAvailable(t *testing.T) { + t.Parallel() + + tempfile := getTempfile(t) lock := NewLock(tempfile) defer lock.Release() @@ -42,8 +54,9 @@ func TestLockIsAvailable(t *testing.T) { } func TestLockIsNotAvailable(t *testing.T) { - tempfile := filepath.Join(os.TempDir(), fmt.Sprintf("%s%d%d.tmp", "TestLockIsNotAvailable", time.Now().UnixNano(), os.Getpid())) - t.Log("Using temporary file", tempfile) + t.Parallel() + + tempfile := getTempfile(t) lock := NewLock(tempfile) defer lock.Release() @@ -62,8 +75,9 @@ func TestLockIsNotAvailable(t *testing.T) { } func TestNoPID(t *testing.T) { - tempfile := filepath.Join(os.TempDir(), fmt.Sprintf("%s%d%d.tmp", "TestNoPID", time.Now().UnixNano(), os.Getpid())) - t.Log("Using temporary file", tempfile) + t.Parallel() + + tempfile := getTempfile(t) lock := NewLock(tempfile) defer lock.Release() lock.TryAcquire() @@ -77,8 +91,9 @@ func TestNoPID(t *testing.T) { } func TestSetOnePID(t *testing.T) { - tempfile := filepath.Join(os.TempDir(), fmt.Sprintf("%s%d%d.tmp", "TestSetPID", time.Now().UnixNano(), os.Getpid())) - t.Log("Using temporary file", tempfile) + t.Parallel() + + tempfile := getTempfile(t) lock := NewLock(tempfile) defer lock.Release() lock.TryAcquire() @@ -93,8 +108,9 @@ func TestSetOnePID(t *testing.T) { } func TestSetMorePID(t *testing.T) { - tempfile := filepath.Join(os.TempDir(), fmt.Sprintf("%s%d%d.tmp", "TestSetMorePID", time.Now().UnixNano(), os.Getpid())) - t.Log("Using temporary file", tempfile) + t.Parallel() + + tempfile := getTempfile(t) lock := NewLock(tempfile) defer lock.Release() lock.TryAcquire() @@ -110,52 +126,14 @@ func TestSetMorePID(t *testing.T) { assert.Equal(t, int32(13), pid) } -// This test is using the shell package. This is just a convenient wrapper around cmd.exe and sh -func TestProcessFinished(t *testing.T) { - childPID := 0 - buffer := &bytes.Buffer{} - - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) - defer signal.Reset(os.Interrupt) - - cmd := shell.NewSignalledCommand("echo", []string{"Hello World!"}, c) - cmd.Stdout = buffer - cmd.SetPID = func(pid int) { - childPID = pid - } - _, _, err := cmd.Run() - if err != nil { - t.Fatal(err) - } - - // at that point, the child process should be finished - running, err := process.PidExists(int32(childPID)) - assert.NoError(t, err) - assert.False(t, running) -} +func TestProcessPID(t *testing.T) { + t.Parallel() -// This test is using the shell package. This is just a convenient wrapper around cmd.exe and sh -func TestProcessNotFinished(t *testing.T) { childPID := 0 buffer := &bytes.Buffer{} - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) - defer signal.Reset(os.Interrupt) - - // use ping to make sure the process is running for long enough to check its existence - var parameters []string - if runtime.GOOS == "windows" { - // it will run for 1 second - parameters = []string{"-n", "2", "127.0.0.1"} - } else { - // run for 200ms (don't need a whole second) - // 0.2 is the minimum in linux, 0.1 in darwin - parameters = []string{"-c", "2", "-i", "0.2", "127.0.0.1"} - } - - cmd := shell.NewSignalledCommand("ping", parameters, c) + // use the lock helper binary (we only need to wait for some time, we don't need the locking part) + cmd := shell.NewCommand(helperBinary, []string{"-wait", "200", "-lock", filepath.Join(t.TempDir(), t.Name())}) cmd.Stdout = buffer // SetPID method is called right after we forked and have a PID available cmd.SetPID = func(pid int) { @@ -165,9 +143,7 @@ func TestProcessNotFinished(t *testing.T) { assert.True(t, running) } _, _, err := cmd.Run() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) // at that point, the child process should be finished running, err := process.PidExists(int32(childPID)) @@ -176,8 +152,9 @@ func TestProcessNotFinished(t *testing.T) { } func TestForceLockIsAvailable(t *testing.T) { - tempfile := filepath.Join(os.TempDir(), fmt.Sprintf("%s%d%d.tmp", "TestForceLockIsAvailable", time.Now().UnixNano(), os.Getpid())) - t.Log("Using temporary file", tempfile) + t.Parallel() + + tempfile := getTempfile(t) lock := NewLock(tempfile) defer lock.Release() @@ -185,8 +162,9 @@ func TestForceLockIsAvailable(t *testing.T) { } func TestForceLockWithNoPID(t *testing.T) { - tempfile := filepath.Join(os.TempDir(), fmt.Sprintf("%s%d%d.tmp", "TestForceLockWithNoPID", time.Now().UnixNano(), os.Getpid())) - t.Log("Using temporary file", tempfile) + t.Parallel() + + tempfile := getTempfile(t) lock := NewLock(tempfile) defer lock.Release() @@ -199,10 +177,10 @@ func TestForceLockWithNoPID(t *testing.T) { assert.False(t, other.HasLocked()) } -// This test is using the shell package. This is just a convenient wrapper around cmd.exe and sh func TestForceLockWithExpiredPID(t *testing.T) { - tempfile := filepath.Join(os.TempDir(), fmt.Sprintf("%s%d%d.tmp", "TestForceLockWithExpiredPID", time.Now().UnixNano(), os.Getpid())) - t.Log("Using temporary file", tempfile) + t.Parallel() + + tempfile := getTempfile(t) lock := NewLock(tempfile) defer lock.Release() @@ -217,9 +195,8 @@ func TestForceLockWithExpiredPID(t *testing.T) { cmd := shell.NewSignalledCommand("echo", []string{"Hello World!"}, c) cmd.SetPID = lock.SetPID _, _, err := cmd.Run() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + // child process should be finished // let's close the lockfile handle manually (unix doesn't actually care, but windows would complain) lock.file.Close() @@ -230,33 +207,18 @@ func TestForceLockWithExpiredPID(t *testing.T) { assert.True(t, other.HasLocked()) } -// This test is using the shell package. This is just a convenient wrapper around cmd.exe and sh func TestForceLockWithRunningPID(t *testing.T) { - tempfile := filepath.Join(os.TempDir(), fmt.Sprintf("%s%d%d.tmp", "TestForceLockWithRunningPID", time.Now().UnixNano(), os.Getpid())) - t.Log("Using temporary file", tempfile) + t.Parallel() + + tempfile := getTempfile(t) lock := NewLock(tempfile) defer lock.Release() assert.True(t, lock.TryAcquire()) assert.True(t, lock.HasLocked()) - // run a child process - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) - defer signal.Reset(os.Interrupt) - - // use ping to make sure the process is running for long enough to check its existence - var parameters []string - if runtime.GOOS == "windows" { - // it will run for 1 second - parameters = []string{"-n", "2", "127.0.0.1"} - } else { - // run for 200ms (don't need a whole second) - // 0.2 is the minimum in linux, 0.1 in darwin - parameters = []string{"-c", "2", "-i", "0.2", "127.0.0.1"} - } - - cmd := shell.NewSignalledCommand("ping", parameters, c) + // user the lock helper binary (we only need to wait for some time, we don't need the locking part) + cmd := shell.NewCommand(helperBinary, []string{"-wait", "100", "-lock", filepath.Join(t.TempDir(), t.Name())}) cmd.SetPID = func(pid int) { lock.SetPID(pid) // make sure we cannot break the lock right now @@ -266,18 +228,16 @@ func TestForceLockWithRunningPID(t *testing.T) { assert.False(t, other.HasLocked()) } _, _, err := cmd.Run() - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) } func TestLockWithNoInterruption(t *testing.T) { - if runtime.GOOS == "windows" { + t.Parallel() + + if platform.IsWindows() { t.Skip("cannot send a signal to a child process in Windows") } - lockfile := "TestLockWithNoInterruption.lock" - // make sure there's no remaining lockfile from a failed test - _ = os.Remove(lockfile) + lockfile := getTempfile(t) var err error buffer := &bytes.Buffer{} @@ -291,23 +251,23 @@ func TestLockWithNoInterruption(t *testing.T) { } func TestLockIsRemovedAfterInterruptSignal(t *testing.T) { - if runtime.GOOS == "windows" { + t.Parallel() + + if platform.IsWindows() { t.Skip("cannot send a signal to a child process in Windows") } - lockfile := "TestLockIsRemovedAfterInterruptSignal.lock" - // make sure there's no remaining lockfile from a failed test - _ = os.Remove(lockfile) + lockfile := getTempfile(t) var err error buffer := &bytes.Buffer{} - cmd := exec.Command(helperBinary, "-wait", "400", "-lock", lockfile) + cmd := exec.Command(helperBinary, "-wait", "2000", "-lock", lockfile) cmd.Stdout = buffer cmd.Stderr = buffer err = cmd.Start() require.NoError(t, err) - time.Sleep(100 * time.Millisecond) + time.Sleep(200 * time.Millisecond) err = cmd.Process.Signal(syscall.SIGINT) require.NoError(t, err) @@ -317,23 +277,23 @@ func TestLockIsRemovedAfterInterruptSignal(t *testing.T) { } func TestLockIsRemovedAfterInterruptSignalInsideShell(t *testing.T) { - if runtime.GOOS == "windows" { + t.Parallel() + + if platform.IsWindows() { t.Skip("cannot send a signal to a child process in Windows") } - lockfile := "TestLockIsRemovedAfterInterruptSignal.lock" - // make sure there's no remaining lockfile from a failed test - _ = os.Remove(lockfile) + lockfile := getTempfile(t) var err error buffer := &bytes.Buffer{} - cmd := exec.Command(helperBinary, "-wait", "600", "-lock", lockfile) + cmd := exec.Command("sh", "-c", "exec "+helperBinary+" -wait 2000 -lock "+lockfile) cmd.Stdout = buffer cmd.Stderr = buffer err = cmd.Start() require.NoError(t, err) - time.Sleep(100 * time.Millisecond) + time.Sleep(200 * time.Millisecond) err = cmd.Process.Signal(syscall.SIGINT) require.NoError(t, err) diff --git a/monitor/mocks/OutputAnalysis.go b/monitor/mocks/OutputAnalysis.go index 28dd1393..b81bc16f 100644 --- a/monitor/mocks/OutputAnalysis.go +++ b/monitor/mocks/OutputAnalysis.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks diff --git a/schedule/mocks/Handler.go b/schedule/mocks/Handler.go index ab2c8b9c..74971545 100644 --- a/schedule/mocks/Handler.go +++ b/schedule/mocks/Handler.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.1. DO NOT EDIT. +// Code generated by mockery v2.43.2. DO NOT EDIT. package mocks