Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tests): new e2e tests [3/N] #1720

Merged
merged 12 commits into from
Mar 22, 2024
Merged
1 change: 1 addition & 0 deletions test/libsinsp_e2e/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ add_executable(libsinsp_e2e_tests
container/docker_utils.cpp
event_capture.cpp
main.cpp
paths.cpp
subprocess.cpp
sys_call_test.cpp
thread_state.cpp
Expand Down
37 changes: 21 additions & 16 deletions test/libsinsp_e2e/container/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,12 @@ TEST_F(sys_call_test, container_cgroups)

static int clone_callback(void* arg)
{
sleep(5);
// Here we need 2 sleeps instead of once because, for some reason,
// we miss the first one. This problem is *probably* related to the
// fact that before we created a brand new inspector for each test but
// not we keep the same and start/stop the capture.
sleep(1);
therealbobo marked this conversation as resolved.
Show resolved Hide resolved
sleep(1);
return 0;
}

Expand Down Expand Up @@ -231,26 +236,23 @@ TEST_F(sys_call_test, container_clone_nspid_ioctl)
//
// TEST CODE
//
run_callback_t test = [&](concurrent_object_handle<sinsp> inspector) { wait(NULL); };
run_callback_t test = [&](concurrent_object_handle<sinsp> inspector) { waitpid(ctid, NULL, 0); };

//
// OUTPUT VALDATION
//
captured_event_callback_t callback = [&](const callback_param& param)
{
sinsp_threadinfo* tinfo = param.m_evt->get_thread_info();
if (tinfo)
if (tinfo && tinfo->m_vtid == 1 && tinfo->m_vpid == 1)
{
EXPECT_EQ(1, tinfo->m_vtid);
EXPECT_EQ(1, tinfo->m_vpid);

done = true;
}
};

ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); });
ASSERT_TRUE(done);
free(stack);
ASSERT_TRUE(done);
}

static void run_container_docker_test(bool fork_after_container_start)
Expand Down Expand Up @@ -372,6 +374,11 @@ TEST_F(sys_call_test, container_docker_bad_socket)
return;
}

before_open_t setup = [&](sinsp* inspector)
{
inspector->set_docker_socket_path("/invalid/path");
};

event_filter_t filter = [&](sinsp_evt* evt)
{
if (evt->get_type() == PPME_CONTAINER_JSON_E || evt->get_type() == PPME_CONTAINER_JSON_2_E)
Expand Down Expand Up @@ -426,11 +433,6 @@ TEST_F(sys_call_test, container_docker_bad_socket)
}
};

before_open_t setup = [&](sinsp* inspector)
{
inspector->set_docker_socket_path("/invalid/path");
};

before_close_t cleanup = [&](sinsp* inspector)
{ inspector->set_docker_socket_path("/var/run/docker.sock"); };

Expand Down Expand Up @@ -666,6 +668,9 @@ static void healthcheck_helper(

ASSERT_TRUE(dhelper.build_image() == 0);

before_open_t setup = [&](sinsp* inspector)
{};

event_filter_t filter = [&](sinsp_evt* evt)
{
sinsp_threadinfo* tinfo = evt->get_thread_info();
Expand Down Expand Up @@ -703,11 +708,11 @@ static void healthcheck_helper(
}
};

before_open_t setup = [&](sinsp* inspector)
{};

before_close_t cleanup = [&](sinsp* inspector)
{ capture_stats_str = capture_stats(inspector); };
{
capture_stats_str = capture_stats(inspector);
inspector->stop_dropping_mode();
};

ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); });

Expand Down
81 changes: 43 additions & 38 deletions test/libsinsp_e2e/event_capture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,40 +28,31 @@ limitations under the License.
std::string event_capture::m_engine_string = KMOD_ENGINE;
std::string event_capture::m_engine_path = "";
unsigned long event_capture::m_buffer_dim = DEFAULT_DRIVER_BUFFER_BYTES_DIM;
bool event_capture::inspector_ok = false;

