aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/cluster/poc_test.go81
1 files changed, 81 insertions, 0 deletions
diff --git a/tests/cluster/poc_test.go b/tests/cluster/poc_test.go
index 6f74ba2..6719663 100644
--- a/tests/cluster/poc_test.go
+++ b/tests/cluster/poc_test.go
@@ -139,3 +139,84 @@ func TestPoCHeaderCreation(t *testing.T) {
t.Logf("readEmpty=%d readOk=%d writes=%d", stats.readEmpty, stats.readOk, stats.writes)
}
+
+// TestPoCTornWrite simulates what TestConcurrentCreate does.
+func TestPoCTornWrite(t *testing.T) {
+ path := test_helpers.TmpDir + "/" + t.Name()
+ var wg sync.WaitGroup
+ const loops = 10000
+
+ writerThread := func() {
+ defer wg.Done()
+ for i := 0; i < loops; i++ {
+ if t.Failed() {
+ return
+ }
+ f, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0600)
+ if err != nil {
+ t.Errorf("BUG: this should not happen: open err=%v", err)
+ return
+ }
+
+ // Write dummy header unless it is already there
+ lk := unix.Flock_t{
+ Type: unix.F_WRLCK,
+ Whence: unix.SEEK_SET,
+ Start: 0,
+ Len: 0,
+ }
+ if err := unix.FcntlFlock(uintptr(f.Fd()), syscallcompat.F_OFD_SETLKW, &lk); err != nil {
+ t.Error(err)
+ return
+ }
+
+ hdr := make([]byte, contentenc.HeaderLen)
+ if _, err := f.ReadAt(hdr, 0); err == io.EOF {
+ hdr = bytes.Repeat([]byte{byte(i)}, contentenc.HeaderLen)
+ if _, err := f.WriteAt(hdr, 0); err != nil {
+ t.Errorf("header write failed: %v", err)
+ return
+ }
+ } else if err != nil {
+ t.Error(err)
+ return
+ }
+ lk.Type = unix.F_UNLCK
+ if err := unix.FcntlFlock(uintptr(f.Fd()), syscallcompat.F_OFD_SETLKW, &lk); err != nil {
+ t.Error(err)
+ return
+ }
+
+ // Write dummy data
+ blockData := bytes.Repeat([]byte{byte(i)}, 42)
+ if _, err = f.WriteAt(blockData, contentenc.HeaderLen); err != nil {
+ t.Errorf("iteration %d: WriteAt: %v", i, err)
+ return
+ }
+
+ readBuf := make([]byte, 100)
+ if n, err := f.ReadAt(readBuf, contentenc.HeaderLen); err == io.EOF {
+ readBuf = readBuf[:n]
+ } else if err != nil {
+ t.Error(err)
+ return
+ }
+ if len(readBuf) != len(blockData) {
+ t.Error("wrong length")
+ return
+ }
+ for _, v := range readBuf {
+ if v != readBuf[0] {
+ t.Errorf("iteration %d: inconsistent block: %x", i, readBuf)
+ return
+ }
+ }
+ f.Close()
+ }
+ }
+
+ wg.Add(2)
+ go writerThread()
+ go writerThread()
+ wg.Wait()
+}