github.com/braveheart12/insolar-09-08-19@v0.8.7/functest/main_test.go (about) 1 // +build functest 2 3 /* 4 * Copyright 2019 Insolar Technologies 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package functest 20 21 import ( 22 "bufio" 23 "encoding/json" 24 "fmt" 25 "go/build" 26 "io" 27 "io/ioutil" 28 "os" 29 "os/exec" 30 "path/filepath" 31 "strings" 32 "syscall" 33 "testing" 34 "time" 35 36 yaml "gopkg.in/yaml.v2" 37 38 "github.com/insolar/insolar/api/requester" 39 "github.com/insolar/insolar/core" 40 "github.com/insolar/insolar/logicrunner/goplugin/goplugintestutils" 41 "github.com/pkg/errors" 42 ) 43 44 const HOST = "http://localhost:19101" 45 const TestAPIURL = HOST + "/api" 46 const TestRPCUrl = TestAPIURL + "/rpc" 47 const TestCallUrl = TestAPIURL + "/call" 48 49 const insolarRootMemberKeys = "root_member_keys.json" 50 51 const conf_dir = "../scripts/insolard/" 52 53 var cmd *exec.Cmd 54 var cmdCompleted = make(chan error, 1) 55 var stdin io.WriteCloser 56 var stdout io.ReadCloser 57 var stderr io.ReadCloser 58 59 var insolarRootMemberKeysPath = filepath.Join(conf_dir+"/configs", insolarRootMemberKeys) 60 61 var info *requester.InfoResponse 62 var root user 63 64 type user struct { 65 ref string 66 privKey string 67 pubKey string 68 } 69 70 func getNumberNodes() (int, error) { 71 type genesisConf struct { 72 DiscoverNodes []interface{} `yaml:"discovery_nodes"` 73 } 74 75 var conf genesisConf 76 77 buff, err := ioutil.ReadFile(conf_dir + "/genesis.yaml") 78 if err != nil { 79 return 0, errors.Wrap(err, "[ getNumberNodes ] Can't read genesis conf") 80 } 81 82 err = yaml.Unmarshal(buff, &conf) 83 if err != nil { 84 return 0, errors.Wrap(err, "[ getNumberNodes ] Can't parse genesis conf") 85 } 86 87 return len(conf.DiscoverNodes), nil 88 } 89 90 func functestPath() string { 91 p, err := build.Default.Import("github.com/insolar/insolar", "", build.FindOnly) 92 if err != nil { 93 panic(err) 94 } 95 return filepath.Join(p.Dir, "functest") 96 } 97 98 func createDirForContracts() error { 99 return os.MkdirAll(filepath.Join(functestPath(), "contractstorage"), 0777) 100 } 101 102 func deleteDirForContracts() error { 103 return os.RemoveAll(filepath.Join(functestPath(), "contractstorage")) 104 } 105 106 func loadRootKeys() error { 107 text, err := ioutil.ReadFile(insolarRootMemberKeysPath) 108 if err != nil { 109 return errors.Wrapf(err, "[ loadRootKeys ] could't load root keys") 110 } 111 var data map[string]string 112 err = json.Unmarshal(text, &data) 113 if err != nil { 114 return errors.Wrapf(err, "[ loadRootKeys ] could't unmarshal root keys") 115 } 116 if data["private_key"] == "" || data["public_key"] == "" { 117 return errors.New("[ loadRootKeys ] could't find any keys") 118 } 119 root.privKey = data["private_key"] 120 root.pubKey = data["public_key"] 121 122 return nil 123 } 124 125 func setInfo() error { 126 var err error 127 info, err = requester.Info(TestAPIURL) 128 if err != nil { 129 return errors.Wrap(err, "[ setInfo ] error sending request") 130 } 131 return nil 132 } 133 134 var insgorundPath string 135 136 func buildGinsiderCLI() (err error) { 137 insgorundPath, _, err = goplugintestutils.Build() 138 return errors.Wrap(err, "[ buildGinsiderCLI ] could't build ginsider CLI: ") 139 } 140 141 func stopInsolard() error { 142 if stdin != nil { 143 defer stdin.Close() 144 } 145 if stdout != nil { 146 defer stdout.Close() 147 } 148 149 if cmd == nil || cmd.Process == nil { 150 return nil 151 } 152 153 err := cmd.Process.Signal(syscall.SIGHUP) 154 if err != nil { 155 return errors.Wrap(err, "[ stopInsolard ] failed to kill process:") 156 } 157 158 pState, err := cmd.Process.Wait() 159 if err != nil { 160 return errors.Wrap(err, "[ stopInsolard ] failed to wait process:") 161 } 162 163 fmt.Println("[ stopInsolard ] State: ", pState.String()) 164 165 return nil 166 } 167 168 var insgorundCleaner func() 169 var secondInsgorundCleaner func() 170 171 func startInsgorund(listenPort string, upstreamPort string) (func(), error) { 172 // It starts on ports of "virtual" node 173 cleaner, err := goplugintestutils.StartInsgorund(insgorundPath, "tcp", "127.0.0.1:"+listenPort, "tcp", "127.0.0.1:"+upstreamPort) 174 if err != nil { 175 return cleaner, errors.Wrap(err, "[ startInsgorund ] couldn't wait for insolard to start completely: ") 176 } 177 return cleaner, nil 178 } 179 180 func startAllInsgorunds() (err error) { 181 insgorundCleaner, err = startInsgorund("33305", "33306") 182 if err != nil { 183 return errors.Wrap(err, "[ setup ] could't start insgorund: ") 184 } 185 fmt.Println("[ startAllInsgorunds ] insgorund was successfully started") 186 187 secondInsgorundCleaner, err = startInsgorund("33327", "33328") 188 if err != nil { 189 return errors.Wrap(err, "[ setup ] could't start second insgorund: ") 190 } 191 fmt.Println("[ startAllInsgorunds ] second insgorund was successfully started") 192 193 return nil 194 } 195 196 func stopAllInsgorunds() error { 197 if insgorundCleaner == nil || secondInsgorundCleaner == nil { 198 return errors.New("[ stopInsgorund ] cleaner func not found") 199 } 200 insgorundCleaner() 201 secondInsgorundCleaner() 202 return nil 203 } 204 205 func waitForNet() error { 206 numAttempts := 90 207 ports := []string{"19101", "19102", "19103", "19104", "19105"} 208 numNodes := len(ports) 209 currentOk := 0 210 for i := 0; i < numAttempts; i++ { 211 currentOk = 0 212 for _, port := range ports { 213 resp, err := requester.Status(fmt.Sprintf("http://127.0.0.1:%s/api", port)) 214 if err != nil { 215 fmt.Println("[ waitForNet ] Problem with port " + port + ". Err: " + err.Error()) 216 break 217 } 218 if resp.NetworkState != core.CompleteNetworkState.String() { 219 fmt.Println("[ waitForNet ] Good response from port " + port + ". Net is not ready. Response: " + resp.NetworkState) 220 break 221 } 222 fmt.Println("[ waitForNet ] Good response from port " + port + ". Net is ready. Response: " + resp.NetworkState) 223 currentOk++ 224 } 225 if currentOk == numNodes { 226 fmt.Printf("[ waitForNet ] All %d nodes have started\n", numNodes) 227 break 228 } 229 230 time.Sleep(time.Second) 231 fmt.Printf("[ waitForNet ] Waiting for net: attempt %d/%d\n", i, numAttempts) 232 } 233 234 if currentOk != numNodes { 235 return errors.New("[ waitForNet ] Can't Start net: No attempts left") 236 } 237 238 return nil 239 } 240 241 func startNet() error { 242 cwd, err := os.Getwd() 243 if err != nil { 244 return errors.Wrap(err, "[ startNet ] Can't get current working directory") 245 } 246 defer os.Chdir(cwd) 247 248 err = os.Chdir("../") 249 if err != nil { 250 return errors.Wrap(err, "[ startNet ] Can't change dir") 251 } 252 253 cmd = exec.Command("./scripts/insolard/launchnet.sh", "-ngw") 254 stdout, _ = cmd.StdoutPipe() 255 if err != nil { 256 return errors.Wrap(err, "[ startNet ] could't set stdout: ") 257 } 258 259 stderr, err = cmd.StderrPipe() 260 if err != nil { 261 return errors.Wrap(err, "[ startNet] could't set stderr: ") 262 } 263 264 err = cmd.Start() 265 if err != nil { 266 return errors.Wrap(err, "[ startNet ] Can't run cmd") 267 } 268 269 err = waitForLaunch() 270 if err != nil { 271 return errors.Wrap(err, "[ startNet ] couldn't waitForLaunch more") 272 } 273 274 err = waitForNet() 275 if err != nil { 276 return errors.Wrap(err, "[ startNet ] couldn't waitForNet more") 277 } 278 279 return nil 280 281 } 282 283 func waitForLaunch() error { 284 done := make(chan bool, 1) 285 timeout := 240 * time.Second 286 287 go func() { 288 scanner := bufio.NewScanner(stdout) 289 fmt.Println("Insolard output: ") 290 for scanner.Scan() { 291 line := scanner.Text() 292 fmt.Println(line) 293 if strings.Contains(line, "start discovery nodes ...") { 294 done <- true 295 } 296 } 297 }() 298 go func() { 299 scanner := bufio.NewScanner(stderr) 300 for scanner.Scan() { 301 line := scanner.Text() 302 fmt.Println(line) 303 } 304 }() 305 306 go func() { cmdCompleted <- cmd.Wait() }() 307 select { 308 case err := <-cmdCompleted: 309 cmdCompleted <- nil 310 return errors.New("[ waitForLaunch ] insolard finished unexpectedly: " + err.Error()) 311 case <-done: 312 return nil 313 case <-time.After(timeout): 314 return errors.Errorf("[ waitForLaunch ] could't wait for launch: timeout of %s was exceeded", timeout) 315 } 316 } 317 318 func setup() error { 319 err := createDirForContracts() 320 if err != nil { 321 return errors.Wrap(err, "[ setup ] could't create dirs for test: ") 322 } 323 fmt.Println("[ setup ] directory for contracts cache was successfully created") 324 325 err = buildGinsiderCLI() 326 if err != nil { 327 return errors.Wrap(err, "[ setup ] could't build ginsider CLI: ") 328 } 329 fmt.Println("[ setup ] ginsider CLI was successfully builded") 330 331 err = startAllInsgorunds() 332 if err != nil { 333 return errors.Wrap(err, "[ setup ] could't start insgorund: ") 334 } 335 fmt.Println("[ setup ] insgorund was successfully started") 336 337 err = startNet() 338 if err != nil { 339 return errors.Wrap(err, "[ setup ] could't startNet") 340 } 341 342 err = loadRootKeys() 343 if err != nil { 344 return errors.Wrap(err, "[ setup ] could't load root keys: ") 345 } 346 fmt.Println("[ setup ] root keys successfully loaded") 347 348 numAttempts := 60 349 for i := 0; i < numAttempts; i++ { 350 err = setInfo() 351 if err != nil { 352 fmt.Printf("[ setup ] Couldn't setInfo. Attempt %d/%d. Err: %s\n", i, numAttempts, err) 353 } else { 354 break 355 } 356 time.Sleep(time.Second) 357 } 358 if err != nil { 359 return errors.Wrap(err, "[ setup ] could't receive root reference ") 360 } 361 362 fmt.Println("[ setup ] root reference successfully received") 363 root.ref = info.RootMember 364 365 return nil 366 } 367 368 func teardown() { 369 var envSetting = os.Getenv("TEST_ENV") 370 var err error 371 fmt.Println("TEST_ENV: ", envSetting) 372 if envSetting != "CI" { 373 err = stopInsolard() 374 375 if err != nil { 376 fmt.Println("[ teardown ] failed to stop insolard: ", err) 377 } 378 fmt.Println("[ teardown ] insolard was successfully stoped") 379 } 380 381 err = stopAllInsgorunds() 382 if err != nil { 383 fmt.Println("[ teardown ] failed to stop all insgrounds: ", err) 384 } 385 fmt.Println("[ teardown ] insgorund was successfully stoped") 386 387 err = deleteDirForContracts() 388 if err != nil { 389 fmt.Println("[ teardown ] failed to remove directory for contracts cache for func tests: ", err) 390 } 391 fmt.Println("[ teardown ] directory for contracts cache was successfully deleted") 392 } 393 394 func testMainWrapper(m *testing.M) int { 395 err := setup() 396 defer teardown() 397 if err != nil { 398 fmt.Println("error while setup, skip tests: ", err) 399 return 1 400 } 401 code := m.Run() 402 return code 403 } 404 405 func TestMain(m *testing.M) { 406 os.Exit(testMainWrapper(m)) 407 }