xhd2015/xgo

Add detailed internal design document

xhd2015 opened this issue · 6 comments

The so-called IR rewriting sounds unfamiliar to people.What's it? How does it solve the problem that go-monkey suffers?How does it compare to other mock strategies?Can we dig further to employ this technique not only in mock, but also system tracing?

Hope for more Information about this technique. Maybe a detailed article?

I will add materials on this issue thread to supplement the design document.

A new gained technique: declare init bodies.

Description: the following code always panics no matter you have deleted __xgo_link_generate_init_regs_body 's body or replaced it with completely new contents.

The only difference with other linking names is that it is called from init.

So the best practice is to not include that panic.

However, in user written code there are also cases where a linked method is called from init, but they are all fine with a panic.

Still needs to dig into this.

func init() {
	__xgo_link_generate_init_regs_body()
}

func __xgo_link_generate_init_regs_body() {
	panic("failed to link __xgo_link_generate_init_regs_body")
}

See d6c2b3d#diff-61c14e77880a87918b0cf686da52025d4e0abdd7b94047196c7baf56eb59ce9fR35

the trap.Inspect(fn) implements a way to retrieve func info.
It has different internal paths for these function types:

  • package level function
    • PC lookup
  • struct method
    • -fm suffix check
    • struct.method proto existence check
    • dynamic retrieval
  • interface method
    • -fm suffix check
    • interface proto existence check
    • dynamic retrieval
  • closure
    • closure is registered using IR
    • PC lookup
  • generic function
    • fullName parsing to de-generic
    • generic template existence check
    • no dynamic retrieval since no recv, but is legal to do so
  • generic struct method
    • -fm suffix check
    • fullName parsing to de-generic
    • generic method template existence check
    • dynamic retrieval just for receiver
  • generic interface method
    • to be supported

the trap.Inspect(fn) implements a way to retrieve func info.
It has different internal paths for these function types:

As a result, xgo exposes a single powerful Mock API to users, because it handle these cases smartly. Hiding most complexity from users. All mock can be done in single unified form:

// package level func
mock.Mock(SomeFunc, interceptor)

// per-instance method
// only the bound instance `v` will be mocked
// `v` can be either a struct or an interface
mock.Mock(v.Method, interceptor)

// per-TParam generic function
// only the specified `int` version will be mocked
mock.Mock(GenericFunc[int], interceptor)

// per TParam and instance generic method
v := GenericStruct[int]
mock.Mock(v.Method, interceptor)

// closure can also be mocked
// less used, but also supported
mock.Mock(closure, interceptor)

However, behind the scene, this topic deserves a good description.

非常感谢作者开源了一个这样强大的mock工具,我想基于入门文档继续咨询一些设计与扩展相关的问题

  1. 这边有这样一种场景,希望对一个go web系统进行插桩,然后从另一个效能服务控制这些插桩的效果,比如go web中有一个ControllerA,我可以通过效能服务判断这个ControllerA是mock返回某个值,还是正常处理业务逻辑。但文档里似乎主要将xgo用于单个服务的单元测试mock,想咨询下这部分作者是否有一些实施建议,或者xgo是否有一些特性导致它不支持这样做?
  2. xgo集成了代码覆盖率功能,但是由于xgo本身会修改代码逻辑,我比较好奇在逻辑修改后,xgo是如何保证覆盖率正常工作的,如果文档中可以添加介绍这一部分可能会让使用者在使用时减少相关的顾虑

期待作者的回复