github.com/tristanisham/sys@v0.0.0-20240326010300-a16cbabb7555/unix/epoll_zos_test.go (about) 1 // Copyright 2020 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 5 //go:build zos && s390x 6 7 package unix_test 8 9 // Modified from Linux tests for epoll. 10 11 import ( 12 "os" 13 "testing" 14 15 "golang.org/x/sys/unix" 16 ) 17 18 func TestEpollIn(t *testing.T) { 19 efd, err := unix.EpollCreate1(0) // no CLOEXEC equivalent on z/OS 20 if err != nil { 21 t.Fatalf("EpollCreate1: %v", err) 22 } 23 // no need to defer a close on efd, as it's not a real file descriptor on zos 24 25 r, w, err := os.Pipe() 26 if err != nil { 27 t.Fatal(err) 28 } 29 defer r.Close() 30 defer w.Close() 31 32 fd := int(r.Fd()) 33 ev := unix.EpollEvent{Events: unix.EPOLLIN, Fd: int32(fd)} 34 35 err = unix.EpollCtl(efd, unix.EPOLL_CTL_ADD, fd, &ev) 36 if err != nil { 37 t.Fatalf("EpollCtl: %v", err) 38 } 39 40 if _, err := w.Write([]byte("HELLO GOPHER")); err != nil { 41 t.Fatal(err) 42 } 43 44 events := make([]unix.EpollEvent, 128) 45 n, err := unix.EpollWait(efd, events, 1) 46 if err != nil { 47 t.Fatalf("EpollWait: %v", err) 48 } 49 50 if n != 1 { 51 t.Errorf("EpollWait: wrong number of events: got %v, expected 1", n) 52 } 53 54 got := int(events[0].Fd) 55 if got != fd { 56 t.Errorf("EpollWait: wrong Fd in event: got %v, expected %v", got, fd) 57 } 58 59 if events[0].Events&unix.EPOLLIN == 0 { 60 t.Errorf("Expected EPOLLIN flag to be set, got %b", events[0].Events) 61 } 62 } 63 64 func TestEpollHup(t *testing.T) { 65 efd, err := unix.EpollCreate1(0) 66 if err != nil { 67 t.Fatalf("EpollCreate1: %v", err) 68 } 69 // no need to defer a close on efd, as it's not a real file descriptor on zos 70 71 r, w, err := os.Pipe() 72 if err != nil { 73 t.Fatal(err) 74 } 75 defer r.Close() 76 77 fd := int(r.Fd()) 78 // EPOLLHUP should be reported even if not explicitly requested 79 ev := unix.EpollEvent{Events: unix.EPOLLIN, Fd: int32(fd)} 80 81 err = unix.EpollCtl(efd, unix.EPOLL_CTL_ADD, fd, &ev) 82 if err != nil { 83 t.Fatalf("EpollCtl: %v", err) 84 } 85 86 events := make([]unix.EpollEvent, 128) 87 n, err := unix.EpollWait(efd, events, 1) 88 if err != nil { 89 t.Fatalf("EpollWait: %v", err) 90 } 91 92 if events[0].Events&unix.EPOLLHUP != 0 { 93 t.Errorf("EPOLLHUP flag aset without hangup event; got n=%d, flags=%b", n, events[0].Events) 94 } 95 96 w.Close() 97 98 events = make([]unix.EpollEvent, 128) 99 n, err = unix.EpollWait(efd, events, 1) 100 if err != nil { 101 t.Fatalf("EpollWait: %v", err) 102 } 103 104 if n < 1 || events[0].Events&unix.EPOLLHUP == 0 { 105 t.Errorf("Expected EPOLLHUP flag to be set, got n=%d, flags=%b", n, events[0].Events) 106 } 107 108 } 109 110 func TestEpollInManyFds(t *testing.T) { 111 efd, err := unix.EpollCreate1(4) // Like on Linux, size arg is ignored. 112 if err != nil { 113 t.Fatalf("EpollCreate: %v", err) 114 } 115 // no need to defer a close on efd, as it's not a real file descriptor on zos 116 117 rFds := make([]int, 10) 118 wPipes := make([]*os.File, 10) 119 120 for i := 0; i < 10; i++ { 121 r, w, err := os.Pipe() 122 if err != nil { 123 t.Fatal(err) 124 } 125 defer r.Close() 126 defer w.Close() 127 128 rFds[i] = int(r.Fd()) 129 wPipes[i] = w 130 } 131 132 // Monitor all 10 read pipes 133 for _, fd := range rFds { 134 ev := unix.EpollEvent{Events: unix.EPOLLIN, Fd: int32(fd)} 135 err = unix.EpollCtl(efd, unix.EPOLL_CTL_ADD, fd, &ev) 136 if err != nil { 137 t.Fatalf("EpollCtl: %v", err) 138 } 139 } 140 141 // Write to only 5 odd-numbered pipes 142 for i, w := range wPipes { 143 if i%2 == 0 { 144 continue 145 } 146 if _, err := w.Write([]byte("HELLO")); err != nil { 147 t.Fatal(err) 148 } 149 } 150 151 events := make([]unix.EpollEvent, 128) 152 n, err := unix.EpollWait(efd, events, 1) 153 if err != nil { 154 t.Fatalf("EpollWait: %v", err) 155 } 156 157 if n != 5 { 158 t.Errorf("EpollWait: wrong number of events: got %v, expected 5", n) 159 } 160 161 // Check level triggering here 162 if _, err := wPipes[0].Write([]byte("HELLO")); err != nil { 163 t.Fatal(err) 164 } 165 166 // Now, a total of 6 pipes have been written to - level triggered notifis should number 6 167 events = make([]unix.EpollEvent, 128) 168 n, err = unix.EpollWait(efd, events, 1) 169 if err != nil { 170 t.Fatalf("EpollWait: %v", err) 171 } 172 173 if n != 6 { 174 t.Errorf("EpollWait: wrong number of events: got %v, expected 6", n) 175 } 176 177 } 178 179 func TestMultipleEpolls(t *testing.T) { 180 efd1, err := unix.EpollCreate1(4) 181 if err != nil { 182 t.Fatalf("EpollCreate: %v", err) 183 } 184 // no need to defer a close on efd1, as it's not a real file descriptor on zos 185 186 efd2, err := unix.EpollCreate1(4) 187 if err != nil { 188 t.Fatalf("EpollCreate: %v", err) 189 } 190 // no need to defer a close on efd2, as it's not a real file descriptor on zos 191 192 rFds := make([]int, 10) 193 wPipes := make([]*os.File, 10) 194 195 for i := 0; i < 10; i++ { 196 r, w, err := os.Pipe() 197 if err != nil { 198 t.Fatal(err) 199 } 200 defer r.Close() 201 defer w.Close() 202 203 rFds[i] = int(r.Fd()) 204 wPipes[i] = w 205 } 206 207 // Monitor first 7 read pipes on epoll1, last 3 on epoll2 208 for i, fd := range rFds { 209 var efd int 210 if i < 7 { 211 efd = efd1 212 } else { 213 efd = efd2 214 } 215 ev := unix.EpollEvent{Events: unix.EPOLLIN, Fd: int32(fd)} 216 err = unix.EpollCtl(efd, unix.EPOLL_CTL_ADD, fd, &ev) 217 if err != nil { 218 t.Fatalf("EpollCtl: %v", err) 219 } 220 } 221 222 // Write to all 10 pipes 223 for _, w := range wPipes { 224 if _, err := w.Write([]byte("HELLO")); err != nil { 225 t.Fatal(err) 226 } 227 } 228 229 events := make([]unix.EpollEvent, 128) 230 n, err := unix.EpollWait(efd1, events, 1) 231 if err != nil { 232 t.Fatalf("EpollWait: %v", err) 233 } 234 if n != 7 { 235 t.Errorf("EpollWait: wrong number of events on ep1: got %v, expected 7", n) 236 } 237 238 events = make([]unix.EpollEvent, 128) 239 n, err = unix.EpollWait(efd2, events, 1) 240 if err != nil { 241 t.Fatalf("EpollWait: %v", err) 242 } 243 if n != 3 { 244 t.Errorf("EpollWait: wrong number of events on ep2: got %v, expected 3", n) 245 } 246 } 247 248 func TestEpollErrors(t *testing.T) { 249 efd, err := unix.EpollCreate1(4) 250 if err != nil { 251 t.Fatalf("EpollCreate: %v", err) 252 } 253 // no need to defer a close on efd, as it's not a real file descriptor on zos 254 255 r, w, err := os.Pipe() 256 if err != nil { 257 t.Fatal(err) 258 } 259 defer r.Close() 260 defer w.Close() 261 262 fd := int(r.Fd()) 263 264 ev := unix.EpollEvent{Events: unix.EPOLLIN, Fd: int32(fd)} 265 if err = unix.EpollCtl(efd+1, unix.EPOLL_CTL_ADD, fd, &ev); err != unix.EBADF { 266 t.Errorf("EpollCtl: got %v when EpollCtl ADD called with invalid epfd, expected EBADF", err) 267 } 268 269 if err = unix.EpollCtl(efd, unix.EPOLL_CTL_ADD, fd, &ev); err != nil { 270 t.Fatalf("EpollCtl: %v", err) 271 } 272 273 if err = unix.EpollCtl(efd, unix.EPOLL_CTL_MOD, -2, &ev); err != unix.ENOENT { 274 t.Errorf("EpollCtl: got %v when EpollCtl MOD called with invalid fd, expected ENOENT", err) 275 } 276 }