1// Copyright 2012 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package syscall_test 6 7import ( 8 "fmt" 9 "internal/testenv" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "strings" 14 "syscall" 15 "testing" 16) 17 18func TestOpen_Dir(t *testing.T) { 19 dir := t.TempDir() 20 21 h, err := syscall.Open(dir, syscall.O_RDONLY, 0) 22 if err != nil { 23 t.Fatalf("Open failed: %v", err) 24 } 25 syscall.CloseHandle(h) 26 h, err = syscall.Open(dir, syscall.O_RDONLY|syscall.O_TRUNC, 0) 27 if err == nil { 28 t.Error("Open should have failed") 29 } else { 30 syscall.CloseHandle(h) 31 } 32 h, err = syscall.Open(dir, syscall.O_RDONLY|syscall.O_CREAT, 0) 33 if err == nil { 34 t.Error("Open should have failed") 35 } else { 36 syscall.CloseHandle(h) 37 } 38} 39 40func TestComputerName(t *testing.T) { 41 name, err := syscall.ComputerName() 42 if err != nil { 43 t.Fatalf("ComputerName failed: %v", err) 44 } 45 if len(name) == 0 { 46 t.Error("ComputerName returned empty string") 47 } 48} 49 50func TestWin32finddata(t *testing.T) { 51 dir := t.TempDir() 52 53 path := filepath.Join(dir, "long_name.and_extension") 54 f, err := os.Create(path) 55 if err != nil { 56 t.Fatalf("failed to create %v: %v", path, err) 57 } 58 f.Close() 59 60 type X struct { 61 fd syscall.Win32finddata 62 got byte 63 pad [10]byte // to protect ourselves 64 65 } 66 var want byte = 2 // it is unlikely to have this character in the filename 67 x := X{got: want} 68 69 pathp, _ := syscall.UTF16PtrFromString(path) 70 h, err := syscall.FindFirstFile(pathp, &(x.fd)) 71 if err != nil { 72 t.Fatalf("FindFirstFile failed: %v", err) 73 } 74 err = syscall.FindClose(h) 75 if err != nil { 76 t.Fatalf("FindClose failed: %v", err) 77 } 78 79 if x.got != want { 80 t.Fatalf("memory corruption: want=%d got=%d", want, x.got) 81 } 82} 83 84func abort(funcname string, err error) { 85 panic(funcname + " failed: " + err.Error()) 86} 87 88func ExampleLoadLibrary() { 89 h, err := syscall.LoadLibrary("kernel32.dll") 90 if err != nil { 91 abort("LoadLibrary", err) 92 } 93 defer syscall.FreeLibrary(h) 94 proc, err := syscall.GetProcAddress(h, "GetVersion") 95 if err != nil { 96 abort("GetProcAddress", err) 97 } 98 r, _, _ := syscall.Syscall(uintptr(proc), 0, 0, 0, 0) 99 major := byte(r) 100 minor := uint8(r >> 8) 101 build := uint16(r >> 16) 102 print("windows version ", major, ".", minor, " (Build ", build, ")\n") 103} 104 105func TestTOKEN_ALL_ACCESS(t *testing.T) { 106 if syscall.TOKEN_ALL_ACCESS != 0xF01FF { 107 t.Errorf("TOKEN_ALL_ACCESS = %x, want 0xF01FF", syscall.TOKEN_ALL_ACCESS) 108 } 109} 110 111func TestStdioAreInheritable(t *testing.T) { 112 testenv.MustHaveGoBuild(t) 113 testenv.MustHaveCGO(t) 114 testenv.MustHaveExecPath(t, "gcc") 115 116 tmpdir := t.TempDir() 117 118 // build go dll 119 const dlltext = ` 120package main 121 122import "C" 123import ( 124 "fmt" 125) 126 127//export HelloWorld 128func HelloWorld() { 129 fmt.Println("Hello World") 130} 131 132func main() {} 133` 134 dllsrc := filepath.Join(tmpdir, "helloworld.go") 135 err := os.WriteFile(dllsrc, []byte(dlltext), 0644) 136 if err != nil { 137 t.Fatal(err) 138 } 139 dll := filepath.Join(tmpdir, "helloworld.dll") 140 cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dll, "-buildmode", "c-shared", dllsrc) 141 out, err := testenv.CleanCmdEnv(cmd).CombinedOutput() 142 if err != nil { 143 t.Fatalf("failed to build go library: %s\n%s", err, out) 144 } 145 146 // build c exe 147 const exetext = ` 148#include <stdlib.h> 149#include <windows.h> 150int main(int argc, char *argv[]) 151{ 152 system("hostname"); 153 ((void(*)(void))GetProcAddress(LoadLibraryA(%q), "HelloWorld"))(); 154 system("hostname"); 155 return 0; 156} 157` 158 exe := filepath.Join(tmpdir, "helloworld.exe") 159 cmd = exec.Command("gcc", "-o", exe, "-xc", "-") 160 cmd.Stdin = strings.NewReader(fmt.Sprintf(exetext, dll)) 161 out, err = testenv.CleanCmdEnv(cmd).CombinedOutput() 162 if err != nil { 163 t.Fatalf("failed to build c executable: %s\n%s", err, out) 164 } 165 out, err = exec.Command(exe).Output() 166 if err != nil { 167 t.Fatalf("c program execution failed: %v: %v", err, string(out)) 168 } 169 170 hostname, err := os.Hostname() 171 if err != nil { 172 t.Fatal(err) 173 } 174 175 have := strings.ReplaceAll(string(out), "\n", "") 176 have = strings.ReplaceAll(have, "\r", "") 177 want := fmt.Sprintf("%sHello World%s", hostname, hostname) 178 if have != want { 179 t.Fatalf("c program output is wrong: got %q, want %q", have, want) 180 } 181} 182 183func TestGetwd_DoesNotPanicWhenPathIsLong(t *testing.T) { 184 // Regression test for https://github.com/golang/go/issues/60051. 185 186 // The length of a filename is also limited, so we can't reproduce the 187 // crash by creating a single directory with a very long name; we need two 188 // layers. 189 a200 := strings.Repeat("a", 200) 190 dirname := filepath.Join(t.TempDir(), a200, a200) 191 192 err := os.MkdirAll(dirname, 0o700) 193 if err != nil { 194 t.Skipf("MkdirAll failed: %v", err) 195 } 196 err = os.Chdir(dirname) 197 if err != nil { 198 t.Skipf("Chdir failed: %v", err) 199 } 200 // Change out of the temporary directory so that we don't inhibit its 201 // removal during test cleanup. 202 defer os.Chdir(`\`) 203 204 syscall.Getwd() 205} 206 207func TestGetStartupInfo(t *testing.T) { 208 var si syscall.StartupInfo 209 err := syscall.GetStartupInfo(&si) 210 if err != nil { 211 // see https://go.dev/issue/31316 212 t.Fatalf("GetStartupInfo: got error %v, want nil", err) 213 } 214} 215 216func FuzzUTF16FromString(f *testing.F) { 217 f.Add("hi") // ASCII 218 f.Add("â") // latin1 219 f.Add("ねこ") // plane 0 220 f.Add("") // extra Plane 0 221 f.Add("\x90") // invalid byte 222 f.Add("\xe3\x81") // truncated 223 f.Add("\xe3\xc1\x81") // invalid middle byte 224 225 f.Fuzz(func(t *testing.T, tst string) { 226 res, err := syscall.UTF16FromString(tst) 227 if err != nil { 228 if strings.Contains(tst, "\x00") { 229 t.Skipf("input %q contains a NUL byte", tst) 230 } 231 t.Fatalf("UTF16FromString(%q): %v", tst, err) 232 } 233 t.Logf("UTF16FromString(%q) = %04x", tst, res) 234 235 if len(res) < 1 || res[len(res)-1] != 0 { 236 t.Fatalf("missing NUL terminator") 237 } 238 if len(res) > len(tst)+1 { 239 t.Fatalf("len(%04x) > len(%q)+1", res, tst) 240 } 241 }) 242} 243