Index: test/base-unittests/platform/semaphore-unittest.cc |
diff --git a/test/base-unittests/platform/semaphore-unittest.cc b/test/base-unittests/platform/semaphore-unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..836e7192603367409604f37a401c11c6b8a7cc5a |
--- /dev/null |
+++ b/test/base-unittests/platform/semaphore-unittest.cc |
@@ -0,0 +1,145 @@ |
+// Copyright 2014 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <cstring> |
+ |
+#include "src/base/platform/platform.h" |
+#include "src/base/platform/semaphore.h" |
+#include "src/base/platform/time.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace v8 { |
+namespace base { |
+ |
+namespace { |
+ |
+static const char kAlphabet[] = "XKOAD"; |
+static const size_t kAlphabetSize = sizeof(kAlphabet) - 1; |
+static const size_t kBufferSize = 987; // GCD(buffer size, alphabet size) = 1 |
+static const size_t kDataSize = kBufferSize * kAlphabetSize * 10; |
+ |
+ |
+class ProducerThread V8_FINAL : public Thread { |
+ public: |
+ ProducerThread(char* buffer, Semaphore* free_space, Semaphore* used_space) |
+ : Thread(Options("ProducerThread")), |
+ buffer_(buffer), |
+ free_space_(free_space), |
+ used_space_(used_space) {} |
+ virtual ~ProducerThread() {} |
+ |
+ virtual void Run() V8_OVERRIDE { |
+ for (size_t n = 0; n < kDataSize; ++n) { |
+ free_space_->Wait(); |
+ buffer_[n % kBufferSize] = kAlphabet[n % kAlphabetSize]; |
+ used_space_->Signal(); |
+ } |
+ } |
+ |
+ private: |
+ char* buffer_; |
+ Semaphore* const free_space_; |
+ Semaphore* const used_space_; |
+}; |
+ |
+ |
+class ConsumerThread V8_FINAL : public Thread { |
+ public: |
+ ConsumerThread(const char* buffer, Semaphore* free_space, |
+ Semaphore* used_space) |
+ : Thread(Options("ConsumerThread")), |
+ buffer_(buffer), |
+ free_space_(free_space), |
+ used_space_(used_space) {} |
+ virtual ~ConsumerThread() {} |
+ |
+ virtual void Run() V8_OVERRIDE { |
+ for (size_t n = 0; n < kDataSize; ++n) { |
+ used_space_->Wait(); |
+ EXPECT_EQ(kAlphabet[n % kAlphabetSize], buffer_[n % kBufferSize]); |
+ free_space_->Signal(); |
+ } |
+ } |
+ |
+ private: |
+ const char* buffer_; |
+ Semaphore* const free_space_; |
+ Semaphore* const used_space_; |
+}; |
+ |
+ |
+class WaitAndSignalThread V8_FINAL : public Thread { |
+ public: |
+ explicit WaitAndSignalThread(Semaphore* semaphore) |
+ : Thread(Options("WaitAndSignalThread")), semaphore_(semaphore) {} |
+ virtual ~WaitAndSignalThread() {} |
+ |
+ virtual void Run() V8_OVERRIDE { |
+ for (int n = 0; n < 100; ++n) { |
+ semaphore_->Wait(); |
+ ASSERT_FALSE(semaphore_->WaitFor(TimeDelta::FromMicroseconds(1))); |
+ semaphore_->Signal(); |
+ } |
+ } |
+ |
+ private: |
+ Semaphore* const semaphore_; |
+}; |
+ |
+} // namespace |
+ |
+ |
+TEST(Semaphore, ProducerConsumer) { |
+ char buffer[kBufferSize]; |
+ std::memset(buffer, 0, sizeof(buffer)); |
+ Semaphore free_space(kBufferSize); |
+ Semaphore used_space(0); |
+ ProducerThread producer_thread(buffer, &free_space, &used_space); |
+ ConsumerThread consumer_thread(buffer, &free_space, &used_space); |
+ producer_thread.Start(); |
+ consumer_thread.Start(); |
+ producer_thread.Join(); |
+ consumer_thread.Join(); |
+} |
+ |
+ |
+TEST(Semaphore, WaitAndSignal) { |
+ Semaphore semaphore(0); |
+ WaitAndSignalThread t1(&semaphore); |
+ WaitAndSignalThread t2(&semaphore); |
+ |
+ t1.Start(); |
+ t2.Start(); |
+ |
+ // Make something available. |
+ semaphore.Signal(); |
+ |
+ t1.Join(); |
+ t2.Join(); |
+ |
+ semaphore.Wait(); |
+ |
+ EXPECT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1))); |
Michael Achenbach
2014/08/22 08:21:07
What's the difference to ASSERT_FALSE above?
Benedikt Meurer
2014/08/22 08:51:58
EXPECT_* just record a failure, while ASSERT_* ter
|
+} |
+ |
+ |
+TEST(Semaphore, WaitFor) { |
+ Semaphore semaphore(0); |
+ |
+ // Semaphore not signalled - timeout. |
+ ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0))); |
+ ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100))); |
+ ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000))); |
Michael Achenbach
2014/08/22 08:21:07
Do we really need the last one? What could make th
|
+ |
+ // Semaphore signalled - no timeout. |
+ semaphore.Signal(); |
+ ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0))); |
+ semaphore.Signal(); |
+ ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100))); |
+ semaphore.Signal(); |
+ ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000))); |
+} |
+ |
+} // namespace base |
+} // namespace v8 |