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 ret = io.registerFilesUpdate(0, files); 113 if (ret == -EINVAL) 114 { 115 version (D_BetterC) 116 { 117 errmsg = "kernel may not support IORING_REGISTER_FILES_UPDATE"; 118 return; 119 } 120 else throw new Exception("kernel may not support IORING_REGISTER_FILES_UPDATE"); 121 } 122 else assert(ret == 0); 123 124 // unregister files 125 ret = io.unregisterFiles(); 126 assert(ret == 0); 127 } 128 129 @("eventfd") 130 unittest 131 { 132 // prepare uring 133 Uring io; 134 auto res = io.setup(4); 135 assert(res >= 0, "Error initializing IO"); 136 137 // prepare event fd 138 auto evt = eventfd(0, EFD_NONBLOCK); 139 assert(evt != -1, "eventfd()"); 140 141 // register it 142 long ret = io.registerEventFD(evt); 143 assert(ret == 0); 144 145 // check that reading from eventfd would block now 146 ulong evtData; 147 ret = read(evt, &evtData, 8); 148 assert(ret == -1); 149 assert(errno == EAGAIN); 150 151 // post some op to io_uring 152 ret = io.putWith!((ref SubmissionEntry e) => e.prepNop()).submit(1); 153 assert(ret == 1); 154 155 // check that event has triggered 156 ret = read(evt, &evtData, 8); 157 assert(ret == 8); 158 assert(!io.empty); 159 160 // and unregister it 161 ret = io.unregisterEventFD(); 162 assert(ret == 0); 163 }