using Omika.Data.Repositories;
namespace Omika.Tests.Mobile;
///
/// Tests de la génération de nom unique des documents côté serveur
/// (DocumentPathResolver.WriteUniqueFile) : jamais d'écrasement, nom en base ==
/// nom physique, écriture atomique anti-collision concurrente, anti path traversal.
///
public class DocumentUniqueFileNameTests : IDisposable
{
private readonly string _dir;
public DocumentUniqueFileNameTests()
{
_dir = Path.Combine(Path.GetTempPath(), "omika-unique", Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(_dir);
}
public void Dispose()
{
if (Directory.Exists(_dir))
{
Directory.Delete(_dir, recursive: true);
}
}
[Fact]
public void PremierUpload_AucunExistant_ConserveLeNom()
{
// Act
string? name = DocumentPathResolver.WriteUniqueFile(_dir, "Viamichelin.pdf", [1, 2, 3]);
// Assert
Assert.Equal("Viamichelin.pdf", name);
Assert.True(File.Exists(Path.Combine(_dir, "Viamichelin.pdf")));
}
[Fact]
public void DeuxiemeUpload_MemeNom_GenereSuffixe_EtConserveLePremier()
{
// Arrange : Viamichelin.pdf existe déjà.
File.WriteAllBytes(Path.Combine(_dir, "Viamichelin.pdf"), new byte[] { 1, 1, 1 });
// Act
string? name = DocumentPathResolver.WriteUniqueFile(_dir, "Viamichelin.pdf", new byte[] { 2, 2, 2 });
// Assert : le second devient Viamichelin_1.pdf, le premier est intact.
Assert.Equal("Viamichelin_1.pdf", name);
Assert.Equal(new byte[] { 1, 1, 1 }, File.ReadAllBytes(Path.Combine(_dir, "Viamichelin.pdf")));
Assert.Equal(new byte[] { 2, 2, 2 }, File.ReadAllBytes(Path.Combine(_dir, "Viamichelin_1.pdf")));
}
[Fact]
public void TroisiemeUpload_DeuxExistants_GenereLeSuffixeSuivant()
{
// Arrange : Viamichelin.pdf et Viamichelin_1.pdf existent déjà.
File.WriteAllBytes(Path.Combine(_dir, "Viamichelin.pdf"), new byte[] { 1 });
File.WriteAllBytes(Path.Combine(_dir, "Viamichelin_1.pdf"), new byte[] { 2 });
// Act
string? name = DocumentPathResolver.WriteUniqueFile(_dir, "Viamichelin.pdf", new byte[] { 3 });
// Assert
Assert.Equal("Viamichelin_2.pdf", name);
Assert.True(File.Exists(Path.Combine(_dir, "Viamichelin_2.pdf")));
}
[Fact]
public void UploadsConcurrents_MemeNom_ProduisentDesNomsDistincts()
{
// Act : écritures parallèles du même nom → chacune doit obtenir un nom unique.
var results = new string?[8];
Parallel.For(0, results.Length, i =>
{
results[i] = DocumentPathResolver.WriteUniqueFile(_dir, "Viamichelin.pdf", [(byte)i]);
});
// Assert : 8 noms distincts (aucun écrasement).
Assert.Equal(results.Length, results.Distinct().Count());
Assert.Equal(results.Length, Directory.GetFiles(_dir).Length);
}
[Fact]
public void NomDangereux_PathTraversal_Bloque()
{
// Act : "..\..\Viamichelin.pdf" doit être réduit au simple nom de fichier.
string? name = DocumentPathResolver.WriteUniqueFile(_dir, @"..\..\Viamichelin.pdf", [1, 2, 3]);
// Assert : aucun fichier hors du répertoire, le nom est assaini.
Assert.Equal("Viamichelin.pdf", name);
Assert.True(File.Exists(Path.Combine(_dir, "Viamichelin.pdf")));
Assert.False(File.Exists(Path.Combine(Path.GetDirectoryName(_dir)!, "Viamichelin.pdf")));
}
[Fact]
public void NomAvecCaracteresInvalides_EstNettoye()
{
// Act + Assert
Assert.Equal("Viami_chel_in.pdf", DocumentPathResolver.SanitizeFileName("Viamiin.pdf"));
Assert.Equal("document", DocumentPathResolver.SanitizeFileName(" "));
}
}