smartystreets / goconvey

Go testing in the browser. Integrates with `go test`. Write behavioral tests in Go.
http://smartystreets.github.io/goconvey/
Other
8.18k stars 553 forks source link

Rendering causes endless memory allocations on proto messages #660

Open antoniomacri opened 2 years ago

antoniomacri commented 2 years ago

Consider this:

import (
    . "github.com/smartystreets/goconvey/convey"
    "google.golang.org/protobuf/types/known/wrapperspb"
    "log"
    "testing"
)

func TestConveyBug(t *testing.T) {
    Convey("Given something", t, func() {
        var x = &wrapperspb.BoolValue{Value: false}
        log.Printf("Receive type %v", x)

        So(nil, ShouldResemble, x)
    })
}

When I run this test (I actually used GoLand), it starts allocating memory until I kill it.

The problem seems to be in this function (render.go):

func (s *traverseState) render(buf *bytes.Buffer, ptrs int, v reflect.Value, implicit bool)
antoniomacri commented 2 years ago

Maybe related to #654?

antoniomacri commented 2 years ago

I digged a bit deeper. There are two kind of problems:

  1. Comparison of proto Messages performed using ShouldResemble, which is unreliable.
  2. Rendering of failed comparison for proto Messages, which could hit a cycle.

About the first problem I opened another issue (#664).

Regarding the second problem, the call to Printf causes x.String() to be called. This in turn initializes the state and its atomicMessageInfo field on the proto message. Therefore, as stated here, via atomicMessageInfo there may be a problem like a cycle.

fezho commented 2 months ago

Upgrading protobuf to v1.33.0 can solve this issue