diff --git a/README.md b/README.md index 19077007..9a010dac 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ func TestPatchFunc(t *testing.T) { NOTE: `Patch` and `Mock`(below) supports top-level variables and consts, see [runtime/mock/MOCK_VAR_CONST.md](runtime/mock/MOCK_VAR_CONST.md). -**Notice for mocking stdlib**: due to performance and security impact, only a few packages and functions of stdlib can be mocked, the list can be found at [runtime/mock/stdlib.md](./runtime/mock/stdlib.md). If you want to mock additional stdlib functions, please file a discussion in [Issue#6](https://github.com/xhd2015/xgo/issues/6). +**Notice for mocking stdlib**: There are different modes for mocking stdlib functions,see [runtime/mock/stdlib.md](./runtime/mock/stdlib.md). ## Mock `runtime/mock` also provides another API called `Mock`, which is similar to `Patch`. diff --git a/README_zh_cn.md b/README_zh_cn.md index a8b66366..bfcb3d31 100644 --- a/README_zh_cn.md +++ b/README_zh_cn.md @@ -209,7 +209,7 @@ func TestPatchFunc(t *testing.T) { 注意: `Mock`和`Patch`也支持对包级别的变量和常量进行mock, 见[runtime/mock/MOCK_VAR_CONST.md](runtime/mock/MOCK_VAR_CONST.md). -**关于标准库Mock的注意事项**: 出于性能和安全考虑, 标准库中只有一部分包和函数能被Mock, 这个List可以在[runtime/mock/stdlib.md](./runtime/mock/stdlib.md)找到. 如果你需要Mock的标准库函数不在列表中, 可以在[Issue#6](https://github.com/xhd2015/xgo/issues/6)中进行评论。 +**关于标准库Mock的注意事项**: 针对标准库有两种不同的模式,参考[runtime/mock/stdlib.md](./runtime/mock/stdlib.md). ## Mock `runtime/mock` 还提供了名为`Mock`的API, 它与`Patch`十分类似,唯一的区别是第二个参数接受一个拦截器。 diff --git a/cmd/xgo/option.go b/cmd/xgo/option.go index 2f084143..d60cf0cc 100644 --- a/cmd/xgo/option.go +++ b/cmd/xgo/option.go @@ -188,6 +188,10 @@ func parseOptions(cmd string, args []string) (*options, error) { }) } + if cmd == "test" { + trapStdlib = true + } + for i := 0; i < nArg; i++ { arg := args[i] if !strings.HasPrefix(arg, "-") { @@ -266,8 +270,14 @@ func parseOptions(cmd string, args []string) (*options, error) { continue } - if arg == "--trap-stdlib" { - trapStdlib = true + // supported flag: --trap-stdlib, --trap-stdlib=false, --trap-stdlib=true + trapStdlibFlag, trapStdlibVal := flag.TrySingleFlag([]string{"--trap-stdlib"}, arg) + if trapStdlibFlag != "" { + if trapStdlibVal == "" || trapStdlibVal == "true" { + trapStdlib = true + } else { + trapStdlib = false + } continue } diff --git a/cmd/xgo/runtime_gen/core/version.go b/cmd/xgo/runtime_gen/core/version.go index cbbc6347..728ef860 100755 --- a/cmd/xgo/runtime_gen/core/version.go +++ b/cmd/xgo/runtime_gen/core/version.go @@ -7,8 +7,8 @@ import ( ) const VERSION = "1.0.37" -const REVISION = "5009615738fb02321f124776178716796d32c0b7+1" -const NUMBER = 244 +const REVISION = "2e709f7b1620aea78fdc1dba282bcf6778dd6d51+1" +const NUMBER = 245 // these fields will be filled by compiler const XGO_VERSION = "" diff --git a/cmd/xgo/version.go b/cmd/xgo/version.go index 38da69bb..b5830f9d 100644 --- a/cmd/xgo/version.go +++ b/cmd/xgo/version.go @@ -3,8 +3,8 @@ package main import "fmt" const VERSION = "1.0.37" -const REVISION = "5009615738fb02321f124776178716796d32c0b7+1" -const NUMBER = 244 +const REVISION = "2e709f7b1620aea78fdc1dba282bcf6778dd6d51+1" +const NUMBER = 245 func getRevision() string { revSuffix := "" diff --git a/runtime/core/version.go b/runtime/core/version.go index cbbc6347..728ef860 100644 --- a/runtime/core/version.go +++ b/runtime/core/version.go @@ -7,8 +7,8 @@ import ( ) const VERSION = "1.0.37" -const REVISION = "5009615738fb02321f124776178716796d32c0b7+1" -const NUMBER = 244 +const REVISION = "2e709f7b1620aea78fdc1dba282bcf6778dd6d51+1" +const NUMBER = 245 // these fields will be filled by compiler const XGO_VERSION = "" diff --git a/runtime/mock/stdlib.md b/runtime/mock/stdlib.md index 28233107..4430abaa 100644 --- a/runtime/mock/stdlib.md +++ b/runtime/mock/stdlib.md @@ -1,11 +1,34 @@ -# Limitation On Stdlib Functions -Stdlib functions like `os.ReadFile`, `io.Read` are widely used by go code. So installing a trap on these functions may have big impact on performance and security. +# Support Of Mocking Stdlib Functions +There are two modes for mocking stdlib functions, +1. Default-Allow Mode +2. Default-Disallow Mode -And as compiler treats stdlib from ordinary module differently, current implementation to support stdlib function is based on source code injection, which may causes build time to slow down. +These two modes can be switched by `--trap-stdlib` and `--trap-stdlib=false`. -So only a limited list of stdlib functions can be mocked. However, if there lacks some functions you may want to use, you can leave a comment in [Issue#6](https://github.com/xhd2015/xgo/issues/6) or fire an issue to let us know and add it. +When running `xgo test`, `--trap-stdlib` is assumed, you can turn it off with `--trap-stdlib=false`. -# Supported List +When running `xgo run` and `xgo build`, `--trap-stdlib=false` is assumed, you can turn it on with `--trap-stdlib`. + +# `--trap-stdlib`: Default-Allow Mode +In this mode, most stdlib packages can be mocked, except `runtime`, `syscall`, `reflect`, `sync`, `sync/atomic`, `testing`, `unsafe`. + +# `--trap-stdlib=false`: Default-Disallow Mode +In this mode, only a small list of stdlib functions can be mocked due to performance and security impact. + +Rational: stdlib functions like `os.ReadFile`, `io.Read` are widely used by go code, installing a trap on these functions may have big impact on performance and security. + +So in this mode only a limited list of stdlib functions can be mocked. However, if there lacks some functions you may want to use, you can leave a comment in [Issue#6](https://github.com/xhd2015/xgo/issues/6) or fire an issue to let us know and add it. + +# Functions In Stdlib Calling `recover()` Cannot Be Mocked +When a function calls `recover()`, it will capture panic when used in defer. + +However, since compiler treats stdlib from ordinary module differently, current implementation to support stdlib function is based on source code injection, which may causes build time to slow down, and also causes functions containing `recover()` to be invalid if rewritten, see https://github.com/xhd2015/xgo/issues/164. + +This will be fixed in the long run, but before that, such functions in stdlib cannot be mocked. + +NOTE: functions outside stdlib, even with calling `recover()`, are not affected since they are rewritten with IR, not source code. + +# Supported List When `--trap-stdlib=false` ## `os` - `Getenv` - `Getwd`