mirror of
https://github.com/restic/restic.git
synced 2025-12-04 03:38:25 +00:00
Add locking functions
This commit is contained in:
170
lock_test.go
Normal file
170
lock_test.go
Normal file
@@ -0,0 +1,170 @@
|
||||
package restic_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/restic/restic"
|
||||
"github.com/restic/restic/backend"
|
||||
"github.com/restic/restic/repository"
|
||||
. "github.com/restic/restic/test"
|
||||
)
|
||||
|
||||
func TestLock(t *testing.T) {
|
||||
repo := SetupRepo()
|
||||
defer TeardownRepo(repo)
|
||||
|
||||
lock, err := restic.NewLock(repo)
|
||||
OK(t, err)
|
||||
|
||||
OK(t, lock.Unlock())
|
||||
}
|
||||
|
||||
func TestDoubleUnlock(t *testing.T) {
|
||||
repo := SetupRepo()
|
||||
defer TeardownRepo(repo)
|
||||
|
||||
lock, err := restic.NewLock(repo)
|
||||
OK(t, err)
|
||||
|
||||
OK(t, lock.Unlock())
|
||||
|
||||
err = lock.Unlock()
|
||||
Assert(t, err != nil,
|
||||
"double unlock didn't return an error, got %v", err)
|
||||
}
|
||||
|
||||
func TestMultipleLock(t *testing.T) {
|
||||
repo := SetupRepo()
|
||||
defer TeardownRepo(repo)
|
||||
|
||||
lock1, err := restic.NewLock(repo)
|
||||
OK(t, err)
|
||||
|
||||
lock2, err := restic.NewLock(repo)
|
||||
OK(t, err)
|
||||
|
||||
OK(t, lock1.Unlock())
|
||||
OK(t, lock2.Unlock())
|
||||
}
|
||||
|
||||
func TestLockExclusive(t *testing.T) {
|
||||
repo := SetupRepo()
|
||||
defer TeardownRepo(repo)
|
||||
|
||||
elock, err := restic.NewExclusiveLock(repo)
|
||||
OK(t, err)
|
||||
OK(t, elock.Unlock())
|
||||
}
|
||||
|
||||
func TestLockOnExclusiveLockedRepo(t *testing.T) {
|
||||
repo := SetupRepo()
|
||||
defer TeardownRepo(repo)
|
||||
|
||||
elock, err := restic.NewExclusiveLock(repo)
|
||||
OK(t, err)
|
||||
|
||||
lock, err := restic.NewLock(repo)
|
||||
Assert(t, err == restic.ErrAlreadyLocked,
|
||||
"create normal lock with exclusively locked repo didn't return an error")
|
||||
|
||||
OK(t, lock.Unlock())
|
||||
OK(t, elock.Unlock())
|
||||
}
|
||||
|
||||
func TestExclusiveLockOnLockedRepo(t *testing.T) {
|
||||
repo := SetupRepo()
|
||||
defer TeardownRepo(repo)
|
||||
|
||||
elock, err := restic.NewLock(repo)
|
||||
OK(t, err)
|
||||
|
||||
lock, err := restic.NewExclusiveLock(repo)
|
||||
Assert(t, err == restic.ErrAlreadyLocked,
|
||||
"create exclusive lock with locked repo didn't return an error")
|
||||
|
||||
OK(t, lock.Unlock())
|
||||
OK(t, elock.Unlock())
|
||||
}
|
||||
|
||||
func createFakeLock(repo *repository.Repository, t time.Time, pid int) (backend.ID, error) {
|
||||
newLock := &restic.Lock{Time: t, PID: pid}
|
||||
return repo.SaveJSONUnpacked(backend.Lock, &newLock)
|
||||
}
|
||||
|
||||
func removeLock(repo *repository.Repository, id backend.ID) error {
|
||||
return repo.Backend().Remove(backend.Lock, id.String())
|
||||
}
|
||||
|
||||
var staleLockTests = []struct {
|
||||
timestamp time.Time
|
||||
stale bool
|
||||
pid int
|
||||
}{
|
||||
{
|
||||
timestamp: time.Now(),
|
||||
stale: false,
|
||||
pid: os.Getpid(),
|
||||
},
|
||||
{
|
||||
timestamp: time.Now().Add(-time.Hour),
|
||||
stale: true,
|
||||
pid: os.Getpid(),
|
||||
},
|
||||
{
|
||||
timestamp: time.Now().Add(3 * time.Minute),
|
||||
stale: false,
|
||||
pid: os.Getpid(),
|
||||
},
|
||||
{
|
||||
timestamp: time.Now(),
|
||||
stale: true,
|
||||
pid: os.Getpid() + 500,
|
||||
},
|
||||
}
|
||||
|
||||
func TestLockStale(t *testing.T) {
|
||||
for i, test := range staleLockTests {
|
||||
lock := restic.Lock{
|
||||
Time: test.timestamp,
|
||||
PID: test.pid,
|
||||
}
|
||||
|
||||
Assert(t, lock.Stale() == test.stale,
|
||||
"TestStaleLock: test %d failed: expected stale: %v, got %v",
|
||||
i, test.stale, !test.stale)
|
||||
}
|
||||
}
|
||||
|
||||
func lockExists(repo *repository.Repository, t testing.TB, id backend.ID) bool {
|
||||
exists, err := repo.Backend().Test(backend.Lock, id.String())
|
||||
OK(t, err)
|
||||
|
||||
return exists
|
||||
}
|
||||
|
||||
func TestLockWithStaleLock(t *testing.T) {
|
||||
repo := SetupRepo()
|
||||
defer TeardownRepo(repo)
|
||||
|
||||
id1, err := createFakeLock(repo, time.Now().Add(-time.Hour), os.Getpid())
|
||||
OK(t, err)
|
||||
|
||||
id2, err := createFakeLock(repo, time.Now().Add(-time.Minute), os.Getpid())
|
||||
OK(t, err)
|
||||
|
||||
id3, err := createFakeLock(repo, time.Now().Add(-time.Minute), os.Getpid()+500)
|
||||
OK(t, err)
|
||||
|
||||
OK(t, restic.RemoveStaleLocks(repo))
|
||||
|
||||
Assert(t, lockExists(repo, t, id1) == false,
|
||||
"stale lock still exists after RemoveStaleLocks was called")
|
||||
Assert(t, lockExists(repo, t, id2) == true,
|
||||
"non-stale lock was removed by RemoveStaleLocks")
|
||||
Assert(t, lockExists(repo, t, id3) == false,
|
||||
"stale lock still exists after RemoveStaleLocks was called")
|
||||
|
||||
OK(t, removeLock(repo, id2))
|
||||
}
|
||||
Reference in New Issue
Block a user