1 module auxil.cursor_accumulator_test; 2 3 import std; 4 5 version(unittest) 6 import unit_threaded; 7 8 import auxil.cursor_accumulator; 9 import auxil.cursor_test : sequence, LogRecord; 10 11 version(unittest) 12 @Name("testForward") 13 unittest 14 { 15 import auxil.cursor : Cursor; 16 17 const order = Cursor.Order.forward; 18 LogRecord[] posLog; 19 CursorAccumulator ca; 20 21 ca.start; 22 23 auto seq = sequence.dup; 24 foreach(e; seq) 25 { 26 ca.begin(e); 27 posLog ~= LogRecord(ca.position!order, e); 28 ca.end(e); 29 } 30 31 posLog.should.be == [ 32 LogRecord(0, 10), 33 LogRecord(10, 21), 34 LogRecord(31, 12), 35 LogRecord(43, 13), 36 LogRecord(56, 24), 37 LogRecord(80, 15), 38 LogRecord(95, 16), 39 LogRecord(111, 17), 40 ]; 41 42 // after traversing and before commit 43 // fixedPosition equals to calcPosition result 44 // and is the position of the next element after 45 // the last one 46 ca.csr.fixedPosition.should.be == 128; 47 ca.csr.calcPosition!order.should.be == 128; 48 ca.position!order.should.be == 128; 49 50 // we call it if we want to scroll further 51 // so we need to store the current position 52 ca.commit!order; 53 54 posLog.should.be == [ 55 LogRecord(0, 10), 56 LogRecord(10, 21), 57 LogRecord(31, 12), 58 LogRecord(43, 13), 59 LogRecord(56, 24), 60 LogRecord(80, 15), 61 LogRecord(95, 16), 62 LogRecord(111, 17), 63 ]; 64 65 // after commit fixedPosition is reset 66 // and the current position returned by calcPosition 67 // equals to the position of the last element 68 // (not the next element after the last one) 69 ca.csr.fixedPosition.should.be == 0; 70 ca.csr.calcPosition!order.should.be == 111; 71 ca.position!order.should.be == 111; 72 } 73 74 version(unittest) 75 @Name("testBackward") 76 unittest 77 { 78 import auxil.cursor : Cursor; 79 80 const order = Cursor.Order.backward; 81 LogRecord[] posLog; 82 auto seq = sequence.dup.retro; 83 CursorAccumulator ca; 84 85 ca.start(sum(seq)); 86 foreach(e; seq) 87 { 88 ca.begin(e); 89 posLog ~= LogRecord(ca.position!order, e); 90 ca.end(e); 91 } 92 93 posLog.should.be == [ 94 LogRecord(111, 17), 95 LogRecord( 95, 16), 96 LogRecord( 80, 15), 97 LogRecord( 56, 24), 98 LogRecord( 43, 13), 99 LogRecord( 31, 12), 100 LogRecord( 10, 21), 101 LogRecord( 0, 10) 102 ]; 103 104 ca.csr.fixedPosition.should.be == 128; 105 ca.csr.calcPosition!order.should.be == -10; 106 ca.position!order.should.be == -10; 107 108 // we call it if we want to scroll further 109 // so we need to store the current position 110 ca.commit!order; 111 112 posLog.should.be == [ 113 LogRecord(111, 17), 114 LogRecord( 95, 16), 115 LogRecord( 80, 15), 116 LogRecord( 56, 24), 117 LogRecord( 43, 13), 118 LogRecord( 31, 12), 119 LogRecord( 10, 21), 120 LogRecord( 0, 10) 121 ]; 122 123 // after commit fixedPosition is reset 124 // and the current position returned by calcPosition 125 // equals to the position of the last element 126 // (not the next element after the last one) 127 ca.csr.fixedPosition.should.be == 0; 128 ca.csr.calcPosition!order.should.be == -10; 129 ca.position!order.should.be == -10; 130 } 131 132 version(unittest) 133 @Name("testTraversingForward") 134 unittest 135 { 136 import auxil.cursor : Cursor; 137 138 const order = Cursor.Order.forward; 139 LogRecord[] posLog; 140 auto seq = sequence.dup; 141 CursorAccumulator ca; 142 143 // start traversing 144 ca.start; 145 146 // step #1 - scroll 3 first elements 147 { 148 posLog = null; 149 foreach(e; seq[0..3]) 150 { 151 ca.begin(e); 152 posLog ~= LogRecord(ca.position!order, e); 153 ca.end(e); 154 } 155 156 // checks 157 posLog.should.be == [ 158 LogRecord(0, 10), 159 LogRecord(10, 21), 160 LogRecord(31, 12), 161 ]; 162 163 ca.position!order.should.be == 43; 164 ca.csr.last_value.should.be == 12; 165 } 166 167 // step #2 - scroll for the next 3 elements 168 { 169 posLog = null; 170 foreach(e; seq[3..6]) 171 { 172 ca.begin(e); 173 posLog ~= LogRecord(ca.position!order, e); 174 ca.end(e); 175 } 176 177 // checks 178 posLog.should.be == [ 179 LogRecord(43, 13), 180 LogRecord(56, 24), 181 LogRecord(80, 15), 182 ]; 183 184 ca.position!order.should.be == 95; 185 ca.csr.last_value.should.be == 15; 186 } 187 188 // step #3 - scroll for the last two elements 189 { 190 posLog = null; 191 foreach(e; seq[6..$]) 192 { 193 ca.begin(e); 194 posLog ~= LogRecord(ca.position!order, e); 195 ca.end(e); 196 } 197 198 // check 199 posLog.should.be == [ 200 LogRecord(95, 16), 201 LogRecord(111, 17), 202 ]; 203 204 ca.position!order.should.be == 128; 205 ca.csr.last_value.should.be == 17; 206 } 207 208 // step #4 - scroll for the first two elements 209 { 210 ca.start; 211 posLog = null; 212 foreach(e; seq[0..2]) 213 { 214 ca.begin(e); 215 posLog ~= LogRecord(ca.position!order, e); 216 ca.end(e); 217 } 218 219 // check 220 posLog.should.be == [ 221 LogRecord(0, 10), 222 LogRecord(10, 21), 223 ]; 224 225 ca.position!order.should.be == 31; 226 ca.csr.last_value.should.be == 21; 227 } 228 } 229 230 version(unittest) 231 @Name("testTraversingBackward") 232 unittest 233 { 234 import auxil.cursor : Cursor; 235 236 const order = Cursor.Order.backward; 237 LogRecord[] posLog; 238 auto seq = sequence.dup.retro; 239 CursorAccumulator ca; 240 241 // start traversing 242 ca.start(sum(seq)); 243 244 // step #1 - scroll 3 first elements 245 { 246 posLog = null; 247 foreach(e; seq[0..3]) 248 { 249 ca.begin(e); 250 posLog ~= LogRecord(ca.position!order, e); 251 ca.end(e); 252 } 253 254 // checks 255 posLog.should.be == [ 256 LogRecord(111, 17), 257 LogRecord( 95, 16), 258 LogRecord( 80, 15), 259 ]; 260 261 ca.csr.fixUp; 262 263 writeln(ca.csr); 264 ca.position!order.should.be == 80; 265 ca.csr.last_value.should.be == 15; 266 } 267 268 // step #2 - scroll for the next 3 elements 269 { 270 posLog = null; 271 foreach(e; seq[3..6]) 272 { 273 ca.begin(e); 274 posLog ~= LogRecord(ca.position!order, e); 275 ca.end(e); 276 } 277 278 // checks 279 posLog.should.be == [ 280 LogRecord(43, 13), 281 LogRecord(56, 24), 282 LogRecord(80, 15), 283 ]; 284 285 ca.position!order.should.be == 95; 286 ca.csr.last_value.should.be == 15; 287 } 288 289 // step #3 - scroll for the last two elements 290 { 291 posLog = null; 292 foreach(e; seq[6..$]) 293 { 294 ca.begin(e); 295 posLog ~= LogRecord(ca.position!order, e); 296 ca.end(e); 297 } 298 299 // check 300 posLog.should.be == [ 301 LogRecord(95, 16), 302 LogRecord(111, 17), 303 ]; 304 305 ca.position!order.should.be == 128; 306 ca.csr.last_value.should.be == 17; 307 } 308 309 // step #4 - scroll for the first two elements 310 { 311 ca.start; 312 posLog = null; 313 foreach(e; seq[0..2]) 314 { 315 ca.begin(e); 316 posLog ~= LogRecord(ca.position!order, e); 317 ca.end(e); 318 } 319 320 // check 321 posLog.should.be == [ 322 LogRecord(0, 10), 323 LogRecord(10, 21), 324 ]; 325 326 ca.position!order.should.be == 31; 327 ca.csr.last_value.should.be == 21; 328 } 329 } 330 331 version(unittest) 332 @Name("testScrollingForward") 333 unittest 334 { 335 import auxil.cursor : Cursor; 336 337 const order = Cursor.Order.forward; 338 LogRecord[] posLog; 339 auto seq = sequence.dup; 340 CursorAccumulator ca; 341 342 // start scrolling 343 ca.start; 344 345 // step 1 346 { 347 foreach(e; seq[0..$/2]) 348 { 349 ca.begin(e); 350 posLog ~= LogRecord(ca.position!order, e); 351 ca.end(e); 352 } 353 354 ca.position!order.should.be == 56; 355 ca.csr.last_value.should.be == 13; 356 357 // commiting is the difference between scrolling and traversing 358 ca.commit!order; 359 360 posLog.should.be == [ 361 LogRecord(0, 10), 362 LogRecord(10, 21), 363 LogRecord(31, 12), 364 LogRecord(43, 13), 365 ]; 366 367 ca.position!order.should.be == 43; 368 ca.csr.last_value.should.be == 13; 369 ca.csr.current_value.should.be == 13; 370 } 371 372 // step 2 373 { 374 posLog = null; 375 376 foreach(e; seq[$/2-1..$]) // <= important that we start from the last element ($/2-1 not just $/2) 377 { 378 ca.begin(e); 379 posLog ~= LogRecord(ca.position!order, e); 380 ca.end(e); 381 } 382 ca.position!order.should.be == 128; 383 ca.csr.last_value.should.be == 17; 384 ca.csr.current_value.should.be == 17; 385 386 ca.commit!order; 387 388 posLog.should.be == [ 389 LogRecord(43, 13), 390 LogRecord(56, 24), 391 LogRecord(80, 15), 392 LogRecord(95, 16), 393 LogRecord(111, 17), 394 ]; 395 396 ca.position!order.should.be == 111; 397 ca.csr.last_value.should.be == 17; 398 ca.csr.current_value.should.be == 17; 399 } 400 }