116 lines
3.1 KiB
Go
116 lines
3.1 KiB
Go
// Copyright 2020 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package syscall_test
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"syscall"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestEscapeArg(t *testing.T) {
|
|
var tests = []struct {
|
|
input, output string
|
|
}{
|
|
{``, `""`},
|
|
{`a`, `a`},
|
|
{` `, `" "`},
|
|
{`\`, `\`},
|
|
{`"`, `\"`},
|
|
{`\"`, `\\\"`},
|
|
{`\\"`, `\\\\\"`},
|
|
{`\\ `, `"\\ "`},
|
|
{` \\`, `" \\\\"`},
|
|
{`a `, `"a "`},
|
|
{`C:\`, `C:\`},
|
|
{`C:\Program Files (x32)\Common\`, `"C:\Program Files (x32)\Common\\"`},
|
|
{`C:\Users\Игорь\`, `C:\Users\Игорь\`},
|
|
{`Андрей\file`, `Андрей\file`},
|
|
{`C:\Windows\temp`, `C:\Windows\temp`},
|
|
{`c:\temp\newfile`, `c:\temp\newfile`},
|
|
{`\\?\C:\Windows`, `\\?\C:\Windows`},
|
|
{`\\?\`, `\\?\`},
|
|
{`\\.\C:\Windows\`, `\\.\C:\Windows\`},
|
|
{`\\server\share\file`, `\\server\share\file`},
|
|
{`\\newserver\tempshare\really.txt`, `\\newserver\tempshare\really.txt`},
|
|
}
|
|
for _, test := range tests {
|
|
if got := syscall.EscapeArg(test.input); got != test.output {
|
|
t.Errorf("EscapeArg(%#q) = %#q, want %#q", test.input, got, test.output)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestChangingProcessParent(t *testing.T) {
|
|
if os.Getenv("GO_WANT_HELPER_PROCESS") == "parent" {
|
|
// in parent process
|
|
|
|
// Parent does nothing. It is just used as a parent of a child process.
|
|
time.Sleep(time.Minute)
|
|
os.Exit(0)
|
|
}
|
|
|
|
if os.Getenv("GO_WANT_HELPER_PROCESS") == "child" {
|
|
// in child process
|
|
dumpPath := os.Getenv("GO_WANT_HELPER_PROCESS_FILE")
|
|
if dumpPath == "" {
|
|
fmt.Fprintf(os.Stderr, "Dump file path cannot be blank.")
|
|
os.Exit(1)
|
|
}
|
|
err := os.WriteFile(dumpPath, []byte(fmt.Sprintf("%d", os.Getppid())), 0644)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error writing dump file: %v", err)
|
|
os.Exit(2)
|
|
}
|
|
os.Exit(0)
|
|
}
|
|
|
|
// run parent process
|
|
|
|
parent := exec.Command(os.Args[0], "-test.run=TestChangingProcessParent")
|
|
parent.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=parent")
|
|
err := parent.Start()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer func() {
|
|
parent.Process.Kill()
|
|
parent.Wait()
|
|
}()
|
|
|
|
// run child process
|
|
|
|
const _PROCESS_CREATE_PROCESS = 0x0080
|
|
const _PROCESS_DUP_HANDLE = 0x0040
|
|
childDumpPath := filepath.Join(t.TempDir(), "ppid.txt")
|
|
ph, err := syscall.OpenProcess(_PROCESS_CREATE_PROCESS|_PROCESS_DUP_HANDLE|syscall.PROCESS_QUERY_INFORMATION,
|
|
false, uint32(parent.Process.Pid))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer syscall.CloseHandle(ph)
|
|
|
|
child := exec.Command(os.Args[0], "-test.run=TestChangingProcessParent")
|
|
child.Env = append(os.Environ(),
|
|
"GO_WANT_HELPER_PROCESS=child",
|
|
"GO_WANT_HELPER_PROCESS_FILE="+childDumpPath)
|
|
child.SysProcAttr = &syscall.SysProcAttr{ParentProcess: ph}
|
|
childOutput, err := child.CombinedOutput()
|
|
if err != nil {
|
|
t.Errorf("child failed: %v: %v", err, string(childOutput))
|
|
}
|
|
childOutput, err = os.ReadFile(childDumpPath)
|
|
if err != nil {
|
|
t.Fatalf("reading child output failed: %v", err)
|
|
}
|
|
if got, want := string(childOutput), fmt.Sprintf("%d", parent.Process.Pid); got != want {
|
|
t.Fatalf("child output: want %q, got %q", want, got)
|
|
}
|
|
}
|