1 module during.tests.api; 2 3 import during; 4 5 version (D_Exceptions) import std.exception : assertThrown; 6 import std.range; 7 8 @("Submission variants") 9 unittest 10 { 11 Uring io; 12 auto res = io.setup(); 13 assert(res >= 0, "Error initializing IO"); 14 15 SubmissionEntry entry; 16 entry.opcode = Operation.NOP; 17 entry.user_data = 1; 18 19 struct MyOp 20 { 21 Operation opcode = Operation.NOP; 22 ulong user_data; 23 } 24 25 // chain operations 26 io 27 .put(entry) 28 .put(MyOp(Operation.NOP, 2)) 29 .putWith!((ref SubmissionEntry e) { e.prepNop(); e.user_data = 42; }) 30 .submit(1); // submit operations and wait for at least 1 completed 31 32 // check completions 33 assert(!io.empty); 34 assert(io.front.user_data == 1); 35 io.popFront(); 36 io.wait(2); 37 assert(io.front.user_data == 2); 38 io.popFront(); 39 assert(!io.empty); 40 assert(io.front.user_data == 42); 41 io.popFront(); 42 assert(io.empty); 43 } 44 45 @("Limits") 46 unittest 47 { 48 struct Nop { Operation opcode = Operation.NOP; } 49 50 Uring io; 51 auto res = io.setup(16); 52 assert(res >= 0, "Error initializing IO"); 53 assert(io.empty); 54 assert(!io.length); 55 assert(!io.full); 56 assert(io.capacity == 16); 57 assert(io.params.sq_entries == 16); 58 assert(io.params.cq_entries == 32); 59 60 // fill submission queue 61 foreach (_; 0..16) io.put(Nop()); 62 assert(io.capacity == 0); 63 assert(io.full); 64 assert(io.empty); 65 assert(!io.length); 66 assert(!io.overflow); 67 assert(!io.dropped); 68 version(D_Exceptions) assertThrown!Throwable(io.put(Nop())); 69 70 io.submit(0); // submit them all 71 assert(io.capacity == 16); 72 assert(!io.full); 73 assert(!io.dropped); 74 75 io.wait(10); 76 assert(io.capacity == 16); 77 assert(!io.full); 78 assert(!io.dropped); 79 assert(!io.empty); 80 assert(io.length == 16); 81 assert(!io.overflow); 82 io.popFront(); 83 assert(io.length == 15); 84 85 // fill up completion queue 86 foreach (_; 0..16) io.put(Nop()); 87 io.submit(16); // submit them and wait for all 88 assert(io.length == 31); 89 assert(!io.overflow); // still no overflow 90 91 // cause overflow 92 foreach (_; 0..2) io.put(Nop()); 93 io.submit(2); 94 assert(io.length == 32); 95 assert(io.overflow == 1); // oops 96 97 io.drop(32); 98 assert(io.empty); 99 assert(io.length == 0); 100 101 // put there another batch 102 foreach (_; 0..16) io.put(Nop()); 103 io.submit(0); 104 io.wait(16); 105 assert(io.length == 16); 106 assert(io.overflow == 1); 107 } 108 109 @("Range interface") 110 unittest 111 { 112 import std.algorithm : copy, equal, map; 113 114 Uring io; 115 auto res = io.setup(16); 116 assert(res >= 0, "Error initializing IO"); 117 118 struct MyOp { Operation opcode; ulong user_data; } 119 static assert(isOutputRange!(Uring, MyOp)); 120 121 // add 32 entries (in 2 batches as we have capacity only for 16 entries) 122 iota(0, 16).map!(a => MyOp(Operation.NOP, a)).copy(io); 123 assert(io.capacity == 0); 124 assert(io.full); 125 res = io.submit(0); // just submit 126 assert(res == 16); 127 iota(16, 32).map!(a => MyOp(Operation.NOP, a)).copy(io); 128 res = io.submit(32); // submit and wait 129 assert(res == 16); 130 assert(!io.empty); 131 assert(io.length == 32); 132 assert(io.map!(c => c.user_data).equal(iota(0, 32))); 133 }