Goconvey在Jenkins上使用go routine时引发了恐慌。

huangapple go评论90阅读模式
英文:

Goconvey causing panic with go routine on Jenkins

问题

我有一组使用GoConvey和Go 1.3.1的测试,在本地运行得很好。但是当我使用Jenkins触发构建时,也是使用Go 1.3.1,我会从Goconvey中得到一个与我在测试中使用的goroutine相关的panic错误。

这里是测试代码:

func TestListApplication(t *testing.T) {
    s := &Session{}
    s.Username = "foo"
    s.Password = "bar"
    ts := serveHTTP(t)
    defer ts.Close()
    s.Baseurl = ts.URL
    s.initialize()

    go func() {
        <-s.Comms.AppCount
    }()

    Convey("TestListApplication", t, func() {
        s.Comms.MainWaitGroup.Add(1)

        application := &Application{}
        err := json.Unmarshal(applicationJSON(), application)
        So(err, ShouldBeNil)

        revisions := &Revisions{}
        err = json.Unmarshal(revisionsJSON(), revisions)
        So(err, ShouldBeNil)

        var wg sync.WaitGroup
        wg.Add(1)
        go func() {
            defer wg.Done()
            line := <-s.Comms.Msg
            So(line, ShouldEqual, "3		admin		foo\n")
        }()
        s.listApplication(application, revisions)
        wg.Wait()
    })
}

这里是错误信息:

86 assertions thus far

..
88 assertions thus far

panic: Convey operation made without context on goroutine stack.
Hint: Perhaps you meant to use `Convey(..., func(c C){...})` ?

goroutine 115 [running]:
runtime.panic(0x350d80, 0xc208083050)
    /Users/administrator/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/1.3.1/src/pkg/runtime/panic.c:279 +0xf5
github.com/smartystreets/goconvey/convey.conveyPanic(0x4960d0, 0x78, 0x0, 0x0, 0x0)
    /Users/administrator/jenkins/workspace/tropoCLI/golang/src/github.com/smartystreets/goconvey/convey/context.go:20 +0x6a
github.com/smartystreets/goconvey/convey.mustGetCurrentContext(0x5ecea0)
    /Users/administrator/jenkins/workspace/tropoCLI/golang/src/github.com/smartystreets/goconvey/convey/context.go:52 +0x57
github.com/smartystreets/goconvey/convey.So(0x2d78e0, 0xc208001e80, 0x48f210, 0xc208001e60, 0x1, 0x1)
    /Users/administrator/jenkins/workspace/tropoCLI/golang/src/github.com/smartystreets/goconvey/convey/doc.go:123 +0x1e
_/Users/administrator/jenkins/workspace/tropoCLI.func·048()
    /Users/administrator/jenkins/workspace/tropoCLI/tropoCLI_test.go:222 +0x17d
created by _/Users/administrator/jenkins/workspace/tropoCLI.func·049
    /Users/administrator/jenkins/workspace/tropoCLI/tropoCLI_test.go:223 +0x398

goroutine 16 [chan receive]:
testing.RunTests(0x48f340, 0x5ed680, 0x29, 0x29, 0x48f701)
    /Users/administrator/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/1.3.1/src/pkg/testing/testing.go:505 +0x923
testing.Main(0x48f340, 0x5ed680, 0x29, 0x29, 0x5f5b40, 0x0, 0x0, 0x5f5b40, 0x0, 0x0)
    /Users/administrator/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/1.3.1/src/pkg/testing/testing.go:435 +0x84
main.main()
    _/Users/administrator/jenkins/workspace/tropoCLI/_test/_testmain.go:127 +0x9c

希望对你有所帮助!

英文:

I have a set of test that use GoConvey with Go 1.3.1 that work just fine locally. But when I trigger a build with Jenkins, with the Go 1.3.1 as well, I get a panic from Goconvey related to a go routine I use in my test.

The test may be seen here:

func TestListApplication(t *testing.T) {
	s := &amp;Session{}
	s.Username = &quot;foo&quot;
	s.Password = &quot;bar&quot;
	ts := serveHTTP(t)
	defer ts.Close()
	s.Baseurl = ts.URL
	s.initialize()

	go func() {
		&lt;-s.Comms.AppCount
	}()

	Convey(&quot;TestListApplication&quot;, t, func() {
		s.Comms.MainWaitGroup.Add(1)

		application := &amp;Application{}
		err := json.Unmarshal(applicationJSON(), application)
		So(err, ShouldBeNil)

		revisions := &amp;Revisions{}
		err = json.Unmarshal(revisionsJSON(), revisions)
		So(err, ShouldBeNil)

		var wg sync.WaitGroup
		wg.Add(1)
		go func() {
			defer wg.Done()
			line := &lt;-s.Comms.Msg
			So(line, ShouldEqual, &quot;3		admin		foo\n&quot;)
		}()
		s.listApplication(application, revisions)
		wg.Wait()
	})
}

The error here:

86 assertions thus far

..
88 assertions thus far

panic: Convey operation made without context on goroutine stack.
Hint: Perhaps you meant to use `Convey(..., func(c C){...})` ?

