1// These tests verify the inner workings of the helper methods associated 2// with check.T. 3 4package check_test 5 6import ( 7 "gopkg.in/check.v1" 8 "os" 9 "reflect" 10 "runtime" 11 "sync" 12) 13 14var helpersS = check.Suite(&HelpersS{}) 15 16type HelpersS struct{} 17 18func (s *HelpersS) TestCountSuite(c *check.C) { 19 suitesRun += 1 20} 21 22// ----------------------------------------------------------------------- 23// Fake checker and bug info to verify the behavior of Assert() and Check(). 24 25type MyChecker struct { 26 info *check.CheckerInfo 27 params []interface{} 28 names []string 29 result bool 30 error string 31} 32 33func (checker *MyChecker) Info() *check.CheckerInfo { 34 if checker.info == nil { 35 return &check.CheckerInfo{Name: "MyChecker", Params: []string{"myobtained", "myexpected"}} 36 } 37 return checker.info 38} 39 40func (checker *MyChecker) Check(params []interface{}, names []string) (bool, string) { 41 rparams := checker.params 42 rnames := checker.names 43 checker.params = append([]interface{}{}, params...) 44 checker.names = append([]string{}, names...) 45 if rparams != nil { 46 copy(params, rparams) 47 } 48 if rnames != nil { 49 copy(names, rnames) 50 } 51 return checker.result, checker.error 52} 53 54type myCommentType string 55 56func (c myCommentType) CheckCommentString() string { 57 return string(c) 58} 59 60func myComment(s string) myCommentType { 61 return myCommentType(s) 62} 63 64// ----------------------------------------------------------------------- 65// Ensure a real checker actually works fine. 66 67func (s *HelpersS) TestCheckerInterface(c *check.C) { 68 testHelperSuccess(c, "Check(1, Equals, 1)", true, func() interface{} { 69 return c.Check(1, check.Equals, 1) 70 }) 71} 72 73// ----------------------------------------------------------------------- 74// Tests for Check(), mostly the same as for Assert() following these. 75 76func (s *HelpersS) TestCheckSucceedWithExpected(c *check.C) { 77 checker := &MyChecker{result: true} 78 testHelperSuccess(c, "Check(1, checker, 2)", true, func() interface{} { 79 return c.Check(1, checker, 2) 80 }) 81 if !reflect.DeepEqual(checker.params, []interface{}{1, 2}) { 82 c.Fatalf("Bad params for check: %#v", checker.params) 83 } 84} 85 86func (s *HelpersS) TestCheckSucceedWithoutExpected(c *check.C) { 87 checker := &MyChecker{result: true, info: &check.CheckerInfo{Params: []string{"myvalue"}}} 88 testHelperSuccess(c, "Check(1, checker)", true, func() interface{} { 89 return c.Check(1, checker) 90 }) 91 if !reflect.DeepEqual(checker.params, []interface{}{1}) { 92 c.Fatalf("Bad params for check: %#v", checker.params) 93 } 94} 95 96func (s *HelpersS) TestCheckFailWithExpected(c *check.C) { 97 checker := &MyChecker{result: false} 98 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 99 " return c\\.Check\\(1, checker, 2\\)\n" + 100 "\\.+ myobtained int = 1\n" + 101 "\\.+ myexpected int = 2\n\n" 102 testHelperFailure(c, "Check(1, checker, 2)", false, false, log, 103 func() interface{} { 104 return c.Check(1, checker, 2) 105 }) 106} 107 108func (s *HelpersS) TestCheckFailWithExpectedAndComment(c *check.C) { 109 checker := &MyChecker{result: false} 110 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 111 " return c\\.Check\\(1, checker, 2, myComment\\(\"Hello world!\"\\)\\)\n" + 112 "\\.+ myobtained int = 1\n" + 113 "\\.+ myexpected int = 2\n" + 114 "\\.+ Hello world!\n\n" 115 testHelperFailure(c, "Check(1, checker, 2, msg)", false, false, log, 116 func() interface{} { 117 return c.Check(1, checker, 2, myComment("Hello world!")) 118 }) 119} 120 121func (s *HelpersS) TestCheckFailWithExpectedAndStaticComment(c *check.C) { 122 checker := &MyChecker{result: false} 123 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 124 " // Nice leading comment\\.\n" + 125 " return c\\.Check\\(1, checker, 2\\) // Hello there\n" + 126 "\\.+ myobtained int = 1\n" + 127 "\\.+ myexpected int = 2\n\n" 128 testHelperFailure(c, "Check(1, checker, 2, msg)", false, false, log, 129 func() interface{} { 130 // Nice leading comment. 131 return c.Check(1, checker, 2) // Hello there 132 }) 133} 134 135func (s *HelpersS) TestCheckFailWithoutExpected(c *check.C) { 136 checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}} 137 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 138 " return c\\.Check\\(1, checker\\)\n" + 139 "\\.+ myvalue int = 1\n\n" 140 testHelperFailure(c, "Check(1, checker)", false, false, log, 141 func() interface{} { 142 return c.Check(1, checker) 143 }) 144} 145 146func (s *HelpersS) TestCheckFailWithoutExpectedAndMessage(c *check.C) { 147 checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}} 148 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 149 " return c\\.Check\\(1, checker, myComment\\(\"Hello world!\"\\)\\)\n" + 150 "\\.+ myvalue int = 1\n" + 151 "\\.+ Hello world!\n\n" 152 testHelperFailure(c, "Check(1, checker, msg)", false, false, log, 153 func() interface{} { 154 return c.Check(1, checker, myComment("Hello world!")) 155 }) 156} 157 158func (s *HelpersS) TestCheckWithMissingExpected(c *check.C) { 159 checker := &MyChecker{result: true} 160 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 161 " return c\\.Check\\(1, checker\\)\n" + 162 "\\.+ Check\\(myobtained, MyChecker, myexpected\\):\n" + 163 "\\.+ Wrong number of parameters for MyChecker: " + 164 "want 3, got 2\n\n" 165 testHelperFailure(c, "Check(1, checker, !?)", false, false, log, 166 func() interface{} { 167 return c.Check(1, checker) 168 }) 169} 170 171func (s *HelpersS) TestCheckWithTooManyExpected(c *check.C) { 172 checker := &MyChecker{result: true} 173 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 174 " return c\\.Check\\(1, checker, 2, 3\\)\n" + 175 "\\.+ Check\\(myobtained, MyChecker, myexpected\\):\n" + 176 "\\.+ Wrong number of parameters for MyChecker: " + 177 "want 3, got 4\n\n" 178 testHelperFailure(c, "Check(1, checker, 2, 3)", false, false, log, 179 func() interface{} { 180 return c.Check(1, checker, 2, 3) 181 }) 182} 183 184func (s *HelpersS) TestCheckWithError(c *check.C) { 185 checker := &MyChecker{result: false, error: "Some not so cool data provided!"} 186 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 187 " return c\\.Check\\(1, checker, 2\\)\n" + 188 "\\.+ myobtained int = 1\n" + 189 "\\.+ myexpected int = 2\n" + 190 "\\.+ Some not so cool data provided!\n\n" 191 testHelperFailure(c, "Check(1, checker, 2)", false, false, log, 192 func() interface{} { 193 return c.Check(1, checker, 2) 194 }) 195} 196 197func (s *HelpersS) TestCheckWithNilChecker(c *check.C) { 198 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 199 " return c\\.Check\\(1, nil\\)\n" + 200 "\\.+ Check\\(obtained, nil!\\?, \\.\\.\\.\\):\n" + 201 "\\.+ Oops\\.\\. you've provided a nil checker!\n\n" 202 testHelperFailure(c, "Check(obtained, nil)", false, false, log, 203 func() interface{} { 204 return c.Check(1, nil) 205 }) 206} 207 208func (s *HelpersS) TestCheckWithParamsAndNamesMutation(c *check.C) { 209 checker := &MyChecker{result: false, params: []interface{}{3, 4}, names: []string{"newobtained", "newexpected"}} 210 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 211 " return c\\.Check\\(1, checker, 2\\)\n" + 212 "\\.+ newobtained int = 3\n" + 213 "\\.+ newexpected int = 4\n\n" 214 testHelperFailure(c, "Check(1, checker, 2) with mutation", false, false, log, 215 func() interface{} { 216 return c.Check(1, checker, 2) 217 }) 218} 219 220// ----------------------------------------------------------------------- 221// Tests for Assert(), mostly the same as for Check() above. 222 223func (s *HelpersS) TestAssertSucceedWithExpected(c *check.C) { 224 checker := &MyChecker{result: true} 225 testHelperSuccess(c, "Assert(1, checker, 2)", nil, func() interface{} { 226 c.Assert(1, checker, 2) 227 return nil 228 }) 229 if !reflect.DeepEqual(checker.params, []interface{}{1, 2}) { 230 c.Fatalf("Bad params for check: %#v", checker.params) 231 } 232} 233 234func (s *HelpersS) TestAssertSucceedWithoutExpected(c *check.C) { 235 checker := &MyChecker{result: true, info: &check.CheckerInfo{Params: []string{"myvalue"}}} 236 testHelperSuccess(c, "Assert(1, checker)", nil, func() interface{} { 237 c.Assert(1, checker) 238 return nil 239 }) 240 if !reflect.DeepEqual(checker.params, []interface{}{1}) { 241 c.Fatalf("Bad params for check: %#v", checker.params) 242 } 243} 244 245func (s *HelpersS) TestAssertFailWithExpected(c *check.C) { 246 checker := &MyChecker{result: false} 247 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 248 " c\\.Assert\\(1, checker, 2\\)\n" + 249 "\\.+ myobtained int = 1\n" + 250 "\\.+ myexpected int = 2\n\n" 251 testHelperFailure(c, "Assert(1, checker, 2)", nil, true, log, 252 func() interface{} { 253 c.Assert(1, checker, 2) 254 return nil 255 }) 256} 257 258func (s *HelpersS) TestAssertFailWithExpectedAndMessage(c *check.C) { 259 checker := &MyChecker{result: false} 260 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 261 " c\\.Assert\\(1, checker, 2, myComment\\(\"Hello world!\"\\)\\)\n" + 262 "\\.+ myobtained int = 1\n" + 263 "\\.+ myexpected int = 2\n" + 264 "\\.+ Hello world!\n\n" 265 testHelperFailure(c, "Assert(1, checker, 2, msg)", nil, true, log, 266 func() interface{} { 267 c.Assert(1, checker, 2, myComment("Hello world!")) 268 return nil 269 }) 270} 271 272func (s *HelpersS) TestAssertFailWithoutExpected(c *check.C) { 273 checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}} 274 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 275 " c\\.Assert\\(1, checker\\)\n" + 276 "\\.+ myvalue int = 1\n\n" 277 testHelperFailure(c, "Assert(1, checker)", nil, true, log, 278 func() interface{} { 279 c.Assert(1, checker) 280 return nil 281 }) 282} 283 284func (s *HelpersS) TestAssertFailWithoutExpectedAndMessage(c *check.C) { 285 checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}} 286 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 287 " c\\.Assert\\(1, checker, myComment\\(\"Hello world!\"\\)\\)\n" + 288 "\\.+ myvalue int = 1\n" + 289 "\\.+ Hello world!\n\n" 290 testHelperFailure(c, "Assert(1, checker, msg)", nil, true, log, 291 func() interface{} { 292 c.Assert(1, checker, myComment("Hello world!")) 293 return nil 294 }) 295} 296 297func (s *HelpersS) TestAssertWithMissingExpected(c *check.C) { 298 checker := &MyChecker{result: true} 299 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 300 " c\\.Assert\\(1, checker\\)\n" + 301 "\\.+ Assert\\(myobtained, MyChecker, myexpected\\):\n" + 302 "\\.+ Wrong number of parameters for MyChecker: " + 303 "want 3, got 2\n\n" 304 testHelperFailure(c, "Assert(1, checker, !?)", nil, true, log, 305 func() interface{} { 306 c.Assert(1, checker) 307 return nil 308 }) 309} 310 311func (s *HelpersS) TestAssertWithError(c *check.C) { 312 checker := &MyChecker{result: false, error: "Some not so cool data provided!"} 313 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 314 " c\\.Assert\\(1, checker, 2\\)\n" + 315 "\\.+ myobtained int = 1\n" + 316 "\\.+ myexpected int = 2\n" + 317 "\\.+ Some not so cool data provided!\n\n" 318 testHelperFailure(c, "Assert(1, checker, 2)", nil, true, log, 319 func() interface{} { 320 c.Assert(1, checker, 2) 321 return nil 322 }) 323} 324 325func (s *HelpersS) TestAssertWithNilChecker(c *check.C) { 326 log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + 327 " c\\.Assert\\(1, nil\\)\n" + 328 "\\.+ Assert\\(obtained, nil!\\?, \\.\\.\\.\\):\n" + 329 "\\.+ Oops\\.\\. you've provided a nil checker!\n\n" 330 testHelperFailure(c, "Assert(obtained, nil)", nil, true, log, 331 func() interface{} { 332 c.Assert(1, nil) 333 return nil 334 }) 335} 336 337// ----------------------------------------------------------------------- 338// Ensure that values logged work properly in some interesting cases. 339 340func (s *HelpersS) TestValueLoggingWithArrays(c *check.C) { 341 checker := &MyChecker{result: false} 342 log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" + 343 " return c\\.Check\\(\\[\\]byte{1, 2}, checker, \\[\\]byte{1, 3}\\)\n" + 344 "\\.+ myobtained \\[\\]uint8 = \\[\\]byte{0x1, 0x2}\n" + 345 "\\.+ myexpected \\[\\]uint8 = \\[\\]byte{0x1, 0x3}\n\n" 346 testHelperFailure(c, "Check([]byte{1}, chk, []byte{3})", false, false, log, 347 func() interface{} { 348 return c.Check([]byte{1, 2}, checker, []byte{1, 3}) 349 }) 350} 351 352func (s *HelpersS) TestValueLoggingWithMultiLine(c *check.C) { 353 checker := &MyChecker{result: false} 354 log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" + 355 " return c\\.Check\\(\"a\\\\nb\\\\n\", checker, \"a\\\\nb\\\\nc\"\\)\n" + 356 "\\.+ myobtained string = \"\" \\+\n" + 357 "\\.+ \"a\\\\n\" \\+\n" + 358 "\\.+ \"b\\\\n\"\n" + 359 "\\.+ myexpected string = \"\" \\+\n" + 360 "\\.+ \"a\\\\n\" \\+\n" + 361 "\\.+ \"b\\\\n\" \\+\n" + 362 "\\.+ \"c\"\n\n" 363 testHelperFailure(c, `Check("a\nb\n", chk, "a\nb\nc")`, false, false, log, 364 func() interface{} { 365 return c.Check("a\nb\n", checker, "a\nb\nc") 366 }) 367} 368 369func (s *HelpersS) TestValueLoggingWithMultiLineException(c *check.C) { 370 // If the newline is at the end of the string, don't log as multi-line. 371 checker := &MyChecker{result: false} 372 log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" + 373 " return c\\.Check\\(\"a b\\\\n\", checker, \"a\\\\nb\"\\)\n" + 374 "\\.+ myobtained string = \"a b\\\\n\"\n" + 375 "\\.+ myexpected string = \"\" \\+\n" + 376 "\\.+ \"a\\\\n\" \\+\n" + 377 "\\.+ \"b\"\n\n" 378 testHelperFailure(c, `Check("a b\n", chk, "a\nb")`, false, false, log, 379 func() interface{} { 380 return c.Check("a b\n", checker, "a\nb") 381 }) 382} 383 384// ----------------------------------------------------------------------- 385// MakeDir() tests. 386 387type MkDirHelper struct { 388 path1 string 389 path2 string 390 isDir1 bool 391 isDir2 bool 392 isDir3 bool 393 isDir4 bool 394} 395 396func (s *MkDirHelper) SetUpSuite(c *check.C) { 397 s.path1 = c.MkDir() 398 s.isDir1 = isDir(s.path1) 399} 400 401func (s *MkDirHelper) Test(c *check.C) { 402 s.path2 = c.MkDir() 403 s.isDir2 = isDir(s.path2) 404} 405 406func (s *MkDirHelper) TearDownSuite(c *check.C) { 407 s.isDir3 = isDir(s.path1) 408 s.isDir4 = isDir(s.path2) 409} 410 411func (s *HelpersS) TestMkDir(c *check.C) { 412 helper := MkDirHelper{} 413 output := String{} 414 check.Run(&helper, &check.RunConf{Output: &output}) 415 c.Assert(output.value, check.Equals, "") 416 c.Check(helper.isDir1, check.Equals, true) 417 c.Check(helper.isDir2, check.Equals, true) 418 c.Check(helper.isDir3, check.Equals, true) 419 c.Check(helper.isDir4, check.Equals, true) 420 c.Check(helper.path1, check.Not(check.Equals), 421 helper.path2) 422 c.Check(isDir(helper.path1), check.Equals, false) 423 c.Check(isDir(helper.path2), check.Equals, false) 424} 425 426func isDir(path string) bool { 427 if stat, err := os.Stat(path); err == nil { 428 return stat.IsDir() 429 } 430 return false 431} 432 433// Concurrent logging should not corrupt the underling buffer. 434// Use go test -race to detect the race in this test. 435func (s *HelpersS) TestConcurrentLogging(c *check.C) { 436 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(runtime.NumCPU())) 437 var start, stop sync.WaitGroup 438 start.Add(1) 439 for i, n := 0, runtime.NumCPU()*2; i < n; i++ { 440 stop.Add(1) 441 go func(i int) { 442 start.Wait() 443 for j := 0; j < 30; j++ { 444 c.Logf("Worker %d: line %d", i, j) 445 } 446 stop.Done() 447 }(i) 448 } 449 start.Done() 450 stop.Wait() 451} 452 453// ----------------------------------------------------------------------- 454// Test the TestName function 455 456type TestNameHelper struct { 457 name1 string 458 name2 string 459 name3 string 460 name4 string 461 name5 string 462} 463 464func (s *TestNameHelper) SetUpSuite(c *check.C) { s.name1 = c.TestName() } 465func (s *TestNameHelper) SetUpTest(c *check.C) { s.name2 = c.TestName() } 466func (s *TestNameHelper) Test(c *check.C) { s.name3 = c.TestName() } 467func (s *TestNameHelper) TearDownTest(c *check.C) { s.name4 = c.TestName() } 468func (s *TestNameHelper) TearDownSuite(c *check.C) { s.name5 = c.TestName() } 469 470func (s *HelpersS) TestTestName(c *check.C) { 471 helper := TestNameHelper{} 472 output := String{} 473 check.Run(&helper, &check.RunConf{Output: &output}) 474 c.Check(helper.name1, check.Equals, "") 475 c.Check(helper.name2, check.Equals, "TestNameHelper.Test") 476 c.Check(helper.name3, check.Equals, "TestNameHelper.Test") 477 c.Check(helper.name4, check.Equals, "TestNameHelper.Test") 478 c.Check(helper.name5, check.Equals, "") 479} 480 481// ----------------------------------------------------------------------- 482// A couple of helper functions to test helper functions. :-) 483 484func testHelperSuccess(c *check.C, name string, expectedResult interface{}, closure func() interface{}) { 485 var result interface{} 486 defer (func() { 487 if err := recover(); err != nil { 488 panic(err) 489 } 490 checkState(c, result, 491 &expectedState{ 492 name: name, 493 result: expectedResult, 494 failed: false, 495 log: "", 496 }) 497 })() 498 result = closure() 499} 500 501func testHelperFailure(c *check.C, name string, expectedResult interface{}, shouldStop bool, log string, closure func() interface{}) { 502 var result interface{} 503 defer (func() { 504 if err := recover(); err != nil { 505 panic(err) 506 } 507 checkState(c, result, 508 &expectedState{ 509 name: name, 510 result: expectedResult, 511 failed: true, 512 log: log, 513 }) 514 })() 515 result = closure() 516 if shouldStop { 517 c.Logf("%s didn't stop when it should", name) 518 } 519} 520