From b1e153e24153a6d35aafb347493ff7d762be3aa8 Mon Sep 17 00:00:00 2001 From: Manuel Menegazzo Date: Mon, 29 Apr 2024 22:40:50 +0200 Subject: [PATCH 1/7] Handled creation of ActorReference from Actor base class Signed-off-by: Manuel Menegazzo --- all.sln | 27 +++++++++++++++------------ src/Dapr.Actors/ActorReference.cs | 24 ++++++++++++++++-------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/all.sln b/all.sln index be5620b64..469de8d1d 100644 --- a/all.sln +++ b/all.sln @@ -1,4 +1,3 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.3.32929.385 @@ -106,18 +105,19 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkflowUnitTest", "example EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GeneratedActor", "GeneratedActor", "{7592AFA4-426B-42F3-AE82-957C86814482}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ActorClient", "examples\GeneratedActor\ActorClient\ActorClient.csproj", "{61C24126-F39D-4BEA-96DC-FC87BA730554}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ActorClient", "examples\GeneratedActor\ActorClient\ActorClient.csproj", "{61C24126-F39D-4BEA-96DC-FC87BA730554}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ActorCommon", "examples\GeneratedActor\ActorCommon\ActorCommon.csproj", "{CB903D21-4869-42EF-BDD6-5B1CFF674337}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ActorCommon", "examples\GeneratedActor\ActorCommon\ActorCommon.csproj", "{CB903D21-4869-42EF-BDD6-5B1CFF674337}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.Actors.Generators", "src\Dapr.Actors.Generators\Dapr.Actors.Generators.csproj", "{980B5FD8-0107-41F7-8FAD-E4E8BAE8A625}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapr.Actors.Generators", "src\Dapr.Actors.Generators\Dapr.Actors.Generators.csproj", "{980B5FD8-0107-41F7-8FAD-E4E8BAE8A625}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ActorService", "examples\GeneratedActor\ActorService\ActorService.csproj", "{7C06FE2D-6C62-48F5-A505-F0D715C554DE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ActorService", "examples\GeneratedActor\ActorService\ActorService.csproj", "{7C06FE2D-6C62-48F5-A505-F0D715C554DE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.Actors.Generators.Test", "test\Dapr.Actors.Generators.Test\Dapr.Actors.Generators.Test.csproj", "{AF89083D-4715-42E6-93E9-38497D12A8A6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapr.Actors.Generators.Test", "test\Dapr.Actors.Generators.Test\Dapr.Actors.Generators.Test.csproj", "{AF89083D-4715-42E6-93E9-38497D12A8A6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.E2E.Test.Actors.Generators", "test\Dapr.E2E.Test.Actors.Generators\Dapr.E2E.Test.Actors.Generators.csproj", "{B5CDB0DC-B26D-48F1-B934-FE5C1C991940}" -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cryptography", "examples\Client\Cryptography\Cryptography.csproj", "{C74FBA78-13E8-407F-A173-4555AEE41FF3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dapr.E2E.Test.Actors.Generators", "test\Dapr.E2E.Test.Actors.Generators\Dapr.E2E.Test.Actors.Generators.csproj", "{B5CDB0DC-B26D-48F1-B934-FE5C1C991940}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cryptography", "examples\Client\Cryptography\Cryptography.csproj", "{C74FBA78-13E8-407F-A173-4555AEE41FF3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -291,10 +291,6 @@ Global {C74FBA78-13E8-407F-A173-4555AEE41FF3}.Debug|Any CPU.Build.0 = Debug|Any CPU {C74FBA78-13E8-407F-A173-4555AEE41FF3}.Release|Any CPU.ActiveCfg = Release|Any CPU {C74FBA78-13E8-407F-A173-4555AEE41FF3}.Release|Any CPU.Build.0 = Release|Any CPU - {D1786E2B-CAA0-4B2D-A974-9845EB9E420F}.Debug|Any CPU.ActiveCfg = Debug - {D1786E2B-CAA0-4B2D-A974-9845EB9E420F}.Debug|Any CPU.Build.0 = Debug - {D1786E2B-CAA0-4B2D-A974-9845EB9E420F}.Release|Any CPU.ActiveCfg = Release - {D1786E2B-CAA0-4B2D-A974-9845EB9E420F}.Release|Any CPU.Build.0 = Release EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -353,3 +349,10 @@ Global SolutionGuid = {65220BF2-EAE1-4CB2-AA58-EBE80768CB40} EndGlobalSection EndGlobal +C991940} = {DD020B34-460F-455F-8D17-CF4A949F100B} + {C74FBA78-13E8-407F-A173-4555AEE41FF3} = {A7F41094-8648-446B-AECD-DCC2CC871F73} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {65220BF2-EAE1-4CB2-AA58-EBE80768CB40} + EndGlobalSection +EndGlobal diff --git a/src/Dapr.Actors/ActorReference.cs b/src/Dapr.Actors/ActorReference.cs index 0e199c3ae..f804ce508 100644 --- a/src/Dapr.Actors/ActorReference.cs +++ b/src/Dapr.Actors/ActorReference.cs @@ -1,4 +1,4 @@ -// ------------------------------------------------------------------------ +// ------------------------------------------------------------------------ // Copyright 2021 The Dapr Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ namespace Dapr.Actors using System; using System.Runtime.Serialization; using Dapr.Actors.Client; + using Dapr.Actors.Runtime; /// /// Encapsulation of a reference to an actor for serialization. @@ -74,18 +75,25 @@ private static ActorReference GetActorReference(object actor) throw new ArgumentNullException("actor"); } - // try as IActorProxy for backward compatibility as customers's mock framework may rely on it before V2 remoting stack. - if (actor is IActorProxy actorProxy) + var actorReference = actor switch { - return new ActorReference() + // try as IActorProxy for backward compatibility as customers's mock framework may rely on it before V2 remoting stack. + IActorProxy actorProxy => new ActorReference() { ActorId = actorProxy.ActorId, ActorType = actorProxy.ActorType, - }; - } + }, + // Handle case when we want to get ActorReference inside the Actor implementation. + Actor actorBase => new ActorReference() + { + ActorId = actorBase.Id, + ActorType = actorBase.Host.ActorTypeInfo.ActorTypeName, + }, + // Handle case when we can't cast to IActorProxy or Actor. + _ => throw new ArgumentOutOfRangeException("actor"), + }; - // TODO check for ActorBase - throw new ArgumentOutOfRangeException("actor"); + return actorReference; } } } From fd5aeab6325b4a4e1334aef5f436357400ed6d30 Mon Sep 17 00:00:00 2001 From: Manuel Menegazzo Date: Mon, 29 Apr 2024 23:04:35 +0200 Subject: [PATCH 2/7] Updated null check Signed-off-by: Manuel Menegazzo --- src/Dapr.Actors/ActorReference.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Dapr.Actors/ActorReference.cs b/src/Dapr.Actors/ActorReference.cs index f804ce508..f80a49523 100644 --- a/src/Dapr.Actors/ActorReference.cs +++ b/src/Dapr.Actors/ActorReference.cs @@ -70,10 +70,7 @@ public object Bind(Type actorInterfaceType) private static ActorReference GetActorReference(object actor) { - if (actor == null) - { - throw new ArgumentNullException("actor"); - } + ArgumentNullException.ThrowIfNull(actor, nameof(actor)); var actorReference = actor switch { From 665cc7939c0308bc6de089df2ea26625b863a9dc Mon Sep 17 00:00:00 2001 From: Manuel Menegazzo Date: Mon, 29 Apr 2024 23:16:43 +0200 Subject: [PATCH 3/7] Added unit test for GetActorReference from null actore and actor proxy Signed-off-by: Manuel Menegazzo --- test/Dapr.Actors.Test/ActorReferenceTests.cs | 42 ++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 test/Dapr.Actors.Test/ActorReferenceTests.cs diff --git a/test/Dapr.Actors.Test/ActorReferenceTests.cs b/test/Dapr.Actors.Test/ActorReferenceTests.cs new file mode 100644 index 000000000..752210195 --- /dev/null +++ b/test/Dapr.Actors.Test/ActorReferenceTests.cs @@ -0,0 +1,42 @@ +using Dapr.Actors.Client; +using Dapr.Actors.Test; +using Xunit; + +namespace Dapr.Actors +{ + public class ActorReferenceTests + { + [Fact] + public void GetActorReference_WhenActorIsNull_ReturnsNull() + { + // Arrange + object actor = null; + + // Act + var result = ActorReference.Get(actor); + + // Assert + Assert.Null(result); + } + + [Fact] + public void GetActorReference_FromActorProxy_ReturnsActorReference() + { + // Arrange + var expectedActorId = new ActorId("abc"); + var expectedActorType = "TestActor"; + var proxy = ActorProxy.Create(expectedActorId, typeof(ITestActor), expectedActorType); + + // Act + var actorReference = ActorReference.Get(proxy); + + // Assert + Assert.NotNull(actorReference); + Assert.Equal(expectedActorId, actorReference.ActorId); + Assert.Equal(expectedActorType, actorReference.ActorType); + } + + + + } +} From e27bc2a3bbc3fd9d704010d1f2bf0e1a5cbc1d40 Mon Sep 17 00:00:00 2001 From: Manuel Menegazzo Date: Mon, 29 Apr 2024 23:27:57 +0200 Subject: [PATCH 4/7] Added test for ActorReference created inside Actor implementation Signed-off-by: Manuel Menegazzo --- test/Dapr.Actors.Test/ActorReferenceTests.cs | 38 +++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/test/Dapr.Actors.Test/ActorReferenceTests.cs b/test/Dapr.Actors.Test/ActorReferenceTests.cs index 752210195..41f8fffbf 100644 --- a/test/Dapr.Actors.Test/ActorReferenceTests.cs +++ b/test/Dapr.Actors.Test/ActorReferenceTests.cs @@ -1,4 +1,6 @@ -using Dapr.Actors.Client; +using System.Threading.Tasks; +using Dapr.Actors.Client; +using Dapr.Actors.Runtime; using Dapr.Actors.Test; using Xunit; @@ -36,7 +38,41 @@ public void GetActorReference_FromActorProxy_ReturnsActorReference() Assert.Equal(expectedActorType, actorReference.ActorType); } + [Fact] + public async Task GetActorReference_FromActorImplementation_ReturnsActorReference() + { + // Arrange + var expectedActorId = new ActorId("abc"); + var expectedActorType = nameof(ActorReferenceTestActor); + var host = ActorHost.CreateForTest(new ActorTestOptions() { ActorId = expectedActorId }); + var actor = new ActorReferenceTestActor(host); + + // Act + var actorReference = await actor.GetActorReference(); + + // Assert + Assert.NotNull(actorReference); + Assert.Equal(expectedActorId, actorReference.ActorId); + Assert.Equal(expectedActorType, actorReference.ActorType); + } + + } + public interface IActorReferenceTestActor : IActor + { + Task GetActorReference(); + } + public class ActorReferenceTestActor : Actor, IActorReferenceTestActor + { + public ActorReferenceTestActor(ActorHost host) + : base(host) + { + } + + public Task GetActorReference() + { + return Task.FromResult(ActorReference.Get(this)); + } } } From f71d5b083ebdd91c908448a6fbf04eba9a9dc256 Mon Sep 17 00:00:00 2001 From: Manuel Menegazzo Date: Mon, 29 Apr 2024 23:31:06 +0200 Subject: [PATCH 5/7] Updated description Signed-off-by: Manuel Menegazzo --- src/Dapr.Actors/ActorReference.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Dapr.Actors/ActorReference.cs b/src/Dapr.Actors/ActorReference.cs index f80a49523..14a35feb6 100644 --- a/src/Dapr.Actors/ActorReference.cs +++ b/src/Dapr.Actors/ActorReference.cs @@ -80,7 +80,8 @@ private static ActorReference GetActorReference(object actor) ActorId = actorProxy.ActorId, ActorType = actorProxy.ActorType, }, - // Handle case when we want to get ActorReference inside the Actor implementation. + // Handle case when we want to get ActorReference inside the Actor implementation, + // we gather actor id and actor type from Actor base class. Actor actorBase => new ActorReference() { ActorId = actorBase.Id, From 9d98c75ddf5f6d5a9d6434ff470740b3b4771dc0 Mon Sep 17 00:00:00 2001 From: Manuel Menegazzo Date: Mon, 29 Apr 2024 23:52:34 +0200 Subject: [PATCH 6/7] Fixed test method naming Signed-off-by: Manuel Menegazzo --- test/Dapr.Actors.Test/ActorReferenceTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Dapr.Actors.Test/ActorReferenceTests.cs b/test/Dapr.Actors.Test/ActorReferenceTests.cs index 41f8fffbf..73e764638 100644 --- a/test/Dapr.Actors.Test/ActorReferenceTests.cs +++ b/test/Dapr.Actors.Test/ActorReferenceTests.cs @@ -9,7 +9,7 @@ namespace Dapr.Actors public class ActorReferenceTests { [Fact] - public void GetActorReference_WhenActorIsNull_ReturnsNull() + public void Get_WhenActorIsNull_ReturnsNull() { // Arrange object actor = null; @@ -22,7 +22,7 @@ public void GetActorReference_WhenActorIsNull_ReturnsNull() } [Fact] - public void GetActorReference_FromActorProxy_ReturnsActorReference() + public void Get_FromActorProxy_ReturnsActorReference() { // Arrange var expectedActorId = new ActorId("abc"); @@ -39,7 +39,7 @@ public void GetActorReference_FromActorProxy_ReturnsActorReference() } [Fact] - public async Task GetActorReference_FromActorImplementation_ReturnsActorReference() + public async Task Get_FromActorImplementation_ReturnsActorReference() { // Arrange var expectedActorId = new ActorId("abc"); From 98497a7ff84ac6891815d69f045474c72311f80c Mon Sep 17 00:00:00 2001 From: Manuel Menegazzo Date: Thu, 2 May 2024 16:16:54 +0200 Subject: [PATCH 7/7] Added unit test for exception generated in case the type is not convertible to an ActorReference Signed-off-by: Manuel Menegazzo --- src/Dapr.Actors/ActorReference.cs | 2 +- test/Dapr.Actors.Test/ActorReferenceTests.cs | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Dapr.Actors/ActorReference.cs b/src/Dapr.Actors/ActorReference.cs index 14a35feb6..d72b6676f 100644 --- a/src/Dapr.Actors/ActorReference.cs +++ b/src/Dapr.Actors/ActorReference.cs @@ -88,7 +88,7 @@ private static ActorReference GetActorReference(object actor) ActorType = actorBase.Host.ActorTypeInfo.ActorTypeName, }, // Handle case when we can't cast to IActorProxy or Actor. - _ => throw new ArgumentOutOfRangeException("actor"), + _ => throw new ArgumentOutOfRangeException("actor", "Invalid actor object type."), }; return actorReference; diff --git a/test/Dapr.Actors.Test/ActorReferenceTests.cs b/test/Dapr.Actors.Test/ActorReferenceTests.cs index 73e764638..7450f616c 100644 --- a/test/Dapr.Actors.Test/ActorReferenceTests.cs +++ b/test/Dapr.Actors.Test/ActorReferenceTests.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Dapr.Actors.Client; using Dapr.Actors.Runtime; using Dapr.Actors.Test; @@ -56,6 +57,20 @@ public async Task Get_FromActorImplementation_ReturnsActorReference() Assert.Equal(expectedActorType, actorReference.ActorType); } + [Fact] + public void Get_WithInvalidObjectType_ThrowArgumentOutOfRangeException() + { + // Arrange + var actor = new object(); + + // Act + var act = () => ActorReference.Get(actor); + + // Assert + var exception = Assert.Throws(act); + Assert.Equal("actor", exception.ParamName); + Assert.Equal("Invalid actor object type. (Parameter 'actor')", exception.Message); + } } public interface IActorReferenceTestActor : IActor