From db4e3c6e8ba716ee913ff4b706a338bfe28b6e6d Mon Sep 17 00:00:00 2001 From: eanzhao Date: Mon, 23 Jun 2025 15:44:47 +0800 Subject: [PATCH 1/3] fix event type judgement during calling event wrapper base observer. --- src/Aevatar.Core/GAgentBase.Observers.cs | 5 ++-- .../TestGAgents/EventBaseTypeTestGAgent.cs | 27 +++++++++++++++++++ test/Aevatar.GAgents.Tests/GAgentBaseTests.cs | 11 ++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 test/Aevatar.Core.Tests/TestGAgents/EventBaseTypeTestGAgent.cs diff --git a/src/Aevatar.Core/GAgentBase.Observers.cs b/src/Aevatar.Core/GAgentBase.Observers.cs index 035edbe7..92ea7ec5 100644 --- a/src/Aevatar.Core/GAgentBase.Observers.cs +++ b/src/Aevatar.Core/GAgentBase.Observers.cs @@ -173,10 +173,11 @@ private async Task HandleEventWrapper( { switch (eventWrapper.Event) { - case { } ev when parameterType.BaseType == typeof(EventBase): + case { } ev when parameterType.BaseType != null && + typeof(EventBase).IsAssignableFrom(parameterType.BaseType): await HandleEvent(method, ev); break; - + case not null when parameterType == typeof(EventWrapperBase): await HandleEventWrapperBase(method, eventWrapper); break; diff --git a/test/Aevatar.Core.Tests/TestGAgents/EventBaseTypeTestGAgent.cs b/test/Aevatar.Core.Tests/TestGAgents/EventBaseTypeTestGAgent.cs new file mode 100644 index 00000000..13eb5a34 --- /dev/null +++ b/test/Aevatar.Core.Tests/TestGAgents/EventBaseTypeTestGAgent.cs @@ -0,0 +1,27 @@ +using Aevatar.Core; +using Aevatar.Core.Abstractions; +using Aevatar.Core.Tests.TestGAgents; +using Aevatar.PermissionManagement; + +[GenerateSerializer] +public class EventBaseTypeTestGAgentState : NaiveTestGAgentState; + +[GenerateSerializer] +public class EventBaseTypeTestStateLogEvent : StateLogEventBase; + +[GenerateSerializer] +public class TestPermissionEvent : PermissionEventBase; + +[GAgent] +public class EventBaseTypeTestGAgent : GAgentBase +{ + public override Task GetDescriptionAsync() + { + return Task.FromResult("This is a GAgent for testing event base types."); + } + + public async Task HandleEventAsync(TestPermissionEvent @event) + { + State.Content.Add("test"); + } +} \ No newline at end of file diff --git a/test/Aevatar.GAgents.Tests/GAgentBaseTests.cs b/test/Aevatar.GAgents.Tests/GAgentBaseTests.cs index 8d2a29c2..be63d4e6 100644 --- a/test/Aevatar.GAgents.Tests/GAgentBaseTests.cs +++ b/test/Aevatar.GAgents.Tests/GAgentBaseTests.cs @@ -107,6 +107,17 @@ await publishingGAgent.PublishEventAsync(new NaiveTestEvent state.Called.ShouldBe(true); } + [Fact] + public async Task EventBaseTypeTest() + { + var gAgent = await _gAgentFactory.GetGAgentAsync>(); + var publishingGAgent = await _gAgentFactory.GetGAgentAsync(); + await publishingGAgent.RegisterAsync(gAgent); + await publishingGAgent.PublishEventAsync(new TestPermissionEvent()); + var state = await gAgent.GetStateAsync(); + state.Content.Count.ShouldBePositive(); + } + private async Task CheckState(IStateGAgent investor1) { var state = await investor1.GetStateAsync(); From 3600fbccc3a43cae7757a8ed3af697c03d728a07 Mon Sep 17 00:00:00 2001 From: eanzhao Date: Tue, 24 Jun 2025 16:01:47 +0800 Subject: [PATCH 2/3] fix EventBaseTypeTest. --- .../TestGAgents/NaiveTestGAgent.cs | 2 +- test/Aevatar.Core.Tests/TestHelper.cs | 21 +++++++++++++++++++ test/Aevatar.GAgents.Tests/GAgentBaseTests.cs | 12 ++++++----- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/test/Aevatar.Core.Tests/TestGAgents/NaiveTestGAgent.cs b/test/Aevatar.Core.Tests/TestGAgents/NaiveTestGAgent.cs index 2f376061..7518eaf1 100644 --- a/test/Aevatar.Core.Tests/TestGAgents/NaiveTestGAgent.cs +++ b/test/Aevatar.Core.Tests/TestGAgents/NaiveTestGAgent.cs @@ -5,7 +5,7 @@ namespace Aevatar.Core.Tests.TestGAgents; [GenerateSerializer] public class NaiveTestGAgentState : StateBase { - [Id(0)] public List Content { get; set; } + [Id(0)] public List Content { get; set; } = []; } public class NaiveTestStateLogEvent : StateLogEventBase diff --git a/test/Aevatar.Core.Tests/TestHelper.cs b/test/Aevatar.Core.Tests/TestHelper.cs index 18e9216e..b2499f14 100644 --- a/test/Aevatar.Core.Tests/TestHelper.cs +++ b/test/Aevatar.Core.Tests/TestHelper.cs @@ -1,3 +1,6 @@ +using Aevatar.Core.Abstractions; +using Aevatar.Core.Tests.TestGAgents; + namespace Aevatar.GAgents.Tests; public static class TestHelper @@ -38,4 +41,22 @@ async Task Loop() } } } + + public static async Task CheckStateAsync(IStateGAgent testGAgent, int expectedCount = 1, + TimeSpan? timeout = null) where TState : NaiveTestGAgentState, new() + { + if (timeout != null) + { + timeout = TimeSpan.FromSeconds(20); + } + + await WaitUntilAsync(_ => PerformCheckStateAsync(testGAgent, expectedCount), timeout); + } + + private static async Task PerformCheckStateAsync(IStateGAgent testGAgent, int expectedCount) + where TState : NaiveTestGAgentState, new() + { + var state = await testGAgent.GetStateAsync(); + return state.Content.Count == expectedCount; + } } \ No newline at end of file diff --git a/test/Aevatar.GAgents.Tests/GAgentBaseTests.cs b/test/Aevatar.GAgents.Tests/GAgentBaseTests.cs index be63d4e6..78941207 100644 --- a/test/Aevatar.GAgents.Tests/GAgentBaseTests.cs +++ b/test/Aevatar.GAgents.Tests/GAgentBaseTests.cs @@ -70,7 +70,7 @@ await publishingGAgent.PublishEventAsync(new NewDemandTestEvent Description = "New demand from customer." }); - await TestHelper.WaitUntilAsync(_ => CheckState(investor1), TimeSpan.FromSeconds(20)); + await TestHelper.CheckStateAsync(investor1, 2); var groupState = await groupGAgent.GetStateAsync(); groupState.RegisteredGAgents.ShouldBe(2); @@ -107,20 +107,22 @@ await publishingGAgent.PublishEventAsync(new NaiveTestEvent state.Called.ShouldBe(true); } - [Fact] + [Fact(DisplayName = "Can handle multiple inherited event types.")] public async Task EventBaseTypeTest() { var gAgent = await _gAgentFactory.GetGAgentAsync>(); var publishingGAgent = await _gAgentFactory.GetGAgentAsync(); await publishingGAgent.RegisterAsync(gAgent); await publishingGAgent.PublishEventAsync(new TestPermissionEvent()); + await TestHelper.CheckStateAsync(gAgent); var state = await gAgent.GetStateAsync(); state.Content.Count.ShouldBePositive(); } - private async Task CheckState(IStateGAgent investor1) + private async Task CheckState(IStateGAgent testGAgent, int expectedCount = 1) + where TState : NaiveTestGAgentState, new() { - var state = await investor1.GetStateAsync(); - return !state.Content.IsNullOrEmpty() && state.Content.Count == 2; + var state = await testGAgent.GetStateAsync(); + return !state.Content.IsNullOrEmpty() && state.Content.Count == expectedCount; } } \ No newline at end of file From 2a3e22b194496674d740d28f71dbdb5555496965 Mon Sep 17 00:00:00 2001 From: eanzhao Date: Tue, 24 Jun 2025 16:32:52 +0800 Subject: [PATCH 3/3] add more judgements to ComplicatedEventHandleTest --- .../TestGAgents/DeveloperTestGAgent.cs | 4 +++- .../TestGAgents/DevelopingLeaderTestGAgent.cs | 9 +++++--- .../TestGAgents/InvestorTestGAgent.cs | 17 ++++---------- .../TestGAgents/MarketingLeaderTestGAgent.cs | 9 +++++--- .../TestGAgents/NaiveTestGAgent.cs | 3 ++- test/Aevatar.GAgents.Tests/GAgentBaseTests.cs | 23 +++++++++++++++---- 6 files changed, 39 insertions(+), 26 deletions(-) diff --git a/test/Aevatar.Core.Tests/TestGAgents/DeveloperTestGAgent.cs b/test/Aevatar.Core.Tests/TestGAgents/DeveloperTestGAgent.cs index 2da6ac2e..69c3018d 100644 --- a/test/Aevatar.Core.Tests/TestGAgents/DeveloperTestGAgent.cs +++ b/test/Aevatar.Core.Tests/TestGAgents/DeveloperTestGAgent.cs @@ -4,7 +4,7 @@ namespace Aevatar.Core.Tests.TestGAgents; -public interface IDeveloperTestGAgent : IGAgent; +public interface IDeveloperTestGAgent : IStateGAgent; [GenerateSerializer] public class DeveloperTestGAgentState : NaiveTestGAgentState; @@ -27,6 +27,8 @@ public async Task HandleEventAsync(DevelopTaskTest State.Content.Add(eventData.Description); Logger.LogInformation("TEST"); + + State.PublishedEventList.Add(nameof(NewFeatureCompletedTestEvent)); return new NewFeatureCompletedTestEvent { PullRequestUrl = $"PR for {eventData.Description}" diff --git a/test/Aevatar.Core.Tests/TestGAgents/DevelopingLeaderTestGAgent.cs b/test/Aevatar.Core.Tests/TestGAgents/DevelopingLeaderTestGAgent.cs index e3b5d0ea..26627cfd 100644 --- a/test/Aevatar.Core.Tests/TestGAgents/DevelopingLeaderTestGAgent.cs +++ b/test/Aevatar.Core.Tests/TestGAgents/DevelopingLeaderTestGAgent.cs @@ -4,25 +4,27 @@ namespace Aevatar.Core.Tests.TestGAgents; -public interface IDevelopingLeaderTestGAgent : IGAgent; +public interface IDevelopingLeaderTestGAgent : IStateGAgent; [GenerateSerializer] public class DevelopingLeaderTestGAgentState : NaiveTestGAgentState; [GAgent("developingLeader", "test")] -public class DevelopingLeaderTestGAgent : GAgentBase, IDevelopingLeaderTestGAgent +public class DevelopingLeaderTestGAgent : GAgentBase, + IDevelopingLeaderTestGAgent { public override Task GetDescriptionAsync() { return Task.FromResult("This GAgent acts as a developing leader."); } - + public async Task HandleEventAsync(NewDemandTestEvent eventData) { await PublishAsync(new DevelopTaskTestEvent { Description = $"This is the demand for the task: {eventData.Description}" }); + State.PublishedEventList.Add(nameof(DevelopTaskTestEvent)); } public async Task HandleEventAsync(NewFeatureCompletedTestEvent eventData) @@ -40,6 +42,7 @@ await PublishAsync(new NewFeatureCompletedTestEvent { PullRequestUrl = string.Join("\n", State.Content) }); + State.PublishedEventList.Add(nameof(NewFeatureCompletedTestEvent)); } } } \ No newline at end of file diff --git a/test/Aevatar.Core.Tests/TestGAgents/InvestorTestGAgent.cs b/test/Aevatar.Core.Tests/TestGAgents/InvestorTestGAgent.cs index b94ee457..9e5f39f9 100644 --- a/test/Aevatar.Core.Tests/TestGAgents/InvestorTestGAgent.cs +++ b/test/Aevatar.Core.Tests/TestGAgents/InvestorTestGAgent.cs @@ -4,16 +4,10 @@ namespace Aevatar.Core.Tests.TestGAgents; -public interface IInvestorTestGAgent: IGAgent -{ - -} +public interface IInvestorTestGAgent: IStateGAgent; [GenerateSerializer] -public class InvestorTestGAgentState : NaiveTestGAgentState -{ - -} +public class InvestorTestGAgentState : NaiveTestGAgentState; [GAgent("investor", "test")] public class InvestorTestGAgent : GAgentBase, IInvestorTestGAgent @@ -25,16 +19,13 @@ public override Task GetDescriptionAsync() public async Task HandleEventAsync(WorkingOnTestEvent eventData) { - if (State.Content.IsNullOrEmpty()) - { - State.Content = []; - } - State.Content.Add(eventData.Description); await PublishAsync(new InvestorFeedbackTestEvent { Content = $"This is the feedback for the event: {eventData.Description}" }); + + State.PublishedEventList.Add(nameof(InvestorFeedbackTestEvent)); } } \ No newline at end of file diff --git a/test/Aevatar.Core.Tests/TestGAgents/MarketingLeaderTestGAgent.cs b/test/Aevatar.Core.Tests/TestGAgents/MarketingLeaderTestGAgent.cs index 28542e21..d46df2a5 100644 --- a/test/Aevatar.Core.Tests/TestGAgents/MarketingLeaderTestGAgent.cs +++ b/test/Aevatar.Core.Tests/TestGAgents/MarketingLeaderTestGAgent.cs @@ -4,12 +4,13 @@ namespace Aevatar.Core.Tests.TestGAgents; -public interface IMarketingLeaderTestGAgent : IGAgent; +public interface IMarketingLeaderTestGAgent : IStateGAgent; [GenerateSerializer] public class MarketingLeaderTestGAgentState : NaiveTestGAgentState; [GAgent("marketingLeader", "test")] -public class MarketingLeaderTestGAgent : GAgentBase, IMarketingLeaderTestGAgent +public class MarketingLeaderTestGAgent : GAgentBase, + IMarketingLeaderTestGAgent { public override Task GetDescriptionAsync() { @@ -22,6 +23,7 @@ await PublishAsync(new WorkingOnTestEvent { Description = $"Working on `{eventData.Description}`", }); + State.PublishedEventList.Add(nameof(WorkingOnTestEvent)); } public async Task HandleEventAsync(NewFeatureCompletedTestEvent eventData) @@ -30,8 +32,9 @@ await PublishAsync(new WorkingOnTestEvent { Description = $"Working completed: {eventData.PullRequestUrl}" }); + State.PublishedEventList.Add(nameof(WorkingOnTestEvent)); } - + public async Task HandleEventAsync(InvestorFeedbackTestEvent eventData) { if (State.Content.IsNullOrEmpty()) diff --git a/test/Aevatar.Core.Tests/TestGAgents/NaiveTestGAgent.cs b/test/Aevatar.Core.Tests/TestGAgents/NaiveTestGAgent.cs index 2f376061..bb38e648 100644 --- a/test/Aevatar.Core.Tests/TestGAgents/NaiveTestGAgent.cs +++ b/test/Aevatar.Core.Tests/TestGAgents/NaiveTestGAgent.cs @@ -5,7 +5,8 @@ namespace Aevatar.Core.Tests.TestGAgents; [GenerateSerializer] public class NaiveTestGAgentState : StateBase { - [Id(0)] public List Content { get; set; } + [Id(0)] public List Content { get; set; } = []; + [Id(1)] public List PublishedEventList { get; set; } = []; } public class NaiveTestStateLogEvent : StateLogEventBase diff --git a/test/Aevatar.GAgents.Tests/GAgentBaseTests.cs b/test/Aevatar.GAgents.Tests/GAgentBaseTests.cs index 8d2a29c2..99690b0f 100644 --- a/test/Aevatar.GAgents.Tests/GAgentBaseTests.cs +++ b/test/Aevatar.GAgents.Tests/GAgentBaseTests.cs @@ -53,8 +53,8 @@ public async Task ComplicatedEventHandleTest() await developingLeader.RegisterAsync(developer2); await developingLeader.RegisterAsync(developer3); - var investor1 = _grainFactory.GetGrain>(guid); - var investor2 = _grainFactory.GetGrain>(Guid.NewGuid()); + var investor1 = _grainFactory.GetGrain(guid); + var investor2 = _grainFactory.GetGrain(Guid.NewGuid()); await marketingLeader.RegisterAsync(investor1); await marketingLeader.RegisterAsync(investor2); @@ -72,11 +72,24 @@ await publishingGAgent.PublishEventAsync(new NewDemandTestEvent await TestHelper.WaitUntilAsync(_ => CheckState(investor1), TimeSpan.FromSeconds(20)); + var marketingLeaderState = await marketingLeader.GetStateAsync(); + marketingLeaderState.PublishedEventList.Count.ShouldBe(2); + marketingLeaderState.PublishedEventList.ShouldContain(nameof(WorkingOnTestEvent)); + + var developingLeaderState = await developingLeader.GetStateAsync(); + developingLeaderState.PublishedEventList.Count.ShouldBe(2); + developingLeaderState.PublishedEventList.ShouldContain(nameof(DevelopTaskTestEvent)); + developingLeaderState.PublishedEventList.ShouldContain(nameof(NewFeatureCompletedTestEvent)); + + var developer1State = await developer1.GetStateAsync(); + developer1State.PublishedEventList.Count.ShouldBe(1); + + var investor1State = await investor1.GetStateAsync(); + investor1State.Content.Count.ShouldBe(2); + investor1State.PublishedEventList.Count.ShouldBe(2); + var groupState = await groupGAgent.GetStateAsync(); groupState.RegisteredGAgents.ShouldBe(2); - - var investorState = await investor1.GetStateAsync(); - investorState.Content.Count.ShouldBe(2); } [Fact(DisplayName = "SyncWorker should be worked and not block current GAgent.")]