Hello community, here is the log from the commit of package go-gocheck for openSUSE:Factory checked in at 2012-09-14 12:23:31 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/go-gocheck (Old) and /work/SRC/openSUSE:Factory/.go-gocheck.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "go-gocheck", Maintainer is "" Changes: -------- --- /work/SRC/openSUSE:Factory/go-gocheck/go-gocheck.changes 2012-06-12 07:08:14.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.go-gocheck.new/go-gocheck.changes 2012-09-14 12:23:35.000000000 +0200 @@ -1,0 +2,6 @@ +Tue Aug 14 20:56:32 UTC 2012 - [email protected] + +- Update to latest r2012.07.24 +- support for std libs testing package benchmarking + +------------------------------------------------------------------- Old: ---- gocheck-0.0.0+bzr20120304.tar.bz2 New: ---- gocheck-2012.07.24.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ go-gocheck.spec ++++++ --- /var/tmp/diff_new_pack.e3P41p/_old 2012-09-14 12:23:36.000000000 +0200 +++ /var/tmp/diff_new_pack.e3P41p/_new 2012-09-14 12:23:36.000000000 +0200 @@ -18,7 +18,7 @@ Name: go-gocheck -Version: 0.0.0+bzr20120304 +Version: 2012.07.24 Release: 0 Summary: Rich testing framework for the Go language License: BSD-3-Clause @@ -28,10 +28,11 @@ %define go_import launchpad.net/gocheck BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: go-devel +%if 0%{?suse_version} >= 1100 Recommends: go-gocheck-doc +%endif %{go_provides} %{go_requires} -%{go_disable_brp_strip_static_archive} %description The Go language provides an internal testing library, named "testing", which is @@ -46,6 +47,7 @@ - Richer test helpers: assertions which interrupt the test immediately, - deep multi-type comparisons, string matching, etc - Suite-based grouping of tests + - Benchmarks integrated in the suite logic (with fixtures, etc) - Fixtures: per suite and/or per test set up and tear down - Management of temporary directories - Panic-catching logic, with proper error reporting @@ -71,9 +73,11 @@ %gobuild %install +%{go_disable_brp_strip_static_archive} + %goinstall %godoc -%gotest launchpad.net/gocheck +%go_disable_brp_strip_static_archive %check %files ++++++ gocheck-0.0.0+bzr20120304.tar.bz2 -> gocheck-2012.07.24.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gocheck/TODO new/gocheck/TODO --- old/gocheck/TODO 2012-03-05 06:43:39.000000000 +0100 +++ new/gocheck/TODO 2012-08-14 21:36:50.000000000 +0200 @@ -1,3 +1,2 @@ - Assert(slice, Contains, item) - Parallel test support -- Benchmark support diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gocheck/benchmark.go new/gocheck/benchmark.go --- old/gocheck/benchmark.go 1970-01-01 01:00:00.000000000 +0100 +++ new/gocheck/benchmark.go 2012-08-14 21:36:50.000000000 +0200 @@ -0,0 +1,176 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gocheck + +import ( + "fmt" + "reflect" + "runtime" + "time" +) + +// testingB is a type passed to Benchmark functions to manage benchmark +// timing and to specify the number of iterations to run. +type timer struct { + start time.Time // Time test or benchmark started + duration time.Duration + N int + bytes int64 + timerOn bool + benchTime time.Duration +} + +// StartTimer starts timing a test. This function is called automatically +// before a benchmark starts, but it can also used to resume timing after +// a call to StopTimer. +func (c *C) StartTimer() { + if !c.timerOn { + c.start = time.Now() + c.timerOn = true + } +} + +// StopTimer stops timing a test. This can be used to pause the timer +// while performing complex initialization that you don't +// want to measure. +func (c *C) StopTimer() { + if c.timerOn { + c.duration += time.Now().Sub(c.start) + c.timerOn = false + } +} + +// ResetTimer sets the elapsed benchmark time to zero. +// It does not affect whether the timer is running. +func (c *C) ResetTimer() { + if c.timerOn { + c.start = time.Now() + } + c.duration = 0 +} + +// SetBytes informs the number of bytes that the benchmark processes +// on each iteration. If this is called in a benchmark it will also +// report MB/s. +func (c *C) SetBytes(n int64) { + c.bytes = n +} + +func (c *C) nsPerOp() int64 { + if c.N <= 0 { + return 0 + } + return c.duration.Nanoseconds() / int64(c.N) +} + +func (c *C) mbPerSec() float64 { + if c.bytes <= 0 || c.duration <= 0 || c.N <= 0 { + return 0 + } + return (float64(c.bytes) * float64(c.N) / 1e6) / c.duration.Seconds() +} + +func (c *C) timerString() string { + if c.N <= 0 { + return fmt.Sprintf("%3.3fs", float64(c.duration.Nanoseconds())/1e9) + } + mbs := c.mbPerSec() + mb := "" + if mbs != 0 { + mb = fmt.Sprintf("\t%7.2f MB/s", mbs) + } + nsop := c.nsPerOp() + ns := fmt.Sprintf("%10d ns/op", nsop) + if c.N > 0 && nsop < 100 { + // The format specifiers here make sure that + // the ones digits line up for all three possible formats. + if nsop < 10 { + ns = fmt.Sprintf("%13.2f ns/op", float64(c.duration.Nanoseconds())/float64(c.N)) + } else { + ns = fmt.Sprintf("%12.1f ns/op", float64(c.duration.Nanoseconds())/float64(c.N)) + } + } + return fmt.Sprintf("%8d\t%s%s", c.N, ns, mb) +} + +func min(x, y int) int { + if x > y { + return y + } + return x +} + +func max(x, y int) int { + if x < y { + return y + } + return x +} + +// roundDown10 rounds a number down to the nearest power of 10. +func roundDown10(n int) int { + var tens = 0 + // tens = floor(log_10(n)) + for n > 10 { + n = n / 10 + tens++ + } + // result = 10^tens + result := 1 + for i := 0; i < tens; i++ { + result *= 10 + } + return result +} + +// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX]. +func roundUp(n int) int { + base := roundDown10(n) + if n < (2 * base) { + return 2 * base + } + if n < (5 * base) { + return 5 * base + } + return 10 * base +} + +// benchmarkN runs a single benchmark for the specified number of iterations. +func benchmarkN(c *C, n int) { + // Try to get a comparable environment for each run + // by clearing garbage from previous runs. + runtime.GC() + c.N = n + c.ResetTimer() + c.StartTimer() + c.method.Call([]reflect.Value{reflect.ValueOf(c)}) + c.StopTimer() +} + +// benchmark runs the benchmark function. It gradually increases the number +// of benchmark iterations until the benchmark runs for a second in order +// to get a reasonable measurement. +func benchmark(c *C) { + // Run the benchmark for a single iteration in case it's expensive. + n := 1 + benchmarkN(c, n) + // Run the benchmark for at least the specified amount of time. + for c.status == succeededSt && c.duration < c.benchTime && n < 1e9 { + last := n + // Predict iterations/sec. + if c.nsPerOp() == 0 { + n = 1e9 + } else { + n = int(c.benchTime.Nanoseconds() / c.nsPerOp()) + } + // Run more iterations than we think we'll need for a second (1.5x). + // Don't grow too fast in case we had timing errors previously. + // Be sure to run at least one more than last time. + n = max(min(n+n/2, 100*last), last+1) + // Round up to something easy to read. + n = roundUp(n) + benchmarkN(c, n) + } +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gocheck/benchmark_test.go new/gocheck/benchmark_test.go --- old/gocheck/benchmark_test.go 1970-01-01 01:00:00.000000000 +0100 +++ new/gocheck/benchmark_test.go 2012-08-14 21:36:50.000000000 +0200 @@ -0,0 +1,69 @@ +// These tests verify the test running logic. + +package gocheck_test + +import ( + . "launchpad.net/gocheck" + "time" +) + +var benchmarkS = Suite(&BenchmarkS{}) + +type BenchmarkS struct{} + +func (s *BenchmarkS) TestCountSuite(c *C) { + suitesRun += 1 +} + +func (s *BenchmarkS) TestBasicTestTiming(c *C) { + helper := FixtureHelper{sleepOn: "Test1", sleep: 1000000 * time.Nanosecond} + output := String{} + runConf := RunConf{Output: &output, Verbose: true} + Run(&helper, &runConf) + + expected := "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test1\t0\\.001s\n" + + "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test2\t0\\.000s\n" + c.Assert(output.value, Matches, expected) +} + +func (s *BenchmarkS) TestStreamTestTiming(c *C) { + helper := FixtureHelper{sleepOn: "SetUpSuite", sleep: 1000000 * time.Nanosecond} + output := String{} + runConf := RunConf{Output: &output, Stream: true} + Run(&helper, &runConf) + + expected := "(?s).*\nPASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.SetUpSuite\t *0\\.001s\n.*" + c.Assert(output.value, Matches, expected) +} + +// Quite unfortunate that these two tests alone account for most of the + +func (s *BenchmarkS) TestBenchmark(c *C) { + helper := FixtureHelper{sleep: 100000} + output := String{} + runConf := RunConf{ + Output: &output, + Benchmark: true, + BenchmarkTime: 10000000, + Filter: "Benchmark1", + } + Run(&helper, &runConf) + + expected := "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Benchmark1\t *100\t *[12][0-9]{5} ns/op\n" + c.Assert(output.value, Matches, expected) +} + +func (s *BenchmarkS) TestBenchmarkBytes(c *C) { + helper := FixtureHelper{sleep: 100000} + output := String{} + runConf := RunConf{ + Output: &output, + Benchmark: true, + BenchmarkTime: 10000000, + Filter: "Benchmark2", + } + Run(&helper, &runConf) + + expected := "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Benchmark2\t *100\t *[12][0-9]{5} ns/op\t *[4-9]\\.[0-9]{2} MB/s\n" + c.Assert(output.value, Matches, expected) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gocheck/foundation_test.go new/gocheck/foundation_test.go --- old/gocheck/foundation_test.go 2012-03-05 06:43:39.000000000 +0100 +++ new/gocheck/foundation_test.go 2012-08-14 21:36:50.000000000 +0200 @@ -242,7 +242,7 @@ expected := "" + "FAIL EXPECTED: foundation_test\\.go:[0-9]+:" + - " ExpectFailureSucceedHelper\\.TestSucceed \\(It booms!\\)\n" + " ExpectFailureSucceedHelper\\.TestSucceed \\(It booms!\\)\t *[.0-9]+s\n" matched, err := regexp.MatchString(expected, output.value) if err != nil { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gocheck/gocheck.go new/gocheck/gocheck.go --- old/gocheck/gocheck.go 2012-03-05 06:43:39.000000000 +0100 +++ new/gocheck/gocheck.go 2012-08-14 21:36:50.000000000 +0200 @@ -15,6 +15,7 @@ "strconv" "strings" "sync" + "time" ) // ----------------------------------------------------------------------- @@ -23,7 +24,6 @@ const ( fixtureKd = iota testKd - benchmarkKd ) type funcKind int @@ -63,13 +63,7 @@ reason string mustFail bool tempDir *tempDir -} - -func newC(method *methodType, kind funcKind, logb *bytes.Buffer, logw io.Writer, tempDir *tempDir) *C { - if logb == nil { - logb = bytes.NewBuffer(nil) - } - return &C{method: method, kind: kind, logb: logb, logw: logw, tempDir: tempDir, done: make(chan *C, 1)} + timer } func (c *C) stopNow() { @@ -112,7 +106,7 @@ if td._path != "" { err := os.RemoveAll(td._path) if err != nil { - fmt.Fprintf(os.Stderr, "WARNING: Error cleaning up temporaries: " + err.Error()) + fmt.Fprintf(os.Stderr, "WARNING: Error cleaning up temporaries: "+err.Error()) } } } @@ -190,7 +184,7 @@ i := 0 n := len(s) for i < n { - j := i+1 + j := i + 1 for j < n && s[j-1] != '\n' { j++ } @@ -452,30 +446,29 @@ tempDir *tempDir output *outputWriter reportedProblemLast bool + benchTime time.Duration } type RunConf struct { - Output io.Writer - Stream bool - Verbose bool - Filter string + Output io.Writer + Stream bool + Verbose bool + Filter string + Benchmark bool + BenchmarkTime time.Duration // Defaults to 1 second } // Create a new suiteRunner able to run all methods in the given suite. func newSuiteRunner(suite interface{}, runConf *RunConf) *suiteRunner { - var writer io.Writer - var stream, verbose bool - var filter string - - writer = os.Stdout - + var conf RunConf if runConf != nil { - if runConf.Output != nil { - writer = runConf.Output - } - stream = runConf.Stream - verbose = runConf.Verbose - filter = runConf.Filter + conf = *runConf + } + if conf.Output == nil { + conf.Output = os.Stdout + } + if conf.Benchmark { + conf.Verbose = true } suiteType := reflect.TypeOf(suite) @@ -483,17 +476,20 @@ suiteValue := reflect.ValueOf(suite) runner := &suiteRunner{ - suite: suite, - output: newOutputWriter(writer, stream, verbose), - tracker: newResultTracker(), + suite: suite, + output: newOutputWriter(conf.Output, conf.Stream, conf.Verbose), + tracker: newResultTracker(), + benchTime: conf.BenchmarkTime, } - runner.tests = make([]*methodType, suiteNumMethods) + runner.tests = make([]*methodType, 0, suiteNumMethods) runner.tempDir = new(tempDir) - testsLen := 0 + if runner.benchTime == 0 { + runner.benchTime = 1 * time.Second + } var filterRegexp *regexp.Regexp - if filter != "" { - if regexp, err := regexp.Compile(filter); err != nil { + if conf.Filter != "" { + if regexp, err := regexp.Compile(conf.Filter); err != nil { msg := "Bad filter expression: " + err.Error() runner.tracker.result.RunError = errors.New(msg) return runner @@ -530,28 +526,31 @@ case "TearDownTest": runner.tearDownTest = method default: - if isWantedTest(suiteName, method.Info.Name, filterRegexp) { - runner.tests[testsLen] = method - testsLen += 1 + if isWanted(conf.Benchmark, suiteName, method.Info.Name, filterRegexp) { + runner.tests = append(runner.tests, method) } } } - - runner.tests = runner.tests[0:testsLen] return runner } -// Return true if the given suite name and method name should be -// considered as a test to be run. -func isWantedTest(suiteName, testName string, filterRegexp *regexp.Regexp) bool { - if !strings.HasPrefix(testName, "Test") { +// isWanted returns true if the given suite and method names should be run. +// The bench result indicates whether the method is a benchmark rather than +// a test. +func isWanted(benchmark bool, suiteName, methodName string, filterRegexp *regexp.Regexp) bool { + prefix := "Test" + if benchmark { + prefix = "Benchmark" + } + if !strings.HasPrefix(methodName, prefix) { return false - } else if filterRegexp == nil { + } + if filterRegexp == nil { return true } - return (filterRegexp.MatchString(testName) || + return (filterRegexp.MatchString(methodName) || filterRegexp.MatchString(suiteName) || - filterRegexp.MatchString(suiteName+"."+testName)) + filterRegexp.MatchString(suiteName+"."+methodName)) } // Run all methods in the given suite. @@ -590,7 +589,18 @@ if runner.output.Stream { logw = runner.output } - c := newC(method, kind, logb, logw, runner.tempDir) + if logb == nil { + logb = bytes.NewBuffer(nil) + } + c := &C{ + method: method, + kind: kind, + logb: logb, + logw: logw, + tempDir: runner.tempDir, + done: make(chan *C, 1), + timer: timer{benchTime: runner.benchTime}, + } runner.tracker.expectCall(c) go (func() { runner.reportCallStarted(c) @@ -647,6 +657,9 @@ func (runner *suiteRunner) runFixture(method *methodType, logb *bytes.Buffer) *C { if method != nil { c := runner.runFunc(method, fixtureKd, logb, func(c *C) { + c.ResetTimer() + c.StartTimer() + defer c.StopTimer() c.method.Call([]reflect.Value{reflect.ValueOf(c)}) }) return c @@ -682,14 +695,25 @@ defer runner.runFixtureWithPanic(runner.tearDownTest, nil, &skipped) runner.runFixtureWithPanic(runner.setUpTest, c.logb, &skipped) mt := c.method.Type() - if mt.NumIn() == 1 && mt.In(0) == reflect.TypeOf(c) { - c.method.Call([]reflect.Value{reflect.ValueOf(c)}) - } else { + if mt.NumIn() != 1 || mt.In(0) != reflect.TypeOf(c) { // Rather than a plain panic, provide a more helpful message when // the argument type is incorrect. c.status = panickedSt c.logArgPanic(c.method, "*gocheck.C") + return + } + if strings.HasPrefix(c.method.Info.Name, "Test") { + c.ResetTimer() + c.StartTimer() + defer c.StopTimer() + c.method.Call([]reflect.Value{reflect.ValueOf(c)}) + return + } + if strings.HasPrefix(c.method.Info.Name, "Benchmark") { + benchmark(c) + return } + panic("unexpected method prefix: " + c.method.Info.Name) }) } @@ -810,10 +834,14 @@ func (ow *outputWriter) WriteCallSuccess(label string, c *C) { if ow.Stream || (ow.Verbose && c.kind == testKd) { + // TODO Use a buffer here. var suffix string if c.reason != "" { suffix = " (" + c.reason + ")" } + if c.status == succeededSt { + suffix += "\t" + c.timerString() + } suffix += "\n" if ow.Stream { suffix += "\n" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gocheck/gocheck_test.go new/gocheck/gocheck_test.go --- old/gocheck/gocheck_test.go 2012-03-05 06:43:39.000000000 +0100 +++ new/gocheck/gocheck_test.go 2012-08-14 21:36:50.000000000 +0200 @@ -11,12 +11,13 @@ "flag" "fmt" "os" + "time" ) // We count the number of suites run at least to get a vague hint that the // test suite is behaving as it should. Otherwise a bug introduced at the // very core of the system could go unperceived. -const suitesRunExpected = 7 +const suitesRunExpected = 8 var suitesRun int = 0 @@ -93,11 +94,14 @@ // Helper suite for testing ordering and behavior of fixture. type FixtureHelper struct { - calls [64]string - n int - panicOn string - skip bool - skipOnN int + calls [64]string + n int + panicOn string + skip bool + skipOnN int + sleepOn string + sleep time.Duration + bytes int64 } func (s *FixtureHelper) trace(name string, c *gocheck.C) { @@ -107,6 +111,9 @@ if name == s.panicOn { panic(name) } + if s.sleep > 0 && s.sleepOn == name { + time.Sleep(s.sleep) + } if s.skip && s.skipOnN == n { c.Skip("skipOnN == n") } @@ -136,6 +143,21 @@ s.trace("Test2", c) } +func (s *FixtureHelper) Benchmark1(c *gocheck.C) { + s.trace("Benchmark1", c) + for i := 0; i < c.N; i++ { + time.Sleep(s.sleep) + } +} + +func (s *FixtureHelper) Benchmark2(c *gocheck.C) { + s.trace("Benchmark2", c) + c.SetBytes(1024) + for i := 0; i < c.N; i++ { + time.Sleep(s.sleep) + } +} + // ----------------------------------------------------------------------- // Helper which checks the state of the test and ensures that it matches // the given expectations. Depends on c.Errorf() working, so shouldn't diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gocheck/run.go new/gocheck/run.go --- old/gocheck/run.go 2012-03-05 06:43:39.000000000 +0100 +++ new/gocheck/run.go 2012-08-14 21:36:50.000000000 +0200 @@ -1,9 +1,10 @@ package gocheck import ( - "testing" "flag" "fmt" + "testing" + "time" ) // ----------------------------------------------------------------------- @@ -22,18 +23,26 @@ // ----------------------------------------------------------------------- // Public running interface. -var filterFlag = flag.String("gocheck.f", "", - "Regular expression selecting what to run") -var verboseFlag = flag.Bool("gocheck.v", false, - "Verbose mode") -var streamFlag = flag.Bool("gocheck.vv", false, - "Super verbose mode (disables output caching)") +var ( + filterFlag = flag.String("gocheck.f", "", "Regular expression selecting what to run") + verboseFlag = flag.Bool("gocheck.v", false, "Verbose mode") + streamFlag = flag.Bool("gocheck.vv", false, "Super verbose mode (disables output caching)") + benchFlag = flag.Bool("gocheck.b", false, "Run benchmarks") + benchTime = flag.Duration("gocheck.btime", 1 * time.Second, "approximate run time for each benchmark") +) // Run all test suites registered with the Suite() function, printing // results to stdout, and reporting any failures back to the 'testing' // module. func TestingT(testingT *testing.T) { - result := RunAll(&RunConf{Filter: *filterFlag, Verbose: *verboseFlag, Stream: *streamFlag}) + conf := &RunConf{ + Filter: *filterFlag, + Verbose: *verboseFlag, + Stream: *streamFlag, + Benchmark: *benchFlag, + BenchmarkTime: *benchTime, + } + result := RunAll(conf) println(result.String()) if !result.Passed() { testingT.Fail() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gocheck/run_test.go new/gocheck/run_test.go --- old/gocheck/run_test.go 2012-03-05 06:43:39.000000000 +0100 +++ new/gocheck/run_test.go 2012-08-14 21:36:50.000000000 +0200 @@ -288,8 +288,8 @@ runConf := RunConf{Output: &output, Verbose: true} Run(&helper, &runConf) - expected := "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test1\n" + - "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test2\n" + expected := "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test1\t *[.0-9]+s\n" + + "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test2\t *[.0-9]+s\n" c.Assert(output.value, Matches, expected) } @@ -301,7 +301,7 @@ Run(&helper, &runConf) expected := "(?s).*PANIC.*\n-+\n" + // Should have an extra line. - "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test2\n" + "PASS: gocheck_test\\.go:[0-9]+: FixtureHelper\\.Test2\t *[.0-9]+s\n" c.Assert(output.value, Matches, expected) } @@ -344,9 +344,9 @@ Run(helper, &runConf) expected := "START: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\n0\n" + - "PASS: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\n\n" + + "PASS: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\t *[.0-9]+s\n\n" + "START: run_test\\.go:[0-9]+: StreamHelper\\.Test1\n1\n" + - "PASS: run_test\\.go:[0-9]+: StreamHelper\\.Test1\n\n" + + "PASS: run_test\\.go:[0-9]+: StreamHelper\\.Test1\t *[.0-9]+s\n\n" + "START: run_test\\.go:[0-9]+: StreamHelper\\.Test2\n2\n3\n4\n" + "FAIL: run_test\\.go:[0-9]+: StreamHelper\\.Test2\n\n" -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
