github.com/igggame/nebulas-go@v2.1.0+incompatible/common/mvccdb/mvccdb_test.go (about) 1 // Copyright (C) 2018 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // the go-nebulas library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with the go-nebulas library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 19 package mvccdb 20 21 import ( 22 "os" 23 "testing" 24 "time" 25 26 "github.com/nebulasio/go-nebulas/common/trie" 27 "github.com/nebulasio/go-nebulas/crypto/hash" 28 "github.com/nebulasio/go-nebulas/util/byteutils" 29 30 "github.com/stretchr/testify/assert" 31 32 "github.com/nebulasio/go-nebulas/storage" 33 ) 34 35 func TestMVCCDB_NewMVCCDB(t *testing.T) { 36 storage, _ := storage.NewMemoryStorage() 37 db, err := NewMVCCDB(storage, false) 38 assert.Nil(t, err) 39 40 assert.False(t, db.isInTransaction) 41 assert.False(t, db.isPreparedDB) 42 } 43 44 func TestMVCCDB_FunctionEntryCondition(t *testing.T) { 45 stor, _ := storage.NewMemoryStorage() 46 db, _ := NewMVCCDB(stor, false) 47 48 assert.Nil(t, db.Begin()) 49 assert.Equal(t, ErrUnsupportedNestedTransaction, db.Begin()) 50 assert.Nil(t, db.Commit()) 51 assert.Equal(t, ErrTransactionNotStarted, db.Commit()) 52 53 assert.Nil(t, db.Begin()) 54 assert.Nil(t, db.RollBack()) 55 assert.Equal(t, ErrTransactionNotStarted, db.RollBack()) 56 57 pdb, err := db.Prepare(nil) 58 assert.Nil(t, pdb) 59 assert.Error(t, ErrTransactionNotStarted, err) 60 61 tid := "tid" 62 assert.Nil(t, db.Begin()) 63 pdb, err = db.Prepare(nil) 64 assert.Nil(t, pdb) 65 assert.Equal(t, ErrTidIsNil, err) 66 67 pdb, err = db.Prepare(tid) 68 assert.NotNil(t, pdb) 69 assert.Nil(t, err) 70 71 deps, err := pdb.CheckAndUpdate() 72 assert.Equal(t, 0, len(deps)) 73 assert.Nil(t, err) 74 75 err = pdb.Reset() 76 assert.Nil(t, err) 77 } 78 79 func TestMVCCDB_KeyChangeOutOfMVCCDB(t *testing.T) { 80 stor, _ := storage.NewMemoryStorage() 81 db, _ := NewMVCCDB(stor, false) 82 83 db.Begin() 84 85 // get non-exist key. 86 key := []byte("key") 87 val, err := db.Get(key) 88 assert.Nil(t, val) 89 assert.Equal(t, storage.ErrKeyNotFound, err) 90 91 // put to storage. 92 stor.Put(key, []byte("value")) 93 94 // get again. 95 val, err = db.Get(key) 96 assert.Nil(t, val) 97 assert.Equal(t, storage.ErrKeyNotFound, err) 98 } 99 100 func TestMVCCDB_DirectOpts(t *testing.T) { 101 storage, _ := storage.NewMemoryStorage() 102 db, _ := NewMVCCDB(storage, false) 103 104 key := []byte("key") 105 val := []byte("val") 106 107 v, err := db.getFromStorage(key) 108 assert.Nil(t, v) 109 assert.NotNil(t, err) 110 111 err = db.putToStorage(key, val) 112 assert.Nil(t, err) 113 114 v, err = db.getFromStorage(key) 115 assert.Nil(t, err) 116 assert.Equal(t, val, v) 117 118 err = db.delFromStorage(key) 119 assert.Nil(t, err) 120 121 v, err = db.getFromStorage(key) 122 assert.Nil(t, v) 123 assert.NotNil(t, err) 124 } 125 126 func TestMVCCDB_OptsWithoutTransaction(t *testing.T) { 127 storage, _ := storage.NewMemoryStorage() 128 db, _ := NewMVCCDB(storage, false) 129 130 key := []byte("key") 131 val := []byte("val") 132 133 v, err := db.Get(key) 134 assert.Nil(t, v) 135 assert.NotNil(t, err) 136 137 err = db.Put(key, val) 138 assert.Nil(t, err) 139 140 v, err = db.Get(key) 141 assert.Nil(t, err) 142 assert.Equal(t, val, v) 143 144 err = db.Del(key) 145 assert.Nil(t, err) 146 147 v, err = db.Get(key) 148 assert.Nil(t, v) 149 assert.NotNil(t, err) 150 } 151 152 func TestMVCCDB_OptsWithinTransaction(t *testing.T) { 153 store, _ := storage.NewMemoryStorage() 154 db, _ := NewMVCCDB(store, false) 155 156 key := []byte("key") 157 val := []byte("val") 158 159 err := db.Begin() 160 assert.Nil(t, err) 161 assert.True(t, db.isInTransaction) 162 163 // unsupported nested transaction. 164 err = db.Begin() 165 assert.Equal(t, err, ErrUnsupportedNestedTransaction) 166 167 v, err := db.Get(key) 168 assert.Nil(t, v) 169 assert.Equal(t, err, storage.ErrKeyNotFound) 170 171 err = db.Put(key, val) 172 assert.Nil(t, err) 173 174 { 175 // other MVCCDB can't read before commit. 176 db2, _ := NewMVCCDB(store, false) 177 v, err := db2.Get(key) 178 assert.Nil(t, v) 179 assert.Equal(t, err, storage.ErrKeyNotFound) 180 } 181 182 // commit. 183 db.Commit() 184 185 // read. 186 v, err = db.Get(key) 187 assert.Nil(t, err) 188 assert.Equal(t, val, v) 189 190 // begin. 191 err = db.Begin() 192 assert.Nil(t, err) 193 194 err = db.Del(key) 195 assert.Nil(t, err) 196 197 { 198 // other MVCCDB read old value. 199 db2, _ := NewMVCCDB(store, false) 200 v, err := db2.Get(key) 201 assert.Equal(t, val, v) 202 assert.Nil(t, err) 203 } 204 205 v, err = db.Get(key) 206 assert.Nil(t, v) 207 assert.Equal(t, err, storage.ErrKeyNotFound) 208 209 // rollback. 210 db.RollBack() 211 212 // read. 213 v, err = db.Get(key) 214 assert.Nil(t, err) 215 assert.Equal(t, val, v) 216 217 { 218 // other MVCCDB read old value. 219 db2, _ := NewMVCCDB(store, false) 220 v, err := db2.Get(key) 221 assert.Equal(t, val, v) 222 assert.Nil(t, err) 223 } 224 225 // begin. 226 err = db.Begin() 227 assert.Nil(t, err) 228 229 err = db.Del(key) 230 assert.Nil(t, err) 231 232 // commit. 233 db.Commit() 234 235 // read. 236 v, err = db.Get(key) 237 assert.Nil(t, v) 238 assert.Equal(t, err, storage.ErrKeyNotFound) 239 240 { 241 // other MVCCDB read nil. 242 db2, _ := NewMVCCDB(store, false) 243 v, err := db2.Get(key) 244 assert.Nil(t, v) 245 assert.Equal(t, err, storage.ErrKeyNotFound) 246 } 247 } 248 249 func TestMVCCDB_PrepareAndUpdate(t *testing.T) { 250 store, _ := storage.NewMemoryStorage() 251 db, _ := NewMVCCDB(store, false) 252 253 // init base data. 254 db.Put([]byte("title"), []byte("this is test program")) 255 256 // tid0 update. 257 { 258 db.Begin() 259 260 tid := "tid0" 261 pdb, err := db.Prepare(tid) 262 assert.Nil(t, err) 263 264 pdb.Put([]byte("duration"), []byte("65536")) 265 pdb.Put([]byte("creator"), []byte("robin")) 266 pdb.Put([]byte("count"), []byte("0")) 267 pdb.Put([]byte("createdAt"), []byte("c0")) 268 pdb.Put([]byte("updatedAt"), []byte("u0")) 269 270 deps, err := pdb.CheckAndUpdate() 271 assert.Nil(t, err) 272 assert.Equal(t, 0, len(deps)) 273 274 db.Commit() 275 } 276 277 // concurrent update. 278 db.Begin() 279 280 type RetValue struct { 281 tid interface{} 282 pdb *MVCCDB 283 depends []interface{} 284 err error 285 } 286 287 ret := make([]*RetValue, 0, 2) 288 289 { 290 tid := "tid1" 291 pdb, err := db.Prepare(tid) 292 assert.Nil(t, err) 293 assert.NotNil(t, pdb) 294 295 pdb.Get([]byte("count")) 296 pdb.Put([]byte("count"), []byte("10")) 297 pdb.Put([]byte("updatedAt"), []byte("u10")) 298 299 ret = append(ret, &RetValue{ 300 tid: tid, 301 pdb: pdb, 302 }) 303 } 304 305 { 306 tid := "tid2" 307 pdb, err := db.Prepare(tid) 308 assert.Nil(t, err) 309 assert.NotNil(t, pdb) 310 311 pdb.Get([]byte("count")) 312 pdb.Put([]byte("duration"), []byte("1024")) 313 pdb.Put([]byte("updatedAt"), []byte("u20")) 314 pdb.Del([]byte("creator")) 315 pdb.Put([]byte("description"), []byte("new description")) 316 317 ret = append(ret, &RetValue{ 318 tid: tid, 319 pdb: pdb, 320 }) 321 } 322 323 for _, v := range ret { 324 deps, err := v.pdb.CheckAndUpdate() 325 v.depends = deps 326 v.err = err 327 } 328 329 // commit. 330 db.Commit() 331 332 // verify. 333 var finalRet, errorRet *RetValue 334 for _, v := range ret { 335 if v.err == nil { 336 finalRet = v 337 } else { 338 errorRet = v 339 } 340 } 341 342 assert.NotNil(t, finalRet) 343 assert.NotNil(t, errorRet) 344 345 assert.Nil(t, finalRet.err) 346 assert.Equal(t, ErrStagingTableKeyConfliction, errorRet.err) 347 348 assert.Equal(t, 0, len(finalRet.depends)) 349 assert.Equal(t, 0, len(errorRet.depends)) 350 351 // verify value. 352 val, err := db.Get([]byte("title")) 353 assert.Nil(t, err) 354 assert.Equal(t, []byte("this is test program"), val) 355 356 val, err = db.Get([]byte("duration")) 357 assert.Nil(t, err) 358 assert.Equal(t, []byte("65536"), val) 359 360 val, err = db.Get([]byte("creator")) 361 assert.Nil(t, err) 362 assert.Equal(t, []byte("robin"), val) 363 364 val, err = db.Get([]byte("count")) 365 assert.Nil(t, err) 366 assert.Equal(t, []byte("10"), val) 367 368 val, err = db.Get([]byte("createdAt")) 369 assert.Nil(t, err) 370 assert.Equal(t, []byte("c0"), val) 371 372 val, err = db.Get([]byte("updatedAt")) 373 assert.Nil(t, err) 374 assert.Equal(t, []byte("u10"), val) 375 376 val, err = db.Get([]byte("description")) 377 assert.Equal(t, storage.ErrKeyNotFound, err) 378 assert.Nil(t, val) 379 } 380 381 func TestMVCCDB_ResetAndReuse(t *testing.T) { 382 store, _ := storage.NewMemoryStorage() 383 db, _ := NewMVCCDB(store, false) 384 385 // begin. 386 db.Begin() 387 388 key1 := []byte("key1") 389 val1_1 := []byte("val1_1") 390 val1_2 := []byte("val1_2") 391 val1_3 := []byte("val1_3") 392 393 err := db.Put(key1, val1_1) 394 assert.Nil(t, err) 395 396 // prepare. 397 pdb, err := db.Prepare("tid1") 398 assert.Nil(t, err) 399 400 assert.Nil(t, pdb.Del(key1)) 401 val, err := pdb.Get(key1) 402 assert.Nil(t, val) 403 assert.Equal(t, storage.ErrKeyNotFound, err) 404 405 pdb.Reset() 406 407 assert.Nil(t, pdb.Put(key1, val1_2)) 408 val, err = pdb.Get(key1) 409 assert.Equal(t, val1_2, val) 410 assert.Nil(t, err) 411 412 // nested prepare. 413 pdb2, err := pdb.Prepare("tid2") 414 assert.Nil(t, err) 415 val, err = pdb2.Get(key1) 416 assert.Equal(t, val1_2, val) 417 assert.Nil(t, err) 418 419 assert.Nil(t, pdb2.Put(key1, val1_3)) 420 val, err = pdb2.Get(key1) 421 assert.Equal(t, val1_3, val) 422 assert.Nil(t, err) 423 424 // verify pdb, 425 val, err = pdb.Get(key1) 426 assert.Equal(t, val1_2, val) 427 assert.Nil(t, err) 428 429 // close. 430 assert.Nil(t, pdb2.Close()) 431 assert.Nil(t, pdb.Close()) 432 433 // Commit. 434 db.Commit() 435 436 val, err = db.Get(key1) 437 assert.Equal(t, val1_1, val) 438 assert.Nil(t, err) 439 } 440 441 func TestMVCCDB_ClosePreparedDB(t *testing.T) { 442 store, _ := storage.NewMemoryStorage() 443 db, _ := NewMVCCDB(store, false) 444 445 // begin. 446 db.Begin() 447 448 key1 := []byte("key1") 449 val1_1 := []byte("val1_1") 450 val1_2 := []byte("val1_2") 451 452 assert.Nil(t, db.Put(key1, val1_1)) 453 454 pdb, err := db.Prepare("tid1") 455 assert.Nil(t, err) 456 457 // duplicate prepare. 458 v, err := db.Prepare("tid1") 459 assert.Nil(t, v) 460 assert.Equal(t, ErrTidIsExist, err) 461 462 // close. 463 assert.Nil(t, pdb.Close()) 464 val, err := pdb.Get(key1) 465 assert.Nil(t, val) 466 assert.Equal(t, ErrPreparedDBIsClosed, err) 467 468 err = pdb.Put(key1, val1_2) 469 assert.Equal(t, ErrPreparedDBIsClosed, err) 470 471 err = pdb.Del(key1) 472 assert.Equal(t, ErrPreparedDBIsClosed, err) 473 474 // prepare again 475 v, err = db.Prepare("tid1") 476 assert.Nil(t, err) 477 assert.False(t, pdb == v) 478 479 assert.Nil(t, v.Put(key1, val1_2)) 480 val, err = v.Get(key1) 481 assert.Equal(t, val1_2, val) 482 assert.Nil(t, err) 483 } 484 485 func TestMVCCDB_ParallelsExeTowTx(t *testing.T) { 486 store, _ := storage.NewMemoryStorage() 487 db, _ := NewMVCCDB(store, false) 488 489 // expected t1(a-b) and t2(a-b) parallels execution will be failed. 490 491 db.Begin() 492 493 t1, err := db.Prepare("t1") 494 assert.Nil(t, err) 495 t2, err := db.Prepare("t2") 496 assert.Nil(t, err) 497 498 // 1st time. 499 t1.Put([]byte("a"), []byte("9")) 500 t1.Put([]byte("b"), []byte("11")) 501 t2.Put([]byte("a"), []byte("9")) 502 t2.Put([]byte("b"), []byte("11")) 503 504 // t1 1st: commit, failed. 505 deps, err := t1.CheckAndUpdate() 506 assert.Nil(t, err) 507 assert.Equal(t, 0, len(deps)) 508 509 // t2: 1st, failed. 510 deps, err = t2.CheckAndUpdate() 511 assert.Equal(t, ErrStagingTableKeyConfliction, err) 512 513 // t2: 2nd, succeed. 514 t2.Close() 515 t2, err = db.Prepare("t2") 516 assert.Nil(t, err) 517 518 t2.Put([]byte("a"), []byte("9")) 519 t2.Put([]byte("b"), []byte("11")) 520 deps, err = t2.CheckAndUpdate() 521 assert.Nil(t, err) 522 assert.Equal(t, 1, len(deps)) 523 assert.Equal(t, "t1", deps[0]) 524 } 525 526 func TestPerformance(t *testing.T) { 527 store, _ := storage.NewRocksStorage("test.db") 528 defer os.RemoveAll("test.db") 529 db, _ := NewMVCCDB(store, true) 530 531 // begin. 532 db.Begin() 533 534 val := []byte("kbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghaadgncdgkenkbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghaadgncdgkenkbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghaadgncdgkenkbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghakbtiuwgqybgheb l dvhjbgkajbn ba.dkghoeubgkjabgk.jdbga;kdjhguibnaklefgn;ndjghao;idngsndbghaadgncdgken") 535 assert.Equal(t, len(val), 3640) 536 537 for i := 0; i < 400; i++ { 538 pdb, err := db.Prepare(byteutils.Hex(hash.Sha3256(byteutils.FromInt32(int32(i))))) 539 for j := 0; j < 20; j++ { 540 assert.Nil(t, db.Put(byteutils.FromInt32(int32(i*20+j)), val)) 541 } 542 _, err = pdb.CheckAndUpdate() 543 assert.Nil(t, err) 544 } 545 546 start := time.Now().UnixNano() 547 err := db.Commit() 548 end := time.Now().UnixNano() 549 assert.Nil(t, err) 550 assert.True(t, (end-start) < 1000000000, "%s", end-start) 551 } 552 553 func TestOperateAfterParentClosed(t *testing.T) { 554 store, _ := storage.NewMemoryStorage() 555 db, _ := NewMVCCDB(store, true) 556 557 db.Begin() 558 tx1, err := db.Prepare("1") 559 assert.Nil(t, err) 560 tree1, err := trie.NewTrie(nil, tx1, false) 561 assert.Nil(t, err) 562 tree1.Put([]byte("111111"), []byte("111")) 563 tree1.Put([]byte("111112"), []byte("112")) 564 tx1.CheckAndUpdate() 565 566 tx2, err := db.Prepare("2") 567 assert.Nil(t, err) 568 tree2, err := trie.NewTrie(tree1.RootHash(), tx2, false) 569 assert.Nil(t, err) 570 571 db.RollBack() 572 573 bytes, err := tree2.Put([]byte("111113"), []byte("113")) 574 assert.Nil(t, bytes) 575 assert.Equal(t, err, ErrPreparedDBIsClosed) 576 }