resampler_test.dart 33.4 KB
Newer Older
1 2 3 4 5
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/gestures.dart';
6
import 'package:flutter_test/flutter_test.dart';
7 8

void main() {
9
  PointerEvent createSimulatedPointerAddedEvent(
10 11 12 13 14 15 16 17 18 19
      int timeStampUs,
      double x,
      double y,
  ) {
    return PointerAddedEvent(
        timeStamp: Duration(microseconds: timeStampUs),
        position: Offset(x, y),
    );
  }

20
  PointerEvent createSimulatedPointerRemovedEvent(
21 22 23 24 25 26 27 28 29 30
      int timeStampUs,
      double x,
      double y,
  ) {
    return PointerRemovedEvent(
        timeStamp: Duration(microseconds: timeStampUs),
        position: Offset(x, y),
    );
  }

31
  PointerEvent createSimulatedPointerDownEvent(
32 33 34 35 36 37 38 39 40 41
      int timeStampUs,
      double x,
      double y,
  ) {
    return PointerDownEvent(
        timeStamp: Duration(microseconds: timeStampUs),
        position: Offset(x, y),
    );
  }

42
  PointerEvent createSimulatedPointerMoveEvent(
43 44 45 46 47 48 49 50 51 52 53 54 55
      int timeStampUs,
      double x,
      double y,
      double deltaX,
      double deltaY,
  ) {
    return PointerMoveEvent(
        timeStamp: Duration(microseconds: timeStampUs),
        position: Offset(x, y),
        delta: Offset(deltaX, deltaY),
    );
  }

56
  PointerEvent createSimulatedPointerHoverEvent(
57 58 59 60 61 62 63 64 65 66 67 68 69
      int timeStampUs,
      double x,
      double y,
      double deltaX,
      double deltaY,
  ) {
    return PointerHoverEvent(
        timeStamp: Duration(microseconds: timeStampUs),
        position: Offset(x, y),
        delta: Offset(deltaX, deltaY),
    );
  }

70
  PointerEvent createSimulatedPointerUpEvent(
71 72 73 74 75 76 77 78 79 80 81 82
      int timeStampUs,
      double x,
      double y,
  ) {
    return PointerUpEvent(
        timeStamp: Duration(microseconds: timeStampUs),
        position: Offset(x, y),
    );
  }

  test('basic', () {
    final PointerEventResampler resampler = PointerEventResampler();
83 84 85 86 87 88 89 90 91
    final PointerEvent event0 = createSimulatedPointerAddedEvent(1000, 0.0, 50.0);
    final PointerEvent event1 = createSimulatedPointerHoverEvent(2000, 10.0, 40.0, 10.0, -10.0);
    final PointerEvent event2 = createSimulatedPointerDownEvent(2000, 10.0, 40.0);
    final PointerEvent event3 = createSimulatedPointerMoveEvent(3000, 20.0, 30.0, 10.0, -10.0);
    final PointerEvent event4 = createSimulatedPointerMoveEvent(4000, 30.0, 20.0, 10.0, -10.0);
    final PointerEvent event5 = createSimulatedPointerUpEvent(4000, 30.0, 20.0);
    final PointerEvent event6 = createSimulatedPointerHoverEvent(5000, 40.0, 10.0, 10.0, -10.0);
    final PointerEvent event7 = createSimulatedPointerHoverEvent(6000, 50.0, 0.0, 10.0, -10.0);
    final PointerEvent event8 = createSimulatedPointerRemovedEvent(6000, 50.0, 0.0);
92 93 94 95 96 97 98

    resampler
      ..addEvent(event0)
      ..addEvent(event1)
      ..addEvent(event2)
      ..addEvent(event3)
      ..addEvent(event4)
99 100 101 102
      ..addEvent(event5)
      ..addEvent(event6)
      ..addEvent(event7)
      ..addEvent(event8);
103 104 105

    final List<PointerEvent> result = <PointerEvent>[];

106
    resampler.sample(const Duration(microseconds: 500), Duration.zero, result.add);
107 108 109 110

    // No pointer event should have been returned yet.
    expect(result.isEmpty, true);

111
    resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
112 113 114 115 116 117 118 119

    // Add pointer event should have been returned.
    expect(result.length, 1);
    expect(result[0].timeStamp, const Duration(microseconds: 1500));
    expect(result[0] is PointerAddedEvent, true);
    expect(result[0].position.dx, 5.0);
    expect(result[0].position.dy, 45.0);

120
    resampler.sample(const Duration(microseconds: 2500), Duration.zero, result.add);
121

122 123
    // Hover and down pointer events should have been returned.
    expect(result.length, 3);
124
    expect(result[1].timeStamp, const Duration(microseconds: 2500));
125
    expect(result[1] is PointerHoverEvent, true);
126 127
    expect(result[1].position.dx, 15.0);
    expect(result[1].position.dy, 35.0);
128 129 130 131 132 133
    expect(result[1].delta.dx, 10.0);
    expect(result[1].delta.dy, -10.0);
    expect(result[2].timeStamp, const Duration(microseconds: 2500));
    expect(result[2] is PointerDownEvent, true);
    expect(result[2].position.dx, 15.0);
    expect(result[2].position.dy, 35.0);
134

135
    resampler.sample(const Duration(microseconds: 3500), Duration.zero, result.add);
136 137

    // Move pointer event should have been returned.
138 139 140 141 142 143 144
    expect(result.length, 4);
    expect(result[3].timeStamp, const Duration(microseconds: 3500));
    expect(result[3] is PointerMoveEvent, true);
    expect(result[3].position.dx, 25.0);
    expect(result[3].position.dy, 25.0);
    expect(result[3].delta.dx, 10.0);
    expect(result[3].delta.dy, -10.0);
145

146
    resampler.sample(const Duration(microseconds: 4500), Duration.zero, result.add);
147

148 149 150 151 152 153 154 155
    // Move and up pointer events should have been returned.
    expect(result.length, 6);
    expect(result[4].timeStamp, const Duration(microseconds: 4500));
    expect(result[4] is PointerMoveEvent, true);
    expect(result[4].position.dx, 35.0);
    expect(result[4].position.dy, 15.0);
    expect(result[4].delta.dx, 10.0);
    expect(result[4].delta.dy, -10.0);
156 157
    // buttons field needs to be a valid value
    expect(result[4].buttons, kPrimaryButton);
158 159 160 161
    expect(result[5].timeStamp, const Duration(microseconds: 4500));
    expect(result[5] is PointerUpEvent, true);
    expect(result[5].position.dx, 35.0);
    expect(result[5].position.dy, 15.0);
162

163
    resampler.sample(const Duration(microseconds: 5500), Duration.zero, result.add);
164

165 166
    // Hover pointer event should have been returned.
    expect(result.length, 7);
167 168 169 170 171 172
    expect(result[6].timeStamp, const Duration(microseconds: 5500));
    expect(result[6] is PointerHoverEvent, true);
    expect(result[6].position.dx, 45.0);
    expect(result[6].position.dy, 5.0);
    expect(result[6].delta.dx, 10.0);
    expect(result[6].delta.dy, -10.0);
173

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
    resampler.sample(const Duration(microseconds: 6500), Duration.zero, result.add);

    // Hover and removed pointer events should have been returned.
    expect(result.length, 9);
    expect(result[7].timeStamp, const Duration(microseconds: 6500));
    expect(result[7] is PointerHoverEvent, true);
    expect(result[7].position.dx, 50.0);
    expect(result[7].position.dy, 0.0);
    expect(result[7].delta.dx, 5.0);
    expect(result[7].delta.dy, -5.0);
    expect(result[8].timeStamp, const Duration(microseconds: 6500));
    expect(result[8] is PointerRemovedEvent, true);
    expect(result[8].position.dx, 50.0);
    expect(result[8].position.dy, 0.0);

    resampler.sample(const Duration(microseconds: 7500), Duration.zero, result.add);
190 191

    // No pointer event should have been returned.
192
    expect(result.length, 9);
193 194 195 196
  });

  test('stream', () {
    final PointerEventResampler resampler = PointerEventResampler();
197 198 199 200 201 202 203 204 205
    final PointerEvent event0 = createSimulatedPointerAddedEvent(1000, 0.0, 50.0);
    final PointerEvent event1 = createSimulatedPointerHoverEvent(2000, 10.0, 40.0, 10.0, -10.0);
    final PointerEvent event2 = createSimulatedPointerDownEvent(2000, 10.0, 40.0);
    final PointerEvent event3 = createSimulatedPointerMoveEvent(3000, 20.0, 30.0, 10.0, -10.0);
    final PointerEvent event4 = createSimulatedPointerMoveEvent(4000, 30.0, 20.0, 10.0, -10.0);
    final PointerEvent event5 = createSimulatedPointerUpEvent(4000, 30.0, 20.0);
    final PointerEvent event6 = createSimulatedPointerHoverEvent(5000, 40.0, 10.0, 10.0, -10.0);
    final PointerEvent event7 = createSimulatedPointerHoverEvent(6000, 50.0, 0.0, 10.0, -10.0);
    final PointerEvent event8 = createSimulatedPointerRemovedEvent(6000, 50.0, 0.0);
206 207 208 209 210 211 212 213 214

    resampler.addEvent(event0);

    //
    // Initial sample time a 0.5 ms.
    //

    final List<PointerEvent> result = <PointerEvent>[];

215
    resampler.sample(const Duration(microseconds: 500), Duration.zero, result.add);
216 217 218 219

    // No pointer event should have been returned yet.
    expect(result.isEmpty, true);

220 221 222
    resampler
      ..addEvent(event1)
      ..addEvent(event2);
223

224
    resampler.sample(const Duration(microseconds: 500), Duration.zero, result.add);
225 226 227 228 229 230 231 232

    // No pointer event should have been returned yet.
    expect(result.isEmpty, true);

    //
    // Advance sample time to 1.5 ms.
    //

233
    resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
234

235
    // Added pointer event should have been returned.
236 237 238 239 240 241
    expect(result.length, 1);
    expect(result[0].timeStamp, const Duration(microseconds: 1500));
    expect(result[0] is PointerAddedEvent, true);
    expect(result[0].position.dx, 5.0);
    expect(result[0].position.dy, 45.0);

242
    resampler.addEvent(event3);
243

244
    resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
245 246 247 248 249 250 251 252

    // No more pointer events should have been returned.
    expect(result.length, 1);

    //
    // Advance sample time to 2.5 ms.
    //

253
    resampler.sample(const Duration(microseconds: 2500), Duration.zero, result.add);
254

255 256
    // Hover and down pointer events should have been returned.
    expect(result.length, 3);
257
    expect(result[1].timeStamp, const Duration(microseconds: 2500));
258
    expect(result[1] is PointerHoverEvent, true);
259 260
    expect(result[1].position.dx, 15.0);
    expect(result[1].position.dy, 35.0);
261 262 263 264 265 266
    expect(result[1].delta.dx, 10.0);
    expect(result[1].delta.dy, -10.0);
    expect(result[2].timeStamp, const Duration(microseconds: 2500));
    expect(result[2] is PointerDownEvent, true);
    expect(result[2].position.dx, 15.0);
    expect(result[2].position.dy, 35.0);
267

268 269 270
    resampler
      ..addEvent(event4)
      ..addEvent(event5);
271

272
    resampler.sample(const Duration(microseconds: 2500), Duration.zero, result.add);
273 274

    // No more pointer events should have been returned.
275
    expect(result.length, 3);
276 277 278 279 280

    //
    // Advance sample time to 3.5 ms.
    //

281
    resampler.sample(const Duration(microseconds: 3500), Duration.zero, result.add);
282 283

    // Move pointer event should have been returned.
284 285 286 287 288 289 290
    expect(result.length, 4);
    expect(result[3].timeStamp, const Duration(microseconds: 3500));
    expect(result[3] is PointerMoveEvent, true);
    expect(result[3].position.dx, 25.0);
    expect(result[3].position.dy, 25.0);
    expect(result[3].delta.dx, 10.0);
    expect(result[3].delta.dy, -10.0);
291

292
    resampler.addEvent(event6);
293

294
    resampler.sample(const Duration(microseconds: 3500), Duration.zero, result.add);
295 296

    // No more pointer events should have been returned.
297
    expect(result.length, 4);
298 299 300 301 302

    //
    // Advance sample time to 4.5 ms.
    //

303
    resampler.sample(const Duration(microseconds: 4500), Duration.zero, result.add);
304

305 306 307 308 309 310 311 312 313 314 315 316
    // Move and up pointer events should have been returned.
    expect(result.length, 6);
    expect(result[4].timeStamp, const Duration(microseconds: 4500));
    expect(result[4] is PointerMoveEvent, true);
    expect(result[4].position.dx, 35.0);
    expect(result[4].position.dy, 15.0);
    expect(result[4].delta.dx, 10.0);
    expect(result[4].delta.dy, -10.0);
    expect(result[5].timeStamp, const Duration(microseconds: 4500));
    expect(result[5] is PointerUpEvent, true);
    expect(result[5].position.dx, 35.0);
    expect(result[5].position.dy, 15.0);
317

318 319 320
    resampler
      ..addEvent(event7)
      ..addEvent(event8);
321

322
    resampler.sample(const Duration(microseconds: 4500), Duration.zero, result.add);
323 324

    // No more pointer events should have been returned.
325
    expect(result.length, 6);
326 327 328 329 330

    //
    // Advance sample time to 5.5 ms.
    //

331
    resampler.sample(const Duration(microseconds: 5500), Duration.zero, result.add);
332

333 334
    // Hover pointer event should have been returned.
    expect(result.length, 7);
335 336 337 338 339 340
    expect(result[6].timeStamp, const Duration(microseconds: 5500));
    expect(result[6] is PointerHoverEvent, true);
    expect(result[6].position.dx, 45.0);
    expect(result[6].position.dy, 5.0);
    expect(result[6].delta.dx, 10.0);
    expect(result[6].delta.dy, -10.0);
341 342 343 344 345

    //
    // Advance sample time to 6.5 ms.
    //

346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
    resampler.sample(const Duration(microseconds: 6500), Duration.zero, result.add);

    // Hover and removed pointer event should have been returned.
    expect(result.length, 9);
    expect(result[7].timeStamp, const Duration(microseconds: 6500));
    expect(result[7] is PointerHoverEvent, true);
    expect(result[7].position.dx, 50.0);
    expect(result[7].position.dy, 0.0);
    expect(result[7].delta.dx, 5.0);
    expect(result[7].delta.dy, -5.0);
    expect(result[8].timeStamp, const Duration(microseconds: 6500));
    expect(result[8] is PointerRemovedEvent, true);
    expect(result[8].position.dx, 50.0);
    expect(result[8].position.dy, 0.0);

    //
    // Advance sample time to 7.5 ms.
    //

    resampler.sample(const Duration(microseconds: 7500), Duration.zero, result.add);
366 367

    // No pointer events should have been returned.
368
    expect(result.length, 9);
369 370 371 372
  });

  test('quick tap', () {
    final PointerEventResampler resampler = PointerEventResampler();
373 374 375 376
    final PointerEvent event0 = createSimulatedPointerAddedEvent(1000, 0.0, 0.0);
    final PointerEvent event1 = createSimulatedPointerDownEvent(1000, 0.0, 0.0);
    final PointerEvent event2 = createSimulatedPointerUpEvent(1000, 0.0, 0.0);
    final PointerEvent event3 = createSimulatedPointerRemovedEvent(1000, 0.0, 0.0);
377 378 379 380 381 382 383 384 385

    resampler
      ..addEvent(event0)
      ..addEvent(event1)
      ..addEvent(event2)
      ..addEvent(event3);

    final List<PointerEvent> result = <PointerEvent>[];

386
    resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409

    // All pointer events should have been returned.
    expect(result.length, 4);
    expect(result[0].timeStamp, const Duration(microseconds: 1500));
    expect(result[0] is PointerAddedEvent, true);
    expect(result[0].position.dx, 0.0);
    expect(result[0].position.dy, 0.0);
    expect(result[1].timeStamp, const Duration(microseconds: 1500));
    expect(result[1] is PointerDownEvent, true);
    expect(result[1].position.dx, 0.0);
    expect(result[1].position.dy, 0.0);
    expect(result[2].timeStamp, const Duration(microseconds: 1500));
    expect(result[2] is PointerUpEvent, true);
    expect(result[2].position.dx, 0.0);
    expect(result[2].position.dy, 0.0);
    expect(result[3].timeStamp, const Duration(microseconds: 1500));
    expect(result[3] is PointerRemovedEvent, true);
    expect(result[3].position.dx, 0.0);
    expect(result[3].position.dy, 0.0);
  });

  test('advance slowly', () {
    final PointerEventResampler resampler = PointerEventResampler();
410 411 412 413 414 415
    final PointerEvent event0 = createSimulatedPointerAddedEvent(1000, 0.0, 0.0);
    final PointerEvent event1 = createSimulatedPointerDownEvent(1000, 0.0, 0.0);
    final PointerEvent event2 = createSimulatedPointerMoveEvent(2000, 10.0, 0.0, 10.0, 0.0);
    final PointerEvent event3 = createSimulatedPointerMoveEvent(3000, 20.0, 0.0, 10.0, 0.0);
    final PointerEvent event4 = createSimulatedPointerUpEvent(3000, 20.0, 0.0);
    final PointerEvent event5 = createSimulatedPointerRemovedEvent(3000, 20.0, 0.0);
416 417 418 419 420 421

    resampler
      ..addEvent(event0)
      ..addEvent(event1)
      ..addEvent(event2)
      ..addEvent(event3)
422 423
      ..addEvent(event4)
      ..addEvent(event5);
424 425 426

    final List<PointerEvent> result = <PointerEvent>[];

427
    resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
428 429 430 431 432 433 434 435 436 437 438 439

    // Added and down pointer events should have been returned.
    expect(result.length, 2);
    expect(result[0].timeStamp, const Duration(microseconds: 1500));
    expect(result[0] is PointerAddedEvent, true);
    expect(result[0].position.dx, 5.0);
    expect(result[0].position.dy, 0.0);
    expect(result[1].timeStamp, const Duration(microseconds: 1500));
    expect(result[1] is PointerDownEvent, true);
    expect(result[1].position.dx, 5.0);
    expect(result[1].position.dy, 0.0);

440
    resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
441 442 443 444

    // No pointer events should have been returned.
    expect(result.length, 2);

445
    resampler.sample(const Duration(microseconds: 1750), Duration.zero, result.add);
446 447 448 449 450 451 452 453 454 455

    // Move pointer event should have been returned.
    expect(result.length, 3);
    expect(result[2].timeStamp, const Duration(microseconds: 1750));
    expect(result[2] is PointerMoveEvent, true);
    expect(result[2].position.dx, 7.5);
    expect(result[2].position.dy, 0.0);
    expect(result[2].delta.dx, 2.5);
    expect(result[2].delta.dy, 0.0);

456
    resampler.sample(const Duration(microseconds: 2000), Duration.zero, result.add);
457 458 459 460 461 462 463 464 465 466

    // Another move pointer event should have been returned.
    expect(result.length, 4);
    expect(result[3].timeStamp, const Duration(microseconds: 2000));
    expect(result[3] is PointerMoveEvent, true);
    expect(result[3].position.dx, 10.0);
    expect(result[3].position.dy, 0.0);
    expect(result[3].delta.dx, 2.5);
    expect(result[3].delta.dy, 0.0);

467
    resampler.sample(const Duration(microseconds: 3000), Duration.zero, result.add);
468

469 470
    // Move, up and removed pointer events should have been returned.
    expect(result.length, 7);
471
    expect(result[4].timeStamp, const Duration(microseconds: 3000));
472
    expect(result[4] is PointerMoveEvent, true);
473
    expect(result[4].position.dx, 20.0);
474
    expect(result[4].position.dy, 0.0);
475
    expect(result[4].delta.dx, 10.0);
476
    expect(result[4].delta.dy, 0.0);
477
    expect(result[5].timeStamp, const Duration(microseconds: 3000));
478
    expect(result[5] is PointerUpEvent, true);
479
    expect(result[5].position.dx, 20.0);
480
    expect(result[5].position.dy, 0.0);
481
    expect(result[6].timeStamp, const Duration(microseconds: 3000));
482
    expect(result[6] is PointerRemovedEvent, true);
483
    expect(result[6].position.dx, 20.0);
484
    expect(result[6].position.dy, 0.0);
485 486 487 488
  });

  test('advance fast', () {
    final PointerEventResampler resampler = PointerEventResampler();
489 490 491 492 493 494
    final PointerEvent event0 = createSimulatedPointerAddedEvent(1000, 0.0, 0.0);
    final PointerEvent event1 = createSimulatedPointerDownEvent(1000, 0.0, 0.0);
    final PointerEvent event2 = createSimulatedPointerMoveEvent(2000, 5.0, 0.0, 5.0, 0.0);
    final PointerEvent event3 = createSimulatedPointerMoveEvent(3000, 20.0, 0.0, 15.0, 0.0);
    final PointerEvent event4 = createSimulatedPointerUpEvent(4000, 30.0, 0.0);
    final PointerEvent event5 = createSimulatedPointerRemovedEvent(4000, 30.0, 0.0);
495 496 497 498 499 500 501 502 503 504 505

    resampler
      ..addEvent(event0)
      ..addEvent(event1)
      ..addEvent(event2)
      ..addEvent(event3)
      ..addEvent(event4)
      ..addEvent(event5);

    final List<PointerEvent> result = <PointerEvent>[];

506
    resampler.sample(const Duration(microseconds: 2500), Duration.zero, result.add);
507

508
    // Addeds and down pointer events should have been returned.
509 510 511 512 513 514 515 516 517 518
    expect(result.length, 2);
    expect(result[0].timeStamp, const Duration(microseconds: 2500));
    expect(result[0] is PointerAddedEvent, true);
    expect(result[0].position.dx, 12.5);
    expect(result[0].position.dy, 0.0);
    expect(result[1].timeStamp, const Duration(microseconds: 2500));
    expect(result[1] is PointerDownEvent, true);
    expect(result[1].position.dx, 12.5);
    expect(result[1].position.dy, 0.0);

519
    resampler.sample(const Duration(microseconds: 5500), Duration.zero, result.add);
520

521 522
    // Move, up and removed pointer events should have been returned.
    expect(result.length, 5);
523
    expect(result[2].timeStamp, const Duration(microseconds: 5500));
524
    expect(result[2] is PointerMoveEvent, true);
525 526
    expect(result[2].position.dx, 30.0);
    expect(result[2].position.dy, 0.0);
527 528
    expect(result[2].delta.dx, 17.5);
    expect(result[2].delta.dy, 0.0);
529
    expect(result[3].timeStamp, const Duration(microseconds: 5500));
530
    expect(result[3] is PointerUpEvent, true);
531 532
    expect(result[3].position.dx, 30.0);
    expect(result[3].position.dy, 0.0);
533 534 535 536
    expect(result[4].timeStamp, const Duration(microseconds: 5500));
    expect(result[4] is PointerRemovedEvent, true);
    expect(result[4].position.dx, 30.0);
    expect(result[4].position.dy, 0.0);
537

538
    resampler.sample(const Duration(microseconds: 6500), Duration.zero, result.add);
539 540

    // No pointer events should have been returned.
541
    expect(result.length, 5);
542 543 544 545
  });

  test('skip', () {
    final PointerEventResampler resampler = PointerEventResampler();
546 547 548 549 550 551 552 553 554
    final PointerEvent event0 = createSimulatedPointerAddedEvent(1000, 0.0, 0.0);
    final PointerEvent event1 = createSimulatedPointerDownEvent(1000, 0.0, 0.0);
    final PointerEvent event2 = createSimulatedPointerMoveEvent(2000, 10.0, 0.0, 10.0, 0.0);
    final PointerEvent event3 = createSimulatedPointerUpEvent(3000, 10.0, 0.0);
    final PointerEvent event4 = createSimulatedPointerHoverEvent(4000, 20.0, 0.0, 10.0, 0.0);
    final PointerEvent event5 = createSimulatedPointerDownEvent(4000, 20.0, 0.0);
    final PointerEvent event6 = createSimulatedPointerMoveEvent(5000, 30.0, 0.0, 10.0, 0.0);
    final PointerEvent event7 = createSimulatedPointerUpEvent(5000, 30.0, 0.0);
    final PointerEvent event8 = createSimulatedPointerRemovedEvent(5000, 30.0, 0.0);
555 556 557 558 559 560 561 562

    resampler
      ..addEvent(event0)
      ..addEvent(event1)
      ..addEvent(event2)
      ..addEvent(event3)
      ..addEvent(event4)
      ..addEvent(event5)
563 564 565
      ..addEvent(event6)
      ..addEvent(event7)
      ..addEvent(event8);
566 567 568

    final List<PointerEvent> result = <PointerEvent>[];

569
    resampler.sample(const Duration(microseconds: 1500), Duration.zero, result.add);
570 571 572 573 574 575 576 577 578 579 580 581

    // Added and down pointer events should have been returned.
    expect(result.length, 2);
    expect(result[0].timeStamp, const Duration(microseconds: 1500));
    expect(result[0] is PointerAddedEvent, true);
    expect(result[0].position.dx, 5.0);
    expect(result[0].position.dy, 0.0);
    expect(result[1].timeStamp, const Duration(microseconds: 1500));
    expect(result[1] is PointerDownEvent, true);
    expect(result[1].position.dx, 5.0);
    expect(result[1].position.dy, 0.0);

582
    resampler.sample(const Duration(microseconds: 5500), Duration.zero, result.add);
583 584

    // All remaining pointer events should have been returned.
585
    expect(result.length, 7);
586
    expect(result[2].timeStamp, const Duration(microseconds: 5500));
587
    expect(result[2] is PointerMoveEvent, true);
588
    expect(result[2].position.dx, 30.0);
589
    expect(result[2].position.dy, 0.0);
590
    expect(result[2].delta.dx, 25.0);
591
    expect(result[2].delta.dy, 0.0);
592
    expect(result[3].timeStamp, const Duration(microseconds: 5500));
593
    expect(result[3] is PointerUpEvent, true);
594
    expect(result[3].position.dx, 30.0);
595
    expect(result[3].position.dy, 0.0);
596
    expect(result[4].timeStamp, const Duration(microseconds: 5500));
597
    expect(result[4] is PointerDownEvent, true);
598
    expect(result[4].position.dx, 30.0);
599
    expect(result[4].position.dy, 0.0);
600
    expect(result[5].timeStamp, const Duration(microseconds: 5500));
601
    expect(result[5] is PointerUpEvent, true);
602
    expect(result[5].position.dx, 30.0);
603
    expect(result[5].position.dy, 0.0);
604
    expect(result[6].timeStamp, const Duration(microseconds: 5500));
605
    expect(result[6] is PointerRemovedEvent, true);
606
    expect(result[6].position.dx, 30.0);
607
    expect(result[6].position.dy, 0.0);
608

609
    resampler.sample(const Duration(microseconds: 6500), Duration.zero, result.add);
610 611

    // No pointer events should have been returned.
612
    expect(result.length, 7);
613 614 615 616
  });

  test('skip all', () {
    final PointerEventResampler resampler = PointerEventResampler();
617 618 619 620 621
    final PointerEvent event0 = createSimulatedPointerAddedEvent(1000, 0.0, 0.0);
    final PointerEvent event1 = createSimulatedPointerDownEvent(1000, 0.0, 0.0);
    final PointerEvent event2 = createSimulatedPointerMoveEvent(4000, 30.0, 0.0, 30.0, 0.0);
    final PointerEvent event3 = createSimulatedPointerUpEvent(4000, 30.0, 0.0);
    final PointerEvent event4 = createSimulatedPointerRemovedEvent(4000, 30.0, 0.0);
622 623 624 625 626

    resampler
      ..addEvent(event0)
      ..addEvent(event1)
      ..addEvent(event2)
627 628
      ..addEvent(event3)
      ..addEvent(event4);
629 630 631

    final List<PointerEvent> result = <PointerEvent>[];

632
    resampler.sample(const Duration(microseconds: 500), Duration.zero, result.add);
633 634 635 636

    // No pointer events should have been returned.
    expect(result.isEmpty, true);

637
    resampler.sample(const Duration(microseconds: 5500), Duration.zero, result.add);
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657

    // All remaining pointer events should have been returned.
    expect(result.length, 4);
    expect(result[0].timeStamp, const Duration(microseconds: 5500));
    expect(result[0] is PointerAddedEvent, true);
    expect(result[0].position.dx, 30.0);
    expect(result[0].position.dy, 0.0);
    expect(result[1].timeStamp, const Duration(microseconds: 5500));
    expect(result[1] is PointerDownEvent, true);
    expect(result[1].position.dx, 30.0);
    expect(result[1].position.dy, 0.0);
    expect(result[2].timeStamp, const Duration(microseconds: 5500));
    expect(result[2] is PointerUpEvent, true);
    expect(result[2].position.dx, 30.0);
    expect(result[2].position.dy, 0.0);
    expect(result[3].timeStamp, const Duration(microseconds: 5500));
    expect(result[3] is PointerRemovedEvent, true);
    expect(result[3].position.dx, 30.0);
    expect(result[3].position.dy, 0.0);

658
    resampler.sample(const Duration(microseconds: 6500), Duration.zero, result.add);
659 660 661 662 663 664 665

    // No pointer events should have been returned.
    expect(result.length, 4);
  });

  test('stop', () {
    final PointerEventResampler resampler = PointerEventResampler();
666 667 668 669 670 671
    final PointerEvent event0 = createSimulatedPointerAddedEvent(1000, 0.0, 0.0);
    final PointerEvent event1 = createSimulatedPointerDownEvent(2000, 0.0, 0.0);
    final PointerEvent event2 = createSimulatedPointerMoveEvent(3000, 10.0, 0.0, 10.0, 0.0);
    final PointerEvent event3 = createSimulatedPointerMoveEvent(4000, 20.0, 0.0, 10.0, 0.0);
    final PointerEvent event4 = createSimulatedPointerUpEvent(4000, 20.0, 0.0);
    final PointerEvent event5 = createSimulatedPointerRemovedEvent(5000, 20.0, 0.0);
672 673 674 675 676 677

    resampler
      ..addEvent(event0)
      ..addEvent(event1)
      ..addEvent(event2)
      ..addEvent(event3)
678 679
      ..addEvent(event4)
      ..addEvent(event5);
680 681 682

    final List<PointerEvent> result = <PointerEvent>[];

683
    resampler.sample(const Duration(microseconds: 500), Duration.zero, result.add);
684 685 686 687 688 689

    // No pointer events should have been returned.
    expect(result.isEmpty, true);

    resampler.stop(result.add);

690
    // All pointer events should have been returned with original
691
    // time stamps and positions.
692
    expect(result.length, 6);
693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
    expect(result[0].timeStamp, const Duration(microseconds: 1000));
    expect(result[0] is PointerAddedEvent, true);
    expect(result[0].position.dx, 0.0);
    expect(result[0].position.dy, 0.0);
    expect(result[1].timeStamp, const Duration(microseconds: 2000));
    expect(result[1] is PointerDownEvent, true);
    expect(result[1].position.dx, 0.0);
    expect(result[1].position.dy, 0.0);
    expect(result[2].timeStamp, const Duration(microseconds: 3000));
    expect(result[2] is PointerMoveEvent, true);
    expect(result[2].position.dx, 10.0);
    expect(result[2].position.dy, 0.0);
    expect(result[2].delta.dx, 10.0);
    expect(result[2].delta.dy, 0.0);
    expect(result[3].timeStamp, const Duration(microseconds: 4000));
708
    expect(result[3] is PointerMoveEvent, true);
709 710
    expect(result[3].position.dx, 20.0);
    expect(result[3].position.dy, 0.0);
711 712 713 714
    expect(result[3].delta.dx, 10.0);
    expect(result[3].delta.dy, 0.0);
    expect(result[4].timeStamp, const Duration(microseconds: 4000));
    expect(result[4] is PointerUpEvent, true);
715 716
    expect(result[4].position.dx, 20.0);
    expect(result[4].position.dy, 0.0);
717 718 719 720
    expect(result[5].timeStamp, const Duration(microseconds: 5000));
    expect(result[5] is PointerRemovedEvent, true);
    expect(result[5].position.dx, 20.0);
    expect(result[5].position.dy, 0.0);
721

722
    resampler.sample(const Duration(microseconds: 10000), Duration.zero, result.add);
723 724

    // No pointer events should have been returned.
725
    expect(result.length, 6);
726
  });
727 728 729

  test('synthetic move', () {
    final PointerEventResampler resampler = PointerEventResampler();
730 731 732 733 734
    final PointerEvent event0 = createSimulatedPointerAddedEvent(1000, 0.0, 0.0);
    final PointerEvent event1 = createSimulatedPointerDownEvent(2000, 0.0, 0.0);
    final PointerEvent event2 = createSimulatedPointerMoveEvent(3000, 10.0, 0.0, 10.0, 0.0);
    final PointerEvent event3 = createSimulatedPointerUpEvent(4000, 10.0, 0.0);
    final PointerEvent event4 = createSimulatedPointerRemovedEvent(5000, 10.0, 0.0);
735 736 737 738 739 740 741 742 743 744

    resampler
      ..addEvent(event0)
      ..addEvent(event1)
      ..addEvent(event2)
      ..addEvent(event3)
      ..addEvent(event4);

    final List<PointerEvent> result = <PointerEvent>[];

745
    resampler.sample(const Duration(microseconds: 500), Duration.zero, result.add);
746 747 748 749

    // No pointer events should have been returned.
    expect(result.isEmpty, true);

750
    resampler.sample(const Duration(microseconds: 2000), Duration.zero, result.add);
751 752 753 754 755 756 757 758 759 760 761 762

    // Added and down pointer events should have been returned.
    expect(result.length, 2);
    expect(result[0].timeStamp, const Duration(microseconds: 2000));
    expect(result[0] is PointerAddedEvent, true);
    expect(result[0].position.dx, 0.0);
    expect(result[0].position.dy, 0.0);
    expect(result[1].timeStamp, const Duration(microseconds: 2000));
    expect(result[1] is PointerDownEvent, true);
    expect(result[1].position.dx, 0.0);
    expect(result[1].position.dy, 0.0);

763
    resampler.sample(const Duration(microseconds: 5000), Duration.zero, result.add);
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782

    // All remaining pointer events and a synthetic move event should
    // have been returned.
    expect(result.length, 5);
    expect(result[2].timeStamp, const Duration(microseconds: 5000));
    expect(result[2] is PointerMoveEvent, true);
    expect(result[2].position.dx, 10.0);
    expect(result[2].position.dy, 0.0);
    expect(result[2].delta.dx, 10.0);
    expect(result[2].delta.dy, 0.0);
    expect(result[3].timeStamp, const Duration(microseconds: 5000));
    expect(result[3] is PointerUpEvent, true);
    expect(result[3].position.dx, 10.0);
    expect(result[3].position.dy, 0.0);
    expect(result[4].timeStamp, const Duration(microseconds: 5000));
    expect(result[4] is PointerRemovedEvent, true);
    expect(result[4].position.dx, 10.0);
    expect(result[4].position.dy, 0.0);

783
    resampler.sample(const Duration(microseconds: 10000), Duration.zero, result.add);
784 785 786 787

    // No pointer events should have been returned.
    expect(result.length, 5);
  });
788 789 790

  test('next sample time', () {
    final PointerEventResampler resampler = PointerEventResampler();
791 792 793 794 795 796 797
    final PointerEvent event0 = createSimulatedPointerAddedEvent(1000, 0.0, 0.0);
    final PointerEvent event1 = createSimulatedPointerDownEvent(1000, 0.0, 0.0);
    final PointerEvent event2 = createSimulatedPointerMoveEvent(2000, 10.0, 0.0, 10.0, 0.0);
    final PointerEvent event3 = createSimulatedPointerMoveEvent(3000, 20.0, 0.0, 10.0, 0.0);
    final PointerEvent event4 = createSimulatedPointerUpEvent(3000, 20.0, 0.0);
    final PointerEvent event5 = createSimulatedPointerHoverEvent(4000, 30.0, 0.0, 10.0, 0.0);
    final PointerEvent event6 = createSimulatedPointerRemovedEvent(4000, 30.0, 0.0);
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870

    resampler
      ..addEvent(event0)
      ..addEvent(event1)
      ..addEvent(event2)
      ..addEvent(event3)
      ..addEvent(event4)
      ..addEvent(event5)
      ..addEvent(event6);

    final List<PointerEvent> result = <PointerEvent>[];

    Duration sampleTime = const Duration(microseconds: 500);
    Duration nextSampleTime = const Duration(microseconds: 1500);
    resampler.sample(sampleTime, nextSampleTime, result.add);

    // No pointer events should have been returned.
    expect(result.isEmpty, true);

    sampleTime = nextSampleTime;
    nextSampleTime = const Duration(microseconds: 2500);
    resampler.sample(sampleTime, nextSampleTime, result.add);

    // Added and down pointer events should have been returned.
    expect(result.length, 2);
    expect(result[0].timeStamp, const Duration(microseconds: 1500));
    expect(result[0] is PointerAddedEvent, true);
    expect(result[0].position.dx, 5.0);
    expect(result[0].position.dy, 0.0);
    expect(result[1].timeStamp, const Duration(microseconds: 1500));
    expect(result[1] is PointerDownEvent, true);
    expect(result[1].position.dx, 5.0);
    expect(result[1].position.dy, 0.0);

    sampleTime = nextSampleTime;
    nextSampleTime = const Duration(microseconds: 3500);
    resampler.sample(sampleTime, nextSampleTime, result.add);

    // Move and up pointer events should have been returned.
    expect(result.length, 4);
    expect(result[2].timeStamp, const Duration(microseconds: 2500));
    expect(result[2] is PointerMoveEvent, true);
    expect(result[2].position.dx, 15.0);
    expect(result[2].position.dy, 0.0);
    expect(result[2].delta.dx, 10.0);
    expect(result[2].delta.dy, 0.0);
    expect(result[3].timeStamp, const Duration(microseconds: 2500));
    expect(result[3] is PointerUpEvent, true);
    expect(result[3].position.dx, 15.0);
    expect(result[3].position.dy, 0.0);

    sampleTime = nextSampleTime;
    nextSampleTime = const Duration(microseconds: 4500);
    resampler.sample(sampleTime, nextSampleTime, result.add);

    // All remaining pointer events should have been returned.
    expect(result.length, 6);
    expect(result[4].timeStamp, const Duration(microseconds: 3500));
    expect(result[4] is PointerHoverEvent, true);
    expect(result[4].position.dx, 25.0);
    expect(result[4].position.dy, 0.0);
    expect(result[4].delta.dx, 10.0);
    expect(result[4].delta.dy, 0.0);
    expect(result[5].timeStamp, const Duration(microseconds: 3500));
    expect(result[5] is PointerRemovedEvent, true);
    expect(result[5].position.dx, 25.0);
    expect(result[5].position.dy, 0.0);

    resampler.sample(const Duration(microseconds: 10000), Duration.zero, result.add);

    // No pointer events should have been returned.
    expect(result.length, 6);
  });
871
}