Reland "Explicitly wrap main thread in test_main.cc."

This is a reland of 711a31aead9007e42dd73c302c8ec40f9e931619

Changes since original landing:

Rename methods only used by tests, mainly via FakeClock,

  MessageQueueManager::ProcessAllMessageQueues
     --> ProcessAllMessageQueuesForTesting

  MessageQueue::IsProcessingMessages
     --> IsProcessingMessagesForTesting

Fix the handling of null rtc::Thread::Current() in
ProcessAllMessageQueuesInternal().

Add override Thread::IsProcessingMessagesForTesting() to return false
for the wrapped main thread, unless it's also the current thread. In
tests, the main thread is typically not processing any messages,
but blocked in an Event::Wait().

Original change's description:
> Explicitly wrap main thread in test_main.cc.
>
> Bug: webrtc:9714
> Change-Id: I6ee234f9a0b88b3656a683f2455c3e4b2acf0d54
> Reviewed-on: https://webrtc-review.googlesource.com/97683
> Reviewed-by: Tommi <tommi@webrtc.org>
> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
> Commit-Queue: Niels Moller <nisse@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#24560}

Bug: webrtc:9714
Change-Id: I6f022d46aaf1e28f86f09f2d68c1803b69770126
Reviewed-on: https://webrtc-review.googlesource.com/98060
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Tommi <tommi@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24596}
This commit is contained in:
Niels Möller 2018-09-06 08:42:44 +02:00 committed by Commit Bot
parent bb081a62dc
commit 8909a63aca
12 changed files with 45 additions and 22 deletions

View File

