Chromium Code Reviews| 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 |