worker_thread_test.cc 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright 2015 The Crashpad Authors. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "util/thread/worker_thread.h"
  15. #include "gtest/gtest.h"
  16. #include "util/misc/clock.h"
  17. #include "util/synchronization/semaphore.h"
  18. namespace crashpad {
  19. namespace test {
  20. namespace {
  21. constexpr uint64_t kNanosecondsPerSecond = static_cast<uint64_t>(1E9);
  22. class WorkDelegate : public WorkerThread::Delegate {
  23. public:
  24. WorkDelegate() {}
  25. ~WorkDelegate() {}
  26. void DoWork(const WorkerThread* thread) override {
  27. if (work_count_ < waiting_for_count_) {
  28. if (++work_count_ == waiting_for_count_) {
  29. semaphore_.Signal();
  30. }
  31. }
  32. }
  33. void SetDesiredWorkCount(int times) {
  34. waiting_for_count_ = times;
  35. }
  36. //! \brief Suspends the calling thread until the DoWork() has been called
  37. //! the number of times specified by SetDesiredWorkCount().
  38. void WaitForWorkCount() {
  39. semaphore_.Wait();
  40. }
  41. int work_count() const { return work_count_; }
  42. private:
  43. Semaphore semaphore_{0};
  44. int work_count_ = 0;
  45. int waiting_for_count_ = -1;
  46. DISALLOW_COPY_AND_ASSIGN(WorkDelegate);
  47. };
  48. TEST(WorkerThread, DoWork) {
  49. WorkDelegate delegate;
  50. WorkerThread thread(0.05, &delegate);
  51. uint64_t start = ClockMonotonicNanoseconds();
  52. delegate.SetDesiredWorkCount(2);
  53. thread.Start(0);
  54. EXPECT_TRUE(thread.is_running());
  55. delegate.WaitForWorkCount();
  56. thread.Stop();
  57. EXPECT_FALSE(thread.is_running());
  58. EXPECT_GE(1 * kNanosecondsPerSecond, ClockMonotonicNanoseconds() - start);
  59. }
  60. TEST(WorkerThread, StopBeforeDoWork) {
  61. WorkDelegate delegate;
  62. WorkerThread thread(1, &delegate);
  63. thread.Start(15);
  64. thread.Stop();
  65. EXPECT_EQ(delegate.work_count(), 0);
  66. }
  67. TEST(WorkerThread, Restart) {
  68. WorkDelegate delegate;
  69. WorkerThread thread(0.05, &delegate);
  70. delegate.SetDesiredWorkCount(1);
  71. thread.Start(0);
  72. EXPECT_TRUE(thread.is_running());
  73. delegate.WaitForWorkCount();
  74. thread.Stop();
  75. ASSERT_FALSE(thread.is_running());
  76. delegate.SetDesiredWorkCount(2);
  77. thread.Start(0);
  78. delegate.WaitForWorkCount();
  79. thread.Stop();
  80. ASSERT_FALSE(thread.is_running());
  81. }
  82. TEST(WorkerThread, DoWorkNow) {
  83. WorkDelegate delegate;
  84. WorkerThread thread(100, &delegate);
  85. uint64_t start = ClockMonotonicNanoseconds();
  86. delegate.SetDesiredWorkCount(1);
  87. thread.Start(0);
  88. EXPECT_TRUE(thread.is_running());
  89. delegate.WaitForWorkCount();
  90. EXPECT_EQ(delegate.work_count(), 1);
  91. delegate.SetDesiredWorkCount(2);
  92. thread.DoWorkNow();
  93. delegate.WaitForWorkCount();
  94. thread.Stop();
  95. EXPECT_EQ(delegate.work_count(), 2);
  96. EXPECT_GE(100 * kNanosecondsPerSecond, ClockMonotonicNanoseconds() - start);
  97. }
  98. TEST(WorkerThread, DoWorkNowAtStart) {
  99. WorkDelegate delegate;
  100. WorkerThread thread(100, &delegate);
  101. uint64_t start = ClockMonotonicNanoseconds();
  102. delegate.SetDesiredWorkCount(1);
  103. thread.Start(100);
  104. EXPECT_TRUE(thread.is_running());
  105. thread.DoWorkNow();
  106. delegate.WaitForWorkCount();
  107. EXPECT_EQ(delegate.work_count(), 1);
  108. EXPECT_GE(100 * kNanosecondsPerSecond, ClockMonotonicNanoseconds() - start);
  109. thread.Stop();
  110. EXPECT_FALSE(thread.is_running());
  111. }
  112. } // namespace
  113. } // namespace test
  114. } // namespace crashpad