用于EagleEye3.0 规则集漏报和误报测试的示例项目,项目收集于github和gitee
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

181 lines
6.0 KiB

/* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License, version 2.0,
as published by the Free Software Foundation.
This program is also distributed with certain software (including
but not limited to OpenSSL) that is licensed under separate terms,
as designated in a particular file or component or in included license
documentation. The authors of MySQL hereby grant you an additional
permission to link the program and your derivative works with the
separately licensed software that they have included with MySQL.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License, version 2.0, for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
This is a unit test written to demonstrate a race issue in debug_sync
functionality which resulted in wait thread getting timed out. This
happens because we use a single global variable to identify the thread
that has signalled. Before the wait could process the signal from the
signal thread, another signal thread can overwrite this global signal
value thus making the wait thread to lose this signal and timeout
waiting for a signal that it has already lost.
*/
#include <gtest/gtest.h>
#include <string>
#include "my_dbug.h"
#include "my_inttypes.h"
#include "sql/debug_sync.h"
#include "unittest/gunit/test_utils.h"
#include "unittest/gunit/thread_utils.h"
#if defined(ENABLED_DEBUG_SYNC)
extern uchar *debug_sync_value_ptr(THD *thd);
namespace debug_sync_unittest {
using my_testing::Mock_error_handler;
using my_testing::Server_initializer;
using thread::Notification;
using thread::Thread;
class DebugSyncTest : public ::testing::Test {
protected:
DebugSyncTest() {}
void SetUp() {
// set debug sync timeout of 60 seconds.
opt_debug_sync_timeout = 60;
debug_sync_init();
}
void TearDown() {
debug_sync_end();
opt_debug_sync_timeout = 0;
}
};
/*
Set up a debug sync action thread. Depending on type of action, the thread
serves different purpose. In the case where it involves wait_for action, it
serves the purpose of a waiting thread that wait at a 'sync_point' in it's
thread of control for named signal event. The debug sync action could
be a signal event, in which case it assumes the role of signalling thread
that signals an event identified by signal name to wake a waiting thread.
*/
class DebugSyncThread : public Thread {
public:
DebugSyncThread(Notification *go, bool wait_thread, std::string action)
: m_go(go), m_wait_thread(wait_thread), m_action(action) {}
virtual void run() {
m_initializer.SetUp();
m_thd = m_initializer.thd();
m_go->wait_for_notification();
if (m_wait_thread) {
std::string sync_point("sync_point ");
std::string action_str = sync_point + m_action;
Mock_error_handler error_handler(m_thd, 0);
debug_sync_set_action(m_thd, action_str.c_str(), action_str.length());
wait_point();
// The above should not generate any warnings.
EXPECT_EQ(0, error_handler.handle_called());
} else {
debug_sync_set_action(m_thd, m_action.c_str(), m_action.length());
}
m_initializer.TearDown();
}
private:
Notification *m_go;
Server_initializer m_initializer;
THD *m_thd; // THD context required to hold debug_sync context.
bool m_wait_thread; // indicate if it is a wait thread.
std::string m_action; // indicate type of action WAIT_FOR or SIGNAL.
void wait_point() { DEBUG_SYNC(m_thd, "sync_point"); }
};
/*
Start a wait thread waiting for signal X1 and two signal threads
one signalling event X1 and other signalling an event X2. Notify
all of them to start at once.
*/
TEST_F(DebugSyncTest, DebugSyncSignalWaitTests) {
Notification go[3];
/* wait thread */
DebugSyncThread wait_thread(&go[0], true, std::string("WAIT_FOR X1"));
/* signal thread */
DebugSyncThread signal_thread1(&go[1], false, std::string("now signal X1"));
DebugSyncThread signal_thread2(&go[2], false, std::string("now signal X2"));
wait_thread.start();
signal_thread1.start();
signal_thread2.start();
// Notify all threads
go[0].notify();
go[1].notify();
go[2].notify();
// Wait for all threads to finish.
wait_thread.join();
signal_thread1.join();
signal_thread2.join();
}
// Test debug_sync_value_ptr
TEST_F(DebugSyncTest, DebugSyncValuesTest) {
std::string action;
Server_initializer server_initializer;
THD *thd;
server_initializer.SetUp();
thd = server_initializer.thd();
// Ensure that we have a empty signal list at startup.
EXPECT_STREQ("ON - signals: ''",
reinterpret_cast<char *>(debug_sync_value_ptr(thd)));
// Set up signalling actions and ensure the signals list reflect it.
action = "now signal x1";
debug_sync_set_action(thd, action.c_str(), action.length());
EXPECT_STREQ("ON - signals: 'x1'",
reinterpret_cast<char *>(debug_sync_value_ptr(thd)));
action = "now signal x2";
debug_sync_set_action(thd, action.c_str(), action.length());
EXPECT_STREQ("ON - signals: 'x1,x2'",
reinterpret_cast<char *>(debug_sync_value_ptr(thd)));
action = "now signal x3";
debug_sync_set_action(thd, action.c_str(), action.length());
EXPECT_STREQ("ON - signals: 'x1,x2,x3'",
reinterpret_cast<char *>(debug_sync_value_ptr(thd)));
// Ensure the signal list is empty after reset.
action = "reset";
debug_sync_set_action(thd, action.c_str(), action.length());
EXPECT_STREQ("ON - signals: ''",
reinterpret_cast<char *>(debug_sync_value_ptr(thd)));
server_initializer.TearDown();
}
} // namespace debug_sync_unittest
#endif