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);
}
}
}