async-test.c++ 20.1 KB
Newer Older
Kenton Varda's avatar
Kenton Varda committed
1 2
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
3
//
Kenton Varda's avatar
Kenton Varda committed
4 5 6 7 8 9
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
10
//
Kenton Varda's avatar
Kenton Varda committed
11 12
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
13
//
Kenton Varda's avatar
Kenton Varda committed
14 15 16 17 18 19 20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
21 22 23

#include "async.h"
#include "debug.h"
24
#include <kj/compat/gtest.h>
25 26 27 28

namespace kj {
namespace {

29 30
#if !_MSC_VER
// TODO(msvc): GetFunctorStartAddress is not supported on MSVC currently, so skip the test.
31 32 33
TEST(Async, GetFunctorStartAddress) {
  EXPECT_TRUE(nullptr != _::GetFunctorStartAddress<>::apply([](){return 0;}));
}
34
#endif
35

36
TEST(Async, EvalVoid) {
37
  EventLoop loop;
38
  WaitScope waitScope(loop);
39 40 41

  bool done = false;

42
  Promise<void> promise = evalLater([&]() { done = true; });
43
  EXPECT_FALSE(done);
44
  promise.wait(waitScope);
45 46 47 48
  EXPECT_TRUE(done);
}

TEST(Async, EvalInt) {
49
  EventLoop loop;
50
  WaitScope waitScope(loop);
51 52 53

  bool done = false;

54
  Promise<int> promise = evalLater([&]() { done = true; return 123; });
55
  EXPECT_FALSE(done);
56
  EXPECT_EQ(123, promise.wait(waitScope));
57 58 59 60
  EXPECT_TRUE(done);
}

TEST(Async, There) {
61
  EventLoop loop;
62
  WaitScope waitScope(loop);
63 64 65 66

  Promise<int> a = 123;
  bool done = false;

67
  Promise<int> promise = a.then([&](int ai) { done = true; return ai + 321; });
68
  EXPECT_FALSE(done);
69
  EXPECT_EQ(444, promise.wait(waitScope));
70 71 72 73
  EXPECT_TRUE(done);
}

TEST(Async, ThereVoid) {
74
  EventLoop loop;
75
  WaitScope waitScope(loop);
76 77 78 79

  Promise<int> a = 123;
  int value = 0;

80
  Promise<void> promise = a.then([&](int ai) { value = ai; });
81
  EXPECT_EQ(0, value);
82
  promise.wait(waitScope);
83 84 85 86
  EXPECT_EQ(123, value);
}

TEST(Async, Exception) {
87
  EventLoop loop;
88
  WaitScope waitScope(loop);
89

90 91
  Promise<int> promise = evalLater(
      [&]() -> int { KJ_FAIL_ASSERT("foo") { return 123; } });
92 93
  EXPECT_TRUE(kj::runCatchingExceptions([&]() {
    // wait() only returns when compiling with -fno-exceptions.
94
    EXPECT_EQ(123, promise.wait(waitScope));
95 96 97 98
  }) != nullptr);
}

TEST(Async, HandleException) {
99
  EventLoop loop;
100
  WaitScope waitScope(loop);
101

102 103
  Promise<int> promise = evalLater(
      [&]() -> int { KJ_FAIL_ASSERT("foo") { return 123; } });
104 105
  int line = __LINE__ - 1;

106
  promise = promise.then(
107 108 109
      [](int i) { return i + 1; },
      [&](Exception&& e) { EXPECT_EQ(line, e.getLine()); return 345; });

110
  EXPECT_EQ(345, promise.wait(waitScope));
111 112 113
}

TEST(Async, PropagateException) {
114
  EventLoop loop;
115
  WaitScope waitScope(loop);
116

117 118
  Promise<int> promise = evalLater(
      [&]() -> int { KJ_FAIL_ASSERT("foo") { return 123; } });
119 120
  int line = __LINE__ - 1;

121
  promise = promise.then([](int i) { return i + 1; });
122

123
  promise = promise.then(
124 125 126
      [](int i) { return i + 2; },
      [&](Exception&& e) { EXPECT_EQ(line, e.getLine()); return 345; });

127
  EXPECT_EQ(345, promise.wait(waitScope));
128 129 130
}

TEST(Async, PropagateExceptionTypeChange) {
131
  EventLoop loop;
132
  WaitScope waitScope(loop);
133

134 135
  Promise<int> promise = evalLater(
      [&]() -> int { KJ_FAIL_ASSERT("foo") { return 123; } });
136 137
  int line = __LINE__ - 1;

138
  Promise<StringPtr> promise2 = promise.then([](int i) -> StringPtr { return "foo"; });
139

140
  promise2 = promise2.then(
141 142 143
      [](StringPtr s) -> StringPtr { return "bar"; },
      [&](Exception&& e) -> StringPtr { EXPECT_EQ(line, e.getLine()); return "baz"; });

144
  EXPECT_EQ("baz", promise2.wait(waitScope));
145 146 147
}

TEST(Async, Then) {
148
  EventLoop loop;
149
  WaitScope waitScope(loop);
150

151
  bool done = false;
152

153 154 155 156
  Promise<int> promise = Promise<int>(123).then([&](int i) {
    done = true;
    return i + 321;
  });
157

158
  EXPECT_FALSE(done);
159

160
  EXPECT_EQ(444, promise.wait(waitScope));
161

162
  EXPECT_TRUE(done);
163 164 165
}

TEST(Async, Chain) {
166
  EventLoop loop;
167
  WaitScope waitScope(loop);
168

169 170
  Promise<int> promise = evalLater([&]() -> int { return 123; });
  Promise<int> promise2 = evalLater([&]() -> int { return 321; });
171

172
  auto promise3 = promise.then([&](int i) {
173
    return promise2.then([i](int j) {
174 175 176
      return i + j;
    });
  });
177

178
  EXPECT_EQ(444, promise3.wait(waitScope));
179 180
}

181 182 183 184 185 186 187 188
TEST(Async, DeepChain) {
  EventLoop loop;
  WaitScope waitScope(loop);

  Promise<void> promise = NEVER_DONE;

  // Create a ridiculous chain of promises.
  for (uint i = 0; i < 1000; i++) {
189
    promise = evalLater(mvCapture(promise, [](Promise<void> promise) {
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
      return kj::mv(promise);
    }));
  }

  loop.run();

  auto trace = promise.trace();
  uint lines = 0;
  for (char c: trace) {
    lines += c == '\n';
  }

  // Chain nodes should have been collapsed such that instead of a chain of 1000 nodes, we have
  // 2-ish nodes.  We'll give a little room for implementation freedom.
  EXPECT_LT(lines, 5);
}

TEST(Async, DeepChain2) {
  EventLoop loop;
  WaitScope waitScope(loop);

  Promise<void> promise = nullptr;
  promise = evalLater([&]() {
    auto trace = promise.trace();
    uint lines = 0;
    for (char c: trace) {
      lines += c == '\n';
    }

    // Chain nodes should have been collapsed such that instead of a chain of 1000 nodes, we have
    // 2-ish nodes.  We'll give a little room for implementation freedom.
    EXPECT_LT(lines, 5);
  });

  // Create a ridiculous chain of promises.
  for (uint i = 0; i < 1000; i++) {
226
    promise = evalLater(mvCapture(promise, [](Promise<void> promise) {
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
      return kj::mv(promise);
    }));
  }

  promise.wait(waitScope);
}

Promise<void> makeChain(uint i) {
  if (i > 0) {
    return evalLater([i]() -> Promise<void> {
      return makeChain(i - 1);
    });
  } else {
    return NEVER_DONE;
  }
}

TEST(Async, DeepChain3) {
  EventLoop loop;
  WaitScope waitScope(loop);

  Promise<void> promise = makeChain(1000);

  loop.run();

  auto trace = promise.trace();
  uint lines = 0;
  for (char c: trace) {
    lines += c == '\n';
  }

  // Chain nodes should have been collapsed such that instead of a chain of 1000 nodes, we have
  // 2-ish nodes.  We'll give a little room for implementation freedom.
  EXPECT_LT(lines, 5);
}

Promise<void> makeChain2(uint i, Promise<void> promise) {
  if (i > 0) {
    return evalLater(mvCapture(promise, [i](Promise<void>&& promise) -> Promise<void> {
      return makeChain2(i - 1, kj::mv(promise));
    }));
  } else {
    return kj::mv(promise);
  }
}

TEST(Async, DeepChain4) {
  EventLoop loop;
  WaitScope waitScope(loop);

  Promise<void> promise = nullptr;
  promise = evalLater([&]() {
    auto trace = promise.trace();
    uint lines = 0;
    for (char c: trace) {
      lines += c == '\n';
    }

    // Chain nodes should have been collapsed such that instead of a chain of 1000 nodes, we have
    // 2-ish nodes.  We'll give a little room for implementation freedom.
    EXPECT_LT(lines, 5);
  });

  promise = makeChain2(1000, kj::mv(promise));

  promise.wait(waitScope);
}

295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
TEST(Async, IgnoreResult) {
  EventLoop loop;
  WaitScope waitScope(loop);

  bool done = false;

  Promise<void> promise = Promise<int>(123).then([&](int i) {
    done = true;
    return i + 321;
  }).ignoreResult();

  EXPECT_FALSE(done);

  promise.wait(waitScope);

  EXPECT_TRUE(done);
}

313
TEST(Async, SeparateFulfiller) {
314
  EventLoop loop;
315
  WaitScope waitScope(loop);
316 317 318 319 320 321 322

  auto pair = newPromiseAndFulfiller<int>();

  EXPECT_TRUE(pair.fulfiller->isWaiting());
  pair.fulfiller->fulfill(123);
  EXPECT_FALSE(pair.fulfiller->isWaiting());

323
  EXPECT_EQ(123, pair.promise.wait(waitScope));
324 325 326
}

TEST(Async, SeparateFulfillerVoid) {
327
  EventLoop loop;
328
  WaitScope waitScope(loop);
329 330 331 332 333 334 335

  auto pair = newPromiseAndFulfiller<void>();

  EXPECT_TRUE(pair.fulfiller->isWaiting());
  pair.fulfiller->fulfill();
  EXPECT_FALSE(pair.fulfiller->isWaiting());

336
  pair.promise.wait(waitScope);
337 338 339 340 341 342
}

TEST(Async, SeparateFulfillerCanceled) {
  auto pair = newPromiseAndFulfiller<void>();

  EXPECT_TRUE(pair.fulfiller->isWaiting());
343
  pair.promise = nullptr;
344 345 346
  EXPECT_FALSE(pair.fulfiller->isWaiting());
}

347
TEST(Async, SeparateFulfillerChained) {
348
  EventLoop loop;
349
  WaitScope waitScope(loop);
350

351
  auto pair = newPromiseAndFulfiller<Promise<int>>();
352 353 354 355 356 357 358 359
  auto inner = newPromiseAndFulfiller<int>();

  EXPECT_TRUE(pair.fulfiller->isWaiting());
  pair.fulfiller->fulfill(kj::mv(inner.promise));
  EXPECT_FALSE(pair.fulfiller->isWaiting());

  inner.fulfiller->fulfill(123);

360
  EXPECT_EQ(123, pair.promise.wait(waitScope));
361 362
}

363
TEST(Async, SeparateFulfillerDiscarded) {
364
  EventLoop loop;
365
  WaitScope waitScope(loop);
366 367 368 369

  auto pair = newPromiseAndFulfiller<int>();
  pair.fulfiller = nullptr;

370
  EXPECT_ANY_THROW(pair.promise.wait(waitScope));
371 372
}

373 374 375
TEST(Async, SeparateFulfillerMemoryLeak) {
  auto paf = kj::newPromiseAndFulfiller<void>();
  paf.fulfiller->fulfill();
376 377 378
}

TEST(Async, Ordering) {
379
  EventLoop loop;
380
  WaitScope waitScope(loop);
381 382 383 384

  int counter = 0;
  Promise<void> promises[6] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};

385
  promises[1] = evalLater([&]() {
386
    EXPECT_EQ(0, counter++);
Kenton Varda's avatar
Kenton Varda committed
387 388 389 390 391 392 393

    {
      // Use a promise and fulfiller so that we can fulfill the promise after waiting on it in
      // order to induce depth-first scheduling.
      auto paf = kj::newPromiseAndFulfiller<void>();
      promises[2] = paf.promise.then([&]() {
        EXPECT_EQ(1, counter++);
394
      }).eagerlyEvaluate(nullptr);
Kenton Varda's avatar
Kenton Varda committed
395 396 397 398 399 400 401 402 403
      paf.fulfiller->fulfill();
    }

    // .then() is scheduled breadth-first if the promise has already resolved, but depth-first
    // if the promise resolves later.
    promises[3] = Promise<void>(READY_NOW).then([&]() {
      EXPECT_EQ(4, counter++);
    }).then([&]() {
      EXPECT_EQ(5, counter++);
404
    }).eagerlyEvaluate(nullptr);
Kenton Varda's avatar
Kenton Varda committed
405 406 407 408 409

    {
      auto paf = kj::newPromiseAndFulfiller<void>();
      promises[4] = paf.promise.then([&]() {
        EXPECT_EQ(2, counter++);
410
      }).eagerlyEvaluate(nullptr);
Kenton Varda's avatar
Kenton Varda committed
411 412 413 414
      paf.fulfiller->fulfill();
    }

    // evalLater() is like READY_NOW.then().
415
    promises[5] = evalLater([&]() {
416
      EXPECT_EQ(6, counter++);
417 418
    }).eagerlyEvaluate(nullptr);
  }).eagerlyEvaluate(nullptr);
419

420
  promises[0] = evalLater([&]() {
421
    EXPECT_EQ(3, counter++);
422 423 424 425

    // Making this a chain should NOT cause it to preempt promises[1].  (This was a problem at one
    // point.)
    return Promise<void>(READY_NOW);
426
  }).eagerlyEvaluate(nullptr);
427

428
  for (auto i: indices(promises)) {
429
    kj::mv(promises[i]).wait(waitScope);
430 431
  }

432
  EXPECT_EQ(7, counter);
433 434
}

435
TEST(Async, Fork) {
436
  EventLoop loop;
437
  WaitScope waitScope(loop);
438

439
  Promise<int> promise = evalLater([&]() { return 123; });
440

441
  auto fork = promise.fork();
442

443 444 445
  auto branch1 = fork.addBranch().then([](int i) {
    EXPECT_EQ(123, i);
    return 456;
446
  });
447 448 449 450 451 452 453 454
  auto branch2 = fork.addBranch().then([](int i) {
    EXPECT_EQ(123, i);
    return 789;
  });

  {
    auto releaseFork = kj::mv(fork);
  }
455

456 457
  EXPECT_EQ(456, branch1.wait(waitScope));
  EXPECT_EQ(789, branch2.wait(waitScope));
458 459 460 461 462
}

struct RefcountedInt: public Refcounted {
  RefcountedInt(int i): i(i) {}
  int i;
463
  Own<RefcountedInt> addRef() { return kj::addRef(*this); }
464 465 466
};

TEST(Async, ForkRef) {
467
  EventLoop loop;
468
  WaitScope waitScope(loop);
469

470 471 472
  Promise<Own<RefcountedInt>> promise = evalLater([&]() {
    return refcounted<RefcountedInt>(123);
  });
473

474
  auto fork = promise.fork();
475

476
  auto branch1 = fork.addBranch().then([](Own<RefcountedInt>&& i) {
477 478 479
    EXPECT_EQ(123, i->i);
    return 456;
  });
480
  auto branch2 = fork.addBranch().then([](Own<RefcountedInt>&& i) {
481 482
    EXPECT_EQ(123, i->i);
    return 789;
483 484
  });

485 486 487 488
  {
    auto releaseFork = kj::mv(fork);
  }

489 490
  EXPECT_EQ(456, branch1.wait(waitScope));
  EXPECT_EQ(789, branch2.wait(waitScope));
491 492
}

493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
TEST(Async, Split) {
  EventLoop loop;
  WaitScope waitScope(loop);

  Promise<Tuple<int, String, Promise<int>>> promise = evalLater([&]() {
    return kj::tuple(123, str("foo"), Promise<int>(321));
  });

  Tuple<Promise<int>, Promise<String>, Promise<int>> split = promise.split();

  EXPECT_EQ(123, get<0>(split).wait(waitScope));
  EXPECT_EQ("foo", get<1>(split).wait(waitScope));
  EXPECT_EQ(321, get<2>(split).wait(waitScope));
}

508 509
TEST(Async, ExclusiveJoin) {
  {
510
    EventLoop loop;
511
    WaitScope waitScope(loop);
512

513
    auto left = evalLater([&]() { return 123; });
514 515
    auto right = newPromiseAndFulfiller<int>();  // never fulfilled

516
    EXPECT_EQ(123, left.exclusiveJoin(kj::mv(right.promise)).wait(waitScope));
517 518 519
  }

  {
520
    EventLoop loop;
521
    WaitScope waitScope(loop);
522 523

    auto left = newPromiseAndFulfiller<int>();  // never fulfilled
524
    auto right = evalLater([&]() { return 123; });
525

526
    EXPECT_EQ(123, left.promise.exclusiveJoin(kj::mv(right)).wait(waitScope));
527 528 529
  }

  {
530
    EventLoop loop;
531
    WaitScope waitScope(loop);
532

533 534
    auto left = evalLater([&]() { return 123; });
    auto right = evalLater([&]() { return 456; });
535

536
    EXPECT_EQ(123, left.exclusiveJoin(kj::mv(right)).wait(waitScope));
537 538 539
  }

  {
540
    EventLoop loop;
541
    WaitScope waitScope(loop);
542

543
    auto left = evalLater([&]() { return 123; });
544
    auto right = evalLater([&]() { return 456; }).eagerlyEvaluate(nullptr);
545

546
    EXPECT_EQ(456, left.exclusiveJoin(kj::mv(right)).wait(waitScope));
547 548 549
  }
}

550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568
TEST(Async, ArrayJoin) {
  EventLoop loop;
  WaitScope waitScope(loop);

  auto builder = heapArrayBuilder<Promise<int>>(3);
  builder.add(123);
  builder.add(456);
  builder.add(789);

  Promise<Array<int>> promise = joinPromises(builder.finish());

  auto result = promise.wait(waitScope);

  ASSERT_EQ(3u, result.size());
  EXPECT_EQ(123, result[0]);
  EXPECT_EQ(456, result[1]);
  EXPECT_EQ(789, result[2]);
}

569 570 571 572 573 574 575 576 577 578 579 580 581 582
TEST(Async, ArrayJoinVoid) {
  EventLoop loop;
  WaitScope waitScope(loop);

  auto builder = heapArrayBuilder<Promise<void>>(3);
  builder.add(READY_NOW);
  builder.add(READY_NOW);
  builder.add(READY_NOW);

  Promise<void> promise = joinPromises(builder.finish());

  promise.wait(waitScope);
}

583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
TEST(Async, Canceler) {
  EventLoop loop;
  WaitScope waitScope(loop);
  Canceler canceler;

  auto never = canceler.wrap(kj::Promise<void>(kj::NEVER_DONE));
  auto now = canceler.wrap(kj::Promise<void>(kj::READY_NOW));
  auto neverI = canceler.wrap(kj::Promise<void>(kj::NEVER_DONE).then([]() { return 123u; }));
  auto nowI = canceler.wrap(kj::Promise<uint>(123u));

  KJ_EXPECT(!never.poll(waitScope));
  KJ_EXPECT(now.poll(waitScope));
  KJ_EXPECT(!neverI.poll(waitScope));
  KJ_EXPECT(nowI.poll(waitScope));

  canceler.cancel("foobar");

600
  KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar", never.wait(waitScope));
601 602 603 604 605
  now.wait(waitScope);
  KJ_EXPECT_THROW_MESSAGE("foobar", neverI.wait(waitScope));
  KJ_EXPECT(nowI.wait(waitScope) == 123u);
}

606 607 608 609 610 611 612 613 614 615
class ErrorHandlerImpl: public TaskSet::ErrorHandler {
public:
  uint exceptionCount = 0;
  void taskFailed(kj::Exception&& exception) override {
    EXPECT_TRUE(exception.getDescription().endsWith("example TaskSet failure"));
    ++exceptionCount;
  }
};

TEST(Async, TaskSet) {
616
  EventLoop loop;
617
  WaitScope waitScope(loop);
618
  ErrorHandlerImpl errorHandler;
619
  TaskSet tasks(errorHandler);
620 621 622

  int counter = 0;

623
  tasks.add(evalLater([&]() {
624 625
    EXPECT_EQ(0, counter++);
  }));
626
  tasks.add(evalLater([&]() {
627 628 629
    EXPECT_EQ(1, counter++);
    KJ_FAIL_ASSERT("example TaskSet failure") { break; }
  }));
630
  tasks.add(evalLater([&]() {
631 632 633
    EXPECT_EQ(2, counter++);
  }));

634
  auto ignore KJ_UNUSED = evalLater([&]() {
635
    KJ_FAIL_EXPECT("Promise without waiter shouldn't execute.");
636 637
  });

638
  evalLater([&]() {
639
    EXPECT_EQ(3, counter++);
640
  }).wait(waitScope);
641 642

  EXPECT_EQ(4, counter);
643
  EXPECT_EQ(1u, errorHandler.exceptionCount);
644 645
}

646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
TEST(Async, TaskSetOnEmpty) {
  EventLoop loop;
  WaitScope waitScope(loop);
  ErrorHandlerImpl errorHandler;
  TaskSet tasks(errorHandler);

  KJ_EXPECT(tasks.isEmpty());

  auto paf = newPromiseAndFulfiller<void>();
  tasks.add(kj::mv(paf.promise));
  tasks.add(evalLater([]() {}));

  KJ_EXPECT(!tasks.isEmpty());

  auto promise = tasks.onEmpty();
  KJ_EXPECT(!promise.poll(waitScope));
  KJ_EXPECT(!tasks.isEmpty());

  paf.fulfiller->fulfill();
  KJ_ASSERT(promise.poll(waitScope));
  KJ_EXPECT(tasks.isEmpty());
  promise.wait(waitScope);
}

670 671 672 673 674 675 676 677 678 679 680 681
class DestructorDetector {
public:
  DestructorDetector(bool& setTrue): setTrue(setTrue) {}
  ~DestructorDetector() { setTrue = true; }

private:
  bool& setTrue;
};

TEST(Async, Attach) {
  bool destroyed = false;

682
  EventLoop loop;
683
  WaitScope waitScope(loop);
684

685
  Promise<int> promise = evalLater([&]() {
686 687
    EXPECT_FALSE(destroyed);
    return 123;
688
  }).attach(kj::heap<DestructorDetector>(destroyed));
689

690
  promise = promise.then([&](int i) {
691 692 693 694 695
    EXPECT_TRUE(destroyed);
    return i + 321;
  });

  EXPECT_FALSE(destroyed);
696
  EXPECT_EQ(444, promise.wait(waitScope));
697 698 699 700 701 702
  EXPECT_TRUE(destroyed);
}

TEST(Async, EagerlyEvaluate) {
  bool called = false;

703
  EventLoop loop;
704
  WaitScope waitScope(loop);
705

706 707 708
  Promise<void> promise = Promise<void>(READY_NOW).then([&]() {
    called = true;
  });
709
  evalLater([]() {}).wait(waitScope);
710 711 712

  EXPECT_FALSE(called);

713
  promise = promise.eagerlyEvaluate(nullptr);
714

715
  evalLater([]() {}).wait(waitScope);
716 717 718 719

  EXPECT_TRUE(called);
}

720
TEST(Async, Detach) {
721
  EventLoop loop;
722
  WaitScope waitScope(loop);
723 724 725 726 727

  bool ran1 = false;
  bool ran2 = false;
  bool ran3 = false;

728 729 730 731
  {
    // let returned promise be destroyed (canceled)
    auto ignore KJ_UNUSED = evalLater([&]() { ran1 = true; });
  }
732
  evalLater([&]() { ran2 = true; }).detach([](kj::Exception&&) { ADD_FAILURE(); });
733
  evalLater([]() { KJ_FAIL_ASSERT("foo"){break;} }).detach([&](kj::Exception&& e) { ran3 = true; });
734 735 736 737 738

  EXPECT_FALSE(ran1);
  EXPECT_FALSE(ran2);
  EXPECT_FALSE(ran3);

739
  evalLater([]() {}).wait(waitScope);
740 741 742 743 744 745

  EXPECT_FALSE(ran1);
  EXPECT_TRUE(ran2);
  EXPECT_TRUE(ran3);
}

746 747 748 749 750
class DummyEventPort: public EventPort {
public:
  bool runnable = false;
  int callCount = 0;

751 752
  bool wait() override { KJ_FAIL_ASSERT("Nothing to wait for."); }
  bool poll() override { return false; }
753
  void setRunnable(bool runnable) override {
754 755 756 757 758 759 760 761
    this->runnable = runnable;
    ++callCount;
  }
};

TEST(Async, SetRunnable) {
  DummyEventPort port;
  EventLoop loop(port);
762
  WaitScope waitScope(loop);
763 764 765 766 767

  EXPECT_FALSE(port.runnable);
  EXPECT_EQ(0, port.callCount);

  {
768
    auto promise = evalLater([]() {}).eagerlyEvaluate(nullptr);
769 770 771 772 773 774

    EXPECT_TRUE(port.runnable);
    loop.run(1);
    EXPECT_FALSE(port.runnable);
    EXPECT_EQ(2, port.callCount);

775
    promise.wait(waitScope);
776 777 778 779 780 781
    EXPECT_FALSE(port.runnable);
    EXPECT_EQ(4, port.callCount);
  }

  {
    auto paf = newPromiseAndFulfiller<void>();
782
    auto promise = paf.promise.then([]() {}).eagerlyEvaluate(nullptr);
783 784
    EXPECT_FALSE(port.runnable);

785
    auto promise2 = evalLater([]() {}).eagerlyEvaluate(nullptr);
786 787 788 789 790 791 792 793
    paf.fulfiller->fulfill();

    EXPECT_TRUE(port.runnable);
    loop.run(1);
    EXPECT_TRUE(port.runnable);
    loop.run(10);
    EXPECT_FALSE(port.runnable);

794
    promise.wait(waitScope);
795 796 797 798 799 800
    EXPECT_FALSE(port.runnable);

    EXPECT_EQ(8, port.callCount);
  }
}

801 802 803 804 805 806 807 808 809 810 811
TEST(Async, Poll) {
  EventLoop loop;
  WaitScope waitScope(loop);

  auto paf = newPromiseAndFulfiller<void>();
  KJ_ASSERT(!paf.promise.poll(waitScope));
  paf.fulfiller->fulfill();
  KJ_ASSERT(paf.promise.poll(waitScope));
  paf.promise.wait(waitScope);
}

812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
KJ_TEST("exclusiveJoin both events complete simultaneously") {
  // Previously, if both branches of an exclusiveJoin() completed simultaneously, then the parent
  // event could be armed twice. This is an error, but the exact results of this error depend on
  // the parent PromiseNode type. One case where it matters is ArrayJoinPromiseNode, which counts
  // events and decides it is done when it has received exactly the number of events expected.

  EventLoop loop;
  WaitScope waitScope(loop);

  auto builder = kj::heapArrayBuilder<kj::Promise<uint>>(2);
  builder.add(kj::Promise<uint>(123).exclusiveJoin(kj::Promise<uint>(456)));
  builder.add(kj::NEVER_DONE);
  auto joined = kj::joinPromises(builder.finish());

  KJ_EXPECT(!joined.poll(waitScope));
}

829 830
}  // namespace
}  // namespace kj