cch123 / supermonkey

Patch all Go functions for testing
MIT License
250 stars 17 forks source link

Failed in Test #2

Closed kiyonlin closed 3 years ago

kiyonlin commented 3 years ago

Hey thanks for the awesome package!

I met some problems when using supermonkey in test.

// main.go
package main

import (
    "fmt"
)

func main() {
    heyHey()
}

//go:noinline
func heyHey() {
    fmt.Println("fake")
}
// main_test.go
package main

import (
    "fmt"
    "testing"

    sm "github.com/cch123/supermonkey"
)

func Test_HeyHey(t *testing.T) {
    fmt.Println("original function output:")
    heyHey()
    fmt.Println()

    sm.PatchByFullSymbolName("main.heyHey", func() {
        fmt.Println("please be polite")
    })
    fmt.Println("after patch, function output:")
    heyHey()
    fmt.Println()

    sm.UnpatchAll()
    fmt.Println("unpatch all, then output:")
    heyHey()
}

And I run the test like

$go test -gcflags="-l" ./
original function output:
fake

The symbol is main.heyHey, and the patch target addr is 0, there may be 2 possible reasons
        1. the function is inlined, please add //go:noinline to function comment or add -l to gcflags
        2. your input for symbolName or pkg/obj/method is wrong, check by using go tool nm {your_bin_file}
--- FAIL: Test_HeyHey (0.00s)
panic:  [recovered]
        panic: 

goroutine 20 [running]:
testing.tRunner.func1.1(0x1193940, 0x1222350)
        /usr/local/Cellar/go/1.14.4/libexec/src/testing/testing.go:940 +0x2f5
testing.tRunner.func1(0xc0000d0360)
        /usr/local/Cellar/go/1.14.4/libexec/src/testing/testing.go:943 +0x3f9
panic(0x1193940, 0x1222350)
        /usr/local/Cellar/go/1.14.4/libexec/src/runtime/panic.go:969 +0x166
github.com/cch123/supermonkey.PatchByFullSymbolName(0x11e749e, 0xb, 0x1191d20, 0x11f4610)
        /Users/kiyon/go/pkg/mod/github.com/cch123/supermonkey@v0.9.2/supermonkey.go:33 +0x326
learn-golang/supermonkey.Test_HeyHey(0xc0000d0360)
        /Users/kiyon/Code/learn/learn-golang/supermonkey/main_test.go:15 +0xac
testing.tRunner(0xc0000d0360, 0x11f4618)
        /usr/local/Cellar/go/1.14.4/libexec/src/testing/testing.go:991 +0xdc
created by testing.(*T).Run
        /usr/local/Cellar/go/1.14.4/libexec/src/testing/testing.go:1042 +0x357
FAIL    learn-golang/supermonkey        0.399s
FAIL

Did I miss something?

momaek commented 3 years ago

Check out https://github.com/cch123/supermonkey/blob/master/supermonkey.go#L57

cch123 commented 3 years ago

it seems the package name generated by test is not main, for example, on my machine:

image

if you want to patch a function, you need to provide its full package path(and a go.mod project will be some github.com/path/to/your/project/pkg.yourprivatefunction), I'll fix the doc as soon as possible

in Chinese

似乎 Go 的 test 生成的包名不是 main,而是我上面图前面那一串,是下划线 + 目录 + 函数名。

如果是在 go.mod 环境下的话,应该就是全路径,比如 github.com/cch123/elasticsql.Convert,这样的。

patch 的时候得写全路径,我是觉得 go.mod 或者有 GOPATH 的环境下问题不大?

我看看是不是能想办法对这种 test 环境做个特殊定制

kiyonlin commented 3 years ago

Thanks for the quick response! I'll try the full package name.

cch123 commented 3 years ago

@kiyonlin , I've done more tests on this, maybe it's hard to setup on linux. The default test binary generated by Go on linux does not have a symbol table, to make it work , I have to execute go test -c -o xxx.test && ./xxx.test

kiyonlin commented 3 years ago

Alright, this is also an approach. I'm appreciate it very much.