public void TestEmptyInput() { using (NativeRunner runner = new NativeRunner(HOST, PORT)) { var result = runner.Execute("echo", new string[] { "123" }, -1, -1, -1, RestrictionLevel.Loose, null); Assert.AreEqual(ExecuteResultType.Success, result.Type); Assert.IsTrue(Encoding.UTF8.GetString(runner.GetBlob(result.OutputBlob)).Contains("123")); } }
public void TestTLE() { using (NativeRunner runner = new NativeRunner(HOST, PORT)) { //Sleep runner.PutFile("code.cpp", Encoding.ASCII.GetBytes("#include <unistd.h>\r\n" + "int main(){" + " sleep(10);" + "}")); var result=runner.Execute("g++", new string[] { "-o", "exec", "code.cpp" }, 1024 * 1024 * 100, 5000, 1024 * 1024 * 100, RestrictionLevel.Loose, null); Assert.AreEqual(ExecuteResultType.Success, result.Type); result=runner.Execute("./exec", new string[] { }, 1024 * 1024 * 10, 1000, 1024 * 1024 * 10, RestrictionLevel.Strict, null); Assert.AreEqual(ExecuteResultType.TimeLimitExceeded, result.Type); Assert.IsTrue(result.RealTime > 1000); Assert.IsTrue(result.UserTime < 100); //While 1 runner.PutFile("code.cpp", Encoding.ASCII.GetBytes("#include <unistd.h>\r\n" + "int main(){" + " while(1)" + " ;" + "}")); result = runner.Execute("g++", new string[] { "-o", "exec", "code.cpp" }, 1024 * 1024 * 100, 5000, 1024 * 1024 * 100, RestrictionLevel.Loose, null); Assert.AreEqual(ExecuteResultType.Success, result.Type); result = runner.Execute("./exec", new string[] { }, 1024 * 1024 * 10, 1000, 1024 * 1024 * 10, RestrictionLevel.Strict, null); Assert.AreEqual(ExecuteResultType.TimeLimitExceeded, result.Type); } }
public void TestSimplePascal() { using (NativeRunner runner = new NativeRunner(HOST, PORT)) { string src = "" + "var\r\n" + " x,y:longint;\r\n" +" mem:array[0..10*1024*1024]of longint;\r\n" + "begin\r\n" + " readln(mem[0],mem[1]);\r\n" + " writeln(mem[0]+mem[1]);\r\n" + "end.\r\n"; string input = "1 2"; runner.PutFile("code.pas", Encoding.UTF8.GetBytes(src)); runner.PutBlob("input", Encoding.UTF8.GetBytes(input)); var result = runner.Execute("fpc", new[] { "-O2", "-ocode", "code.pas" }, 100 * 1024 * 1024, 3000, 10 * 1024 * 1024, RestrictionLevel.Loose, null); Assert.AreEqual(ExecuteResultType.Success, result.Type); result = runner.Execute("./code", new string[] { }, 100 * 1024 * 1024, 1000, 10 * 1024 * 1024, RestrictionLevel.Strict, "input"); var output = Encoding.ASCII.GetString(runner.GetBlob(result.OutputBlob)); Assert.AreEqual(ExecuteResultType.Success, result.Type); Assert.AreEqual("3\n", output); Assert.IsTrue(result.Memory > 4 * 1024 * 1024 * 10); } }
public void TestSimplePython() { using (NativeRunner runner = new NativeRunner(HOST, PORT)) { string src = "print(raw_input())"; string input = "Hello Python"; runner.PutBlob("input", Encoding.ASCII.GetBytes(input)); runner.PutFile("src.py", Encoding.ASCII.GetBytes(src)); var result = runner.Execute("python", new[] { "src.py" }, 100 * 1024 * 1024, 1000, 10 * 1024 * 1024, RestrictionLevel.Loose, "input"); var output = Encoding.ASCII.GetString(runner.GetBlob(result.OutputBlob)); var error = Encoding.ASCII.GetString(runner.GetBlob(result.ErrorBlob)); Assert.AreEqual(ExecuteResultType.Success, result.Type); Assert.AreEqual(input + "\n", output); } }
public void TestSimpleCPP() { using (NativeRunner runner = new NativeRunner(HOST, PORT)) { string src = "#include <cstdio>\n" + "#include <iostream>\n" + "using namespace std;" + "int main(){" + " ios::sync_with_stdio(false);" + " int x,y;" + " cin>>x>>y;" + " cout<<x+y;" + "}"; string input = "1 2"; runner.PutFile("src.cpp", Encoding.UTF8.GetBytes(src)); runner.PutBlob("input", Encoding.UTF8.GetBytes(input)); var result = runner.Execute("g++", new[] { "-o", "exe", "src.cpp" }, 100 * 1024 * 1024, 3000, 10 * 1024 * 1024, RestrictionLevel.Loose, null); Assert.AreEqual(ExecuteResultType.Success, result.Type); result = runner.Execute("./exe", new string[] { }, 100 * 1024 * 1024, 1000, 10, RestrictionLevel.Strict, "input"); Assert.AreEqual(ExecuteResultType.Success, result.Type); var output = Encoding.UTF8.GetString(runner.GetBlob(result.OutputBlob)); Assert.AreEqual("3", output); } }
public void TestSimpleC() { using (NativeRunner runner = new NativeRunner(HOST, PORT)) { string src = "#include <stdio.h>\n" + "int main(){" + " int x,y;" + " scanf(\"%d%d\",&x,&y);" + " printf(\"%d\",x+y);" + " return 0;" + "}"; string input = "1 2"; runner.PutFile("src.c", Encoding.UTF8.GetBytes(src)); runner.PutBlob("input", Encoding.UTF8.GetBytes(input)); var result = runner.Execute("gcc", new[] { "-o", "exe", "src.c" }, 100 * 1024 * 1024, 3000, 10 * 1024 * 1024, RestrictionLevel.Loose, null); Assert.AreEqual(ExecuteResultType.Success, result.Type); result = runner.Execute("./exe", new string[] { }, 100 * 1024 * 1024, 1000, 10, RestrictionLevel.Strict, "input"); Assert.AreEqual(ExecuteResultType.Success, result.Type); var output = Encoding.UTF8.GetString(runner.GetBlob(result.OutputBlob)); Assert.AreEqual("3", output); } }
bool DealRecord(NativeRunner tester,CHDB db, Guid recID, string desp) { var rec = (from r in db.RECORDs where r.ID == recID select r).FirstOrDefault(); if (null == rec) return false; StringBuilder Detail = new StringBuilder("<h5 style=\"color: red; float: right; text-align: right\">测评机:" + desp + "</h5>"); try { ExecuteResult ret = Compile(rec.Code, (Record.LanguageType)rec.Language, tester); if (ret.Type != ExecuteResultType.Success) { rec.Status = (int)Record.StatusType.Compile_Error; Detail.AppendFormat("<h5>编译失败:</h5>\r\n<pre style=\"padding-left: 10px\">\r\n{0}:<br />{1}</pre>", ret.Type.ToString(), Encoding.UTF8.GetString(tester.GetBlob(ret.ErrorBlob, 0, 10240)) + Encoding.UTF8.GetString(tester.GetBlob(ret.OutputBlob, 0, 10240))); return true; } tester.MoveFile2File(commands[(Record.LanguageType)rec.Language]["execname"][0], "exec"); string comparer = rec.PROBLEM1.Comparer == "" ? Resources.DefaultComparer : rec.PROBLEM1.Comparer; var comparerLanguage = rec.PROBLEM1.Comparer == "" ? Record.LanguageType.CPP : (Record.LanguageType)rec.PROBLEM1.ComparerLanguage; ExecuteResult CompileCMP = Compile(comparer, comparerLanguage, tester); if (CompileCMP.Type != ExecuteResultType.Success) { rec.Status = (int)Record.StatusType.CMP_Error; Detail.AppendFormat("<h5>比较器编译失败:</h5>\r\n<pre style=\"padding-left: 10px\">\r\n{0}{1}</pre>", ret.Type.ToString(), Encoding.UTF8.GetString(tester.GetBlob(ret.ErrorBlob))); return true; } tester.MoveFile2File(commands[comparerLanguage]["execname"][0], "comparer"); Detail.Append("<h5>各测试点详细信息:</h5>\r\n<div style=\"padding-left: 10px\">"); int totalTests = 0; int passedTests = 0; rec.MemoryUsed = 0; rec.ExecutedTime = 0; Guid lastHunt; lock (ContestDaemon.HuntLst) { string key = rec.User.ToString() + rec.Problem.ToString(); lastHunt = ContestDaemon.HuntLst.ContainsKey(key) ? ContestDaemon.HuntLst[key] : Guid.Empty; } foreach (var test in (from t in db.TESTDATAs where t.PROBLEM1.ID == rec.PROBLEM1.ID && (t.Available || t.ID == lastHunt) select new { t.ID, t.MemoryLimit, t.TimeLimit }).ToArray()) { totalTests++; string inputName = test.ID.ToString() + "input"; string outputName = test.ID.ToString() + "output"; if (!tester.HasBlob(inputName)) tester.PutBlob(inputName, (from t in db.TESTDATAs where t.ID == test.ID select t.Input).Single()); if (!tester.HasBlob(outputName)) tester.PutBlob(outputName, (from t in db.TESTDATAs where t.ID == test.ID select t.Data).Single()); var result = tester.Execute("./exec", new string[] { }, test.MemoryLimit, test.TimeLimit, -1, RestrictionLevel.Strict, inputName); int Time = result.UserTime; int RealTime = result.RealTime; long Memory_KB = result.Memory / 1024; long Memory = result.Memory; if (result.Type == ExecuteResultType.Success) { tester.CopyBlob2File(outputName, outputName); tester.CopyBlob2File(result.OutputBlob, result.OutputBlob); tester.CopyBlob2File(inputName, inputName); result = tester.Execute("./comparer", new string[] { outputName, result.OutputBlob, inputName }, test.MemoryLimit, test.TimeLimit, 10240, RestrictionLevel.Strict, null); switch (result.Type) { case ExecuteResultType.Success: passedTests++; rec.MemoryUsed = Math.Max((long)rec.MemoryUsed, Memory); rec.ExecutedTime += Time; Detail.AppendFormat("#{0}:<span class=\"score_100\"><b>通过</b></span> ({1} ms / {2} KB)<br />", totalTests, Time, Memory_KB); break; case ExecuteResultType.Failure: switch (result.ExitStatus) { case 1: rec.Status = (int)Record.StatusType.Wrong_Answer; Detail.AppendFormat("#{0}:<span class=\"score_0\"><b>答案错误</b></span> ({1} ms / {2} KB)<br />", totalTests, Time, Memory_KB); break; default: rec.Status = (int)Record.StatusType.CMP_Error; Detail.AppendFormat("#{0}:<span class=\"score_0\"><b>比较器错误:{1}</b></span> ({2} ms / {3} KB)<br />", totalTests, Encoding.UTF8.GetString(tester.GetBlob(result.OutputBlob)), Time, Memory_KB); break; } break; default: rec.Status = (int)Record.StatusType.CMP_Error; Detail.AppendFormat("#{0}:<span class=\"score_0\"><b>比较器错误:{1}</b></span> ({2} ms / {3} KB)<br />", totalTests, Encoding.UTF8.GetString(tester.GetBlob(result.OutputBlob)), Time, Memory_KB); break; } if (result.Type != ExecuteResultType.Success) if (rec.PROBLEM1.CONTEST1.Type != (int)Contest.ContestType.OI) break; } else { switch (result.Type) { case ExecuteResultType.MemoryLimitExceeded: rec.Status = (int)Record.StatusType.Memory_Limit_Execeeded; Detail.AppendFormat("#{0}:<span class=\"score_0\"><b>内存超过限定</b></span> ({1} ms / {2} KB)<br />", totalTests, Time, Memory_KB); break; case ExecuteResultType.Crashed: rec.Status = (int)Record.StatusType.Runtime_Error; Detail.AppendFormat("#{0}:<span class=\"score_0\"><b>运行时错误(程序崩溃)</b></span> ({1} ms / {2} KB)<br />", totalTests, Time, Memory_KB); break; case ExecuteResultType.MathError: rec.Status = (int)Record.StatusType.Runtime_Error; Detail.AppendFormat("#{0}:<span class=\"score_0\"><b>运行时错误(数学错误)</b></span> ({1} ms / {2} KB)<br />", totalTests, Time, Memory_KB); break; case ExecuteResultType.Failure: rec.Status = (int)Record.StatusType.Runtime_Error; Detail.AppendFormat("#{0}:<span class=\"score_0\"><b>运行时错误(返回值不为0)</b></span> ({1} ms / {2} KB)<br />", totalTests, Time, Memory_KB); break; case ExecuteResultType.MemoryAccessViolation: rec.Status = (int)Record.StatusType.Runtime_Error; Detail.AppendFormat("#{0}:<span class=\"score_0\"><b>运行时错误(内存不可访问)</b></span> ({1} ms / {2} KB)<br />", totalTests, Time, Memory_KB); break; case ExecuteResultType.Violation: rec.Status = (int)Record.StatusType.Runtime_Error; Detail.AppendFormat("#{0}:<span class=\"score_0\"><b>运行时错误(受限指令)</b></span> ({1} ms / {2} KB)<br />", totalTests, Time, Memory_KB); break; case ExecuteResultType.TimeLimitExceeded: rec.Status = (int)Record.StatusType.Time_Limit_Execeeded; Detail.AppendFormat("#{0}:<span class=\"score_0\"><b>超时</b></span> (Usertime={1} ms, Realtime={3} ms / {2} KB)<br />", totalTests, Time, Memory_KB,RealTime); break; case ExecuteResultType.OutputLimitExceeded: rec.Status = (int)Record.StatusType.Output_Limit_Execeeded; Detail.AppendFormat("#{0}:<span class=\"score_0\"><b>程序吐槽过多</b></span> ({1} ms / {2} KB)<br />", totalTests, Time, Memory_KB); break; } if (rec.PROBLEM1.CONTEST1.Type != (int)Contest.ContestType.OI) break; } } if (totalTests == passedTests) { rec.Status = (int)Record.StatusType.Accept; } rec.Score = (0 != totalTests ? passedTests * 100 / totalTests : 0); Detail.Append("</div>"); return true; } finally { rec.Detail = Detail.ToString(); } }
bool DealHunt(NativeRunner tester,CHDB db, Guid huntID, string desp) { var rec = (from h in db.HUNTs where h.ID == huntID select h).FirstOrDefault(); if (null == rec) return false; int TimeLimit = (from t in db.TESTDATAs where t.PROBLEM1.ID == rec.RECORD1.PROBLEM1.ID select t).Max(x => x.TimeLimit); long MemoryLimit = (from t in db.TESTDATAs where t.PROBLEM1.ID == rec.RECORD1.PROBLEM1.ID select t).Max(x => x.MemoryLimit); StringBuilder Detail = new StringBuilder("<h5 style=\"color: red; float: right; text-align: right\">测评机:" + desp + "</h5>"); try { string HuntData = null; ExecuteResult result; switch ((Record.LanguageType)rec.DataType) { default: result = Compile(rec.HuntData, (Record.LanguageType)rec.DataType, tester); if (result.Type != ExecuteResultType.Success) { rec.Status = (int)Hunt.StatusType.CompileError; Detail.Append(Encoding.UTF8.GetString(tester.GetBlob(result.ErrorBlob, 0, 10240))); break; } result = tester.Execute("./" + commands[(Record.LanguageType)rec.DataType]["execname"][0], new string[] { }, MemoryLimit, TimeLimit, 100 * 1024 * 1024, RestrictionLevel.Strict, null); if (result.Type != ExecuteResultType.Success) { rec.Status = (int)Hunt.StatusType.BadData; Detail.Append(Encoding.UTF8.GetString(tester.GetBlob(result.OutputBlob))); break; } HuntData = result.OutputBlob; break; case Record.LanguageType.Data: tester.PutBlob(HuntData = tester.RandomString(), Encoding.UTF8.GetBytes(rec.HuntData)); break; } if (null == HuntData) return true; string DataChecker = rec.RECORD1.PROBLEM1.DataChecker; result = Compile(DataChecker, (Record.LanguageType)rec.RECORD1.PROBLEM1.DataCheckerLanguage, tester); if (result.Type != ExecuteResultType.Success) { rec.Status = (int)Hunt.StatusType.DataCheckerError; Detail.Append(Encoding.UTF8.GetString(tester.GetBlob(result.ErrorBlob))); return true; } result = tester.Execute("./" + commands[(Record.LanguageType)rec.RECORD1.PROBLEM1.DataCheckerLanguage]["execname"][0], new string[] { }, MemoryLimit, TimeLimit, 100 * 1024 * 1024, RestrictionLevel.Strict, HuntData); if (result.Type != ExecuteResultType.Success) { if (result.Type == ExecuteResultType.Failure && result.ExitStatus == 1) rec.Status = (int)Hunt.StatusType.BadData; else rec.Status = (int)Hunt.StatusType.DataCheckerError; Detail.Append(result.Type.ToString() + Encoding.UTF8.GetString(tester.GetBlob(result.OutputBlob))); return true; } string stdout = result.OutputBlob; result = Compile(rec.RECORD1.Code, (Record.LanguageType)rec.RECORD1.Language, tester); if (result.Type != ExecuteResultType.Success) { rec.Status = (int)Hunt.StatusType.OtherError; Detail.Append("原记录编译失败"); return true; } result = tester.Execute("./" + commands[(Record.LanguageType)rec.RECORD1.Language]["execname"][0], new string[] { }, MemoryLimit, TimeLimit, 100 * 1024 * 1024, RestrictionLevel.Strict, HuntData); tester.MoveBlob2File(stdout, stdout); tester.MoveBlob2File(HuntData, HuntData); if (result.Type == ExecuteResultType.Success) { string userout = result.OutputBlob; string comparer = rec.RECORD1.PROBLEM1.Comparer == "" ? Resources.DefaultComparer : rec.RECORD1.PROBLEM1.Comparer; var comparerLanguage = rec.RECORD1.PROBLEM1.Comparer == "" ? Record.LanguageType.CPP : (Record.LanguageType)rec.RECORD1.PROBLEM1.ComparerLanguage; result = Compile(comparer, comparerLanguage, tester); if (result.Type != ExecuteResultType.Success) { rec.Status = (int)Hunt.StatusType.OtherError; Detail.Append("比较器编译失败"); return true; } tester.MoveBlob2File(userout, userout); result = tester.Execute("./" + commands[comparerLanguage]["execname"][0], new string[] { stdout, userout, HuntData }, MemoryLimit, TimeLimit, 10 * 1024, RestrictionLevel.Strict, null); if (result.Type == ExecuteResultType.Failure && result.ExitStatus == 1) { var newid = Guid.NewGuid(); rec.RECORD1.PROBLEM1.TESTDATAs.Add(new TESTDATA() { ID = newid, Available = false, MemoryLimit = MemoryLimit, TimeLimit = TimeLimit, Data = tester.GetFile(stdout), Input = tester.GetFile(HuntData) }); rec.RECORD1.Status = (int)Record.StatusType.Hacked; rec.Status = (int)Hunt.StatusType.Success; lock (ContestDaemon.HuntLst) { string key = rec.RECORD1.User.ToString() + rec.RECORD1.Problem.ToString(); if (!ContestDaemon.HuntLst.ContainsKey(key)) ContestDaemon.HuntLst.Add(key, newid); else ContestDaemon.HuntLst[key] = newid; } return true; } else if (result.Type == ExecuteResultType.Success) { rec.Status = (int)Hunt.StatusType.Fail; return true; } else { rec.Status = (int)Hunt.StatusType.OtherError; Detail.Append("比较器错误"); return true; } } else { Guid newid = Guid.NewGuid(); rec.RECORD1.PROBLEM1.TESTDATAs.Add(new TESTDATA() { ID = newid, Available = false, MemoryLimit = MemoryLimit, TimeLimit = TimeLimit, Data = tester.GetFile(stdout), Input = tester.GetFile(HuntData) }); rec.RECORD1.Status = (int)Record.StatusType.Hacked; rec.Status = (int)Hunt.StatusType.Success; lock (ContestDaemon.HuntLst) { string key = rec.RECORD1.User.ToString() + rec.RECORD1.Problem.ToString(); if (!ContestDaemon.HuntLst.ContainsKey(key)) ContestDaemon.HuntLst.Add(key, newid); else ContestDaemon.HuntLst[key] = newid; } return true; } } finally { rec.Detail = Detail.ToString(); } }
ExecuteResult Compile(string code,Record.LanguageType language,NativeRunner runner) { runner.PutFile("code."+commands[language]["extname"][0],Encoding.UTF8.GetBytes(code)); return runner.Execute(commands[language]["compile"][0],commands[language]["compileargv"],CompileMemory,CompileTime,-1,RestrictionLevel.Loose,null); }