github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/modules/renter/hostdb/persist_test.go (about)

     1  package hostdb
     2  
     3  import (
     4  	"crypto/rand"
     5  	"testing"
     6  
     7  	"github.com/NebulousLabs/Sia/modules"
     8  	"github.com/NebulousLabs/Sia/types"
     9  )
    10  
    11  // memPersist implements the persister interface in-memory.
    12  type memPersist hdbPersist
    13  
    14  func (m *memPersist) save(data hdbPersist) error     { *m = memPersist(data); return nil }
    15  func (m *memPersist) saveSync(data hdbPersist) error { *m = memPersist(data); return nil }
    16  func (m memPersist) load(data *hdbPersist) error     { *data = hdbPersist(m); return nil }
    17  
    18  // TestSaveLoad tests that the hostdb can save and load itself.
    19  func TestSaveLoad(t *testing.T) {
    20  	// create hostdb with mocked persist dependency
    21  	hdb := bareHostDB()
    22  	hdb.persist = new(memPersist)
    23  
    24  	// add some fake hosts
    25  	var host1, host2, host3 hostEntry
    26  	host1.NetAddress = "foo"
    27  	host2.NetAddress = "bar"
    28  	host3.NetAddress = "baz"
    29  	hdb.allHosts = map[modules.NetAddress]*hostEntry{
    30  		host1.NetAddress: &host1,
    31  		host2.NetAddress: &host2,
    32  		host3.NetAddress: &host3,
    33  	}
    34  	hdb.activeHosts = map[modules.NetAddress]*hostNode{
    35  		host1.NetAddress: {hostEntry: &host1},
    36  		host2.NetAddress: {hostEntry: &host2},
    37  		host3.NetAddress: {hostEntry: &host3},
    38  	}
    39  	hdb.lastChange = modules.ConsensusChangeID{1, 2, 3}
    40  
    41  	// save and reload
    42  	err := hdb.save()
    43  	if err != nil {
    44  		t.Fatal(err)
    45  	}
    46  	err = hdb.load()
    47  	if err != nil {
    48  		t.Fatal(err)
    49  	}
    50  
    51  	// check that LastChange was loaded
    52  	if hdb.lastChange != (modules.ConsensusChangeID{1, 2, 3}) {
    53  		t.Error("wrong consensus change ID was loaded:", hdb.lastChange)
    54  	}
    55  
    56  	// check that AllHosts was loaded
    57  	_, ok0 := hdb.allHosts[host1.NetAddress]
    58  	_, ok1 := hdb.allHosts[host2.NetAddress]
    59  	_, ok2 := hdb.allHosts[host3.NetAddress]
    60  	if !ok0 || !ok1 || !ok2 || len(hdb.allHosts) != 3 {
    61  		t.Fatal("allHosts was not restored properly:", hdb.allHosts)
    62  	}
    63  
    64  	// check that ActiveHosts was loaded
    65  	_, ok0 = hdb.activeHosts[host1.NetAddress]
    66  	_, ok1 = hdb.activeHosts[host2.NetAddress]
    67  	_, ok2 = hdb.activeHosts[host3.NetAddress]
    68  	if !ok0 || !ok1 || !ok2 || len(hdb.activeHosts) != 3 {
    69  		t.Fatal("active was not restored properly:", hdb.activeHosts)
    70  	}
    71  }
    72  
    73  // rescanCS is a barebones implementation of a consensus set that can be
    74  // subscribed to.
    75  type rescanCS struct {
    76  	changes []modules.ConsensusChange
    77  }
    78  
    79  func (cs *rescanCS) addBlock(b types.Block) {
    80  	cc := modules.ConsensusChange{
    81  		AppliedBlocks: []types.Block{b},
    82  	}
    83  	rand.Read(cc.ID[:])
    84  	cs.changes = append(cs.changes, cc)
    85  }
    86  
    87  func (cs *rescanCS) ConsensusSetSubscribe(s modules.ConsensusSetSubscriber, lastChange modules.ConsensusChangeID) error {
    88  	var start int
    89  	if lastChange != (modules.ConsensusChangeID{}) {
    90  		start = -1
    91  		for i, cc := range cs.changes {
    92  			if cc.ID == lastChange {
    93  				start = i
    94  				break
    95  			}
    96  		}
    97  		if start == -1 {
    98  			return modules.ErrInvalidConsensusChangeID
    99  		}
   100  	}
   101  	for _, cc := range cs.changes[start:] {
   102  		s.ProcessConsensusChange(cc)
   103  	}
   104  	return nil
   105  }
   106  
   107  // TestRescan tests that the hostdb will rescan the blockchain properly.
   108  func TestRescan(t *testing.T) {
   109  	// create hostdb with mocked persist dependency
   110  	hdb := bareHostDB()
   111  	hdb.persist = new(memPersist)
   112  
   113  	// add some fake hosts
   114  	var host1, host2, host3 hostEntry
   115  	host1.NetAddress = "foo"
   116  	host2.NetAddress = "bar"
   117  	host3.NetAddress = "baz"
   118  	hdb.allHosts = map[modules.NetAddress]*hostEntry{
   119  		host1.NetAddress: &host1,
   120  		host2.NetAddress: &host2,
   121  		host3.NetAddress: &host3,
   122  	}
   123  	hdb.activeHosts = map[modules.NetAddress]*hostNode{
   124  		host1.NetAddress: {hostEntry: &host1},
   125  		host2.NetAddress: {hostEntry: &host2},
   126  		host3.NetAddress: {hostEntry: &host3},
   127  	}
   128  
   129  	// use a bogus change ID
   130  	hdb.lastChange = modules.ConsensusChangeID{1, 2, 3}
   131  
   132  	// save the hostdb
   133  	err := hdb.save()
   134  	if err != nil {
   135  		t.Fatal(err)
   136  	}
   137  
   138  	// create a mocked consensus set with a different host announcement
   139  	annBytes, err := makeSignedAnnouncement("quux.com:1234")
   140  	if err != nil {
   141  		t.Fatal(err)
   142  	}
   143  	announceBlock := types.Block{
   144  		Transactions: []types.Transaction{{
   145  			ArbitraryData: [][]byte{annBytes},
   146  		}},
   147  	}
   148  	cs := new(rescanCS)
   149  	cs.addBlock(announceBlock)
   150  
   151  	// Reload the hostdb using the same persist and the mocked consensus set.
   152  	// The old change ID will be rejected, causing a rescan, which should
   153  	// discover the new announcement.
   154  	hdb, err = newHostDB(cs, stdDialer{}, stdSleeper{}, hdb.persist, hdb.log)
   155  	if err != nil {
   156  		t.Fatal(err)
   157  	}
   158  	if len(hdb.allHosts) != 1 {
   159  		t.Fatal("hostdb rescan resulted in wrong host set:", hdb.allHosts)
   160  	}
   161  	if _, exists := hdb.allHosts["quux.com:1234"]; !exists {
   162  		t.Fatal("hostdb rescan resulted in wrong host set:", hdb.allHosts)
   163  	}
   164  }