exception testing

This commit is contained in:
neuecc
2020-05-10 22:44:40 +09:00
parent af6dbd8868
commit 93dd82e3d4
17 changed files with 926 additions and 3963 deletions

View File

@@ -110,26 +110,28 @@ namespace Cysharp.Threading.Tasks.Linq
{
var self = (Enumerator)state;
if (self.awaiter.GetResult())
if (self.TryGetResult(self.awaiter, out var result))
{
self.Current = self.enumerator.Current;
}
else
{
if (self.state == State.RequireAppend)
if (result)
{
self.state = State.Completed;
self.Current = self.element;
self.Current = self.enumerator.Current;
self.completionSource.TrySetResult(true);
}
else
{
self.state = State.Completed;
self.completionSource.TrySetResult(false);
return;
if (self.state == State.RequireAppend)
{
self.state = State.Completed;
self.Current = self.element;
self.completionSource.TrySetResult(true);
}
else
{
self.state = State.Completed;
self.completionSource.TrySetResult(false);
}
}
}
self.completionSource.TrySetResult(true);
}
public UniTask DisposeAsync()
@@ -144,770 +146,3 @@ namespace Cysharp.Threading.Tasks.Linq
}
}

View File

@@ -31,6 +31,21 @@ namespace Cysharp.Threading.Tasks.Linq
{
completionSource.GetResult(token);
}
protected bool TryGetResult<T>(UniTask<T>.Awaiter awaiter, out T result)
{
try
{
result = awaiter.GetResult();
return true;
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
result = default;
return false;
}
}
}

View File

@@ -1,775 +1,53 @@
namespace Cysharp.Threading.Tasks.Linq
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Cast
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TResult> Cast<TResult>(this IUniTaskAsyncEnumerable<Object> source)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new Cast<TResult>(source);
}
}
}
internal sealed class Cast<TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<object> source;
public Cast(IUniTaskAsyncEnumerable<object> source)
{
this.source = source;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<object, TResult>
{
public Enumerator(IUniTaskAsyncEnumerable<object> source, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
Current = (TResult)SourceCurrent;
result = true;
return true;
}
result = false;
return true;
}
}
}
}

View File

@@ -86,7 +86,15 @@ namespace Cysharp.Threading.Tasks.Linq
}
}
awaiter = enumerator.MoveNextAsync().GetAwaiter();
try
{
awaiter = enumerator.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
if (awaiter.IsCompleted)
{
@@ -102,21 +110,24 @@ namespace Cysharp.Threading.Tasks.Linq
{
var self = (Enumerator)state;
if (self.awaiter.GetResult())
if (self.TryGetResult(self.awaiter, out var result))
{
self.Current = self.enumerator.Current;
self.completionSource.TrySetResult(true);
}
else
{
if (self.iteratingState == IteratingState.IteratingFirst)
if (result)
{
self.RunSecondAfterDisposeAsync().Forget();
return;
self.Current = self.enumerator.Current;
self.completionSource.TrySetResult(true);
}
else
{
if (self.iteratingState == IteratingState.IteratingFirst)
{
self.RunSecondAfterDisposeAsync().Forget();
return;
}
self.iteratingState = IteratingState.Complete;
self.completionSource.TrySetResult(false);
self.iteratingState = IteratingState.Complete;
self.completionSource.TrySetResult(false);
}
}
}

View File

@@ -1,775 +0,0 @@
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class Create
{
}
}

View File

@@ -1,775 +1,135 @@
namespace Cysharp.Threading.Tasks.Linq
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class DefaultIfEmpty
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> DefaultIfEmpty<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new DefaultIfEmpty<TSource>(source, default);
}
public static IUniTaskAsyncEnumerable<TSource> DefaultIfEmpty<TSource>(this IUniTaskAsyncEnumerable<TSource> source, TSource defaultValue)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new DefaultIfEmpty<TSource>(source, defaultValue);
}
}
internal sealed class DefaultIfEmpty<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly TSource defaultValue;
public DefaultIfEmpty(IUniTaskAsyncEnumerable<TSource> source, TSource defaultValue)
{
this.source = source;
this.defaultValue = defaultValue;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, defaultValue, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
{
enum IteratingState : byte
{
Empty,
Iterating,
Completed
}
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly TSource defaultValue;
CancellationToken cancellationToken;
IteratingState iteratingState;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter awaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, TSource defaultValue, CancellationToken cancellationToken)
{
this.source = source;
this.defaultValue = defaultValue;
this.cancellationToken = cancellationToken;
this.iteratingState = IteratingState.Empty;
}
public TSource Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (iteratingState == IteratingState.Empty)
{
return CompletedTasks.False;
}
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
MoveNextCore(this);
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
return new UniTask<bool>(this, completionSource.Version);
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
self.iteratingState = IteratingState.Iterating;
self.Current = self.enumerator.Current;
self.completionSource.TrySetResult(true);
}
else
{
if (self.iteratingState == IteratingState.Empty)
{
self.iteratingState = IteratingState.Completed;
self.Current = self.defaultValue;
self.completionSource.TrySetResult(true);
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
}

View File

@@ -1,775 +1,61 @@
namespace Cysharp.Threading.Tasks.Linq
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
internal sealed class OfType
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TResult> OfType<TResult>(this IUniTaskAsyncEnumerable<Object> source)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new OfType<TResult>(source);
}
}
}
internal sealed class OfType<TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<object> source;
public OfType(IUniTaskAsyncEnumerable<object> source)
{
this.source = source;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<object, TResult>
{
public Enumerator(IUniTaskAsyncEnumerable<object> source, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (SourceCurrent is TResult castCurent)
{
Current = castCurent;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
}

View File

@@ -0,0 +1,54 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TValue> Throw<TValue>(Exception exception)
{
return new Throw<TValue>(exception);
}
}
internal class Throw<TValue> : IUniTaskAsyncEnumerable<TValue>
{
readonly Exception exception;
public Throw(Exception exception)
{
this.exception = exception;
}
public IUniTaskAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(exception, cancellationToken);
}
class Enumerator : IUniTaskAsyncEnumerator<TValue>
{
readonly Exception exception;
CancellationToken cancellationToken;
public Enumerator(Exception exception, CancellationToken cancellationToken)
{
this.exception = exception;
this.cancellationToken = cancellationToken;
}
public TValue Current => default;
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
return UniTask.FromException<bool>(exception);
}
public UniTask DisposeAsync()
{
return default;
}
}
}
}

