using System.IO.Compression; using GitConverter.Lib.Converters; namespace GitConverter.TestsApp.Converters { /// /// Unit tests for focusing on archive helpers and cleanup helpers. /// /// /// Test strategy: /// - Verify archive recognition heuristics via for /// common extensions and composite suffixes (.tar.gz). /// - Validate archive inspection with and /// requirement checks via . /// - Ensure cleanup helpers remove files as expected. /// /// Notes: /// - Tests use temporary directories under the system temp path and remove them in Dispose to /// avoid leaving artifacts on the developer machine or CI agent. /// - Zip archives are created using /// with and without preserving the base directory to exercise folder-name detection (e.g. .gdb folders). /// public class ConverterUtilsTests : IDisposable { private readonly string _root; /// /// Create an isolated temp directory for each test. /// public ConverterUtilsTests() { _root = Path.Combine(Path.GetTempPath(), "GitConverter.ConverterUtilsTests", Guid.NewGuid().ToString("N")); Directory.CreateDirectory(_root); } /// /// Clean up the test directory tree after each test run. /// public void Dispose() { try { if (Directory.Exists(_root)) Directory.Delete(_root, true); } catch { } } /// /// Verifies that the archive detection heuristic recognizes common archive extensions, /// including composite suffixes and uncommon types. /// [Fact(DisplayName = "IsArchiveFile_RecognizesCommonExtensions")] public void IsArchiveFile_RecognizesCommonExtensions() { Assert.True(ConverterUtils.IsArchiveFile("test.zip")); Assert.True(ConverterUtils.IsArchiveFile("archive.tar.gz")); Assert.True(ConverterUtils.IsArchiveFile("example.kmz")); Assert.True(ConverterUtils.IsArchiveFile("package.7z")); Assert.False(ConverterUtils.IsArchiveFile("file.json")); Assert.False(ConverterUtils.IsArchiveFile("noext")); } /// /// Creates a zip archive containing shapefile components and verifies entries are listed /// and that ArchiveContainsAllRequiredExtensions returns true for .shp/.shx/.dbf. /// [Fact(DisplayName = "TryListArchiveEntries_and_ArchiveContainsAllRequiredExtensions")] public void TryListArchiveEntries_and_ArchiveContainsAllRequiredExtensions() { // Create a zip with shapefile components var zipPath = Path.Combine(_root, "shp.zip"); var tempDir = Path.Combine(_root, "ztemp"); Directory.CreateDirectory(tempDir); var shp = Path.Combine(tempDir, "a.shp"); var shx = Path.Combine(tempDir, "a.shx"); var dbf = Path.Combine(tempDir, "a.dbf"); File.WriteAllText(shp, "shp"); File.WriteAllText(shx, "shx"); File.WriteAllText(dbf, "dbf"); ZipFile.CreateFromDirectory(tempDir, zipPath); var entries = ConverterUtils.TryListArchiveEntries(zipPath)?.ToList(); Assert.NotNull(entries); Assert.Contains(entries, e => e.EndsWith("a.shp", StringComparison.OrdinalIgnoreCase)); Assert.Contains(entries, e => e.EndsWith("a.shx", StringComparison.OrdinalIgnoreCase)); Assert.Contains(entries, e => e.EndsWith("a.dbf", StringComparison.OrdinalIgnoreCase)); var required = new[] { ".shp", ".shx", ".dbf" }; Assert.True(ConverterUtils.ArchiveContainsAllRequiredExtensions(zipPath, required)); } /// /// When an archive contains a folder named "*.gdb" and the base directory is preserved /// in the zip entries, the collector should observe the .gdb segment and requirement checks /// should succeed for .gdb. /// [Fact(DisplayName = "ArchiveContainingGdbFolder_IsRecognizedAsGdb")] public void ArchiveContainingGdbFolder_IsRecognizedAsGdb() { // Create a parent folder and a child folder named MyGdb.gdb with a dummy file inside, // then create the zip including the base directory so the .gdb folder name is preserved in entries. var parent = Path.Combine(_root, "parent"); Directory.CreateDirectory(parent); var src = Path.Combine(parent, "MyGdb.gdb"); Directory.CreateDirectory(src); var dummy = Path.Combine(src, "gdbtable"); File.WriteAllText(dummy, "x"); var zipPath = Path.Combine(_root, "gdb.zip"); // includeBaseDirectory = true preserves the MyGdb.gdb segment inside the archive entries ZipFile.CreateFromDirectory(parent, zipPath, CompressionLevel.Fastest, includeBaseDirectory: true); // Entries listing should contain the path segment with .gdb var entries = ConverterUtils.TryListArchiveEntries(zipPath)?.ToList(); Assert.NotNull(entries); Assert.True(entries.Any(e => e.IndexOf(".gdb", StringComparison.OrdinalIgnoreCase) >= 0), "Expected archive entries to include a .gdb folder segment (created with includeBaseDirectory)."); // ArchiveContainsAllRequiredExtensions should detect .gdb when checking for folder markers Assert.True(ConverterUtils.ArchiveContainsAllRequiredExtensions(zipPath, new[] { ".gdb" })); } /// /// Verifies that CleanupExtractedFiles deletes the specified files and does not throw when files are missing. /// [Fact(DisplayName = "CleanupExtractedFiles_DeletesFiles")] public void CleanupExtractedFiles_DeletesFiles() { var f1 = Path.Combine(_root, "t1.tmp"); var f2 = Path.Combine(_root, "t2.tmp"); File.WriteAllText(f1, "x"); File.WriteAllText(f2, "y"); ConverterUtils.CleanupExtractedFiles(new[] { f1, f2 }); Assert.False(File.Exists(f1)); Assert.False(File.Exists(f2)); // Calling again with missing files should not throw ConverterUtils.CleanupExtractedFiles(new[] { f1, f2, "" }); } /// /// TryListArchiveEntries should return null for a non-existent archive and ArchiveContainsAllRequiredExtensions /// should return false when required components are missing. /// [Fact(DisplayName = "TryListArchiveEntries_NonexistentOrMissingComponents")] public void TryListArchiveEntries_NonexistentOrMissingComponents() { var missingPath = Path.Combine(_root, "doesnotexist.zip"); var entries = ConverterUtils.TryListArchiveEntries(missingPath); Assert.Null(entries); // Create an archive that lacks required components for a shapefile var zipPath = Path.Combine(_root, "incomplete.zip"); var tempDir = Path.Combine(_root, "inc"); Directory.CreateDirectory(tempDir); File.WriteAllText(Path.Combine(tempDir, "only.txt"), "x"); ZipFile.CreateFromDirectory(tempDir, zipPath); var contains = ConverterUtils.ArchiveContainsAllRequiredExtensions(zipPath, new[] { ".shp", ".shx", ".dbf" }); Assert.False(contains); } } }