Go语言猴子补丁框架

Overview

Go语言猴子补丁框架 🙉 🐒

test workflow

Go 语言猴子补丁(monkey patching)框架。

本项目对 Bouke 的项目做了优化,不同协程可以独立 patch 同一个函数而互不影响。从而可以并发运行单元测试。

工作原理请参考我的系列文章:

Bouke 已经不再维护原项目,所以只能开一个新项目了 🤣

有兴趣的同学也可以加微信 taoshu-in 讨论,拉你进群。

快速入门

首先,引入 monkey 包

go get github.com/go-kiss/monkey

然后,调用 monkey.Patch 方法 mock 指定函数。

package main

import (
	"fmt"

	"github.com/go-kiss/monkey"
)

func sum(a, b int) int { return a + b }

func main() {
	monkey.Patch(sum, func(a b int) int { return a - b })
	fmt.Println(sum(1,2)) // 输出 -1
}

更多用法请参考使用示例测试用例

注意事项

  1. Monkey 需要关闭 Go 语言的内联优化才能生效,比如测试的时候需要:go test -gcflags=-l
  2. Monkey 需要在运行的时候修改内存代码段,因而无法在一些对安全性要求比较高的系统上工作。
  3. Monkey 不应该用于生产系统,但用来 mock 测试代码还是没有问题的。
  4. Monkey 目前仅支持 amd64 指令架构。支持 linux 和 macos。目前 windows 平台还有问题。
Issues
  • fix: window下支持

    fix: window下支持

    Windows

    TEXT github.com/huandu/go-tls/g.getg.abi0(SB) C:/Users/lzq/go/pkg/mod/github.com/huandu/[email protected]/g/getg_amd64.s
      getg_amd64.s:9	0x45ab80		65488b0c2528000000	MOVQ GS:0x28, CX	
      getg_amd64.s:10	0x45ab89		488b8100000000		MOVQ 0(CX), AX	// 需要在move一次	
      getg_amd64.s:11	0x45ab90		4889442408		MOVQ AX, 0x8(SP)	
      getg_amd64.s:12	0x45ab95		c3			RET			
    

    目前发现win下gs:0x28取出来其实是个二级指针,还需要再做一次取值才能和程序中的一致;我对汇编不是很熟,大致修改了一下,自己测试是可以的,大佬有更好的改法也可由大佬来改一下。

    opened by kkbblzq 4
  • 如何做到在patch状态下调用原函数

    如何做到在patch状态下调用原函数

    刚刚睡不着,画了大概10多分钟看了go夜读的 #119 Go monkey patch 的原理及应用 录播,发现都有一个问题对于类似这种情况见: https://github.com/cch123/supermonkey/issues/12 我看了原理以后感觉应该还是有办法能解决的,例如给开始加个汇编的判断,然后强制走回原函数,不过这个判断的值就比较麻烦了,如果引用一个全局变量倒是比较简单,但是这样频繁修改也不是太合理,要是能直接判断出父级方法是指定的方法然后调用原函数就好了。

    顺便放一下应用场景: https://blog.zeromake.com/pages/replace-now-offset/

    opened by zeromake 3