github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/command/local_command_test.go (about) 1 package command 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "runtime" 8 "testing" 9 10 "github.com/evergreen-ci/evergreen" 11 . "github.com/smartystreets/goconvey/convey" 12 ) 13 14 func TestLocalCommands(t *testing.T) { 15 if runtime.GOOS == "windows" { 16 t.Skip("shell command test doesn't make sense on windows") 17 } 18 19 Convey("When running local commands", t, func() { 20 21 Convey("the preparation step should replace expansions and forward"+ 22 " slashes in the command string", func() { 23 24 command := &LocalCommand{ 25 CmdString: "one ${two} \\three${four|five}", 26 } 27 28 expansions := NewExpansions(map[string]string{ 29 "two": "TWO", 30 "six": "SIX", 31 }) 32 33 // run the preparation stage, and make sure the replacements are 34 // correctly made 35 So(command.PrepToRun(expansions), ShouldBeNil) 36 So(command.CmdString, ShouldEqual, "one TWO \\threefive") 37 38 }) 39 40 Convey("the preparation step should replace expansion in the working directory", func() { 41 command := &LocalCommand{ 42 WorkingDirectory: "one ${two} ${other|three} four five ${six}", 43 } 44 45 expansions := NewExpansions(map[string]string{ 46 "two": "TWO", 47 "six": "SIX", 48 }) 49 50 So(command.PrepToRun(expansions), ShouldBeNil) 51 So(command.WorkingDirectory, ShouldEqual, "one TWO three four five SIX") 52 }) 53 54 Convey("the perpetration step should return an error if invalid expansions", func() { 55 expansions := NewExpansions(map[string]string{"foo": "bar"}) 56 57 for _, cmd := range []*LocalCommand{ 58 {WorkingDirectory: "${foo|${bar}}"}, 59 {CmdString: "${foo${bar}}"}, 60 } { 61 So(cmd.PrepToRun(expansions), ShouldNotBeNil) 62 } 63 64 }) 65 66 Convey("the preparation step should not replace strings without expansions", func() { 67 var cmd *LocalCommand 68 69 expansions := NewExpansions(map[string]string{"foo": "bar"}) 70 71 for _, input := range []string{"", "nothing", "this is empty", "foo"} { 72 cmd = &LocalCommand{WorkingDirectory: input} 73 So(cmd.PrepToRun(expansions), ShouldBeNil) 74 So(cmd.WorkingDirectory, ShouldEqual, input) 75 76 cmd = &LocalCommand{CmdString: input} 77 So(cmd.PrepToRun(expansions), ShouldBeNil) 78 So(cmd.CmdString, ShouldEqual, input) 79 } 80 }) 81 82 Convey("the specified environment should be used", func() { 83 stdout := &CacheLastWritten{} 84 85 command := &LocalCommand{ 86 CmdString: "echo $local_command_test", 87 Stdout: stdout, 88 Stderr: ioutil.Discard, 89 } 90 91 // get the current env 92 command.Environment = os.Environ() 93 94 // run the command - the environment variable should be empty 95 So(command.Run(), ShouldBeNil) 96 So(string(stdout.LastWritten), ShouldEqual, "\n") 97 98 // add the environment variable to the env 99 command.Environment = append(command.Environment, 100 "local_command_test=hello") 101 102 // run the command again - the environment variable should be set 103 // correctly 104 So(command.Run(), ShouldBeNil) 105 So(string(stdout.LastWritten), ShouldEqual, "hello\n") 106 107 }) 108 109 Convey("the specified working directory should be used", func() { 110 111 stdout := &CacheLastWritten{} 112 113 workingDir, err := filepath.Abs(evergreen.FindEvergreenHome()) 114 So(err, ShouldBeNil) 115 116 command := &LocalCommand{ 117 CmdString: "pwd", 118 Stdout: stdout, 119 Stderr: ioutil.Discard, 120 WorkingDirectory: workingDir, 121 } 122 // run the command - the working directory should be as specified 123 So(command.Run(), ShouldBeNil) 124 125 reportedPwd := string(stdout.LastWritten) 126 reportedPwd = reportedPwd[:len(reportedPwd)-1] 127 reportedPwd, err = filepath.EvalSymlinks(reportedPwd) 128 So(err, ShouldBeNil) 129 130 So(reportedPwd, ShouldEqual, workingDir) 131 132 }) 133 134 Convey("the specified shell should be used", func() { 135 for _, sh := range []string{"bash", "sh", "/bin/bash", "/bin/sh"} { 136 stdout := &CacheLastWritten{} 137 command := &LocalCommand{ 138 Shell: sh, 139 CmdString: "echo $0", 140 Stdout: stdout, 141 Stderr: ioutil.Discard, 142 } 143 144 So(command.Run(), ShouldBeNil) 145 So(string(stdout.LastWritten), ShouldEqual, sh+"\n") 146 } 147 }) 148 149 Convey("if not specified, sh should be used", func() { 150 stdout := &CacheLastWritten{} 151 command := &LocalCommand{ 152 CmdString: "echo $0", 153 Stdout: stdout, 154 Stderr: ioutil.Discard, 155 } 156 157 So(command.Run(), ShouldBeNil) 158 So(string(stdout.LastWritten), ShouldEqual, "sh\n") 159 }) 160 161 Convey("when specified, local command can also use python", func() { 162 stdout := &CacheLastWritten{} 163 command := &LocalCommand{ 164 Shell: "python", 165 CmdString: "print('hello world')", 166 Stdout: stdout, 167 Stderr: ioutil.Discard, 168 } 169 170 So(command.Run(), ShouldBeNil) 171 So(string(stdout.LastWritten), ShouldEqual, "hello world\n") 172 }) 173 174 }) 175 } 176 177 func TestLocalCommandGroups(t *testing.T) { 178 179 Convey("With a group of local commands", t, func() { 180 181 Convey("the global preparation step should invoke all of the prep"+ 182 " steps for the group", func() { 183 184 // the three commands for the group, whose preparation steps will 185 // yield different results for expanding the command string 186 firstCommand := &LocalCommand{ 187 CmdString: "one\\ ${two} \\three", 188 } 189 secondCommand := &LocalCommand{ 190 CmdString: "${four|five}", 191 } 192 thirdCommand := &LocalCommand{ 193 CmdString: "six seven", 194 } 195 196 expansions := NewExpansions(map[string]string{ 197 "two": "TWO", 198 "six": "SIX", 199 }) 200 201 cmdGroup := &LocalCommandGroup{ 202 Commands: []*LocalCommand{firstCommand, secondCommand, 203 thirdCommand}, 204 Expansions: expansions, 205 } 206 207 // run the preparation step for the command group, make sure it is 208 // run for each command individually 209 So(cmdGroup.PrepToRun(), ShouldBeNil) 210 So(firstCommand.CmdString, ShouldEqual, "one\\ TWO \\three") 211 So(secondCommand.CmdString, ShouldEqual, "five") 212 So(thirdCommand.CmdString, ShouldEqual, "six seven") 213 214 }) 215 216 Convey("The global preparation step should fail if any of the"+ 217 " individual group members' prep steps fail", func() { 218 219 // the three commands for the group. only the second will error 220 firstCommand := &LocalCommand{ 221 CmdString: "one\\ ${two} \\three", 222 } 223 secondCommand := &LocalCommand{ 224 CmdString: "${four|five}${", 225 } 226 thirdCommand := &LocalCommand{ 227 CmdString: "six seven", 228 } 229 230 expansions := NewExpansions(map[string]string{ 231 "two": "TWO", 232 "six": "SIX", 233 }) 234 235 cmdGroup := &LocalCommandGroup{ 236 Commands: []*LocalCommand{firstCommand, secondCommand, 237 thirdCommand}, 238 Expansions: expansions, 239 } 240 241 // the preparation step should fail 242 So(cmdGroup.PrepToRun(), ShouldNotBeNil) 243 244 }) 245 246 }) 247 248 } 249 250 func TestLocalScript(t *testing.T) { 251 if runtime.GOOS == "windows" { 252 t.Skip("shell command test doesn't make sense on windows") 253 } 254 255 Convey("When running local commands in script mode", t, func() { 256 257 Convey("A multi-line script should run all lines", func() { 258 259 stdout := &CacheLastWritten{} 260 261 workingDir, err := filepath.Abs(evergreen.FindEvergreenHome()) 262 So(err, ShouldBeNil) 263 264 command := &LocalCommand{ 265 CmdString: "set -v\necho 'hi'\necho 'foo'\necho `pwd`", 266 ScriptMode: true, 267 Stdout: stdout, 268 Stderr: ioutil.Discard, 269 WorkingDirectory: workingDir, 270 } 271 272 // run the command - the working directory should be as specified 273 So(command.Run(), ShouldBeNil) 274 275 reportedPwd := string(stdout.LastWritten) 276 reportedPwd = reportedPwd[:len(reportedPwd)-1] 277 reportedPwd, err = filepath.EvalSymlinks(reportedPwd) 278 So(err, ShouldBeNil) 279 So(reportedPwd, ShouldEqual, workingDir) 280 }) 281 282 }) 283 }