Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor unit tests on package lock #374

Merged
merged 4 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/mocks/NamedPropertySet.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion config/mocks/ProfileInfo.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion config/mocks/PropertyInfo.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion config/mocks/SectionInfo.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

130 changes: 61 additions & 69 deletions lock/lock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,51 @@ 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
if platform.IsWindows() {
helperBinary += ".exe"
creativeprojects marked this conversation as resolved.
Show resolved Hide resolved
}
// compile helper command
cmd := exec.Command("go", "build", "-o", helperBinary, "./test")
cmd.Run()
}

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()

assert.True(t, lock.TryAcquire())
}

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()

Expand All @@ -62,8 +71,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()
Expand All @@ -77,8 +87,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()
Expand All @@ -93,8 +104,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()
Expand All @@ -110,8 +122,9 @@ 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) {
t.Parallel()

childPID := 0
buffer := &bytes.Buffer{}

Expand All @@ -135,27 +148,18 @@ func TestProcessFinished(t *testing.T) {
assert.False(t, running)
}

// This test is using the shell package. This is just a convenient wrapper around cmd.exe and sh
func TestProcessNotFinished(t *testing.T) {
t.Parallel()

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)
// user the lock helper binary (we only need to wait for some time, we don't need the locking part)
cmd := shell.NewSignalledCommand(helperBinary, []string{"-wait", "100", "-lock", t.Name()}, c)
cmd.Stdout = buffer
// SetPID method is called right after we forked and have a PID available
cmd.SetPID = func(pid int) {
Expand All @@ -165,9 +169,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))
Expand All @@ -176,17 +178,19 @@ 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()

assert.True(t, lock.ForceAcquire())
}

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()

Expand All @@ -199,10 +203,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()

Expand Down Expand Up @@ -230,10 +234,10 @@ 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()

Expand All @@ -245,18 +249,8 @@ func TestForceLockWithRunningPID(t *testing.T) {
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.NewSignalledCommand(helperBinary, []string{"-wait", "100", "-lock", t.Name()}, c)
cmd.SetPID = func(pid int) {
lock.SetPID(pid)
// make sure we cannot break the lock right now
Expand All @@ -266,18 +260,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{}
Expand All @@ -291,12 +283,12 @@ 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{}
Expand All @@ -317,12 +309,12 @@ 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{}
Expand Down
2 changes: 1 addition & 1 deletion monitor/mocks/OutputAnalysis.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion schedule/mocks/Handler.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading