github.com/cgcardona/r-subnet-evm@v0.1.5/tests/utils/command.go (about) 1 // Copyright (C) 2019-2022, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package utils 5 6 import ( 7 "context" 8 "encoding/json" 9 "fmt" 10 "os" 11 "path/filepath" 12 "strings" 13 "time" 14 15 "github.com/ava-labs/avalanchego/api/health" 16 "github.com/ethereum/go-ethereum/log" 17 "github.com/go-cmd/cmd" 18 "github.com/onsi/ginkgo/v2" 19 "github.com/onsi/gomega" 20 ) 21 22 // RunCommand starts the command [bin] with the given [args] and returns the command to the caller 23 // TODO cmd package mentions we can do this more efficiently with cmd.NewCmdOptions rather than looping 24 // and calling Status(). 25 func RunCommand(bin string, args ...string) (*cmd.Cmd, error) { 26 log.Info("Executing", "cmd", fmt.Sprintf("%s %s", bin, strings.Join(args, " "))) 27 28 curCmd := cmd.NewCmd(bin, args...) 29 _ = curCmd.Start() 30 31 // to stream outputs 32 ticker := time.NewTicker(10 * time.Millisecond) 33 go func() { 34 prevLine := "" 35 for range ticker.C { 36 status := curCmd.Status() 37 n := len(status.Stdout) 38 if n == 0 { 39 continue 40 } 41 42 line := status.Stdout[n-1] 43 if prevLine != line && line != "" { 44 fmt.Println("[streaming output]", line) 45 } 46 47 prevLine = line 48 } 49 }() 50 51 return curCmd, nil 52 } 53 54 func RegisterPingTest() { 55 ginkgo.It("ping the network", ginkgo.Label("ping"), func() { 56 client := health.NewClient(DefaultLocalNodeURI) 57 healthy, err := client.Readiness(context.Background(), nil) 58 gomega.Expect(err).Should(gomega.BeNil()) 59 gomega.Expect(healthy.Healthy).Should(gomega.BeTrue()) 60 }) 61 } 62 63 // At boot time subnets are created, one for each test suite. This global 64 // variable has all the subnets IDs that can be used. 65 // 66 // One process creates the AvalancheGo node and all the subnets, and these 67 // subnets IDs are passed to all other processes and stored in this global 68 // variable 69 var BlockchainIDs map[string]string 70 71 // Timeout to boot the AvalancheGo node 72 var bootAvalancheNodeTimeout = 5 * time.Minute 73 74 // Timeout for the health API to check the AvalancheGo is ready 75 var healthCheckTimeout = 5 * time.Second 76 77 func RegisterNodeRun() { 78 // Keep track of the AvalancheGo external bash script, it is null for most 79 // processes except the first process that starts AvalancheGo 80 var startCmd *cmd.Cmd 81 82 // Our test suite runs in a separated processes, ginkgo hasI 83 // SynchronizedBeforeSuite() which is promised to run once, and its output is 84 // passed over to each worker. 85 // 86 // In here an AvalancheGo node instance is started, and subnets are created for 87 // each test case. Each test case has its own subnet, therefore all tests can 88 // run in parallel without any issue. 89 // 90 // This function also compiles all the solidity contracts 91 var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { 92 ctx, cancel := context.WithTimeout(context.Background(), bootAvalancheNodeTimeout) 93 defer cancel() 94 95 wd, err := os.Getwd() 96 gomega.Expect(err).Should(gomega.BeNil()) 97 log.Info("Starting AvalancheGo node", "wd", wd) 98 cmd, err := RunCommand("./scripts/run.sh") 99 startCmd = cmd 100 gomega.Expect(err).Should(gomega.BeNil()) 101 102 // Assumes that startCmd will launch a node with HTTP Port at [utils.DefaultLocalNodeURI] 103 healthClient := health.NewClient(DefaultLocalNodeURI) 104 healthy, err := health.AwaitReady(ctx, healthClient, healthCheckTimeout, nil) 105 gomega.Expect(err).Should(gomega.BeNil()) 106 gomega.Expect(healthy).Should(gomega.BeTrue()) 107 log.Info("AvalancheGo node is healthy") 108 109 blockchainIds := make(map[string]string) 110 files, err := filepath.Glob("./tests/precompile/genesis/*.json") 111 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 112 113 for _, file := range files { 114 basename := filepath.Base(file) 115 index := basename[:len(basename)-5] 116 blockchainIds[index] = CreateNewSubnet(ctx, file) 117 } 118 119 blockchainIDsBytes, err := json.Marshal(blockchainIds) 120 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 121 return blockchainIDsBytes 122 }, func(data []byte) { 123 err := json.Unmarshal(data, &BlockchainIDs) 124 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 125 }) 126 127 // SynchronizedAfterSuite() takes two functions, the first runs after each test suite is done and the second 128 // function is executed once when all the tests are done. This function is used 129 // to gracefully shutdown the AvalancheGo node. 130 var _ = ginkgo.SynchronizedAfterSuite(func() {}, func() { 131 gomega.Expect(startCmd).ShouldNot(gomega.BeNil()) 132 gomega.Expect(startCmd.Stop()).Should(gomega.BeNil()) 133 }) 134 }