< Summary

Information
Class: AmbientServices.Test.TestAsync
Assembly: AmbientServices.Async.Test
File(s): /home/runner/work/AmbientServices.Async/AmbientServices.Async/AmbientServices.Async.Test/TestAsync.cs
Tag: 76_25271648613
Line coverage
96%
Covered lines: 442
Uncovered lines: 17
Coverable lines: 459
Total lines: 844
Line coverage: 96.2%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Async_Basic()100%11100%
Async_AlreadyRun()100%11100%
Async_NotAlreadyRun()100%11100%
Async_AggregateExceptionUnwrap()100%11100%
Async_AggregateExceptionUnwrapWithTask()100%11100%
<Async_AggregateExceptionUnwrapWithTask()100%11100%
Async_AggregateExceptionUnwrapWithReturn()100%11100%
<Async_AggregateExceptionUnwrapWithReturn()100%1166.67%
Async_AggregateExceptionCantUnwrap()100%11100%
Async_AggregateExceptionCantUnwrapWithTask()100%11100%
<Async_AggregateExceptionCantUnwrapWithTask()100%11100%
Async_AggregateExceptionCantUnwrapWithReturn()100%11100%
<Async_AggregateExceptionCantUnwrapWithReturn()100%1166.67%
Async_SynchronizeVariations()100%11100%
Async_Misc()100%11100%
Async_BasicAsyncThrow(...)100%11100%
Async_BasicAsync()100%11100%
Async_BasicAsyncPart1()100%11100%
Async_BasicAsyncPart2()100%11100%
Async_BasicAsyncPart3()100%11100%
Async_BasicAsyncPart4()100%11100%
Async_BasicAsyncWithLock()100%11100%
Async_Enumerable()100%11100%
TestAsyncEnum()100%11100%
Async_Synchronize()100%11100%
AsyncTest()100%11100%
Async_SyncInAsyncInSyncVoid()100%11100%
Loop1()100%11100%
Loop2()100%1188.24%
Async_SyncInAsyncInSyncWithReturn()100%11100%
LoopWithReturn1()100%11100%
LoopWithReturn2()100%1188.89%
Async_ValueTaskSyncInAsyncInSyncVoid()100%11100%
ValueTaskLoop1()100%11100%
ValueTaskLoop2()100%1188.24%
Async_ValueTaskSyncInAsyncInSyncWithReturn()100%11100%
ValueTaskLoopWithReturn1()100%11100%
ValueTaskLoopWithReturn2()100%1192%
Sync_Enumerator()100%11100%
Synchronized_AsyncEnumerator()100%11100%
Sync_AsyncEnumerator()100%11100%
<Sync_AsyncEnumerator()100%11100%
<Sync_AsyncEnumerator()100%11100%
<Sync_AsyncEnumerator()100%11100%
<Sync_AsyncEnumerator()100%11100%
<Sync_AsyncEnumerator()100%11100%
<Sync_AsyncEnumerator()100%11100%
<Sync_AsyncEnumerator()100%11100%
<Sync_AsyncEnumerator()100%1166.67%
<Sync_AsyncEnumerator()100%1166.67%
Async_AsyncEnumerator()100%11100%
EnumerateAsync()100%11100%
Async_AsyncEnumeratorExceptions()100%11100%
<Async_AsyncEnumeratorExceptions()100%1133.33%
<Async_AsyncEnumeratorExceptions()100%1133.33%
NullAsyncEnumerable()100%210%
Async_InfiniteEnumeratorAsyncToSync()100%11100%
InfiniteEnumerateAsync()100%11100%
SynchronousSynchronizationContextExceptions()100%11100%
Async_ArgumentNullExceptions()100%11100%
Async_ArgumentNullExceptionsAsync()100%11100%
<Async_ArgumentNullExceptionsAsync()100%11100%
<Async_ArgumentNullExceptionsAsync()100%11100%
<Async_ArgumentNullExceptionsAsync()100%11100%
<Async_ArgumentNullExceptionsAsync()100%11100%
FilterAsyncFromStackTrace()100%11100%
<FilterAsyncFromStackTrace()100%11100%
ArgumentNullExceptions()100%11100%

File(s)

/home/runner/work/AmbientServices.Async/AmbientServices.Async/AmbientServices.Async.Test/TestAsync.cs

