Skip to content

Commit

Permalink
make --trap-stdlib default with running xgo test
Browse files Browse the repository at this point in the history
  • Loading branch information
xhd2015 committed May 29, 2024
1 parent 2e709f7 commit bd3bfe5
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
2 changes: 1 addition & 1 deletion README_zh_cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`十分类似,唯一的区别是第二个参数接受一个拦截器。
Expand Down
14 changes: 12 additions & 2 deletions cmd/xgo/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -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, "-") {
Expand Down Expand Up @@ -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
}

Expand Down
4 changes: 2 additions & 2 deletions cmd/xgo/runtime_gen/core/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ""
Expand Down
4 changes: 2 additions & 2 deletions cmd/xgo/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 := ""
Expand Down
8 changes: 5 additions & 3 deletions patch/ctxt/stdlib.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,11 @@ var stdBlocklist = map[string]map[string]bool{
"*": true,
},
// testing is not harmful
// "testing": map[string]bool{
// "*": true,
// },
// but may cause infinite loop?
// we may dig later or just add somce whitelist
"testing": map[string]bool{
"*": true,
},
"unsafe": map[string]bool{
"*": true,
},
Expand Down
4 changes: 2 additions & 2 deletions runtime/core/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ""
Expand Down
33 changes: 28 additions & 5 deletions runtime/mock/stdlib.md
Original file line number Diff line number Diff line change
@@ -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`
Expand Down

0 comments on commit bd3bfe5

Please sign in to comment.