goroutine 115 [running]:
runtime.panic(0x350d80, 0xc208083050)
	/Users/administrator/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/1.3.1/src/pkg/runtime/panic.c:279 +0xf5
github.com/smartystreets/goconvey/convey.conveyPanic(0x4960d0, 0x78, 0x0, 0x0, 0x0)
	/Users/administrator/jenkins/workspace/tropoCLI/golang/src/github.com/smartystreets/goconvey/convey/context.go:20 +0x6a
github.com/smartystreets/goconvey/convey.mustGetCurrentContext(0x5ecea0)
	/Users/administrator/jenkins/workspace/tropoCLI/golang/src/github.com/smartystreets/goconvey/convey/context.go:52 +0x57
github.com/smartystreets/goconvey/convey.So(0x2d78e0, 0xc208001e80, 0x48f210, 0xc208001e60, 0x1, 0x1)
	/Users/administrator/jenkins/workspace/tropoCLI/golang/src/github.com/smartystreets/goconvey/convey/doc.go:123 +0x1e
_/Users/administrator/jenkins/workspace/tropoCLI.func&#172;∑048()
	/Users/administrator/jenkins/workspace/tropoCLI/tropoCLI_test.go:222 +0x17d
created by _/Users/administrator/jenkins/workspace/tropoCLI.func&#172;∑049
	/Users/administrator/jenkins/workspace/tropoCLI/tropoCLI_test.go:223 +0x398

goroutine 16 [chan receive]:
testing.RunTests(0x48f340, 0x5ed680, 0x29, 0x29, 0x48f701)
	/Users/administrator/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/1.3.1/src/pkg/testing/testing.go:505 +0x923
testing.Main(0x48f340, 0x5ed680, 0x29, 0x29, 0x5f5b40, 0x0, 0x0, 0x5f5b40, 0x0, 0x0)
	/Users/administrator/jenkins/tools/org.jenkinsci.plugins.golang.GolangInstallation/1.3.1/src/pkg/testing/testing.go:435 +0x84
main.main()
	_/Users/administrator/jenkins/workspace/tropoCLI/_test/_testmain.go:127 +0x9c

答案1

得分: 11

因为您正在尝试从另一个goroutine执行断言,所以您需要在func()签名中使用最近添加的上下文结构体(C),然后从该上下文调用So。这是稍作修改的版本:

Convey("TestListApplication", t, func(c C) {
    s.Comms.MainWaitGroup.Add(1)

    application := &Application{}
    err := json.Unmarshal(applicationJSON(), application)
    So(err, ShouldBeNil)

    revisions := &Revisions{}
    err = json.Unmarshal(revisionsJSON(), revisions)
    So(err, ShouldBeNil)

    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        line := <-s.Comms.Msg
        c.So(line, ShouldEqual, "3        admin       foo\n")
    }()
    s.listApplication(application, revisions)
    wg.Wait()
})

这是请求 #264的结果。

英文:

Because you are trying to perform an assertion from another goroutine, you'll need to make use of the recently added context struct (C) in the func() signature, then call So off of that context. Here's your version with a slight modification:

Convey(&quot;TestListApplication&quot;, t, func(c C) {
    s.Comms.MainWaitGroup.Add(1)

    application := &amp;Application{}
    err := json.Unmarshal(applicationJSON(), application)
    So(err, ShouldBeNil)

    revisions := &amp;Revisions{}
    err = json.Unmarshal(revisionsJSON(), revisions)
    So(err, ShouldBeNil)

    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        line := &lt;-s.Comms.Msg
        c.So(line, ShouldEqual, &quot;3        admin       foo\n&quot;)
    }()
    s.listApplication(application, revisions)
    wg.Wait()
})

This was a result of pull request #264.

答案2

得分: 0

这个异常是由context.go#mustGetCurrentContext()引发的。你可以在story_conventions_test.go#TestFailureModeNoContext中看到触发相同异常的测试。

Convey("Foo", t, func() {
    done := make(chan int, 1)
    go func() {
        defer func() { done <- 1 }()
        defer expectPanic(t, noStackContext)
        So(len("I have no context"), ShouldBeGreaterThan, 0)
    }()
    <-done
})

从测试示例中可以看出,如果在Convey测试中从一个goroutine中调用另一个goroutine,可能会触发无上下文的panic。

由于Jenkins是从一个goroutine中启动测试,这可能解释了为什么你的GoConvey测试失败(即使在直接调用go test时,在Jenkins之外运行时是正常的)。

英文:

This exception is launched by context.go#mustGetCurrentContext().
you can see a test triggering that same exception in story_conventions_test.go#TestFailureModeNoContext

Convey(&quot;Foo&quot;, t, func() {
    done := make(chan int, 1)
    go func() {
        defer func() { done &lt;- 1 }()
        defer expectPanic(t, noStackContext)
        So(len(&quot;I have no context&quot;), ShouldBeGreaterThan, 0)
    }()
    &lt;-done
})

From the test example, if seems that calling a goroutine from within a goroutine from within a Convey test would trigger the no context panic.

Since Jenkins launches the tests from a goroutine, that might explain why your GoConvey test fails (even though it runs when you are calling go test directly, outside of Jenkins)

huangapple
  • 本文由 发表于 2014年11月14日 07:23:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/26920344.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定