221 lines
7.4 KiB
C#
221 lines
7.4 KiB
C#
using System.IO.Compression;
|
|
using LiquidCode.Tester.Worker.Services;
|
|
using Microsoft.Extensions.Logging;
|
|
using Moq;
|
|
|
|
namespace LiquidCode.Tester.Worker.Tests;
|
|
|
|
public class PolygonPackageParserTests : IDisposable
|
|
{
|
|
private readonly PackageParserService _service;
|
|
private readonly string _testDirectory;
|
|
|
|
public PolygonPackageParserTests()
|
|
{
|
|
var logger = new Mock<ILogger<PackageParserService>>();
|
|
var xmlLogger = new Mock<ILogger<PolygonProblemXmlParser>>();
|
|
var answerGenLogger = new Mock<ILogger<AnswerGenerationService>>();
|
|
var cppLogger = new Mock<ILogger<CppCompilationService>>();
|
|
var cppConfigMock = new Mock<Microsoft.Extensions.Configuration.IConfiguration>();
|
|
|
|
var polygonParser = new PolygonProblemXmlParser(xmlLogger.Object);
|
|
|
|
var compilationFactory = new Mock<ICompilationServiceFactory>();
|
|
var executionFactory = new Mock<IExecutionServiceFactory>();
|
|
var answerGenerator = new AnswerGenerationService(
|
|
compilationFactory.Object,
|
|
executionFactory.Object,
|
|
answerGenLogger.Object);
|
|
|
|
var cppCompilation = new CppCompilationService(cppLogger.Object, cppConfigMock.Object);
|
|
|
|
_service = new PackageParserService(logger.Object, polygonParser, answerGenerator, cppCompilation);
|
|
_testDirectory = Path.Combine(Path.GetTempPath(), "PolygonPackageTests", Guid.NewGuid().ToString());
|
|
Directory.CreateDirectory(_testDirectory);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ParsePackageAsync_PolygonPackageWithProblemXml_ParsesSuccessfully()
|
|
{
|
|
// Arrange
|
|
var problemXml = @"<?xml version=""1.0"" encoding=""utf-8"" standalone=""no""?>
|
|
<problem revision=""7"" short-name=""test-problem"">
|
|
<judging>
|
|
<testset name=""tests"">
|
|
<time-limit>1000</time-limit>
|
|
<memory-limit>268435456</memory-limit>
|
|
<test-count>2</test-count>
|
|
<input-path-pattern>tests/%02d</input-path-pattern>
|
|
<answer-path-pattern>tests/%02d.a</answer-path-pattern>
|
|
</testset>
|
|
</judging>
|
|
</problem>";
|
|
|
|
var zipStream = CreatePolygonPackage(problemXml, new[]
|
|
{
|
|
("tests/01", "input1"),
|
|
("tests/01.a", "output1"),
|
|
("tests/02", "input2"),
|
|
("tests/02.a", "output2")
|
|
});
|
|
|
|
// Act
|
|
var result = await _service.ParsePackageAsync(zipStream);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(2, result.TestCases.Count);
|
|
Assert.Equal(1000, result.DefaultTimeLimit);
|
|
Assert.Equal(256, result.DefaultMemoryLimit);
|
|
|
|
// Verify first test
|
|
Assert.Equal(1, result.TestCases[0].Number);
|
|
Assert.True(File.Exists(result.TestCases[0].InputFilePath));
|
|
Assert.True(File.Exists(result.TestCases[0].OutputFilePath));
|
|
Assert.Equal("input1", await File.ReadAllTextAsync(result.TestCases[0].InputFilePath));
|
|
Assert.Equal("output1", await File.ReadAllTextAsync(result.TestCases[0].OutputFilePath));
|
|
|
|
// Verify second test
|
|
Assert.Equal(2, result.TestCases[1].Number);
|
|
Assert.True(File.Exists(result.TestCases[1].InputFilePath));
|
|
Assert.True(File.Exists(result.TestCases[1].OutputFilePath));
|
|
|
|
// Cleanup
|
|
if (Directory.Exists(result.WorkingDirectory))
|
|
{
|
|
Directory.Delete(result.WorkingDirectory, true);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ParsePackageAsync_PolygonPackageMissingAnswerFiles_SkipsTests()
|
|
{
|
|
// Arrange
|
|
var problemXml = @"<?xml version=""1.0"" encoding=""utf-8"" standalone=""no""?>
|
|
<problem revision=""7"" short-name=""test-problem"">
|
|
<judging>
|
|
<testset name=""tests"">
|
|
<time-limit>2000</time-limit>
|
|
<memory-limit>536870912</memory-limit>
|
|
<test-count>3</test-count>
|
|
<input-path-pattern>tests/%02d</input-path-pattern>
|
|
<answer-path-pattern>tests/%02d.a</answer-path-pattern>
|
|
</testset>
|
|
</judging>
|
|
</problem>";
|
|
|
|
var zipStream = CreatePolygonPackage(problemXml, new[]
|
|
{
|
|
("tests/01", "input1"),
|
|
("tests/01.a", "output1"),
|
|
("tests/02", "input2"),
|
|
// Missing 02.a
|
|
("tests/03", "input3"),
|
|
("tests/03.a", "output3")
|
|
});
|
|
|
|
// Act
|
|
var result = await _service.ParsePackageAsync(zipStream);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(2, result.TestCases.Count); // Only tests with answer files
|
|
Assert.Equal(1, result.TestCases[0].Number);
|
|
Assert.Equal(3, result.TestCases[1].Number); // Test 2 skipped
|
|
|
|
// Cleanup
|
|
if (Directory.Exists(result.WorkingDirectory))
|
|
{
|
|
Directory.Delete(result.WorkingDirectory, true);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ParsePackageAsync_NoProblemXml_FallsBackToLegacyFormat()
|
|
{
|
|
// Arrange - create package without problem.xml
|
|
var zipStream = CreateLegacyPackage(new[]
|
|
{
|
|
("tests/test1.in", "input1"),
|
|
("tests/test1.out", "output1"),
|
|
("tests/test2.in", "input2"),
|
|
("tests/test2.out", "output2")
|
|
});
|
|
|
|
// Act
|
|
var result = await _service.ParsePackageAsync(zipStream);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(2, result.TestCases.Count);
|
|
Assert.Equal(2000, result.DefaultTimeLimit); // Default values
|
|
Assert.Equal(256, result.DefaultMemoryLimit);
|
|
|
|
// Cleanup
|
|
if (Directory.Exists(result.WorkingDirectory))
|
|
{
|
|
Directory.Delete(result.WorkingDirectory, true);
|
|
}
|
|
}
|
|
|
|
private MemoryStream CreatePolygonPackage(string problemXml, IEnumerable<(string fileName, string content)> files)
|
|
{
|
|
var memoryStream = new MemoryStream();
|
|
|
|
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
|
|
{
|
|
// Add problem.xml
|
|
var xmlEntry = archive.CreateEntry("problem.xml");
|
|
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);
|
|
}
|
|
}
|
|
|
|
memoryStream.Position = 0;
|
|
return memoryStream;
|
|
}
|
|
|
|
private MemoryStream CreateLegacyPackage(IEnumerable<(string fileName, string content)> files)
|
|
{
|
|
var memoryStream = new MemoryStream();
|
|
|
|
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
memoryStream.Position = 0;
|
|
return memoryStream;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Directory.Exists(_testDirectory))
|
|
{
|
|
try
|
|
{
|
|
Directory.Delete(_testDirectory, true);
|
|
}
|
|
catch
|
|
{
|
|
// Ignore cleanup errors
|
|
}
|
|
}
|
|
}
|
|
}
|