Merged PR 940316: KillSwitch tests
Added FunctTests to check KillSwitch feature: - killSwitchWorks checks that a token is banned and events are dropped - killIsTemporary checks that a token is banned for an amount of time and no events are dropped after that Related work items: #1608758
This commit is contained in:
Родитель
20d4e94160
Коммит
306a8257be
|
@ -66,8 +66,22 @@ class HttpServer : private Reactor::Callback
|
|||
size_t m_maxRequestHeadersSize, m_maxRequestContentSize;
|
||||
std::string m_serverHost;
|
||||
|
||||
// Map of killed token to kill duration of that token
|
||||
// Ideally we need a map of string --> std::pair<std::string /* suffix */, uint64_t /* duration */
|
||||
std::map<std::string, uint64_t> m_killedTokens;
|
||||
|
||||
public:
|
||||
|
||||
void setKilledToken(std::string token, uint64_t duration)
|
||||
{
|
||||
m_killedTokens[token] = duration;
|
||||
};
|
||||
|
||||
void clearKilledTokens()
|
||||
{
|
||||
m_killedTokens.clear();
|
||||
}
|
||||
|
||||
void setKeepalive(bool keepAlive)
|
||||
{
|
||||
allowKeepalive = keepAlive;
|
||||
|
@ -547,6 +561,18 @@ class HttpServer : private Reactor::Callback
|
|||
conn.response.headers["Connection"] = (conn.keepalive ? "keep-alive" : "close");
|
||||
conn.response.headers["Date"] = formatTimestamp(time(nullptr));
|
||||
conn.response.headers["Content-Length"] = std::to_string(conn.response.content.size());
|
||||
int kill_duration = -1;
|
||||
for (auto &kv : m_killedTokens)
|
||||
{
|
||||
std::string val = kv.first;
|
||||
val += ":all";
|
||||
conn.response.headers.insert(std::pair<std::string, std::string>("kill-tokens", val));
|
||||
kill_duration = std::max(kill_duration, (int)kv.second);
|
||||
}
|
||||
|
||||
if (m_killedTokens.size() > 0) {
|
||||
conn.response.headers.insert(std::pair<std::string, std::string>("kill-duration", std::to_string(kill_duration)));
|
||||
}
|
||||
}
|
||||
|
||||
static std::string formatTimestamp(time_t time)
|
||||
|
|
|
@ -24,6 +24,7 @@ using namespace ARIASDK_NS;
|
|||
char const* const TEST_STORAGE_FILENAME = "BasicFuncTests.db";
|
||||
|
||||
#define TEST_TOKEN "6d084bbf6a9644ef83f40a77c9e34580-c2d379e0-4408-4325-9b4d-2a7d78131e14-7322"
|
||||
#define KILLED_TOKEN "deadbeefdeadbeefdeadbeefdeadbeef-c2d379e0-4408-4325-9b4d-2a7d78131e14-7322"
|
||||
#define HTTP_PORT 19000
|
||||
|
||||
class BasicFuncTests : public ::testing::Test,
|
||||
|
@ -852,6 +853,263 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class KillSwitchListener : public DebugEventListener {
|
||||
public :
|
||||
std::atomic<unsigned> numLogged;
|
||||
std::atomic<unsigned> numSent;
|
||||
std::atomic<unsigned> numDropped;
|
||||
std::atomic<unsigned> numReject;
|
||||
std::atomic<unsigned> numHttpError;
|
||||
std::atomic<unsigned> numHttpOK;
|
||||
std::atomic<unsigned> numHttpFailure;
|
||||
std::atomic<unsigned> numCached;
|
||||
|
||||
KillSwitchListener() :
|
||||
numLogged(0),
|
||||
numSent(0),
|
||||
numDropped(0),
|
||||
numReject(0),
|
||||
numHttpError(0),
|
||||
numHttpOK(0),
|
||||
numHttpFailure(0),
|
||||
numCached(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnDebugEvent(DebugEvent &evt) {
|
||||
switch (evt.type) {
|
||||
case EVT_LOG_SESSION:
|
||||
numLogged++;
|
||||
break;
|
||||
case EVT_REJECTED:
|
||||
numReject++;
|
||||
break;
|
||||
case EVT_ADDED:
|
||||
break;
|
||||
/* Event counts below would never overflow the size of unsigned int */
|
||||
case EVT_CACHED:
|
||||
numCached += (unsigned int)evt.param1;
|
||||
break;
|
||||
case EVT_DROPPED:
|
||||
numDropped += (unsigned int)evt.param1;
|
||||
break;
|
||||
case EVT_SENT:
|
||||
numSent += (unsigned int)evt.param1;
|
||||
break;
|
||||
case EVT_HTTP_FAILURE:
|
||||
numHttpFailure++;
|
||||
break;
|
||||
case EVT_HTTP_ERROR:
|
||||
numHttpError++;
|
||||
break;
|
||||
case EVT_HTTP_OK:
|
||||
numHttpOK++;
|
||||
break;
|
||||
case EVT_UNKNOWN:
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
void printStats(){
|
||||
std::cerr << "[ ] numLogged = " << numLogged << std::endl;
|
||||
std::cerr << "[ ] numSent = " << numSent << std::endl;
|
||||
std::cerr << "[ ] numDropped = " << numDropped << std::endl;
|
||||
std::cerr << "[ ] numReject = " << numReject << std::endl;
|
||||
std::cerr << "[ ] numHttpError = " << numHttpError << std::endl;
|
||||
std::cerr << "[ ] numHttpOK = " << numHttpOK << std::endl;
|
||||
std::cerr << "[ ] numHttpFailure = " << numHttpFailure << std::endl;
|
||||
std::cerr << "[ ] numCached = " << numCached << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
void addListeners(DebugEventListener &listener) {
|
||||
LogManager::AddEventListener(DebugEventType::EVT_LOG_SESSION, listener);
|
||||
LogManager::AddEventListener(DebugEventType::EVT_REJECTED, listener);
|
||||
LogManager::AddEventListener(DebugEventType::EVT_SENT, listener);
|
||||
LogManager::AddEventListener(DebugEventType::EVT_DROPPED, listener);
|
||||
LogManager::AddEventListener(DebugEventType::EVT_HTTP_OK, listener);
|
||||
LogManager::AddEventListener(DebugEventType::EVT_HTTP_ERROR, listener);
|
||||
LogManager::AddEventListener(DebugEventType::EVT_HTTP_FAILURE, listener);
|
||||
LogManager::AddEventListener(DebugEventType::EVT_CACHED, listener);
|
||||
}
|
||||
|
||||
void removeListeners(DebugEventListener &listener) {
|
||||
LogManager::RemoveEventListener(DebugEventType::EVT_LOG_SESSION, listener);
|
||||
LogManager::RemoveEventListener(DebugEventType::EVT_REJECTED, listener);
|
||||
LogManager::RemoveEventListener(DebugEventType::EVT_SENT, listener);
|
||||
LogManager::RemoveEventListener(DebugEventType::EVT_DROPPED, listener);
|
||||
LogManager::RemoveEventListener(DebugEventType::EVT_HTTP_OK, listener);
|
||||
LogManager::RemoveEventListener(DebugEventType::EVT_HTTP_ERROR, listener);
|
||||
LogManager::RemoveEventListener(DebugEventType::EVT_HTTP_FAILURE, listener);
|
||||
LogManager::RemoveEventListener(DebugEventType::EVT_CACHED, listener);
|
||||
}
|
||||
|
||||
TEST_F(BasicFuncTests, killSwitchWorks)
|
||||
{
|
||||
CleanStorage();
|
||||
// Create the configuration to send to fake server
|
||||
auto configuration = LogManager::GetLogConfiguration();
|
||||
|
||||
configuration[CFG_INT_TRACE_LEVEL_MASK] = 0xFFFFFFFF;
|
||||
configuration[CFG_INT_TRACE_LEVEL_MIN] = ACTTraceLevel_Warn;
|
||||
configuration[CFG_INT_SDK_MODE] = SdkModeTypes::SdkModeTypes_Aria;
|
||||
|
||||
configuration[CFG_INT_RAM_QUEUE_SIZE] = 4096 * 20;
|
||||
configuration[CFG_STR_CACHE_FILE_PATH] = TEST_STORAGE_FILENAME;
|
||||
configuration[CFG_INT_MAX_TEARDOWN_TIME] = 2; // 2 seconds wait on shutdown
|
||||
configuration[CFG_STR_COLLECTOR_URL] = serverAddress.c_str();
|
||||
configuration["http"]["compress"] = false; // disable compression for now
|
||||
configuration["stats"]["interval"] = 30 * 60; // 30 mins
|
||||
|
||||
configuration["name"] = __FILE__;
|
||||
configuration["version"] = "1.0.0";
|
||||
configuration["config"] = { { "host", __FILE__ } }; // Host instance
|
||||
|
||||
// set the killed token on the server
|
||||
server.setKilledToken(KILLED_TOKEN, 6384);
|
||||
KillSwitchListener listener;
|
||||
addListeners(listener);
|
||||
// Log 100 events from valid and invalid 4 times
|
||||
int repetitions = 4;
|
||||
for (int i = 0; i < repetitions; i++) {
|
||||
// Initialize the logger for the valid token and log 100 events
|
||||
LogManager::Initialize(TEST_TOKEN, configuration);
|
||||
LogManager::ResumeTransmission();
|
||||
auto myLogger = LogManager::GetLogger(TEST_TOKEN, "killed");
|
||||
int numIterations = 100;
|
||||
while (numIterations--) {
|
||||
EventProperties event1("fooEvent");
|
||||
event1.SetProperty("property", "value");
|
||||
myLogger->LogEvent(event1);
|
||||
}
|
||||
// Initialize the logger for the killed token and log 100 events
|
||||
LogManager::Initialize(KILLED_TOKEN, configuration);
|
||||
LogManager::ResumeTransmission();
|
||||
myLogger = LogManager::GetLogger(KILLED_TOKEN, "killed");
|
||||
numIterations = 100;
|
||||
while (numIterations--) {
|
||||
EventProperties event2("failEvent");
|
||||
event2.SetProperty("property", "value");
|
||||
myLogger->LogEvent(event2);
|
||||
}
|
||||
}
|
||||
// Try to upload and wait for 2 seconds to complete
|
||||
LogManager::UploadNow();
|
||||
PAL::sleep(2000);
|
||||
|
||||
// Log 100 events with valid logger
|
||||
LogManager::Initialize(TEST_TOKEN, configuration);
|
||||
LogManager::ResumeTransmission();
|
||||
auto myLogger = LogManager::GetLogger(TEST_TOKEN, "killed");
|
||||
int numIterations = 100;
|
||||
while (numIterations--) {
|
||||
EventProperties event1("fooEvent");
|
||||
event1.SetProperty("property", "value");
|
||||
myLogger->LogEvent(event1);
|
||||
}
|
||||
|
||||
LogManager::Initialize(KILLED_TOKEN, configuration);
|
||||
LogManager::ResumeTransmission();
|
||||
myLogger = LogManager::GetLogger(KILLED_TOKEN, "killed");
|
||||
numIterations = 100;
|
||||
while (numIterations--) {
|
||||
EventProperties event2("failEvent");
|
||||
event2.SetProperty("property", "value");
|
||||
myLogger->LogEvent(event2);
|
||||
}
|
||||
// Expect all events to be dropped
|
||||
EXPECT_EQ(100, listener.numDropped);
|
||||
LogManager::FlushAndTeardown();
|
||||
|
||||
listener.printStats();
|
||||
removeListeners(listener);
|
||||
server.clearKilledTokens();
|
||||
}
|
||||
|
||||
TEST_F(BasicFuncTests, killIsTemporary)
|
||||
{
|
||||
CleanStorage();
|
||||
// Create the configuration to send to fake server
|
||||
auto configuration = LogManager::GetLogConfiguration();
|
||||
|
||||
configuration[CFG_INT_TRACE_LEVEL_MASK] = 0xFFFFFFFF;
|
||||
configuration[CFG_INT_TRACE_LEVEL_MIN] = ACTTraceLevel_Warn;
|
||||
configuration[CFG_INT_SDK_MODE] = SdkModeTypes::SdkModeTypes_Aria;
|
||||
|
||||
configuration[CFG_INT_RAM_QUEUE_SIZE] = 4096 * 20;
|
||||
configuration[CFG_STR_CACHE_FILE_PATH] = TEST_STORAGE_FILENAME;
|
||||
configuration[CFG_INT_MAX_TEARDOWN_TIME] = 2; // 2 seconds wait on shutdown
|
||||
configuration[CFG_STR_COLLECTOR_URL] = serverAddress.c_str();
|
||||
configuration["http"]["compress"] = false; // disable compression for now
|
||||
configuration["stats"]["interval"] = 30 * 60; // 30 mins
|
||||
|
||||
configuration["name"] = __FILE__;
|
||||
configuration["version"] = "1.0.0";
|
||||
configuration["config"] = { { "host", __FILE__ } }; // Host instance
|
||||
|
||||
// set the killed token on the server
|
||||
server.setKilledToken(KILLED_TOKEN, 10);
|
||||
KillSwitchListener listener;
|
||||
addListeners(listener);
|
||||
// Log 100 events from valid and invalid 4 times
|
||||
int repetitions = 4;
|
||||
for (int i = 0; i < repetitions; i++) {
|
||||
// Initialize the logger for the valid token and log 100 events
|
||||
LogManager::Initialize(TEST_TOKEN, configuration);
|
||||
LogManager::ResumeTransmission();
|
||||
auto myLogger = LogManager::GetLogger(TEST_TOKEN, "killed");
|
||||
int numIterations = 100;
|
||||
while (numIterations--) {
|
||||
EventProperties event1("fooEvent");
|
||||
event1.SetProperty("property", "value");
|
||||
myLogger->LogEvent(event1);
|
||||
}
|
||||
// Initialize the logger for the killed token and log 100 events
|
||||
LogManager::Initialize(KILLED_TOKEN, configuration);
|
||||
LogManager::ResumeTransmission();
|
||||
myLogger = LogManager::GetLogger(KILLED_TOKEN, "killed");
|
||||
numIterations = 100;
|
||||
while (numIterations--) {
|
||||
EventProperties event2("failEvent");
|
||||
event2.SetProperty("property", "value");
|
||||
myLogger->LogEvent(event2);
|
||||
}
|
||||
}
|
||||
// Try and wait to upload
|
||||
LogManager::UploadNow();
|
||||
PAL::sleep(2000);
|
||||
// Sleep for 11 seconds so the killed time has expired, clear the killed tokens on server
|
||||
PAL::sleep(11000);
|
||||
server.clearKilledTokens();
|
||||
// Log 100 events with valid logger
|
||||
LogManager::Initialize(TEST_TOKEN, configuration);
|
||||
LogManager::ResumeTransmission();
|
||||
auto myLogger = LogManager::GetLogger(TEST_TOKEN, "killed");
|
||||
int numIterations = 100;
|
||||
while (numIterations--) {
|
||||
EventProperties event1("fooEvent");
|
||||
event1.SetProperty("property", "value");
|
||||
myLogger->LogEvent(event1);
|
||||
}
|
||||
|
||||
LogManager::Initialize(KILLED_TOKEN, configuration);
|
||||
LogManager::ResumeTransmission();
|
||||
myLogger = LogManager::GetLogger(KILLED_TOKEN, "killed");
|
||||
numIterations = 100;
|
||||
while (numIterations--) {
|
||||
EventProperties event2("failEvent");
|
||||
event2.SetProperty("property", "value");
|
||||
myLogger->LogEvent(event2);
|
||||
}
|
||||
// Expect to 0 events to be dropped
|
||||
EXPECT_EQ(0, listener.numDropped);
|
||||
LogManager::FlushAndTeardown();
|
||||
|
||||
listener.printStats();
|
||||
removeListeners(listener);
|
||||
server.clearKilledTokens();
|
||||
}
|
||||
|
||||
TEST_F(BasicFuncTests, sendManyRequestsAndCancel)
|
||||
{
|
||||
CleanStorage();
|
||||
|
|
Загрузка…
Ссылка в новой задаче