View File

@@ -243,19 +243,21 @@ namespace Cysharp.Threading.Tasks.Linq
{
get
{
if (error != null)
{
ExceptionDispatchInfo.Capture(error).Throw();
}
if (useCachedCurrent)
{
return current;
}
current = queuedResult.Dequeue();
useCachedCurrent = true;
return current;
if (queuedResult.Count != 0)
{
current = queuedResult.Dequeue();
useCachedCurrent = true;
return current;
}
else
{
return default; // undefined.
}
}
}

View File

@@ -1,18 +1,57 @@
using System;
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> Where<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
public static IUniTaskAsyncEnumerable<TSource> Where<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate)
{
return new Cysharp.Threading.Tasks.Linq.Where<TSource>(source, predicate);
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new Where<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<bool>> predicate)
public static IUniTaskAsyncEnumerable<TSource> Where<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, Boolean> predicate)
{
return new Cysharp.Threading.Tasks.Linq.WhereAwait<TSource>(source, predicate);
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new WhereInt<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new WhereAwait<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new WhereAwaitInt<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new WhereAwaitCancellation<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new WhereAwaitIntCancellation<TSource>(source, predicate);
}
}
@@ -66,6 +105,57 @@ namespace Cysharp.Threading.Tasks.Linq
}
}
internal sealed class WhereInt<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, bool> predicate;
public WhereInt(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly Func<TSource, int, bool> predicate;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (predicate(SourceCurrent, checked(index++)))
{
Current = SourceCurrent;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
internal sealed class WhereAwait<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
@@ -113,4 +203,149 @@ namespace Cysharp.Threading.Tasks.Linq
}
}
internal sealed class WhereAwaitInt<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, UniTask<bool>> predicate;
public WhereAwaitInt(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
readonly Func<TSource, int, UniTask<bool>> predicate;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
return predicate(sourceCurrent, checked(index++));
}
protected override bool TrySetCurrentCore(bool awaitResult)
{
if (awaitResult)
{
Current = SourceCurrent;
return true;
}
else
{
return false;
}
}
}
}
internal sealed class WhereAwaitCancellation<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<bool>> predicate;
public WhereAwaitCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
readonly Func<TSource, CancellationToken, UniTask<bool>> predicate;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
return predicate(sourceCurrent, cancellationToken);
}
protected override bool TrySetCurrentCore(bool awaitResult)
{
if (awaitResult)
{
Current = SourceCurrent;
return true;
}
else
{
return false;
}
}
}
}
internal sealed class WhereAwaitIntCancellation<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, CancellationToken, UniTask<bool>> predicate;
public WhereAwaitIntCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
readonly Func<TSource, int, CancellationToken, UniTask<bool>> predicate;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
return predicate(sourceCurrent, checked(index++), cancellationToken);
}
protected override bool TrySetCurrentCore(bool awaitResult)
{
if (awaitResult)
{
Current = SourceCurrent;
return true;
}
else
{
return false;
}
}
}
}
}

View File

@@ -90,22 +90,34 @@ namespace Cysharp.Threading.Tasks.Linq
{
var self = (Enumerator)state;
if (self.firstAwaiter.GetResult())
if (self.TryGetResult(self.firstAwaiter, out var result))
{
self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter();
if (self.secondAwaiter.IsCompleted)
if (result)
{
SecondMoveNextCore(self);
try
{
self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
if (self.secondAwaiter.IsCompleted)
{
SecondMoveNextCore(self);
}
else
{
self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self);
}
}
else
{
self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self);
self.completionSource.TrySetResult(false);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
static void SecondMoveNextCore(object state)

View File

@@ -24,24 +24,8 @@ namespace ___Dummy
public static IUniTaskAsyncEnumerable<TResult> Cast<TResult>(this IUniTaskAsyncEnumerable<Object> source)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> DefaultIfEmpty<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> DefaultIfEmpty<TSource>(this IUniTaskAsyncEnumerable<TSource> source, TSource defaultValue)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> Distinct<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
{
throw new NotImplementedException();
@@ -259,11 +243,6 @@ namespace ___Dummy
public static IUniTaskAsyncEnumerable<TResult> OfType<TResult>(this IUniTaskAsyncEnumerable<Object> source)
{
throw new NotImplementedException();
}
public static IOrderedAsyncEnumerable<TSource> OrderBy<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
throw new NotImplementedException();
@@ -550,35 +529,7 @@ namespace ___Dummy
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> Where<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> Where<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, Boolean> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask<Boolean>> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask<Boolean>> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<ValueTuple<TFirst, TSecond>> Zip<TFirst, TSecond>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second)
{