Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
#if SILVERLIGHT && !SILVERLIGHTM7
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Browser;
using Microsoft.Silverlight.Testing;
namespace ReactiveTests
{
public class App : Application
{
public App()
{
this.Startup += (o, e) =>
{
// TODO: Investigate UnitTestSettings configuration of TestService and LogProviders.
// var settings = new UnitTestSettings { StartRunImmediately = true };
RootVisual = UnitTestSystem.CreateTestPage(/* settings */);
};
this.UnhandledException += (o, e) =>
{
if (!Debugger.IsAttached)
{
e.Handled = true;
Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
}
};
}
private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
{
try
{
string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");
HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight Application " + errorMsg + "\");");
}
catch (Exception)
{
}
}
}
}
#endif

View File

@@ -0,0 +1,71 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
#if !NO_WINDOWS_THREADING
using System;
using System.Threading;
using System.Windows.Threading;
namespace ReactiveTests
{
static class DispatcherHelpers
{
public static DispatcherWrapper EnsureDispatcher()
{
#if DESKTOPCLR
var dispatcher = new Thread(Dispatcher.Run);
dispatcher.IsBackground = true;
dispatcher.Start();
while (Dispatcher.FromThread(dispatcher) == null)
Thread.Sleep(10);
var d = Dispatcher.FromThread(dispatcher);
while (d.BeginInvoke(new Action(() => { })).Status == DispatcherOperationStatus.Aborted) ;
return new DispatcherWrapper(d);
#else
return new DispatcherWrapper(System.Windows.Deployment.Current.Dispatcher);
#endif
}
}
class DispatcherWrapper
{
private Dispatcher _dispatcher;
public DispatcherWrapper(Dispatcher dispatcher)
{
_dispatcher = dispatcher;
}
public Dispatcher Dispatcher { get { return _dispatcher; } }
public void InvokeShutdown()
{
#if !USE_SL_DISPATCHER
_dispatcher.InvokeShutdown();
#endif
}
public static implicit operator Dispatcher(DispatcherWrapper wrapper)
{
return wrapper._dispatcher;
}
#if !USE_SL_DISPATCHER
public event DispatcherUnhandledExceptionEventHandler UnhandledException
{
add { _dispatcher.UnhandledException += value; }
remove { _dispatcher.UnhandledException -= value; }
}
#endif
public void BeginInvoke(Action action)
{
_dispatcher.BeginInvoke(action);
}
}
}
#endif

View File

