104 lines
3.8 KiB
C#
104 lines
3.8 KiB
C#
using Omika.Data.Repositories;
|
|
|
|
namespace Omika.Tests.Mobile;
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
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("Viami<chel>in.pdf"));
|
|
Assert.Equal("document", DocumentPathResolver.SanitizeFileName(" "));
|
|
}
|
|
}
|