Skip to content

Commit

Permalink
support mocking variables and constants
Browse files Browse the repository at this point in the history
  • Loading branch information
xhd2015 committed Apr 6, 2024
1 parent 1211c51 commit f805071
Show file tree
Hide file tree
Showing 44 changed files with 1,134 additions and 196 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ There are other options,see [doc/INSTALLATION.md](./doc/INSTALLATION.md).
There is no specific limitation on OS and Architecture.

**All OS and Architectures** are supported by `xgo` as long as they are supported by `go`.
| | x86_64 | ARM64 | Any Other Arch... |
|---------|-----------|-----------|-----------|
| Linux | Y | Y | Y|
| Windows | Y | Y | Y|
| macOS | Y | Y | Y|
| Any Other OS... | Y | Y | Y|
| | x86 | x86_64 (amd64) | arm64 | any other Arch... |
|:---------|:-----------:|:-----------:|:-----------:|:-----------:|
| Linux | Y | Y | Y | Y |
| Windows | Y | Y | Y | Y |
| macOS | Y | Y | Y | Y |
| any other OS... | Y | Y | Y | Y|

# Quick Start
Let's write a unit test with `xgo`:
Expand Down
12 changes: 6 additions & 6 deletions README_zh_cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ xgo version

对OS和Arch没有限制, `xgo`支持所有`go`支持的OS和Arch。

| | x86_64 | ARM64 | 任何其他架构... |
|---------|-----------|-----------|-----------|
| Linux | Y | Y | Y|
| Windows | Y | Y | Y|
| macOS | Y | Y | Y|
| 任何其他OS... | Y | Y | Y|
| | x86 | x86_64 (amd64) | arm64 | 任何其他架构... |
|:---------|:-----------:|:-----------:|:-----------:|:-----------:|
| Linux | Y | Y | Y | Y |
| Windows | Y | Y | Y | Y |
| macOS | Y | Y | Y | Y |
| 任何其他OS... | Y | Y | Y | Y|

