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  }