launchpad.net/gocheck@v0.0.0-20140225173054-000000000087/helpers_test.go (about)

     1  // These tests verify the inner workings of the helper methods associated
     2  // with gocheck.T.
     3  
     4  package gocheck_test
     5  
     6  import (
     7  	"launchpad.net/gocheck"
     8  	"os"
     9  	"reflect"
    10  	"runtime"
    11  	"sync"
    12  )
    13  
    14  var helpersS = gocheck.Suite(&HelpersS{})
    15  
    16  type HelpersS struct{}
    17  
    18  func (s *HelpersS) TestCountSuite(c *gocheck.C) {
    19  	suitesRun += 1
    20  }
    21  
    22  // -----------------------------------------------------------------------
    23  // Fake checker and bug info to verify the behavior of Assert() and Check().
    24  
    25  type MyChecker struct {
    26  	info   *gocheck.CheckerInfo
    27  	params []interface{}
    28  	names  []string
    29  	result bool
    30  	error  string
    31  }
    32  
    33  func (checker *MyChecker) Info() *gocheck.CheckerInfo {
    34  	if checker.info == nil {
    35  		return &gocheck.CheckerInfo{Name: "MyChecker", Params: []string{"myobtained", "myexpected"}}
    36  	}
    37  	return checker.info
    38  }
    39  
    40  func (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  
    54  type myCommentType string
    55  
    56  func (c myCommentType) CheckCommentString() string {
    57  	return string(c)
    58  }
    59  
    60  func myComment(s string) myCommentType {
    61  	return myCommentType(s)
    62  }
    63  
    64  // -----------------------------------------------------------------------
    65  // Ensure a real checker actually works fine.
    66  
    67  func (s *HelpersS) TestCheckerInterface(c *gocheck.C) {
    68  	testHelperSuccess(c, "Check(1, Equals, 1)", true, func() interface{} {
    69  		return c.Check(1, gocheck.Equals, 1)
    70  	})
    71  }
    72  
    73  // -----------------------------------------------------------------------
    74  // Tests for Check(), mostly the same as for Assert() following these.
    75  
    76  func (s *HelpersS) TestCheckSucceedWithExpected(c *gocheck.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  
    86  func (s *HelpersS) TestCheckSucceedWithoutExpected(c *gocheck.C) {
    87  	checker := &MyChecker{result: true, info: &gocheck.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  
    96  func (s *HelpersS) TestCheckFailWithExpected(c *gocheck.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  
   108  func (s *HelpersS) TestCheckFailWithExpectedAndComment(c *gocheck.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  
   121  func (s *HelpersS) TestCheckFailWithExpectedAndStaticComment(c *gocheck.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  
   135  func (s *HelpersS) TestCheckFailWithoutExpected(c *gocheck.C) {
   136  	checker := &MyChecker{result: false, info: &gocheck.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  
   146  func (s *HelpersS) TestCheckFailWithoutExpectedAndMessage(c *gocheck.C) {
   147  	checker := &MyChecker{result: false, info: &gocheck.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  
   158  func (s *HelpersS) TestCheckWithMissingExpected(c *gocheck.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  
   171  func (s *HelpersS) TestCheckWithTooManyExpected(c *gocheck.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  
   184  func (s *HelpersS) TestCheckWithError(c *gocheck.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  
   197  func (s *HelpersS) TestCheckWithNilChecker(c *gocheck.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  
   208  func (s *HelpersS) TestCheckWithParamsAndNamesMutation(c *gocheck.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  
   223  func (s *HelpersS) TestAssertSucceedWithExpected(c *gocheck.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  
   234  func (s *HelpersS) TestAssertSucceedWithoutExpected(c *gocheck.C) {
   235  	checker := &MyChecker{result: true, info: &gocheck.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  
   245  func (s *HelpersS) TestAssertFailWithExpected(c *gocheck.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  
   258  func (s *HelpersS) TestAssertFailWithExpectedAndMessage(c *gocheck.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  
   272  func (s *HelpersS) TestAssertFailWithoutExpected(c *gocheck.C) {
   273  	checker := &MyChecker{result: false, info: &gocheck.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  
   284  func (s *HelpersS) TestAssertFailWithoutExpectedAndMessage(c *gocheck.C) {
   285  	checker := &MyChecker{result: false, info: &gocheck.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  
   297  func (s *HelpersS) TestAssertWithMissingExpected(c *gocheck.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  
   311  func (s *HelpersS) TestAssertWithError(c *gocheck.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  
   325  func (s *HelpersS) TestAssertWithNilChecker(c *gocheck.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  
   340  func (s *HelpersS) TestValueLoggingWithArrays(c *gocheck.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  
   352  func (s *HelpersS) TestValueLoggingWithMultiLine(c *gocheck.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  
   369  func (s *HelpersS) TestValueLoggingWithMultiLineException(c *gocheck.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  
   387  type MkDirHelper struct {
   388  	path1  string
   389  	path2  string
   390  	isDir1 bool
   391  	isDir2 bool
   392  	isDir3 bool
   393  	isDir4 bool
   394  }
   395  
   396  func (s *MkDirHelper) SetUpSuite(c *gocheck.C) {
   397  	s.path1 = c.MkDir()
   398  	s.isDir1 = isDir(s.path1)
   399  }
   400  
   401  func (s *MkDirHelper) Test(c *gocheck.C) {
   402  	s.path2 = c.MkDir()
   403  	s.isDir2 = isDir(s.path2)
   404  }
   405  
   406  func (s *MkDirHelper) TearDownSuite(c *gocheck.C) {
   407  	s.isDir3 = isDir(s.path1)
   408  	s.isDir4 = isDir(s.path2)
   409  }
   410  
   411  func (s *HelpersS) TestMkDir(c *gocheck.C) {
   412  	helper := MkDirHelper{}
   413  	output := String{}
   414  	gocheck.Run(&helper, &gocheck.RunConf{Output: &output})
   415  	c.Assert(output.value, gocheck.Equals, "")
   416  	c.Check(helper.isDir1, gocheck.Equals, true)
   417  	c.Check(helper.isDir2, gocheck.Equals, true)
   418  	c.Check(helper.isDir3, gocheck.Equals, true)
   419  	c.Check(helper.isDir4, gocheck.Equals, true)
   420  	c.Check(helper.path1, gocheck.Not(gocheck.Equals),
   421  		helper.path2)
   422  	c.Check(isDir(helper.path1), gocheck.Equals, false)
   423  	c.Check(isDir(helper.path2), gocheck.Equals, false)
   424  }
   425  
   426  func 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.
   435  func (s *HelpersS) TestConcurrentLogging(c *gocheck.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  // A couple of helper functions to test helper functions. :-)
   455  
   456  func testHelperSuccess(c *gocheck.C, name string, expectedResult interface{}, closure func() interface{}) {
   457  	var result interface{}
   458  	defer (func() {
   459  		if err := recover(); err != nil {
   460  			panic(err)
   461  		}
   462  		checkState(c, result,
   463  			&expectedState{
   464  				name:   name,
   465  				result: expectedResult,
   466  				failed: false,
   467  				log:    "",
   468  			})
   469  	})()
   470  	result = closure()
   471  }
   472  
   473  func testHelperFailure(c *gocheck.C, name string, expectedResult interface{}, shouldStop bool, log string, closure func() interface{}) {
   474  	var result interface{}
   475  	defer (func() {
   476  		if err := recover(); err != nil {
   477  			panic(err)
   478  		}
   479  		checkState(c, result,
   480  			&expectedState{
   481  				name:   name,
   482  				result: expectedResult,
   483  				failed: true,
   484  				log:    log,
   485  			})
   486  	})()
   487  	result = closure()
   488  	if shouldStop {
   489  		c.Logf("%s didn't stop when it should", name)
   490  	}
   491  }