private void ProcessSubmission(Submission submission)
        {
            // TODO: Check for N+1 queries problem
            this.logger.InfoFormat("Work on submission №{0} started.", submission.Id);

            var executionStrategy = this.CreateExecutionStrategy(submission.SubmissionType.ExecutionStrategyType);
            var context = new ExecutionContext
            {
                SubmissionId = submission.Id,
                AdditionalCompilerArguments = submission.SubmissionType.AdditionalCompilerArguments,
                CheckerAssemblyName = submission.Problem.Checker.DllFile,
                CheckerParameter = submission.Problem.Checker.Parameter,
                CheckerTypeName = submission.Problem.Checker.ClassName,
                FileContent = submission.Content,
                AllowedFileExtensions = submission.SubmissionType.AllowedFileExtensions,
                CompilerType = submission.SubmissionType.CompilerType,
                MemoryLimit = submission.Problem.MemoryLimit,
                TimeLimit = submission.Problem.TimeLimit,
            };

            context.Tests = submission.Problem.Tests.ToList().Select(x => new TestContext
            {
                Id = x.Id,
                Input = x.InputDataAsString,
                Output = x.OutputDataAsString,
                IsTrialTest = x.IsTrialTest
            });

            ExecutionResult executionResult;
            try
            {
                executionResult = executionStrategy.Execute(context);
            }
            catch (Exception exception)
            {
                this.logger.ErrorFormat("executionStrategy.Execute on submission №{0} has thrown an exception: {1}", submission.Id, exception);
                submission.ProcessingComment = string.Format("Exception in executionStrategy.Execute: {0}", exception.Message);
                return;
            }

            submission.IsCompiledSuccessfully = executionResult.IsCompiledSuccessfully;
            submission.CompilerComment = executionResult.CompilerComment;

            if (!executionResult.IsCompiledSuccessfully)
            {
                return;
            }

            foreach (var testResult in executionResult.TestResults)
            {
                var testRun = new TestRun
                {
                    CheckerComment = testResult.CheckerDetails.Comment,
                    ExpectedOutputFragment = testResult.CheckerDetails.ExpectedOutputFragment,
                    UserOutputFragment = testResult.CheckerDetails.UserOutputFragment,
                    ExecutionComment = testResult.ExecutionComment,
                    MemoryUsed = testResult.MemoryUsed,
                    ResultType = testResult.ResultType,
                    TestId = testResult.Id,
                    TimeUsed = testResult.TimeUsed,
                };
                submission.TestRuns.Add(testRun);
            }

            this.logger.InfoFormat("Work on submission №{0} ended.", submission.Id);
        }
        public void Copy(OjsDbContext context, TelerikContestSystemEntities oldDb)
        {
            var tests = context.Tests.Select(x => new { x.Id, x.ProblemId, x.IsTrialTest, x.OrderBy }).ToList();

            var count = oldDb.Submissions.Count();
            const int ElementsByIteration = 500;
            var iterations = Math.Ceiling((decimal)count / ElementsByIteration);
            for (int i = 0; i < iterations; i++)
            {
                GC.Collect();
                var newDb = new OjsDbContext();
                newDb.Configuration.AutoDetectChangesEnabled = false;
                newDb.Configuration.ValidateOnSaveEnabled = false;
                var csharpSubmissionType = newDb.SubmissionTypes.FirstOrDefault(x => x.Name == "C# code");
                var cplusPlusSubmissionType = newDb.SubmissionTypes.FirstOrDefault(x => x.Name == "C++ code");
                var javaScriptSubmissionType =
                    newDb.SubmissionTypes.FirstOrDefault(x => x.Name == "JavaScript code (NodeJS)");

                oldDb = new TelerikContestSystemEntities();
                var dataSource =
                    oldDb.Submissions.AsNoTracking()
                        .Where(x => x.Id != 127774)
                        .OrderBy(x => x.Id)
                        .Skip(i * ElementsByIteration)
                        .Take(ElementsByIteration);

                foreach (var oldSubmission in dataSource)
                {
                    var problem = newDb.Problems.FirstOrDefault(x => x.OldId == oldSubmission.Task);
                    var participant = newDb.Participants.FirstOrDefault(x => x.OldId == oldSubmission.Participant);
                    var submission = new Submission
                                         {
                                             Content = oldSubmission.File.ToText().Compress(),
                                             PreserveCreatedOn = true,
                                             CreatedOn = oldSubmission.SubmittedOn,
                                             Problem = problem,
                                             Participant = participant,
                                             Points = oldSubmission.Points,
                                             Processed = true,
                                             Processing = false,
                                         };

                    switch (oldSubmission.Language)
                    {
                        case "C# Code":
                            submission.SubmissionType = csharpSubmissionType;
                            break;
                        case "C++ Code":
                            submission.SubmissionType = cplusPlusSubmissionType;
                            break;
                        case "JavaScript Code":
                            submission.SubmissionType = javaScriptSubmissionType;
                            break;
                        case "C + + 觐�":
                            submission.SubmissionType = cplusPlusSubmissionType;
                            break;
                        default:
                            submission.SubmissionType = csharpSubmissionType;
                            break;
                    }

                    var reportFragments = oldSubmission.FullReport.Split(
                        new[] { this.contentHeader },
                            StringSplitOptions.RemoveEmptyEntries);

                    if (string.IsNullOrWhiteSpace(oldSubmission.FullReport) || !reportFragments.Any())
                    {
                        continue;
                    }

                    if (reportFragments.Count() == 1)
                    {
                        // Some kind of exception (e.g. "not enough disk space")
                        var errorFragments = reportFragments[0].Split(
                            new[] { this.contentFooter },
                            StringSplitOptions.RemoveEmptyEntries);
                        submission.IsCompiledSuccessfully = false;
                        submission.CompilerComment = errorFragments[0];
                    }
                    else if (!reportFragments[1].Trim().StartsWith("Compilation successfull!!!"))
                    {
                        submission.IsCompiledSuccessfully = false;
                        var compilerParts = reportFragments[0].Split(
                            new[] { "\r\n" },
                            3,
                            StringSplitOptions.RemoveEmptyEntries);

                        submission.CompilerComment = compilerParts.Count() > 2 ? compilerParts[2].Trim(' ', '\n', '\r', '\t', '-', '=') : null;
                    }
                    else
                    {
                        submission.IsCompiledSuccessfully = true;
                        var compilerParts = reportFragments[0].Split(
                            new[] { "\r\n" },
                            3,
                            StringSplitOptions.RemoveEmptyEntries);
                        submission.CompilerComment = compilerParts.Count() > 2 ? compilerParts[2].Trim(' ', '\n', '\r', '\t', '-', '=') : null;

                        for (int j = 2; j < reportFragments.Length - 1; j++)
                        {
                            var testRunText = reportFragments[j].Trim();
                            var testRunTextParts = testRunText.Split(new[] { this.contentFooter }, StringSplitOptions.None);
                            var testRunTitle = testRunTextParts[0].Trim();
                            var testRunDescription = testRunTextParts[1].Trim() + Environment.NewLine;
                            var isZeroTest = testRunTitle.StartsWith("Zero");

                            var testOrderAsString = testRunTitle.GetStringBetween("�", " ");

                            var testOrder = int.Parse(testOrderAsString);

                            var test =
                                tests.FirstOrDefault(
                                    x =>
                                    x.ProblemId == problem.Id && x.IsTrialTest == isZeroTest && x.OrderBy == testOrder);

                            if (test == null)
                            {
                                continue;
                            }

                            var testRun = new TestRun
                                              {
                                                  MemoryUsed = 0,
                                                  TimeUsed = 0,
                                                  Submission = submission,
                                                  TestId = test.Id,
                                              };

                            if (testRunDescription.StartsWith("Answer correct!!!"))
                            {
                                testRun.ResultType = TestRunResultType.CorrectAnswer;
                                testRun.ExecutionComment = null;
                                testRun.CheckerComment = null;

                                var timeUsedAsString =
                                    testRunDescription.GetStringBetween("Time used (in milliseconds): ", "Memory used");
                                if (timeUsedAsString != null)
                                {
                                    double timeUsed;
                                    if (double.TryParse(timeUsedAsString.Replace(",", ".").Trim(), out timeUsed))
                                    {
                                        testRun.TimeUsed = (int)timeUsed;
                                    }
                                }

                                var memoryUsedAsString = testRunDescription.GetStringBetween(
                                    "Memory used (in bytes): ",
                                    Environment.NewLine);
                                if (memoryUsedAsString != null)
                                {
                                    testRun.MemoryUsed = int.Parse(memoryUsedAsString.Trim());
                                }
                            }
                            else if (testRunDescription.StartsWith("Answer incorrect!"))
                            {
                                testRun.ResultType = TestRunResultType.WrongAnswer;
                                testRun.ExecutionComment = null;
                                testRun.CheckerComment = testRunDescription.GetStringBetween(
                                    "Answer incorrect!",
                                    "Time used"); // Won't work with non-zero tests (will return null)
                                if (testRun.CheckerComment != null)
                                {
                                    testRun.CheckerComment = testRun.CheckerComment.Trim();
                                    if (string.IsNullOrWhiteSpace(testRun.CheckerComment))
                                    {
                                        testRun.CheckerComment = null;
                                    }
                                }

                                var timeUsedAsString =
                                    testRunDescription.GetStringBetween("Time used (in milliseconds): ", "Memory used");
                                if (timeUsedAsString != null)
                                {
                                    double timeUsed;
                                    if (double.TryParse(timeUsedAsString.Replace(",", ".").Trim(), out timeUsed))
                                    {
                                        testRun.TimeUsed = (int)timeUsed;
                                    }
                                }

                                var memoryUsedAsString = testRunDescription.GetStringBetween(
                                    "Memory used (in bytes): ",
                                    Environment.NewLine);
                                if (memoryUsedAsString != null)
                                {
                                    testRun.MemoryUsed = int.Parse(memoryUsedAsString.Trim());
                                }
                            }
                            else if (testRunDescription.StartsWith("Runtime error:"))
                            {
                                testRun.ResultType = TestRunResultType.RunTimeError;
                                testRun.ExecutionComment = testRunDescription.Replace("Runtime error:", string.Empty).Trim();
                                testRun.CheckerComment = null;
                                testRun.TimeUsed = 0;
                                testRun.MemoryUsed = 0;
                            }
                            else if (testRunDescription.StartsWith("Time limit!"))
                            {
                                testRun.ResultType = TestRunResultType.TimeLimit;
                                testRun.ExecutionComment = null;
                                testRun.CheckerComment = null;
                                testRun.TimeUsed = problem.TimeLimit;
                                testRun.MemoryUsed = 0;
                            }
                            else
                            {
                                testRun.ResultType = TestRunResultType.RunTimeError;
                                testRun.ExecutionComment = testRunDescription.Trim();
                                testRun.CheckerComment = null;
                                testRun.TimeUsed = 0;
                                testRun.MemoryUsed = 0;
                            }

                            newDb.TestRuns.Add(testRun);
                        }
                    }

                    newDb.Submissions.Add(submission);
                }

                newDb.SaveChanges();
                Console.Write(".");
            }
        }
        public TestsControllerBaseTestsClass()
        {
            var firstCategory = new ContestCategory()
            {
                Id = 1,
                Name = "Category"
            };

            var secondCategory = new ContestCategory()
            {
                Id = 2,
                Name = "Another category"
            };

            var thirdCategory = new ContestCategory()
            {
                Id = 3,
                Name = "And another category"
            };

            var contest = new Contest
            {
                Id = 1,
                Name = "Contest",
                CategoryId = 1,
                Category = firstCategory
            };

            var otherContest = new Contest
            {
                Id = 2,
                Name = "Other contest",
                CategoryId = 1,
                Category = firstCategory
            };

            firstCategory.Contests.Add(contest);
            firstCategory.Contests.Add(otherContest);

            var selectedProblem = new Problem
            {
                Id = 1,
                Name = "Problem",
                Contest = contest,
                ContestId = 1,
            };

            var otherProblem = new Problem
            {
                Id = 2,
                Name = "Other problem",
                Contest = contest,
                ContestId = 1,
            };

            var problemWithOnlyTrialTests = new Problem
            {
                Id = 3,
                Name = "OnlyTrialTests",
                Contest = contest,
                ContestId = 1,
            };

            var problemWithOnlyNormalTests = new Problem
            {
                Id = 4,
                Name = "OnlyNormalTests",
                Contest = contest,
                ContestId = 1,
            };

            var testRun = new TestRun()
            {
                Id = 1,
                TestId = 1,
                ResultType = TestRunResultType.CorrectAnswer,
                MemoryUsed = 100,
                TimeUsed = 100,
                SubmissionId = 1,
                ExecutionComment = "Comment execution",
                CheckerComment = "Comment checker",
                Submission = new Submission
                {
                    Id = 1,
                    CreatedOn = DateTime.Now,
                },
            };

            var test = new Test
            {
                Id = 1,
                InputDataAsString = "Sample test input",
                OutputDataAsString = "Sample test output",
                IsTrialTest = false,
                TestRuns = new HashSet<TestRun>()
                {
                    testRun,
                },
                Problem = selectedProblem,
                ProblemId = 1,
                OrderBy = 5,
            };

            testRun.Test = test;

            selectedProblem.Tests.Add(test);

            selectedProblem.Tests.Add(new Test
            {
                InputDataAsString = "Trial input test 1",
                OutputDataAsString = "Trial output test 1",
                IsTrialTest = true,
                Problem = selectedProblem,
                ProblemId = 1,
            });

            selectedProblem.Tests.Add(new Test
            {
                InputDataAsString = "Trial input test 2",
                OutputDataAsString = "Trial output test 2",
                IsTrialTest = true,
                Problem = selectedProblem,
                ProblemId = 1,
            });

            problemWithOnlyTrialTests.Tests.Add(new Test
            {
                InputDataAsString = "Zero test 1\nZero test 1 second line",
                OutputDataAsString = "Zero test 1\nZero test 1 second lint output",
                IsTrialTest = true,
                Problem = selectedProblem,
                ProblemId = 1,
            });

            for (int i = 0; i < 10; i++)
            {
                selectedProblem.Tests.Add(new Test
                {
                    InputDataAsString = i.ToString(),
                    OutputDataAsString = (i + 1).ToString(),
                    IsTrialTest = false,
                    Problem = selectedProblem,
                    ProblemId = 1,
                });
            }

            otherProblem.Tests.Add(new Test
            {
                InputDataAsString = "Trial input test 1 other",
                OutputDataAsString = "Trial output test 1 other",
                IsTrialTest = true,
                Problem = selectedProblem,
                ProblemId = 1,
            });

            otherProblem.Tests.Add(new Test
            {
                InputDataAsString = "Trial input test 2 other",
                OutputDataAsString = "Trial output test 2 other",
                IsTrialTest = true,
                Problem = selectedProblem,
                ProblemId = 1,
            });

            for (int i = 0; i < 10; i++)
            {
                otherProblem.Tests.Add(new Test
                {
                    InputDataAsString = i.ToString() + "other",
                    OutputDataAsString = (i + 1).ToString() + "other",
                    IsTrialTest = false,
                    Problem = selectedProblem,
                    ProblemId = 1,
                });
            }

            for (int i = 0; i < 10; i++)
            {
                problemWithOnlyNormalTests.Tests.Add(new Test
                {
                    InputDataAsString = "Only normal tests " + i.ToString(),
                    OutputDataAsString = "Only normal tests output" + i.ToString(),
                    IsTrialTest = false,
                    Problem = selectedProblem,
                    ProblemId = 1,
                });
            }

            contest.Problems.Add(selectedProblem);
            contest.Problems.Add(otherProblem);
            contest.Problems.Add(problemWithOnlyTrialTests);
            contest.Problems.Add(problemWithOnlyNormalTests);

            this.TestViewModel = new TestViewModel
            {
                Id = 1,
                InputFull = "Input test",
                OutputFull = "Output test",
                IsTrialTest = false,
                OrderBy = 1,
                ProblemId = 1,
            };

            //// TODO: get these mocks in base class for reuse

            var listsOfTests = new List<Test>(selectedProblem.Tests);

            this.data = new Mock<IOjsData>();
            this.Problems = new Mock<IDeletableEntityRepository<Problem>>();
            this.Tests = new Mock<ITestRepository>();
            this.TestsRuns = new Mock<ITestRunsRepository>();
            this.Categories = new Mock<IDeletableEntityRepository<ContestCategory>>();
            this.Contests = new Mock<IContestsRepository>();
            this.Submissions = new Mock<ISubmissionsRepository>();

            this.Problems.Setup(x => x.All()).Returns((new List<Problem>() { selectedProblem, otherProblem, problemWithOnlyTrialTests, problemWithOnlyNormalTests }).AsQueryable());

            this.Tests.Setup(x => x.All()).Returns(listsOfTests.AsQueryable());
            this.Tests.Setup(x => x.Add(It.IsAny<Test>())).Callback((Test t) => { listsOfTests.Add(t); });
            this.Tests.Setup(x => x.Delete(It.IsAny<int>())).Callback((int id) =>
            {
                foreach (var currentTest in listsOfTests)
                {
                    if (currentTest.Id == id)
                    {
                        listsOfTests.Remove(currentTest);
                        break;
                    }
                }
            });

            this.TestsRuns.Setup(x => x.All()).Returns(new List<TestRun>() { testRun }.AsQueryable());
            this.Categories.Setup(x => x.All()).Returns(new List<ContestCategory>() { firstCategory, secondCategory, thirdCategory }.AsQueryable());
            this.Contests.Setup(x => x.All()).Returns(new List<Contest>() { contest, otherContest }.AsQueryable());

            this.data.SetupGet(x => x.Problems).Returns(this.Problems.Object);
            this.data.SetupGet(x => x.Tests).Returns(this.Tests.Object);
            this.data.SetupGet(x => x.TestRuns).Returns(this.TestsRuns.Object);
            this.data.SetupGet(x => x.ContestCategories).Returns(this.Categories.Object);
            this.data.SetupGet(x => x.Contests).Returns(this.Contests.Object);
            this.data.SetupGet(x => x.Submissions).Returns(this.Submissions.Object);

            this.TestsController = new TestsController(this.data.Object);

            this.ControllerContext = new ControllerContext(this.MockHttpContestBase(), new RouteData(), this.TestsController);
        }