// // StatefulInjectorTests.cs // // Copyright (c) František Boháček. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Reflection; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NosSmooth.Core.Client; using NosSmooth.Core.Commands; using NosSmooth.Core.Extensions; using NosSmooth.Core.Packets; using NosSmooth.Core.Stateful; using NosSmooth.Core.Tests.Fakes; using NosSmooth.Core.Tests.Fakes.Commands; using NosSmooth.Core.Tests.Fakes.Packets; using NosSmooth.Core.Tests.Packets; using NosSmooth.Packets.Server.Maps; using NosSmooth.PacketSerializer.Abstractions.Attributes; using NosSmooth.PacketSerializer.Extensions; using NosSmooth.PacketSerializer.Packets; using Remora.Results; using Xunit; namespace NosSmooth.Core.Tests.Stateful; /// /// Tests injecting stateful entities. /// public class StatefulInjectorTests { /// /// Tests that get entity returns the same instance for the same INostaleClient. /// [Fact] public void GetEntity_ReturnsSameEntityForSameClient() { var services = new ServiceCollection() .AddSingleton() .AddSingleton() .AddSingleton() .BuildServiceProvider(); var injector = new StatefulInjector(new StatefulRepository()); var client = services.GetRequiredService(); injector.Client = client; var entity = injector.GetEntity(services, typeof(FakeEntity)); var entity2 = injector.GetEntity(services, typeof(FakeEntity)); Assert.Equal(entity, entity2); } /// /// Tests that get entity returns different instance for different INostaleClient. /// [Fact] public void GetEntity_ReturnsDifferentEntityForDifferentClient() { var services = new ServiceCollection() .AddSingleton() .AddSingleton() .BuildServiceProvider(); var repository = new StatefulRepository(); var injector = new StatefulInjector(repository); var injector2 = new StatefulInjector(repository); var client = new FakeEmptyNostaleClient(); var client2 = new FakeEmptyNostaleClient(); injector.Client = client; injector2.Client = client2; var entity = injector.GetEntity(services, typeof(FakeEntity)); var entity2 = injector2.GetEntity(services, typeof(FakeEntity)); Assert.NotEqual(entity, entity2); } /// /// Tests that extension methods for service provider work correctly with injectable entities, correctly adding pre event to command processor. /// /// A representing the asynchronous unit test. [Fact] public async Task CommandProcessor_PreEvent_InjectsClient() { var client1 = new FakeEmptyNostaleClient(); var client2 = new FakeEmptyNostaleClient(); FakeEntity? entity1 = null; FakeEntity? entity2 = null; var services = new ServiceCollection() .AddSingleton() .AddStatefulInjector() .AddStatefulEntity() .AddSingleton() .AddScoped> (p => { var client = p.GetRequiredService(); var entity = p.GetRequiredService(); return new FakeCommandHandler((c) => { if (c.Input == "1") { Assert.Equal(client1, client); entity1 = entity; } else { Assert.Equal(client2, client); entity2 = entity; } return Result.FromSuccess(); } ); } ) .BuildServiceProvider(); var processor = services.GetRequiredService(); Assert.True((await processor.ProcessCommand(client1, new FakeCommand("1"), default)).IsSuccess); Assert.True((await processor.ProcessCommand(client2, new FakeCommand("2"), default)).IsSuccess); Assert.NotNull(entity1); Assert.NotNull(entity2); Assert.NotEqual(entity1, entity2); } /// /// Tests that extension methods for service provider work correctly with injectable entities, correctly adding pre event to packet handler. /// /// A representing the asynchronous unit test. [Fact] public async Task PacketHandler_PreEvent_InjectsClient() { var client1 = new FakeEmptyNostaleClient(); var client2 = new FakeEmptyNostaleClient(); FakeEntity? entity1 = null; FakeEntity? entity2 = null; var services = new ServiceCollection() .AddSingleton() .AddStatefulInjector() .AddStatefulEntity() .AddSingleton() .AddSingleton(typeof(ILogger<>), typeof(FakeLogger<>)) .AddPacketSerialization() .AddGeneratedSerializers(Assembly.GetExecutingAssembly()) .AddSingleton() .AddScoped> (p => { var client = p.GetRequiredService(); var entity = p.GetRequiredService(); return new FakePacketResponder ((c) => { if (c.Packet.Input == "1") { Assert.Equal(client1, client); entity1 = entity; } else { Assert.Equal(client2, client); entity2 = entity; } return Result.FromSuccess(); } ); } ) .BuildServiceProvider(); var handler = services.GetRequiredService(); services.GetRequiredService().AddPacketType(typeof(FakePacket)); Assert.True((await handler.HandlePacketAsync(client1, PacketSource.Server, "fake 1")).IsSuccess); Assert.True((await handler.HandlePacketAsync(client2, PacketSource.Server, "fake 2")).IsSuccess); Assert.NotNull(entity1); Assert.NotNull(entity2); Assert.NotEqual(entity1, entity2); } }