Source file
src/syscall/syscall_windows_test.go
1
2
3
4
5 package syscall_test
6
7 import (
8 "fmt"
9 "internal/testenv"
10 "os"
11 "os/exec"
12 "path/filepath"
13 "strings"
14 "syscall"
15 "testing"
16 )
17
18 func TestOpen(t *testing.T) {
19 t.Parallel()
20
21 dir := t.TempDir()
22 file := filepath.Join(dir, "a")
23 f, err := os.Create(file)
24 if err != nil {
25 t.Fatal(err)
26 }
27 f.Close()
28
29 tests := []struct {
30 path string
31 flag int
32 err error
33 }{
34 {dir, syscall.O_RDONLY, nil},
35 {dir, syscall.O_CREAT, nil},
36 {dir, syscall.O_RDONLY | syscall.O_CREAT, nil},
37 {file, syscall.O_APPEND | syscall.O_WRONLY | os.O_CREATE, nil},
38 {file, syscall.O_APPEND | syscall.O_WRONLY | os.O_CREATE | os.O_TRUNC, nil},
39 {dir, syscall.O_RDONLY | syscall.O_TRUNC, syscall.ERROR_ACCESS_DENIED},
40 {dir, syscall.O_WRONLY | syscall.O_RDWR, syscall.EISDIR},
41 {dir, syscall.O_WRONLY, syscall.EISDIR},
42 {dir, syscall.O_RDWR, syscall.EISDIR},
43 }
44 for i, tt := range tests {
45 h, err := syscall.Open(tt.path, tt.flag, 0o660)
46 if err == nil {
47 syscall.CloseHandle(h)
48 }
49 if err != tt.err {
50 t.Errorf("%d: Open got %q, want %q", i, err, tt.err)
51 }
52 }
53 }
54
55 func TestComputerName(t *testing.T) {
56 name, err := syscall.ComputerName()
57 if err != nil {
58 t.Fatalf("ComputerName failed: %v", err)
59 }
60 if len(name) == 0 {
61 t.Error("ComputerName returned empty string")
62 }
63 }
64
65 func TestWin32finddata(t *testing.T) {
66 dir := t.TempDir()
67
68 path := filepath.Join(dir, "long_name.and_extension")
69 f, err := os.Create(path)
70 if err != nil {
71 t.Fatalf("failed to create %v: %v", path, err)
72 }
73 f.Close()
74
75 type X struct {
76 fd syscall.Win32finddata
77 got byte
78 pad [10]byte
79
80 }
81 var want byte = 2
82 x := X{got: want}
83
84 pathp, _ := syscall.UTF16PtrFromString(path)
85 h, err := syscall.FindFirstFile(pathp, &(x.fd))
86 if err != nil {
87 t.Fatalf("FindFirstFile failed: %v", err)
88 }
89 err = syscall.FindClose(h)
90 if err != nil {
91 t.Fatalf("FindClose failed: %v", err)
92 }
93
94 if x.got != want {
95 t.Fatalf("memory corruption: want=%d got=%d", want, x.got)
96 }
97 }
98
99 func abort(funcname string, err error) {
100 panic(funcname + " failed: " + err.Error())
101 }
102
103 func ExampleLoadLibrary() {
104 h, err := syscall.LoadLibrary("kernel32.dll")
105 if err != nil {
106 abort("LoadLibrary", err)
107 }
108 defer syscall.FreeLibrary(h)
109 proc, err := syscall.GetProcAddress(h, "GetVersion")
110 if err != nil {
111 abort("GetProcAddress", err)
112 }
113 r, _, _ := syscall.Syscall(uintptr(proc), 0, 0, 0, 0)
114 major := byte(r)
115 minor := uint8(r >> 8)
116 build := uint16(r >> 16)
117 print("windows version ", major, ".", minor, " (Build ", build, ")\n")
118 }
119
120 func TestTOKEN_ALL_ACCESS(t *testing.T) {
121 if syscall.TOKEN_ALL_ACCESS != 0xF01FF {
122 t.Errorf("TOKEN_ALL_ACCESS = %x, want 0xF01FF", syscall.TOKEN_ALL_ACCESS)
123 }
124 }
125
126 func TestStdioAreInheritable(t *testing.T) {
127 testenv.MustHaveGoBuild(t)
128 testenv.MustHaveCGO(t)
129 testenv.MustHaveExecPath(t, "gcc")
130
131 tmpdir := t.TempDir()
132
133
134 const dlltext = `
135 package main
136
137 import "C"
138 import (
139 "fmt"
140 )
141
142 //export HelloWorld
143 func HelloWorld() {
144 fmt.Println("Hello World")
145 }
146
147 func main() {}
148 `
149 dllsrc := filepath.Join(tmpdir, "helloworld.go")
150 err := os.WriteFile(dllsrc, []byte(dlltext), 0644)
151 if err != nil {
152 t.Fatal(err)
153 }
154 dll := filepath.Join(tmpdir, "helloworld.dll")
155 cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dll, "-buildmode", "c-shared", dllsrc)
156 out, err := testenv.CleanCmdEnv(cmd).CombinedOutput()
157 if err != nil {
158 t.Fatalf("failed to build go library: %s\n%s", err, out)
159 }
160
161
162 const exetext = `
163 #include <stdlib.h>
164 #include <windows.h>
165 int main(int argc, char *argv[])
166 {
167 system("hostname");
168 ((void(*)(void))GetProcAddress(LoadLibraryA(%q), "HelloWorld"))();
169 system("hostname");
170 return 0;
171 }
172 `
173 exe := filepath.Join(tmpdir, "helloworld.exe")
174 cmd = exec.Command("gcc", "-o", exe, "-xc", "-")
175 cmd.Stdin = strings.NewReader(fmt.Sprintf(exetext, dll))
176 out, err = testenv.CleanCmdEnv(cmd).CombinedOutput()
177 if err != nil {
178 t.Fatalf("failed to build c executable: %s\n%s", err, out)
179 }
180 out, err = exec.Command(exe).Output()
181 if err != nil {
182 t.Fatalf("c program execution failed: %v: %v", err, string(out))
183 }
184
185 hostname, err := os.Hostname()
186 if err != nil {
187 t.Fatal(err)
188 }
189
190 have := strings.ReplaceAll(string(out), "\n", "")
191 have = strings.ReplaceAll(have, "\r", "")
192 want := fmt.Sprintf("%sHello World%s", hostname, hostname)
193 if have != want {
194 t.Fatalf("c program output is wrong: got %q, want %q", have, want)
195 }
196 }
197
198 func TestGetwd_DoesNotPanicWhenPathIsLong(t *testing.T) {
199
200 tmp := t.TempDir()
201 t.Chdir(tmp)
202
203
204
205
206 a200 := strings.Repeat("a", 200)
207 dirname := filepath.Join(tmp, a200, a200)
208
209 err := os.MkdirAll(dirname, 0o700)
210 if err != nil {
211 t.Skipf("MkdirAll failed: %v", err)
212 }
213 err = os.Chdir(dirname)
214 if err != nil {
215 t.Skipf("Chdir failed: %v", err)
216 }
217
218 syscall.Getwd()
219 }
220
221 func TestGetStartupInfo(t *testing.T) {
222 var si syscall.StartupInfo
223 err := syscall.GetStartupInfo(&si)
224 if err != nil {
225
226 t.Fatalf("GetStartupInfo: got error %v, want nil", err)
227 }
228 }
229
230 func TestSyscallAllocations(t *testing.T) {
231 testenv.SkipIfOptimizationOff(t)
232
233 t.Parallel()
234
235
236
237
238 h, err := syscall.LoadLibrary("kernel32.dll")
239 if err != nil {
240 t.Fatal(err)
241 }
242 defer syscall.FreeLibrary(h)
243 proc, err := syscall.GetProcAddress(h, "GetVersion")
244 if err != nil {
245 t.Fatal(err)
246 }
247
248 testAllocs := func(t *testing.T, name string, fn func() error) {
249 t.Run(name, func(t *testing.T) {
250 n := int(testing.AllocsPerRun(10, func() {
251 if err := fn(); err != nil {
252 t.Fatalf("%s: %v", name, err)
253 }
254 }))
255 if n > 0 {
256 t.Errorf("allocs = %d, want 0", n)
257 }
258 })
259 }
260
261 testAllocs(t, "SyscallN", func() error {
262 r0, _, e1 := syscall.SyscallN(proc, 0, 0, 0)
263 if r0 == 0 {
264 return syscall.Errno(e1)
265 }
266 return nil
267 })
268 testAllocs(t, "Syscall", func() error {
269 r0, _, e1 := syscall.Syscall(proc, 3, 0, 0, 0)
270 if r0 == 0 {
271 return syscall.Errno(e1)
272 }
273 return nil
274 })
275 }
276
277 func FuzzUTF16FromString(f *testing.F) {
278 f.Add("hi")
279 f.Add("รข")
280 f.Add("ใญใ")
281 f.Add("๐")
282 f.Add("\x90")
283 f.Add("\xe3\x81")
284 f.Add("\xe3\xc1\x81")
285
286 f.Fuzz(func(t *testing.T, tst string) {
287 res, err := syscall.UTF16FromString(tst)
288 if err != nil {
289 if strings.Contains(tst, "\x00") {
290 t.Skipf("input %q contains a NUL byte", tst)
291 }
292 t.Fatalf("UTF16FromString(%q): %v", tst, err)
293 }
294 t.Logf("UTF16FromString(%q) = %04x", tst, res)
295
296 if len(res) < 1 || res[len(res)-1] != 0 {
297 t.Fatalf("missing NUL terminator")
298 }
299 if len(res) > len(tst)+1 {
300 t.Fatalf("len(%04x) > len(%q)+1", res, tst)
301 }
302 })
303 }
304
View as plain text