github.com/maxgio92/test-infra@v0.1.0/kubetest/process/process_test.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package process 18 19 import ( 20 "errors" 21 "log" 22 "os/exec" 23 "strconv" 24 "strings" 25 "testing" 26 "time" 27 28 "github.com/maxgio92/test-infra/kubetest/util" 29 ) 30 31 func TestXMLWrap(t *testing.T) { 32 cases := []struct { 33 name string 34 interrupted bool 35 shouldInterrupt bool 36 err string 37 expectSkipped bool 38 expectError bool 39 }{ 40 { 41 name: "xmlWrap can pass", 42 }, 43 { 44 name: "xmlWrap can error", 45 err: "hello there", 46 expectError: true, 47 }, 48 { 49 name: "xmlWrap always errors on interrupt", 50 err: "", 51 shouldInterrupt: true, 52 expectError: true, 53 }, 54 { 55 name: "xmlWrap errors on interrupt", 56 shouldInterrupt: true, 57 err: "the step failed", 58 expectError: true, 59 }, 60 { 61 name: "xmlWrap skips errors when already interrupted", 62 interrupted: true, 63 err: "this failed because we interrupted the previous step", 64 expectSkipped: true, 65 }, 66 { 67 name: "xmlWrap can pass when interrupted", 68 interrupted: true, 69 err: "", 70 }, 71 } 72 73 for _, tc := range cases { 74 interrupt := time.NewTimer(time.Duration(0)) 75 terminate := time.NewTimer(time.Duration(0)) 76 c := NewControl(time.Duration(0), interrupt, terminate, false) 77 c.interrupted = tc.interrupted 78 suite := util.TestSuite{ 79 Failures: 6, 80 Tests: 9, 81 } 82 err := c.XMLWrap(&suite, tc.name, func() error { 83 if tc.shouldInterrupt { 84 c.interrupted = true 85 } 86 if tc.err != "" { 87 return errors.New(tc.err) 88 } 89 return nil 90 }) 91 92 if tc.shouldInterrupt && tc.expectError { 93 if err == nil { 94 t.Fatalf("Case %s did not error", tc.name) 95 } 96 if tc.err == "" { 97 tc.err = err.Error() 98 } 99 } 100 if (tc.err == "") != (err == nil) { 101 t.Errorf("Case %s expected err: %s != actual: %v", tc.name, tc.err, err) 102 } 103 if tc.shouldInterrupt && !c.interrupted { 104 t.Errorf("Case %s did not interrupt", tc.name) 105 } 106 if len(suite.Cases) != 1 { 107 t.Fatalf("Case %s did not result in a single suite testcase: %v", tc.name, suite.Cases) 108 } 109 110 sc := suite.Cases[0] 111 if sc.Name != tc.name { 112 t.Errorf("Case %s resulted in wrong test case name %s", tc.name, sc.Name) 113 } 114 if tc.expectError { 115 if sc.Failure != tc.err { 116 t.Errorf("Case %s expected error %s but got %s", tc.name, tc.err, sc.Failure) 117 } 118 if suite.Failures != 7 { 119 t.Errorf("Case %s failed and should increase suite failures from 6 to 7, found: %d", tc.name, suite.Failures) 120 } 121 } else if tc.expectSkipped { 122 if sc.Skipped != tc.err { 123 t.Errorf("Case %s expected skipped %s but got %s", tc.name, tc.err, sc.Skipped) 124 } 125 if suite.Failures != 7 { 126 t.Errorf("Case %s interrupted and increase suite failures from 6 to 7, found: %d", tc.name, suite.Failures) 127 } 128 } else { 129 if suite.Failures != 6 { 130 t.Errorf("Case %s passed so suite failures should remain at 6, found: %d", tc.name, suite.Failures) 131 } 132 } 133 134 } 135 } 136 137 func TestOutput(t *testing.T) { 138 cases := []struct { 139 name string 140 terminated bool 141 interrupted bool 142 causeTermination bool 143 causeInterruption bool 144 pass bool 145 sleep int 146 output bool 147 shouldError bool 148 shouldInterrupt bool 149 shouldTerminate bool 150 }{ 151 { 152 name: "finishRunning can pass", 153 pass: true, 154 }, 155 { 156 name: "output can pass", 157 output: true, 158 pass: true, 159 }, 160 { 161 name: "finishRuning can fail", 162 pass: false, 163 shouldError: true, 164 }, 165 { 166 name: "output can fail", 167 pass: false, 168 output: true, 169 shouldError: true, 170 }, 171 { 172 name: "finishRunning should error when terminated", 173 terminated: true, 174 pass: true, 175 shouldError: true, 176 }, 177 { 178 name: "output should error when terminated", 179 terminated: true, 180 pass: true, 181 output: true, 182 shouldError: true, 183 }, 184 { 185 name: "finishRunning should interrupt when interrupted", 186 pass: true, 187 sleep: 60, 188 causeInterruption: true, 189 shouldError: true, 190 }, 191 { 192 name: "output should interrupt when interrupted", 193 pass: true, 194 sleep: 60, 195 output: true, 196 causeInterruption: true, 197 shouldError: true, 198 }, 199 { 200 name: "output should terminate when terminated", 201 pass: true, 202 sleep: 60, 203 output: true, 204 causeTermination: true, 205 shouldError: true, 206 }, 207 { 208 name: "finishRunning should terminate when terminated", 209 pass: true, 210 sleep: 60, 211 causeTermination: true, 212 shouldError: true, 213 }, 214 } 215 216 clearTimers := func(c *Control) { 217 if !c.Terminate.Stop() { 218 <-c.Terminate.C 219 } 220 if !c.Interrupt.Stop() { 221 <-c.Interrupt.C 222 } 223 } 224 225 for _, tc := range cases { 226 log.Println(tc.name) 227 interrupt := time.NewTimer(time.Duration(0)) 228 terminate := time.NewTimer(time.Duration(0)) 229 c := NewControl(time.Duration(0), interrupt, terminate, false) 230 c.terminated = tc.terminated 231 c.interrupted = tc.interrupted 232 clearTimers(c) 233 if tc.causeInterruption { 234 interrupt.Reset(0) 235 } 236 if tc.causeTermination { 237 terminate.Reset(0) 238 } 239 var cmd *exec.Cmd 240 if !tc.pass { 241 cmd = exec.Command("false") 242 } else if tc.sleep == 0 { 243 cmd = exec.Command("true") 244 } else { 245 cmd = exec.Command("sleep", strconv.Itoa(tc.sleep)) 246 } 247 var err error 248 if tc.output { 249 _, err = c.Output(cmd) 250 } else { 251 err = c.FinishRunning(cmd) 252 } 253 if err == nil == tc.shouldError { 254 t.Errorf("Step %s shouldError=%v error: %v", tc.name, tc.shouldError, err) 255 } 256 if tc.causeInterruption && !c.interrupted { 257 t.Errorf("Step %s did not interrupt, err: %v", tc.name, err) 258 } else if tc.causeInterruption && !terminate.Reset(0) { 259 t.Errorf("Step %s did not reset the terminate timer: %v", tc.name, err) 260 } 261 if tc.causeTermination && !c.terminated { 262 t.Errorf("Step %s did not terminate, err: %v", tc.name, err) 263 } 264 } 265 } 266 267 func TestFinishRunningParallel(t *testing.T) { 268 cases := []struct { 269 name string 270 terminated bool 271 interrupted bool 272 causeTermination bool 273 causeInterruption bool 274 cmds []*exec.Cmd 275 shouldError bool 276 shouldInterrupt bool 277 shouldTerminate bool 278 }{ 279 { 280 name: "finishRunningParallel with single command can pass", 281 cmds: []*exec.Cmd{exec.Command("true")}, 282 }, 283 { 284 name: "finishRunningParallel with multiple commands can pass", 285 cmds: []*exec.Cmd{exec.Command("true"), exec.Command("true")}, 286 }, 287 { 288 name: "finishRunningParallel with single command can fail", 289 cmds: []*exec.Cmd{exec.Command("false")}, 290 shouldError: true, 291 }, 292 { 293 name: "finishRunningParallel with multiple commands can fail", 294 cmds: []*exec.Cmd{exec.Command("true"), exec.Command("false")}, 295 shouldError: true, 296 }, 297 { 298 name: "finishRunningParallel should error when terminated", 299 cmds: []*exec.Cmd{exec.Command("true"), exec.Command("true")}, 300 terminated: true, 301 shouldError: true, 302 }, 303 { 304 name: "finishRunningParallel should interrupt when interrupted", 305 cmds: []*exec.Cmd{exec.Command("true"), exec.Command("sleep", "60"), exec.Command("sleep", "30")}, 306 causeInterruption: true, 307 shouldError: true, 308 }, 309 { 310 name: "finishRunningParallel should terminate when terminated", 311 cmds: []*exec.Cmd{exec.Command("true"), exec.Command("sleep", "60"), exec.Command("sleep", "30")}, 312 causeTermination: true, 313 shouldError: true, 314 }, 315 } 316 317 clearTimers := func(c *Control) { 318 if !c.Terminate.Stop() { 319 <-c.Terminate.C 320 } 321 if !c.Interrupt.Stop() { 322 <-c.Interrupt.C 323 } 324 } 325 326 for _, tc := range cases { 327 log.Println(tc.name) 328 interrupt := time.NewTimer(time.Duration(0)) 329 terminate := time.NewTimer(time.Duration(0)) 330 c := NewControl(time.Duration(0), interrupt, terminate, false) 331 c.terminated = tc.terminated 332 c.interrupted = tc.interrupted 333 clearTimers(c) 334 if tc.causeInterruption { 335 interrupt.Reset(1 * time.Second) 336 } 337 if tc.causeTermination { 338 terminate.Reset(1 * time.Second) 339 } 340 341 err := c.FinishRunningParallel(tc.cmds...) 342 if err == nil == tc.shouldError { 343 t.Errorf("TC %q shouldError=%v error: %v", tc.name, tc.shouldError, err) 344 } 345 if tc.causeInterruption && !c.interrupted { 346 t.Errorf("TC %q did not interrupt, err: %v", tc.name, err) 347 } else if tc.causeInterruption && !terminate.Reset(0) { 348 t.Errorf("TC %q did not reset the terminate timer: %v", tc.name, err) 349 } 350 if tc.causeTermination && !c.terminated { 351 t.Errorf("TC %q did not terminate, err: %v", tc.name, err) 352 } 353 } 354 } 355 356 func TestOutputOutputs(t *testing.T) { 357 interrupt := time.NewTimer(time.Duration(1) * time.Second) 358 terminate := time.NewTimer(time.Duration(1) * time.Second) 359 c := NewControl(time.Duration(1)*time.Second, interrupt, terminate, false) 360 361 b, err := c.Output(exec.Command("echo", "hello world")) 362 txt := string(b) 363 if err != nil { 364 t.Fatalf("failed to echo: %v", err) 365 } 366 if !strings.Contains(txt, "hello world") { 367 t.Errorf("output() did not echo hello world: %v", txt) 368 } 369 }