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