gitlab.com/SkynetLabs/skyd@v1.6.9/cmd/skyc/maincmd_test.go (about) 1 package main 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/spf13/cobra" 8 "gitlab.com/SkynetLabs/skyd/build" 9 ) 10 11 // TestRootSkycCmd tests root siac command for expected outputs. The test 12 // runs its own node and requires no service running at port 5555. 13 func TestRootSkycCmd(t *testing.T) { 14 if testing.Short() { 15 t.SkipNow() 16 } 17 t.Parallel() 18 19 // Create a test node for this test group 20 groupDir := skycTestDir(t.Name()) 21 n, err := newTestNode(groupDir) 22 if err != nil { 23 t.Fatal(err) 24 } 25 defer func() { 26 if err := n.Close(); err != nil { 27 t.Fatal(err) 28 } 29 }() 30 31 // Initialize siac root command with its subcommands and flags 32 root := getRootCmdForSkycCmdsTests(groupDir) 33 34 // define test constants: 35 // Regular expressions to check siac output 36 37 begin := "^" 38 nl := ` 39 ` // platform agnostic new line 40 end := "$" 41 42 // Capture root command usage for test comparison 43 // catch stdout and stderr 44 rootCmdUsagePattern := getCmdUsage(t, root) 45 46 IPv6addr := n.Address 47 IPv4Addr := strings.ReplaceAll(n.Address, "[::]", "localhost") 48 49 // Regex helpers 50 // \s+ to match 1 or more spaces. Helpful with the tab writter 51 // \d+ to match a number 52 rootCmdOutPattern := `Consensus: 53 Synced: (No|Yes) 54 Height:\s+\d+ 55 56 Wallet: 57 ( Status: Locked| Status: unlocked 58 Siacoin Balance: \d+(\.\d*|) (SC|KS|MS)) 59 60 Renter: 61 File Summary: 62 Files:\s+\d+ 63 Total Stored:\s+\d+(\.\d+|) ( B|kB|MB|GB|TB) 64 Total Renewing Data:\s+\d+(\.\d+|) ( B|kB|MB|GB|TB) 65 Repair Status: 66 Last Health Check:\s+\d+(m) 67 Repair Data Remaining:\s+\d+(\.\d+|) ( B|kB|MB|GB|TB) 68 Stuck Repair Remaining:\s+\d+(\.\d+|) ( B|kB|MB|GB|TB) 69 Stuck Chunks:\s+\d+ 70 Max Health:\s+\d+(\%) 71 Min Redundancy:\s+(\d+.\d{2}|-) 72 Lost Files:\s+\d+ 73 Contract Summary: 74 ( Renew Window \(days\): renew window not set) 75 Active Contracts:\s+\d+ 76 Passive Contracts:\s+\d+ 77 Disabled Contracts:\s+\d+` 78 79 rootCmdVerbosePartPattern := `Global Rate limits: 80 Download Speed: (no limit|\d+(\.\d+)? (B/s|KB/s|MB/s|GB/s|TB/s)) 81 Upload Speed: (no limit|\d+(\.\d+)? (B/s|KB/s|MB/s|GB/s|TB/s)) 82 83 Gateway Rate limits: 84 Download Speed: (no limit|\d+(\.\d+)? (B/s|KB/s|MB/s|GB/s|TB/s)) 85 Upload Speed: (no limit|\d+(\.\d+)? (B/s|KB/s|MB/s|GB/s|TB/s)) 86 87 Renter Rate limits: 88 Download Speed: (no limit|\d+(\.\d+)? (B/s|KB/s|MB/s|GB/s|TB/s)) 89 Upload Speed: (no limit|\d+(\.\d+)? (B/s|KB/s|MB/s|GB/s|TB/s))` 90 91 connectionRefusedPattern := `Could not get consensus status: \[failed to get reader response; GET request failed; Get "?http://127.0.0.1:5555/consensus"?: dial tcp 127.0.0.1:5555: connect: connection refused\]` 92 versionReplacer := strings.NewReplacer(".", `\.`, "?", `\?`) 93 skyClientVersionPattern := "Skynet Client v" + versionReplacer.Replace(build.NodeVersion) 94 95 // Define subtests 96 // We can't test siad on default address (port) when test node has 97 // dynamically allocated port, we have to use node address. 98 subTests := []skycCmdSubTest{ 99 { 100 name: "TestRootCmdWithShortAddressFlagIPv6", 101 test: testGenericSkycCmd, 102 cmd: root, 103 cmdStrs: []string{"-a", IPv6addr}, 104 expectedOutPattern: begin + rootCmdOutPattern + nl + nl + end, 105 }, 106 { 107 name: "TestRootCmdWithShortAddressFlagIPv4", 108 test: testGenericSkycCmd, 109 cmd: root, 110 cmdStrs: []string{"-a", IPv4Addr}, 111 expectedOutPattern: begin + rootCmdOutPattern + nl + nl + end, 112 }, 113 { 114 name: "TestRootCmdWithLongAddressFlagIPv6", 115 test: testGenericSkycCmd, 116 cmd: root, 117 cmdStrs: []string{"--addr", IPv6addr}, 118 expectedOutPattern: begin + rootCmdOutPattern + nl + nl + end, 119 }, 120 { 121 name: "TestRootCmdWithLongAddressFlagIPv4", 122 test: testGenericSkycCmd, 123 cmd: root, 124 cmdStrs: []string{"--addr", IPv4Addr}, 125 expectedOutPattern: begin + rootCmdOutPattern + nl + nl + end, 126 }, 127 { 128 name: "TestRootCmdWithVerboseFlag", 129 test: testGenericSkycCmd, 130 cmd: root, 131 cmdStrs: []string{"--addr", IPv4Addr, "-v"}, 132 expectedOutPattern: begin + rootCmdOutPattern + nl + nl + rootCmdVerbosePartPattern + nl + nl + end, 133 }, 134 { 135 name: "TestRootCmdWithInvalidFlag", 136 test: testGenericSkycCmd, 137 cmd: root, 138 cmdStrs: []string{"-x"}, 139 expectedOutPattern: begin + "Error: unknown shorthand flag: 'x' in -x" + nl + rootCmdUsagePattern + nl + end, 140 }, 141 { 142 name: "TestRootCmdWithInvalidAddress", 143 test: testGenericSkycCmd, 144 cmd: root, 145 cmdStrs: []string{"-a", "127.0.0.1:5555"}, 146 expectedOutPattern: begin + connectionRefusedPattern + nl + nl + end, 147 }, 148 { 149 name: "TestRootCmdWithHelpFlag", 150 test: testGenericSkycCmd, 151 cmd: root, 152 cmdStrs: []string{"-h"}, 153 expectedOutPattern: begin + skyClientVersionPattern + nl + nl + rootCmdUsagePattern + end, 154 }, 155 } 156 157 // run tests 158 err = runSkycCmdSubTests(t, subTests) 159 if err != nil { 160 t.Fatal(err) 161 } 162 } 163 164 // getCmdUsage gets root command usage regex pattern by calling usage function 165 func getCmdUsage(t *testing.T, cmd *cobra.Command) string { 166 // Capture usage by calling a usage function 167 c, err := newOutputCatcher() 168 if err != nil { 169 t.Fatal("Error starting catching stdout/stderr", err) 170 } 171 usageFunc := cmd.UsageFunc() 172 err = usageFunc(cmd) 173 if err != nil { 174 t.Fatal("Error getting reference root siac usage", err) 175 } 176 baseUsage, err := c.stop() 177 178 // Escape regex special chars 179 usage := escapeRegexChars(baseUsage) 180 181 // Inject 2 missing rows 182 beforeHelpCommand := "Perform gateway actions" 183 helpCommand := " help Help about any command" 184 nl := ` 185 ` 186 usage = strings.ReplaceAll(usage, beforeHelpCommand, beforeHelpCommand+nl+helpCommand) 187 beforeHelpFlag := "the password for the API's http authentication" 188 helpFlag := ` -h, --help help for .*skyc(\.test|)` 189 cmdUsagePattern := strings.ReplaceAll(usage, beforeHelpFlag, beforeHelpFlag+nl+helpFlag) 190 191 return cmdUsagePattern 192 }