github.com/petermattis/pebble@v0.0.0-20190905164901-ab51a2166067/vfs/file_lock_test.go (about)

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