Files
Roman Pytkov e154890897
Some checks failed
Build and Push Docker Images / build (src/LiquidCode.Tester.Gateway/Dockerfile, git.nullptr.top/liquidcode/liquidcode-tester-gateway-roman, gateway) (push) Successful in 1m12s
Build and Push Docker Images / build (src/LiquidCode.Tester.Worker/Dockerfile, git.nullptr.top/liquidcode/liquidcode-tester-worker-roman, worker) (push) Has been cancelled
Штуки
2025-11-02 19:31:34 +03:00

219 lines
7.2 KiB
C#

using System.IO.Compression;
using LiquidCode.Tester.Common.Models;
using LiquidCode.Tester.Worker.Controllers;
using LiquidCode.Tester.Worker.Services;
using Microsoft.Extensions.Logging;
using Moq;
namespace LiquidCode.Tester.Worker.Tests;
public class TestingServiceTests : IDisposable
{
private readonly Mock<IPackageParserService> _packageParserMock;
private readonly Mock<ICompilationServiceFactory> _compilationFactoryMock;
private readonly Mock<IExecutionServiceFactory> _executionFactoryMock;
private readonly Mock<IOutputCheckerService> _outputCheckerMock;
private readonly Mock<ICallbackService> _callbackServiceMock;
private readonly Mock<ILogger<TestingService>> _loggerMock;
private readonly TestingService _service;
private readonly string _testDirectory;
public TestingServiceTests()
{
_packageParserMock = new Mock<IPackageParserService>();
_compilationFactoryMock = new Mock<ICompilationServiceFactory>();
_executionFactoryMock = new Mock<IExecutionServiceFactory>();
_outputCheckerMock = new Mock<IOutputCheckerService>();
_callbackServiceMock = new Mock<ICallbackService>();
_loggerMock = new Mock<ILogger<TestingService>>();
_service = new TestingService(
_packageParserMock.Object,
_compilationFactoryMock.Object,
_executionFactoryMock.Object,
_outputCheckerMock.Object,
_callbackServiceMock.Object,
_loggerMock.Object
);
_testDirectory = Path.Combine(Path.GetTempPath(), "TestingServiceTests", Guid.NewGuid().ToString());
Directory.CreateDirectory(_testDirectory);
}
[Fact]
public async Task ProcessSubmitAsync_EmptyPackage_ReturnsUnknownError()
{
// Arrange
var packageFilePath = Path.Combine(_testDirectory, "empty_package.zip");
await CreateEmptyPackage(packageFilePath);
var request = new TestRequest
{
Id = 123,
MissionId = 456,
Language = "cpp",
LanguageVersion = "17",
SourceCode = "int main() { return 0; }",
PackageFilePath = packageFilePath,
CallbackUrl = "http://localhost/callback"
};
var emptyPackage = new ProblemPackage
{
WorkingDirectory = _testDirectory,
ExtractionRoot = _testDirectory,
TestCases = new List<TestCase>() // Empty list!
};
_packageParserMock
.Setup(x => x.ParsePackageAsync(It.IsAny<Stream>()))
.ReturnsAsync(emptyPackage);
// Act
await _service.ProcessSubmitAsync(request);
// Assert - verify callback was called with error
_callbackServiceMock.Verify(
x => x.SendStatusAsync(
request.CallbackUrl,
It.Is<TesterResponseModel>(r =>
r.State == State.Done &&
r.ErrorCode == ErrorCode.UnknownError &&
r.Message == "No test cases found in package"
)
),
Times.Once
);
// Verify compilation was NOT attempted
_compilationFactoryMock.Verify(
x => x.GetCompilationService(It.IsAny<string>()),
Times.Never
);
}
[Fact]
public async Task ProcessSubmitAsync_ValidPackage_RunsAllTests()
{
// Arrange
var packageFilePath = Path.Combine(_testDirectory, "valid_package.zip");
var inputFile = Path.Combine(_testDirectory, "1.in");
var outputFile = Path.Combine(_testDirectory, "1.out");
var executablePath = Path.Combine(_testDirectory, "solution.exe");
await File.WriteAllTextAsync(inputFile, "test input");
await File.WriteAllTextAsync(outputFile, "expected output");
await File.WriteAllTextAsync(executablePath, "dummy");
await CreateEmptyPackage(packageFilePath);
var request = new TestRequest
{
Id = 123,
MissionId = 456,
Language = "cpp",
LanguageVersion = "17",
SourceCode = "int main() { return 0; }",
PackageFilePath = packageFilePath,
CallbackUrl = "http://localhost/callback"
};
var package = new ProblemPackage
{
WorkingDirectory = _testDirectory,
ExtractionRoot = _testDirectory,
TestCases = new List<TestCase>
{
new TestCase
{
Number = 1,
InputFilePath = inputFile,
OutputFilePath = outputFile,
TimeLimit = 2000,
MemoryLimit = 256
}
}
};
var compilationService = new Mock<ICompilationService>();
var executionService = new Mock<IExecutionService>();
_packageParserMock
.Setup(x => x.ParsePackageAsync(It.IsAny<Stream>()))
.ReturnsAsync(package);
_compilationFactoryMock
.Setup(x => x.GetCompilationService("cpp"))
.Returns(compilationService.Object);
_executionFactoryMock
.Setup(x => x.GetExecutionService("cpp"))
.Returns(executionService.Object);
compilationService
.Setup(x => x.CompileAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(new CompilationResult
{
Success = true,
ExecutablePath = executablePath
});
executionService
.Setup(x => x.ExecuteAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<int>()))
.ReturnsAsync(new ExecutionResult
{
Success = true,
Output = "expected output",
ExitCode = 0,
RuntimeError = false,
TimeLimitExceeded = false,
MemoryLimitExceeded = false
});
_outputCheckerMock
.Setup(x => x.CheckOutputWithCheckerAsync(
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string?>()))
.ReturnsAsync(true);
// Act
await _service.ProcessSubmitAsync(request);
// Assert - verify callback was called with success
_callbackServiceMock.Verify(
x => x.SendStatusAsync(
request.CallbackUrl,
It.Is<TesterResponseModel>(r =>
r.State == State.Done &&
r.ErrorCode == ErrorCode.None &&
r.Message == "All tests passed"
)
),
Times.AtLeastOnce
);
}
private async Task CreateEmptyPackage(string filePath)
{
using var fileStream = File.Create(filePath);
using var archive = new ZipArchive(fileStream, ZipArchiveMode.Create);
// Create empty archive
}
public void Dispose()
{
if (Directory.Exists(_testDirectory))
{
try
{
Directory.Delete(_testDirectory, true);
}
catch
{
// Ignore cleanup errors in tests
}
}
}
}