upd: set up files and CMake

This commit is contained in:
2023-11-29 01:26:53 +00:00
parent ad155603ba
commit f2d9f9086a
18 changed files with 148 additions and 2 deletions

3
.gitignore vendored
View File

@ -2,4 +2,5 @@
/.vscode
/maintenance/test/data
.clang-format
/frontend/node_modules
/frontend/node_modules
/build

View File

@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.15.2)
project(BookStore)
file(GLOB_RECURSE main_src backend/src/*.cpp)
include_directories(${PROJECT_SOURCE_DIR}/backend/include)
add_executable(code ${main_src})
add_subdirectory(maintenance/test)
include(maintenance/test/ctest_config)

View File

View File

View File

0
backend/include/engine.h Normal file
View File

View File

View File

0
backend/src/database.cpp Normal file
View File

View File

0
backend/src/engine.cpp Normal file
View File

1
backend/src/main.cpp Normal file
View File

@ -0,0 +1 @@
int main() { return 0; }

0
backend/src/schedule.cpp Normal file
View File

View File

@ -43,7 +43,7 @@ memoryriver类维护一个缓存简单地缓存高频访问和连续访问
### 引擎模块
具体执行业务一次请求对应且只对应一次引擎模块API调用支持并行API阻塞但可同时运行。当API入口函数被调用后执行相关具体操作包括会话管理然后返回响应。
### 通信与调度模块
### 调度模块
负责对外提供文本模式的交互,以及维护请求级的并行。从流`request`读取文本格式的命令并把内部数据格式的响应翻译成文本格式向引擎模块发送请求调用引擎模块对外提供的API并把响应返回到流`response`。支持条件允许时的并行:
- 输入子模块从`request`读取请求,打上时间戳,分独占式请求和可并行请求按时间戳顺序分批处理。处理一个请求时,启动一个工作线程调用翻译子模块。同一个会话的请求不可并行,把`std::thread`move进相应的该会话的工作线程句柄队列下一个join前一个。成批执行可并行请求时启动完当前批次所有工作线程后join每个session的最后一个工作线程结束之后就可以执行下一批了。为了在服务模式下处理时有时无的请求两个流在读取时是阻塞的自己封装一个`std::condition_variable`通讯),并且读一个处理一个,碰到“不属于自己批次”的东西才算一批结束。
- 翻译子模块(入口函数本身阻塞)join完同一个session的上一个请求后向引擎模块API发送请求得到响应后把响应数据传给输出子模块的调用接口(阻塞但可并行,处理部分同时运行,上锁后直接输出到`response`,输出本身不同时进行)。

View 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)

View 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"},
]
}

View File

View 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;
}