| // 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) | 
 | 	} | 
 | } |