BatonTestHelpers.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * Copyright 2016-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <folly/portability/GTest.h>
  18. #include <folly/synchronization/Baton.h>
  19. #include <folly/test/DeterministicSchedule.h>
  20. namespace folly {
  21. namespace test {
  22. typedef DeterministicSchedule DSched;
  23. template <bool MayBlock, template <typename> class Atom>
  24. void run_basic_test() {
  25. Baton<MayBlock, Atom> b;
  26. b.post();
  27. b.wait();
  28. }
  29. template <bool MayBlock, template <typename> class Atom>
  30. void run_pingpong_test(int numRounds) {
  31. using B = Baton<MayBlock, Atom>;
  32. B batons[17];
  33. B& a = batons[0];
  34. B& b = batons[16]; // to get it on a different cache line
  35. auto thr = DSched::thread([&] {
  36. for (int i = 0; i < numRounds; ++i) {
  37. a.wait();
  38. a.reset();
  39. b.post();
  40. }
  41. });
  42. for (int i = 0; i < numRounds; ++i) {
  43. a.post();
  44. b.wait();
  45. b.reset();
  46. }
  47. DSched::join(thr);
  48. }
  49. template <bool MayBlock, template <typename> class Atom, typename Clock>
  50. void run_basic_timed_wait_tests() {
  51. Baton<MayBlock, Atom> b;
  52. b.post();
  53. // tests if early delivery works fine
  54. EXPECT_TRUE(b.try_wait_until(Clock::now()));
  55. }
  56. template <bool MayBlock, template <typename> class Atom, typename Clock>
  57. void run_timed_wait_tmo_tests() {
  58. Baton<MayBlock, Atom> b;
  59. auto thr = DSched::thread([&] {
  60. bool rv = b.try_wait_until(Clock::now() + std::chrono::milliseconds(1));
  61. // main thread is guaranteed to not post until timeout occurs
  62. EXPECT_FALSE(rv);
  63. });
  64. DSched::join(thr);
  65. }
  66. template <bool MayBlock, template <typename> class Atom, typename Clock>
  67. void run_timed_wait_regular_test() {
  68. Baton<MayBlock, Atom> b;
  69. auto thr = DSched::thread([&] {
  70. // To wait forever we'd like to use time_point<Clock>::max, but
  71. // std::condition_variable does math to convert the timeout to
  72. // system_clock without handling overflow.
  73. auto farFuture = Clock::now() + std::chrono::hours(1000);
  74. bool rv = b.try_wait_until(farFuture);
  75. if (!std::is_same<Atom<int>, DeterministicAtomic<int>>::value) {
  76. // DeterministicAtomic ignores actual times, so doesn't guarantee
  77. // a lack of timeout
  78. EXPECT_TRUE(rv);
  79. }
  80. });
  81. if (!std::is_same<Atom<int>, DeterministicAtomic<int>>::value) {
  82. // If we are using std::atomic (or EmulatedFutexAtomic) then
  83. // a sleep here guarantees to a large extent that 'thr' will
  84. // execute wait before we post it, thus testing late delivery. For
  85. // DeterministicAtomic, we just rely on DeterministicSchedule to do
  86. // the scheduling. The test won't fail if we lose the race, we just
  87. // don't get coverage.
  88. std::this_thread::sleep_for(std::chrono::milliseconds(2));
  89. }
  90. b.post();
  91. DSched::join(thr);
  92. }
  93. template <bool MayBlock, template <typename> class Atom>
  94. void run_try_wait_tests() {
  95. Baton<MayBlock, Atom> b;
  96. EXPECT_FALSE(b.ready());
  97. EXPECT_FALSE(b.try_wait());
  98. b.post();
  99. EXPECT_TRUE(b.ready());
  100. EXPECT_TRUE(b.try_wait());
  101. }
  102. } // namespace test
  103. } // namespace folly