gitlab.com/SkynetLabs/skyd@v1.6.9/skymodules/renter/hostdb/persist_test.go (about)

     1  package hostdb
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  	"testing"
     7  	"time"
     8  
     9  	"gitlab.com/NebulousLabs/errors"
    10  	"gitlab.com/NebulousLabs/fastrand"
    11  
    12  	"gitlab.com/SkynetLabs/skyd/build"
    13  	"gitlab.com/SkynetLabs/skyd/skymodules"
    14  	"go.sia.tech/siad/modules"
    15  	"go.sia.tech/siad/types"
    16  )
    17  
    18  // quitAfterLoadDeps will quit startup in newHostDB
    19  type quitAfterLoadDeps struct {
    20  	modules.ProductionDependencies
    21  }
    22  
    23  // Send a disrupt signal to the quitAfterLoad codebreak.
    24  func (*quitAfterLoadDeps) Disrupt(s string) bool {
    25  	if s == "quitAfterLoad" {
    26  		return true
    27  	}
    28  	return false
    29  }
    30  
    31  // TestSaveLoad tests that the hostdb can save and load itself.
    32  func TestSaveLoad(t *testing.T) {
    33  	if testing.Short() {
    34  		t.SkipNow()
    35  	}
    36  	t.Parallel()
    37  	hdbt, err := newHDBTester(t.Name())
    38  	if err != nil {
    39  		t.Fatal(err)
    40  	}
    41  
    42  	// Mine two blocks to put the hdb height at 2.
    43  	for i := 0; i < 2; i++ {
    44  		_, err := hdbt.miner.AddBlock()
    45  		if err != nil {
    46  			t.Fatal(err)
    47  		}
    48  	}
    49  
    50  	// Verify that the hdb height is 2.
    51  	if hdbt.hdb.blockHeight != 2 {
    52  		t.Fatal("test setup incorrect, hdb height needs to be 2 for remainder of test")
    53  	}
    54  
    55  	// Add fake hosts and a fake consensus change. The fake consensus change
    56  	// would normally be detected and routed around, but we stunt the loading
    57  	// process to only load the persistent fields.
    58  	var host1, host2, host3 skymodules.HostDBEntry
    59  	host1.FirstSeen = 1
    60  	host2.FirstSeen = 2
    61  	host3.FirstSeen = 3
    62  	host1.PublicKey.Key = fastrand.Bytes(32)
    63  	host2.PublicKey.Key = fastrand.Bytes(32)
    64  	host3.PublicKey.Key = []byte("baz")
    65  	hdbt.hdb.staticHostTree.Insert(host1)
    66  	hdbt.hdb.staticHostTree.Insert(host2)
    67  	hdbt.hdb.staticHostTree.Insert(host3)
    68  
    69  	// Manually set listed Hosts and filterMode
    70  	filteredHosts := make(map[string]types.SiaPublicKey)
    71  	filteredHosts[host1.PublicKey.String()] = host1.PublicKey
    72  	filteredHosts[host2.PublicKey.String()] = host2.PublicKey
    73  	filteredHosts[host3.PublicKey.String()] = host3.PublicKey
    74  	filterMode := skymodules.HostDBActiveWhitelist
    75  
    76  	// Manually set list of blocked domains
    77  	badDomain := "baddomain.com"
    78  	blockedDomains := []string{badDomain}
    79  
    80  	// Save, close, and reload.
    81  	hdbt.hdb.mu.Lock()
    82  	hdbt.hdb.lastChange = modules.ConsensusChangeID{1, 2, 3}
    83  	hdbt.hdb.disableIPViolationCheck = true
    84  	stashedLC := hdbt.hdb.lastChange
    85  	hdbt.hdb.filteredHosts = filteredHosts
    86  	hdbt.hdb.filterMode = filterMode
    87  	hdbt.hdb.staticBlockedDomains = newBlockedDomains(blockedDomains)
    88  	err = hdbt.hdb.saveSync()
    89  	hdbt.hdb.mu.Unlock()
    90  	if err != nil {
    91  		t.Fatal(err)
    92  	}
    93  	err = hdbt.hdb.Close()
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  	var errChan <-chan error
    98  	hdbt.hdb, errChan = NewCustomHostDB(hdbt.gateway, hdbt.cs, hdbt.tpool, hdbt.mux, filepath.Join(hdbt.persistDir, skymodules.RenterDir), &quitAfterLoadDeps{})
    99  	if err := <-errChan; err != nil {
   100  		t.Fatal(err)
   101  	}
   102  
   103  	// Last change and disableIPViolationCheck should have been reloaded.
   104  	err = build.Retry(100, 100*time.Millisecond, func() error {
   105  		hdbt.hdb.mu.Lock()
   106  		lastChange := hdbt.hdb.lastChange
   107  		disableIPViolationCheck := hdbt.hdb.disableIPViolationCheck
   108  		hdbt.hdb.mu.Unlock()
   109  		if lastChange != stashedLC {
   110  			return fmt.Errorf("wrong consensus change ID was loaded: %v", hdbt.hdb.lastChange)
   111  		}
   112  		if disableIPViolationCheck != true {
   113  			return errors.New("disableIPViolationCheck should've been true but was false")
   114  		}
   115  		return nil
   116  	})
   117  	if err != nil {
   118  		t.Error(err)
   119  	}
   120  
   121  	// Check that AllHosts was loaded.
   122  	h1, ok0 := hdbt.hdb.staticHostTree.Select(host1.PublicKey)
   123  	h2, ok1 := hdbt.hdb.staticHostTree.Select(host2.PublicKey)
   124  	h3, ok2 := hdbt.hdb.staticHostTree.Select(host3.PublicKey)
   125  	if !ok0 || !ok1 || !ok2 || len(hdbt.hdb.staticHostTree.All()) != 3 {
   126  		t.Error("allHosts was not restored properly", ok0, ok1, ok2, len(hdbt.hdb.staticHostTree.All()))
   127  	}
   128  	if h1.FirstSeen != 1 {
   129  		t.Error("h1 block height loaded incorrectly", h1.FirstSeen)
   130  	}
   131  	if h2.FirstSeen != 2 {
   132  		t.Error("h2 block height loaded incorrectly", h2.FirstSeen)
   133  	}
   134  	if h3.FirstSeen != 3 {
   135  		t.Error("h3 block height loaded incorrectly", h3.FirstSeen)
   136  	}
   137  
   138  	// Check that FilterMode was saved
   139  	if hdbt.hdb.filterMode != skymodules.HostDBActiveWhitelist {
   140  		t.Error("filter mode should be whitelist")
   141  	}
   142  	if _, ok := hdbt.hdb.filteredHosts[host1.PublicKey.String()]; !ok {
   143  		t.Error("host1 not found in filteredHosts")
   144  	}
   145  	if _, ok := hdbt.hdb.filteredHosts[host2.PublicKey.String()]; !ok {
   146  		t.Error("host2 not found in filteredHosts")
   147  	}
   148  	if _, ok := hdbt.hdb.filteredHosts[host3.PublicKey.String()]; !ok {
   149  		t.Error("host3 not found in filteredHosts")
   150  	}
   151  
   152  	// Check that the blocked domains were saved
   153  	bd := hdbt.hdb.staticBlockedDomains
   154  	bd.mu.Lock()
   155  	_, ok := bd.domains[badDomain]
   156  	bd.mu.Unlock()
   157  	if !ok {
   158  		t.Fatal("badDomain not found in blockedDomains", hdbt.hdb.staticBlockedDomains)
   159  	}
   160  }
   161  
   162  // TestRescan tests that the hostdb will rescan the blockchain properly, picking
   163  // up new hosts which appear in an alternate past.
   164  func TestRescan(t *testing.T) {
   165  	if testing.Short() {
   166  		t.SkipNow()
   167  	}
   168  	_, err := newHDBTester(t.Name())
   169  	if err != nil {
   170  		t.Fatal(err)
   171  	}
   172  
   173  	t.Skip("create two consensus sets with blocks + announcements")
   174  }