remove k8s configs, update worker for multi-languages support, add local-submit option
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
using LiquidCode.Tester.Worker.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
|
||||
namespace LiquidCode.Tester.Worker.Tests;
|
||||
|
||||
public class CompilationServiceFactoryTests
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly CompilationServiceFactory _factory;
|
||||
|
||||
public CompilationServiceFactoryTests()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
// Mock configuration
|
||||
var configuration = new Mock<IConfiguration>();
|
||||
services.AddSingleton(configuration.Object);
|
||||
|
||||
// Mock logger
|
||||
var loggerFactory = new Mock<ILoggerFactory>();
|
||||
loggerFactory.Setup(x => x.CreateLogger(It.IsAny<string>()))
|
||||
.Returns(new Mock<ILogger>().Object);
|
||||
services.AddSingleton(loggerFactory.Object);
|
||||
services.AddLogging();
|
||||
|
||||
// Register compilation services
|
||||
services.AddSingleton<CppCompilationService>();
|
||||
services.AddSingleton<JavaCompilationService>();
|
||||
services.AddSingleton<KotlinCompilationService>();
|
||||
services.AddSingleton<CSharpCompilationService>();
|
||||
services.AddSingleton<PythonCompilationService>();
|
||||
|
||||
_serviceProvider = services.BuildServiceProvider();
|
||||
_factory = new CompilationServiceFactory(
|
||||
_serviceProvider,
|
||||
_serviceProvider.GetRequiredService<ILogger<CompilationServiceFactory>>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("C++", typeof(CppCompilationService))]
|
||||
[InlineData("c++", typeof(CppCompilationService))]
|
||||
[InlineData("cpp", typeof(CppCompilationService))]
|
||||
[InlineData("CPP", typeof(CppCompilationService))]
|
||||
public void GetCompilationService_CppLanguage_ReturnsCppCompilationService(string language, Type expectedType)
|
||||
{
|
||||
// Act
|
||||
var service = _factory.GetCompilationService(language);
|
||||
|
||||
// Assert
|
||||
Assert.IsType(expectedType, service);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Java", typeof(JavaCompilationService))]
|
||||
[InlineData("java", typeof(JavaCompilationService))]
|
||||
[InlineData("JAVA", typeof(JavaCompilationService))]
|
||||
public void GetCompilationService_JavaLanguage_ReturnsJavaCompilationService(string language, Type expectedType)
|
||||
{
|
||||
// Act
|
||||
var service = _factory.GetCompilationService(language);
|
||||
|
||||
// Assert
|
||||
Assert.IsType(expectedType, service);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Kotlin", typeof(KotlinCompilationService))]
|
||||
[InlineData("kotlin", typeof(KotlinCompilationService))]
|
||||
[InlineData("KOTLIN", typeof(KotlinCompilationService))]
|
||||
public void GetCompilationService_KotlinLanguage_ReturnsKotlinCompilationService(string language, Type expectedType)
|
||||
{
|
||||
// Act
|
||||
var service = _factory.GetCompilationService(language);
|
||||
|
||||
// Assert
|
||||
Assert.IsType(expectedType, service);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("C#", typeof(CSharpCompilationService))]
|
||||
[InlineData("c#", typeof(CSharpCompilationService))]
|
||||
[InlineData("csharp", typeof(CSharpCompilationService))]
|
||||
[InlineData("CSharp", typeof(CSharpCompilationService))]
|
||||
[InlineData("CSHARP", typeof(CSharpCompilationService))]
|
||||
public void GetCompilationService_CSharpLanguage_ReturnsCSharpCompilationService(string language, Type expectedType)
|
||||
{
|
||||
// Act
|
||||
var service = _factory.GetCompilationService(language);
|
||||
|
||||
// Assert
|
||||
Assert.IsType(expectedType, service);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Python", typeof(PythonCompilationService))]
|
||||
[InlineData("python", typeof(PythonCompilationService))]
|
||||
[InlineData("PYTHON", typeof(PythonCompilationService))]
|
||||
public void GetCompilationService_PythonLanguage_ReturnsPythonCompilationService(string language, Type expectedType)
|
||||
{
|
||||
// Act
|
||||
var service = _factory.GetCompilationService(language);
|
||||
|
||||
// Assert
|
||||
Assert.IsType(expectedType, service);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Go")]
|
||||
[InlineData("Rust")]
|
||||
[InlineData("JavaScript")]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
public void GetCompilationService_UnsupportedLanguage_ThrowsNotSupportedException(string language)
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<NotSupportedException>(() => _factory.GetCompilationService(language));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetCompilationService_NullLanguage_ThrowsException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<NullReferenceException>(() => _factory.GetCompilationService(null!));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
using LiquidCode.Tester.Worker.Services;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
|
||||
namespace LiquidCode.Tester.Worker.Tests;
|
||||
|
||||
public class ExecutionServiceFactoryTests
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ExecutionServiceFactory _factory;
|
||||
|
||||
public ExecutionServiceFactoryTests()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
// Mock configuration
|
||||
var configuration = new Mock<IConfiguration>();
|
||||
services.AddSingleton(configuration.Object);
|
||||
|
||||
// Mock logger
|
||||
var loggerFactory = new Mock<ILoggerFactory>();
|
||||
loggerFactory.Setup(x => x.CreateLogger(It.IsAny<string>()))
|
||||
.Returns(new Mock<ILogger>().Object);
|
||||
services.AddSingleton(loggerFactory.Object);
|
||||
services.AddLogging();
|
||||
|
||||
// Register execution services
|
||||
services.AddSingleton<CppExecutionService>();
|
||||
services.AddSingleton<JavaExecutionService>();
|
||||
services.AddSingleton<KotlinExecutionService>();
|
||||
services.AddSingleton<CSharpExecutionService>();
|
||||
services.AddSingleton<PythonExecutionService>();
|
||||
|
||||
_serviceProvider = services.BuildServiceProvider();
|
||||
_factory = new ExecutionServiceFactory(
|
||||
_serviceProvider,
|
||||
_serviceProvider.GetRequiredService<ILogger<ExecutionServiceFactory>>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("C++", typeof(CppExecutionService))]
|
||||
[InlineData("c++", typeof(CppExecutionService))]
|
||||
[InlineData("cpp", typeof(CppExecutionService))]
|
||||
[InlineData("CPP", typeof(CppExecutionService))]
|
||||
public void GetExecutionService_CppLanguage_ReturnsCppExecutionService(string language, Type expectedType)
|
||||
{
|
||||
// Act
|
||||
var service = _factory.GetExecutionService(language);
|
||||
|
||||
// Assert
|
||||
Assert.IsType(expectedType, service);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Java", typeof(JavaExecutionService))]
|
||||
[InlineData("java", typeof(JavaExecutionService))]
|
||||
[InlineData("JAVA", typeof(JavaExecutionService))]
|
||||
public void GetExecutionService_JavaLanguage_ReturnsJavaExecutionService(string language, Type expectedType)
|
||||
{
|
||||
// Act
|
||||
var service = _factory.GetExecutionService(language);
|
||||
|
||||
// Assert
|
||||
Assert.IsType(expectedType, service);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Kotlin", typeof(KotlinExecutionService))]
|
||||
[InlineData("kotlin", typeof(KotlinExecutionService))]
|
||||
[InlineData("KOTLIN", typeof(KotlinExecutionService))]
|
||||
public void GetExecutionService_KotlinLanguage_ReturnsKotlinExecutionService(string language, Type expectedType)
|
||||
{
|
||||
// Act
|
||||
var service = _factory.GetExecutionService(language);
|
||||
|
||||
// Assert
|
||||
Assert.IsType(expectedType, service);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("C#", typeof(CSharpExecutionService))]
|
||||
[InlineData("c#", typeof(CSharpExecutionService))]
|
||||
[InlineData("csharp", typeof(CSharpExecutionService))]
|
||||
[InlineData("CSharp", typeof(CSharpExecutionService))]
|
||||
[InlineData("CSHARP", typeof(CSharpExecutionService))]
|
||||
public void GetExecutionService_CSharpLanguage_ReturnsCSharpExecutionService(string language, Type expectedType)
|
||||
{
|
||||
// Act
|
||||
var service = _factory.GetExecutionService(language);
|
||||
|
||||
// Assert
|
||||
Assert.IsType(expectedType, service);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Python", typeof(PythonExecutionService))]
|
||||
[InlineData("python", typeof(PythonExecutionService))]
|
||||
[InlineData("PYTHON", typeof(PythonExecutionService))]
|
||||
public void GetExecutionService_PythonLanguage_ReturnsPythonExecutionService(string language, Type expectedType)
|
||||
{
|
||||
// Act
|
||||
var service = _factory.GetExecutionService(language);
|
||||
|
||||
// Assert
|
||||
Assert.IsType(expectedType, service);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Go")]
|
||||
[InlineData("Rust")]
|
||||
[InlineData("JavaScript")]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
public void GetExecutionService_UnsupportedLanguage_ThrowsNotSupportedException(string language)
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<NotSupportedException>(() => _factory.GetExecutionService(language));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetExecutionService_NullLanguage_ThrowsException()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.Throws<NullReferenceException>(() => _factory.GetExecutionService(null!));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
|
||||
<PackageReference Include="Moq" Version="4.20.70" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\LiquidCode.Tester.Worker\LiquidCode.Tester.Worker.csproj" />
|
||||
<ProjectReference Include="..\..\src\LiquidCode.Tester.Common\LiquidCode.Tester.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,169 @@
|
||||
using LiquidCode.Tester.Worker.Services;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
|
||||
namespace LiquidCode.Tester.Worker.Tests;
|
||||
|
||||
public class OutputCheckerServiceTests : IDisposable
|
||||
{
|
||||
private readonly OutputCheckerService _service;
|
||||
private readonly string _testDirectory;
|
||||
|
||||
public OutputCheckerServiceTests()
|
||||
{
|
||||
var logger = new Mock<ILogger<OutputCheckerService>>();
|
||||
_service = new OutputCheckerService(logger.Object);
|
||||
_testDirectory = Path.Combine(Path.GetTempPath(), "OutputCheckerTests", Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(_testDirectory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckOutputAsync_ExactMatch_ReturnsTrue()
|
||||
{
|
||||
// Arrange
|
||||
var expectedOutput = "Hello, World!";
|
||||
var actualOutput = "Hello, World!";
|
||||
var expectedFilePath = CreateTempFile(expectedOutput);
|
||||
|
||||
// Act
|
||||
var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckOutputAsync_DifferentOutput_ReturnsFalse()
|
||||
{
|
||||
// Arrange
|
||||
var expectedOutput = "Hello, World!";
|
||||
var actualOutput = "Goodbye, World!";
|
||||
var expectedFilePath = CreateTempFile(expectedOutput);
|
||||
|
||||
// Act
|
||||
var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckOutputAsync_TrailingWhitespace_ReturnsTrue()
|
||||
{
|
||||
// Arrange
|
||||
var expectedOutput = "Hello, World!";
|
||||
var actualOutput = "Hello, World! \n\n";
|
||||
var expectedFilePath = CreateTempFile(expectedOutput);
|
||||
|
||||
// Act
|
||||
var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckOutputAsync_LeadingWhitespace_ReturnsTrue()
|
||||
{
|
||||
// Arrange
|
||||
var expectedOutput = "Hello, World!";
|
||||
var actualOutput = " \n\nHello, World!";
|
||||
var expectedFilePath = CreateTempFile(expectedOutput);
|
||||
|
||||
// Act
|
||||
var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckOutputAsync_DifferentLineEndings_ReturnsTrue()
|
||||
{
|
||||
// Arrange
|
||||
var expectedOutput = "Line1\nLine2\nLine3";
|
||||
var actualOutput = "Line1\r\nLine2\r\nLine3";
|
||||
var expectedFilePath = CreateTempFile(expectedOutput);
|
||||
|
||||
// Act
|
||||
var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckOutputAsync_MultipleLines_ExactMatch_ReturnsTrue()
|
||||
{
|
||||
// Arrange
|
||||
var expectedOutput = "Line 1\nLine 2\nLine 3";
|
||||
var actualOutput = "Line 1\nLine 2\nLine 3";
|
||||
var expectedFilePath = CreateTempFile(expectedOutput);
|
||||
|
||||
// Act
|
||||
var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckOutputAsync_EmptyOutputs_ReturnsTrue()
|
||||
{
|
||||
// Arrange
|
||||
var expectedOutput = "";
|
||||
var actualOutput = "";
|
||||
var expectedFilePath = CreateTempFile(expectedOutput);
|
||||
|
||||
// Act
|
||||
var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckOutputAsync_OnlyWhitespace_ReturnsTrue()
|
||||
{
|
||||
// Arrange
|
||||
var expectedOutput = " \n\n ";
|
||||
var actualOutput = " \n\n ";
|
||||
var expectedFilePath = CreateTempFile(expectedOutput);
|
||||
|
||||
// Act
|
||||
var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckOutputAsync_CaseSensitive_ReturnsFalse()
|
||||
{
|
||||
// Arrange
|
||||
var expectedOutput = "Hello, World!";
|
||||
var actualOutput = "hello, world!";
|
||||
var expectedFilePath = CreateTempFile(expectedOutput);
|
||||
|
||||
// Act
|
||||
var result = await _service.CheckOutputAsync(actualOutput, expectedFilePath);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
private string CreateTempFile(string content)
|
||||
{
|
||||
var filePath = Path.Combine(_testDirectory, $"test_{Guid.NewGuid()}.txt");
|
||||
File.WriteAllText(filePath, content);
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Directory.Exists(_testDirectory))
|
||||
{
|
||||
Directory.Delete(_testDirectory, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
using System.IO.Compression;
|
||||
using LiquidCode.Tester.Worker.Services;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
|
||||
namespace LiquidCode.Tester.Worker.Tests;
|
||||
|
||||
public class PackageParserServiceTests : IDisposable
|
||||
{
|
||||
private readonly PackageParserService _service;
|
||||
private readonly string _testDirectory;
|
||||
|
||||
public PackageParserServiceTests()
|
||||
{
|
||||
var logger = new Mock<ILogger<PackageParserService>>();
|
||||
_service = new PackageParserService(logger.Object);
|
||||
_testDirectory = Path.Combine(Path.GetTempPath(), "PackageParserTests", Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(_testDirectory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParsePackageAsync_ValidPackageWithTestCases_ParsesSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var zipStream = CreateTestPackage(new[]
|
||||
{
|
||||
("1.in", "input1"),
|
||||
("1.out", "output1"),
|
||||
("2.in", "input2"),
|
||||
("2.out", "output2"),
|
||||
("3.in", "input3"),
|
||||
("3.out", "output3")
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = await _service.ParsePackageAsync(zipStream);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(3, result.TestCases.Count);
|
||||
Assert.True(Directory.Exists(result.WorkingDirectory));
|
||||
|
||||
// Check test case 1
|
||||
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));
|
||||
|
||||
// Check test case 2
|
||||
Assert.Equal(2, result.TestCases[1].Number);
|
||||
Assert.True(File.Exists(result.TestCases[1].InputFilePath));
|
||||
Assert.True(File.Exists(result.TestCases[1].OutputFilePath));
|
||||
|
||||
// Check test case 3
|
||||
Assert.Equal(3, result.TestCases[2].Number);
|
||||
Assert.True(File.Exists(result.TestCases[2].InputFilePath));
|
||||
Assert.True(File.Exists(result.TestCases[2].OutputFilePath));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParsePackageAsync_PackageWithDefaultLimits_UsesDefaultValues()
|
||||
{
|
||||
// Arrange
|
||||
var zipStream = CreateTestPackage(new[]
|
||||
{
|
||||
("1.in", "input1"),
|
||||
("1.out", "output1")
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = await _service.ParsePackageAsync(zipStream);
|
||||
|
||||
// Assert
|
||||
Assert.Single(result.TestCases);
|
||||
Assert.Equal(2000, result.TestCases[0].TimeLimit); // Default time limit
|
||||
Assert.Equal(256, result.TestCases[0].MemoryLimit); // Default memory limit
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParsePackageAsync_EmptyPackage_ReturnsEmptyTestCasesList()
|
||||
{
|
||||
// Arrange
|
||||
var zipStream = CreateTestPackage(Array.Empty<(string, string)>());
|
||||
|
||||
// Act
|
||||
var result = await _service.ParsePackageAsync(zipStream);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Empty(result.TestCases);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParsePackageAsync_TestCasesNotInOrder_SortsCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var zipStream = CreateTestPackage(new[]
|
||||
{
|
||||
("3.in", "input3"),
|
||||
("3.out", "output3"),
|
||||
("1.in", "input1"),
|
||||
("1.out", "output1"),
|
||||
("2.in", "input2"),
|
||||
("2.out", "output2")
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = await _service.ParsePackageAsync(zipStream);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(3, result.TestCases.Count);
|
||||
Assert.Equal(1, result.TestCases[0].Number);
|
||||
Assert.Equal(2, result.TestCases[1].Number);
|
||||
Assert.Equal(3, result.TestCases[2].Number);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParsePackageAsync_MissingOutputFile_SkipsTestCase()
|
||||
{
|
||||
// Arrange
|
||||
var zipStream = CreateTestPackage(new[]
|
||||
{
|
||||
("1.in", "input1"),
|
||||
("1.out", "output1"),
|
||||
("2.in", "input2"),
|
||||
// Missing 2.out
|
||||
("3.in", "input3"),
|
||||
("3.out", "output3")
|
||||
});
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParsePackageAsync_MissingInputFile_SkipsTestCase()
|
||||
{
|
||||
// Arrange
|
||||
var zipStream = CreateTestPackage(new[]
|
||||
{
|
||||
("1.in", "input1"),
|
||||
("1.out", "output1"),
|
||||
// Missing 2.in
|
||||
("2.out", "output2"),
|
||||
("3.in", "input3"),
|
||||
("3.out", "output3")
|
||||
});
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ParsePackageAsync_TestsInSubdirectory_ParsesSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var zipStream = CreateTestPackage(new[]
|
||||
{
|
||||
("tests/1.in", "input1"),
|
||||
("tests/1.out", "output1"),
|
||||
("tests/2.in", "input2"),
|
||||
("tests/2.out", "output2")
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = await _service.ParsePackageAsync(zipStream);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, result.TestCases.Count);
|
||||
Assert.Equal(1, result.TestCases[0].Number);
|
||||
Assert.Equal(2, result.TestCases[1].Number);
|
||||
}
|
||||
|
||||
private MemoryStream CreateTestPackage(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))
|
||||
{
|
||||
Directory.Delete(_testDirectory, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user