upd: add test in CMake
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,7 +1,6 @@
|
|||||||
/.devcontainer
|
/.devcontainer
|
||||||
/.vscode
|
/.vscode
|
||||||
/maintenance/test
|
/maintenance/test/data
|
||||||
/maintenance/demo
|
|
||||||
.clang-format
|
.clang-format
|
||||||
/frontend/Web/node_modules
|
/frontend/Web/node_modules
|
||||||
/frontend/client/node_modules
|
/frontend/client/node_modules
|
||||||
|
7
maintenance/test/CMakeLists.txt
Normal file
7
maintenance/test/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
set(PROJECT_NAME ${CMAKE_PROJECT_NAME})
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_FLAGS "-O2")
|
||||||
|
set(ENV{MAKEFLAGS} "-j16")
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/external)
|
||||||
|
add_executable(test-core test-core.cpp)
|
||||||
|
target_precompile_headers(test-core PUBLIC ${PROJECT_SOURCE_DIR}/external/clipp/clipp.h ${PROJECT_SOURCE_DIR}/external/json/json.hpp)
|
8
maintenance/test/config.json
Normal file
8
maintenance/test/config.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"StatusInterpreter":{"0":"OK","1":"Wrong Answer","139":"Segmentation fault","137":"(Killed) maybe Time Limit Error"},
|
||||||
|
"Cases":
|
||||||
|
[
|
||||||
|
{"command":"cd /workspaces/BH-Bookstore-2023 && timeout -s 9 1s build/code <test/testcases/basic-testcases/test0.in >/tmp/B0.out && diff -u /tmp/B0.out test/testcases/basic-testcases/test0.out >/tmp/diff_B0","uid":"#0","tid":"/1/0"},
|
||||||
|
{"command":"cd /workspaces/BH-Bookstore-2023 && timeout -s 9 3s build/code <test/testcases/bigint-testcases/BigIntegerTest0.in >/tmp/I0.out && diff -u /tmp/I0.out test/testcases/bigint-testcases/BigIntegerTest0.out >/tmp/diff_I0","uid":"#14","tid":"/2/0"},
|
||||||
|
]
|
||||||
|
}
|
0
maintenance/test/ctest_config
Normal file
0
maintenance/test/ctest_config
Normal file
122
maintenance/test/test-core.cpp
Normal file
122
maintenance/test/test-core.cpp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#include <cstdlib>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "clipp/clipp.h"
|
||||||
|
#include "json/json.hpp"
|
||||||
|
std::string getDirectory(const std::string &filepath) {
|
||||||
|
size_t found = filepath.find_last_of("/\\");
|
||||||
|
return filepath.substr(0, found);
|
||||||
|
}
|
||||||
|
#define DeEscape std::string
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
bool continuous = false;
|
||||||
|
bool test_all = false;
|
||||||
|
bool test_listed_cases = false;
|
||||||
|
std::vector<std::string> listed_cases;
|
||||||
|
std::string filePath(__FILE__);
|
||||||
|
std::string directoryPath = getDirectory(filePath);
|
||||||
|
std::string config_file = directoryPath + "/config.json";
|
||||||
|
bool use_custoem_config = false;
|
||||||
|
std::string new_config = "";
|
||||||
|
bool test_sub_tree = false;
|
||||||
|
std::string sub_tree;
|
||||||
|
bool read_lists_from_stdin = false;
|
||||||
|
bool read_lists_from_file = false;
|
||||||
|
std::string list_file_path;
|
||||||
|
// clang-format off
|
||||||
|
auto cli=(
|
||||||
|
clipp::option("--config").set(config_file).doc("config file path") & clipp::value("config file path",config_file),
|
||||||
|
clipp::option("-c","--continuous").set(continuous).doc("continuous mode"),
|
||||||
|
(
|
||||||
|
clipp::required("-a","--all").set(test_all).doc("test all")|
|
||||||
|
(clipp::required("-s","--subtree").set(test_sub_tree).doc("test subtree") & clipp::value("subtree",sub_tree))|
|
||||||
|
(clipp::required("-l","--list").set(test_listed_cases).doc("test listed cases") & clipp::values("cases",listed_cases))|
|
||||||
|
(clipp::required("-i","--stdin").set(read_lists_from_stdin).doc("read test list from stdin"))|
|
||||||
|
(clipp::required("-f","--filelist").set(read_lists_from_file).doc("read test list from file") & clipp::value("file",list_file_path))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// clang-format on
|
||||||
|
if (!clipp::parse(argc, argv, cli)) {
|
||||||
|
std::cout << clipp::make_man_page(cli, argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (use_custoem_config) config_file = new_config;
|
||||||
|
using json = nlohmann::json;
|
||||||
|
std::ifstream conf(config_file);
|
||||||
|
json config = json::parse(conf);
|
||||||
|
std::unordered_map<std::string, std::string> index;
|
||||||
|
for (int i = 0; i < config["Cases"].size(); i++) {
|
||||||
|
index[DeEscape(config["Cases"][i]["tid"])] =
|
||||||
|
DeEscape(config["Cases"][i]["command"]);
|
||||||
|
index[DeEscape(config["Cases"][i]["uid"])] =
|
||||||
|
DeEscape(config["Cases"][i]["command"]);
|
||||||
|
}
|
||||||
|
if (test_all) {
|
||||||
|
listed_cases.clear();
|
||||||
|
for (int i = 0; i < config["Cases"].size(); i++) {
|
||||||
|
listed_cases.push_back(DeEscape(config["Cases"][i]["tid"]));
|
||||||
|
}
|
||||||
|
} else if (test_sub_tree) {
|
||||||
|
listed_cases.clear();
|
||||||
|
for (int i = 0; i < config["Cases"].size(); i++) {
|
||||||
|
if (DeEscape(config["Cases"][i]["tid"]).find(sub_tree) == 0 &&
|
||||||
|
(DeEscape(config["Cases"][i]["tid"]).length() == sub_tree.length() ||
|
||||||
|
DeEscape(config["Cases"][i]["tid"])[sub_tree.length()] == '/')) {
|
||||||
|
listed_cases.push_back(DeEscape(config["Cases"][i]["tid"]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (read_lists_from_stdin) {
|
||||||
|
listed_cases.clear();
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(std::cin, line)) {
|
||||||
|
listed_cases.push_back(line);
|
||||||
|
}
|
||||||
|
} else if (read_lists_from_file) {
|
||||||
|
listed_cases.clear();
|
||||||
|
std::ifstream list_file(list_file_path);
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(list_file, line)) {
|
||||||
|
listed_cases.push_back(line);
|
||||||
|
}
|
||||||
|
} else if (!test_listed_cases)
|
||||||
|
throw std::runtime_error("No test cases specified");
|
||||||
|
int total_cases = 0, total_passed = 0;
|
||||||
|
for (int i = 0; i < listed_cases.size(); i++) {
|
||||||
|
std::cerr << "Testing " << listed_cases[i] << std::endl;
|
||||||
|
if (index.find(listed_cases[i]) == index.end()) {
|
||||||
|
std::cerr << "Test " << listed_cases[i] << " not found" << std::endl;
|
||||||
|
std::cerr << '\n' << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::cerr << "Command = " << index[listed_cases[i]] << std::endl;
|
||||||
|
int status = system(index[listed_cases[i]].c_str()) / 256;
|
||||||
|
total_cases++;
|
||||||
|
if (status == 0) total_passed++;
|
||||||
|
if (status == 0) {
|
||||||
|
std::cerr << "Test " << listed_cases[i] << " passed" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cerr << "Test " << listed_cases[i] << " failed" << std::endl;
|
||||||
|
std::cerr << "status code = " << status << std::endl;
|
||||||
|
std::cerr
|
||||||
|
<< "Brief info: "
|
||||||
|
<< (config["StatusInterpreter"].contains(std::to_string(status))
|
||||||
|
? DeEscape(
|
||||||
|
config["StatusInterpreter"][std::to_string(status)])
|
||||||
|
: std::string("Unknown Error"))
|
||||||
|
<< std::endl;
|
||||||
|
if (!continuous) {
|
||||||
|
std::cerr << total_passed << "/" << total_cases << " cases passed"
|
||||||
|
<< std::endl;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cerr << total_passed << "/" << total_cases << " cases passed"
|
||||||
|
<< std::endl;
|
||||||
|
std::cerr << '\n' << std::endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} // Path: maintenance/test/test-core.cpp
|
Reference in New Issue
Block a user