using Microsoft.Data.Sqlite; using WebDrop.Core; using WebDrop.Storage; namespace WebDrop.Core.Tests; public sealed class AvatarFilesTests : IDisposable { private readonly string _dir = Path.Combine(Path.GetTempPath(), "wd-avatar-" + Guid.NewGuid().ToString("N")); public void Dispose() { SqliteConnection.ClearAllPools(); try { Directory.Delete(_dir, true); } catch (IOException) { } } private static string Gif(byte fill) => "data:image/gif;base64," + Convert.ToBase64String([(byte)'G', (byte)'I', (byte)'F', fill, fill, fill, fill, fill]); [Fact] public void SavedAvatarsAreContentAddressedFilesAndResolveBack() { var files = new AvatarFiles(Path.Combine(_dir, "a")); string first = files.Save(Gif(1)), again = files.Save(Gif(1)), other = files.Save(Gif(2)); Assert.Equal(first, again); Assert.NotEqual(first, other); var blob = files.Resolve(first)!; Assert.Equal("image/gif", blob.Mime); Assert.Equal(8, new FileInfo(blob.Path).Length); Assert.Null(files.Resolve("../../etc/passwd")); Assert.Null(files.Resolve(new string('0', 64) + ".gif")); } [Fact] public void LegacyDataUrlRowsAreMovedToFilesOnOpenAndOrphansAreSwept() { string db = Path.Combine(_dir, "v2", "webdrop.db"); var id = Id16.FromBytes(Enumerable.Range(1, 16).Select(i => (byte)i).ToArray()); using (var store = new SqliteChannelStore(db)) { } using (var conn = new SqliteConnection($"Data Source={db}")) { conn.Open(); using var cmd = conn.CreateCommand(); cmd.CommandText = "INSERT INTO channel_avatars(space_id, avatar, thumb) VALUES ($c, $a, $t)"; cmd.Parameters.AddWithValue("$c", id.ToArray()); cmd.Parameters.AddWithValue("$a", Gif(3)); cmd.Parameters.AddWithValue("$t", Gif(4)); cmd.ExecuteNonQuery(); } string avatars = Path.Combine(_dir, "v2", "avatars", "space"); File.WriteAllBytes(Path.Combine(avatars, "orphan.gif"), [1]); using var reopened = new SqliteChannelStore(db); var (full, thumb) = reopened.Read(tx => (tx.GetChannelAvatar(id, thumb: false), tx.GetChannelAvatar(id, thumb: true))); Assert.NotNull(full); Assert.NotNull(thumb); Assert.NotEqual(full!.Hash, thumb!.Hash); Assert.False(File.Exists(Path.Combine(avatars, "orphan.gif"))); Assert.Equal(2, Directory.GetFiles(avatars).Length); } }