aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2023-06-08 15:50:05 +0200
committerJakob Unterwurzacher2024-12-04 19:53:15 +0100
commit655d9a81c211f8fa151d42fe87ebf91c7fc8cc10 (patch)
treea530a4d9166300b2337d4cd49433a7dbc474337b
parent9f7beae2499a186bd2f78c004ca582a24b1a5220 (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.go65
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()
+}