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