| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- // Copyright (C) 2014 The Syncthing Authors.
- //
- // This Source Code Form is subject to the terms of the Mozilla Public
- // License, v. 2.0. If a copy of the MPL was not distributed with this file,
- // You can obtain one at https://mozilla.org/MPL/2.0/.
- package db
- import (
- "testing"
- "github.com/syncthing/syncthing/lib/protocol"
- "github.com/syndtr/goleveldb/leveldb/util"
- )
- func genBlocks(n int) []protocol.BlockInfo {
- b := make([]protocol.BlockInfo, n)
- for i := range b {
- h := make([]byte, 32)
- for j := range h {
- h[j] = byte(i + j)
- }
- b[i].Size = int32(i)
- b[i].Hash = h
- }
- return b
- }
- var f1, f2, f3 protocol.FileInfo
- var folders = []string{"folder1", "folder2"}
- func init() {
- blocks := genBlocks(30)
- f1 = protocol.FileInfo{
- Name: "f1",
- Blocks: blocks[:10],
- }
- f2 = protocol.FileInfo{
- Name: "f2",
- Blocks: blocks[10:20],
- }
- f3 = protocol.FileInfo{
- Name: "f3",
- Blocks: blocks[20:],
- }
- }
- func setup() (*Instance, *BlockFinder) {
- // Setup
- db := OpenMemory()
- return db, NewBlockFinder(db)
- }
- func dbEmpty(db *Instance) bool {
- iter := db.NewIterator(util.BytesPrefix([]byte{KeyTypeBlock}), nil)
- defer iter.Release()
- return !iter.Next()
- }
- func TestBlockMapAddUpdateWipe(t *testing.T) {
- db, f := setup()
- if !dbEmpty(db) {
- t.Fatal("db not empty")
- }
- m := NewBlockMap(db, db.folderIdx.ID([]byte("folder1")))
- f3.Type = protocol.FileInfoTypeDirectory
- err := m.Add([]protocol.FileInfo{f1, f2, f3})
- if err != nil {
- t.Fatal(err)
- }
- f.Iterate(folders, f1.Blocks[0].Hash, func(folder, file string, index int32) bool {
- if folder != "folder1" || file != "f1" || index != 0 {
- t.Fatal("Mismatch")
- }
- return true
- })
- f.Iterate(folders, f2.Blocks[0].Hash, func(folder, file string, index int32) bool {
- if folder != "folder1" || file != "f2" || index != 0 {
- t.Fatal("Mismatch")
- }
- return true
- })
- f.Iterate(folders, f3.Blocks[0].Hash, func(folder, file string, index int32) bool {
- t.Fatal("Unexpected block")
- return true
- })
- f3.Permissions = f1.Permissions
- f3.Deleted = f1.Deleted
- f3.Invalid = f1.Invalid
- f1.Deleted = true
- f2.Invalid = true
- // Should remove
- err = m.Update([]protocol.FileInfo{f1, f2, f3})
- if err != nil {
- t.Fatal(err)
- }
- f.Iterate(folders, f1.Blocks[0].Hash, func(folder, file string, index int32) bool {
- t.Fatal("Unexpected block")
- return false
- })
- f.Iterate(folders, f2.Blocks[0].Hash, func(folder, file string, index int32) bool {
- t.Fatal("Unexpected block")
- return false
- })
- f.Iterate(folders, f3.Blocks[0].Hash, func(folder, file string, index int32) bool {
- if folder != "folder1" || file != "f3" || index != 0 {
- t.Fatal("Mismatch")
- }
- return true
- })
- err = m.Drop()
- if err != nil {
- t.Fatal(err)
- }
- if !dbEmpty(db) {
- t.Fatal("db not empty")
- }
- // Should not add
- err = m.Add([]protocol.FileInfo{f1, f2})
- if err != nil {
- t.Fatal(err)
- }
- if !dbEmpty(db) {
- t.Fatal("db not empty")
- }
- f1.Deleted = false
- f1.Invalid = false
- f1.Permissions = 0
- f2.Deleted = false
- f2.Invalid = false
- f2.Permissions = 0
- f3.Deleted = false
- f3.Invalid = false
- f3.Permissions = 0
- }
- func TestBlockFinderLookup(t *testing.T) {
- db, f := setup()
- m1 := NewBlockMap(db, db.folderIdx.ID([]byte("folder1")))
- m2 := NewBlockMap(db, db.folderIdx.ID([]byte("folder2")))
- err := m1.Add([]protocol.FileInfo{f1})
- if err != nil {
- t.Fatal(err)
- }
- err = m2.Add([]protocol.FileInfo{f1})
- if err != nil {
- t.Fatal(err)
- }
- counter := 0
- f.Iterate(folders, f1.Blocks[0].Hash, func(folder, file string, index int32) bool {
- counter++
- switch counter {
- case 1:
- if folder != "folder1" || file != "f1" || index != 0 {
- t.Fatal("Mismatch")
- }
- case 2:
- if folder != "folder2" || file != "f1" || index != 0 {
- t.Fatal("Mismatch")
- }
- default:
- t.Fatal("Unexpected block")
- }
- return false
- })
- if counter != 2 {
- t.Fatal("Incorrect count", counter)
- }
- f1.Deleted = true
- err = m1.Update([]protocol.FileInfo{f1})
- if err != nil {
- t.Fatal(err)
- }
- counter = 0
- f.Iterate(folders, f1.Blocks[0].Hash, func(folder, file string, index int32) bool {
- counter++
- switch counter {
- case 1:
- if folder != "folder2" || file != "f1" || index != 0 {
- t.Fatal("Mismatch")
- }
- default:
- t.Fatal("Unexpected block")
- }
- return false
- })
- if counter != 1 {
- t.Fatal("Incorrect count")
- }
- f1.Deleted = false
- }
- func TestBlockFinderFix(t *testing.T) {
- db, f := setup()
- iterFn := func(folder, file string, index int32) bool {
- return true
- }
- m := NewBlockMap(db, db.folderIdx.ID([]byte("folder1")))
- err := m.Add([]protocol.FileInfo{f1})
- if err != nil {
- t.Fatal(err)
- }
- if !f.Iterate(folders, f1.Blocks[0].Hash, iterFn) {
- t.Fatal("Block not found")
- }
- err = f.Fix("folder1", f1.Name, 0, f1.Blocks[0].Hash, f2.Blocks[0].Hash)
- if err != nil {
- t.Fatal(err)
- }
- if f.Iterate(folders, f1.Blocks[0].Hash, iterFn) {
- t.Fatal("Unexpected block")
- }
- if !f.Iterate(folders, f2.Blocks[0].Hash, iterFn) {
- t.Fatal("Block not found")
- }
- }
|