sglang.0.4.8.post1/gdrcopy/tests/testsuites/testsuite.cpp

239 lines
8.4 KiB
C++

/*
* Copyright (c) 2023, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include "../common.hpp"
#include "testsuite.hpp"
namespace gdrcopy {
namespace testsuite {
TestMap *get_test_map()
{
static TestMap *_test_map = NULL;
if (!_test_map)
_test_map = new TestMap();
return _test_map;
}
void get_all_test_names(std::vector<std::string>& names)
{
TestMap *test_map = get_test_map();
names.clear();
for (TestMap::iterator it = test_map->begin(); it != test_map->end(); ++it)
names.emplace_back(it->first);
}
int run_tests(bool print_summary, std::vector<std::string> tests)
{
TestMap *test_map = get_test_map();
std::vector<std::string> success_tests;
std::vector<std::string> failed_tests;
std::vector<std::string> waived_tests;
for (std::vector<std::string>::iterator it = tests.begin(); it != tests.end(); ++it) {
if (test_map->find(*it) == test_map->end()) {
gdrcopy::test::print_dbg("Error: Encountered unknown test %s\n", *it);
return EINVAL;
}
}
for (std::vector<std::string>::iterator it = tests.begin(); it != tests.end(); ++it) {
test_status_t status = (*test_map)[*it]->run();
switch (status) {
case TEST_STATUS_SUCCESS:
success_tests.push_back(*it);
break;
case TEST_STATUS_FAILED:
failed_tests.push_back(*it);
break;
case TEST_STATUS_WAIVED:
waived_tests.push_back(*it);
break;
default:
gdrcopy::test::print_dbg("Error: Unknown test status\n");
return EINVAL;
}
}
if (print_summary) {
printf(
"Total: %lu, Passed: %lu, Failed: %lu, Waived: %lu\n",
tests.size(),
success_tests.size(),
failed_tests.size(),
waived_tests.size()
);
if (failed_tests.size() > 0) {
printf("\n");
printf("List of failed tests:\n");
for (std::vector<std::string>::iterator it = failed_tests.begin(); it != failed_tests.end(); ++it)
printf(" %s\n", it->c_str());
}
if (waived_tests.size() > 0) {
printf("\n");
printf("List of waived tests:\n");
for (std::vector<std::string>::iterator it = waived_tests.begin(); it != waived_tests.end(); ++it)
printf(" %s\n", it->c_str());
}
}
if (failed_tests.size() > 0)
return TEST_STATUS_FAILED;
return TEST_STATUS_SUCCESS;
}
int run_all_tests(bool print_summary)
{
std::vector<std::string> tests;
get_all_test_names(tests);
return run_tests(print_summary, tests);
}
Test::Test(std::string name) : t_name(name)
{
register_test();
}
test_status_t Test::run()
{
test_status_t status = TEST_STATUS_FAILED;
const char *testname = t_name.c_str();
int filedes_0[2];
int filedes_1[2];
int read_fd;
int write_fd;
ASSERT_NEQ(pipe(filedes_0), -1);
ASSERT_NEQ(pipe(filedes_1), -1);
gdrcopy::test::print_dbg("&&&& RUNNING %s\n", testname);
fflush(stdout);
fflush(stderr);
pid_t pid = fork();
if (pid < 0) {
gdrcopy::test::print_dbg("Cannot fork\n");
gdrcopy::test::print_dbg("&&&& FAILED %s\n", testname);
status = TEST_STATUS_FAILED;
goto out;
}
else if (pid > 0){
int child_exit_status = -EINVAL;
pid_t group_pid;
ssize_t read_size;
close(filedes_0[1]);
close(filedes_1[0]);
read_fd = filedes_0[0];
write_fd = filedes_1[1];
read_size = read(read_fd, &group_pid, sizeof(group_pid));
if (read_size != sizeof(group_pid)) {
gdrcopy::test::print_dbg("Error in receiving group_pid\n");
gdrcopy::test::print_dbg("&&&& FAILED %s\n", testname);
status = TEST_STATUS_FAILED;
goto out;
}
close(read_fd);
close(write_fd);
if (waitpid(pid, &child_exit_status, 0) == -1) {
gdrcopy::test::print_dbg("waitpid returned an error\n");
gdrcopy::test::print_dbg("&&&& FAILED %s\n", testname);
status = TEST_STATUS_FAILED;
goto out;
}
if (!WIFEXITED(child_exit_status)) {
gdrcopy::test::print_dbg("Error: The test process got terminated\n");
gdrcopy::test::print_dbg("&&&& FAILED %s\n", testname);
status = TEST_STATUS_FAILED;
goto out;
}
child_exit_status = WEXITSTATUS(child_exit_status);
if (child_exit_status == EXIT_SUCCESS) {
gdrcopy::test::print_dbg("&&&& PASSED %s\n", testname);
status = TEST_STATUS_SUCCESS;
}
else if (child_exit_status == EXIT_WAIVED) {
gdrcopy::test::print_dbg("&&&& WAIVED %s\n", testname);
status = TEST_STATUS_WAIVED;
}
else {
gdrcopy::test::print_dbg("&&&& FAILED %s\n", testname);
status = TEST_STATUS_FAILED;
}
killpg(group_pid, SIGKILL);
goto out;
}
else {
close(filedes_0[0]);
close(filedes_1[1]);
read_fd = filedes_1[0];
write_fd = filedes_0[1];
this->run_executor(read_fd, write_fd);
}
out:
return status;
}
void Test::run_executor(int read_fd, int write_fd)
{
int status = 0;
pid_t group_pid;
status = setpgid(0, 0);
if (status)
exit(EXIT_FAILURE);
group_pid = getpgrp();
if (group_pid == -1)
exit(EXIT_FAILURE);
ASSERT_EQ(write(write_fd, &group_pid, sizeof(group_pid)), sizeof(group_pid));
close(read_fd);
close(write_fd);
this->test();
// Quit this process.
exit(EXIT_SUCCESS);
}
void Test::register_test()
{
TestMap *test_map = get_test_map();
ASSERT(test_map->find(t_name) == test_map->end());
(*test_map)[t_name] = this;
}
}
}