//-------------------------------------------------------------------------------
// <copyright file="EventBrokerTest.cs" company="bbv Software Services AG">
// Copyright (c) 2008 bbv Software Services AG
//
// 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.
// </copyright>
//-------------------------------------------------------------------------------
namespace bbv.Common.EventBroker
{
using System;
using System.ComponentModel;
using System.Threading;
using bbv.Common.EventBroker.Exceptions;
using NUnit.Framework;
/// <summary>
/// Test for EventBroker.
/// </summary>
/// <remarks>
/// Note that no tests that require a UI thread can be done. --> no tests on <see cref="ThreadOption.UserInterface"/> and <see cref="ThreadOption.UserInterfaceBackground"/>
/// </remarks>
[TestFixture]
public class EventBrokerTest
{
EventBroker eb;
Publisher p;
Subscriber s;
[SetUp]
public void SetUp()
{
Subscriber.Count = 0;
eb = new EventBroker();
p = new Publisher();
s = new Subscriber();
eb.Register(p);
eb.Register(s);
}
[TearDown]
public void TearDown()
{
if (p != null) eb.Unregister(p);
if (s != null) eb.Unregister(s);
eb.Dispose();
}
#region SimpleEvent
[Test]
public void SimpleEvent()
{
p.CallSimpleEvent();
Assert.IsTrue(s.SimpleEventCalled);
}
[Test]
public void SimpleEvent2Subscribers()
{
Subscriber s2 = new Subscriber();
eb.Register(s2);
p.CallSimpleEvent();
Assert.IsTrue(s.SimpleEventCalled);
Assert.IsTrue(s2.SimpleEventCalled);
}
#endregion
#region CustomEventArgs
[Test]
public void CustomEventArgs()
{
const string value = "Test";
string v = value;
p.CallCustomEventArgs(v);
Assert.IsNotNull(s.ReceivedCustomEventArguments);
Assert.AreEqual(value, s.ReceivedCustomEventArguments.String);
}
#endregion
#region BackgroundThread
[Test]
public void BackgroundThread()
{
p.CallBackgroundThread();
Assert.IsTrue(s.Signal.WaitOne(1000, false), "signal not set.");
Assert.AreNotEqual(-1, s.ThreadId);
Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, s.ThreadId);
}
#endregion
#region MultiplePublicationTokens
[Test]
public void MultiplePublicationTokens()
{
p.CallMultiplePublicationTokens();
Assert.IsTrue(s.MultiplePublicationToken1Called);
Assert.IsTrue(s.MultiplePublicationToken2Called);
Assert.IsTrue(s.MultiplePublicationToken3Called);
}
#endregion
#region MultipleSubscriptionTokens
[Test]
public void MultipleSubscriptionTokens()
{
p.CallMultipleSubscriptionTokens();
Assert.AreEqual(3, s.MultipleSubscriptionTokensCount);
}
#endregion
#region CancelEventArgs
[Test]
public void CancelEventArgs()
{
bool cancel = p.CallCancelEvent();
Assert.IsTrue(cancel, "Result from event call should be true. Return value could not be given back from handler.");
}
#endregion
}
[TestFixture]
public class EventBrokerCountTest
{
[Test]
public void PublisherWithoutSubscriber()
{
EventBroker eb = new EventBroker();
Publisher p = new Publisher();
Subscriber.Count = 0;
eb.Register(p);
p.CallCount();
eb.Unregister(p);
Assert.AreEqual(0, Subscriber.Count);
}
[Test]
public void MultiplePublisherMultipleSubscriber()
{
EventBroker eb = new EventBroker();
Subscriber.Count = 0;
Publisher p1 = new Publisher();
Publisher p2 = new Publisher();
Subscriber s1 = new Subscriber();
Subscriber s2 = new Subscriber();
Subscriber s3 = new Subscriber();
eb.Register(p1);
eb.Register(p2);
eb.Register(s1);
eb.Register(s2);
eb.Register(s3);
p1.CallCount();
p2.CallCount();
eb.Unregister(p1);
eb.Unregister(p2);
eb.Unregister(s1);
eb.Unregister(s2);
eb.Unregister(s3);
Assert.AreEqual(6, Subscriber.Count);
}
}
[TestFixture]
public class EventBrokerCleanupTest
{
EventBroker eb;
[SetUp]
public void SetUp()
{
eb = new EventBroker();
Subscriber.Count = 0;
}
[Test]
public void FreedSubscriber()
{
Publisher p = new Publisher();
Subscriber s1 = new Subscriber();
Subscriber s2 = new Subscriber();
eb.Register(p);
eb.Register(s1);
eb.Register(s2);
s1 = null;
GC.Collect(); // breaks up the weak reference to the subscriber
p.CallCount();
Assert.AreEqual(1, Subscriber.Count);
Assert.Greater(s2.ThreadId, -10); // just some stupid code to prevent s2 from being collected
}
}
[TestFixture]
public class EventBrokerExceptionTest
{
EventBroker eb;
[SetUp]
public void SetUp()
{
eb = new EventBroker();
}
#region Multiple Publications
[Test]
[ExpectedException(typeof(Exceptions.RepeatedPublicationException))]
public void MultiplePublication()
{
InvalidPublisherRepeatedEventPublication p = new InvalidPublisherRepeatedEventPublication();
eb.Register(p);
}
#endregion
#region Wrong Signature
[Test]
[ExpectedException(typeof(Exceptions.InvalidPublicationSignatureException))]
public void WrongEventSignature()
{
InvalidPublisherWrongEventSignature p = new InvalidPublisherWrongEventSignature();
eb.Register(p);
}
[Test]
[ExpectedException(typeof(Exceptions.InvalidSubscriptionSignatureException))]
public void WrongSubscriptionSignature()
{
InvalidSubscriberWrongSignature s = new InvalidSubscriberWrongSignature();
eb.Register(s);
}
#endregion
#region Exception Handling
[Test]
public void ExceptionHandling()
{
try
{
Publisher p = new Publisher();
SubscriberThrowingException s = new SubscriberThrowingException();
eb.Register(p);
eb.Register(s);
p.CallSimpleEvent();
Assert.Fail("must not be reached.");
}
catch (EventTopicException e)
{
Assert.IsTrue(e.InnerException is SubscriberThrowingException.TestException);
}
}
[Test]
[ExpectedException(typeof(EventTopicException))]
public void ExceptionHandlingMultipleException()
{
Publisher p = new Publisher();
SubscriberThrowingException s1 = new SubscriberThrowingException();
SubscriberThrowingException s2 = new SubscriberThrowingException();
eb.Register(p);
eb.Register(s1);
eb.Register(s2);
p.CallSimpleEvent();
}
#endregion
#region Static Event / Handler
[Test]
[ExpectedException(typeof(Exceptions.StaticPublisherEventException))]
public void StaticEvent()
{
InvalidPublisherStaticEvent p = new InvalidPublisherStaticEvent();
eb.Register(p);
}
[Test]
[ExpectedException(typeof(Exceptions.StaticSubscriberHandlerException))]
public void StaticHandler()
{
InvalidSubscriberStaticHandler s = new InvalidSubscriberStaticHandler();
eb.Register(s);
}
#endregion
#region Not User Interface Thread
[Test]
[ExpectedException(typeof(NotUserInterfaceThreadException))]
public void NotInterfaceThread()
{
eb.Register(new UserInterfaceSubscriber());
}
[Test]
public void CheckOnUserInterfaceThreadCanBeSwitchedOff()
{
eb = new EventBroker(new UnitTestFactory());
eb.Register(new UserInterfaceSubscriber());
}
#endregion
}
[TestFixture]
public class FireEventsDirectlyOnEventBrokerTest
{
EventBroker eb;
[SetUp]
public void SetUp()
{
eb = new EventBroker();
}
[Test]
public void FireEvent()
{
Subscriber s = new Subscriber();
eb.Register(s);
eb.Fire(EventTopics.SimpleEvent, this, EventArgs.Empty);
Assert.IsTrue(s.SimpleEventCalled, "event was not received.");
}
}
public static class EventTopics
{
public const string SimpleEvent = "topic://EventBrokerTest/SimpleEvent";
public const string CustomEventArgs = "topic://EventBrokerTest/CustomEventArgs";
public const string BackgroundThread = "topic://EventBrokerTest/BackgroundThread";
public const string CreatorThread = "topic://EventBrokerTest/CreatorThread";
public const string Count = "topic://EventBrokerTest/Count";
public const string MultiplePublicationTokens = "topic://EventBroker/MultiplePublicationTokens";
public const string MultipleSubscriptionTokens = "topic://EventBroker/MultipleSubscriptionTokens";
public const string Private = "topic://EventBrokerTest/Private";
public const string CancelEventArgs = "topic://EventBrokerTest/CancelEventArgs";
}
public class Publisher
{
#region SimpleEvent
[EventPublication(EventTopics.SimpleEvent)]
public event EventHandler SimpleEvent;
public void CallSimpleEvent()
{
SimpleEvent(this, EventArgs.Empty);
}
#endregion
#region CustomEventArgs
[EventPublication(EventTopics.CustomEventArgs)]
public event EventHandler<CustomEventArguments> CustomEventArgs;
public void CallCustomEventArgs(string value)
{
CustomEventArgs(this, new CustomEventArguments(value));
}
#endregion
#region BackgroundThread
[EventPublication(EventTopics.BackgroundThread)]
public event EventHandler BackgroundThread;
public void CallBackgroundThread()
{
BackgroundThread(this, EventArgs.Empty);
}
#endregion
#region Count
[EventPublication(EventTopics.Count)]
public event EventHandler Count;
public void CallCount()
{
Count(this, EventArgs.Empty);
}
#endregion
#region MultiplePublicationTokens
[EventPublication(EventTopics.MultiplePublicationTokens + "1")]
[EventPublication(EventTopics.MultiplePublicationTokens + "2")]
[EventPublication(EventTopics.MultiplePublicationTokens + "3")]
public event EventHandler MultiplePublicationTokens;
public void CallMultiplePublicationTokens()
{
MultiplePublicationTokens(this, EventArgs.Empty);
}
#endregion
#region MultipleSubscriptionTokens
[EventPublication(EventTopics.MultipleSubscriptionTokens + "1")]
public event EventHandler MultipleSubscriptionTokens1;
[EventPublication(EventTopics.MultipleSubscriptionTokens + "2")]
public event EventHandler MultipleSubscriptionTokens2;
[EventPublication(EventTopics.MultipleSubscriptionTokens + "3")]
public event EventHandler MultipleSubscriptionTokens3;
public void CallMultipleSubscriptionTokens()
{
MultipleSubscriptionTokens1(this, EventArgs.Empty);
MultipleSubscriptionTokens2(this, EventArgs.Empty);
MultipleSubscriptionTokens3(this, EventArgs.Empty);
}
#endregion
#region CancelEventArgs
[EventPublication(EventTopics.CancelEventArgs)]
public event EventHandler<CancelEventArgs> CancelEvent;
public bool CallCancelEvent()
{
CancelEventArgs e = new CancelEventArgs(false);
CancelEvent(this, e);
return e.Cancel;
}
#endregion
}
public class Subscriber
{
#region SimpleEvent
public bool SimpleEventCalled = false;
[EventSubscription(EventTopics.SimpleEvent, typeof(Handlers.Publisher))]
public void SimpleEvent(object sender, EventArgs e)
{
SimpleEventCalled = true;
}
#endregion
#region CustomEventArgs
public CustomEventArguments ReceivedCustomEventArguments = null;
[EventSubscription(EventTopics.CustomEventArgs, typeof(Handlers.Publisher))]
public void CustomEventArgs(object sender, CustomEventArguments e)
{
ReceivedCustomEventArguments = e;
}
#endregion
#region BackgroundThread
public int ThreadId = -1;
public AutoResetEvent Signal = new AutoResetEvent(false);
[EventSubscription(EventTopics.BackgroundThread, typeof(Handlers.Background))]
public void BackgroundThread(object sender, EventArgs e)
{
ThreadId = Thread.CurrentThread.ManagedThreadId;
Signal.Set();
}
#endregion
#region Count
public static int Count = 0;
[EventSubscription(EventTopics.Count, typeof(Handlers.Publisher))]
public void CountHandler(object sender, EventArgs e)
{
Count++;
}
#endregion
#region MultiplePublicationTokens
public bool MultiplePublicationToken1Called = false;
public bool MultiplePublicationToken2Called = false;
public bool MultiplePublicationToken3Called = false;
[EventSubscription(EventTopics.MultiplePublicationTokens + "1", typeof(Handlers.Publisher))]
public void MultiplePublicationTokens1(object sender, EventArgs e)
{
MultiplePublicationToken1Called = true;
}
[EventSubscription(EventTopics.MultiplePublicationTokens + "2", typeof(Handlers.Publisher))]
public void MultiplePublicationTokens2(object sender, EventArgs e)
{
MultiplePublicationToken2Called = true;
}
[EventSubscription(EventTopics.MultiplePublicationTokens + "3", typeof(Handlers.Publisher))]
public void MultiplePublicationTokens3(object sender, EventArgs e)
{
MultiplePublicationToken3Called = true;
}
#endregion
#region MultipleSubscriptionTokens
public int MultipleSubscriptionTokensCount = 0;
[EventSubscription(EventTopics.MultipleSubscriptionTokens + "1", typeof(Handlers.Publisher))]
[EventSubscription(EventTopics.MultipleSubscriptionTokens + "2", typeof(Handlers.Publisher))]
[EventSubscription(EventTopics.MultipleSubscriptionTokens + "3", typeof(Handlers.Publisher))]
public void MultipleSubscriptionTokens(object sender, EventArgs e)
{
MultipleSubscriptionTokensCount++;
}
#endregion
#region CancelEventArgs
[EventSubscription(EventTopics.CancelEventArgs, typeof(Handlers.Publisher))]
public void CancelEventArgs(object sender, CancelEventArgs e)
{
e.Cancel = true;
}
#endregion
}
public class InvalidPublisherRepeatedEventPublication
{
[EventPublication(EventTopics.SimpleEvent)]
[EventPublication(EventTopics.SimpleEvent)]
public event EventHandler SimpleEvent1;
public void CallSimpleEvent1()
{
SimpleEvent1(this, EventArgs.Empty);
}
}
public class InvalidPublisherWrongEventSignature
{
public delegate int MyEventHandler(string name);
[EventPublication(EventTopics.SimpleEvent)]
public event MyEventHandler SimpleEvent;
}
public class InvalidPublisherPrivateEvent
{
[EventPublication(EventTopics.SimpleEvent)]
private event EventHandler SimpleEvent;
}
public class InvalidPublisherStaticEvent
{
[EventPublication(EventTopics.SimpleEvent)]
static public event EventHandler SimpleEvent;
}
public class InvalidSubscriberWrongSignature
{
[EventSubscription(EventTopics.SimpleEvent, typeof(Handlers.Publisher))]
public void SimpleEvent(EventArgs e)
{
}
}
public class InvalidSubscriberWrongSignatureWrongEventArgs
{
[EventSubscription(EventTopics.SimpleEvent, typeof(Handlers.Publisher))]
public void SimpleEvent(object sender, CustomEventArguments e)
{
}
}
public class SubscriberThrowingException
{
public class TestException : Exception
{
}
[EventSubscription(EventTopics.SimpleEvent, typeof(Handlers.Publisher))]
public void SimpleEvent(object sender, EventArgs e)
{
throw new TestException();
}
}
public class SubscriberThrowingExceptionBackgroundWorker
{
public class TestException : Exception
{
}
[EventSubscription(EventTopics.SimpleEvent, typeof(Handlers.Background))]
public void SimpleEvent(object sender, EventArgs e)
{
throw new TestException();
}
}
public class InvalidSubscriberStaticHandler
{
[EventSubscription(EventTopics.SimpleEvent, typeof(Handlers.Publisher))]
public static void SimpleEvent(object sender, EventArgs e)
{
}
}
public class UserInterfaceSubscriber
{
[EventSubscription(EventTopics.SimpleEvent, typeof(Handlers.UserInterface))]
public void SimpleEvent(object sender, EventArgs e)
{
}
}
#region CustomEventArgs
public class CustomEventArguments : EventArgs
{
public CustomEventArguments(string s)
{
String = s;
}
public string String;
}
#endregion
}