github.com/Synthesix/Sia@v1.3.3-0.20180413141344-f863baeed3ca/modules/renter/contractor/uptime_test.go (about) 1 package contractor 2 3 import ( 4 "errors" 5 "testing" 6 "time" 7 8 "github.com/Synthesix/Sia/build" 9 "github.com/Synthesix/Sia/modules" 10 "github.com/Synthesix/Sia/types" 11 ) 12 13 // TestIntegrationReplaceOffline tests that when a host goes offline, its 14 // contract is eventually replaced. 15 func TestIntegrationReplaceOffline(t *testing.T) { 16 if testing.Short() { 17 t.SkipNow() 18 } 19 h, c, m, err := newTestingTrio(t.Name()) 20 if err != nil { 21 t.Fatal(err) 22 } 23 24 // form a contract with h 25 c.SetAllowance(modules.Allowance{ 26 Funds: types.SiacoinPrecision.Mul64(250), 27 Hosts: 1, 28 Period: 50, 29 RenewWindow: 20, 30 }) 31 // Block until the contract is registered. 32 err = build.Retry(50, 100*time.Millisecond, func() error { 33 c.mu.Lock() 34 lenC := c.contracts.Len() 35 c.mu.Unlock() 36 if lenC < 1 { 37 return errors.New("allowance forming seems to have failed") 38 } 39 return nil 40 }) 41 if err != nil { 42 t.Log(len(c.Contracts())) 43 t.Error(err) 44 } 45 46 // Take the first host offline. 47 err = h.Close() 48 if err != nil { 49 t.Error(err) 50 } 51 // Block until the host is seen as offline. 52 hosts := c.hdb.AllHosts() 53 err = build.Retry(250, 250*time.Millisecond, func() error { 54 hosts = c.hdb.AllHosts() 55 if len(hosts) != 1 { 56 return errors.New("only expecting one host") 57 } 58 sh := hosts[0].ScanHistory 59 if sh[len(sh)-1].Success { 60 return errors.New("host is reporting as online") 61 } 62 return nil 63 }) 64 if err != nil { 65 t.Fatal(err) 66 } 67 68 // create another host 69 dir := build.TempDir("contractor", t.Name(), "Host2") 70 h2, err := newTestingHost(dir, c.cs.(modules.ConsensusSet), c.tpool.(modules.TransactionPool)) 71 if err != nil { 72 t.Fatal(err) 73 } 74 // Announce the second host. 75 err = h2.Announce() 76 if err != nil { 77 t.Fatal(err) 78 } 79 // Mine a block to get the announcement on-chain. 80 _, err = m.AddBlock() 81 if err != nil { 82 t.Fatal(err) 83 } 84 85 // Wait for a scan of the host to complete. 86 err = build.Retry(250, 250*time.Millisecond, func() error { 87 hosts = c.hdb.AllHosts() 88 if len(hosts) < 2 { 89 return errors.New("waiting for at least two hosts to show up") 90 } 91 for _, host := range hosts { 92 if len(host.ScanHistory) < 2 { 93 return errors.New("waiting for the hosts to have been scanned") 94 } 95 } 96 return nil 97 }) 98 if err != nil { 99 t.Fatal(err) 100 } 101 102 // Mine 3 blocks to trigger an allowance refresh, which should cause the 103 // second, online host to be picked up. Three are mined because mining just 104 // one was causing NDFs. 105 _, err = m.AddBlock() 106 if err != nil { 107 t.Fatal(err) 108 } 109 var numContracts int 110 err = build.Retry(250, 250*time.Millisecond, func() error { 111 numContracts = len(c.Contracts()) 112 if numContracts < 2 { 113 return errors.New("still waiting to form the second contract") 114 } 115 return nil 116 }) 117 if err != nil { 118 t.Fatal(err, numContracts) 119 } 120 }