mirror of https://github.com/dapr/dotnet-sdk.git
256 lines
9.2 KiB
C#
256 lines
9.2 KiB
C#
// ------------------------------------------------------------------------
|
|
// 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.
|
|
// 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.
|
|
// ------------------------------------------------------------------------
|
|
|
|
using System;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Shouldly;
|
|
using Xunit;
|
|
|
|
namespace Dapr.Actors.Description
|
|
{
|
|
public sealed class InterfaceDescriptionTests
|
|
{
|
|
[Fact]
|
|
public void InterfaceDescription_CreateInterfaceDescription()
|
|
{
|
|
// Arrange
|
|
Type type = typeof(ITestActor);
|
|
|
|
// Act
|
|
TestDescription description = new(type);
|
|
|
|
// Assert
|
|
description.ShouldNotBeNull();
|
|
|
|
description.InterfaceType.ShouldBe(type);
|
|
description.Id.ShouldNotBe(0);
|
|
description.V1Id.ShouldBe(0);
|
|
description.Methods.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void InterfaceDescription_CreateCrcIdAndV1Id_WhenUseCrcIdGenerationIsSet()
|
|
{
|
|
// Arrange
|
|
Type type = typeof(ITestActor);
|
|
|
|
// Act
|
|
TestDescription description = new(type, useCRCIdGeneration: true);
|
|
|
|
// Assert
|
|
description.Id.ShouldBe(-934188464);
|
|
description.V1Id.ShouldNotBe(0);
|
|
}
|
|
|
|
[Fact]
|
|
public void InterfaceDescription_CreateThrowsArgumentException_WhenTypeIsGenericDefinition()
|
|
{
|
|
// Arrange
|
|
Type type = typeof(IGenericActor<>);
|
|
|
|
// Act
|
|
Action action = () => { TestDescription _ = new(type); };
|
|
|
|
// Assert
|
|
var exception = Should.Throw<ArgumentException>(action);
|
|
exception.Message.ShouldMatch(@"The actor interface '.*\+IGenericActor`1' is using generics. Generic interfaces cannot be remoted.*");
|
|
exception.ParamName.ShouldBe("actorInterfaceType");
|
|
}
|
|
|
|
[Fact]
|
|
public void InterfaceDescription_CreateThrowsArgumentException_WhenTypeIsGeneric()
|
|
{
|
|
// Arrange
|
|
Type type = typeof(IGenericActor<IActor>);
|
|
|
|
// Act
|
|
Action action = () => { TestDescription _ = new(type); };
|
|
|
|
// Assert
|
|
var exception = Should.Throw<ArgumentException>(action);
|
|
exception.Message.ShouldMatch(@"The actor interface '.*\+IGenericActor`1\[.*IActor.*\]' is using generics. Generic interfaces cannot be remoted.*");
|
|
exception.ParamName.ShouldBe("actorInterfaceType");
|
|
}
|
|
|
|
[Fact]
|
|
public void InterfaceDescription_CreateGeneratesMethodDescriptions_WhenTypeHasTaskMethods_ButDoesNotSeeInheritedMethods()
|
|
{
|
|
// Arrange
|
|
Type type = typeof(IChildActor);
|
|
|
|
// Act
|
|
TestDescription description = new(type);
|
|
|
|
// Assert
|
|
description.Methods.ShouldNotBeNull();
|
|
description.Methods.ShouldBeOfType<MethodDescription[]>();
|
|
description.Methods.Select(m => new {m.Name}).ShouldBe(new[] {new {Name = "GetInt"}});
|
|
}
|
|
|
|
[Fact]
|
|
public void InterfaceDescription_CreateGeneratesMethodDescriptions_WhenTypeHasVoidMethods()
|
|
{
|
|
// Arrange
|
|
Type type = typeof(IVoidActor);
|
|
|
|
// Act
|
|
TestDescription description = new(type, methodReturnCheck: MethodReturnCheck.EnsureReturnsVoid);
|
|
|
|
// Assert
|
|
description.Methods.ShouldNotBeNull();
|
|
description.Methods.ShouldBeOfType<MethodDescription[]>();
|
|
description.Methods.Select(m => new {m.Name}).ShouldBe(new[] {new {Name = "GetString"}, new {Name="MethodWithArguments"}});
|
|
}
|
|
|
|
[Fact]
|
|
public void InterfaceDescription_CreateThrowsArgumentException_WhenMethodsAreNotReturningTask()
|
|
{
|
|
// Arrange
|
|
Type type = typeof(IVoidActor);
|
|
|
|
// Act
|
|
Action action = () =>
|
|
{
|
|
TestDescription _ = new(type);
|
|
};
|
|
|
|
// Assert
|
|
var exception = Should.Throw<ArgumentException>(action);
|
|
exception.Message.ShouldMatch(@"Method 'GetString' of actor interface '.*\+IVoidActor' does not return Task or Task<>. The actor interface methods must be async and must return either Task or Task<>.*");
|
|
exception.ParamName.ShouldBe("actorInterfaceType");
|
|
}
|
|
|
|
[Fact]
|
|
public void InterfaceDescription_CreateThrowsArgumentException_WhenMethodsAreNotReturningVoid()
|
|
{
|
|
// Arrange
|
|
Type type = typeof(IMethodActor);
|
|
|
|
// Act
|
|
Action action = () => { TestDescription _ = new(type, methodReturnCheck: MethodReturnCheck.EnsureReturnsVoid); };
|
|
|
|
// Assert
|
|
var exception = Should.Throw<ArgumentException>(action);
|
|
exception.Message.ShouldMatch(@"Method 'GetString' of actor interface '.*\+IMethodActor' returns '.*\.Task`1\[.*System.String.*\]'.*");
|
|
exception.ParamName.ShouldBe("actorInterfaceType");
|
|
}
|
|
|
|
[Fact]
|
|
public void InterfaceDescription_CreateThrowsArgumentException_WhenMethodsAreOverloaded()
|
|
{
|
|
// Arrange
|
|
Type type = typeof(IOverloadedMethodActor);
|
|
|
|
// Act
|
|
Action action = () => { TestDescription _ = new(type); };
|
|
|
|
// Assert
|
|
var exception = Should.Throw<ArgumentException>(action);
|
|
exception.Message.ShouldMatch(@"Method 'GetString' of actor interface '.*\+IOverloadedMethodActor' is overloaded. The actor interface methods cannot be overloaded.*");
|
|
exception.ParamName.ShouldBe("actorInterfaceType");
|
|
}
|
|
|
|
[Fact]
|
|
public void InterfaceDescription_CreateThrowsArgumentException_WhenMethodIsGeneric()
|
|
{
|
|
// Arrange
|
|
Type type = typeof(IGenericMethodActor);
|
|
|
|
// Act
|
|
Action action = () => { TestDescription _ = new(type); };
|
|
|
|
// Assert
|
|
var exception = Should.Throw<ArgumentException>(action);
|
|
exception.Message.ShouldMatch(@"Method 'Get' of actor interface '.*\+IGenericMethodActor' is using generics. The actor interface methods cannot use generics.*");
|
|
exception.ParamName.ShouldBe("actorInterfaceType");
|
|
}
|
|
|
|
[Fact]
|
|
public void InterfaceDescription_CreateThrowsArgumentException_WhenMethodHasVariableArguments()
|
|
{
|
|
// Arrange
|
|
Type type = typeof(IVariableActor);
|
|
|
|
// Act
|
|
Action action = () => { TestDescription _ = new(type); };
|
|
|
|
// Assert
|
|
var exception = Should.Throw<ArgumentException>(action);
|
|
exception.Message.ShouldMatch(@"Method 'MethodWithVarArgs' of actor interface '.*\+IVariableActor' is using a variable argument list. The actor interface methods cannot have a variable argument list.*");
|
|
exception.ParamName.ShouldBe("actorInterfaceType");
|
|
}
|
|
|
|
internal interface ITestActor : IActor
|
|
{
|
|
}
|
|
|
|
internal interface IGenericActor<T> : IActor
|
|
{
|
|
}
|
|
|
|
internal interface IMethodActor : IActor
|
|
{
|
|
Task<string> GetString();
|
|
|
|
Task MethodWithArguments(int number, bool choice, string information);
|
|
}
|
|
|
|
internal interface IChildActor : IMethodActor
|
|
{
|
|
Task<int> GetInt();
|
|
}
|
|
|
|
internal interface IVariableActor : IActor
|
|
{
|
|
Task MethodWithVarArgs(__arglist);
|
|
}
|
|
|
|
internal interface IVoidActor : IActor
|
|
{
|
|
void GetString();
|
|
|
|
void MethodWithArguments(int number, bool choice, string information);
|
|
}
|
|
|
|
internal interface IOverloadedActor : IMethodActor
|
|
{
|
|
Task<string> GetString(string parameter);
|
|
}
|
|
|
|
internal interface IOverloadedMethodActor : IActor
|
|
{
|
|
Task<string> GetString();
|
|
|
|
Task<string> GetString(string parameter);
|
|
}
|
|
|
|
internal interface IGenericMethodActor : IActor
|
|
{
|
|
Task<T> Get<T>();
|
|
}
|
|
|
|
internal class TestDescription : InterfaceDescription
|
|
{
|
|
public TestDescription(
|
|
Type remotedInterfaceType,
|
|
string remotedInterfaceKindName = "actor",
|
|
bool useCRCIdGeneration = false,
|
|
MethodReturnCheck methodReturnCheck = MethodReturnCheck.EnsureReturnsTask)
|
|
: base(remotedInterfaceKindName, remotedInterfaceType, useCRCIdGeneration, methodReturnCheck)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|