public Problem(ulong id, Test[] tests, ProblemFile checker, byte checkerCompilerId, DateTime lastUpdate) { Id = id; Tests = tests ?? throw new ArgumentNullException(nameof(tests)); Checker = checker ?? throw new ArgumentNullException(nameof(checker)); CheckerCompilerId = checkerCompilerId; LastUpdate = lastUpdate; }
public void RemoveFile(ProblemFile file) { if (file.Content == null && file.id != null) { File.Delete(Path.Combine(directory, file.id)); } else { file.Content = null; } }
public void Copy(ProblemFile file, string path) { if (file.Content == null) { File.Copy(Path.Combine(directory, file.id), path, true); } else { File.WriteAllBytes(path, file.Content); } }
public void SaveFile(ProblemFile file) { if (file.Content != null) { if (string.IsNullOrEmpty(file.id)) { file.id = Guid.NewGuid().ToString(); } File.WriteAllBytes( Path.Combine(directory, file.id), file.Content); file.Content = null; } }
private bool compileSolution(string workdir, ProblemFile solution, Compiler compiler) { string sourceFilename = $"solution{compiler.FileExt}"; string sourceFullPath = Path.Combine(workdir, sourceFilename); string compilerLogFullPath = Path.Combine(workdir, Application.Get().Configuration.CompilerLogFileName); Application.Get().FileProvider.Copy(solution, sourceFullPath); var replacement = GenerateReplacementDictionary( sourceFullPath: sourceFullPath, sourceFilename: sourceFilename, binaryFullPath: Path.Combine(workdir, solutionBinaryFilename), binaryFilename: solutionBinaryFilename, workDirecrory: workdir, compilerLogFilename: Application.Get().Configuration.CompilerLogFileName, compilerLogFullPath: compilerLogFullPath ); return(compile(workdir, compiler, replacement, compilerLogFullPath, false)); }
public WorkerResult Testing(Submission submission, Problem problem, ProblemFile solution) { string workdir = new DirectoryInfo(Path.Combine(Application.Get().Configuration.TestingWorkDirectory, Guid.NewGuid().ToString())).FullName; Directory.CreateDirectory(workdir); logger.Info("Slot {0} starting testing at {1}", slotNum, workdir); Compiler checkerCompiler = Application.Get().Compilers.GetCompiler(problem.CheckerCompilerId); Compiler solutionCompiler = Application.Get().Compilers.GetCompiler(submission.CompilerId); string inputFileFullPath = Path.Combine(workdir, Application.Get().Configuration.InputFileName); string outputFileFullPath = Path.Combine(workdir, Application.Get().Configuration.OutputFileName); string answerFileFullPath = Path.Combine(workdir, Application.Get().Configuration.AnswerFileName); string reportFileFullPath = Path.Combine(workdir, Application.Get().Configuration.ReportFileName); string compilerLogFileFullPath = Path.Combine(workdir, Application.Get().Configuration.CompilerLogFileName); if (!compileChecker(workdir, problem.Checker, checkerCompiler)) { SubmissionLog log = new SubmissionLog(); log.SubmissionId = submission.Id; log.Type = SubmissionLogType.Checker; log.Data = File.ReadAllText(compilerLogFileFullPath); Application.Get().RequestMessages.Enqueue(apiClient.GetSendLogRequestMessage(log)); return(WorkerResult.TestingError); } { bool st = compileSolution(workdir, solution, solutionCompiler); SubmissionLog log = new SubmissionLog(); log.SubmissionId = submission.Id; log.Type = SubmissionLogType.Source; log.Data = File.ReadAllText(compilerLogFileFullPath); if (!string.IsNullOrWhiteSpace(log.Data)) { Application.Get().RequestMessages.Enqueue(apiClient.GetSendLogRequestMessage(log)); } if (!st) { return(WorkerResult.CompilerError); } } for (uint i = 0; i < problem.Tests.Length; i++) { logger.Info("Slot {0}: Starting testing test with num {1}", slotNum, problem.Tests[i].Num); logger.Info("Slot {0}: Preparion solution start enviroment", slotNum); logger.Debug("Slot {0}: Copy input file.", slotNum); Application.Get().FileProvider.Copy(problem.Tests[i].Input, inputFileFullPath); TestResult testResult = new TestResult(); testResult.SubmissionId = submission.Id; testResult.TestId = problem.Tests[i].Id; { Tester tester = new Tester(); var replacement = GenerateReplacementDictionary( binaryFullPath: Path.Combine(workdir, solutionBinaryFilename), binaryFilename: solutionBinaryFilename, workDirecrory: workdir); string program = solutionCompiler.RunCommand.Program.ReplaceByDictionary(re, replacement); string args = solutionCompiler.RunCommand.Arguments.ReplaceByDictionary(re, replacement); tester.SetProgram(program, $"\"{program}\" {args}"); tester.SetWorkDirectory(workdir); tester.SetRealTimeLimit(submission.RealTimeLimit); tester.SetMemoryLimit(submission.MemoryLimit); tester.RedirectIOHandleToFile(IOHandleType.Input, inputFileFullPath); tester.RedirectIOHandleToFile(IOHandleType.Output, outputFileFullPath); tester.RedirectIOHandleToHandle(IOHandleType.Error, tester.GetIORedirectedHandle(IOHandleType.Output)); logger.Info("Slot {0}: Run solution", slotNum); if (tester.Run(true)) { logger.Info("Slot {0}: Solution run successfully", slotNum); } else { logger.Error("Slot {0}: Can't run solution", slotNum); return(WorkerResult.TestingError); } var waitStatus = tester.Wait(); if (waitStatus == WaitingResult.Ok) { logger.Debug("Slot {0}: Waited successfully", slotNum); } else if (waitStatus == WaitingResult.Timeout) { testResult.UsedMemmory = tester.GetUsedResources().PeakMemoryUsageKB; testResult.WorkTime = tester.GetUsedResources().RealTimeUsageMS; testResult.Result = TestingResult.TimeLimitExceeded; Application.Get().RequestMessages.Enqueue(apiClient.GetSendTestingResultRequestMessage(testResult)); logger.Info("Slot {0}: Wait timeouted", slotNum); //Not start checker tester.Destroy(); continue; } else { logger.Error("Slot {0}: Wait failed", slotNum); return(WorkerResult.TestingError); } uint exitCode = tester.GetExitCode(); if (exitCode == 0) { logger.Info("Slot {0}: Solution exited successfully", slotNum); } else { testResult.UsedMemmory = tester.GetUsedResources().PeakMemoryUsageKB; testResult.WorkTime = tester.GetUsedResources().CPUWorkTimeMS; testResult.Result = TestingResult.RuntimeError; Application.Get().RequestMessages.Enqueue(apiClient.GetSendTestingResultRequestMessage(testResult)); logger.Info("Slot {0}: Solution exit with code {1}", slotNum, exitCode); //Not start checker tester.Destroy(); continue; } testResult.UsedMemmory = tester.GetUsedResources().PeakMemoryUsageKB; testResult.WorkTime = tester.GetUsedResources().CPUWorkTimeMS; tester.Destroy(); } if (testResult.WorkTime > submission.TimeLimit) { testResult.Result = TestingResult.TimeLimitExceeded; Application.Get().RequestMessages.Enqueue(apiClient.GetSendTestingResultRequestMessage(testResult)); logger.Info("Slot {0}: Solution work {1}ms and time limit {2}ms", slotNum, testResult.WorkTime, submission.TimeLimit); //Not start checker continue; } if (testResult.UsedMemmory > submission.MemoryLimit) { testResult.Result = TestingResult.MemoryLimitExceeded; Application.Get().RequestMessages.Enqueue(apiClient.GetSendTestingResultRequestMessage(testResult)); logger.Info("Slot {0}: Solution used {1}kb memory and memory limit {2}kb", slotNum, testResult.UsedMemmory, submission.MemoryLimit); //Not start checker continue; } logger.Info("Slot {0}: Preparion checker start enviroment", slotNum); logger.Info("Slot {0}: Copy answer file.", slotNum); Application.Get().FileProvider.Copy(problem.Tests[i].Answer, answerFileFullPath); { Tester tester = new Tester(); var replacement = GenerateReplacementDictionary( binaryFullPath: Path.Combine(workdir, checkerBinaryFilename), binaryFilename: checkerBinaryFilename, workDirecrory: workdir, inputFilePath: inputFileFullPath, outputFilePath: outputFileFullPath, answerFilePath: answerFileFullPath, reportFilePath: reportFileFullPath); string program = checkerCompiler.RunCommand.Program.ReplaceByDictionary(re, replacement); string args = $"{checkerCompiler.RunCommand.Arguments} {checkerCompiler.RunCommand.CheckerArguments}". ReplaceByDictionary(re, replacement); tester.SetProgram(program, $"\"{program}\" {args}"); tester.SetWorkDirectory(workdir); tester.SetRealTimeLimit(60 * 1000); //tester.RedirectIOHandleToFile(IOHandleType.Output, reportFileFullPath); //tester.RedirectIOHandleToHandle(IOHandleType.Error, tester.GetIORedirectedHandle(IOHandleType.Output)); logger.Info("Slot {0}: Run checker", slotNum); if (tester.Run()) { logger.Info("Slot {0}: Checker run successfully", slotNum); } else { logger.Error("Slot {0}: Can't run checker", slotNum); return(WorkerResult.TestingError); } if (tester.Wait() == WaitingResult.Ok) { logger.Debug("Slot {0}: Waited successfully", slotNum); } else { logger.Error("Slot {0}: Wait failed", slotNum); return(WorkerResult.TestingError); } uint exitCode = tester.GetExitCode(); logger.Info("Slot {0}: Checker exit with code {1}", slotNum, exitCode); testResult.Result = (TestingResult)exitCode; testResult.Log = File.ReadAllText(reportFileFullPath); Application.Get().RequestMessages.Enqueue(apiClient.GetSendTestingResultRequestMessage(testResult)); tester.Destroy(); } } try { Directory.Delete(workdir, true); } catch (Exception ex) { logger.Error(ex, "Slot {0}: Can not delete work directory.", slotNum); } return(WorkerResult.Ok); }
public void LoadContent(ProblemFile file) { file.Content = null; file.Content = File.ReadAllBytes( Path.Combine(directory, file.id)); }
public void Do(CancellationToken token) { Application app = Application.Get(); while (!token.IsCancellationRequested) { var submissions = client.GetSuitableSubmissions(app.Compilers.GetCompilers()); if (!submissions.Any()) { Thread.Sleep(app.Configuration.GetSubmissionDelayMs); continue; } var submission = submissions.First(); if (!client.SendRequest(client.GetTakeSubmissionsRequestMessage(submission.Id))) { continue; } logger.Info("Testing slot {0} taken submission with id {1}", slotNumber, submission.Id); logger.Debug("Submission: {0}", submission); WorkerResult result = WorkerResult.Ok; ProblemFile solution = client.DownloadSolution(submission); app.FileProvider.SaveFile(solution); Problem problem = app.Problems.FetchProblem( submission.ProblemId, submission.ProblemUpdatedAt, () => { logger.Debug("Need download problem with id {0}", submission.ProblemId); var downloadedProblem = client.DownloadProblem(submission.ProblemId); if (downloadedProblem is null) { logger.Error("Failed to download problem with id {0}", submission.ProblemId); result = WorkerResult.TestingError; } return(downloadedProblem); } ); Worker worker = new Worker(slotNumber, client); if (result != WorkerResult.TestingError) { try { result = worker.Testing(submission, problem, solution); } catch (Exception ex) { logger.Error("Slot {0} worker testing failed with exception {1}. Error {2}", slotNumber, ex.GetType().Name, ex); result = WorkerResult.TestingError; } } switch (result) { case WorkerResult.Ok: case WorkerResult.CompilerError: app.RequestMessages.Enqueue(client.GetReleaseSubmissionsRequestMessage(submission.Id, result)); break; case WorkerResult.TestingError: app.RequestMessages.Enqueue(client.GetFailSubmissionsRequestMessage(submission.Id)); break; } } token.ThrowIfCancellationRequested(); }