@ -858,7 +858,7 @@ TEST_F(AudioDeviceTest, testInterruptedAudioSession) {
[session notifyDidBeginInterruption];
// Wait for notification to propagate.
rtc::MessageQueueManager::ProcessAllMessageQueues();
rtc::MessageQueueManager::ProcessAllMessageQueuesForTesting();
EXPECT_TRUE(audio_device->is_interrupted_);
// Force it for testing.
@ -869,7 +869,7 @@ TEST_F(AudioDeviceTest, testInterruptedAudioSession) {
[session notifyDidEndInterruptionWithShouldResumeSession:YES];
// Wait for notification to propagate.
rtc::MessageQueueManager::ProcessAllMessageQueues();
rtc::MessageQueueManager::ProcessAllMessageQueuesForTesting();
EXPECT_TRUE(audio_device->is_interrupted_);
audio_device->Init();

View File

@ -28,7 +28,7 @@ void FakeClock::SetTimeNanos(int64_t nanos) {
}
// If message queues are waiting in a socket select() with a timeout provided
// by the OS, they should wake up and dispatch all messages that are ready.
MessageQueueManager::ProcessAllMessageQueues();
MessageQueueManager::ProcessAllMessageQueuesForTesting();
}
void FakeClock::AdvanceTime(webrtc::TimeDelta delta) {
@ -36,7 +36,7 @@ void FakeClock::AdvanceTime(webrtc::TimeDelta delta) {
CritScope cs(&lock_);
time_ += delta.ns();
}
MessageQueueManager::ProcessAllMessageQueues();
MessageQueueManager::ProcessAllMessageQueuesForTesting();
}
ScopedFakeClock::ScopedFakeClock() {

View File

@ -124,7 +124,7 @@ void MessageQueueManager::ClearInternal(MessageHandler* handler) {
}
}
void MessageQueueManager::ProcessAllMessageQueues() {
void MessageQueueManager::ProcessAllMessageQueuesForTesting() {
if (!instance_) {
return;
}
@ -153,7 +153,7 @@ void MessageQueueManager::ProcessAllMessageQueuesInternal() {
{
MarkProcessingCritScope cs(&crit_, &processing_);
for (MessageQueue* queue : message_queues_) {
if (!queue->IsProcessingMessages()) {
if (!queue->IsProcessingMessagesForTesting()) {
// If the queue is not processing messages, it can
// be ignored. If we tried to post a message to it, it would be dropped
// or ignored.
@ -163,11 +163,15 @@ void MessageQueueManager::ProcessAllMessageQueuesInternal() {
new ScopedIncrement(&queues_not_done));
}
}
// Note: One of the message queues may have been on this thread, which is why
// we can't synchronously wait for queues_not_done to go to 0; we need to
// process messages as well.
rtc::Thread* current = rtc::Thread::Current();
// Note: One of the message queues may have been on this thread, which is
// why we can't synchronously wait for queues_not_done to go to 0; we need
// to process messages as well.
while (AtomicOps::AcquireLoad(&queues_not_done) > 0) {
rtc::Thread::Current()->ProcessMessages(0);
if (current) {
current->ProcessMessages(0);
}
}
}
@ -245,7 +249,7 @@ bool MessageQueue::IsQuitting() {
return AtomicOps::AcquireLoad(&stop_) != 0;
}
bool MessageQueue::IsProcessingMessages() {
bool MessageQueue::IsProcessingMessagesForTesting() {
return !IsQuitting();
}

View File

@ -49,10 +49,13 @@ class MessageQueueManager {
// MessageQueueManager instance when necessary.
static bool IsInitialized();
// Mainly for testing purposes, for use with a simulated clock.
// TODO(nisse): Delete alias, as soon as downstream code is updated.
static void ProcessAllMessageQueues() { ProcessAllMessageQueuesForTesting(); }
// For testing purposes, for use with a simulated clock.
// Ensures that all message queues have processed delayed messages
// up until the current point in time.
static void ProcessAllMessageQueues();
static void ProcessAllMessageQueuesForTesting();
private:
static MessageQueueManager* Instance();
@ -226,7 +229,7 @@ class MessageQueue {
// Not all message queues actually process messages (such as SignalThread).
// In those cases, it's important to know, before posting, that it won't be
// Processed. Normally, this would be true until IsQuitting() is true.
virtual bool IsProcessingMessages();
virtual bool IsProcessingMessagesForTesting();
// Get() will process I/O until:
// 1) A message is available (returns true)

View File

@ -182,7 +182,7 @@ TEST(MessageQueueManager, ProcessAllMessageQueues) {
b->PostDelayed(RTC_FROM_HERE, 0, &incrementer);
rtc::Thread::Current()->Post(RTC_FROM_HERE, &event_signaler);
MessageQueueManager::ProcessAllMessageQueues();
MessageQueueManager::ProcessAllMessageQueuesForTesting();
EXPECT_EQ(4, AtomicOps::AcquireLoad(&messages_processed));
}
@ -191,7 +191,7 @@ TEST(MessageQueueManager, ProcessAllMessageQueuesWithQuittingThread) {
auto t = Thread::CreateWithSocketServer();
t->Start();
t->Quit();
MessageQueueManager::ProcessAllMessageQueues();
MessageQueueManager::ProcessAllMessageQueuesForTesting();
}
// Test that ProcessAllMessageQueues doesn't hang if a queue clears its
@ -218,7 +218,7 @@ TEST(MessageQueueManager, ProcessAllMessageQueuesWithClearedQueue) {
// Post messages (both delayed and non delayed) to both threads.
t->Post(RTC_FROM_HERE, &clearer);
rtc::Thread::Current()->Post(RTC_FROM_HERE, &event_signaler);
MessageQueueManager::ProcessAllMessageQueues();
MessageQueueManager::ProcessAllMessageQueuesForTesting();
}
class RefCountedHandler : public MessageHandler, public rtc::RefCountInterface {

View File

@ -151,7 +151,7 @@ void SignalThread::OnMainThreadDestroyed() {
main_ = nullptr;
}
bool SignalThread::Worker::IsProcessingMessages() {
bool SignalThread::Worker::IsProcessingMessagesForTesting() {
return false;
}

View File

@ -105,7 +105,7 @@ class SignalThread : public sigslot::has_slots<>, protected MessageHandler {
explicit Worker(SignalThread* parent);
~Worker() override;
void Run() override;
bool IsProcessingMessages() override;
bool IsProcessingMessagesForTesting() override;
private:
SignalThread* parent_;

View File

@ -451,6 +451,11 @@ void Thread::InvokeInternal(const Location& posted_from,
Send(posted_from, handler);
}
bool Thread::IsProcessingMessagesForTesting() {
return (owned_ || IsCurrent()) &&
MessageQueue::IsProcessingMessagesForTesting();
}
void Thread::Clear(MessageHandler* phandler,
uint32_t id,
MessageList* removed) {

View File

@ -189,6 +189,7 @@ class RTC_LOCKABLE Thread : public MessageQueue {
}
// From MessageQueue
bool IsProcessingMessagesForTesting() override;
void Clear(MessageHandler* phandler,
uint32_t id = MQID_ANY,
MessageList* removed = nullptr) override;

View File

@ -93,7 +93,7 @@
[self.audioSession notifyDidBeginInterruption];
// Wait for notification to propagate.
rtc::MessageQueueManager::ProcessAllMessageQueues();
rtc::MessageQueueManager::ProcessAllMessageQueuesForTesting();
XCTAssertTrue(_audio_device->IsInterrupted());
// Force it for testing.
@ -101,7 +101,7 @@
[self.audioSession notifyDidEndInterruptionWithShouldResumeSession:YES];
// Wait for notification to propagate.
rtc::MessageQueueManager::ProcessAllMessageQueues();
rtc::MessageQueueManager::ProcessAllMessageQueuesForTesting();
XCTAssertTrue(_audio_device->IsInterrupted());
_audio_device->Init();

View File

@ -209,7 +209,7 @@ if (rtc_include_tests) {
":field_trial",
":fileutils",
":perf_test",
"../rtc_base:rtc_base_approved",
"../rtc_base:rtc_base",
"../system_wrappers:field_trial_default",
"../system_wrappers:metrics_default",
"../system_wrappers:runtime_enabled_features_default",

View File

@ -10,6 +10,7 @@
#include "rtc_base/flags.h"
#include "rtc_base/logging.h"
#include "rtc_base/thread.h"
#include "system_wrappers/include/field_trial_default.h"
#include "system_wrappers/include/metrics_default.h"
#include "test/field_trial.h"
@ -87,6 +88,15 @@ int main(int argc, char* argv[]) {
rtc::LogMessage::SetLogToStderr(FLAG_logs);
// Ensure that main thread gets wrapped as an rtc::Thread.
// TODO(bugs.webrt.org/9714): It might be better to avoid wrapping the main
// thread, or leave it to individual tests that need it. But as long as we
// have automatic thread wrapping, we need this to avoid that some other
// random thread (which one depending on which tests are run) gets
// automatically wrapped.
rtc::ThreadManager::Instance()->WrapCurrentThread();
RTC_CHECK(rtc::Thread::Current());
#if defined(WEBRTC_IOS)
rtc::test::InitTestSuite(RUN_ALL_TESTS, argc, argv,