@@ -0,0 +1,16 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
namespace ReactiveTests.Dummies
{
class DummyDisposable : IDisposable
{
public static readonly DummyDisposable Instance = new DummyDisposable();
public void Dispose()
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,45 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
namespace ReactiveTests.Dummies
{
class DummyEnumerable<T> : IEnumerable<T>
{
public static readonly DummyEnumerable<T> Instance = new DummyEnumerable<T>();
private DummyEnumerable()
{
}
public IEnumerator<T> GetEnumerator()
{
throw new NotImplementedException();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
class NullEnumeratorEnumerable<T> : IEnumerable<T>
{
public static readonly NullEnumeratorEnumerable<T> Instance = new NullEnumeratorEnumerable<T>();
private NullEnumeratorEnumerable()
{
}
public IEnumerator<T> GetEnumerator()
{
return null;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View File

@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
namespace ReactiveTests.Dummies
{
static class DummyFunc<T>
{
public static readonly Func<T> Instance = () => { throw new NotImplementedException(); };
}
static class DummyFunc<T, U>
{
public static readonly Func<T, U> Instance = t => { throw new NotImplementedException(); };
}
static class DummyFunc<T, U, V>
{
public static readonly Func<T, U, V> Instance = (t, u) => { throw new NotImplementedException(); };
}
static class DummyFunc<T, U, V, W>
{
public static readonly Func<T, U, V, W> Instance = (t, u, v) => { throw new NotImplementedException(); };
}
static class DummyFunc<T, U, V, W, X>
{
public static readonly Func<T, U, V, W, X> Instance = (t, u, v, w) => { throw new NotImplementedException(); };
}
static class DummyAction
{
public static readonly Action Instance = () => { throw new NotImplementedException(); };
}
static class DummyAction<T>
{
public static readonly Action<T> Instance = t => { throw new NotImplementedException(); };
}
static class DummyAction<T, U>
{
public static readonly Action<T, U> Instance = (t, u) => { throw new NotImplementedException(); };
}
}

View File

@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
namespace ReactiveTests.Dummies
{
class DummyObservable<T> : IObservable<T>
{
public static readonly DummyObservable<T> Instance = new DummyObservable<T>();
DummyObservable()
{
}
public IDisposable Subscribe(IObserver<T> observer)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
namespace ReactiveTests.Dummies
{
class DummyObserver<T> : IObserver<T>
{
public static readonly DummyObserver<T> Instance = new DummyObserver<T>();
DummyObserver()
{
}
public void OnNext(T value)
{
throw new NotImplementedException();
}
public void OnError(Exception exception)
{
throw new NotImplementedException();
}
public void OnCompleted()
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,36 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Reactive.Concurrency;
namespace ReactiveTests.Dummies
{
class DummyScheduler : IScheduler
{
public static readonly DummyScheduler Instance = new DummyScheduler();
DummyScheduler()
{
}
public DateTimeOffset Now
{
get { return DateTimeOffset.MinValue; }
}
public IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)
{
throw new NotImplementedException();
}
public IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)
{
throw new NotImplementedException();
}
public IDisposable Schedule<TState>(TState state, DateTimeOffset dueTime, Func<IScheduler, TState, IDisposable> action)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,39 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using Microsoft.Reactive.Testing;
namespace ReactiveTests
{
public static class Extensions
{
//public static IDisposable ScheduleAbsolute(this TestScheduler scheduler, long time, Action action)
//{
// return scheduler.ScheduleAbsolute(default(object), time, (scheduler1, state1) => { action(); return Disposable.Empty; });
//}
//public static IDisposable ScheduleRelative(this TestScheduler scheduler, long time, Action action)
//{
// return scheduler.ScheduleRelative(default(object), time, (scheduler1, state1) => { action(); return Disposable.Empty; });
//}
public static void EnsureTrampoline(this CurrentThreadScheduler scheduler, Action action)
{
if (scheduler.ScheduleRequired)
scheduler.Schedule(action);
else
action();
}
public static IEnumerable<R> Zip<T1, T2, R>(this IEnumerable<T1> source1, IEnumerable<T2> source2, Func<T1, T2, R> f)
{
using (var e1 = source1.GetEnumerator())
using (var e2 = source2.GetEnumerator())
while (e1.MoveNext() && e2.MoveNext())
yield return f(e1.Current, e2.Current);
}
}
}

View File

@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Reactive.Testing;
namespace ReactiveTests
{
public class MockDisposable : List<long>, IDisposable
{
TestScheduler scheduler;
public MockDisposable(TestScheduler scheduler)
{
if (scheduler == null)
throw new ArgumentNullException("scheduler");
this.scheduler = scheduler;
Add(scheduler.Clock);
}
public void Dispose()
{
Add(scheduler.Clock);
}
}
}

View File

@@ -0,0 +1,97 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Reactive.Concurrency;
using Microsoft.Reactive.Testing;
using System;
namespace ReactiveTests
{
public class MockEnumerable<T> : IEnumerable<T>
{
public readonly TestScheduler Scheduler;
public readonly List<Subscription> Subscriptions = new List<Subscription>();
IEnumerable<T> underlyingEnumerable;
public MockEnumerable(TestScheduler scheduler, IEnumerable<T> underlyingEnumerable)
{
if (scheduler == null)
throw new ArgumentNullException("scheduler");
if (underlyingEnumerable == null)
throw new ArgumentNullException("underlyingEnumerable");
this.Scheduler = scheduler;
this.underlyingEnumerable = underlyingEnumerable;
}
public IEnumerator<T> GetEnumerator()
{
return new MockEnumerator(Scheduler, Subscriptions, underlyingEnumerable.GetEnumerator());
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
class MockEnumerator : IEnumerator<T>
{
List<Subscription> subscriptions;
IEnumerator<T> enumerator;
TestScheduler scheduler;
int index;
bool disposed = false;
public MockEnumerator(TestScheduler scheduler, List<Subscription> subscriptions, IEnumerator<T> enumerator)
{
this.subscriptions = subscriptions;
this.enumerator = enumerator;
this.scheduler = scheduler;
index = subscriptions.Count;
subscriptions.Add(new Subscription(scheduler.Clock));
}
public T Current
{
get
{
if (disposed)
throw new ObjectDisposedException("this");
return enumerator.Current;
}
}
public void Dispose()
{
if (!disposed)
{
disposed = true;
enumerator.Dispose();
subscriptions[index] = new Subscription(subscriptions[index].Subscribe, scheduler.Clock);
}
}
object System.Collections.IEnumerator.Current
{
get { return Current; }
}
public bool MoveNext()
{
if (disposed)
throw new ObjectDisposedException("this");
return enumerator.MoveNext();
}
public void Reset()
{
if (disposed)
throw new ObjectDisposedException("this");
enumerator.Reset();
}
}
}
}

View File

@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Reactive.Disposables;
using System;
namespace ReactiveTests
{
public class NullErrorObservable<T> : IObservable<T>
{
public static NullErrorObservable<T> Instance = new NullErrorObservable<T>();
private NullErrorObservable()
{
}
public IDisposable Subscribe(IObserver<T> observer)
{
if (observer == null)
throw new ArgumentNullException("observer");
observer.OnError(null);
return Disposable.Empty;
}
}
}

View File

@@ -0,0 +1,7 @@
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Deployment.Parts>
</Deployment.Parts>
</Deployment>

View File

@@ -0,0 +1,18 @@
using System;
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Tests.System.Reactive")]
[assembly: AssemblyDescription("Unit tests for Reactive Extensions product assemblies.")]
#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
#else
[assembly: AssemblyConfiguration("Retail")]
#endif
[assembly: AssemblyCompany("Microsoft Open Technologies, Inc.")]
[assembly: AssemblyProduct("Reactive Extensions")]
[assembly: AssemblyCopyright("\x00a9 Microsoft Open Technologies, Inc. All rights reserved.")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: ComVisible(false)]

View File

@@ -0,0 +1,116 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
#if SILVERLIGHT
using System;
namespace System.Threading
{
//Monitor based implementation of Semaphore
//that mimicks the .NET Semaphore class (System.Threading.Semaphore)
internal sealed class Semaphore : IDisposable
{
private int m_currentCount;
private int m_maximumCount;
private object m_lockObject;
private bool m_disposed;
public Semaphore(int initialCount, int maximumCount)
{
if (initialCount < 0)
{
throw new ArgumentOutOfRangeException("initialCount", "Non-negative number required.");
}
if (maximumCount < 1)
{
throw new ArgumentOutOfRangeException("maximumCount", "Positive number required.");
}
if (initialCount > maximumCount)
{
throw new ArgumentException("Initial count must be smaller than maximum");
}
m_currentCount = initialCount;
m_maximumCount = maximumCount;
m_lockObject = new object();
}
public int Release()
{
return this.Release(1);
}
public int Release(int releaseCount)
{
if (releaseCount < 1)
{
throw new ArgumentOutOfRangeException("releaseCount", "Positive number required.");
}
if (m_disposed)
{
throw new ObjectDisposedException("Semaphore");
}
var oldCount = default(int);
lock (m_lockObject)
{
oldCount = m_currentCount;
if (releaseCount + m_currentCount > m_maximumCount)
{
throw new ArgumentOutOfRangeException("releaseCount", "Amount of releases would overflow maximum");
}
m_currentCount += releaseCount;
//PulseAll makes sure all waiting threads get queued for acquiring the lock
//Pulse would only queue one thread.
Monitor.PulseAll(m_lockObject);
}
return oldCount;
}
public bool WaitOne()
{
return WaitOne(Timeout.Infinite);
}
public bool WaitOne(int millisecondsTimeout)
{
if (m_disposed)
{
throw new ObjectDisposedException("Semaphore");
}
lock (m_lockObject)
{
while (m_currentCount == 0)
{
if (!Monitor.Wait(m_lockObject, millisecondsTimeout))
{
return false;
}
}
m_currentCount--;
return true;
}
}
public bool WaitOne(TimeSpan timeout)
{
return WaitOne((int)timeout.TotalMilliseconds);
}
public void Close()
{
Dispose();
}
public void Dispose()
{
//the .NET CLR semaphore does not release waits upon dispose
//so we don't do that either.
m_disposed = true;
m_lockObject = null;
}
}
}
#endif

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,74 @@
// 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.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
#if NUNIT
using NUnit.Framework;
using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
using TestMethodAttribute = NUnit.Framework.TestAttribute;
using TestInitializeAttribute = NUnit.Framework.SetUpAttribute;
#else
using Microsoft.VisualStudio.TestTools.UnitTesting;
#endif
namespace ReactiveTests.Stress.Schedulers
{
/// <summary>
/// Test for <see href="https://rx.codeplex.com/workitem/37">work item #37</see>.
/// </summary>
public static class EventLoop
{
private static readonly FieldInfo semaphore = typeof(EventLoopScheduler).GetField("_evt", BindingFlags.NonPublic | BindingFlags.Instance);
public static void NoSemaphoreFullException()
{
var failed = new TaskCompletionSource<int>();
using (var scheduler = new EventLoopScheduler())
{
Assert.AreEqual(0, scheduler.CurrentCount());
var maxCount = Environment.ProcessorCount;
using (Enumerable.Range(1, maxCount)
.Select(_ => scheduler.SchedulePeriodic(TimeSpan.Zero, () =>
{
var count = scheduler.CurrentCount();
if (count > maxCount)
failed.SetResult(count);
}))
.Aggregate(
new CompositeDisposable(),
(c, d) =>
{
c.Add(d);
return c;
}))
{
if (failed.Task.Wait(TimeSpan.FromSeconds(10)))
{
Assert.Fail("Semaphore count is too high: {0}", failed.Task.Result);
}
}
}
}
private static int CurrentCount(this EventLoopScheduler scheduler)
{
#if !NO_CDS
return ((SemaphoreSlim)semaphore.GetValue(scheduler)).CurrentCount;
#else
return 0;
#endif
}
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More