3

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 := &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()
    })
}

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·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
Michael Whatcott
  • 5,603
  • 6
  • 36
  • 50
jsgoecke
  • 249
  • 3
  • 11

2 Answers2

11

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("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()
})

This was a result of pull request #264.

Michael Whatcott
  • 5,603
  • 6
  • 36
  • 50
0

This exception is launched by context.go#mustGetCurrentContext().
you can see a test triggering that same exception in 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
})

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)

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250