Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mock doesn't work or it triggers a signal SIGBUS Error on arm64 cpu #75

Open
RicardoAGu opened this issue Jan 2, 2025 · 2 comments
Open

Comments

@RicardoAGu
Copy link

Describe the bug

Mock doesn't work or it triggers a signal SIGBUS Error on arm64 cpu, using [email protected].
在使用m3芯片的macbook pro时,使用arm64架构编译运行测试函数,百分百必现mock失效或者触发signal SIGBUS Error,go版本为1.20.5。

To Reproduce
Copy the code below to a new go file, then run the test funtion. I have set "Go tool argument" to -gcflags="all=-l -N" in Goland.
复制如下代码到一个新文件里,运行测试函数即可。我在goland中已经设置了go工具实参 -gcflags="all=-l -N"

package pkg1

import (
	"fmt"
	"testing"

	"github.com/bytedance/mockey"
	. "github.com/smartystreets/goconvey/convey"
)

func Foo(in string) string {
	return in
}

type Fooer interface {
	Fooo(in string) string
}

type A struct{}

func (a A) Foo(in string) string { return in }

func (a *A) Fooo(in string) string { return in }

var Bar = 0

func TestMockXXX(t *testing.T) {
	mockey.PatchConvey("TestMockXXX", t, func() {
		mockey.PatchConvey("simple case", func() {
			mockey.Mock(Foo).Return("c").Build()   // mock函数
			mockey.Mock(A.Foo).Return("d").Build() // mock方法
			mockey.MockValue(&Bar).To(1)           // mock变量

			So(Foo("a"), ShouldEqual, "c")        // 断言`Foo`成功mock
			So(new(A).Foo("b"), ShouldEqual, "d") // 断言`A.Foo`成功mock
			So(Bar, ShouldEqual, 1)               // 断言`Bar`成功mock
		})
		mockey.PatchConvey("modify funcion content", func() {
			mockey.Mock((*A).Fooo).To(
				func(a *A, in string) string { // 函数签名要保持一致,method需要把reciever带上,放在第一个
					fmt.Println("Mocked") // 不止是简单的改变函数返回值,还可以改变函数的行为
					return "Mock: " + in
				},
			).Build()

			So(new(A).Fooo("c"), ShouldEqual, "Mock: c") // 断言`(*A).Fooo`成功mock
		})
		mockey.PatchConvey("mock interface is useless", func() {
			var fooer Fooer
			fooer = &A{}
			mockey.Mock(fooer.Fooo).Return("e").Build()
			So(fooer.Fooo("f"), ShouldEqual, "f") // mock失败。对interface的mock是无效的,程序无法推断需要改变哪段内存的值。
		})
		mockey.PatchConvey("you need to mock struct's method", func() {
			var fooer Fooer
			fooer = &A{}

			mockey.Mock((*A).Fooo).Return("e").Build()
			So(fooer.Fooo("f"), ShouldEqual, "e") // mock成功,必须直接对实现接口的结构体的方法进行mock。
		})
		mockey.PatchConvey("re-mock is forbidden", func() {
			mockey.Mock(Foo).Return("c").Build()
			mockey.PatchConvey("sub convey", func() {
				mocker := mockey.Mock(Foo).Return("d").Build() // 不同层级convey的重复mock不冲突
				So(Foo("a"), ShouldEqual, "d")

				So(func() { mockey.Mock(Foo).Return("c").Build() }, ShouldPanic) // 同一层convey的重复mock会冲突,直接panic

				mocker.Return("e")
				So(Foo("a"), ShouldEqual, "e")

				mocker.Release() // 手动释放之后才可以继续build mocker
				mockey.Mock(Foo).Return("f").Build()
				So(Foo("a"), ShouldEqual, "f")
			})
			So(Foo("a"), ShouldEqual, "c")
		})
		mockey.PatchConvey("mockey support counting called times", func() {
			mocker := mockey.Mock((*A).Fooo).Return("c").Build()

			a := &A{}
			for i := 0; i < 5; i++ {
				So(a.Fooo("a"), ShouldEqual, "c")
			}
			So(mocker.MockTimes(), ShouldEqual, 5)
		})
		mockey.PatchConvey("mockey support condition", func() {
			builder := mockey.Mock(Foo).Return("A").When(
				func(in string) bool { // 条件函数,返回true则mock,false则不mock,入参必须和原函数相同,是方法的话需要带上reciever,放在入参第一个
					return in == "a"
				},
			)
			builder.When(func(in string) bool { return in == "b" }).Return("B").Build()
			So(Foo("a"), ShouldEqual, "A")
			So(Foo("b"), ShouldEqual, "B")
			So(Foo("c"), ShouldEqual, "c")
		})
	})
	// `PatchConvey`外自动释放mock
	fmt.Println(Foo("a"))        // a
	fmt.Println(new(A).Foo("b")) // b
	fmt.Println(Bar)             // 0
}

Expected behavior

When set GOARCH=amd64, the test function can stably succeed, but can not be debugged step by step.
在mac上设置了GOARCH环境变量为amd64后,测试函数可以正常通过,但是无法单步调试,因为delve调试器必须使用arm64版本(跟实际CPU相适配),调试器跟环境变量冲突。
image

Screenshots

image

image

Mockey version:

v1.2.13

Environment:

GO111MODULE="auto"
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/agu/Library/Caches/go-build"
GOENV="/Users/agu/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/agu/go/pkg/mod"
GONOPROXY= you may not concern
GONOSUMDB= you may not concern
GOOS="darwin"
GOPATH="/Users/agu/go"
GOPRIVATE= you may not concern
GOPROXY= you may not concern
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR="/Users/agu/go/temp"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.20.5"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD= you may not concern
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/Users/agu/go/temp/go-build2968640997=/tmp/go-build -gno-record-gcc-switches -fno-common"

Additional context

@Sychorius
Copy link
Collaborator

We tried to reproduce many times but never encountered a BUS error. (M3+ go1.20.5 MacOS14.6.1)
Are you using an older version of MacOS? If so, try set go env -w CGO_ENABLED=0.

@Sychorius
Copy link
Collaborator

Other attempts on the M1 chip may very occasionally trigger a BUS error. This may be caused by #68.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants