using System.Runtime.CompilerServices; using Avalonia.Platform.Storage; namespace AtomUI.Desktop.Controls.Tests.Upload; internal abstract class TestStorageItem : IStorageItem { public string Name { get; } public Uri Path { get; } public int DisposeCount { get; private set; } public bool CanBookmark => false; protected TestStorageItem(string name, string path) { Name = name; Path = new Uri(path, UriKind.Absolute); } public virtual Task GetBasicPropertiesAsync() { return Task.FromResult(new StorageItemProperties()); } public Task SaveBookmarkAsync() => Task.FromResult(null); public Task GetParentAsync() => Task.FromResult(null); public Task DeleteAsync() => Task.CompletedTask; public Task MoveAsync(IStorageFolder destination) => Task.FromResult(null); public void Dispose() { DisposeCount++; } } internal sealed class TestStorageFile : TestStorageItem, IStorageFile { private readonly byte[] _content; private readonly StorageItemProperties _properties; public int OpenReadCount { get; private set; } public Exception? MetadataException { get; init; } public Exception? OpenReadException { get; init; } public TestStorageFile( string name, string path, byte[]? content = null, ulong? size = null, DateTimeOffset? dateCreated = null, DateTimeOffset? dateModified = null) : base(name, path) { _content = content ?? [1, 2, 3]; _properties = new StorageItemProperties(size ?? (ulong)_content.Length, dateCreated, dateModified); } public override Task GetBasicPropertiesAsync() { return MetadataException is null ? Task.FromResult(_properties) : Task.FromException(MetadataException); } public Task OpenReadAsync() { OpenReadCount++; return OpenReadException is null ? Task.FromResult(new MemoryStream(_content, writable: false)) : Task.FromException(OpenReadException); } public Task OpenWriteAsync() { return Task.FromResult(new MemoryStream()); } } internal sealed class ThrowingStorageFile : IStorageFile { public string Name { get; } public Uri Path { get; } public bool CanBookmark => false; public int DisposeCount { get; private set; } internal ThrowingStorageFile(string name, string path) { Name = name; Path = new Uri(path, UriKind.Absolute); } public Task GetBasicPropertiesAsync() => Task.FromResult(new StorageItemProperties(3)); public Task OpenReadAsync() => Task.FromResult(new MemoryStream([1, 2, 3], writable: false)); public Task OpenWriteAsync() => Task.FromResult(new MemoryStream()); public Task SaveBookmarkAsync() => Task.FromResult(null); public Task GetParentAsync() => Task.FromResult(null); public Task DeleteAsync() => Task.CompletedTask; public Task MoveAsync(IStorageFolder destination) => Task.FromResult(null); public void Dispose() { DisposeCount++; throw new InvalidOperationException($"Dispose failed for {Name}."); } } internal sealed class TestStorageFolder : TestStorageItem, IStorageFolder { private readonly IReadOnlyList _items; public Exception? EnumerationException { get; init; } public TaskCompletionSource? EnumerationGate { get; init; } public TaskCompletionSource EnumerationStarted { get; } = new(TaskCreationOptions.RunContinuationsAsynchronously); public int? PauseAfterItemCount { get; init; } public TaskCompletionSource? EnumerationPauseGate { get; init; } public TaskCompletionSource EnumerationPaused { get; } = new(TaskCreationOptions.RunContinuationsAsynchronously); public TestStorageFolder(string name, string path, params IStorageItem[] items) : base(name, path) { _items = items; } public IAsyncEnumerable GetItemsAsync() => EnumerateAsync(); public Task GetFolderAsync(string name) => Task.FromResult(null); public Task GetFileAsync(string name) => Task.FromResult(null); public Task CreateFileAsync(string name) => Task.FromResult(null); public Task CreateFolderAsync(string name) => Task.FromResult(null); private async IAsyncEnumerable EnumerateAsync( [EnumeratorCancellation] CancellationToken cancellationToken = default) { EnumerationStarted.TrySetResult(); if (EnumerationGate is not null) { await EnumerationGate.Task.WaitAsync(cancellationToken); } if (EnumerationException is not null) { throw EnumerationException; } var yieldedCount = 0; foreach (var item in _items) { cancellationToken.ThrowIfCancellationRequested(); yield return item; yieldedCount++; if (PauseAfterItemCount == yieldedCount && EnumerationPauseGate is not null) { EnumerationPaused.TrySetResult(); await EnumerationPauseGate.Task.WaitAsync(cancellationToken); } } } }