diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 22077c70..50bec03a 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -16,11 +16,19 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Prepare typo config + run: | + # Don't correct the word "Incrimental" + echo -ne '[files]\nextend-exclude = ["**/vendir/**/*"]\n[default.extend-words]\nIncrimental = "Incrimental"\n' > /tmp/typo-config.toml + cat /tmp/typo-config.toml + - name: Check spelling of files uses: crate-ci/typos@master continue-on-error: false with: files: ./ + config: /tmp/typo-config.toml + isolated: true - name: Set up Go1.17 uses: actions/setup-go@v4 diff --git a/cmd/xgo/exec_tool/debug.go b/cmd/xgo/exec_tool/debug.go index d506a006..3de50e64 100644 --- a/cmd/xgo/exec_tool/debug.go +++ b/cmd/xgo/exec_tool/debug.go @@ -50,6 +50,7 @@ func getDebugEnvList(xgoCompilerEnableEnv string) [][2]string { // strace {XGO_STACK_TRACE, os.Getenv(XGO_STACK_TRACE)}, {XGO_STACK_TRACE_DIR, os.Getenv(XGO_STACK_TRACE_DIR)}, + {XGO_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT, os.Getenv(XGO_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT)}, {XGO_STD_LIB_TRAP_DEFAULT_ALLOW, os.Getenv(XGO_STD_LIB_TRAP_DEFAULT_ALLOW)}, {XGO_DEBUG_COMPILE_PKG, os.Getenv(XGO_DEBUG_COMPILE_PKG)}, diff --git a/cmd/xgo/exec_tool/env.go b/cmd/xgo/exec_tool/env.go index 68d7e207..f940987c 100644 --- a/cmd/xgo/exec_tool/env.go +++ b/cmd/xgo/exec_tool/env.go @@ -20,6 +20,9 @@ const XGO_STACK_TRACE = "XGO_STACK_TRACE" // --strace-dir const XGO_STACK_TRACE_DIR = "XGO_STACK_TRACE_DIR" +// --strace-snapshot-main-module-default +const XGO_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT = "XGO_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT" + const XGO_COMPILE_PKG_DATA_DIR = "XGO_COMPILE_PKG_DATA_DIR" const XGO_STD_LIB_TRAP_DEFAULT_ALLOW = "XGO_STD_LIB_TRAP_DEFAULT_ALLOW" diff --git a/cmd/xgo/main.go b/cmd/xgo/main.go index 6b56d25d..76a41fab 100644 --- a/cmd/xgo/main.go +++ b/cmd/xgo/main.go @@ -168,6 +168,7 @@ func handleBuild(cmd string, args []string) error { dumpAST := opts.dumpAST stackTrace := opts.stackTrace stackTraceDir := opts.stackTraceDir + straceSnapshotMainModuleDefault := opts.straceSnapshotMainModuleDefault trapStdlib := opts.trapStdlib if cmdExec && len(remainArgs) == 0 { @@ -293,7 +294,9 @@ func handleBuild(cmd string, args []string) error { h.Write(optionsFromFileContent) buildCacheSuffix += "-" + hex.EncodeToString(h.Sum(nil)) } + var enableStackTrace bool if stackTrace == "on" || stackTrace == "true" { + enableStackTrace = true v := stackTrace if v == "true" { v = "on" @@ -660,6 +663,9 @@ func handleBuild(cmd string, args []string) error { if stackTraceDir != "" { execCmd.Env = append(execCmd.Env, exec_tool.XGO_STACK_TRACE_DIR+"="+stackTraceDir) } + if enableStackTrace && straceSnapshotMainModuleDefault != "" { + execCmd.Env = append(execCmd.Env, exec_tool.XGO_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT+"="+straceSnapshotMainModuleDefault) + } // trap stdlib var trapStdlibEnv string diff --git a/cmd/xgo/option.go b/cmd/xgo/option.go index fb588382..64af194f 100644 --- a/cmd/xgo/option.go +++ b/cmd/xgo/option.go @@ -77,6 +77,8 @@ type options struct { stackTrace string // --strace-dir stackTraceDir string + // --strace-snapshot-main-module-default + straceSnapshotMainModuleDefault string remainArgs []string @@ -129,6 +131,7 @@ func parseOptions(cmd string, args []string) (*options, error) { var modfile string var stackTrace string var stackTraceDir string + var straceSnapshotMainModuleDefault string var trapStdlib bool var remainArgs []string @@ -358,6 +361,11 @@ func parseOptions(cmd string, args []string) (*options, error) { stackTrace = argVal continue } + stackTraceMainModuleDefaultFlag, val := flag.TrySingleFlag([]string{"--strace-snapshot-main-module-default"}, arg) + if stackTraceMainModuleDefaultFlag != "" { + straceSnapshotMainModuleDefault = val + continue + } // supported flag: --trap-stdlib, --trap-stdlib=false, --trap-stdlib=true trapStdlibFlag, trapStdlibVal := flag.TrySingleFlag([]string{"--trap-stdlib"}, arg) @@ -458,13 +466,14 @@ func parseOptions(cmd string, args []string) (*options, error) { // default true syncWithLink: syncWithLink == nil || *syncWithLink, - mod: mod, - gcflags: gcflags, - overlay: overlay, - modfile: modfile, - stackTrace: stackTrace, - stackTraceDir: stackTraceDir, - trapStdlib: trapStdlib, + mod: mod, + gcflags: gcflags, + overlay: overlay, + modfile: modfile, + stackTrace: stackTrace, + stackTraceDir: stackTraceDir, + straceSnapshotMainModuleDefault: straceSnapshotMainModuleDefault, + trapStdlib: trapStdlib, remainArgs: remainArgs, testArgs: testArgs, diff --git a/cmd/xgo/runtime_gen/trace/trace.go b/cmd/xgo/runtime_gen/trace/trace.go index 1dfd9baa..3a84041a 100755 --- a/cmd/xgo/runtime_gen/trace/trace.go +++ b/cmd/xgo/runtime_gen/trace/trace.go @@ -5,7 +5,9 @@ import ( "fmt" "os" "path/filepath" + "runtime/debug" "strconv" + "strings" "sync" "testing" "time" @@ -27,7 +29,18 @@ type testInfo struct { onFinish func() } +var effectMainModule string + func init() { + if flags.MAIN_MODULE != "" { + // fmt.Fprintf(os.Stderr, "DEBUG main module from flags: %s\n", flags.MAIN_MODULE) + effectMainModule = flags.MAIN_MODULE + } else { + buildInfo, _ := debug.ReadBuildInfo() + if buildInfo != nil { + effectMainModule = buildInfo.Main.Path + } + } __xgo_link_on_test_start(func(t *testing.T, fn func(t *testing.T)) { name := t.Name() if name == "" { @@ -268,6 +281,15 @@ func handleTracePre(ctx context.Context, f *core.FuncInfo, args core.Object, res break } } + + // check if allow main module to be defaultly snapshoted + if !anySnapshot && flags.STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT != "false" && effectMainModule != "" && strings.HasPrefix(f.Pkg, effectMainModule) { + // main_module or main_module/* + if len(f.Pkg) == len(effectMainModule) || f.Pkg[len(effectMainModule)] == '/' { + // fmt.Fprintf(os.Stderr, "DEBUG main module snapshot: %s of %s\n", f.Pkg, effectMainModule) + anySnapshot = true + } + } if anySnapshot { stack.Snapshot = true stack.Args = premarshal(stack.Args) diff --git a/cmd/xgo/runtime_gen/trap/flags/flags.go b/cmd/xgo/runtime_gen/trap/flags/flags.go index b3aaf24e..b8bf1127 100755 --- a/cmd/xgo/runtime_gen/trap/flags/flags.go +++ b/cmd/xgo/runtime_gen/trap/flags/flags.go @@ -1,5 +1,17 @@ package flags +// to inject these flags, see patch/syntax/syntax.go, search for flag_MAIN_MODULE +// this package exists to make flags passed to xgo to be persisted in building and running. + +// flag: none +// env: XGO_MAIN_MODULE +// description: +// +// auto detected by xgo in the beginning of building. +// can be used prior to ask runtime/debug's info: +// var mainModulePath = runtime/debug.ReadBuildInfo().Main.Path +const MAIN_MODULE = "" + // flag: --strace // env: XGO_STACK_TRACE // description: @@ -21,6 +33,21 @@ const STRACE = "" // directory, default current dir const STRACE_DIR = "" +// flag: --strace-snapshot-main-module +// env: XGO_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT +// description: +// +// collecting main module's trace in snapshot mode, +// while other's are non snapshot mode +// +// snapshot mode: args are serialized before executing +// the function, and results are serilaized after return. +// this is useful if an object will be modified in later +// process. +// +// values: true or false +const STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT = "" + // flag: --trap-stdlib // env: XGO_STD_LIB_TRAP_DEFAULT_ALLOW // description: if true, stdlib trap is by default allowed diff --git a/cmd/xgo/trace.go b/cmd/xgo/trace.go index 2d857f9a..ffd2b15e 100644 --- a/cmd/xgo/trace.go +++ b/cmd/xgo/trace.go @@ -29,6 +29,10 @@ type importResult struct { var runtimeGenFS embed.FS // TODO: may apply tags +// importRuntimeDep detect if the target package already +// has github.com/xhd2015/xgo/runtime as dependency, +// if not, dynamically modify the go.mod to include that, +// and add a blank import in the main package func importRuntimeDep(test bool, goroot string, goBinary string, goVersion *goinfo.GoVersion, absModFile string, xgoSrc string, projectDir string, modRootRel []string, mainModule string, mod string, args []string) (*importResult, error) { if mainModule == "" { // only work with module @@ -64,7 +68,6 @@ func importRuntimeDep(test bool, goroot string, goBinary string, goVersion *goin return nil, err } - pkgArgs := getPkgArgs(args) tmpRoot, tmpProjectDir, err := createWorkDir(projectRoot) if err != nil { return nil, err @@ -84,6 +87,7 @@ func importRuntimeDep(test bool, goroot string, goBinary string, goVersion *goin } } + pkgArgs := getPkgArgs(args) fileReplace, err := addBlankImports(goroot, goBinary, projectDir, pkgArgs, test, tmpProjectDir) if err != nil { return nil, err @@ -171,8 +175,10 @@ type Overlay struct { type dependencyInfo struct { modReplace map[string]string - mod string - modfile string // alternative go.mod + // the -mod flag + mod string + // the -modfile flag + modfile string // alternative go.mod } func createWorkDir(projectRoot string) (tmpRoot string, tmpProjectDir string, err error) { diff --git a/cmd/xgo/version.go b/cmd/xgo/version.go index 3e528af0..c7653b52 100644 --- a/cmd/xgo/version.go +++ b/cmd/xgo/version.go @@ -6,8 +6,8 @@ import "fmt" // VERSION is manually updated when needed a new tag // see also runtime/core/version.go const VERSION = "1.0.51" -const REVISION = "f43d1801162be8396dd5b73a27b529253a121a88+1" -const NUMBER = 319 +const REVISION = "38209d904dbe681a458641ad5e7f1c408c8a3626+1" +const NUMBER = 320 // the matching runtime/core's version // manually updated diff --git a/doc/test-explorer/README.md b/doc/test-explorer/README.md index f6151287..88089d5f 100644 --- a/doc/test-explorer/README.md +++ b/doc/test-explorer/README.md @@ -20,7 +20,7 @@ An example config: "env":{ "TEST_WITH_XGO":"true" }, - "flags":["-p=12"], + "flags":["-p=4"], "args":["--my-program-env","TEST"], "mock_rules":[{ "stdlib": true, @@ -149,10 +149,17 @@ Definition: Definition: ```json { - "disabled": true + "disabled": true|false, + "diff_with": "origin/master", + "include": [...], + "exclude": [...] } ``` By default, if `coverage` is missing or `null`, then coverage is enabled. +If set `diff_with` to `none`, then incremental coverage will be disabled. + +`include` and `exclude` specify which files will be included or excluded in coverage display. + Setting `"coverage": false` or `"coverage":{"disabled": true}` will disable it. \ No newline at end of file diff --git a/patch/syntax/syntax.go b/patch/syntax/syntax.go index 0ad01b2b..e23b021a 100644 --- a/patch/syntax/syntax.go +++ b/patch/syntax/syntax.go @@ -30,9 +30,12 @@ const XGO_VERSION = "XGO_VERSION" const XGO_REVISION = "XGO_REVISION" const XGO_NUMBER = "XGO_NUMBER" +const XGO_MAIN_MODULE = "XGO_MAIN_MODULE" + // --strace const XGO_STACK_TRACE = "XGO_STACK_TRACE" const XGO_STACK_TRACE_DIR = "XGO_STACK_TRACE_DIR" +const XGO_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT = "XGO_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT" const XGO_STD_LIB_TRAP_DEFAULT_ALLOW = "XGO_STD_LIB_TRAP_DEFAULT_ALLOW" // Deprecated: use flag_STRACE,.. instead @@ -40,10 +43,14 @@ const straceFlagConstName = "__xgo_injected_StraceFlag" const trapStdlibFlagConstName = "__xgo_injected_StdlibTrapDefaultAllow" const ( + // auto detected + flag_MAIN_MODULE = "MAIN_MODULE" // --strace flag_STRACE = "STRACE" // --strace-dir flag_STRACE_DIR = "STRACE_DIR" + // --strace-snapshot-main-module + flag_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT = "STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT" // --trap-stdlib flag_TRAP_STDLIB = "TRAP_STDLIB" ) @@ -454,10 +461,14 @@ func injectXgoGeneralFlags(fileList []*syntax.File) { forEachConst(file.DeclList, func(constDecl *syntax.ConstDecl) bool { for _, name := range constDecl.NameList { switch name.Value { + case flag_MAIN_MODULE: + constDecl.Values = newStringLit(os.Getenv(XGO_MAIN_MODULE)) case flag_STRACE: constDecl.Values = newStringLit(os.Getenv(XGO_STACK_TRACE)) case flag_STRACE_DIR: constDecl.Values = newStringLit(os.Getenv(XGO_STACK_TRACE_DIR)) + case flag_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT: + constDecl.Values = newStringLit(os.Getenv(XGO_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT)) case flag_TRAP_STDLIB: constDecl.Values = newStringLit(os.Getenv(XGO_STD_LIB_TRAP_DEFAULT_ALLOW)) } diff --git a/runtime/test/stack_trace/snapshot_main_default/trace_snapshot_main_default_test.go b/runtime/test/stack_trace/snapshot_main_default/trace_snapshot_main_default_test.go new file mode 100644 index 00000000..c53055cf --- /dev/null +++ b/runtime/test/stack_trace/snapshot_main_default/trace_snapshot_main_default_test.go @@ -0,0 +1,9 @@ +package snapshot_main_default + +import "testing" + +func TestSnapshotMainDefault(t *testing.T) { + // TODO: I forgot how to write test against trace + // see https://github.com/xhd2015/xgo/issues/281#issuecomment-2466153734 + // for test detail +} diff --git a/runtime/test/trace/snapshot/snapshot_test.go b/runtime/test/trace/snapshot/snapshot_test.go index bbd4191b..ec01c68e 100644 --- a/runtime/test/trace/snapshot/snapshot_test.go +++ b/runtime/test/trace/snapshot/snapshot_test.go @@ -13,6 +13,12 @@ import ( // NOTE: do not run with -cover, because // extra function will be included in trace +// TODO: this test currently fails, but +// it is not so urgent to fix it, so +// I'll keep it here. +// once I got enough time to do, I'll +// try my best. +// see related https://github.com/xhd2015/xgo/issues/281 func TestNoSnapshot(t *testing.T) { test(t, noSnapshotExpect, nil) } diff --git a/runtime/trace/trace.go b/runtime/trace/trace.go index 1dfd9baa..3a84041a 100644 --- a/runtime/trace/trace.go +++ b/runtime/trace/trace.go @@ -5,7 +5,9 @@ import ( "fmt" "os" "path/filepath" + "runtime/debug" "strconv" + "strings" "sync" "testing" "time" @@ -27,7 +29,18 @@ type testInfo struct { onFinish func() } +var effectMainModule string + func init() { + if flags.MAIN_MODULE != "" { + // fmt.Fprintf(os.Stderr, "DEBUG main module from flags: %s\n", flags.MAIN_MODULE) + effectMainModule = flags.MAIN_MODULE + } else { + buildInfo, _ := debug.ReadBuildInfo() + if buildInfo != nil { + effectMainModule = buildInfo.Main.Path + } + } __xgo_link_on_test_start(func(t *testing.T, fn func(t *testing.T)) { name := t.Name() if name == "" { @@ -268,6 +281,15 @@ func handleTracePre(ctx context.Context, f *core.FuncInfo, args core.Object, res break } } + + // check if allow main module to be defaultly snapshoted + if !anySnapshot && flags.STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT != "false" && effectMainModule != "" && strings.HasPrefix(f.Pkg, effectMainModule) { + // main_module or main_module/* + if len(f.Pkg) == len(effectMainModule) || f.Pkg[len(effectMainModule)] == '/' { + // fmt.Fprintf(os.Stderr, "DEBUG main module snapshot: %s of %s\n", f.Pkg, effectMainModule) + anySnapshot = true + } + } if anySnapshot { stack.Snapshot = true stack.Args = premarshal(stack.Args) diff --git a/runtime/trap/flags/flags.go b/runtime/trap/flags/flags.go index b3aaf24e..b8bf1127 100644 --- a/runtime/trap/flags/flags.go +++ b/runtime/trap/flags/flags.go @@ -1,5 +1,17 @@ package flags +// to inject these flags, see patch/syntax/syntax.go, search for flag_MAIN_MODULE +// this package exists to make flags passed to xgo to be persisted in building and running. + +// flag: none +// env: XGO_MAIN_MODULE +// description: +// +// auto detected by xgo in the beginning of building. +// can be used prior to ask runtime/debug's info: +// var mainModulePath = runtime/debug.ReadBuildInfo().Main.Path +const MAIN_MODULE = "" + // flag: --strace // env: XGO_STACK_TRACE // description: @@ -21,6 +33,21 @@ const STRACE = "" // directory, default current dir const STRACE_DIR = "" +// flag: --strace-snapshot-main-module +// env: XGO_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT +// description: +// +// collecting main module's trace in snapshot mode, +// while other's are non snapshot mode +// +// snapshot mode: args are serialized before executing +// the function, and results are serilaized after return. +// this is useful if an object will be modified in later +// process. +// +// values: true or false +const STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT = "" + // flag: --trap-stdlib // env: XGO_STD_LIB_TRAP_DEFAULT_ALLOW // description: if true, stdlib trap is by default allowed diff --git a/script/run-test/main.go b/script/run-test/main.go index 4df10149..b0c6be41 100644 --- a/script/run-test/main.go +++ b/script/run-test/main.go @@ -9,6 +9,7 @@ import ( "strings" "time" + "github.com/xhd2015/xgo/cmd/xgo/exec_tool" "github.com/xhd2015/xgo/support/cmd" ) @@ -149,6 +150,9 @@ var extraSubTests = []*TestCase{ name: "trace-snapshot", dir: "runtime/test/trace/snapshot", skipOnCover: true, + // TODO: let program configure it + env: []string{exec_tool.XGO_STRACE_SNAPSHOT_MAIN_MODULE_DEFAULT + "=false"}, + // flags: []string{"--strace-snapshot-main-module-default=false"}, }, { name: "trace-custom-dir",