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 }