返回 DeepSeek-Reasonix
background_process_gate_test.go
根目录 / desktop / background_process_gate_test.go
1 package main
2
3 import (
4 "go/ast"
5 "go/build"
6 "go/parser"
7 "go/token"
8 "io/fs"
9 "path/filepath"
10 "strconv"
11 "strings"
12 "testing"
13 )
14
15 // TestWindowsDesktopCommandsUseProcConstructors keeps new Windows-capable
16 // desktop code from bypassing internal/proc. Background commands must be
17 // hidden by default; user-visible launches have to opt in with VisibleCommand.
18 func TestWindowsDesktopCommandsUseProcConstructors(t *testing.T) {
19 roots := []string{".", "../internal"}
20 // These packages either are the constructor implementation itself or launch
21 // a real user-facing terminal/application from the CLI/desktop launcher.
22 visibleOrInfrastructure := []string{
23 "../internal/cli/",
24 "../internal/desktoplauncher/",
25 "../internal/notify/",
26 "../internal/proc/",
27 }
28 windowsBuild := build.Default
29 windowsBuild.GOOS = "windows"
30 windowsBuild.GOARCH = "amd64"
31
32 checkRoot := func(root string) error {
33 return filepath.WalkDir(root, func(path string, entry fs.DirEntry, walkErr error) error {
34 if walkErr != nil {
35 return walkErr
36 }
37 cleanPath := filepath.ToSlash(path)
38 for _, prefix := range visibleOrInfrastructure {
39 if strings.HasPrefix(cleanPath, prefix) {
40 if entry.IsDir() {
41 return filepath.SkipDir
42 }
43 return nil
44 }
45 }
46 if entry.IsDir() {
47 name := entry.Name()
48 if name == "third_party" || name == "frontend" || name == "build" || strings.HasPrefix(name, ".") {
49 return filepath.SkipDir
50 }
51 return nil
52 }
53 if !strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "_test.go") {
54 return nil
55 }
56 dir, name := filepath.Split(path)
57 matched, err := windowsBuild.MatchFile(filepath.Clean(dir), name)
58 if err != nil || !matched {
59 return err
60 }
61
62 file, err := parser.ParseFile(token.NewFileSet(), path, nil, 0)
63 if err != nil {
64 return err
65 }
66 execNames := map[string]bool{}
67 for _, imp := range file.Imports {
68 importPath, err := strconv.Unquote(imp.Path.Value)
69 if err != nil || importPath != "os/exec" {
70 continue
71 }
72 name := "exec"
73 if imp.Name != nil {
74 name = imp.Name.Name
75 }
76 execNames[name] = true
77 }
78 ast.Inspect(file, func(node ast.Node) bool {
79 selector, ok := node.(*ast.SelectorExpr)
80 if !ok || (selector.Sel.Name != "Command" && selector.Sel.Name != "CommandContext") {
81 return true
82 }
83 ident, ok := selector.X.(*ast.Ident)
84 if ok && execNames[ident.Name] {
85 t.Errorf("%s bypasses internal/proc with %s.%s", path, ident.Name, selector.Sel.Name)
86 }
87 return true
88 })
89 return nil
90 })
91 }
92 for _, root := range roots {
93 if err := checkRoot(root); err != nil {
94 t.Fatal(err)
95 }
96 }
97 }
98
98 lines GO