1 module during.tests.register; 2 3 import during; 4 import during.tests.base; 5 6 import core.stdc.stdlib; 7 import core.sys.linux.errno; 8 import core.sys.linux.fcntl; 9 import core.sys.linux.sys.eventfd; 10 import core.sys.posix.sys.uio : iovec; 11 import core.sys.posix.unistd; 12 13 import std.algorithm : copy, equal, map; 14 import std.range : iota; 15 16 @("buffers") 17 unittest 18 { 19 // prepare uring 20 Uring io; 21 auto res = io.setup(4); 22 assert(res >= 0, "Error initializing IO"); 23 24 void* ptr; 25 26 // single array 27 { 28 ptr = malloc(4096); 29 assert(ptr); 30 scope (exit) free(ptr); 31 32 ubyte[] buffer = (cast(ubyte*)ptr)[0..4096]; 33 auto r = io.registerBuffers(buffer); 34 assert(r == 0); 35 r = io.unregisterBuffers(); 36 assert(r == 0); 37 } 38 39 // multidimensional array 40 { 41 alias BA = ubyte[]; 42 ubyte[][] mbuffer; 43 ptr = malloc(4 * BA.sizeof); 44 assert(ptr); 45 scope (exit) 46 { 47 foreach (i; 0..4) 48 { 49 if (mbuffer[i] !is null) free(&mbuffer[i][0]); 50 } 51 free(&mbuffer[0]); 52 } 53 54 mbuffer = (cast(BA*)ptr)[0..4]; 55 foreach (i; 0..4) 56 { 57 ptr = malloc(4096); 58 assert(ptr); 59 mbuffer[i] = (cast(ubyte*)ptr)[0..4096]; 60 } 61 62 auto r = io.registerBuffers(mbuffer); 63 assert(r == 0); 64 r = io.unregisterBuffers(); 65 assert(r == 0); 66 } 67 } 68 69 @("files") 70 unittest 71 { 72 // prepare uring 73 Uring io; 74 auto res = io.setup(4); 75 assert(res >= 0, "Error initializing IO"); 76 77 // prepare some file 78 auto fname = getTestFileName!"reg_files"; 79 ubyte[256] buf; 80 iota(0, 256).map!(a => cast(ubyte)a).copy(buf[]); 81 auto file = openFile(fname, O_CREAT | O_WRONLY); 82 auto wr = write(file, &buf[0], buf.length); 83 assert(wr == buf.length); 84 close(file); 85 scope (exit) unlink(&fname[0]); 86 87 // register file 88 file = openFile(fname, O_RDONLY); 89 int[] files = (cast(int*)&file)[0..1]; 90 auto ret = io.registerFiles(files); 91 assert(ret == 0); 92 93 // read file 94 iovec v; 95 v.iov_base = cast(void*)&buf[0]; 96 v.iov_len = buf.length; 97 ret = io.putWith!((ref SubmissionEntry e, ref iovec v) 98 { 99 e.prepReadv(0, v, 0); // 0 points to the array of registered fds 100 e.flags = SubmissionEntryFlags.FIXED_FILE; 101 })(v) 102 .submit(1); 103 assert(ret == 1); 104 assert(!io.empty); 105 assert(io.front.res == buf.length); 106 assert(buf[].equal(iota(0, 256))); 107 io.popFront(); 108 109 // close and update reg files (5.5) 110 close(file); 111 files[0] = -1; 112 113 if (checkKernelVersion(5, 5)) 114 { 115 ret = io.registerFilesUpdate(0, files); 116 if (ret == -EINVAL) 117 { 118 version (D_BetterC) 119 { 120 errmsg = "kernel may not support IORING_REGISTER_FILES_UPDATE"; 121 return; 122 } 123 else throw new Exception("kernel may not support IORING_REGISTER_FILES_UPDATE"); 124 } 125 else assert(ret == 0); 126 } 127 128 // unregister files 129 ret = io.unregisterFiles(); 130 assert(ret == 0); 131 } 132 133 @("eventfd") 134 unittest 135 { 136 // prepare uring 137 Uring io; 138 auto res = io.setup(4); 139 assert(res >= 0, "Error initializing IO"); 140 141 // prepare event fd 142 auto evt = eventfd(0, EFD_NONBLOCK); 143 assert(evt != -1, "eventfd()"); 144 145 // register it 146 long ret = io.registerEventFD(evt); 147 assert(ret == 0); 148 149 // check that reading from eventfd would block now 150 ulong evtData; 151 ret = read(evt, &evtData, 8); 152 assert(ret == -1); 153 assert(errno == EAGAIN); 154 155 // post some op to io_uring 156 ret = io.putWith!((ref SubmissionEntry e) => e.prepNop()).submit(1); 157 assert(ret == 1); 158 159 // check that event has triggered 160 ret = read(evt, &evtData, 8); 161 assert(ret == 8); 162 assert(!io.empty); 163 164 // and unregister it 165 ret = io.unregisterEventFD(); 166 assert(ret == 0); 167 }