Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor event system. #262

Merged
merged 1 commit into from
Jul 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions src/CatLib.Core.Tests/CatLib/TestsApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

using CatLib.Container;
using CatLib.EventDispatcher;
using CatLib.Events;
using CatLib.Exception;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
Expand Down Expand Up @@ -71,9 +72,10 @@ public void TestBootstrapSkip()
var foo = new Mock<IBootstrap>();
var bar = new Mock<IBootstrap>();

dispatcher.AddListener<BootingEventArgs>(args =>
dispatcher.AddListener(ApplicationEvents.OnBooting, eventArgs =>
{
if (args.GetBootstrap() == foo.Object)
if (eventArgs is BootingEventArgs args &&
args.GetBootstrap() == foo.Object)
{
args.Skip();
}
Expand All @@ -91,9 +93,10 @@ public void TestRegisterSkip()
var foo = new Mock<IServiceProvider>();
var bar = new Mock<IServiceProvider>();

dispatcher.AddListener<RegisterProviderEventArgs>((args) =>
dispatcher.AddListener(ApplicationEvents.OnRegisterProvider, (eventArgs) =>
{
if (args.GetServiceProvider() == foo.Object)
if (eventArgs is RegisterProviderEventArgs args &&
args.GetServiceProvider() == foo.Object)
{
args.Skip();
}
Expand Down Expand Up @@ -122,7 +125,7 @@ public void TestInitingRegister()
var foo = new Mock<IServiceProvider>();
var bar = new Mock<IServiceProvider>();

dispatcher.AddListener<InitProviderEventArgs>((args) =>
dispatcher.AddListener(ApplicationEvents.OnInitProvider, (args) =>
{
application.Register(foo.Object);
});
Expand All @@ -138,7 +141,7 @@ public void TestTerminateRegister()
{
var foo = new Mock<IServiceProvider>();

dispatcher.AddListener<BeforeTerminateEventArgs>((args) =>
dispatcher.AddListener(ApplicationEvents.OnBeforeTerminate, (args) =>
{
application.Register(foo.Object);
});
Expand All @@ -152,12 +155,12 @@ public void TestTerminateRegister()
public void TestTerminateSequenceOfEvents()
{
var count = 0;
dispatcher.AddListener<BeforeTerminateEventArgs>((args) =>
dispatcher.AddListener(ApplicationEvents.OnBeforeTerminate, (args) =>
{
Assert.AreEqual(0, count++);
});

dispatcher.AddListener<AfterTerminateEventArgs>((args) =>
dispatcher.AddListener(ApplicationEvents.OnAfterTerminate, (args) =>
{
Assert.AreEqual(1, count++);
});
Expand Down
210 changes: 75 additions & 135 deletions src/CatLib.Core.Tests/EventDispatcher/TestsEventDispatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* Document: https://catlib.io/
*/

using CatLib.Exception;
using CatLib.Tests.Fixture;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
Expand All @@ -21,224 +21,164 @@ namespace CatLib.EventDispatcher.Tests
[TestClass]
public class TestsEventDispatcher
{
internal interface IResponse<T>
private Dispatcher eventDispatcher;

internal interface IResponse
{
void Foo(T eventArgs);
void Foo(EventArgs eventArgs);
}

[TestInitialize]
public void Initialize()
{
eventDispatcher = new Dispatcher();
}

[TestMethod]
public void TestDispatch()
{
var eventDispatcher = new Dispatcher();
var expected = new TestEventArgs();
var mock = new Mock<IResponse<TestEventArgs>>();
eventDispatcher.AddListener<TestEventArgs>(mock.Object.Foo);
eventDispatcher.Dispatch(expected);
var mock = new Mock<IResponse>();
eventDispatcher.AddListener("foo", mock.Object.Foo);
eventDispatcher.Dispatch("foo", expected);
mock.Verify((o) => o.Foo(expected));
}

[TestMethod]
public void TestAddListener()
{
var eventDispatcher = new Dispatcher();
var first = new Mock<IResponse<TestEventArgs>>();
var second = new Mock<IResponse<TestEventArgs>>();
var first = new Mock<IResponse>();
var second = new Mock<IResponse>();

eventDispatcher.AddListener<TestEventArgs>(first.Object.Foo);
eventDispatcher.AddListener<TestEventArgs>(second.Object.Foo);
eventDispatcher.AddListener("foo", first.Object.Foo);
eventDispatcher.AddListener("foo", second.Object.Foo);

Assert.AreEqual(2, eventDispatcher.GetListeners<TestEventArgs>().Count());
CollectionAssert.AreEqual(
new Action<EventArgs>[]
{
second.Object.Foo,
first.Object.Foo,
}, eventDispatcher.GetListeners("foo"));
}

[TestMethod]
public void TestAddListenerBySort()
{
var eventDispatcher = new Dispatcher();
var first = new Mock<IResponse<TestEventArgs>>();
var second = new Mock<IResponse<TestEventArgs>>();
var third = new Mock<IResponse<TestEventArgs>>();
var first = new Mock<IResponse>();
var second = new Mock<IResponse>();
var third = new Mock<IResponse>();

eventDispatcher.AddListener<TestEventArgs>(first.Object.Foo, 10);
eventDispatcher.AddListener<TestEventArgs>(second.Object.Foo, -10);
eventDispatcher.AddListener<TestEventArgs>(third.Object.Foo);
eventDispatcher.AddListener("foo", first.Object.Foo, 10);
eventDispatcher.AddListener("foo", second.Object.Foo, -10);
eventDispatcher.AddListener("foo", third.Object.Foo);

CollectionAssert.AreEqual(
new Action<TestEventArgs>[]
new Action<EventArgs>[]
{
second.Object.Foo, third.Object.Foo, first.Object.Foo,
},
eventDispatcher.GetListeners<TestEventArgs>().ToList());
eventDispatcher.GetListeners("foo"));
}

[TestMethod]
public void TestHasListener()
{
var eventDispatcher = new Dispatcher();
var first = new Mock<IResponse<TestEventArgs>>();
var second = new Mock<IResponse<BaseTestEventArgs>>();

eventDispatcher.AddListener<TestEventArgs>(first.Object.Foo);
eventDispatcher.AddListener<BaseTestEventArgs>(second.Object.Foo);

Assert.IsTrue(eventDispatcher.HasListeners<TestEventArgs>());
Assert.IsTrue(eventDispatcher.HasListeners<BaseTestEventArgs>());
}

[TestMethod]
public void TestDispatchForInheritanceChain()
{
var eventDispatcher = new Dispatcher();
var first = new Mock<IResponse<TestEventArgs>>();
var second = new Mock<IResponse<BaseTestEventArgs>>();
var third = new Mock<IResponse<EventArgs>>();
var expected = new TestEventArgs();

eventDispatcher.AddListener<TestEventArgs>(first.Object.Foo);
eventDispatcher.AddListener<BaseTestEventArgs>(second.Object.Foo);
eventDispatcher.AddListener<EventArgs>(third.Object.Foo);

eventDispatcher.Dispatch(expected);

first.Verify((o) => o.Foo(expected));
second.Verify((o) => o.Foo(expected));
third.Verify((o) => o.Foo(expected));

var expectedBase = new BaseTestEventArgs();

eventDispatcher.Dispatch(expectedBase);
second.Verify((o) => o.Foo(expectedBase));
third.Verify((o) => o.Foo(expectedBase));
}

[TestMethod]
public void TestDispatchForInheritanceChainDisabled()
{
var eventDispatcher = new Dispatcher(false);
var first = new Mock<IResponse<TestEventArgs>>();
var second = new Mock<IResponse<BaseTestEventArgs>>();
var third = new Mock<IResponse<EventArgs>>();
var expected = new TestEventArgs();
var foo = new Mock<IResponse>();
var bar = new Mock<IResponse>();

eventDispatcher.AddListener<TestEventArgs>(first.Object.Foo);
eventDispatcher.AddListener<BaseTestEventArgs>(second.Object.Foo);
eventDispatcher.AddListener<EventArgs>(third.Object.Foo);
eventDispatcher.AddListener("foo", foo.Object.Foo);
eventDispatcher.AddListener("bar", bar.Object.Foo);

eventDispatcher.Dispatch(expected);

first.Verify((o) => o.Foo(expected));
second.Verify((o) => o.Foo(expected), Times.Never);
third.Verify((o) => o.Foo(expected), Times.Never);
Assert.IsTrue(eventDispatcher.HasListeners("foo"));
Assert.IsTrue(eventDispatcher.HasListeners("bar"));
Assert.IsFalse(eventDispatcher.HasListeners("baz"));
}

[TestMethod]
[ExpectedException(typeof(RuntimeException))]
public void TestRepateAddSameListeners()
{
var eventDispatcher = new Dispatcher(false);
var first = new Mock<IResponse<TestEventArgs>>();
var first = new Mock<IResponse>();

eventDispatcher.AddListener<TestEventArgs>(first.Object.Foo);
eventDispatcher.AddListener<TestEventArgs>(first.Object.Foo);
Assert.IsTrue(eventDispatcher.AddListener("foo", first.Object.Foo));
Assert.IsFalse(eventDispatcher.AddListener("foo", first.Object.Foo));
}

[TestMethod]
public void TestRemoveListeners()
{
var eventDispatcher = new Dispatcher();
var first = new Mock<IResponse<TestEventArgs>>();
var second = new Mock<IResponse<EventArgs>>();
var foo = new Mock<IResponse>();
var bar = new Mock<IResponse>();
var expected = new TestEventArgs();

eventDispatcher.AddListener<TestEventArgs>(first.Object.Foo);
eventDispatcher.AddListener<EventArgs>(second.Object.Foo);
eventDispatcher.AddListener("foo", foo.Object.Foo);
eventDispatcher.AddListener("bar", bar.Object.Foo);

eventDispatcher.Dispatch(expected);
eventDispatcher.Dispatch("foo", expected);
eventDispatcher.Dispatch("bar", expected);

first.Verify((o) => o.Foo(expected));
second.Verify((o) => o.Foo(expected));
foo.Verify((o) => o.Foo(expected));
bar.Verify((o) => o.Foo(expected));

eventDispatcher.RemoveListener<TestEventArgs>(first.Object.Foo);
eventDispatcher.RemoveListener("foo", foo.Object.Foo);

eventDispatcher.Dispatch(expected);
eventDispatcher.Dispatch("foo", expected);
eventDispatcher.Dispatch("bar", expected);

first.Verify((o) => o.Foo(expected), Times.Exactly(1));
second.Verify((o) => o.Foo(expected), Times.Exactly(2));
foo.Verify((o) => o.Foo(expected), Times.Exactly(1));
bar.Verify((o) => o.Foo(expected), Times.Exactly(2));
}

[TestMethod]
public void TestRemoveAllListeners()
{
var eventDispatcher = new Dispatcher();
var first = new Mock<IResponse<TestEventArgs>>();
var second = new Mock<IResponse<TestEventArgs>>();
var foo = new Mock<IResponse>();
var foobar = new Mock<IResponse>();
var expected = new TestEventArgs();

eventDispatcher.AddListener<TestEventArgs>(first.Object.Foo);
eventDispatcher.AddListener<TestEventArgs>(second.Object.Foo);
eventDispatcher.AddListener("foo", foo.Object.Foo);
eventDispatcher.AddListener("foo", foobar.Object.Foo);

eventDispatcher.Dispatch(expected);
eventDispatcher.Dispatch("foo", expected);

first.Verify((o) => o.Foo(expected));
second.Verify((o) => o.Foo(expected));
foo.Verify((o) => o.Foo(expected));
foobar.Verify((o) => o.Foo(expected));

eventDispatcher.RemoveListener<TestEventArgs>();
eventDispatcher.RemoveListener("foo");

eventDispatcher.Dispatch(expected);
eventDispatcher.Dispatch("foo", expected);

first.Verify((o) => o.Foo(expected), Times.Exactly(1));
second.Verify((o) => o.Foo(expected), Times.Exactly(1));
foo.Verify((o) => o.Foo(expected), Times.Exactly(1));
foobar.Verify((o) => o.Foo(expected), Times.Exactly(1));
}

[TestMethod]
public void TestRemoveNotExistsListener()
{
var eventDispatcher = new Dispatcher();
var first = new Mock<IResponse<TestEventArgs>>();
eventDispatcher.RemoveListener<TestEventArgs>(first.Object.Foo);
var foo = new Mock<IResponse>();
Assert.IsFalse(eventDispatcher.RemoveListener("foo", foo.Object.Foo));
Assert.IsFalse(eventDispatcher.RemoveListener("bar"));
}

[TestMethod]
public void TestStoppableEvent()
{
var eventDispatcher = new Dispatcher();
var first = new Mock<IResponse<TestEventArgs>>();
var second = new Mock<IResponse<TestEventArgs>>();
var first = new Mock<IResponse>();
var second = new Mock<IResponse>();
var expected = new TestEventArgs();

// Same priority, post-listener priority.
second.Setup((o) => o.Foo(expected)).Callback(() =>
{
expected.Stop();
});

eventDispatcher.AddListener<TestEventArgs>(first.Object.Foo);
eventDispatcher.AddListener<TestEventArgs>(second.Object.Foo);
eventDispatcher.AddListener("foo", first.Object.Foo);
eventDispatcher.AddListener("foo", second.Object.Foo);

eventDispatcher.Dispatch(expected);
eventDispatcher.Dispatch("foo", expected);

first.Verify((o) => o.Foo(expected), Times.Never);
second.Verify((o) => o.Foo(expected));
}

internal class BaseTestEventArgs : EventArgs
{
public string Name { get; set; } = "foo";
}

internal class TestEventArgs : BaseTestEventArgs, IStoppableEvent
{
private bool isPropagationStopped;

public object Payload { get; set; }

public bool IsPropagationStopped()
{
return isPropagationStopped;
}

public void Stop()
{
isPropagationStopped = true;
}
}
}
}
Loading