Штуки
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
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
This commit is contained in:
@@ -147,10 +147,10 @@ public class PackageParserServiceTests : IDisposable
|
||||
// Act
|
||||
var result = await _service.ParsePackageAsync(zipStream);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, result.TestCases.Count); // Only test 1 and 3
|
||||
Assert.Equal(1, result.TestCases[0].Number);
|
||||
Assert.Equal(3, result.TestCases[1].Number);
|
||||
// Assert
|
||||
Assert.Equal(2, result.TestCases.Count); // Only tests with complete I/O pairs
|
||||
Assert.Equal(1, result.TestCases[0].Number);
|
||||
Assert.Equal(2, result.TestCases[1].Number);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -171,9 +171,9 @@ public class PackageParserServiceTests : IDisposable
|
||||
var result = await _service.ParsePackageAsync(zipStream);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, result.TestCases.Count); // Only test 1 and 3
|
||||
Assert.Equal(1, result.TestCases[0].Number);
|
||||
Assert.Equal(3, result.TestCases[1].Number);
|
||||
Assert.Equal(2, result.TestCases.Count); // Only tests with complete I/O pairs
|
||||
Assert.Equal(1, result.TestCases[0].Number);
|
||||
Assert.Equal(2, result.TestCases[1].Number);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -206,9 +206,11 @@ public class PackageParserServiceTests : IDisposable
|
||||
foreach (var (fileName, content) in files)
|
||||
{
|
||||
var entry = archive.CreateEntry(fileName);
|
||||
using var entryStream = entry.Open();
|
||||
using var writer = new StreamWriter(entryStream);
|
||||
writer.Write(content);
|
||||
using (var entryStream = entry.Open())
|
||||
using (var writer = new StreamWriter(entryStream))
|
||||
{
|
||||
writer.Write(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using LiquidCode.Tester.Worker.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Xunit;
|
||||
|
||||
namespace LiquidCode.Tester.Worker.Tests;
|
||||
|
||||
public class PolygonPackageIntegrationTests
|
||||
{
|
||||
private readonly PackageParserService _parserService;
|
||||
|
||||
public PolygonPackageIntegrationTests()
|
||||
{
|
||||
var configuration = new ConfigurationBuilder().Build();
|
||||
|
||||
var cppCompilation = new CppCompilationService(NullLogger<CppCompilationService>.Instance, configuration);
|
||||
var cppExecution = new CppExecutionService(NullLogger<CppExecutionService>.Instance);
|
||||
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IConfiguration>(configuration);
|
||||
services.AddSingleton(cppCompilation);
|
||||
services.AddSingleton(cppExecution);
|
||||
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
var compilationFactory = new CompilationServiceFactory(serviceProvider, NullLogger<CompilationServiceFactory>.Instance);
|
||||
var executionFactory = new ExecutionServiceFactory(serviceProvider, NullLogger<ExecutionServiceFactory>.Instance);
|
||||
var answerGenerator = new AnswerGenerationService(compilationFactory, executionFactory, NullLogger<AnswerGenerationService>.Instance);
|
||||
var polygonParser = new PolygonProblemXmlParser(NullLogger<PolygonProblemXmlParser>.Instance);
|
||||
|
||||
_parserService = new PackageParserService(
|
||||
NullLogger<PackageParserService>.Instance,
|
||||
polygonParser,
|
||||
answerGenerator,
|
||||
cppCompilation);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParsePolygonPackageAsync_GeneratesTestsCheckerAndAnswers()
|
||||
{
|
||||
if (!IsExecutableAvailable("g++"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var packageDirectory = ResolvePackageDirectory("exam-queue-17");
|
||||
Assert.True(Directory.Exists(packageDirectory));
|
||||
|
||||
await using var packageStream = CreateZipFromDirectory(packageDirectory);
|
||||
|
||||
var package = await _parserService.ParsePackageAsync(packageStream);
|
||||
|
||||
try
|
||||
{
|
||||
Assert.Equal(51, package.TestCases.Count);
|
||||
Assert.NotNull(package.CheckerPath);
|
||||
Assert.True(File.Exists(package.CheckerPath), $"Checker not present at {package.CheckerPath}");
|
||||
|
||||
foreach (var testCase in package.TestCases)
|
||||
{
|
||||
Assert.True(File.Exists(testCase.InputFilePath), $"Missing input {testCase.InputFilePath}");
|
||||
Assert.True(File.Exists(testCase.OutputFilePath), $"Missing output {testCase.OutputFilePath}");
|
||||
Assert.True(new FileInfo(testCase.InputFilePath).Length > 0);
|
||||
Assert.True(new FileInfo(testCase.OutputFilePath).Length > 0);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!string.IsNullOrEmpty(package.ExtractionRoot) && Directory.Exists(package.ExtractionRoot))
|
||||
{
|
||||
Directory.Delete(package.ExtractionRoot, recursive: true);
|
||||
}
|
||||
else if (Directory.Exists(package.WorkingDirectory))
|
||||
{
|
||||
Directory.Delete(package.WorkingDirectory, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsExecutableAvailable(string executable)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = executable,
|
||||
Arguments = "--version",
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
if (!process.WaitForExit(5000))
|
||||
{
|
||||
try
|
||||
{
|
||||
process.Kill(entireProcessTree: true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return process.ExitCode == 0;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static MemoryStream CreateZipFromDirectory(string directoryPath)
|
||||
{
|
||||
var memoryStream = new MemoryStream();
|
||||
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, leaveOpen: true))
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(directoryPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
var entryName = Path.GetRelativePath(directoryPath, file).Replace("\\", "/");
|
||||
var entry = archive.CreateEntry(entryName, CompressionLevel.Fastest);
|
||||
|
||||
using (var entryStream = entry.Open())
|
||||
using (var fileStream = File.OpenRead(file))
|
||||
{
|
||||
fileStream.CopyTo(entryStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memoryStream.Position = 0;
|
||||
return memoryStream;
|
||||
}
|
||||
|
||||
private static string ResolvePackageDirectory(string folderName)
|
||||
{
|
||||
var baseDirectory = AppContext.BaseDirectory;
|
||||
var root = Path.GetFullPath(Path.Combine(baseDirectory, "..", "..", "..", "..", ".."));
|
||||
return Path.Combine(root, folderName);
|
||||
}
|
||||
}
|
||||
@@ -166,17 +166,21 @@ public class PolygonPackageParserTests : IDisposable
|
||||
{
|
||||
// Add problem.xml
|
||||
var xmlEntry = archive.CreateEntry("problem.xml");
|
||||
using var xmlStream = xmlEntry.Open();
|
||||
using var xmlWriter = new StreamWriter(xmlStream);
|
||||
xmlWriter.Write(problemXml);
|
||||
using (var xmlStream = xmlEntry.Open())
|
||||
using (var xmlWriter = new StreamWriter(xmlStream))
|
||||
{
|
||||
xmlWriter.Write(problemXml);
|
||||
}
|
||||
|
||||
// Add test files
|
||||
foreach (var (fileName, content) in files)
|
||||
{
|
||||
var entry = archive.CreateEntry(fileName);
|
||||
using var entryStream = entry.Open();
|
||||
using var writer = new StreamWriter(entryStream);
|
||||
writer.Write(content);
|
||||
using (var entryStream = entry.Open())
|
||||
using (var writer = new StreamWriter(entryStream))
|
||||
{
|
||||
writer.Write(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,9 +197,11 @@ public class PolygonPackageParserTests : IDisposable
|
||||
foreach (var (fileName, content) in files)
|
||||
{
|
||||
var entry = archive.CreateEntry(fileName);
|
||||
using var entryStream = entry.Open();
|
||||
using var writer = new StreamWriter(entryStream);
|
||||
writer.Write(content);
|
||||
using (var entryStream = entry.Open())
|
||||
using (var writer = new StreamWriter(entryStream))
|
||||
{
|
||||
writer.Write(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ public class TestingServiceTests : IDisposable
|
||||
var emptyPackage = new ProblemPackage
|
||||
{
|
||||
WorkingDirectory = _testDirectory,
|
||||
ExtractionRoot = _testDirectory,
|
||||
TestCases = new List<TestCase>() // Empty list!
|
||||
};
|
||||
|
||||
@@ -103,6 +104,7 @@ public class TestingServiceTests : IDisposable
|
||||
await File.WriteAllTextAsync(inputFile, "test input");
|
||||
await File.WriteAllTextAsync(outputFile, "expected output");
|
||||
await File.WriteAllTextAsync(executablePath, "dummy");
|
||||
await CreateEmptyPackage(packageFilePath);
|
||||
|
||||
var request = new TestRequest
|
||||
{
|
||||
@@ -118,6 +120,7 @@ public class TestingServiceTests : IDisposable
|
||||
var package = new ProblemPackage
|
||||
{
|
||||
WorkingDirectory = _testDirectory,
|
||||
ExtractionRoot = _testDirectory,
|
||||
TestCases = new List<TestCase>
|
||||
{
|
||||
new TestCase
|
||||
@@ -167,7 +170,11 @@ public class TestingServiceTests : IDisposable
|
||||
});
|
||||
|
||||
_outputCheckerMock
|
||||
.Setup(x => x.CheckOutputAsync(It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Setup(x => x.CheckOutputWithCheckerAsync(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string?>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
|
||||
Reference in New Issue
Block a user