1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
// Copyright 2014 The LevelDB-Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package db_test
import (
"bytes"
"flag"
"io/ioutil"
"os"
"os/exec"
"testing"
"github.com/golang/leveldb/db"
)
var lockFilename = flag.String("lockfile", "", "File to lock. A non-empty value implies a child process.")
func spawn(prog, filename string) ([]byte, error) {
return exec.Command(prog, "-lockfile", filename, "-test.v",
"-test.run=TestLock$").CombinedOutput()
}
// TestLock locks a file, spawns a second process that attempts to grab the
// lock to verify it fails.
// Then it closes the lock, and spawns a third copy to verify it can be
// relocked.
func TestLock(t *testing.T) {
child := *lockFilename != ""
var filename string
if child {
filename = *lockFilename
} else {
f, err := ioutil.TempFile("", "golang-leveldb-db-testlock-")
if err != nil {
t.Fatal(err)
}
filename = f.Name()
defer os.Remove(filename)
}
// Avoid truncating an existing, non-empty file.
fi, err := os.Stat(filename)
if err == nil && fi.Size() != 0 {
t.Fatalf("The file %s is not empty", filename)
}
t.Logf("Locking %s\n", filename)
lock, err := db.DefaultFileSystem.Lock(filename)
if err != nil {
t.Fatalf("Could not lock %s: %v", filename, err)
}
if !child {
t.Logf("Spawning child, should fail to grab lock.")
out, err := spawn(os.Args[0], filename)
if err == nil {
t.Fatalf("Attempt to grab open lock should have failed.\n%s", out)
}
if !bytes.Contains(out, []byte("Could not lock")) {
t.Fatalf("Child failed with unexpected output: %s\n", out)
}
t.Logf("Child failed to grab lock as expected.")
}
t.Logf("Unlocking %s", filename)
if err := lock.Close(); err != nil {
t.Fatalf("Could not unlock %s: %v", filename, err)
}
if !child {
t.Logf("Spawning child, should successfully grab lock.")
if out, err := spawn(os.Args[0], filename); err != nil {
t.Fatalf("Attempt to re-open lock should have succeeded: %v\n%s",
err, out)
}
t.Logf("Child grabbed lock.")
}
}
|