Reject null event base arguments

Summary:
If you use a null eventbase, folly implicitly decides which one to run the futures in, for example
the timekeeper thread.
The only component that passes in event bases is sonar.cpp.

Reviewed By: priteshrnandgaonkar

Differential Revision: D9539443

fbshipit-source-id: 7fd7289257c84b039a7ac00b14f78bb271262480
This commit is contained in:
John Knox
2018-09-03 11:10:52 -07:00
committed by Facebook Github Bot
parent 661d5a8f5b
commit a5af72a169
2 changed files with 95 additions and 1 deletions

View File

@@ -21,6 +21,7 @@
#include <iostream> #include <iostream>
#include <thread> #include <thread>
#include <folly/io/async/AsyncSocketException.h> #include <folly/io/async/AsyncSocketException.h>
#include <stdexcept>
#include "CertificateUtils.h" #include "CertificateUtils.h"
#ifdef __ANDROID__ #ifdef __ANDROID__
@@ -96,7 +97,10 @@ class Responder : public rsocket::RSocketResponder {
}; };
SonarWebSocketImpl::SonarWebSocketImpl(SonarInitConfig config, std::shared_ptr<SonarState> state) SonarWebSocketImpl::SonarWebSocketImpl(SonarInitConfig config, std::shared_ptr<SonarState> state)
: deviceData_(config.deviceData), sonarState_(state), sonarEventBase_(config.callbackWorker), connectionEventBase_(config.connectionWorker) {} : deviceData_(config.deviceData), sonarState_(state), sonarEventBase_(config.callbackWorker), connectionEventBase_(config.connectionWorker) {
CHECK_THROW(config.callbackWorker, std::invalid_argument);
CHECK_THROW(config.connectionWorker, std::invalid_argument);
}
SonarWebSocketImpl::~SonarWebSocketImpl() { SonarWebSocketImpl::~SonarWebSocketImpl() {
stop(); stop();

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*
*/
#include <Sonar/SonarWebSocketImpl.h>
#include <gtest/gtest.h>
namespace facebook {
namespace sonar {
namespace test {
using folly::EventBase;
class SonarWebSocketImplTerminationTest : public ::testing::Test {
protected:
void SetUp() override {
// Folly singletons must be registered before they are used.
// Without this, test fails in phabricator.
folly::SingletonVault::singleton()->registrationComplete();
}
};
TEST_F(SonarWebSocketImplTerminationTest, testNullEventBaseGetsRejected) {
try {
auto instance = std::make_shared<SonarWebSocketImpl>(SonarInitConfig {
DeviceData {},
nullptr,
new EventBase()
}, std::make_shared<SonarState>());
FAIL();
} catch (std::invalid_argument& e) {
// Pass test
}
try {
auto instance = std::make_shared<SonarWebSocketImpl>(SonarInitConfig {
DeviceData {},
new EventBase(),
nullptr
}, std::make_shared<SonarState>());
FAIL();
} catch (std::invalid_argument& e) {
// Pass test
}
}
TEST_F(SonarWebSocketImplTerminationTest, testNonStartedEventBaseDoesntHang) {
auto config = SonarInitConfig {
DeviceData {},
new EventBase(),
new EventBase()
};
auto state = std::make_shared<SonarState>();
auto instance = std::make_shared<SonarWebSocketImpl>(config, state);
instance->start();
}
TEST_F(SonarWebSocketImplTerminationTest, testStartedEventBaseDoesntHang) {
auto sonarEventBase = new EventBase();
auto connectionEventBase = new EventBase();
auto sonarThread = std::thread([sonarEventBase](){
sonarEventBase->loopForever();
});
auto connectionThread = std::thread([connectionEventBase](){
connectionEventBase->loopForever();
});
auto config = SonarInitConfig {
DeviceData {},
sonarEventBase,
connectionEventBase
};
auto state = std::make_shared<SonarState>();
auto instance = std::make_shared<SonarWebSocketImpl>(config, state);
instance->start();
sonarEventBase->terminateLoopSoon();
connectionEventBase->terminateLoopSoon();
sonarThread.join();
connectionThread.join();
}
} // namespace test
} // namespace sonar
} // namespace facebook