Added package filtering
This commit is contained in:
@@ -0,0 +1,349 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Moq;
|
||||
using sh.actions.package_cleanup.Models;
|
||||
using sh.actions.package_cleanup.Service;
|
||||
using Xunit;
|
||||
|
||||
namespace sh.actions.package_cleanup.Tests.Service;
|
||||
|
||||
public class PackageServiceVersionDetectionTests
|
||||
{
|
||||
private readonly IPackageService _packageService;
|
||||
private readonly Mock<IConfiguration> _configurationMock;
|
||||
private readonly Mock<IGiteaPackageService> _giteaPackageServiceMock;
|
||||
|
||||
public PackageServiceVersionDetectionTests()
|
||||
{
|
||||
_configurationMock = new Mock<IConfiguration>();
|
||||
_giteaPackageServiceMock = new Mock<IGiteaPackageService>();
|
||||
_packageService = new PackageService(_configurationMock.Object, _giteaPackageServiceMock.Object);
|
||||
}
|
||||
|
||||
#region Release Type Detection Tests
|
||||
|
||||
[Theory]
|
||||
[InlineData("1.0.0")]
|
||||
[InlineData("2.5.3")]
|
||||
[InlineData("10.20.30")]
|
||||
[InlineData("2025.2.14.1")]
|
||||
public void FilterPackagesToDelete_WithProdReleases_ShouldIdentifyAsNonDeletable(string version)
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = version, Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - Prod releases should not be in delete list (CLEAN_PROD_VERSIONS=false by default)
|
||||
Assert.DoesNotContain(result, p => p.Id == 1);
|
||||
Assert.Empty(result); // No packages should be deleted without CLEAN_PROD_VERSIONS=true
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1.0.0-alpha")]
|
||||
[InlineData("1.0.0-ALPHA")]
|
||||
[InlineData("2.5.3-alpha123")]
|
||||
[InlineData("1.0.0-beta")]
|
||||
[InlineData("1.0.0-BETA")]
|
||||
[InlineData("1.0.0-rc")]
|
||||
[InlineData("1.0.0-RC1")]
|
||||
[InlineData("1.0.0-preview")]
|
||||
[InlineData("1.0.0-PREVIEW")]
|
||||
public void FilterPackagesToDelete_WithPrereleaseVersions_ShouldIdentifyCorrectly(string version)
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = version, Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - Prerelease should be kept (default KEEP_PRERELEASE_VERSIONS=3, so 1 package is kept)
|
||||
Assert.NotNull(result);
|
||||
Assert.Empty(result); // Single prerelease should be kept as it's within the limit
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1.0.0-dev")]
|
||||
[InlineData("1.0.0-DEV")]
|
||||
[InlineData("2.5.3-dev123")]
|
||||
[InlineData("1.0.0-development")]
|
||||
[InlineData("1.0.0-DEV")]
|
||||
public void FilterPackagesToDelete_WithDevVersions_ShouldIdentifyCorrectly(string version)
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = version, Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - Dev version should be kept (default KEEP_DEV_VERSIONS=5, so 1 package is kept)
|
||||
Assert.NotNull(result);
|
||||
Assert.Empty(result); // Single dev version should be kept as it's within the limit
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Semantic Version Detection Tests
|
||||
|
||||
[Theory]
|
||||
[InlineData("1.0")]
|
||||
[InlineData("1.0.0")]
|
||||
[InlineData("1.0.0.0")]
|
||||
[InlineData("2.5")]
|
||||
[InlineData("2.5.3")]
|
||||
[InlineData("2.5.3.100")]
|
||||
[InlineData("0.0.0.0")]
|
||||
[InlineData("99.99.99.99")]
|
||||
public void FilterPackagesToDelete_WithValidSemanticVersions_ShouldProcess(string version)
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = version, Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - Should process without throwing and not delete prod releases
|
||||
Assert.NotNull(result);
|
||||
Assert.DoesNotContain(result, p => p.Id == 1); // Prod version should not be deleted
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1")] // Only 1 component
|
||||
[InlineData("1.0.0.0.0")] // 5 components
|
||||
[InlineData("1.a.0.0")] // Non-numeric
|
||||
[InlineData("a.b.c.d")] // All non-numeric
|
||||
public void FilterPackagesToDelete_WithInvalidSemanticVersions_ShouldSkip(string version)
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = version, Type = "docker", CreatedAt = DateTime.UtcNow },
|
||||
new() { Id = 2, Name = "test", Version = "2.0.0.0", Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - Invalid version should be skipped, only valid semantic version (id=2) is processed
|
||||
Assert.NotNull(result);
|
||||
// Should not crash and should only consider the valid version
|
||||
Assert.DoesNotContain(result, p => p.Id == 2); // Valid prod should not be deleted
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("101.0.0.0")]
|
||||
[InlineData("200.5.3.100")]
|
||||
[InlineData("1000.0.0.0")]
|
||||
public void FilterPackagesToDelete_WithLargeMajorVersion_ShouldTreatAsDateVersion(string version)
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = version, Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - Large major versions (>100) are detected as date versions, not semantic
|
||||
// These will fail date validation (invalid month/day) and be skipped
|
||||
Assert.NotNull(result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Date Version Detection Tests
|
||||
|
||||
[Theory]
|
||||
[InlineData("2024.1.1.1")]
|
||||
[InlineData("2025.2.14.1")]
|
||||
[InlineData("2026.12.31.999")]
|
||||
[InlineData("2000.6.15.100")]
|
||||
[InlineData("1999.1.1.1")]
|
||||
public void FilterPackagesToDelete_WithValidDateVersions_ShouldProcess(string version)
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = version, Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - Should process without throwing and not delete prod date versions
|
||||
Assert.NotNull(result);
|
||||
Assert.DoesNotContain(result, p => p.Id == 1); // Prod date version should not be deleted
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("2025.1.1")] // 3 components (missing build)
|
||||
[InlineData("2025.1.1.1.1")] // 5 components
|
||||
[InlineData("2025.13.1.1")] // Month out of range
|
||||
[InlineData("2025.0.1.1")] // Month zero
|
||||
[InlineData("2025.2.32.1")] // Day out of range
|
||||
[InlineData("2025.2.0.1")] // Day zero
|
||||
[InlineData("999.2.14.1")] // Year too small
|
||||
[InlineData("3000.2.14.1")] // Year too large
|
||||
[InlineData("2025.a.14.1")] // Non-numeric month
|
||||
public void FilterPackagesToDelete_WithInvalidDateVersions_ShouldSkip(string version)
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = version, Type = "docker", CreatedAt = DateTime.UtcNow },
|
||||
new() { Id = 2, Name = "test", Version = "1.0.0.0", Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - Invalid date version should be skipped, valid semantic version (id=2) is processed as prod
|
||||
Assert.NotNull(result);
|
||||
Assert.DoesNotContain(result, p => p.Id == 2); // Valid semantic prod should not be deleted
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1000.1.1.1")] // Minimum valid year
|
||||
[InlineData("2999.12.31.999")] // Maximum valid year
|
||||
[InlineData("2025.1.1.1")] // January 1
|
||||
[InlineData("2025.12.31.1")] // December 31
|
||||
public void FilterPackagesToDelete_WithDateVersionBoundaries_ShouldProcess(string version)
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = version, Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - Boundary date versions should be recognized as valid
|
||||
Assert.NotNull(result);
|
||||
Assert.DoesNotContain(result, p => p.Id == 1); // Prod date version should not be deleted
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Case Sensitivity Tests
|
||||
|
||||
[Theory]
|
||||
[InlineData("1.0.0-alpha")]
|
||||
[InlineData("1.0.0-ALPHA")]
|
||||
[InlineData("1.0.0-Alpha")]
|
||||
[InlineData("1.0.0-AlPhA")]
|
||||
public void FilterPackagesToDelete_WithDifferentCasePrerelease_ShouldHandleCorrectly(string version)
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = version, Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - All case variations should be recognized as prerelease
|
||||
Assert.NotNull(result);
|
||||
Assert.Empty(result); // Single prerelease should be kept
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1.0.0-dev")]
|
||||
[InlineData("1.0.0-DEV")]
|
||||
[InlineData("1.0.0-Dev")]
|
||||
[InlineData("1.0.0-DeV")]
|
||||
public void FilterPackagesToDelete_WithDifferentCaseDev_ShouldHandleCorrectly(string version)
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = version, Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - All case variations should be recognized as dev version
|
||||
Assert.NotNull(result);
|
||||
Assert.Empty(result); // Single dev version should be kept
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Suffix/Identifier Tests
|
||||
|
||||
[Theory]
|
||||
[InlineData("1.0.0-alpha1")]
|
||||
[InlineData("1.0.0-alpha.1")]
|
||||
[InlineData("1.0.0-beta2")]
|
||||
[InlineData("1.0.0-rc.1")]
|
||||
[InlineData("2025.2.14.1-dev.1")]
|
||||
[InlineData("2025.2.14.1-dev123")]
|
||||
public void FilterPackagesToDelete_WithCompoundSuffixes_ShouldIdentifyCorrectly(string version)
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = version, Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - Compound suffixes should be recognized and not cause errors
|
||||
Assert.NotNull(result);
|
||||
Assert.Empty(result); // Single prerelease/dev should be kept
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Empty and Null Tests
|
||||
|
||||
[Fact]
|
||||
public void FilterPackagesToDelete_WithEmptyList_ShouldReturnEmpty()
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>();
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - Empty input should return empty result
|
||||
Assert.NotNull(result);
|
||||
Assert.Empty(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FilterPackagesToDelete_WithNullableInputs_ShouldHandleGracefully()
|
||||
{
|
||||
// Arrange
|
||||
var packages = new List<GiteaPackage>
|
||||
{
|
||||
new() { Id = 1, Name = "test", Version = "1.0.0", Type = "docker", CreatedAt = DateTime.UtcNow }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _packageService.FilterPackagesToDelete(packages);
|
||||
|
||||
// Assert - Should handle without throwing and not delete prod
|
||||
Assert.NotNull(result);
|
||||
Assert.Empty(result); // Prod should not be deleted
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user