gitlab.com/jokerrs1/Sia@v1.3.2/modules/renter/renter_test.go (about) 1 package renter 2 3 import ( 4 "path/filepath" 5 "reflect" 6 "testing" 7 8 "github.com/NebulousLabs/Sia/build" 9 "github.com/NebulousLabs/Sia/crypto" 10 "github.com/NebulousLabs/Sia/modules" 11 "github.com/NebulousLabs/Sia/modules/consensus" 12 "github.com/NebulousLabs/Sia/modules/gateway" 13 "github.com/NebulousLabs/Sia/modules/miner" 14 "github.com/NebulousLabs/Sia/modules/renter/contractor" 15 "github.com/NebulousLabs/Sia/modules/transactionpool" 16 "github.com/NebulousLabs/Sia/modules/wallet" 17 "github.com/NebulousLabs/Sia/types" 18 ) 19 20 // renterTester contains all of the modules that are used while testing the renter. 21 type renterTester struct { 22 cs modules.ConsensusSet 23 gateway modules.Gateway 24 miner modules.TestMiner 25 tpool modules.TransactionPool 26 wallet modules.Wallet 27 walletKey crypto.TwofishKey 28 29 renter *Renter 30 } 31 32 // Close shuts down the renter tester. 33 func (rt *renterTester) Close() error { 34 rt.wallet.Lock() 35 rt.cs.Close() 36 rt.gateway.Close() 37 return nil 38 } 39 40 // newRenterTester creates a ready-to-use renter tester with money in the 41 // wallet. 42 func newRenterTester(name string) (*renterTester, error) { 43 // Create the modules. 44 testdir := build.TempDir("renter", name) 45 g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir)) 46 if err != nil { 47 return nil, err 48 } 49 cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir)) 50 if err != nil { 51 return nil, err 52 } 53 tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir)) 54 if err != nil { 55 return nil, err 56 } 57 w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir)) 58 if err != nil { 59 return nil, err 60 } 61 key := crypto.GenerateTwofishKey() 62 _, err = w.Encrypt(key) 63 if err != nil { 64 return nil, err 65 } 66 err = w.Unlock(key) 67 if err != nil { 68 return nil, err 69 } 70 r, err := New(g, cs, w, tp, filepath.Join(testdir, modules.RenterDir)) 71 if err != nil { 72 return nil, err 73 } 74 m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir)) 75 if err != nil { 76 return nil, err 77 } 78 79 // Assemble all pieces into a renter tester. 80 rt := &renterTester{ 81 cs: cs, 82 gateway: g, 83 miner: m, 84 tpool: tp, 85 wallet: w, 86 87 renter: r, 88 } 89 90 // Mine blocks until there is money in the wallet. 91 for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ { 92 _, err := rt.miner.AddBlock() 93 if err != nil { 94 return nil, err 95 } 96 } 97 return rt, nil 98 } 99 100 // newContractorTester creates a renterTester, but with the supplied 101 // hostContractor. 102 func newContractorTester(name string, hdb hostDB, hc hostContractor) (*renterTester, error) { 103 // Create the modules. 104 testdir := build.TempDir("renter", name) 105 g, err := gateway.New("localhost:0", false, filepath.Join(testdir, modules.GatewayDir)) 106 if err != nil { 107 return nil, err 108 } 109 cs, err := consensus.New(g, false, filepath.Join(testdir, modules.ConsensusDir)) 110 if err != nil { 111 return nil, err 112 } 113 tp, err := transactionpool.New(cs, g, filepath.Join(testdir, modules.TransactionPoolDir)) 114 if err != nil { 115 return nil, err 116 } 117 w, err := wallet.New(cs, tp, filepath.Join(testdir, modules.WalletDir)) 118 if err != nil { 119 return nil, err 120 } 121 key := crypto.GenerateTwofishKey() 122 _, err = w.Encrypt(key) 123 if err != nil { 124 return nil, err 125 } 126 err = w.Unlock(key) 127 if err != nil { 128 return nil, err 129 } 130 r, err := newRenter(g, cs, tp, hdb, hc, filepath.Join(testdir, modules.RenterDir)) 131 if err != nil { 132 return nil, err 133 } 134 m, err := miner.New(cs, tp, w, filepath.Join(testdir, modules.MinerDir)) 135 if err != nil { 136 return nil, err 137 } 138 139 // Assemble all pieces into a renter tester. 140 rt := &renterTester{ 141 cs: cs, 142 gateway: g, 143 miner: m, 144 tpool: tp, 145 wallet: w, 146 147 renter: r, 148 } 149 150 // Mine blocks until there is money in the wallet. 151 for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ { 152 _, err := rt.miner.AddBlock() 153 if err != nil { 154 return nil, err 155 } 156 } 157 return rt, nil 158 } 159 160 // stubHostDB is the minimal implementation of the hostDB interface. It can be 161 // embedded in other mock hostDB types, removing the need to reimplement all 162 // of the hostDB's methods on every mock. 163 type stubHostDB struct{} 164 165 func (stubHostDB) ActiveHosts() []modules.HostDBEntry { return nil } 166 func (stubHostDB) AllHosts() []modules.HostDBEntry { return nil } 167 func (stubHostDB) AverageContractPrice() types.Currency { return types.Currency{} } 168 func (stubHostDB) Close() error { return nil } 169 func (stubHostDB) IsOffline(modules.NetAddress) bool { return true } 170 func (stubHostDB) RandomHosts(int, []types.SiaPublicKey) []modules.HostDBEntry { 171 return []modules.HostDBEntry{} 172 } 173 func (stubHostDB) EstimateHostScore(modules.HostDBEntry) modules.HostScoreBreakdown { 174 return modules.HostScoreBreakdown{} 175 } 176 func (stubHostDB) Host(types.SiaPublicKey) (modules.HostDBEntry, bool) { 177 return modules.HostDBEntry{}, false 178 } 179 func (stubHostDB) ScoreBreakdown(modules.HostDBEntry) modules.HostScoreBreakdown { 180 return modules.HostScoreBreakdown{} 181 } 182 183 // stubContractor is the minimal implementation of the hostContractor 184 // interface. 185 type stubContractor struct{} 186 187 func (stubContractor) SetAllowance(modules.Allowance) error { return nil } 188 func (stubContractor) Allowance() modules.Allowance { return modules.Allowance{} } 189 func (stubContractor) Contract(modules.NetAddress) (modules.RenterContract, bool) { 190 return modules.RenterContract{}, false 191 } 192 func (stubContractor) Contracts() []modules.RenterContract { return nil } 193 func (stubContractor) CurrentPeriod() types.BlockHeight { return 0 } 194 func (stubContractor) IsOffline(modules.NetAddress) bool { return false } 195 func (stubContractor) Editor(types.FileContractID) (contractor.Editor, error) { return nil, nil } 196 func (stubContractor) Downloader(types.FileContractID) (contractor.Downloader, error) { 197 return nil, nil 198 } 199 200 type pricesStub struct { 201 stubHostDB 202 203 dbEntries []modules.HostDBEntry 204 } 205 206 func (ps pricesStub) RandomHosts(n int, exclude []types.SiaPublicKey) []modules.HostDBEntry { 207 return ps.dbEntries 208 } 209 210 // TestRenterPricesVolatility verifies that the renter caches its price 211 // estimation, and subsequent calls result in non-volatile results. 212 func TestRenterPricesVolatility(t *testing.T) { 213 if testing.Short() { 214 t.SkipNow() 215 } 216 rt, err := newRenterTester(t.Name()) 217 if err != nil { 218 t.Fatal(err) 219 } 220 defer rt.Close() 221 222 // create a stubbed hostdb, query it with one contract, add another, verify 223 // the price estimation remains constant until the timeout has passed. 224 hdb := &pricesStub{} 225 id := rt.renter.mu.Lock() 226 rt.renter.hostDB = hdb 227 rt.renter.mu.Unlock(id) 228 dbe := modules.HostDBEntry{} 229 dbe.ContractPrice = types.SiacoinPrecision 230 dbe.DownloadBandwidthPrice = types.SiacoinPrecision 231 dbe.StoragePrice = types.SiacoinPrecision 232 dbe.UploadBandwidthPrice = types.SiacoinPrecision 233 hdb.dbEntries = append(hdb.dbEntries, dbe) 234 initial := rt.renter.PriceEstimation() 235 dbe.ContractPrice = dbe.ContractPrice.Mul64(2) 236 hdb.dbEntries = append(hdb.dbEntries, dbe) 237 after := rt.renter.PriceEstimation() 238 if !reflect.DeepEqual(initial, after) { 239 t.Log(initial) 240 t.Log(after) 241 t.Fatal("expected renter price estimation to be constant") 242 } 243 _, err = rt.miner.AddBlock() 244 if err != nil { 245 t.Fatal(err) 246 } 247 after = rt.renter.PriceEstimation() 248 if reflect.DeepEqual(initial, after) { 249 t.Fatal("expected renter price estimation to change after mining a block") 250 } 251 }