Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/rx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Rx.NET/Tests.System.Reactive/Stress/Core/Disposables')
-rw-r--r--Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/Composite.cs159
-rw-r--r--Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/RefCount.cs160
-rw-r--r--Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/Serial.cs147
-rw-r--r--Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/SingleAssignment.cs75
4 files changed, 541 insertions, 0 deletions
diff --git a/Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/Composite.cs b/Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/Composite.cs
new file mode 100644
index 0000000..eccb08f
--- /dev/null
+++ b/Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/Composite.cs
@@ -0,0 +1,159 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if STRESS
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Disposables;
+using System.Reflection;
+using System.Threading;
+
+namespace ReactiveTests.Stress.Disposables
+{
+ public class Composite
+ {
+ /// <summary>
+ /// Allocates a CompositeDisposable and performs random Add and Remove operations. Checks that all contained disposables get properly disposed.
+ /// The CompositeDisposable is disposed either at the start, at the end, or at a random time.
+ /// </summary>
+ public static void Potpourri()
+ {
+ Console.Title = MethodInfo.GetCurrentMethod().Name + " - 0% complete";
+
+ for (int i = 1; i <= 100; i++)
+ {
+ for (int j = 0; j < 10; j++)
+ {
+ DisposeBeforeAddRemove();
+ DisposeDuringAddRemove();
+ DisposeDuringAddRemove();
+ DisposeDuringAddRemove();
+ DisposeAfterAddRemove();
+ }
+
+ Console.Title = MethodInfo.GetCurrentMethod().Name + " - " + i + "% complete";
+ }
+ }
+
+ /// <summary>
+ /// Allocates a CompositeDisposable and performs random Add and Remove operations. Checks that all contained disposables get properly disposed.
+ /// The CompositeDisposable is disposed at the start.
+ /// </summary>
+ public static void DisposeBeforeAddRemove()
+ {
+ Impl(0);
+ }
+
+ /// <summary>
+ /// Allocates a CompositeDisposable and performs random Add and Remove operations. Checks that all contained disposables get properly disposed.
+ /// The CompositeDisposable is disposed at a random time.
+ /// </summary>
+ public static void DisposeDuringAddRemove()
+ {
+ Impl(1);
+ }
+
+ /// <summary>
+ /// Allocates a CompositeDisposable and performs random Add and Remove operations. Checks that all contained disposables get properly disposed.
+ /// The CompositeDisposable is disposed at the end.
+ /// </summary>
+ public static void DisposeAfterAddRemove()
+ {
+ Impl(2);
+ }
+
+ static void Impl(int disposeAt)
+ {
+ var rand = new Random();
+
+ var g = new CompositeDisposable();
+
+ Console.Write("Dispose @ = {0} - ", disposeAt);
+
+ if (disposeAt == 0)
+ {
+ g.Dispose();
+ Console.Write("{GD} ");
+ }
+
+ if (disposeAt == 1)
+ {
+ var sleep = rand.Next(0, 5) > 1 /* 60% chance */ ? rand.Next(2, 1000) : 0;
+
+ ThreadPool.QueueUserWorkItem(_ =>
+ {
+ Helpers.SleepOrSpin(sleep);
+ g.Dispose();
+ Console.Write("{GD} ");
+ });
+ }
+
+ var n = rand.Next(0, 1000);
+ var cd = new CountdownEvent(n);
+
+ var ds = Enumerable.Range(0, n).Select(_ => Disposable.Create(() => cd.Signal())).ToArray();
+
+ var m = rand.Next(1, 100);
+ var jobs = ds.GroupBy(_ => rand.Next() % m).Select(Enumerable.ToList).ToList();
+
+ Console.Write("N = {0}, M = {1} - ", n, m);
+
+ var done = new CountdownEvent(jobs.Count);
+
+ foreach (var job in jobs)
+ {
+ var sleep = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0;
+ var sleepAt = Enumerable.Range(0, rand.Next(0, job.Count) / rand.Next(1, 100)).ToArray();
+ var sleeps = sleepAt.Select(_ => rand.Next(0, 50)).ToArray();
+
+ var rem = rand.Next(0, 3) == 0; /* 33% chance */
+ var remAt = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0;
+
+ var mine = job;
+ ThreadPool.QueueUserWorkItem(_ =>
+ {
+ Helpers.SleepOrSpin(sleep);
+
+ var j = 0;
+ foreach (var d in mine)
+ {
+ var dd = d;
+
+ if (sleepAt.Contains(j))
+ Helpers.SleepOrSpin(sleeps[j]);
+
+ g.Add(dd);
+ Console.Write("+");
+
+ if (rem)
+ {
+ ThreadPool.QueueUserWorkItem(__ =>
+ {
+ Helpers.SleepOrSpin(remAt);
+ g.Remove(dd);
+ Console.Write("-");
+ });
+ }
+
+ j++;
+ }
+
+ done.Signal();
+ });
+ }
+
+ done.Wait();
+
+ if (disposeAt == 2)
+ {
+ g.Dispose();
+ Console.Write("{GD} ");
+ }
+
+ cd.Wait();
+
+ Console.WriteLine(".");
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/RefCount.cs b/Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/RefCount.cs
new file mode 100644
index 0000000..f2364a8
--- /dev/null
+++ b/Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/RefCount.cs
@@ -0,0 +1,160 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if STRESS
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reactive.Disposables;
+using System.Reflection;
+using System.Threading;
+
+namespace ReactiveTests.Stress.Disposables
+{
+ public class RefCount
+ {
+ /// <summary>
+ /// Disposes the primary disposable first, allocates a number of dependents on different threads, and disposes them on different threads.
+ /// Ref count should reach zero, and the inner disposable should be called.
+ /// </summary>
+ public static void PrimaryFirst_DependentsTrigger()
+ {
+ Console.Title = MethodInfo.GetCurrentMethod().Name + " - 0% complete";
+
+ var rnd = new Random();
+
+ for (int i = 1; i <= 100; i++)
+ {
+ Impl(true, false, new[] { 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 });
+ Impl(true, false, new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
+ Impl(true, false, Enumerable.Range(0, 10).Select(_ => rnd.Next(0, 1000)));
+
+ Console.Title = MethodInfo.GetCurrentMethod().Name + " - " + i + "% complete";
+ }
+ }
+
+ /// <summary>
+ /// Allocates a number of dependents on different threads, disposes them on different threads, and disposes the primary disposable last.
+ /// Ref count should reach zero, and the inner disposable should be called.
+ /// </summary>
+ public static void DependentsFirst_PrimaryTrigger()
+ {
+ Console.Title = MethodInfo.GetCurrentMethod().Name + " - 0% complete";
+
+ var rnd = new Random();
+
+ for (int i = 1; i <= 100; i++)
+ {
+ Impl(false, false, new[] { 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 });
+ Impl(false, false, new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
+ Impl(false, false, Enumerable.Range(0, 10).Select(_ => rnd.Next(0, 1000)));
+
+ Console.Title = MethodInfo.GetCurrentMethod().Name + " - " + i + "% complete";
+ }
+ }
+
+ /// <summary>
+ /// Allocates a number of dependents on different threads, disposes them on different threads, and disposes the primary disposable at a random time.
+ /// Ref count should reach zero, and the inner disposable should be called.
+ /// </summary>
+ public static void DependentsFirst_PrimaryRandom()
+ {
+ Console.Title = MethodInfo.GetCurrentMethod().Name + " - 0% complete";
+
+ var rnd = new Random();
+
+ for (int i = 1; i <= 100; i++)
+ {
+ Impl(false, true, new[] { 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 });
+ Impl(false, true, new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
+ Impl(false, true, Enumerable.Range(0, 10).Select(_ => rnd.Next(0, 1000)));
+
+ Console.Title = MethodInfo.GetCurrentMethod().Name + " - " + i + "% complete";
+ }
+ }
+
+ private static void Impl(bool primaryFirst, bool primaryRandom, IEnumerable<int> nDependents)
+ {
+ var rand = new Random();
+
+ foreach (var n in nDependents)
+ {
+ var e = new ManualResetEvent(false);
+ var hasDependent = new ManualResetEvent(false);
+ var r = new RefCountDisposable(Disposable.Create(() => { e.Set(); }));
+
+ var d = default(IDisposable);
+ if (primaryFirst)
+ {
+ d = r.GetDisposable();
+ r.Dispose();
+ }
+ else if (primaryRandom)
+ {
+ var sleep = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0;
+
+ ThreadPool.QueueUserWorkItem(_ =>
+ {
+ hasDependent.WaitOne();
+ Helpers.SleepOrSpin(sleep);
+ r.Dispose();
+ });
+
+ if (n == 0)
+ hasDependent.Set();
+ }
+
+ Console.Write(n + " - ");
+
+ var cd = new CountdownEvent(n * 2);
+ for (int i = 0; i < n; i++)
+ {
+ var j = i;
+
+ var sleep1 = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0;
+ var sleep2 = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0;
+ var sleep3 = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0;
+
+ ThreadPool.QueueUserWorkItem(_ =>
+ {
+ Helpers.SleepOrSpin(sleep1);
+
+ Console.Write("+");
+
+ var f = r.GetDisposable();
+
+ if (j == 0)
+ hasDependent.Set();
+
+ Helpers.SleepOrSpin(sleep2);
+
+ ThreadPool.QueueUserWorkItem(__ =>
+ {
+ Helpers.SleepOrSpin(sleep3);
+
+ f.Dispose();
+
+ Console.Write("-");
+
+ cd.Signal();
+ });
+
+ cd.Signal();
+ });
+ }
+
+ cd.Wait();
+
+ if (primaryFirst)
+ d.Dispose();
+ else if (!primaryRandom)
+ r.Dispose();
+
+ e.WaitOne();
+
+ Console.WriteLine(".");
+ }
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/Serial.cs b/Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/Serial.cs
new file mode 100644
index 0000000..a9b87d1
--- /dev/null
+++ b/Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/Serial.cs
@@ -0,0 +1,147 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if STRESS
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Disposables;
+using System.Reflection;
+using System.Threading;
+
+namespace ReactiveTests.Stress.Disposables
+{
+ public class Serial
+ {
+ /// <summary>
+ /// Allocates a SerialDisposable and performs random assignment operations. Checks that all contained disposables get properly disposed.
+ /// The SerialDisposable is disposed either at the start, at the end, or at a random time.
+ /// </summary>
+ public static void RandomAssignAndDispose()
+ {
+ Console.Title = MethodInfo.GetCurrentMethod().Name + " - 0% complete";
+
+ for (int i = 1; i <= 100; i++)
+ {
+ for (int j = 0; j < 10; j++)
+ {
+ DisposeBeforeAssign();
+ DisposeDuringAssign();
+ DisposeDuringAssign();
+ DisposeDuringAssign();
+ DisposeAfterAssign();
+ }
+
+ Console.Title = MethodInfo.GetCurrentMethod().Name + " - " + i + "% complete";
+ }
+ }
+
+ /// <summary>
+ /// Allocates a SerialDisposable and performs random assignment operations. Checks that all contained disposables get properly disposed.
+ /// The SerialDisposable is disposed at the start.
+ /// </summary>
+ public static void DisposeBeforeAssign()
+ {
+ Impl(0);
+ }
+
+ /// <summary>
+ /// Allocates a SerialDisposable and performs random assignment operations. Checks that all contained disposables get properly disposed.
+ /// The SerialDisposable is disposed at a random time.
+ /// </summary>
+ public static void DisposeDuringAssign()
+ {
+ Impl(1);
+ }
+
+ /// <summary>
+ /// Allocates a SerialDisposable and performs random assignment operations. Checks that all contained disposables get properly disposed.
+ /// The SerialDisposable is disposed at the end.
+ /// </summary>
+ public static void DisposeAfterAssign()
+ {
+ Impl(2);
+ }
+
+ static void Impl(int disposeAt)
+ {
+ var rand = new Random();
+
+ var s = new SerialDisposable();
+
+ Console.Write("Dispose @ = {0} - ", disposeAt);
+
+ if (disposeAt == 0)
+ {
+ s.Dispose();
+ Console.Write("{SD} ");
+ }
+
+ if (disposeAt == 1)
+ {
+ var sleep = rand.Next(0, 5) > 1 /* 60% chance */ ? rand.Next(2, 1000) : 0;
+
+ ThreadPool.QueueUserWorkItem(_ =>
+ {
+ Helpers.SleepOrSpin(sleep);
+ s.Dispose();
+ Console.Write("{SD} ");
+ });
+ }
+
+ var n = rand.Next(0, 1000);
+ var cd = new CountdownEvent(n);
+
+ var ds = Enumerable.Range(0, n).Select(_ => Disposable.Create(() => cd.Signal())).ToArray();
+
+ var m = rand.Next(1, 100);
+ var jobs = ds.GroupBy(_ => rand.Next() % m).Select(Enumerable.ToList).ToList();
+
+ Console.Write("N = {0}, M = {1} - ", n, m);
+
+ var done = new CountdownEvent(jobs.Count);
+
+ foreach (var job in jobs)
+ {
+ var sleep = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0;
+ var sleepAt = Enumerable.Range(0, rand.Next(0, job.Count) / rand.Next(1, 100)).ToArray();
+ var sleeps = sleepAt.Select(_ => rand.Next(0, 50)).ToArray();
+
+ var rem = rand.Next(0, 3) == 0; /* 33% chance */
+ var remAt = rand.Next(0, 10) == 0 /* 10% chance */ ? rand.Next(2, 100) : 0;
+
+ var mine = job;
+ ThreadPool.QueueUserWorkItem(_ =>
+ {
+ Helpers.SleepOrSpin(sleep);
+
+ var j = 0;
+ foreach (var d in mine)
+ {
+ if (sleepAt.Contains(j))
+ Helpers.SleepOrSpin(sleeps[j]);
+
+ s.Disposable = d;
+ Console.Write("+");
+
+ j++;
+ }
+
+ done.Signal();
+ });
+ }
+
+ done.Wait();
+
+ if (disposeAt == 2)
+ {
+ s.Dispose();
+ Console.Write("{SD} ");
+ }
+
+ cd.Wait();
+
+ Console.WriteLine(".");
+ }
+ }
+}
+#endif \ No newline at end of file
diff --git a/Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/SingleAssignment.cs b/Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/SingleAssignment.cs
new file mode 100644
index 0000000..b558a98
--- /dev/null
+++ b/Rx.NET/Tests.System.Reactive/Stress/Core/Disposables/SingleAssignment.cs
@@ -0,0 +1,75 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if STRESS
+using System;
+using System.Reactive.Disposables;
+using System.Reflection;
+using System.Threading;
+
+namespace ReactiveTests.Stress.Disposables
+{
+ public class SingleAssignment
+ {
+ /// <summary>
+ /// Allocates a SingleAssignmentDisposable and assigns a disposable object at a random time. Also disposes the container at a random time.
+ /// Expected behavior is to see the assigned disposable getting disposed no matter what.
+ /// </summary>
+ public static void RandomAssignAndDispose()
+ {
+ Console.Title = MethodInfo.GetCurrentMethod().Name + " - 0% complete";
+
+ for (int i = 1; i <= 100; i++)
+ {
+ for (int j = 0; j < 10; j++)
+ {
+ Impl();
+ }
+
+ Console.Title = MethodInfo.GetCurrentMethod().Name + " - " + i + "% complete";
+ }
+ }
+
+ private static void Impl()
+ {
+ var rand = new Random();
+
+ for (int i = 0; i < 1000; i++)
+ {
+ var d = new SingleAssignmentDisposable();
+ var e = new ManualResetEvent(false);
+ var cd = new CountdownEvent(2);
+
+ var sleep1 = rand.Next(0, 1) == 0 ? 0 : rand.Next(2, 100);
+ var sleep2 = rand.Next(0, 1) == 0 ? 0 : rand.Next(2, 100);
+
+ ThreadPool.QueueUserWorkItem(_ =>
+ {
+ Helpers.SleepOrSpin(sleep1);
+
+ Console.Write("{DB} ");
+ d.Dispose();
+ Console.Write("{DE} ");
+
+ cd.Signal();
+ });
+
+ ThreadPool.QueueUserWorkItem(_ =>
+ {
+ Helpers.SleepOrSpin(sleep2);
+
+ Console.Write("{AB} ");
+ d.Disposable = Disposable.Create(() => e.Set());
+ Console.Write("{AE} ");
+
+ cd.Signal();
+ });
+
+ e.WaitOne();
+ cd.Wait();
+
+ Console.WriteLine(".");
+ }
+ }
+ }
+}
+#endif \ No newline at end of file