concurrent_object_handle<sinsp> event_capture::get_inspector_handle()
{
return {m_inspector.get(), m_inspector_mutex};
return {get_inspector(), m_inspector_mutex};
}

void event_capture::capture()
void event_capture::init_inspector()
{
std::unique_ptr<sinsp_cycledumper> dumper;
{ // Begin init synchronized section
std::scoped_lock init_lock(m_inspector_mutex, m_object_state_mutex);

m_inspector = std::make_unique<sinsp>();

m_inspector->m_thread_manager->set_max_thread_table_size(m_max_thread_table_size);
m_inspector->m_thread_timeout_ns = m_thread_timeout_ns;
m_inspector->set_auto_threads_purging_interval_s(m_inactive_thread_scan_time_ns);
m_inspector->set_auto_threads_purging(false);
get_inspector()->m_thread_manager->set_max_thread_table_size(m_max_thread_table_size);
get_inspector()->m_thread_timeout_ns = m_thread_timeout_ns;
get_inspector()->set_auto_threads_purging_interval_s(m_inactive_thread_scan_time_ns);
get_inspector()->set_auto_threads_purging(false);

m_inspector->set_get_procs_cpu_from_driver(true);
get_inspector()->set_get_procs_cpu_from_driver(true);

m_param.m_inspector = m_inspector.get();

m_before_open(m_inspector.get());

ASSERT_FALSE(m_inspector->is_capture());
ASSERT_FALSE(m_inspector->is_live());
ASSERT_FALSE(m_inspector->is_nodriver());
ASSERT_FALSE(get_inspector()->is_capture());
ASSERT_FALSE(get_inspector()->is_live());
ASSERT_FALSE(get_inspector()->is_nodriver());

try
{
if (m_mode == SINSP_MODE_NODRIVER)
{
m_inspector->open_nodriver();
get_inspector()->open_nodriver();
}
else
{
Expand All @@ -73,7 +64,7 @@ void event_capture::capture()
m_start_failed = true;
m_start_failure_message =
"couldn't open inspector (maybe driver hasn't been loaded yet?) err=" +
m_inspector->getlasterr() + " exception=" + e.what();
get_inspector()->getlasterr() + " exception=" + e.what();
{
//std::unique_lock<std::mutex> lock(m_mutex);
m_capture_started = true;
Expand All @@ -82,31 +73,45 @@ void event_capture::capture()
return;
}

const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
get_inspector()->set_debug_mode(true);
get_inspector()->set_hostname_and_port_resolution_mode(false);
}

m_inspector->set_debug_mode(true);
m_inspector->set_hostname_and_port_resolution_mode(false);
void event_capture::capture()
{
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
std::unique_ptr<sinsp_cycledumper> dumper;
{
std::scoped_lock init_lock(m_inspector_mutex, m_object_state_mutex);

m_inspector->start_capture();
if(!inspector_ok)
{
init_inspector();
inspector_ok = true;
}

m_param.m_inspector = get_inspector();

m_before_open(get_inspector());

get_inspector()->start_capture();
if (m_mode != SINSP_MODE_NODRIVER)
{
m_dump_filename = std::string(LIBSINSP_TEST_CAPTURES_PATH) + test_info->test_case_name() + "_" +
test_info->name() + ".scap";
dumper = std::make_unique<sinsp_cycledumper>(m_inspector.get(), m_dump_filename.c_str(),
dumper = std::make_unique<sinsp_cycledumper>(get_inspector(), m_dump_filename.c_str(),
0, 0, 0, 0, true);
}
} // End init synchronized section


bool signaled_start = false;
sinsp_evt* event;
bool result = true;
int32_t next_result = SCAP_SUCCESS;
while (!m_capture_stopped && result && !::testing::Test::HasFatalFailure())
{
if (SCAP_SUCCESS == (next_result = m_inspector->next(&event)))
if (SCAP_SUCCESS == (next_result = get_inspector()->next(&event)))
{
result = handle_event(event);
}
Expand All @@ -126,7 +131,7 @@ void event_capture::capture()
uint32_t n_timeouts = 0;
while (result && !::testing::Test::HasFatalFailure())
{
next_result = m_inspector->next(&event);
next_result = get_inspector()->next(&event);
if (next_result == SCAP_TIMEOUT)
{
n_timeouts++;
Expand Down Expand Up @@ -154,7 +159,7 @@ void event_capture::capture()
}
{
std::scoped_lock inspector_next_lock(m_inspector_mutex);
while (SCAP_SUCCESS == m_inspector->next(&event))
while (SCAP_SUCCESS == get_inspector()->next(&event))
{
// just consume the remaining events
dumper->dump(event);
Expand All @@ -164,11 +169,11 @@ void event_capture::capture()

{ // Begin teardown synchronized section
std::scoped_lock teardown_lock(m_inspector_mutex, m_object_state_mutex);
m_before_close(m_inspector.get());
m_before_close(get_inspector());

get_inspector()->stop_capture();
m_capture_stopped = true;
m_condition_stopped.notify_one();

} // End teardown synchronized section

}
Expand Down Expand Up @@ -235,7 +240,7 @@ handle_event(sinsp_evt* event)
m_param.m_evt = event;
m_captured_event_callback(m_param);
}
catch (...)
catch(...)
{
res = false;
}
Expand All @@ -259,7 +264,7 @@ void event_capture::open_engine(const std::string& engine_string, libsinsp::even
#ifdef HAS_ENGINE_KMOD
else if(!engine_string.compare(KMOD_ENGINE))
{
m_inspector->open_kmod(m_buffer_dim);
get_inspector()->open_kmod(m_buffer_dim);
}
#endif
#ifdef HAS_ENGINE_BPF
Expand All @@ -270,13 +275,13 @@ void event_capture::open_engine(const std::string& engine_string, libsinsp::even
std::cerr << "You must specify the path to the bpf probe if you use the 'bpf' engine" << std::endl;
exit(EXIT_FAILURE);
}
m_inspector->open_bpf(event_capture::get_engine_path().c_str(), m_buffer_dim);
get_inspector()->open_bpf(event_capture::get_engine_path().c_str(), m_buffer_dim);
}
#endif
#ifdef HAS_ENGINE_MODERN_BPF
else if(!engine_string.compare(MODERN_BPF_ENGINE))
{
m_inspector->open_modern_bpf(m_buffer_dim);
get_inspector()->open_modern_bpf(m_buffer_dim);
}
#endif
else
Expand Down
9 changes: 8 additions & 1 deletion test/libsinsp_e2e/event_capture.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ typedef std::function<void(concurrent_object_handle<sinsp> inspector)> run_callb
class event_capture
{
public:
void init_inspector();
void capture();
void stop_capture();
void wait_for_capture_start();
Expand All @@ -130,6 +131,12 @@ class event_capture

static bool always_continue() { return true; }

sinsp* get_inspector()
{
static sinsp inspector = sinsp();
return &inspector;
}

static void run(run_callback_t run_function,
captured_event_callback_t captured_event_callback,
event_filter_t filter,
Expand Down Expand Up @@ -223,7 +230,7 @@ class event_capture
std::string m_start_failure_message;
std::string m_dump_filename;
callback_param m_param;
std::unique_ptr<sinsp> m_inspector;
static bool inspector_ok;
sinsp_mode_t m_mode;
uint64_t m_max_timeouts;
};
3 changes: 2 additions & 1 deletion test/libsinsp_e2e/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ int main(int argc, char** argv)

if(!std::filesystem::exists(captures_dir))
{
if (!std::filesystem::create_directory(captures_dir)) {
if(!std::filesystem::create_directory(captures_dir))
{
std::cerr << "Failed to create captures directory." << std::endl;;
return EXIT_FAILURE;
}
Expand Down
Loading
Loading