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 }