gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/host/contractmanager/contractmanager_test.go (about) 1 package contractmanager 2 3 import ( 4 "errors" 5 "os" 6 "path/filepath" 7 "testing" 8 9 "gitlab.com/SiaPrime/SiaPrime/build" 10 "gitlab.com/SiaPrime/SiaPrime/modules" 11 ) 12 13 // contractManagerTester holds a contract manager along with some other fields 14 // useful for testing, and has methods implemented on it that can assist 15 // testing. 16 type contractManagerTester struct { 17 cm *ContractManager 18 19 persistDir string 20 } 21 22 // panicClose will attempt to call Close on the contract manager tester. If 23 // there is an error, the function will panic. A convenient function for making 24 // sure that the cleanup code is always running correctly, without needing to 25 // write a lot of boiler code. 26 func (cmt *contractManagerTester) panicClose() { 27 err := cmt.Close() 28 if err != nil { 29 panic(err) 30 } 31 } 32 33 // Close will perform clean shutdown on the contract manager tester. 34 func (cmt *contractManagerTester) Close() error { 35 if cmt.cm == nil { 36 return errors.New("nil contract manager") 37 } 38 return cmt.cm.Close() 39 } 40 41 // newContractManagerTester returns a ready-to-rock contract manager tester. 42 func newContractManagerTester(name string) (*contractManagerTester, error) { 43 if testing.Short() { 44 panic("use of newContractManagerTester during short testing") 45 } 46 47 testdir := build.TempDir(modules.ContractManagerDir, name) 48 cm, err := New(filepath.Join(testdir, modules.ContractManagerDir)) 49 if err != nil { 50 return nil, err 51 } 52 cmt := &contractManagerTester{ 53 cm: cm, 54 persistDir: testdir, 55 } 56 return cmt, nil 57 } 58 59 // newMockedContractManagerTester returns a contract manager tester that uses 60 // the input dependencies instead of the production ones. 61 func newMockedContractManagerTester(d modules.Dependencies, name string) (*contractManagerTester, error) { 62 if testing.Short() { 63 panic("use of newContractManagerTester during short testing") 64 } 65 66 testdir := build.TempDir(modules.ContractManagerDir, name) 67 cm, err := newContractManager(d, filepath.Join(testdir, modules.ContractManagerDir)) 68 if err != nil { 69 return nil, err 70 } 71 cmt := &contractManagerTester{ 72 cm: cm, 73 persistDir: testdir, 74 } 75 return cmt, nil 76 } 77 78 // TestNewContractManager does basic startup and shutdown of a contract 79 // manager, checking for egregious errors. 80 func TestNewContractManager(t *testing.T) { 81 if testing.Short() { 82 t.SkipNow() 83 } 84 t.Parallel() 85 86 // Create a contract manager. 87 parentDir := build.TempDir(modules.ContractManagerDir, "TestNewContractManager") 88 cmDir := filepath.Join(parentDir, modules.ContractManagerDir) 89 cm, err := New(cmDir) 90 if err != nil { 91 t.Fatal(err) 92 } 93 // Close the contract manager. 94 err = cm.Close() 95 if err != nil { 96 t.Fatal(err) 97 } 98 99 // Create a new contract manager using the same directory. 100 cm, err = New(cmDir) 101 if err != nil { 102 t.Fatal(err) 103 } 104 // Close it again. 105 err = cm.Close() 106 if err != nil { 107 t.Fatal(err) 108 } 109 } 110 111 // dependencyErroredStartupis a mocked dependency that will cause the contract 112 // manager to be returned with an error upon startup. 113 type dependencyErroredStartup struct { 114 modules.ProductionDependencies 115 } 116 117 // disrupt will disrupt the threadedSyncLoop, causing the loop to terminate as 118 // soon as it is created. 119 func (d *dependencyErroredStartup) Disrupt(s string) bool { 120 // Cause an error to be returned during startup. 121 if s == "erroredStartup" { 122 return true 123 } 124 return false 125 } 126 127 // TestNewContractManagerErroredStartup uses disruption to simulate an error 128 // during startup, allowing the test to verify that the cleanup code ran 129 // correctly. 130 func TestNewContractManagerErroredStartup(t *testing.T) { 131 if testing.Short() { 132 t.SkipNow() 133 } 134 t.Parallel() 135 136 // Create a new contract manager where the startup gets disrupted. 137 d := new(dependencyErroredStartup) 138 testdir := build.TempDir(modules.ContractManagerDir, "TestNewContractManagerErroredStartup") 139 cmd := filepath.Join(testdir, modules.ContractManagerDir) 140 _, err := newContractManager(d, cmd) 141 if err == nil || err.Error() != "startup disrupted" { 142 t.Fatal("expecting contract manager startup to be disrupted:", err) 143 } 144 145 // Verify that shutdown was triggered correctly - tmp files should be gone, 146 // WAL file should also be gone. 147 walFileName := filepath.Join(cmd, walFile) 148 walFileTmpName := filepath.Join(cmd, walFileTmp) 149 settingsFileTmpName := filepath.Join(cmd, settingsFileTmp) 150 _, err = os.Stat(walFileName) 151 if !os.IsNotExist(err) { 152 t.Error("file should have been removed:", err) 153 } 154 _, err = os.Stat(walFileTmpName) 155 if !os.IsNotExist(err) { 156 t.Error("file should have been removed:", err) 157 } 158 _, err = os.Stat(settingsFileTmpName) 159 if !os.IsNotExist(err) { 160 t.Error("file should have been removed:", err) 161 } 162 }