github.com/vescale/zgraph@v0.0.0-20230410094002-959c02d50f95/storage/transaction_test.go (about) 1 // Copyright 2022 zGraph Authors. All rights reserved. 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 storage 16 17 import ( 18 "context" 19 "encoding/binary" 20 "io" 21 "log" 22 "math/rand" 23 "testing" 24 25 "github.com/stretchr/testify/assert" 26 "github.com/vescale/zgraph/storage/kv" 27 "go.uber.org/atomic" 28 ) 29 30 func TestTxn_Commit(t *testing.T) { 31 assert := assert.New(t) 32 33 storage, err := Open(t.TempDir()) 34 assert.Nil(err) 35 assert.NotNil(storage) 36 defer storage.Close() 37 38 cases := []struct { 39 keys []string 40 vals []string 41 }{ 42 { 43 keys: []string{"a"}, 44 vals: []string{"b"}, 45 }, 46 // Overwrite same key. 47 { 48 keys: []string{"a"}, 49 vals: []string{"c"}, 50 }, 51 // Multiple key transaction 52 { 53 keys: []string{"c", "d", "e"}, 54 vals: []string{"x", "y", "z"}, 55 }, 56 } 57 for _, c := range cases { 58 txn, err := storage.Begin() 59 assert.Nil(err) 60 assert.NotNil(txn) 61 for i, k := range c.keys { 62 err := txn.Set(kv.Key(k), []byte(c.vals[i])) 63 assert.Nil(err) 64 } 65 err = txn.Commit(context.Background()) 66 assert.Nil(err) 67 68 // Validate the data 69 snapshot, err := storage.Snapshot(storage.CurrentVersion()) 70 assert.Nil(err) 71 for i, k := range c.keys { 72 val, err := snapshot.Get(context.Background(), kv.Key(k)) 73 assert.Nil(err) 74 assert.Equal(c.vals[i], string(val)) 75 } 76 77 // Batch get interface. 78 var keys []kv.Key 79 var vals = map[string][]byte{} 80 for i, k := range c.keys { 81 keys = append(keys, kv.Key(k)) 82 vals[k] = []byte(c.vals[i]) 83 } 84 res, err := snapshot.BatchGet(context.Background(), keys) 85 assert.Nil(err) 86 assert.Equal(vals, res) 87 } 88 } 89 90 func TestTxn_Iter(t *testing.T) { 91 assert := assert.New(t) 92 93 storage, err := Open(t.TempDir()) 94 assert.Nil(err) 95 assert.NotNil(storage) 96 defer storage.Close() 97 98 cases := []struct { 99 keys []string 100 vals []string 101 order []string 102 result map[string]string 103 }{ 104 { 105 keys: []string{"a"}, 106 vals: []string{"b"}, 107 order: []string{"a"}, 108 result: map[string]string{ 109 "a": "b", 110 }, 111 }, 112 // Overwrite same key. 113 { 114 keys: []string{"a"}, 115 vals: []string{"c"}, 116 order: []string{"a"}, 117 result: map[string]string{ 118 "a": "c", 119 }, 120 }, 121 // Multiple key transaction 122 { 123 keys: []string{"c", "d", "e"}, 124 vals: []string{"x", "y", "z"}, 125 order: []string{"a", "c", "d", "e"}, 126 result: map[string]string{ 127 "a": "c", 128 "c": "x", 129 "d": "y", 130 "e": "z", 131 }, 132 }, 133 } 134 for _, c := range cases { 135 txn, err := storage.Begin() 136 assert.Nil(err) 137 assert.NotNil(txn) 138 for i, k := range c.keys { 139 err := txn.Set(kv.Key(k), []byte(c.vals[i])) 140 assert.Nil(err) 141 } 142 err = txn.Commit(context.Background()) 143 assert.Nil(err) 144 145 // Validate the data 146 snapshot, err := storage.Snapshot(storage.CurrentVersion()) 147 assert.Nil(err) 148 iter, err := snapshot.Iter(nil, nil) 149 assert.Nil(err) 150 151 var order []string 152 var result = map[string]string{} 153 for iter.Valid() { 154 key := iter.Key() 155 val := iter.Value() 156 order = append(order, string(key)) 157 result[string(key)] = string(val) 158 err = iter.Next() 159 assert.Nil(err) 160 } 161 assert.Equal(c.order, order) 162 assert.Equal(c.result, result) 163 } 164 } 165 166 func benchmarkTxnCommit(b *testing.B, parallelism int) { 167 assert := assert.New(b) 168 169 const kvCount = 10 170 171 storage, err := Open(b.TempDir()) 172 assert.Nil(err) 173 assert.NotNil(storage) 174 175 log.SetOutput(io.Discard) 176 b.SetParallelism(parallelism) 177 178 counter := atomic.Uint64{} 179 180 b.RunParallel(func(pb *testing.PB) { 181 for pb.Next() { 182 txn, err := storage.Begin() 183 assert.Nil(err) 184 for n := 0; n < kvCount; n++ { 185 key := make([]byte, 8) 186 val := make([]byte, 8) 187 binary.BigEndian.AppendUint64(key, counter.Inc()) 188 binary.BigEndian.AppendUint64(val, rand.Uint64()) 189 err := txn.Set(key, val) 190 assert.Nil(err) 191 } 192 err = txn.Commit(context.Background()) 193 if err != nil { 194 // Only txn conflict allow 195 _, ok := err.(*kv.ErrConflict) 196 assert.True(ok) 197 } 198 } 199 }) 200 201 } 202 203 func BenchmarkTxn_Commit_P32(b *testing.B) { 204 benchmarkTxnCommit(b, 32) 205 } 206 207 func BenchmarkTxn_Commit_P128(b *testing.B) { 208 benchmarkTxnCommit(b, 128) 209 } 210 211 func BenchmarkTxn_Commit_P256(b *testing.B) { 212 benchmarkTxnCommit(b, 256) 213 } 214 215 func BenchmarkTxn_Commit_P512(b *testing.B) { 216 benchmarkTxnCommit(b, 512) 217 } 218 219 func BenchmarkTxn_Commit_P1024(b *testing.B) { 220 benchmarkTxnCommit(b, 1024) 221 }