go.etcd.io/etcd@v3.3.27+incompatible/mvcc/backend/batch_tx_test.go (about) 1 // Copyright 2015 The etcd Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package backend 16 17 import ( 18 "reflect" 19 "testing" 20 "time" 21 22 bolt "github.com/coreos/bbolt" 23 ) 24 25 func TestBatchTxPut(t *testing.T) { 26 b, tmpPath := NewTmpBackend(time.Hour, 10000) 27 defer cleanup(b, tmpPath) 28 29 tx := b.batchTx 30 tx.Lock() 31 defer tx.Unlock() 32 33 // create bucket 34 tx.UnsafeCreateBucket([]byte("test")) 35 36 // put 37 v := []byte("bar") 38 tx.UnsafePut([]byte("test"), []byte("foo"), v) 39 40 // check put result before and after tx is committed 41 for k := 0; k < 2; k++ { 42 _, gv := tx.UnsafeRange([]byte("test"), []byte("foo"), nil, 0) 43 if !reflect.DeepEqual(gv[0], v) { 44 t.Errorf("v = %s, want %s", string(gv[0]), string(v)) 45 } 46 tx.commit(false) 47 } 48 } 49 50 func TestBatchTxRange(t *testing.T) { 51 b, tmpPath := NewTmpBackend(time.Hour, 10000) 52 defer cleanup(b, tmpPath) 53 54 tx := b.batchTx 55 tx.Lock() 56 defer tx.Unlock() 57 58 tx.UnsafeCreateBucket([]byte("test")) 59 // put keys 60 allKeys := [][]byte{[]byte("foo"), []byte("foo1"), []byte("foo2")} 61 allVals := [][]byte{[]byte("bar"), []byte("bar1"), []byte("bar2")} 62 for i := range allKeys { 63 tx.UnsafePut([]byte("test"), allKeys[i], allVals[i]) 64 } 65 66 tests := []struct { 67 key []byte 68 endKey []byte 69 limit int64 70 71 wkeys [][]byte 72 wvals [][]byte 73 }{ 74 // single key 75 { 76 []byte("foo"), nil, 0, 77 allKeys[:1], allVals[:1], 78 }, 79 // single key, bad 80 { 81 []byte("doo"), nil, 0, 82 nil, nil, 83 }, 84 // key range 85 { 86 []byte("foo"), []byte("foo1"), 0, 87 allKeys[:1], allVals[:1], 88 }, 89 // key range, get all keys 90 { 91 []byte("foo"), []byte("foo3"), 0, 92 allKeys, allVals, 93 }, 94 // key range, bad 95 { 96 []byte("goo"), []byte("goo3"), 0, 97 nil, nil, 98 }, 99 // key range with effective limit 100 { 101 []byte("foo"), []byte("foo3"), 1, 102 allKeys[:1], allVals[:1], 103 }, 104 // key range with limit 105 { 106 []byte("foo"), []byte("foo3"), 4, 107 allKeys, allVals, 108 }, 109 } 110 for i, tt := range tests { 111 keys, vals := tx.UnsafeRange([]byte("test"), tt.key, tt.endKey, tt.limit) 112 if !reflect.DeepEqual(keys, tt.wkeys) { 113 t.Errorf("#%d: keys = %+v, want %+v", i, keys, tt.wkeys) 114 } 115 if !reflect.DeepEqual(vals, tt.wvals) { 116 t.Errorf("#%d: vals = %+v, want %+v", i, vals, tt.wvals) 117 } 118 } 119 } 120 121 func TestBatchTxDelete(t *testing.T) { 122 b, tmpPath := NewTmpBackend(time.Hour, 10000) 123 defer cleanup(b, tmpPath) 124 125 tx := b.batchTx 126 tx.Lock() 127 defer tx.Unlock() 128 129 tx.UnsafeCreateBucket([]byte("test")) 130 tx.UnsafePut([]byte("test"), []byte("foo"), []byte("bar")) 131 132 tx.UnsafeDelete([]byte("test"), []byte("foo")) 133 134 // check put result before and after tx is committed 135 for k := 0; k < 2; k++ { 136 ks, _ := tx.UnsafeRange([]byte("test"), []byte("foo"), nil, 0) 137 if len(ks) != 0 { 138 t.Errorf("keys on foo = %v, want nil", ks) 139 } 140 tx.commit(false) 141 } 142 } 143 144 func TestBatchTxCommit(t *testing.T) { 145 b, tmpPath := NewTmpBackend(time.Hour, 10000) 146 defer cleanup(b, tmpPath) 147 148 tx := b.batchTx 149 tx.Lock() 150 tx.UnsafeCreateBucket([]byte("test")) 151 tx.UnsafePut([]byte("test"), []byte("foo"), []byte("bar")) 152 tx.Unlock() 153 154 tx.Commit() 155 156 // check whether put happens via db view 157 b.db.View(func(tx *bolt.Tx) error { 158 bucket := tx.Bucket([]byte("test")) 159 if bucket == nil { 160 t.Errorf("bucket test does not exit") 161 return nil 162 } 163 v := bucket.Get([]byte("foo")) 164 if v == nil { 165 t.Errorf("foo key failed to written in backend") 166 } 167 return nil 168 }) 169 } 170 171 func TestBatchTxBatchLimitCommit(t *testing.T) { 172 // start backend with batch limit 1 so one write can 173 // trigger a commit 174 b, tmpPath := NewTmpBackend(time.Hour, 1) 175 defer cleanup(b, tmpPath) 176 177 tx := b.batchTx 178 tx.Lock() 179 tx.UnsafeCreateBucket([]byte("test")) 180 tx.UnsafePut([]byte("test"), []byte("foo"), []byte("bar")) 181 tx.Unlock() 182 183 // batch limit commit should have been triggered 184 // check whether put happens via db view 185 b.db.View(func(tx *bolt.Tx) error { 186 bucket := tx.Bucket([]byte("test")) 187 if bucket == nil { 188 t.Errorf("bucket test does not exit") 189 return nil 190 } 191 v := bucket.Get([]byte("foo")) 192 if v == nil { 193 t.Errorf("foo key failed to written in backend") 194 } 195 return nil 196 }) 197 }