gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/host/network_test.go (about) 1 package host 2 3 import ( 4 "sync/atomic" 5 "testing" 6 "time" 7 8 "gitlab.com/SiaPrime/SiaPrime/build" 9 "gitlab.com/SiaPrime/SiaPrime/modules" 10 ) 11 12 // blockingPortForward is a dependency set that causes the host port forward 13 // call at startup to block for 10 seconds, simulating the amount of blocking 14 // that can occur in production. 15 // 16 // blockingPortForward will also cause managedClearPort to always return an 17 // error. 18 type blockingPortForward struct { 19 modules.ProductionDependencies 20 } 21 22 // disrupt will cause the port forward call to block for 10 seconds, but still 23 // complete normally. disrupt will also cause managedClearPort to return an 24 // error. 25 func (*blockingPortForward) Disrupt(s string) bool { 26 // Return an error when clearing the port. 27 if s == "managedClearPort return error" { 28 return true 29 } 30 31 // Block during port forwarding. 32 if s == "managedForwardPort" { 33 time.Sleep(time.Second * 3) 34 } 35 return false 36 } 37 38 // TestPortFowardBlocking checks that the host does not accidentally call a 39 // write on a closed logger due to a long-running port forward call. 40 func TestPortForwardBlocking(t *testing.T) { 41 if testing.Short() { 42 t.SkipNow() 43 } 44 t.Parallel() 45 ht, err := newMockHostTester(&blockingPortForward{}, "TestPortForwardBlocking") 46 if err != nil { 47 t.Fatal(err) 48 } 49 50 // The close operation would previously fail here because of improper 51 // thread control regarding upnp and shutdown. 52 err = ht.Close() 53 if err != nil { 54 t.Fatal(err) 55 } 56 57 // The trailing sleep is needed to catch the previously existing error 58 // where the host was not shutting down correctly. Currently, the extra 59 // sleep does nothing, but in the regression a logging panic would occur. 60 time.Sleep(time.Second * 4) 61 } 62 63 // TestHostWorkingStatus checks that the host properly updates its working 64 // state 65 func TestHostWorkingStatus(t *testing.T) { 66 if testing.Short() || !build.VLONG { 67 t.SkipNow() 68 } 69 t.Parallel() 70 71 ht, err := newHostTester(t.Name()) 72 if err != nil { 73 t.Fatal(err) 74 } 75 defer ht.Close() 76 77 // TODO: this causes an ndf, because it relies on the host tester starting up 78 // and fully returning faster than the first check, which isnt always the 79 // case. This check is disabled for now, but can be fixed by using the 80 // Disrupt() pattern. 81 // if ht.host.WorkingStatus() != modules.HostWorkingStatusChecking { 82 // t.Fatal("expected working state to initially be modules.HostWorkingStatusChecking") 83 // } 84 85 for i := 0; i < 5; i++ { 86 // Simulate some setting calls, and see if the host picks up on it. 87 atomic.AddUint64(&ht.host.atomicSettingsCalls, workingStatusThreshold+1) 88 89 success := false 90 for start := time.Now(); time.Since(start) < 30*time.Second; time.Sleep(time.Millisecond * 10) { 91 if ht.host.WorkingStatus() == modules.HostWorkingStatusWorking { 92 success = true 93 break 94 } 95 } 96 if !success { 97 t.Fatal("expected working state to flip to HostWorkingStatusWorking after incrementing settings calls") 98 } 99 100 // make no settings calls, host should flip back to NotWorking 101 success = false 102 for start := time.Now(); time.Since(start) < 30*time.Second; time.Sleep(time.Millisecond * 10) { 103 if ht.host.WorkingStatus() == modules.HostWorkingStatusNotWorking { 104 success = true 105 break 106 } 107 } 108 if !success { 109 t.Fatal("expected working state to flip to HostStatusNotWorking if no settings calls occur") 110 } 111 } 112 } 113 114 // TestHostConnectabilityStatus checks that the host properly updates its connectable 115 // state 116 func TestHostConnectabilityStatus(t *testing.T) { 117 if testing.Short() { 118 t.SkipNow() 119 } 120 t.Parallel() 121 ht, err := newHostTester(t.Name()) 122 if err != nil { 123 t.Fatal(err) 124 } 125 defer ht.Close() 126 127 // TODO: this causes an ndf, because it relies on the host tester starting up 128 // and fully returning faster than the first check, which isnt always the 129 // case. This check is disabled for now, but can be fixed by using the 130 // Disrupt() pattern. 131 // if ht.host.ConnectabilityStatus() != modules.HostConnectabilityStatusChecking { 132 // t.Fatal("expected connectability state to initially be ConnectablityStateChecking") 133 // } 134 135 success := false 136 for start := time.Now(); time.Since(start) < 30*time.Second; time.Sleep(time.Millisecond * 10) { 137 if ht.host.ConnectabilityStatus() == modules.HostConnectabilityStatusConnectable { 138 success = true 139 break 140 } 141 } 142 if !success { 143 t.Fatal("expected connectability state to flip to HostConnectabilityStatusConnectable") 144 } 145 }