using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks.Linq; using System; using System.Collections.Generic; using System.Runtime.ExceptionServices; using System.Threading; namespace NetCoreTests.Linq { public class UniTaskTestException : Exception { public static IUniTaskAsyncEnumerable ThrowImmediate() { return UniTaskAsyncEnumerable.Throw(new UniTaskTestException()); } public static IUniTaskAsyncEnumerable ThrowAfter() { return new ThrowAfter(new UniTaskTestException()); } public static IUniTaskAsyncEnumerable ThrowInMoveNext() { return new ThrowIn(new UniTaskTestException()); } public static IEnumerable> Throws(int count = 3) { yield return ThrowImmediate(); yield return ThrowAfter(); yield return ThrowInMoveNext(); yield return UniTaskAsyncEnumerable.Range(1, count).Concat(ThrowImmediate()); yield return UniTaskAsyncEnumerable.Range(1, count).Concat(ThrowAfter()); yield return UniTaskAsyncEnumerable.Range(1, count).Concat(ThrowInMoveNext()); } } internal class ThrowIn : IUniTaskAsyncEnumerable { readonly Exception exception; public ThrowIn(Exception exception) { this.exception = exception; } public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { return new Enumerator(exception, cancellationToken); } class Enumerator : IUniTaskAsyncEnumerator { readonly Exception exception; CancellationToken cancellationToken; public Enumerator(Exception exception, CancellationToken cancellationToken) { this.exception = exception; this.cancellationToken = cancellationToken; } public TValue Current => default; public UniTask MoveNextAsync() { ExceptionDispatchInfo.Capture(exception).Throw(); return new UniTask(false); } public UniTask DisposeAsync() { return default; } } } internal class ThrowAfter : IUniTaskAsyncEnumerable { readonly Exception exception; public ThrowAfter(Exception exception) { this.exception = exception; } public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { return new Enumerator(exception, cancellationToken); } class Enumerator : IUniTaskAsyncEnumerator { readonly Exception exception; CancellationToken cancellationToken; public Enumerator(Exception exception, CancellationToken cancellationToken) { this.exception = exception; this.cancellationToken = cancellationToken; } public TValue Current => default; public UniTask MoveNextAsync() { cancellationToken.ThrowIfCancellationRequested(); var tcs = new UniTaskCompletionSource(); var awaiter = UniTask.Yield().GetAwaiter(); awaiter.UnsafeOnCompleted(() => { Thread.Sleep(1); tcs.TrySetException(exception); }); return tcs.Task; } public UniTask DisposeAsync() { return default; } } } }