]> Cypherpunks repositories - gostls13.git/commitdiff
io: correctly compute call depth in test
authorDavid Lazar <lazard@golang.org>
Tue, 18 Apr 2017 19:12:54 +0000 (15:12 -0400)
committerDavid Lazar <lazard@golang.org>
Tue, 18 Apr 2017 19:56:54 +0000 (19:56 +0000)
TestMultiReaderFlatten determines the call depth by counting PCs
returned by runtime.Callers. With inlining, this is incorrect because
a PC can represent multiple calls. Furthermore, runtime.Callers might
return an additional "skip" PC, which does not represent a real call.
This modifies the test to use CallersFrames to determine the call depth.
Now the test passes with -l=4.

Change-Id: I284f3b1e0b2d194bd08c230c616914503e5a370d
Reviewed-on: https://go-review.googlesource.com/40990
Run-TryBot: David Lazar <lazard@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/io/multi_test.go

index 710776ad24af1e6aa76418794dfdfa2d29b112a0..0a7eb43032b99f823e1a931dbdae9c860dae22b2 100644 (file)
@@ -175,13 +175,26 @@ func (f readerFunc) Read(p []byte) (int, error) {
        return f(p)
 }
 
+// callDepth returns the logical call depth for the given PCs.
+func callDepth(callers []uintptr) (depth int) {
+       frames := runtime.CallersFrames(callers)
+       more := true
+       for more {
+               _, more = frames.Next()
+               depth++
+       }
+       return
+}
+
 // Test that MultiReader properly flattens chained multiReaders when Read is called
 func TestMultiReaderFlatten(t *testing.T) {
        pc := make([]uintptr, 1000) // 1000 should fit the full stack
-       var myDepth = runtime.Callers(0, pc)
+       n := runtime.Callers(0, pc)
+       var myDepth = callDepth(pc[:n])
        var readDepth int // will contain the depth from which fakeReader.Read was called
        var r Reader = MultiReader(readerFunc(func(p []byte) (int, error) {
-               readDepth = runtime.Callers(1, pc)
+               n := runtime.Callers(1, pc)
+               readDepth = callDepth(pc[:n])
                return 0, errors.New("irrelevant")
        }))