3c1f479b9d
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
310 lines
7.2 KiB
C#
310 lines
7.2 KiB
C#
// ManualResetEventSlimTests.cs
|
|
//
|
|
// Authors:
|
|
// Marek Safar (marek.safar@gmail.com)
|
|
// Jeremie Laval (jeremie.laval@gmail.com)
|
|
//
|
|
// Copyright (c) 2008 Jérémie "Garuma" Laval
|
|
// Copyright (c) 2012 Xamarin, Inc (http://www.xamarin.com)
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
//
|
|
//
|
|
|
|
#if NET_4_0
|
|
|
|
using System;
|
|
using System.Threading;
|
|
|
|
using NUnit.Framework;
|
|
|
|
using MonoTests.System.Threading.Tasks;
|
|
|
|
namespace MonoTests.System.Threading
|
|
{
|
|
|
|
[TestFixture]
|
|
public class ManualResetEventSlimTests
|
|
{
|
|
ManualResetEventSlim mre;
|
|
|
|
[SetUp]
|
|
public void Setup()
|
|
{
|
|
mre = new ManualResetEventSlim();
|
|
}
|
|
|
|
[Test]
|
|
public void Constructor_Defaults ()
|
|
{
|
|
Assert.IsFalse (mre.IsSet, "#1");
|
|
Assert.AreEqual (10, mre.SpinCount, "#2");
|
|
}
|
|
|
|
[Test]
|
|
public void Constructor_Invalid ()
|
|
{
|
|
try {
|
|
new ManualResetEventSlim (true, -1);
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentException) {
|
|
}
|
|
|
|
try {
|
|
new ManualResetEventSlim (true, 2048);
|
|
Assert.Fail ("#2");
|
|
} catch (ArgumentException) {
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void IsSetTestCase()
|
|
{
|
|
Assert.IsFalse(mre.IsSet, "#1");
|
|
mre.Set();
|
|
Assert.IsTrue(mre.IsSet, "#2");
|
|
mre.Reset();
|
|
Assert.IsFalse(mre.IsSet, "#3");
|
|
}
|
|
|
|
[Test]
|
|
public void WaitTest()
|
|
{
|
|
int count = 0;
|
|
bool s = false;
|
|
|
|
ParallelTestHelper.ParallelStressTest(mre, delegate (ManualResetEventSlim m) {
|
|
if (Interlocked.Increment(ref count) % 2 == 0) {
|
|
Thread.Sleep(50);
|
|
for (int i = 0; i < 10; i++) {
|
|
if (i % 2 == 0)
|
|
m.Reset();
|
|
else
|
|
m.Set();
|
|
}
|
|
} else {
|
|
m.Wait();
|
|
s = true;
|
|
}
|
|
}, 2);
|
|
|
|
Assert.IsTrue(s, "#1");
|
|
Assert.IsTrue(mre.IsSet, "#2");
|
|
}
|
|
|
|
[Test]
|
|
public void Wait_SetConcurrent ()
|
|
{
|
|
for (int i = 0; i < 10000; ++i) {
|
|
var mre = new ManualResetEventSlim ();
|
|
bool b = true;
|
|
|
|
ThreadPool.QueueUserWorkItem (delegate {
|
|
mre.Set ();
|
|
});
|
|
|
|
ThreadPool.QueueUserWorkItem (delegate {
|
|
b &= mre.Wait (1000);
|
|
});
|
|
|
|
Assert.IsTrue (mre.Wait (1000), i.ToString ());
|
|
Assert.IsTrue (b, i.ToString ());
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Wait_DisposeWithCancel ()
|
|
{
|
|
var token = new CancellationTokenSource ();
|
|
ThreadPool.QueueUserWorkItem (delegate {
|
|
Thread.Sleep (10);
|
|
mre.Dispose ();
|
|
token.Cancel ();
|
|
});
|
|
|
|
try {
|
|
mre.Wait (10000, token.Token);
|
|
Assert.Fail ("#0");
|
|
} catch (OperationCanceledException e) {
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Wait_Expired ()
|
|
{
|
|
Assert.IsFalse (mre.Wait (10));
|
|
}
|
|
|
|
[Test, ExpectedException (typeof (ObjectDisposedException))]
|
|
public void WaitAfterDisposeTest ()
|
|
{
|
|
mre.Dispose ();
|
|
mre.Wait ();
|
|
}
|
|
|
|
[Test]
|
|
public void SetAfterDisposeTest ()
|
|
{
|
|
ParallelTestHelper.Repeat (delegate {
|
|
Exception disp = null, setting = null;
|
|
|
|
CountdownEvent evt = new CountdownEvent (2);
|
|
CountdownEvent evtFinish = new CountdownEvent (2);
|
|
|
|
ThreadPool.QueueUserWorkItem (delegate {
|
|
try {
|
|
evt.Signal ();
|
|
evt.Wait (1000);
|
|
mre.Dispose ();
|
|
} catch (Exception e) {
|
|
disp = e;
|
|
}
|
|
evtFinish.Signal ();
|
|
});
|
|
ThreadPool.QueueUserWorkItem (delegate {
|
|
try {
|
|
evt.Signal ();
|
|
evt.Wait (1000);
|
|
mre.Set ();
|
|
} catch (Exception e) {
|
|
setting = e;
|
|
}
|
|
evtFinish.Signal ();
|
|
});
|
|
|
|
bool bb = evtFinish.Wait (1000);
|
|
if (!bb)
|
|
Assert.AreEqual (true, evtFinish.IsSet);
|
|
|
|
Assert.IsTrue (bb, "#0");
|
|
Assert.IsNull (disp, "#1");
|
|
Assert.IsNull (setting, "#2");
|
|
|
|
evt.Dispose ();
|
|
evtFinish.Dispose ();
|
|
});
|
|
}
|
|
|
|
[Test]
|
|
public void WaitHandle_Initialized ()
|
|
{
|
|
var mre = new ManualResetEventSlim (true);
|
|
Assert.IsTrue (mre.WaitHandle.WaitOne (0), "#1");
|
|
mre.Reset ();
|
|
Assert.IsFalse (mre.WaitHandle.WaitOne (0), "#2");
|
|
Assert.AreEqual (mre.WaitHandle, mre.WaitHandle, "#3");
|
|
}
|
|
|
|
[Test]
|
|
public void WaitHandle_NotInitialized ()
|
|
{
|
|
var mre = new ManualResetEventSlim (false);
|
|
Assert.IsFalse (mre.WaitHandle.WaitOne (0), "#1");
|
|
mre.Set ();
|
|
Assert.IsTrue (mre.WaitHandle.WaitOne (0), "#2");
|
|
}
|
|
|
|
[Test]
|
|
public void WaitHandleConsistencyTest ()
|
|
{
|
|
var mre = new ManualResetEventSlim ();
|
|
mre.WaitHandle.WaitOne (0);
|
|
|
|
for (int i = 0; i < 10000; i++) {
|
|
int count = 2;
|
|
SpinWait wait = new SpinWait ();
|
|
|
|
ThreadPool.QueueUserWorkItem (_ => { while (count > 1) wait.SpinOnce (); mre.Set (); Interlocked.Decrement (ref count); });
|
|
ThreadPool.QueueUserWorkItem (_ => { mre.Reset (); Interlocked.Decrement (ref count); });
|
|
|
|
while (count > 0)
|
|
wait.SpinOnce ();
|
|
Assert.AreEqual (mre.IsSet, mre.WaitHandle.WaitOne (0));
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void WaitWithCancellationTokenAndNotImmediateSetTest ()
|
|
{
|
|
var mres = new ManualResetEventSlim ();
|
|
var cts = new CancellationTokenSource ();
|
|
ThreadPool.QueueUserWorkItem(x => { Thread.Sleep (1000); mres.Set (); });
|
|
Assert.IsTrue (mres.Wait (TimeSpan.FromSeconds (10), cts.Token), "Wait returned false despite event was set.");
|
|
}
|
|
|
|
[Test]
|
|
public void WaitWithCancellationTokenAndCancel ()
|
|
{
|
|
var mres = new ManualResetEventSlim ();
|
|
var cts = new CancellationTokenSource ();
|
|
ThreadPool.QueueUserWorkItem(x => { Thread.Sleep (1000); cts.Cancel (); });
|
|
try {
|
|
mres.Wait (TimeSpan.FromSeconds (10), cts.Token);
|
|
Assert.Fail ("Wait did not throw an exception despite cancellation token was cancelled.");
|
|
} catch (OperationCanceledException) {
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void WaitWithCancellationTokenAndTimeout ()
|
|
{
|
|
var mres = new ManualResetEventSlim ();
|
|
var cts = new CancellationTokenSource ();
|
|
Assert.IsFalse (mres.Wait (TimeSpan.FromSeconds (1), cts.Token), "Wait returned true despite timeout.");
|
|
}
|
|
|
|
[Test]
|
|
public void Dispose ()
|
|
{
|
|
var mre = new ManualResetEventSlim (false);
|
|
mre.Dispose ();
|
|
Assert.IsFalse (mre.IsSet, "#0a");
|
|
|
|
try {
|
|
mre.Reset ();
|
|
Assert.Fail ("#1");
|
|
} catch (ObjectDisposedException) {
|
|
}
|
|
|
|
mre.Set ();
|
|
|
|
try {
|
|
mre.Wait (0);
|
|
Assert.Fail ("#3");
|
|
} catch (ObjectDisposedException) {
|
|
}
|
|
|
|
try {
|
|
var v = mre.WaitHandle;
|
|
Assert.Fail ("#4");
|
|
} catch (ObjectDisposedException) {
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Dispose_Double ()
|
|
{
|
|
var mre = new ManualResetEventSlim ();
|
|
mre.Dispose ();
|
|
mre.Dispose ();
|
|
}
|
|
}
|
|
}
|
|
#endif
|