#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; }; template T getValueOrPanic(T value); int main(int argc, char* argv[]) { LOG("Zengtudor OI test tools . loading files .. please add a json file in arg"); printValue(argv[0]) AS_EQ(argc,2) std::filesystem::path jsonPath(argv[1]); if (!jsonPath.is_absolute()) { LOG("The path is not absolute, changing it") jsonPath = std::filesystem::current_path()/jsonPath; } LOG("getting json files current dir") LOG(jsonPath) AS_EM(std::filesystem::exists(jsonPath), true, "Please create the json file,the json file was not exist") LOG("getting project path") const auto projectPath = jsonPath.parent_path(); LOG(projectPath) LOG("will use g++ compiler") LOG("checking g++ compiler version") int sys_ret = system("g++ --version"); AS_EM(sys_ret,0,"get g++ --version failed") const auto buildDir = projectPath / "build"; LOG("getting build dir") LOG(buildDir) LOG("parsing json file") ifstream jsonFileStream(jsonPath); Json::Value jsonValue; Json::Reader jsonReader; jsonReader.parse(jsonFileStream,jsonValue); AS_NM(jsonValue["files"], Json::nullValue, "cannot read the json value `files` array") string projectFilesBuildString; LOG("parsing files in json values") for(auto i:jsonValue["files"]){ projectFilesBuildString = projectFilesBuildString + " " +getProtectPath(getAbsolutePath(projectPath, std::filesystem::path(i.asString()))); } printValue(projectFilesBuildString) LOG("parsing g++ compiler args") string compileArgs; for(auto i:jsonValue["args"]){ compileArgs = compileArgs + " "+i.asString(); } printValue(compileArgs) if(std::filesystem::exists(buildDir)==false){ LOG("creating building dir") std::filesystem::create_directory(buildDir); } LOG("compiling") string compileCommands; const path exePath = (buildDir/"main").string()+(isWindows==true?".exe":""); printValue(exePath) compileCommands=compileCommands+"g++ "+"-o "+getProtectPath(exePath)+" "+projectFilesBuildString+" "+compileArgs; printValue(compileCommands) AS_EM(system(compileCommands.c_str()), 0, "compile the program failed") auto cpuNums = getCpuNums(); printValue(cpuNums) if(jsonValue["tests"].size()==0)LOG("cannot find tests"); LOG("parsing tests") vector tests; auto &jsonTests = jsonValue["tests"]; for(unsigned int i=1;i<=jsonTests.size();i++){ tests.push_back({ .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(auto i:tests){ tasks.push([i,&exePathStr,&testsPath]()->ProgramRet{ string commands; std::stringstream ss; ss<>id_str; path outPath = testsPath/(id_str+".out") ; commands = commands+exePathStr+" < "+getProtectPath(i.in)+" > "+getProtectPath(outPath); LOG(commands) auto start = high_resolution_clock::now(); system(commands.c_str()); auto end=high_resolution_clock::now(); return ProgramRet{ .start=start, .end = end }; }); } while(tasks.size()>0){ auto i = tasks.front(); tasks.pop(); thread newThread(i); AS_EQ(newThread.joinable(),true); newThread.join(); } } string getProtectPath(const std::filesystem::path &p){ return "\""+p.string()+"\""; } template 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; }