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 }