diff options
author | Jakob Unterwurzacher | 2023-06-08 15:50:05 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2024-12-04 19:53:15 +0100 |
commit | 655d9a81c211f8fa151d42fe87ebf91c7fc8cc10 (patch) | |
tree | a530a4d9166300b2337d4cd49433a7dbc474337b | |
parent | 9f7beae2499a186bd2f78c004ca582a24b1a5220 (diff) |
tests/cluster: add TestPoCTornWrite
Scary. But explains why TestConcurrentCreate fails.
gocryptfs/tests/cluster$ go test -run TestPoCTornWrite
--- FAIL: TestPoCTornWrite (0.00s)
poc_test.go:210: iteration 214: inconsistent block: d6d6d6d6d6d6d6d6d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1d1
FAIL
-rw-r--r-- | tests/cluster/poc_test.go | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/tests/cluster/poc_test.go b/tests/cluster/poc_test.go index 6f74ba2..811ffea 100644 --- a/tests/cluster/poc_test.go +++ b/tests/cluster/poc_test.go @@ -139,3 +139,68 @@ func TestPoCHeaderCreation(t *testing.T) { t.Logf("readEmpty=%d readOk=%d writes=%d", stats.readEmpty, stats.readOk, stats.writes) } + +// TestPoCTornWrite simulates what TestConcurrentCreate does. +// +// Fails on ext4, quoting https://stackoverflow.com/a/35256626 : +// > Linux 4.2.6 with ext4: update atomicity = 1 byte +// +// Passes on XFS. +func TestPoCTornWrite(t *testing.T) { + if os.Getenv("ENABLE_CLUSTER_TEST") != "1" { + t.Skipf("This test is disabled by default because it fails unless on XFS.\n" + + "Run it like this: ENABLE_CLUSTER_TEST=1 go test\n" + + "Choose a backing directory by setting TMPDIR.") + } + + 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 + blockData := bytes.Repeat([]byte{byte(i)}, 42) + if _, err = f.WriteAt(blockData, 0); err != nil { + t.Errorf("iteration %d: WriteAt: %v", i, err) + return + } + + // Readback and verify + readBuf := make([]byte, 100) + if n, err := f.ReadAt(readBuf, 0); 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() +} |