This adds a thin type that holds the state associated with the leveldb.DB, leaving the huge Instance type more or less stateless. Also moves some keying stuff into the DB package so that other packages need not know the keying specifics. (This does not, yet, fix the cmd/stindex program, in order to keep the diff size down. Hence the keying constants are still exported.)
This commit is contained in:
+16
-106
@@ -7,107 +7,20 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
func TestDropIndexIDs(t *testing.T) {
|
||||
db := OpenMemory()
|
||||
|
||||
d1 := []byte("device67890123456789012345678901")
|
||||
d2 := []byte("device12345678901234567890123456")
|
||||
|
||||
// Set some index IDs
|
||||
|
||||
db.setIndexID(protocol.LocalDeviceID[:], []byte("foo"), 1)
|
||||
db.setIndexID(protocol.LocalDeviceID[:], []byte("bar"), 2)
|
||||
db.setIndexID(d1, []byte("foo"), 3)
|
||||
db.setIndexID(d1, []byte("bar"), 4)
|
||||
db.setIndexID(d2, []byte("foo"), 5)
|
||||
db.setIndexID(d2, []byte("bar"), 6)
|
||||
|
||||
// Verify them
|
||||
|
||||
if db.getIndexID(protocol.LocalDeviceID[:], []byte("foo")) != 1 {
|
||||
t.Fatal("fail local 1")
|
||||
}
|
||||
if db.getIndexID(protocol.LocalDeviceID[:], []byte("bar")) != 2 {
|
||||
t.Fatal("fail local 2")
|
||||
}
|
||||
if db.getIndexID(d1, []byte("foo")) != 3 {
|
||||
t.Fatal("fail remote 1")
|
||||
}
|
||||
if db.getIndexID(d1, []byte("bar")) != 4 {
|
||||
t.Fatal("fail remote 2")
|
||||
}
|
||||
if db.getIndexID(d2, []byte("foo")) != 5 {
|
||||
t.Fatal("fail remote 3")
|
||||
}
|
||||
if db.getIndexID(d2, []byte("bar")) != 6 {
|
||||
t.Fatal("fail remote 4")
|
||||
}
|
||||
|
||||
// Drop the local ones, verify only they got dropped
|
||||
|
||||
db.DropLocalDeltaIndexIDs()
|
||||
|
||||
if db.getIndexID(protocol.LocalDeviceID[:], []byte("foo")) != 0 {
|
||||
t.Fatal("fail local 1")
|
||||
}
|
||||
if db.getIndexID(protocol.LocalDeviceID[:], []byte("bar")) != 0 {
|
||||
t.Fatal("fail local 2")
|
||||
}
|
||||
if db.getIndexID(d1, []byte("foo")) != 3 {
|
||||
t.Fatal("fail remote 1")
|
||||
}
|
||||
if db.getIndexID(d1, []byte("bar")) != 4 {
|
||||
t.Fatal("fail remote 2")
|
||||
}
|
||||
if db.getIndexID(d2, []byte("foo")) != 5 {
|
||||
t.Fatal("fail remote 3")
|
||||
}
|
||||
if db.getIndexID(d2, []byte("bar")) != 6 {
|
||||
t.Fatal("fail remote 4")
|
||||
}
|
||||
|
||||
// Set local ones again
|
||||
|
||||
db.setIndexID(protocol.LocalDeviceID[:], []byte("foo"), 1)
|
||||
db.setIndexID(protocol.LocalDeviceID[:], []byte("bar"), 2)
|
||||
|
||||
// Drop the remote ones, verify only they got dropped
|
||||
|
||||
db.DropRemoteDeltaIndexIDs()
|
||||
|
||||
if db.getIndexID(protocol.LocalDeviceID[:], []byte("foo")) != 1 {
|
||||
t.Fatal("fail local 1")
|
||||
}
|
||||
if db.getIndexID(protocol.LocalDeviceID[:], []byte("bar")) != 2 {
|
||||
t.Fatal("fail local 2")
|
||||
}
|
||||
if db.getIndexID(d1, []byte("foo")) != 0 {
|
||||
t.Fatal("fail remote 1")
|
||||
}
|
||||
if db.getIndexID(d1, []byte("bar")) != 0 {
|
||||
t.Fatal("fail remote 2")
|
||||
}
|
||||
if db.getIndexID(d2, []byte("foo")) != 0 {
|
||||
t.Fatal("fail remote 3")
|
||||
}
|
||||
if db.getIndexID(d2, []byte("bar")) != 0 {
|
||||
t.Fatal("fail remote 4")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIgnoredFiles(t *testing.T) {
|
||||
ldb, err := openJSONS("testdata/v0.14.48-ignoredfiles.db.jsons")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
db, _ := newDBInstance(ldb, "<memory>")
|
||||
db := NewLowlevel(ldb, "<memory>")
|
||||
UpdateSchema(db)
|
||||
|
||||
fs := NewFileSet("test", fs.NewFilesystem(fs.FilesystemTypeBasic, "."), db)
|
||||
|
||||
// The contents of the database are like this:
|
||||
@@ -228,11 +141,13 @@ func TestUpdate0to3(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
db, _ := newDBInstance(ldb, "<memory>")
|
||||
|
||||
db := newInstance(NewLowlevel(ldb, "<memory>"))
|
||||
updater := schemaUpdater{db}
|
||||
|
||||
folder := []byte(update0to3Folder)
|
||||
|
||||
db.updateSchema0to1()
|
||||
updater.updateSchema0to1()
|
||||
|
||||
if _, ok := db.getFile(db.keyer.GenerateDeviceFileKey(nil, folder, protocol.LocalDeviceID[:], []byte(slashPrefixed))); ok {
|
||||
t.Error("File prefixed by '/' was not removed during transition to schema 1")
|
||||
@@ -242,7 +157,7 @@ func TestUpdate0to3(t *testing.T) {
|
||||
t.Error("Invalid file wasn't added to global list")
|
||||
}
|
||||
|
||||
db.updateSchema1to2()
|
||||
updater.updateSchema1to2()
|
||||
|
||||
found := false
|
||||
db.withHaveSequence(folder, 0, func(fi FileIntf) bool {
|
||||
@@ -263,7 +178,7 @@ func TestUpdate0to3(t *testing.T) {
|
||||
t.Error("Local file wasn't added to sequence bucket", err)
|
||||
}
|
||||
|
||||
db.updateSchema2to3()
|
||||
updater.updateSchema2to3()
|
||||
|
||||
need := map[string]protocol.FileInfo{
|
||||
haveUpdate0to3[remoteDevice0][0].Name: haveUpdate0to3[remoteDevice0][0],
|
||||
@@ -288,22 +203,17 @@ func TestUpdate0to3(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDowngrade(t *testing.T) {
|
||||
loc := "testdata/downgrade.db"
|
||||
db, err := Open(loc)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
db.Close()
|
||||
os.RemoveAll(loc)
|
||||
}()
|
||||
db := OpenMemory()
|
||||
UpdateSchema(db) // sets the min version etc
|
||||
|
||||
miscDB := NewNamespacedKV(db, string(KeyTypeMiscData))
|
||||
// Bump the database version to something newer than we actually support
|
||||
miscDB := NewMiscDataNamespace(db)
|
||||
miscDB.PutInt64("dbVersion", dbVersion+1)
|
||||
l.Infoln(dbVersion)
|
||||
|
||||
db.Close()
|
||||
db, err = Open(loc)
|
||||
// Pretend we just opened the DB and attempt to update it again
|
||||
err := UpdateSchema(db)
|
||||
|
||||
if err, ok := err.(databaseDowngradeError); !ok {
|
||||
t.Fatal("Expected error due to database downgrade, got", err)
|
||||
} else if err.minSyncthingVersion != dbMinSyncthingVersion {
|
||||
|
||||
Reference in New Issue
Block a user