Closed Zurvarian closed 4 months ago
I'm using version v0.5.6
Unfortunately there is no way currently to fix that behaviour, because of how interfaces and type casts are working in golang.
I was thinking about hacking into type matching table cache, but failed to do so.
So the only way currently to do this is use the proxy.UnsafeCast
method from go-dyno
library, which already should be inside your project's dependency.
Maybe I can expose this as an API method for mockio
if you find it useful
After some thinking, I decided to add Cast[T]
method directly to mockio API. It will check for whether the cast is safe, and cast correctly to another interface.
Hi @ovechkin-dm,
Thanks for the quick response. I was expecting an answer like that... unfortunately the casting is happening inside the source code under test, not in the test method, so I cannot make use of any mocking function there.
The solution I've found, while a bit "workaroundish", was to wrap the call to the interface Y under an ad-hoc struct that implements the interface X. TL;DR: I solved the problem using Delegation pattern https://en.wikipedia.org/wiki/Delegation_pattern
I hoped there could be a simpler solution... Perhaps in future versions of Golang.
Good that you have found a workaround. I think this is the only case where library fails to do it's job well. Other issues should be easily fixable.
@Zurvarian
Actually I have an idea how to fix this.
The idea is to use reflect.StructOf
with delegated anonymous interface, as you mentioned.
I already have a working POC.
It still requires some rework though, because StructOf
does not allow invoking creating/methods.
I think I will fix it within a month.
Amazing, I'll test it once it is released :)
I think I managed to do it.
Can you please check?
v0.6.0
Hi,
Tested, it throws an error though.
When testing with --race
flag:
=== RUN TestInterfaceShadowingNotWorking
fatal error: checkptr: converted pointer straddles multiple allocations
goroutine 6 [running]:
runtime.throw({0x8a17fe?, 0xc00023e220?})
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/panic.go:1077 +0x5c fp=0xc0002258b0 sp=0xc000225880 pc=0x47313c
runtime.checkptrAlignment(0xc00023e210?, 0x10?, 0x2?)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/checkptr.go:26 +0x5b fp=0xc0002258d0 sp=0xc0002258b0 pc=0x44197b
github.com/ovechkin-dm/go-dyno/proxy.Create[...](0x927900)
/home/jmontesinos/.asdf/installs/golang/1.21.9/packages/pkg/mod/github.com/ovechkin-dm/go-dyno@v0.1.2/proxy/proxy.go:34 +0x8b6 fp=0xc000225c18 sp=0xc0002258d0 pc=0x815016
github.com/ovechkin-dm/go-dyno/pkg/dyno.Dynamic[...]({0x922800, 0xc0000e1110?})
/home/jmontesinos/.asdf/installs/golang/1.21.9/packages/pkg/mod/github.com/ovechkin-dm/go-dyno@v0.1.2/pkg/dyno/api.go:20 +0xf7 fp=0xc000225c60 sp=0xc000225c18 pc=0x8146f7
github.com/ovechkin-dm/mockio/mock.Mock[...].func1()
/home/jmontesinos/.asdf/installs/golang/1.21.9/packages/pkg/mod/github.com/ovechkin-dm/mockio@v0.6.0/registry/registry.go:62 +0xb4 fp=0xc000225d18 sp=0xc000225c60 pc=0x812374
github.com/ovechkin-dm/mockio/registry.withCheck[...](0xc0000b7e38?)
/home/jmontesinos/.asdf/installs/golang/1.21.9/packages/pkg/mod/github.com/ovechkin-dm/mockio@v0.6.0/registry/registry.go:155 +0x26c fp=0xc000225e10 sp=0xc000225d18 pc=0x815ccc
github.com/ovechkin-dm/mockio/registry.Mock[...](...)
/home/jmontesinos/.asdf/installs/golang/1.21.9/packages/pkg/mod/github.com/ovechkin-dm/mockio@v0.6.0/registry/registry.go:60
github.com/ovechkin-dm/mockio/mock.Mock[...]()
/home/jmontesinos/.asdf/installs/golang/1.21.9/packages/pkg/mod/github.com/ovechkin-dm/mockio@v0.6.0/mock/api.go:65 +0x88 fp=0xc000225e58 sp=0xc000225e10 pc=0x8145c8
jmontesinos/golang-mocking/test/mockio.TestInterfaceShadowingNotWorking(0x0?)
/home/jmontesinos/Projects/Training/Go/golang-mocking/test/mockio/interface_shadowing_test.go:20 +0x45 fp=0xc000225ea0 sp=0xc000225e58 pc=0x811285
testing.tRunner(0xc00023a4e0, 0x8bf6d8)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/testing/testing.go:1595 +0x262 fp=0xc000225fb0 sp=0xc000225ea0 pc=0x5b6002
testing.(*T).Run.func1()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/testing/testing.go:1648 +0x45 fp=0xc000225fe0 sp=0xc000225fb0 pc=0x5b7ca5
runtime.goexit()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc000225fe8 sp=0xc000225fe0 pc=0x4aad21
created by testing.(*T).Run in goroutine 1
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/testing/testing.go:1648 +0x846
goroutine 1 [chan receive]:
runtime.gopark(0x0?, 0x0?, 0x50?, 0x21?, 0x18?)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/proc.go:398 +0xce fp=0xc0002296a0 sp=0xc000229680 pc=0x47602e
runtime.chanrecv(0xc0000184d0, 0xc000229787, 0x1)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/chan.go:583 +0x385 fp=0xc000229718 sp=0xc0002296a0 pc=0x441185
runtime.chanrecv1(0x88aec0?, 0x834520?)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/chan.go:442 +0x12 fp=0xc000229740 sp=0xc000229718 pc=0x440dd2
testing.(*T).Run(0xc00023a340, {0x899db0, 0x20}, 0x8bf6d8)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/testing/testing.go:1649 +0x871 fp=0xc000229860 sp=0xc000229740 pc=0x5b7a11
testing.runTests.func1(0x0?)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/testing/testing.go:2054 +0x85 fp=0xc0002298b8 sp=0xc000229860 pc=0x5bb9a5
testing.tRunner(0xc00023a340, 0xc000229af8)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/testing/testing.go:1595 +0x262 fp=0xc0002299c8 sp=0xc0002298b8 pc=0x5b6002
testing.runTests(0xc0000e4be0?, {0xb3b8c0, 0x2, 0x2}, {0xd0?, 0x1e?, 0xb45800?})
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/testing/testing.go:2052 +0x8ae fp=0xc000229b28 sp=0xc0002299c8 pc=0x5bb80e
testing.(*M).Run(0xc0000e4be0)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/testing/testing.go:1925 +0xcd8 fp=0xc000229eb8 sp=0xc000229b28 pc=0x5b8d98
main.main()
_testmain.go:49 +0x2be fp=0xc000229f40 sp=0xc000229eb8 pc=0x81613e
runtime.main()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/proc.go:267 +0x2bb fp=0xc000229fe0 sp=0xc000229f40 pc=0x475bbb
runtime.goexit()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc000229fe8 sp=0xc000229fe0 pc=0x4aad21
goroutine 2 [force gc (idle)]:
runtime.gopark(0xb04d50?, 0xb460e0?, 0x0?, 0x0?, 0x0?)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/proc.go:398 +0xce fp=0xc0000a27a8 sp=0xc0000a2788 pc=0x47602e
runtime.goparkunlock(...)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/proc.go:404
runtime.forcegchelper()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/proc.go:322 +0xb3 fp=0xc0000a27e0 sp=0xc0000a27a8 pc=0x475e93
runtime.goexit()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc0000a27e8 sp=0xc0000a27e0 pc=0x4aad21
created by runtime.init.6 in goroutine 1
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/proc.go:310 +0x1a
goroutine 3 [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/proc.go:398 +0xce fp=0xc0000b2f78 sp=0xc0000b2f58 pc=0x47602e
runtime.goparkunlock(...)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/proc.go:404
runtime.bgsweep(0x0?)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/mgcsweep.go:280 +0x94 fp=0xc0000b2fc8 sp=0xc0000b2f78 pc=0x460134
runtime.gcenable.func1()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/mgc.go:200 +0x25 fp=0xc0000b2fe0 sp=0xc0000b2fc8 pc=0x455305
runtime.goexit()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc0000b2fe8 sp=0xc0000b2fe0 pc=0x4aad21
created by runtime.gcenable in goroutine 1
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/mgc.go:200 +0x66
goroutine 4 [GC scavenge wait]:
runtime.gopark(0xc000018070?, 0x91f990?, 0x1?, 0x0?, 0xc0000071e0?)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/proc.go:398 +0xce fp=0xc0000b8f70 sp=0xc0000b8f50 pc=0x47602e
runtime.goparkunlock(...)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/proc.go:404
runtime.(*scavengerState).park(0xb45880)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/mgcscavenge.go:425 +0x49 fp=0xc0000b8fa0 sp=0xc0000b8f70 pc=0x45da29
runtime.bgscavenge(0x0?)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/mgcscavenge.go:653 +0x3c fp=0xc0000b8fc8 sp=0xc0000b8fa0 pc=0x45df9c
runtime.gcenable.func2()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/mgc.go:201 +0x25 fp=0xc0000b8fe0 sp=0xc0000b8fc8 pc=0x4552a5
runtime.goexit()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc0000b8fe8 sp=0xc0000b8fe0 pc=0x4aad21
created by runtime.gcenable in goroutine 1
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/mgc.go:201 +0xa5
goroutine 5 [finalizer wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/proc.go:398 +0xce fp=0xc000184e20 sp=0xc000184e00 pc=0x47602e
runtime.runfinq()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/mfinal.go:193 +0x13b fp=0xc000184fe0 sp=0xc000184e20 pc=0x45431b
runtime.goexit()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc000184fe8 sp=0xc000184fe0 pc=0x4aad21
created by runtime.createfing in goroutine 1
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/mfinal.go:163 +0x3d
FAIL jmontesinos/golang-mocking/test/mockio 0.010s
When testing without --race
flag:
--- FAIL: TestInterfaceShadowingNotWorking (0.00s)
panic: interface conversion: struct { Delegate mockio.ShadowingInterface; DynamicStruct *proxy.DynamicStruct } is not mockio.ShadowingInterface: missing method methodX [recovered]
panic: interface conversion: struct { Delegate mockio.ShadowingInterface; DynamicStruct *proxy.DynamicStruct } is not mockio.ShadowingInterface: missing method methodX
goroutine 35 [running]:
testing.tRunner.func1.2({0x6b56a0, 0xc0001954d0})
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/testing/testing.go:1545 +0x238
testing.tRunner.func1()
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/testing/testing.go:1548 +0x397
panic({0x6b56a0?, 0xc0001954d0?})
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/runtime/panic.go:914 +0x21f
github.com/ovechkin-dm/go-dyno/proxy.Create[...](0x0)
/home/jmontesinos/.asdf/installs/golang/1.21.9/packages/pkg/mod/github.com/ovechkin-dm/go-dyno@v0.1.2/proxy/proxy.go:48 +0x786
github.com/ovechkin-dm/go-dyno/pkg/dyno.Dynamic[...]({0x7775a0, 0xc000195080?})
/home/jmontesinos/.asdf/installs/golang/1.21.9/packages/pkg/mod/github.com/ovechkin-dm/go-dyno@v0.1.2/pkg/dyno/api.go:20 +0x86
github.com/ovechkin-dm/mockio/mock.Mock[...].func1()
/home/jmontesinos/.asdf/installs/golang/1.21.9/packages/pkg/mod/github.com/ovechkin-dm/mockio@v0.6.0/registry/registry.go:62 +0x5c
github.com/ovechkin-dm/mockio/registry.withCheck[...](0xc000210710?)
/home/jmontesinos/.asdf/installs/golang/1.21.9/packages/pkg/mod/github.com/ovechkin-dm/mockio@v0.6.0/registry/registry.go:155 +0x156
github.com/ovechkin-dm/mockio/registry.Mock[...](...)
/home/jmontesinos/.asdf/installs/golang/1.21.9/packages/pkg/mod/github.com/ovechkin-dm/mockio@v0.6.0/registry/registry.go:60
github.com/ovechkin-dm/mockio/mock.Mock[...]()
/home/jmontesinos/.asdf/installs/golang/1.21.9/packages/pkg/mod/github.com/ovechkin-dm/mockio@v0.6.0/mock/api.go:65 +0x35
jmontesinos/golang-mocking/test/mockio.TestInterfaceShadowingNotWorking(0x0?)
/home/jmontesinos/Projects/Training/Go/golang-mocking/test/mockio/interface_shadowing_test.go:20 +0x31
testing.tRunner(0xc000185040, 0x727f70)
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/testing/testing.go:1595 +0xff
created by testing.(*T).Run in goroutine 1
/home/jmontesinos/.asdf/installs/golang/1.21.9/go/src/testing/testing.go:1648 +0x3ad
exit status 2
FAIL jmontesinos/golang-mocking/test/mockio 0.005s
The issue is with unexported method in the interface. Will try to fix it.
Tested with an exported method and it, indeed works.
Though the issue with --race
flag persists.
Will fix both issues, probably tomorrow
Should work fine now
v0.6.1
Can you please check?
It works like a charm now :)
Though I have another obscure issue when using -race
and working with channels.
runtime: pointer 0xc0001c1228 to unused region of span span.base()=0xc0004f2000 span.limit=0xc0004f8000 span.state=1
runtime: found in object at *(0xc000395500+0x88)
object=0xc000395500 s.base()=0xc000394000 s.limit=0xc000395f80 s.spanclass=62 s.elemsize=896 s.state=mSpanInUse
It very well could be the test itself that is doing something off, and it works when the -race
flag is not supplied, so I think this could be treated as a different issue.
Thanks for checking. I will close this issue then. Feel free to provide minimal reproducible example for that race error.
I know this is a rather obscure case, but, if I try to do a casting of an interface X into another interface Y that shares the same method, if the instance behind interface X is a mock, it throws a runtime exception stating that the DynamicStruct lacks of the "shared" method (In a sense that both have the same method)
Test Example: