220 lines
6.4 KiB
C#
220 lines
6.4 KiB
C#
#region License
|
|
|
|
/*
|
|
* Copyright 2002-2004 the original author or authors.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#endregion
|
|
|
|
using System;
|
|
using System.Threading;
|
|
using Spring.Pool;
|
|
using Spring.Threading;
|
|
using NUnit.Framework;
|
|
|
|
|
|
namespace Spring.Threading
|
|
{
|
|
[TestFixture]
|
|
public class SemaphoreTest
|
|
{
|
|
private static long SHORT_DELAY_MS = 300;
|
|
[Test]
|
|
public void UsingLikeAMutex ()
|
|
{
|
|
|
|
Semaphore semaphore = new Semaphore (1);
|
|
Latch latch = new Latch ();
|
|
Helper helper = new Helper (semaphore, latch);
|
|
Thread thread = new Thread (new ThreadStart (helper.Go));
|
|
semaphore.Acquire ();
|
|
thread.Start ();
|
|
latch.Acquire ();
|
|
Assert.IsFalse (helper.gone);
|
|
semaphore.Release ();
|
|
thread.Join ();
|
|
Assert.IsTrue (helper.gone, "not gone");
|
|
|
|
}
|
|
[Test]
|
|
public void AquireInSameThrad()
|
|
{
|
|
Semaphore s = new Semaphore(2);
|
|
Assert.AreEqual(2, s.Permits);
|
|
s.Acquire();
|
|
s.Acquire();
|
|
Assert.AreEqual(0, s.Permits);
|
|
|
|
}
|
|
|
|
[Test]
|
|
public void ReleaseMultipleTimesInSameThread()
|
|
{
|
|
Semaphore s = new Semaphore(2);
|
|
Assert.AreEqual(2, s.Permits);
|
|
s.Acquire();
|
|
s.Acquire();
|
|
s.Release(2);
|
|
Assert.AreEqual(2, s.Permits);
|
|
}
|
|
|
|
[Test]
|
|
public void AttemptWithNegativeMillisInSameThread()
|
|
{
|
|
Semaphore s = new Semaphore(2);
|
|
Assert.AreEqual(2, s.Permits);
|
|
s.Acquire();
|
|
Assert.IsTrue(s.Attempt(-400));
|
|
s.Release(2);
|
|
Assert.AreEqual(2, s.Permits);
|
|
}
|
|
|
|
[Test]
|
|
[ExpectedException(typeof(ArgumentOutOfRangeException))]
|
|
public void ReleaseMultipleBadArgument()
|
|
{
|
|
Semaphore s = new Semaphore(2);
|
|
Assert.AreEqual(2, s.Permits);
|
|
s.Acquire();
|
|
s.Acquire();
|
|
s.Release(-2);
|
|
Assert.AreEqual(2, s.Permits);
|
|
}
|
|
|
|
[Test]
|
|
public void AttemptInSameThread()
|
|
{
|
|
Semaphore s = new Semaphore(1);
|
|
Assert.IsTrue(s.Attempt(SHORT_DELAY_MS));
|
|
s.Release();
|
|
Assert.IsTrue(s.Attempt(SHORT_DELAY_MS));
|
|
s.Release();
|
|
Assert.IsTrue(s.Attempt(SHORT_DELAY_MS));
|
|
s.Release();
|
|
Assert.IsTrue(s.Attempt(SHORT_DELAY_MS));
|
|
s.Release();
|
|
Assert.IsTrue(s.Attempt(SHORT_DELAY_MS));
|
|
s.Release();
|
|
Assert.AreEqual(1, s.Permits);
|
|
|
|
}
|
|
|
|
//TODO tests that interrupt a thread.
|
|
|
|
[Test]
|
|
public void AquireReleaseInSameThread()
|
|
{
|
|
Semaphore s = new Semaphore(1);
|
|
s.Acquire();
|
|
s.Release();
|
|
s.Acquire();
|
|
s.Release();
|
|
s.Acquire();
|
|
s.Release();
|
|
s.Acquire();
|
|
s.Release();
|
|
s.Acquire();
|
|
s.Release();
|
|
s.Acquire();
|
|
s.Release();
|
|
Assert.AreEqual(1, s.Permits);
|
|
}
|
|
|
|
[Test]
|
|
public void AcquireReleaseInDifferentThreads()
|
|
{
|
|
Semaphore s = new Semaphore(0);
|
|
AcquireReleaseWorker worker1 = new AcquireReleaseWorker(s);
|
|
Thread thread1 = new Thread(new ThreadStart(worker1.DoWork));
|
|
|
|
thread1.Start();
|
|
Thread.Sleep(300);
|
|
s.Release();
|
|
s.Release();
|
|
s.Acquire();
|
|
s.Acquire();
|
|
s.Release();
|
|
thread1.Join();
|
|
|
|
}
|
|
|
|
[Test]
|
|
public void AttemptReleaseInDifferentThreads()
|
|
{
|
|
Semaphore s = new Semaphore(0);
|
|
AttemptReleaseWorker worker1 = new AttemptReleaseWorker(s);
|
|
Thread thread1 = new Thread(new ThreadStart(worker1.DoWork));
|
|
|
|
thread1.Start();
|
|
//TODO investigate...
|
|
//Assert.IsTrue(s.Attempt(SHORT_DELAY_MS));
|
|
s.Attempt(SHORT_DELAY_MS);
|
|
s.Release();
|
|
//Assert.IsTrue(s.Attempt(SHORT_DELAY_MS));
|
|
s.Attempt(SHORT_DELAY_MS);
|
|
s.Release();
|
|
s.Release();
|
|
thread1.Join();
|
|
}
|
|
|
|
[Test]
|
|
public void TimetoMillis()
|
|
{
|
|
long millis = Utils.CurrentTimeMillis;
|
|
//hmm should be using UtcNow, the impl in CurrentTimeMillis doesn't use UTC.
|
|
long epochTime = ((DateTime.Now-new DateTime (1970, 1, 1)).Ticks)/TimeSpan.TicksPerMillisecond;
|
|
long delta = epochTime-millis;
|
|
Assert.IsTrue(delta < 500);
|
|
}
|
|
}
|
|
|
|
public class AcquireReleaseWorker
|
|
{
|
|
private Semaphore sem;
|
|
public AcquireReleaseWorker(Semaphore s)
|
|
{
|
|
sem = s;
|
|
}
|
|
|
|
public void DoWork()
|
|
{
|
|
sem.Acquire();
|
|
sem.Release();
|
|
sem.Release();
|
|
sem.Acquire();
|
|
}
|
|
}
|
|
|
|
public class AttemptReleaseWorker
|
|
{
|
|
private Semaphore sem;
|
|
public AttemptReleaseWorker(Semaphore s)
|
|
{
|
|
sem = s;
|
|
}
|
|
|
|
public void DoWork()
|
|
{
|
|
long SHORT_DELAY_MS = 300;
|
|
sem.Release();
|
|
|
|
//TODO can we do Assert.IsTrue here?
|
|
sem.Attempt(SHORT_DELAY_MS);
|
|
sem.Release();
|
|
sem.Attempt(SHORT_DELAY_MS);
|
|
}
|
|
}
|
|
|
|
}
|