#LineLine coverage
 1using AmbientServices.Utilities;
 2using AmbientServices;
 3using Microsoft.VisualStudio.TestTools.UnitTesting;
 4using System;
 5using System.Collections.Generic;
 6using System.Diagnostics;
 7using System.Linq;
 8using System.Runtime.CompilerServices;
 9using System.Text;
 10using System.Threading;
 11using System.Threading.Tasks;
 12
 13namespace AmbientServices.Test
 14{
 15    [TestClass]
 16    public class TestAsync
 17    {
 18        /// <summary>
 19        /// Performs basic tests on the <see cref="Async"/> class.
 20        /// </summary>
 21        [TestMethod]
 22        public void Async_Basic()
 23        {
 124            Assert.AreNotEqual(Async.DefaultAsyncContext, Async.SinglethreadedContext);
 125            int result = Async.RunTaskSync(() =>
 126            {
 127                Task<int> task = Async_BasicAsync();
 128                return task;
 129            });
 130        }
 31        /// <summary>
 32        /// Performs basic tests on the <see cref="Async"/> class.
 33        /// </summary>
 34        [TestMethod]
 35        public void Async_AlreadyRun()
 36        {
 137            Async.RunTaskSync(() => Task.CompletedTask);
 138        }
 39        /// <summary>
 40        /// Performs basic tests on the <see cref="Async"/> class.
 41        /// </summary>
 42        [TestMethod]
 43        public void Async_NotAlreadyRun()
 44        {
 145            Async.RunTaskSync(() => new Task(() => { }));
 146        }
 47        /// <summary>
 48        /// Performs basic tests on the <see cref="Async"/> class.
 49        /// </summary>
 50        [TestMethod]
 51        public void Async_AggregateExceptionUnwrap()
 52        {
 153            Assert.ThrowsExactly<ExpectedException>(() => Async.RunTaskSync(() => throw new AggregateException(new Expec
 154        }
 55        /// <summary>
 56        /// Performs basic tests on the <see cref="Async"/> class.
 57        /// </summary>
 58        [TestMethod]
 59        public void Async_AggregateExceptionUnwrapWithTask()
 60        {
 161            Assert.ThrowsExactly<ExpectedException>(() => Async.RunTaskSync(async () => { await Task.Delay(10); throw ne
 162        }
 63        /// <summary>
 64        /// Performs basic tests on the <see cref="Async"/> class.
 65        /// </summary>
 66        [TestMethod]
 67        public void Async_AggregateExceptionUnwrapWithReturn()
 68        {
 169            Assert.AreNotEqual(Async.DefaultAsyncContext, Async.SinglethreadedContext);
 170            Assert.ThrowsExactly<ExpectedException>(() => Async.RunTaskSync(async () =>
 171            {
 172                await Task.Delay(10);
 173                return await Async_BasicAsyncThrow(new AggregateException(new ExpectedException(nameof(Async_AggregateEx
 074            }));
 175        }
 76        /// <summary>
 77        /// Performs basic tests on the <see cref="Async"/> class.
 78        /// </summary>
 79        [TestMethod]
 80        public void Async_AggregateExceptionCantUnwrap()
 81        {
 182            Assert.ThrowsExactly<AggregateException>(() => Async.RunTaskSync(() => throw new AggregateException(new Expe
 183        }
 84        /// <summary>
 85        /// Performs basic tests on the <see cref="Async"/> class.
 86        /// </summary>
 87        [TestMethod]
 88        public void Async_AggregateExceptionCantUnwrapWithTask()
 89        {
 190            Assert.ThrowsExactly<AggregateException>(() => Async.RunTaskSync(async () => { await Task.Delay(10); throw n
 191        }
 92        /// <summary>
 93        /// Performs basic tests on the <see cref="Async"/> class.
 94        /// </summary>
 95        [TestMethod]
 96        public void Async_AggregateExceptionCantUnwrapWithReturn()
 97        {
 198            Assert.AreNotEqual(Async.DefaultAsyncContext, Async.SinglethreadedContext);
 199            Assert.ThrowsExactly<AggregateException>(() => Async.RunTaskSync(async () =>
 1100            {
 1101                await Task.Delay(10);
 1102                return await Async_BasicAsyncThrow(new AggregateException(new ExpectedException(nameof(Async_AggregateEx
 0103            }));
 1104        }
 105        /// <summary>
 106        /// Performs basic tests on the <see cref="Async"/> class.
 107        /// </summary>
 108        [TestMethod]
 109        public void Async_SynchronizeVariations()
 110        {
 1111            TimeSpan timeout = TimeSpan.FromSeconds(60);
 1112            Async.RunTaskSync(() =>
 1113            {
 1114                Task task = Async_BasicAsyncPart2();
 1115                return task;
 1116            });
 1117            Async.RunTaskSync(() => Async_BasicAsyncPart2(default));
 1118            int result = Async.RunTaskSync(Async_BasicAsyncPart3);
 1119            result = Async.RunTaskSync(() => Async_BasicAsyncPart4(default));
 1120        }
 121
 122        /// <summary>
 123        /// Performs basic tests on the <see cref="Async"/> class.
 124        /// </summary>
 125        [TestMethod]
 126        public void Async_Misc()
 127        {
 128            // try to create a copy
 1129            System.Threading.SynchronizationContext context = SynchronousSynchronizationContext.Default.CreateCopy();
 130            // try to send a delegate (should execute synchronously)
 1131            int set = 0;
 1132            SynchronousSynchronizationContext.Default.Send(new SendOrPostCallback(o =>
 1133            {
 1134                set = 1;
 1135            }),
 1136                this);
 1137            Assert.AreEqual(1, set);
 138
 1139            Assert.AreEqual(1, SynchronousTaskScheduler.Default.MaximumConcurrencyLevel);
 1140        }
 141
 142        private Task<int> Async_BasicAsyncThrow(Exception ex)
 143        {
 1144            throw ex;
 145        }
 146
 147        private async Task<int> Async_BasicAsync()
 148        {
 1149            await Async_BasicAsyncPart1();
 1150            await Async_BasicAsyncPart2();
 1151            await Async_BasicAsyncWithLock();
 1152            int result = await Async_BasicAsyncPart3();
 1153            return result;
 1154        }
 155
 156        private async Task Async_BasicAsyncPart1()
 157        {
 1158            await Task.Delay(200);
 1159            await Task.Delay(50);
 1160        }
 161
 162        private async Task Async_BasicAsyncPart2(CancellationToken cancel = default)
 163        {
 1164            Thread.Sleep(200);
 1165            Thread.Sleep(50);
 1166            await Task.Yield();
 1167        }
 168        private async Task<int> Async_BasicAsyncPart3()
 169        {
 1170            await Task.Delay(50);
 1171            return 1378902;
 1172        }
 173        private async Task<int> Async_BasicAsyncPart4(CancellationToken cancel = default)
 174        {
 1175            await Task.Delay(50, cancel);
 1176            return 1378902;
 1177        }
 178
 179        private async Task Async_BasicAsyncWithLock(CancellationToken cancel = default)
 180        {
 1181            using SemaphoreSlim lock2 = new(1);
 1182            await lock2.WaitAsync(1000, cancel);
 183            try
 184            {
 1185                await Task.Delay(50);
 1186                await Task.Yield();
 1187            }
 188            finally
 189            {
 1190                lock2.Release();
 191            }
 1192        }
 193
 194#if NETSTANDARD2_1 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
 195        /// <summary>
 196        /// Performs basic tests on the <see cref="Async"/> class.
 197        /// </summary>
 198        [TestMethod]
 199        public void Async_Enumerable()
 200        {
 1201            int count = 0;
 1202            foreach (int i in Async.AsyncEnumerableToEnumerable(() => TestAsyncEnum(10, 100)))
 203            {
 1204                ++count;
 205            }
 1206            Assert.AreEqual(100, count);
 1207        }
 208        private async IAsyncEnumerable<int> TestAsyncEnum(int delayMilliseconds, int limit, [EnumeratorCancellation] Can
 209        {
 1210            for (int loop = 0; loop < limit; ++loop)
 211            {
 1212                await Task.Delay(delayMilliseconds);
 1213                yield return loop;
 214            }
 1215        }
 216        /// <summary>
 217        /// Performs basic tests on the <see cref="Async"/> class.
 218        /// </summary>
 219        [TestMethod]
 220        public void Async_Synchronize()
 221        {
 1222            Assert.AreNotEqual(Async.DefaultAsyncContext, Async.SinglethreadedContext);
 1223            Async.RunTaskSync(AsyncTest);
 1224        }
 225        private async Task AsyncTest()
 226        {
 1227            await Task.Delay(10);
 1228        }
 229#endif
 230
 231
 232        /// <summary>
 233        /// Performs basic tests on the <see cref="Async"/> class.
 234        /// </summary>
 235        [TestMethod]
 236        public void Async_SyncInAsyncInSyncVoid()
 237        {
 1238            int mainThreadId = Thread.CurrentThread.ManagedThreadId;
 1239            int threadId = Thread.CurrentThread.ManagedThreadId;
 1240            for (int count = 0; count < 3; ++count)
 241            {
 1242                Async.RunTaskSync(() => Loop1(mainThreadId));
 1243                threadId = Thread.CurrentThread.ManagedThreadId;
 1244                Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 245            }
 1246        }
 247        private async Task Loop1(int mainThreadId)
 248        {
 1249            Assert.IsTrue(Async.UsingSynchronousExecution);
 1250            int threadId = Thread.CurrentThread.ManagedThreadId;
 1251            for (int count = 0; count < 3; ++count)
 252            {
 1253                Async.RunTaskSync(() => Loop2(mainThreadId, Thread.CurrentThread.ManagedThreadId));
 1254                threadId = Thread.CurrentThread.ManagedThreadId;
 1255                Assert.AreEqual(mainThreadId, threadId);
 256            }
 1257            Assert.IsTrue(Async.UsingSynchronousExecution);
 1258            for (int count = 0; count < 3; ++count)
 259            {
 1260                await Async.RunTaskAsync(() => Loop2(mainThreadId, Thread.CurrentThread.ManagedThreadId));
 1261                threadId = Thread.CurrentThread.ManagedThreadId;
 1262                Assert.AreEqual(mainThreadId, threadId);    // RunAsync, unlike a native await, keeps us on the same thr
 263            }
 1264            Assert.IsTrue(Async.UsingSynchronousExecution);
 1265            for (int count = 0; count < 3; ++count)
 266            {
 1267                await Loop2(mainThreadId, Thread.CurrentThread.ManagedThreadId);    // this native await on a non-specia
 1268                threadId = Thread.CurrentThread.ManagedThreadId;
 1269                Assert.IsFalse(Async.UsingSynchronousExecution);
 1270                Assert.AreNotEqual(mainThreadId, threadId);
 271            }
 1272        }
 273        private async Task Loop2(int mainThreadId, int mainThreadId2)
 274        {
 1275            int threadId = Thread.CurrentThread.ManagedThreadId;
 1276            Assert.AreEqual(threadId, mainThreadId2);
 1277            for (int count = 0; count < 3; ++count)
 278            {
 1279                await Async.RunTask(() => Task.Delay(10));
 1280                threadId = Thread.CurrentThread.ManagedThreadId;
 1281                if (Async.UsingSynchronousExecution)
 282                {
 1283                    Assert.AreEqual(mainThreadId, threadId);
 1284                    Assert.AreEqual(mainThreadId2, threadId);
 285                }
 286                else
 287                {
 1288                    Assert.AreNotEqual(mainThreadId, threadId);
 289                    // when we're not using sync execution, although the main thread is unavailable to execute tasks (be
 290                    // main thread 2 *is* available, so we could end up using that here, so we can't check be sure that 
 291                }
 292            }
 1293            for (int count = 0; count < 3; ++count)
 294            {
 1295                await Task.Delay(10);
 1296                threadId = Thread.CurrentThread.ManagedThreadId;
 1297                if (Async.UsingSynchronousExecution)
 298                {
 0299                    Assert.AreEqual(mainThreadId, threadId);
 0300                    Assert.AreEqual(mainThreadId2, threadId);
 301                }
 302                else
 303                {
 1304                    Assert.AreNotEqual(mainThreadId, threadId);
 305                    // when we're not using sync execution, although the main thread is unavailable to execute tasks (be
 306                    // main thread 2 *is* available, so we could end up using that here, so we can't check be sure that 
 307                }
 308            }
 1309        }
 310
 311
 312        /// <summary>
 313        /// Performs basic tests on the <see cref="Async"/> class.
 314        /// </summary>
 315        [TestMethod]
 316        public void Async_SyncInAsyncInSyncWithReturn()
 317        {
 1318            int mainThreadId = Thread.CurrentThread.ManagedThreadId;
 1319            int threadId = Thread.CurrentThread.ManagedThreadId;
 1320            for (int count = 0; count < 3; ++count)
 321            {
 1322                int result = Async.RunTaskSync(() => LoopWithReturn1(mainThreadId));
 1323                threadId = Thread.CurrentThread.ManagedThreadId;
 1324                Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 325            }
 1326        }
 327        private async Task<int> LoopWithReturn1(int mainThreadId)
 328        {
 1329            Assert.IsTrue(Async.UsingSynchronousExecution);
 1330            int threadId = Thread.CurrentThread.ManagedThreadId;
 1331            for (int count = 0; count < 3; ++count)
 332            {
 1333                int result = Async.RunTaskSync(() => LoopWithReturn2(mainThreadId, Thread.CurrentThread.ManagedThreadId)
 1334                threadId = Thread.CurrentThread.ManagedThreadId;
 1335                Assert.AreEqual(mainThreadId, threadId);
 336            }
 1337            Assert.IsTrue(Async.UsingSynchronousExecution);
 1338            for (int count = 0; count < 3; ++count)
 339            {
 1340                int result = await Async.RunTaskAsync(() => LoopWithReturn2(mainThreadId, Thread.CurrentThread.ManagedTh
 1341                threadId = Thread.CurrentThread.ManagedThreadId;
 1342                Assert.AreEqual(mainThreadId, threadId);    // RunAsync, unlike a native await, keeps us on the same thr
 343            }
 1344            Assert.IsTrue(Async.UsingSynchronousExecution);
 1345            for (int count = 0; count < 3; ++count)
 346            {
 1347                int result = await LoopWithReturn2(mainThreadId, Thread.CurrentThread.ManagedThreadId);    // this nativ
 1348                threadId = Thread.CurrentThread.ManagedThreadId;
 1349                Assert.IsFalse(Async.UsingSynchronousExecution);
 1350                Assert.AreNotEqual(mainThreadId, threadId);
 351            }
 1352            return 0;
 1353        }
 354        private async Task<int> LoopWithReturn2(int mainThreadId, int mainThreadId2)
 355        {
 1356            int threadId = Thread.CurrentThread.ManagedThreadId;
 1357            Assert.AreEqual(threadId, mainThreadId2);
 1358            for (int count = 0; count < 3; ++count)
 359            {
 1360                int result = await Async.RunTask(() => Task.FromResult(0));
 1361                threadId = Thread.CurrentThread.ManagedThreadId;
 1362                if (Async.UsingSynchronousExecution)
 363                {
 1364                    Assert.AreEqual(mainThreadId, threadId);
 1365                    Assert.AreEqual(mainThreadId2, threadId);
 366                }
 367                else
 368                {
 1369                    Assert.AreNotEqual(mainThreadId, threadId);
 370                    // when we're not using sync execution, although the main thread is unavailable to execute tasks (be
 371                    // main thread 2 *is* available, so we could end up using that here, so we can't check be sure that 
 372                }
 373            }
 1374            for (int count = 0; count < 3; ++count)
 375            {
 1376                await Task.Delay(10);
 1377                threadId = Thread.CurrentThread.ManagedThreadId;
 1378                if (Async.UsingSynchronousExecution)
 379                {
 0380                    Assert.AreEqual(mainThreadId, threadId);
 0381                    Assert.AreEqual(mainThreadId2, threadId);
 382                }
 383                else
 384                {
 1385                    Assert.AreNotEqual(mainThreadId, threadId);
 386                    // when we're not using sync execution, although the main thread is unavailable to execute tasks (be
 387                    // main thread 2 *is* available, so we could end up using that here, so we can't check be sure that 
 388                }
 389            }
 1390            return 0;
 1391        }
 392
 393
 394        /// <summary>
 395        /// Performs basic tests on the <see cref="Async"/> class.
 396        /// </summary>
 397        [TestMethod]
 398        public void Async_ValueTaskSyncInAsyncInSyncVoid()
 399        {
 1400            int mainThreadId = Thread.CurrentThread.ManagedThreadId;
 1401            int threadId = Thread.CurrentThread.ManagedThreadId;
 1402            for (int count = 0; count < 3; ++count)
 403            {
 1404                Async.RunSync(() => ValueTaskLoop1(mainThreadId));
 1405                threadId = Thread.CurrentThread.ManagedThreadId;
 1406                Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 407            }
 1408        }
 409        private async ValueTask ValueTaskLoop1(int mainThreadId)
 410        {
 1411            Assert.IsTrue(Async.UsingSynchronousExecution);
 1412            int threadId = Thread.CurrentThread.ManagedThreadId;
 1413            for (int count = 0; count < 3; ++count)
 414            {
 1415                Async.RunSync(() => ValueTaskLoop2(mainThreadId, Thread.CurrentThread.ManagedThreadId));
 1416                threadId = Thread.CurrentThread.ManagedThreadId;
 1417                Assert.AreEqual(mainThreadId, threadId);
 418            }
 1419            Assert.IsTrue(Async.UsingSynchronousExecution);
 1420            for (int count = 0; count < 3; ++count)
 421            {
 1422                await Async.RunAsync(() => ValueTaskLoop2(mainThreadId, Thread.CurrentThread.ManagedThreadId));
 1423                threadId = Thread.CurrentThread.ManagedThreadId;
 1424                Assert.AreEqual(mainThreadId, threadId);    // RunAsync, unlike a native await, keeps us on the same thr
 425            }
 1426            Assert.IsTrue(Async.UsingSynchronousExecution);
 1427            for (int count = 0; count < 3; ++count)
 428            {
 1429                await ValueTaskLoop2(mainThreadId, Thread.CurrentThread.ManagedThreadId);    // this native await on a n
 1430                threadId = Thread.CurrentThread.ManagedThreadId;
 1431                Assert.IsFalse(Async.UsingSynchronousExecution);
 1432                Assert.AreNotEqual(mainThreadId, threadId);
 433            }
 1434        }
 435        private async ValueTask ValueTaskLoop2(int mainThreadId, int mainThreadId2)
 436        {
 1437            int threadId = Thread.CurrentThread.ManagedThreadId;
 1438            Assert.AreEqual(threadId, mainThreadId2);
 1439            for (int count = 0; count < 3; ++count)
 440            {
 1441                await Async.RunTask(() => Task.Delay(10));
 1442                threadId = Thread.CurrentThread.ManagedThreadId;
 1443                if (Async.UsingSynchronousExecution)
 444                {
 1445                    Assert.AreEqual(mainThreadId, threadId);
 1446                    Assert.AreEqual(mainThreadId2, threadId);
 447                }
 448                else
 449                {
 1450                    Assert.AreNotEqual(mainThreadId, threadId);
 451                    // when we're not using sync execution, although the main thread is unavailable to execute tasks (be
 452                    // main thread 2 *is* available, so we could end up using that here, so we can't check be sure that 
 453                }
 454            }
 1455            for (int count = 0; count < 3; ++count)
 456            {
 1457                await Task.Delay(10);
 1458                threadId = Thread.CurrentThread.ManagedThreadId;
 1459                if (Async.UsingSynchronousExecution)
 460                {
 0461                    Assert.AreEqual(mainThreadId, threadId);
 0462                    Assert.AreEqual(mainThreadId2, threadId);
 463                }
 464                else
 465                {
 1466                    Assert.AreNotEqual(mainThreadId, threadId);
 467                    // when we're not using sync execution, although the main thread is unavailable to execute tasks (be
 468                    // main thread 2 *is* available, so we could end up using that here, so we can't check be sure that 
 469                }
 470            }
 1471        }
 472
 473
 474        /// <summary>
 475        /// Performs basic tests on the <see cref="Async"/> class.
 476        /// </summary>
 477        [TestMethod]
 478        public void Async_ValueTaskSyncInAsyncInSyncWithReturn()
 479        {
 1480            int mainThreadId = Thread.CurrentThread.ManagedThreadId;
 1481            int threadId = Thread.CurrentThread.ManagedThreadId;
 1482            for (int count = 0; count < 3; ++count)
 483            {
 1484                int result = Async.RunSync(() => ValueTaskLoopWithReturn1(mainThreadId));
 1485                threadId = Thread.CurrentThread.ManagedThreadId;
 1486                Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 487            }
 1488        }
 489        private async ValueTask<int> ValueTaskLoopWithReturn1(int mainThreadId)
 490        {
 1491            Assert.IsTrue(Async.UsingSynchronousExecution);
 1492            int threadId = Thread.CurrentThread.ManagedThreadId;
 1493            for (int count = 0; count < 3; ++count)
 494            {
 1495                int result = Async.RunSync(() => ValueTaskLoopWithReturn2(mainThreadId, Thread.CurrentThread.ManagedThre
 1496                threadId = Thread.CurrentThread.ManagedThreadId;
 1497                Assert.AreEqual(mainThreadId, threadId);
 498            }
 1499            Assert.IsTrue(Async.UsingSynchronousExecution);
 1500            for (int count = 0; count < 3; ++count)
 501            {
 1502                int result = await Async.RunAsync(() => ValueTaskLoopWithReturn2(mainThreadId, Thread.CurrentThread.Mana
 1503                threadId = Thread.CurrentThread.ManagedThreadId;
 1504                Assert.AreEqual(mainThreadId, threadId);    // RunAsync, unlike a native await, keeps us on the same thr
 505            }
 1506            Assert.IsTrue(Async.UsingSynchronousExecution);
 1507            for (int count = 0; count < 3; ++count)
 508            {
 1509                int result = await ValueTaskLoopWithReturn2(mainThreadId, Thread.CurrentThread.ManagedThreadId);    // t
 1510                threadId = Thread.CurrentThread.ManagedThreadId;
 1511                Assert.IsFalse(Async.UsingSynchronousExecution);
 1512                Assert.AreNotEqual(mainThreadId, threadId);
 513            }
 1514            return 0;
 1515        }
 516        private async ValueTask<int> ValueTaskLoopWithReturn2(int mainThreadId, int mainThreadId2)
 517        {
 1518            int threadId = Thread.CurrentThread.ManagedThreadId;
 1519            Assert.AreEqual(threadId, mainThreadId2);
 1520            for (int count = 0; count < 3; ++count)
 521            {
 1522                int result = await Async.Run(() => new ValueTask<int>(0));
 1523                threadId = Thread.CurrentThread.ManagedThreadId;
 1524                if (Async.UsingSynchronousExecution)
 525                {
 1526                    Assert.AreEqual(mainThreadId, threadId);
 1527                    Assert.AreEqual(mainThreadId2, threadId);
 528                }
 529                else
 530                {
 1531                    Assert.AreNotEqual(mainThreadId, threadId);
 532                    // when we're not using sync execution, although the main thread is unavailable to execute tasks (be
 533                    // main thread 2 *is* available, so we could end up using that here, so we can't check to be sure th
 534                }
 535            }
 1536            for (int count = 0; count < 3; ++count)
 537            {
 1538                await Async.Run(() => default);
 1539                threadId = Thread.CurrentThread.ManagedThreadId;
 1540                if (Async.UsingSynchronousExecution)
 541                {
 1542                    Assert.AreEqual(mainThreadId, threadId);
 1543                    Assert.AreEqual(mainThreadId2, threadId);
 544                }
 545                else
 546                {
 1547                    Assert.AreNotEqual(mainThreadId, threadId);
 548                    // when we're not using sync execution, although the main thread is unavailable to execute tasks (be
 549                    // main thread 2 *is* available, so we could end up using that here, so we can't check to be sure th
 550                }
 551            }
 1552            for (int count = 0; count < 3; ++count)
 553            {
 1554                await Task.Delay(10);
 1555                threadId = Thread.CurrentThread.ManagedThreadId;
 1556                if (Async.UsingSynchronousExecution)
 557                {
 0558                    Assert.AreEqual(mainThreadId, threadId);
 0559                    Assert.AreEqual(mainThreadId2, threadId);
 560                }
 561                else
 562                {
 1563                    Assert.AreNotEqual(mainThreadId, threadId);
 564                    // when we're not using sync execution, although the main thread is unavailable to execute tasks (be
 565                    // main thread 2 *is* available, so we could end up using that here, so we can't check to be sure th
 566                }
 567            }
 1568            return 0;
 1569        }
 570        /// <summary>
 571        /// Performs basic tests on the <see cref="Async"/> class.
 572        /// </summary>
 573        [TestMethod]
 574        public void Sync_Enumerator()
 575        {
 1576            int count = 0;
 1577            foreach (int ret in 1.ToSingleItemEnumerable())
 578            {
 1579                Assert.AreEqual(1, ++count);
 1580                Assert.AreEqual(1, ret);
 581            }
 1582        }
 583#if NETSTANDARD2_1 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
 584        /// <summary>
 585        /// Performs basic tests on the <see cref="Async"/> class.
 586        /// </summary>
 587        [TestMethod]
 588        public void Synchronized_AsyncEnumerator()
 589        {
 1590            int mainThreadId = Thread.CurrentThread.ManagedThreadId;
 1591            int threadId = Thread.CurrentThread.ManagedThreadId;
 1592            foreach (int ret in Async.AsyncEnumerableToEnumerable(() => EnumerateAsync(10, default)))
 593            {
 1594                Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 595            }
 1596        }
 597        /// <summary>
 598        /// Performs basic tests on the <see cref="Async"/> class.
 599        /// </summary>
 600        [TestMethod]
 601        public void Sync_AsyncEnumerator()
 602        {
 1603            int mainThreadId = Thread.CurrentThread.ManagedThreadId;
 1604            int threadId = Thread.CurrentThread.ManagedThreadId;
 1605            Async.RunTaskSync(async () =>
 1606            {
 1607                await foreach (int ret in EnumerateAsync(10, default))
 1608                {
 1609                    Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 1610                }
 1611            });
 1612            Async.RunSync(() => Async.AwaitForEach(EnumerateAsync(10, default), t =>
 1613            {
 1614                Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 1615            }, default));
 1616            Async.RunSync(() => Async.AwaitForEach(EnumerateAsync(10, default), (t, c) =>
 1617            {
 1618                Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 1619                return default;
 1620            }, default));
 1621            Async.RunTaskSync(async () =>
 1622            {
 1623                foreach (int ret in await EnumerateAsync(10, default).GetAsyncEnumerator().ToListAsync())
 1624                {
 1625                    Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 1626                }
 1627            });
 1628            Async.RunTaskSync(async () =>
 1629            {
 1630                foreach (int ret in await EnumerateAsync(10, default).GetAsyncEnumerator().ToArrayAsync())
 1631                {
 1632                    Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 1633                }
 1634            });
 1635            Async.RunTaskSync(async () =>
 1636            {
 1637                foreach (int ret in await EnumerateAsync(10, default).GetAsyncEnumerator().ToEnumerableAsync())
 1638                {
 1639                    Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 1640                }
 1641            });
 1642            Async.RunTaskSync(async () =>
 1643            {
 1644                await foreach (int ret in new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }.ToAsyncEnumerable())
 1645                {
 1646                    Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 1647                }
 1648            });
 1649            Async.RunTaskSync(async () =>
 1650            {
 1651                await foreach (int ret in ((IEnumerable<int>)new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }).GetEnumerator(
 1652                {
 1653                    Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 1654                }
 1655            });
 1656            Async.RunTaskSync(async () =>
 1657            {
 1658                await foreach (int ret in 1.ToSingleItemAsyncEnumerable())
 1659                {
 1660                    Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 1661                }
 1662            });
 1663            Async.RunTaskSync(async () =>
 1664            {
 1665                await foreach (int ret in Array.Empty<int>().ToAsyncEnumerable())
 1666                {
 0667                    Assert.Fail("There should be no entries!");
 1668                }
 1669            });
 1670            Async.RunTaskSync(async () =>
 1671            {
 1672                await foreach (int ret in ((IEnumerable<int>)Array.Empty<int>()).GetEnumerator().ToAsyncEnumerable())
 1673                {
 0674                    Assert.Fail("There should be no entries!");
 1675                }
 1676            });
 1677            foreach (int ret in Async.AsyncEnumerableToEnumerable(() => EnumerateAsync(10, default)))
 678            {
 1679                Assert.AreEqual(mainThreadId, Thread.CurrentThread.ManagedThreadId);
 680            }
 1681        }
 682        /// <summary>
 683        /// Performs basic tests on the <see cref="Async"/> class.
 684        /// </summary>
 685        [TestMethod]
 686        public async Task Async_AsyncEnumerator()
 687        {
 1688            int mainThreadId = Thread.CurrentThread.ManagedThreadId;
 1689            int threadId = Thread.CurrentThread.ManagedThreadId;
 1690            int limit = 10;
 1691            int max = 0;
 1692            await foreach (int ret in EnumerateAsync(10, default))
 693            {
 1694                max = Math.Max(max, ret);
 695            }
 1696            Assert.AreEqual(limit - 1, max);
 1697            max = 0;
 1698            await Async.Run(() => Async.AwaitForEach(EnumerateAsync(limit, default), ret =>
 1699            {
 1700                max = Math.Max(max, ret);
 1701            }, default));
 1702            Assert.AreEqual(limit - 1, max);
 1703            max = 0;
 1704            await Async.Run(() => Async.AwaitForEach(EnumerateAsync(limit, default), (ret, c) =>
 1705            {
 1706                max = Math.Max(max, ret);
 1707                return default;
 1708            }, default));
 1709            Assert.AreEqual(limit - 1, max);
 1710            max = 0;
 1711            max = 0;
 1712            foreach (int ret in await EnumerateAsync(limit, default).GetAsyncEnumerator().ToListAsync())
 713            {
 1714                max = Math.Max(max, ret);
 715            }
 1716            Assert.AreEqual(limit - 1, max);
 1717            max = 0;
 1718            foreach (int ret in await EnumerateAsync(limit, default).GetAsyncEnumerator().ToArrayAsync())
 719            {
 1720                max = Math.Max(max, ret);
 721            }
 1722            Assert.AreEqual(limit - 1, max);
 1723            max = 0;
 1724            foreach (int ret in await EnumerateAsync(limit, default).GetAsyncEnumerator().ToEnumerableAsync())
 725            {
 1726                max = Math.Max(max, ret);
 727            }
 1728            Assert.AreEqual(limit - 1, max);
 1729            max = 0;
 1730            foreach (int ret in Async.AsyncEnumerableToEnumerable(() => EnumerateAsync(limit, default)))
 731            {
 1732                max = Math.Max(max, ret);
 733            }
 1734            Assert.AreEqual(limit - 1, max);
 1735        }
 736        private async IAsyncEnumerable<int> EnumerateAsync(int limit, [EnumeratorCancellation] CancellationToken cancel 
 737        {
 1738            for (int ret = 0; ret < limit; ++ret)
 739            {
 1740                cancel.ThrowIfCancellationRequested();
 1741                await Async.RunTask(() => Task.Delay(10));
 1742                yield return ret;
 743            }
 1744        }
 745
 746        /// <summary>
 747        /// Performs basic tests on the <see cref="Async"/> class.
 748        /// </summary>
 749        [TestMethod]
 750        public async Task Async_AsyncEnumeratorExceptions()
 751        {
 1752            int mainThreadId = Thread.CurrentThread.ManagedThreadId;
 1753            await Assert.ThrowsExactlyAsync<ArgumentNullException>(async () =>
 1754            {
 1755                await foreach (int ret in ((int[])null!).ToAsyncEnumerable())
 1756                {
 0757                    Assert.Fail("Should be empty!");
 1758                }
 1759            });
 1760            await Assert.ThrowsExactlyAsync<ArgumentNullException>(async () =>
 1761            {
 1762                await foreach (int ret in ((IEnumerator<int>)null!).ToAsyncEnumerable())
 1763                {
 0764                    Assert.Fail("Should be empty!");
 1765                }
 1766            });
 0767        }
 768        private IAsyncEnumerable<int> NullAsyncEnumerable()
 769        {
 0770            return null!;
 771        }
 772        /// <summary>
 773        /// Performs basic tests on the <see cref="Async"/> class.
 774        /// </summary>
 775        [TestMethod]
 776        public void Async_InfiniteEnumeratorAsyncToSync()
 777        {
 1778            foreach (int ret in Async.AsyncEnumerableToEnumerable(() => InfiniteEnumerateAsync(default)))
 779            {
 1780                if (ret >= 10) break;
 781            }
 1782        }
 783        private async IAsyncEnumerable<int> InfiniteEnumerateAsync([EnumeratorCancellation] CancellationToken cancel = d
 784        {
 1785            int ret = 0;
 786            while (true)
 787            {
 1788                await Async.RunTask(() => Task.Delay(10));
 1789                yield return ++ret;
 790            }
 1791        }
 792#endif
 793        [TestMethod]
 794        public void SynchronousSynchronizationContextExceptions()
 795        {
 1796            SynchronousSynchronizationContext c = SynchronousSynchronizationContext.Default;
 1797            Assert.ThrowsExactly<ArgumentNullException>(() => c.Send(null!, null));
 1798            Assert.ThrowsExactly<ArgumentNullException>(() => c.Post(null!, null));
 1799        }
 800        [TestMethod]
 801        public void Async_ArgumentNullExceptions()
 802        {
 1803            Assert.ThrowsExactly<ArgumentNullException>(() => Async.ConvertAggregateException(null!));
 1804            Assert.ThrowsExactly<ArgumentNullException>(() =>
 1805            {
 1806                foreach (var x in Async.AsyncEnumerableToEnumerable<IAsyncEnumerable<int>>(null!))
 1807                {
 1808                }
 0809            });
 1810        }
 811#if NETSTANDARD2_1 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER
 812        [TestMethod]
 813        public async Task Async_ArgumentNullExceptionsAsync()
 814        {
 1815            await Assert.ThrowsExactlyAsync<ArgumentNullException>(async () => await Async.AwaitForEach<int>(null!, n =>
 1816            await Assert.ThrowsExactlyAsync<ArgumentNullException>(async () => await Async.AwaitForEach<int>(1.ToSingleI
 1817            await Assert.ThrowsExactlyAsync<ArgumentNullException>(async () => await Async.AwaitForEach<int>(null!, (i, 
 1818            await Assert.ThrowsExactlyAsync<ArgumentNullException>(async () => await Async.AwaitForEach<int>(1.ToSingleI
 1819        }
 820#endif
 821        [TestMethod]
 822        public void FilterAsyncFromStackTrace()
 823        {
 824            FilteredStackTrace trace;
 1825            Async.RunTaskSync(async () =>
 1826            {
 1827                string? projectPath = AssemblyUtilities.GetCallingCodeSourceFolder(1, 1)?.TrimEnd(System.IO.Path.Directo
 1828                FilteredStackTrace.AddSourcePathToErase(projectPath ?? "Z:\\");
 1829                FilteredStackTrace.AddNamespaceToFilter("Async.Synchronize");
 1830                trace = new FilteredStackTrace(new ExpectedException("This is a test"), 0, true);
 1831                Assert.IsTrue(string.IsNullOrEmpty(trace.ToString().Trim()));
 1832                await Task.CompletedTask;
 1833            });
 1834        }
 835        [TestMethod]
 836        public async Task ArgumentNullExceptions()
 837        {
 1838            await Assert.ThrowsExactlyAsync<ArgumentNullException>(() => Async.RunTask(null!));
 1839            await Assert.ThrowsExactlyAsync<ArgumentNullException>(() => Async.RunTask<int>(null!));
 1840            await Assert.ThrowsExactlyAsync<ArgumentNullException>(() => Async.Run(null!).AsTask());
 1841            await Assert.ThrowsExactlyAsync<ArgumentNullException>(() => Async.Run<int>(null!).AsTask());
 1842        }
 843    }
 844}

Methods/Properties

Async_Basic()
Async_AlreadyRun()
Async_NotAlreadyRun()
Async_AggregateExceptionUnwrap()
Async_AggregateExceptionUnwrapWithTask()
<Async_AggregateExceptionUnwrapWithTask()
Async_AggregateExceptionUnwrapWithReturn()
<Async_AggregateExceptionUnwrapWithReturn()
Async_AggregateExceptionCantUnwrap()
Async_AggregateExceptionCantUnwrapWithTask()
<Async_AggregateExceptionCantUnwrapWithTask()
Async_AggregateExceptionCantUnwrapWithReturn()
<Async_AggregateExceptionCantUnwrapWithReturn()
Async_SynchronizeVariations()
Async_Misc()
Async_BasicAsyncThrow(System.Exception)
Async_BasicAsync()
Async_BasicAsyncPart1()
Async_BasicAsyncPart2()
Async_BasicAsyncPart3()
Async_BasicAsyncPart4()
Async_BasicAsyncWithLock()
Async_Enumerable()
TestAsyncEnum()
Async_Synchronize()
AsyncTest()
Async_SyncInAsyncInSyncVoid()
Loop1()
Loop2()
Async_SyncInAsyncInSyncWithReturn()
LoopWithReturn1()
LoopWithReturn2()
Async_ValueTaskSyncInAsyncInSyncVoid()
ValueTaskLoop1()
ValueTaskLoop2()
Async_ValueTaskSyncInAsyncInSyncWithReturn()
ValueTaskLoopWithReturn1()
ValueTaskLoopWithReturn2()
Sync_Enumerator()
Synchronized_AsyncEnumerator()
Sync_AsyncEnumerator()
<Sync_AsyncEnumerator()
<Sync_AsyncEnumerator()
<Sync_AsyncEnumerator()
<Sync_AsyncEnumerator()
<Sync_AsyncEnumerator()
<Sync_AsyncEnumerator()
<Sync_AsyncEnumerator()
<Sync_AsyncEnumerator()
<Sync_AsyncEnumerator()
Async_AsyncEnumerator()
EnumerateAsync()
Async_AsyncEnumeratorExceptions()
<Async_AsyncEnumeratorExceptions()
<Async_AsyncEnumeratorExceptions()
NullAsyncEnumerable()
Async_InfiniteEnumeratorAsyncToSync()
InfiniteEnumerateAsync()
SynchronousSynchronizationContextExceptions()
Async_ArgumentNullExceptions()
Async_ArgumentNullExceptionsAsync()
<Async_ArgumentNullExceptionsAsync()
<Async_ArgumentNullExceptionsAsync()
<Async_ArgumentNullExceptionsAsync()
<Async_ArgumentNullExceptionsAsync()
FilterAsyncFromStackTrace()
<FilterAsyncFromStackTrace()
ArgumentNullExceptions()