@@ -2,6 +2,10 @@ package etcdserver
2
2
3
3
import (
4
4
"context"
5
+ "crypto/sha256"
6
+ "github.com/stretchr/testify/require"
7
+ "io"
8
+ "os"
5
9
"strings"
6
10
"sync"
7
11
"testing"
@@ -55,8 +59,7 @@ func TestReadonlyTxnError(t *testing.T) {
55
59
}
56
60
57
61
func TestWriteTxnPanic (t * testing.T ) {
58
- b , _ := betesting .NewDefaultTmpBackend (t )
59
- defer betesting .Close (t , b )
62
+ b , bePath := betesting .NewDefaultTmpBackend (t )
60
63
s := mvcc .New (zap .NewExample (), b , & lease.FakeLessor {}, mvcc.StoreConfig {})
61
64
defer s .Close ()
62
65
@@ -92,5 +95,29 @@ func TestWriteTxnPanic(t *testing.T) {
92
95
},
93
96
}
94
97
98
+ // compute DB file hash before applying the txn
99
+ dbHashBefore , err := computeFileHash (bePath )
100
+ require .NoErrorf (t , err , "failed to compute DB file hash before txn" )
101
+
102
+ // we verify the following properties below:
103
+ // 1. server panics after a write txn aply fails (invariant: server should never try to move on from a failed write)
104
+ // 2. no writes from the txn are applied to the backend (invariant: failed write should have no side-effect on DB state besides panic)
95
105
assert .Panics (t , func () { a .Txn (ctx , txn ) }, "Expected panic in Txn with writes" )
106
+ dbHashAfter , err := computeFileHash (bePath )
107
+ require .NoErrorf (t , err , "failed to compute DB file hash after txn" )
108
+ require .Equalf (t , dbHashBefore , dbHashAfter , "mismatch in DB hash before and after failed write txn" )
109
+ }
110
+
111
+ func computeFileHash (filePath string ) (string , error ) {
112
+ file , err := os .Open (filePath )
113
+ if err != nil {
114
+ return "" , err
115
+ }
116
+ defer file .Close ()
117
+
118
+ h := sha256 .New ()
119
+ if _ , err := io .Copy (h , file ); err != nil {
120
+ return "" , err
121
+ }
122
+ return string (h .Sum (nil )), nil
96
123
}
0 commit comments