# 快速开始
我们基于`xgo`编写一个单元测试:
Expand Down
1 change: 1 addition & 0 deletions cmd/xgo/exec_tool/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func getDebugEnv(xgoCompilerEnableEnv string) map[string]string {
XGO_DEBUG_DUMP_AST: os.Getenv(XGO_DEBUG_DUMP_AST),
XGO_DEBUG_DUMP_AST_FILE: os.Getenv(XGO_DEBUG_DUMP_AST_FILE),
"GOCACHE": os.Getenv("GOCACHE"),
XGO_MAIN_MODULE: os.Getenv(XGO_MAIN_MODULE),
"GOROOT": "../..",
"PATH": "../../bin:${env:PATH}",
"XGO_COMPILER_ENABLE": xgoCompilerEnableEnv,
Expand Down
2 changes: 2 additions & 0 deletions cmd/xgo/exec_tool/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ const XGO_DEBUG_VSCODE = "XGO_DEBUG_VSCODE"
const XGO_TOOLCHAIN_VERSION = "XGO_TOOLCHAIN_VERSION"
const XGO_TOOLCHAIN_REVISION = "XGO_TOOLCHAIN_REVISION"
const XGO_TOOLCHAIN_VERSION_NUMBER = "XGO_TOOLCHAIN_VERSION_NUMBER"

const XGO_MAIN_MODULE = "XGO_MAIN_MODULE"
11 changes: 10 additions & 1 deletion cmd/xgo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,17 @@ func handleBuild(cmd string, args []string) error {
go tailLog(compileLog)
}

execCmdEnv := os.Environ()
var execCmd *exec.Cmd
if !cmdExec {
mainModule, err := goinfo.ResolveMainModule(projectDir, remainArgs)
if err != nil {
if !errors.Is(err, goinfo.ErrGoModNotFound) && !errors.Is(err, goinfo.ErrGoModDoesNotHaveModule) {
return err
}
}
logDebug("resolved main module: %s", mainModule)
execCmdEnv = append(execCmdEnv, "XGO_MAIN_MODULE="+mainModule)
// GOCACHE="$shdir/build-cache" PATH=$goroot/bin:$PATH GOROOT=$goroot DEBUG_PKG=$debug go build -toolexec="$shdir/exce_tool $cmd" "${build_flags[@]}" "$@"
buildCmdArgs := []string{cmd}
if toolExecFlag != "" {
Expand Down Expand Up @@ -401,7 +410,7 @@ func handleBuild(cmd string, args []string) error {
logDebug("command: %v", remainArgs)
execCmd = exec.Command(remainArgs[0], remainArgs[1:]...)
}
execCmd.Env = os.Environ()
execCmd.Env = execCmdEnv
execCmd.Env, err = patchEnvWithGoroot(execCmd.Env, instrumentGoroot)
if err != nil {
return err
Expand Down
15 changes: 9 additions & 6 deletions cmd/xgo/patch/runtime_def.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ if os.Getenv("XGO_COMPILER_ENABLE")=="true" {
for _, n := range noders {
files = append(files, n.file)
}
xgo_syntax.AfterFilesParsed(files, func(name string, r io.Reader) {
xgo_syntax.AfterFilesParsed(files, func(name string, r io.Reader) *syntax.File {
p := &noder{
err: make(chan syntax.Error),
}
Expand All @@ -88,10 +88,11 @@ if os.Getenv("XGO_COMPILER_ENABLE")=="true" {
if err != nil {
e := err.(syntax.Error)
p.error(e)
return
return nil
}
p.file = file
noders = append(noders, p)
return file
})
}
`
Expand All @@ -102,17 +103,18 @@ if os.Getenv("XGO_COMPILER_ENABLE")=="true" {
for _, n := range noders {
files = append(files, n.file)
}
xgo_syntax.AfterFilesParsed(files, func(name string, r io.Reader) {
xgo_syntax.AfterFilesParsed(files, func(name string, r io.Reader) *syntax.File {
p := &noder{}
fbase := syntax.NewFileBase(name)
file, err := syntax.Parse(fbase, r, nil, p.pragma, syntax.CheckBranches)
if err != nil {
e := err.(syntax.Error)
base.ErrorfAt(p.makeXPos(e.Pos), "%s", e.Msg)
return
return nil
}
p.file = file
noders = append(noders, p)
return file
})
}
`
Expand All @@ -123,17 +125,18 @@ if os.Getenv("XGO_COMPILER_ENABLE")=="true" {
for _, n := range noders {
files = append(files, n.file)
}
xgo_syntax.AfterFilesParsed(files, func(name string, r io.Reader) {
xgo_syntax.AfterFilesParsed(files, func(name string, r io.Reader) *syntax.File {
p := &noder{}
fbase := syntax.NewFileBase(name)
file, err := syntax.Parse(fbase, r, nil, p.pragma, syntax.CheckBranches)
if err != nil {
e := err.(syntax.Error)
base.ErrorfAt(m.makeXPos(e.Pos), 0,"%s", e.Msg)
return
return nil
}
p.file = file
noders = append(noders, p)
return file
})
}
`
Expand Down
2 changes: 2 additions & 0 deletions cmd/xgo/patch/runtime_def_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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.18"
const REVISION = "03d82b3e31832e5947c5d3a7ef8752f4f39db28c+1"
const NUMBER = 162
const REVISION = "1211c519c8005ddbd66189cf64e958aa69e5789f+1"
const NUMBER = 163

func getRevision() string {
revSuffix := ""
Expand Down
3 changes: 0 additions & 3 deletions patch/adapter_go1.17_18.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,5 @@ func wrapListType(expr *ir.CompLitExpr) *ir.CompLitExpr {
}

func canInsertTrap(fn *ir.Func) bool {
if isSkippableSpecialPkg() {
return false
}
return true
}
13 changes: 0 additions & 13 deletions patch/adapter_go1.17_18_19.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,3 @@
// +build go1.17,!go1.20

package patch

import (
xgo_ctxt "cmd/compile/internal/xgo_rewrite_internal/patch/ctxt"
"strings"
)

func isSkippableSpecialPkg() bool {
curPkgPath := xgo_ctxt.GetPkgPath()
if strings.HasPrefix(curPkgPath, "golang.org/x/") {
return true
}
return false
}
3 changes: 0 additions & 3 deletions patch/adapter_go1.19.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ func canInsertTrap(fn *ir.Func) bool {
if curPkgPath != fnPkgPath {
return false
}
if isSkippableSpecialPkg() {
return false
}
// fnName := fn.Sym().Name
// if strings.Contains(fnName, "[") && strings.Contains(fnName, "]") {
// return false
Expand Down
18 changes: 15 additions & 3 deletions patch/ctxt/ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@ package ctxt

import (
"cmd/compile/internal/base"
"os"
"strings"
)

const XgoModule = "github.com/xhd2015/xgo"
const XgoRuntimePkg = XgoModule + "/runtime"
const XgoRuntimeCorePkg = XgoModule + "/runtime/core"

var XgoMainModule = os.Getenv("XGO_MAIN_MODULE")

func SkipPackageTrap() bool {
pkgPath := GetPkgPath()
if pkgPath == "" {
return true
}
if strings.HasPrefix(pkgPath, "runtime/") || strings.HasPrefix(pkgPath, "internal/") {
return true
}
if base.Flag.Std {
// skip std lib, especially skip:
// runtime, runtime/internal, runtime/*, reflect, unsafe, syscall, sync, sync/atomic, internal/*
Expand All @@ -24,14 +34,15 @@ func SkipPackageTrap() bool {
// func may be a foreigner.

// allow http
pkgPath := GetPkgPath()
if _, ok := stdWhitelist[pkgPath]; ok {
return false
}
return true
}
if isSkippableSpecialPkg(pkgPath) {
return true
}

pkgPath := GetPkgPath()
if IsPkgXgoSkipTrap(pkgPath) {
return true
}
Expand Down Expand Up @@ -111,6 +122,7 @@ func AllowPkgFuncTrap(pkgPath string, isStd bool, funcName string) bool {
return true
}

// skip all packages for xgo,except test
func IsPkgXgoSkipTrap(pkg string) bool {
suffix, ok := cutPkgPrefix(pkg, XgoModule)
if !ok {
Expand All @@ -119,7 +131,7 @@ func IsPkgXgoSkipTrap(pkg string) bool {
if suffix == "" {
return true
}
// check if the package is test, runtime/test
// check if the package is test or runtime/test
_, ok = cutPkgPrefix(suffix, "test")
if ok {
return false
Expand Down
15 changes: 15 additions & 0 deletions patch/ctxt/skip_pkg_go1.19_and_below.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//go:build go1.17 && !go1.20
// +build go1.17,!go1.20

package ctx

import (
"strings"
)

func isSkippableSpecialPkg(pkgPath string) bool {
if strings.HasPrefix(pkgPath, "golang.org/x/") {
return true
}
return false
}
8 changes: 8 additions & 0 deletions patch/ctxt/skip_pkg_go1.20.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//go:build go1.20
// +build go1.20

package ctxt

func isSkippableSpecialPkg(pkgPath string) bool {
return false
}
13 changes: 11 additions & 2 deletions patch/link_name.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,21 @@ const xgoRuntimeTrapPkg = xgoRuntimePkgPrefix + "trap"
const xgoOnTestStart = "__xgo_on_test_start"

const XgoLinkSetTrap = "__xgo_link_set_trap"
const XgoLinkSetTrapVar = "__xgo_link_set_trap_var"
const XgoTrapForGenerated = "__xgo_trap_for_generated"
const setTrap = "__xgo_set_trap"
const setTrapVar = "__xgo_set_trap_var"
const XgoTrapVarForGenerated = "__xgo_trap_var_for_generated"

// only allowed from reflect
const reflectSetImpl = "__xgo_set_all_method_by_name_impl"

var linkMap = map[string]string{
"__xgo_link_getcurg": "__xgo_getcurg",
"__xgo_link_set_trap": setTrap,
XgoLinkSetTrap: setTrap,
XgoLinkSetTrapVar: setTrapVar,
xgo_syntax.XgoLinkTrapForGenerated: XgoTrapForGenerated,
"__xgo_link_trap_var_for_generated": XgoTrapVarForGenerated,
"__xgo_link_init_finished": "__xgo_init_finished",
"__xgo_link_on_init_finished": "__xgo_on_init_finished",
"__xgo_link_on_gonewproc": "__xgo_on_gonewproc",
Expand Down Expand Up @@ -64,7 +69,7 @@ func isLinkValid(fnName string, targetName string, pkgPath string) bool {
return pkgPath == "reflect"
}

isLinkTrap := fnName == XgoLinkSetTrap
isLinkTrap := fnName == XgoLinkSetTrap || fnName == XgoLinkSetTrapVar
if isLinkTrap {
// the special trap
return pkgPath == xgoRuntimeTrapPkg || strings.HasPrefix(pkgPath, xgoTestPkgPrefix)
Expand Down Expand Up @@ -118,6 +123,10 @@ func replaceWithRuntimeCall(fn *ir.Func, name string) {
getCallerPC := typecheck.LookupRuntime("getcallerpc")
paramNames[1] = ir.NewCallExpr(fn.Pos(), ir.OCALL, getCallerPC, nil)
}
if name == XgoTrapVarForGenerated {
// set pos to auto generated
fn.SetPos(base.AutogeneratedPos)
}
resNames := getTypeNames(results)
fnPos := fn.Pos()

Expand Down
4 changes: 3 additions & 1 deletion patch/syntax/func_stub_def.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package syntax

const expected__xgo_stub_def = `struct {
PkgPath string
Kind int // 0 = func, 1 = var, 2=var_ptr 3 = const
Fn interface{}
PC uintptr // filled later
Var interface{} // pointer to a variable if this is a declare variable
PC uintptr // filled later
Interface bool
Generic bool
Closure bool // is the given function a closure
Expand Down
9 changes: 8 additions & 1 deletion patch/syntax/helper_code.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@

package syntax

const __xgo_local_pkg_name = "" // filled later

type __xgo_local_func_stub struct {
PkgPath string
Kind int // 0 = func, 1 = var, 2=var_ptr 3 = const
Fn interface{}
PC uintptr // filled later
Var interface{} // pointer to a variable if this is a declare variable
PC uintptr // filled later
Interface bool
Generic bool
Closure bool // is the given function a closure
Expand Down Expand Up @@ -46,6 +50,9 @@ func __xgo_link_trap_for_generated(pkgPath string, pc uintptr, identityName stri
// linked by compiler
return nil, false
}
func __xgo_link_trap_var_for_generated(pkgPath string, name string, tmpVarAddr interface{}, takeAddr bool) {
// linked by compiler
}

func __xgo_link_generated_register_func(fn interface{}) {
// linked later by compiler
Expand Down
Loading

0 comments on commit f805071

Please sign in to comment.