#include "json/reader.h" #include "json/value.h" #include #include #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #else #include "unistd.h" #endif using std::cerr,std::endl,std::cout,std::ifstream,std::string,std::vector,std::queue,std::filesystem::path,std::thread,std::chrono::time_point,std::chrono::steady_clock,std::chrono::high_resolution_clock,std::chrono::system_clock,std::filesystem::exists; #define AS_EQ(a,b){if((a)!=(b)){cerr<<"assert eq failed :"< start; time_point end; #else time_point start; time_point end; #endif path outPath; unsigned int id; friend std::ostream& operator<<(std::ostream&os,ProgramRet&ret){ os<<"ProgramRet { start: "< T getValueOrPanic(T value); int compareFiles(const std::string& path1, const std::string& path2); struct Statu{ bool isTLE = false; int cmp; int id; friend std::ostream& operator<<(std::ostream &os,Statu &s){ if(s.isTLE){ os<<"tests "< tests(jsonValue["tests"].size()+1); auto &jsonTests = jsonValue["tests"]; for(unsigned int i=1;i<=jsonTests.size();i++){ tests[i]={ .id = i, .in=getAbsolutePath(projectPath, getValueOrPanic(jsonTests[i-1]["in"]).asString()), .ans=getAbsolutePath(projectPath,getValueOrPanic(jsonTests[i-1]["ans"]).asString()), }; } queue> tasks; const auto testsPath = projectPath/"tests"; if(!exists(testsPath)){ LOG("creating the test dir") std::filesystem::create_directory(testsPath); } printValue(testsPath) const string exePathStr = getProtectPath(exePath); for (int j=1;j<=jsonTests.size();j++) { auto &i = tests[j]; tasks.push([i, &exePathStr, &testsPath]() -> ProgramRet { string id_str = std::to_string(i.id); path outPath = testsPath / (id_str + ".out"); // 构建命令 string commands = exePathStr + " < " + getProtectPath(i.in) + " > " + getProtectPath(outPath); // 输出构建的命令进行调试 LOG(commands); // 执行命令 auto start = high_resolution_clock::now(); int result = system(commands.c_str()); auto end = high_resolution_clock::now(); if (result != 0) { cerr << "Error executing command: " << commands << endl; exit(1); } return ProgramRet{ .start = start, .end = end, .outPath=outPath, .id=i.id }; }); } vector> futures; while(tasks.size()>0){ auto i = tasks.front(); tasks.pop(); futures.push_back(std::async(std::launch::async,i)); } vector results(jsonTests.size()+1); for(auto &i:futures){ if(runtimeout>0){ if(i.wait_for(std::chrono::milliseconds(runtimeout))==std::future_status::ready){ auto ret = i.get(); results[ret.id]=ret; } }else{ i.wait(); auto ret = i.get(); results[ret.id]=ret; } } LOG("get results done") for(int i=1;i<=jsonTests.size();i++){ LOG(results[i]) } vector status(jsonTests.size()+1); for(int i=1;i<=jsonTests.size();i++){ printValue(tests[i].ans) status[i]={ .isTLE=(results[i].id==0?true:false), .cmp=compareFiles(results[i].outPath,tests[i].ans), .id=i }; } for(int i=1;i<=jsonTests.size();i++){ cout< T getValueOrPanic(T value){ AS_NE(value, Json::nullValue) return value; } std::filesystem::path getAbsolutePath(std::filesystem::path rootPath,std::filesystem::path filePath){ if(filePath.is_absolute()==false){ filePath = rootPath/filePath; } return filePath; }