mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-11 08:36:43 +00:00

* [NOD-849] Cover ffldb/transaction with tests. * [NOD-849] Cover cursor.go with tests. * [NOD-849] Cover ldb/transaction with tests. * [NOD-849] Cover location.go with tests. * [NOD-849] Write TestFlatFileMultiFileRollback. * [NOD-849] Fix merge errors. * [NOD-849] Fix a comment. * [NOD-849] Fix a comment. * [NOD-849] Add a test that makes sure that files get deleted on rollback. * [NOD-849] Add a test that makes sure that serializeLocation serialized to an expected value. * [NOD-849] Improve TestFlatFileLocationDeserializationErrors. * [NOD-849] Fix a copy+paste error. * [NOD-849] Explain maxFileSize = 16. * [NOD-849] Remove redundant RollbackUnlessClosed call. * [NOD-849] Extract bucket to a variable in TestCursorSanity. * [NOD-849] Rename TestKeyValueTransactionCommit to TestTransactionCommitForLevelDBMethods. * [NOD-849] Extract prepareXXX into separate functions. * [NOD-849] Simplify function calls in TestTransactionCloseErrors. * [NOD-849] Extract validateCurrentCursorKeyAndValue to a separate function. * [NOD-849] Add a comment over TestCursorSanity. * [NOD-849] Add a comment over function in TestCursorCloseErrors. * [NOD-849] Add a comment over function in TestTransactionCloseErrors. * [NOD-849] Separate TestTransactionCloseErrors to TestTransactionCommitErrors and TestTransactionRollbackErrors. * [NOD-849] Separate TestTransactionCloseErrors to TestTransactionCommitErrors and TestTransactionRollbackErrors. * [NOD-849] Fix copy+paste error in comments. * [NOD-849] Fix merge errors. * [NOD-849] Merge TestTransactionCommitErrors and TestTransactionRollbackErrors into TestTransactionCloseErrors. * [NOD-849] Move prepareDatabaseForTest into ffldb_test.go. * [NOD-849] Add cursorKey to Value error messages in validateCurrentCursorKeyAndValue.
176 lines
4.9 KiB
Go
176 lines
4.9 KiB
Go
package ff
|
|
|
|
import (
|
|
"bytes"
|
|
"github.com/kaspanet/kaspad/database"
|
|
"io/ioutil"
|
|
"os"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func prepareStoreForTest(t *testing.T, testName string) (store *flatFileStore, teardownFunc func()) {
|
|
// Create a temp db to run tests against
|
|
path, err := ioutil.TempDir("", testName)
|
|
if err != nil {
|
|
t.Fatalf("%s: TempDir unexpectedly "+
|
|
"failed: %s", testName, err)
|
|
}
|
|
name := "test"
|
|
store, err = openFlatFileStore(path, name)
|
|
if err != nil {
|
|
t.Fatalf("%s: openFlatFileStore "+
|
|
"unexpectedly failed: %s", testName, err)
|
|
}
|
|
teardownFunc = func() {
|
|
err = store.Close()
|
|
if err != nil {
|
|
t.Fatalf("%s: Close unexpectedly "+
|
|
"failed: %s", testName, err)
|
|
}
|
|
}
|
|
return store, teardownFunc
|
|
}
|
|
|
|
func TestFlatFileStoreSanity(t *testing.T) {
|
|
store, teardownFunc := prepareStoreForTest(t, "TestFlatFileStoreSanity")
|
|
defer teardownFunc()
|
|
|
|
// Write something to the store
|
|
writeData := []byte("Hello world!")
|
|
location, err := store.write(writeData)
|
|
if err != nil {
|
|
t.Fatalf("TestFlatFileStoreSanity: Write returned "+
|
|
"unexpected error: %s", err)
|
|
}
|
|
|
|
// Read from the location previously written to
|
|
readData, err := store.read(location)
|
|
if err != nil {
|
|
t.Fatalf("TestFlatFileStoreSanity: read returned "+
|
|
"unexpected error: %s", err)
|
|
}
|
|
|
|
// Make sure that the written data and the read data are equal
|
|
if !reflect.DeepEqual(readData, writeData) {
|
|
t.Fatalf("TestFlatFileStoreSanity: read data and "+
|
|
"write data are not equal. Wrote: %s, read: %s",
|
|
string(writeData), string(readData))
|
|
}
|
|
}
|
|
|
|
func TestFlatFilePath(t *testing.T) {
|
|
tests := []struct {
|
|
dbPath string
|
|
storeName string
|
|
fileNumber uint32
|
|
expectedPath string
|
|
}{
|
|
{
|
|
dbPath: "path",
|
|
storeName: "store",
|
|
fileNumber: 0,
|
|
expectedPath: "path/store-000000000.fdb",
|
|
},
|
|
{
|
|
dbPath: "path/to/database",
|
|
storeName: "blocks",
|
|
fileNumber: 123456789,
|
|
expectedPath: "path/to/database/blocks-123456789.fdb",
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
path := flatFilePath(test.dbPath, test.storeName, test.fileNumber)
|
|
if path != test.expectedPath {
|
|
t.Errorf("TestFlatFilePath: unexpected path. Want: %s, got: %s",
|
|
test.expectedPath, path)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFlatFileMultiFileRollback(t *testing.T) {
|
|
store, teardownFunc := prepareStoreForTest(t, "TestFlatFileMultiFileRollback")
|
|
defer teardownFunc()
|
|
|
|
// Set the maxFileSize to 16 bytes so that we don't have to write
|
|
// an enormous amount of data to disk to get multiple files, all
|
|
// for the sake of this test.
|
|
currentMaxFileSize := maxFileSize
|
|
maxFileSize = 16
|
|
defer func() {
|
|
maxFileSize = currentMaxFileSize
|
|
}()
|
|
|
|
// Write five 8 byte chunks and keep the last location written to
|
|
var lastWriteLocation1 *flatFileLocation
|
|
for i := byte(0); i < 5; i++ {
|
|
writeData := []byte{i, i, i, i, i, i, i, i}
|
|
var err error
|
|
lastWriteLocation1, err = store.write(writeData)
|
|
if err != nil {
|
|
t.Fatalf("TestFlatFileMultiFileRollback: write returned "+
|
|
"unexpected error: %s", err)
|
|
}
|
|
}
|
|
|
|
// Grab the current location and the current file number
|
|
currentLocation := store.currentLocation()
|
|
fileNumberBeforeWriting := store.writeCursor.currentFileNumber
|
|
|
|
// Write (2 * maxOpenFiles) more 8 byte chunks and keep the last location written to
|
|
var lastWriteLocation2 *flatFileLocation
|
|
for i := byte(0); i < byte(2*maxFileSize); i++ {
|
|
writeData := []byte{0, 1, 2, 3, 4, 5, 6, 7}
|
|
var err error
|
|
lastWriteLocation2, err = store.write(writeData)
|
|
if err != nil {
|
|
t.Fatalf("TestFlatFileMultiFileRollback: write returned "+
|
|
"unexpected error: %s", err)
|
|
}
|
|
}
|
|
|
|
// Grab the file number again to later make sure its file no longer exists
|
|
fileNumberAfterWriting := store.writeCursor.currentFileNumber
|
|
|
|
// Rollback
|
|
err := store.rollback(currentLocation)
|
|
if err != nil {
|
|
t.Fatalf("TestFlatFileMultiFileRollback: rollback returned "+
|
|
"unexpected error: %s", err)
|
|
}
|
|
|
|
// Make sure that lastWriteLocation1 still exists
|
|
expectedData := []byte{4, 4, 4, 4, 4, 4, 4, 4}
|
|
data, err := store.read(lastWriteLocation1)
|
|
if err != nil {
|
|
t.Fatalf("TestFlatFileMultiFileRollback: read returned "+
|
|
"unexpected error: %s", err)
|
|
}
|
|
if !bytes.Equal(data, expectedData) {
|
|
t.Fatalf("TestFlatFileMultiFileRollback: read returned "+
|
|
"unexpected data. Want: %s, got: %s", string(expectedData),
|
|
string(data))
|
|
}
|
|
|
|
// Make sure that lastWriteLocation2 does NOT exist
|
|
_, err = store.read(lastWriteLocation2)
|
|
if err == nil {
|
|
t.Fatalf("TestFlatFileMultiFileRollback: read " +
|
|
"unexpectedly succeeded")
|
|
}
|
|
if !database.IsNotFoundError(err) {
|
|
t.Fatalf("TestFlatFileMultiFileRollback: read "+
|
|
"returned unexpected error: %s", err)
|
|
}
|
|
|
|
// Make sure that all the appropriate files have been deleted
|
|
for i := fileNumberAfterWriting; i > fileNumberBeforeWriting; i-- {
|
|
filePath := flatFilePath(store.basePath, store.storeName, i)
|
|
if _, err := os.Stat(filePath); err == nil || !os.IsNotExist(err) {
|
|
t.Fatalf("TestFlatFileMultiFileRollback: file "+
|
|
"unexpectedly still exists: %s", filePath)
|
|
}
|
|
}
|
|
}
|