Good case
package main
import (
"io"
"bytes"
// "github.com/sirupsen/logrus"
)
type A struct {}
func (a *A) exec( stdout io.Writer, stderr io.Writer, stdin io.Reader, paramList []string, env []string, timeout int) {
stdout.Write([]byte("hello"))
stderr.Write([]byte("hello"))
}
func main() {
var a A
writer := &bytes.Buffer{}
writer2 := &bytes.Buffer{}
a.exec( writer, writer2, nil, nil, nil, 1)
}
package main
import (
"bytes"
"io"
"reflect"
"testing"
"github.com/agiledragon/gomonkey/v2"
)
func TestA_exec(t *testing.T) {
var a *A
defer gomonkey.ApplyPrivateMethod(reflect.TypeOf(a), "exec", func(_ *A, stdout io.Writer, stderr io.Writer, stdin io.Reader, paramList []string, env []string, timeout int) {
stdout.Write([]byte("hello"))
stderr.Write([]byte("hello"))
}).Reset()
aa := &A{}
writer := &bytes.Buffer{}
writer2 := &bytes.Buffer{}
writer.Write([]byte("hello"))
writer2.Write([]byte("hello"))
aa.exec(writer, writer2, nil, nil, nil, 1)
}
Bad case
package main
import (
"io"
"bytes"
// "github.com/sirupsen/logrus"
)
type A struct {}
func (a *A) exec( paramList []string, env []string, timeout int, stdout io.Writer, stderr io.Writer, stdin io.Reader,) {
stdout.Write([]byte("hello"))
stderr.Write([]byte("hello"))
}
func main() {
var a A
writer := &bytes.Buffer{}
writer2 := &bytes.Buffer{}
a.exec( nil, nil, 1, writer, writer2, nil,)
}
package main
import (
"bytes"
"io"
"reflect"
"testing"
"github.com/agiledragon/gomonkey/v2"
// "github.com/sirupsen/logrus"
)
func TestA_exec(t *testing.T) {
var a *A
defer gomonkey.ApplyPrivateMethod(reflect.TypeOf(a), "exec", func(_ *A, paramList []string, env []string, timeout int, stdout io.Writer, stderr io.Writer, stdin io.Reader) {
stdout.Write([]byte("hello"))
stderr.Write([]byte("hello"))
}).Reset()
aa := &A{}
writer := &bytes.Buffer{}
writer2 := &bytes.Buffer{}
writer.Write([]byte("hello"))
writer2.Write([]byte("hello"))
aa.exec(nil, nil, 1, writer, writer2, nil)
}
For bad case when I run go test cmd like go test -gcflags=all=-l -v ./... it will panic, but the good case will not. The only difference between them is the order of parameters.
When I run cmd like go run main.go they are both OK.
=== RUN TestA_exec
unexpected fault address 0x0
fatal error: fault
[signal SIGBUS: bus error code=0x1 addr=0x0 pc=0x43e9f9004beb]
goroutine 18 gp=0x4000104540 m=0 mp=0x3908c0 [running]:
runtime.throw({0x21b99f?, 0x1bac68?})
/root/.g/go/src/runtime/panic.go:1067 +0x38 fp=0x4000119e40 sp=0x4000119e10 pc=0x85868
runtime.sigpanic()
/root/.g/go/src/runtime/signal_unix.go:914 +0x90 fp=0x4000119e70 sp=0x4000119e40 pc=0x87460
gotest/test_gomonkey.TestA_exec.func1(0x4000124930?, {0x21b913?, 0x5?, 0x4?}, {0x1e9dc0?, 0x22d478?, 0x4000119f08?}, 0x897d0?, {0x23d720, 0x4000124900}, ...)
/root/go/gotest/test_gomonkey/main_test.go:18 +0xb0 fp=0x4000119eb0 sp=0x4000119e80 pc=0x1baca0
gotest/test_gomonkey.TestA_exec(0x400012a680?)
/root/go/gotest/test_gomonkey/main_test.go:25 +0x10c fp=0x4000119f60 sp=0x4000119eb0 pc=0x1bab4c
testing.tRunner(0x400012a680, 0x22d388)
/root/.g/go/src/testing/testing.go:1690 +0xe4 fp=0x4000119fb0 sp=0x4000119f60 pc=0x130384
testing.(*T).Run.gowrap1()
/root/.g/go/src/testing/testing.go:1743 +0x2c fp=0x4000119fd0 sp=0x4000119fb0 pc=0x13106c
runtime.goexit({})
/root/.g/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x4000119fd0 sp=0x4000119fd0 pc=0x8d394
created by testing.(*T).Run in goroutine 1
/root/.g/go/src/testing/testing.go:1743 +0x2f0
goroutine 1 gp=0x40000021c0 m=nil [chan receive]:
runtime.gopark(0x22d570, 0x4000112300, 0xe, 0x7, 0x2)
/root/.g/go/src/runtime/proc.go:424 +0xe0 fp=0x4000118aa0 sp=0x4000118a70 pc=0x859a0
runtime.chanrecv(0x40001122a0, 0x4000118b9f, 0x1)
/root/.g/go/src/runtime/chan.go:639 +0x298 fp=0x4000118b20 sp=0x4000118aa0 pc=0x1a8e8
runtime.chanrecv1(0x1ea360?, 0x1d5dc0?)
/root/.g/go/src/runtime/chan.go:489 +0x14 fp=0x4000118b50 sp=0x4000118b20 pc=0x1a614
testing.(*T).Run(0x400012a4e0, {0x21cc16, 0xa}, 0x22d388)
/root/.g/go/src/testing/testing.go:1751 +0x304 fp=0x4000118c10 sp=0x4000118b50 pc=0x130f34
testing.runTests.func1(0x400012a4e0)
/root/.g/go/src/testing/testing.go:2168 +0x40 fp=0x4000118c50 sp=0x4000118c10 pc=0x132b50
testing.tRunner(0x400012a4e0, 0x4000118d48)
/root/.g/go/src/testing/testing.go:1690 +0xe4 fp=0x4000118ca0 sp=0x4000118c50 pc=0x130384
testing.runTests(0x4000122168, {0x3852f0, 0x1, 0x1}, {0x98?, 0x20c9c0?, 0x38fce0?})
/root/.g/go/src/testing/testing.go:2166 +0x2e8 fp=0x4000118d70 sp=0x4000118ca0 pc=0x132a68
testing.(*M).Run(0x40001300a0)
/root/.g/go/src/testing/testing.go:2034 +0x400 fp=0x4000118ee0 sp=0x4000118d70 pc=0x1318c0
main.main()
_testmain.go:45 +0x90 fp=0x4000118f60 sp=0x4000118ee0 pc=0x1bae30
runtime.main()
/root/.g/go/src/runtime/proc.go:272 +0x224 fp=0x4000118fd0 sp=0x4000118f60 pc=0x508e4
runtime.goexit({})
/root/.g/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x4000118fd0 sp=0x4000118fd0 pc=0x8d394
goroutine 2 gp=0x4000002700 m=nil [force gc (idle)]:
runtime.gopark(0x22d898, 0x38f750, 0x11, 0xa, 0x1)
/root/.g/go/src/runtime/proc.go:424 +0xe0 fp=0x4000046f70 sp=0x4000046f40 pc=0x859a0
runtime.goparkunlock(0x38f750?, 0x0?, 0x0?, 0x0?)
/root/.g/go/src/runtime/proc.go:430 +0x34 fp=0x4000046fa0 sp=0x4000046f70 pc=0x50d74
runtime.forcegchelper()
/root/.g/go/src/runtime/proc.go:337 +0xb4 fp=0x4000046fd0 sp=0x4000046fa0 pc=0x50c44
runtime.goexit({})
/root/.g/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x4000046fd0 sp=0x4000046fd0 pc=0x8d394
created by runtime.init.7 in goroutine 1
/root/.g/go/src/runtime/proc.go:325 +0x24
goroutine 3 gp=0x4000002c40 m=nil [GC sweep wait]:
runtime.gopark(0x22d898, 0x38f9e0, 0xc, 0x9, 0x1)
/root/.g/go/src/runtime/proc.go:424 +0xe0 fp=0x4000047740 sp=0x4000047710 pc=0x859a0
runtime.goparkunlock(0x38f9e0?, 0x0?, 0x0?, 0x0?)
/root/.g/go/src/runtime/proc.go:430 +0x34 fp=0x4000047770 sp=0x4000047740 pc=0x50d74
runtime.bgsweep(0x400001c080)
/root/.g/go/src/runtime/mgcsweep.go:277 +0x9c fp=0x40000477b0 sp=0x4000047770 pc=0x37f9c
runtime.gcenable.gowrap1()
/root/.g/go/src/runtime/mgc.go:203 +0x28 fp=0x40000477d0 sp=0x40000477b0 pc=0x2c848
runtime.goexit({})
/root/.g/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x40000477d0 sp=0x40000477d0 pc=0x8d394
created by runtime.gcenable in goroutine 1
/root/.g/go/src/runtime/mgc.go:203 +0x6c
goroutine 4 gp=0x4000002e00 m=nil [GC scavenge wait]:
runtime.gopark(0x22d898, 0x38fd60, 0xd, 0xa, 0x2)
/root/.g/go/src/runtime/proc.go:424 +0xe0 fp=0x4000047f20 sp=0x4000047ef0 pc=0x859a0
runtime.goparkunlock(0x38fd60?, 0x98?, 0xa3?, 0x1?)
/root/.g/go/src/runtime/proc.go:430 +0x34 fp=0x4000047f50 sp=0x4000047f20 pc=0x50d74
runtime.(*scavengerState).park(0x38fd60)
/root/.g/go/src/runtime/mgcscavenge.go:425 +0x4c fp=0x4000047f80 sp=0x4000047f50 pc=0x3562c
runtime.bgscavenge(0x400001c080)
/root/.g/go/src/runtime/mgcscavenge.go:653 +0x44 fp=0x4000047fb0 sp=0x4000047f80 pc=0x35b54
runtime.gcenable.gowrap2()
/root/.g/go/src/runtime/mgc.go:204 +0x28 fp=0x4000047fd0 sp=0x4000047fb0 pc=0x2c7e8
runtime.goexit({})
/root/.g/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x4000047fd0 sp=0x4000047fd0 pc=0x8d394
created by runtime.gcenable in goroutine 1
/root/.g/go/src/runtime/mgc.go:204 +0xac
goroutine 17 gp=0x4000104380 m=nil [finalizer wait]:
runtime.gopark(0x22d5d0, 0x3b5f48, 0x10, 0xa, 0x1)
/root/.g/go/src/runtime/proc.go:424 +0xe0 fp=0x4000046590 sp=0x4000046560 pc=0x859a0
runtime.runfinq()
/root/.g/go/src/runtime/mfinal.go:193 +0xf0 fp=0x40000467d0 sp=0x4000046590 pc=0x2b9e0
runtime.goexit({})
/root/.g/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x40000467d0 sp=0x40000467d0 pc=0x8d394
created by runtime.createfing in goroutine 1
/root/.g/go/src/runtime/mfinal.go:163 +0x4c
FAIL gotest/test_gomonkey 0.005s
FAIL
Good case
Bad case
For bad case when I run go test cmd like
go test -gcflags=all=-l -v ./...it will panic, but the good case will not. The only difference between them is the order of parameters.When I run cmd like
go run main.gothey are both OK.