using System; using System.Reflection; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Tgstation.Server.Api.Models; using Tgstation.Server.Host.Configuration; using Tgstation.Server.Host.Jobs; using Tgstation.Server.Host.Models; using Tgstation.Server.Host.System; using Tgstation.Server.Host.Utils; namespace Tgstation.Server.Host.Components.Chat.Providers.Tests { [TestClass] public sealed class TestDiscordProvider { static ChatBot testToken1; static IJobManager mockJobManager; [ClassInitialize] public static void Initialize(TestContext _) { var actualToken = Environment.GetEnvironmentVariable("TGS_TEST_DISCORD_TOKEN"); if (!String.IsNullOrWhiteSpace(actualToken)) testToken1 = new ChatBot { ConnectionString = actualToken, ReconnectionInterval = 1, Instance = new Models.Instance() }; var mockSetup = new Mock(); mockSetup .Setup(x => x.RegisterOperation(It.IsNotNull(), It.IsNotNull(), It.IsAny())) .Callback((job, entrypoint, cancellationToken) => job.StartedBy ??= new User { }) .Returns(ValueTask.CompletedTask); mockSetup .Setup(x => x.WaitForJobCompletion(It.IsNotNull(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(ValueTask.FromResult(true)); mockJobManager = mockSetup.Object; } [TestMethod] public async Task TestConstructionAndDisposal() { var bot = new ChatBot { ConnectionString = "fake_token", ReconnectionInterval = 1, Instance = new Models.Instance(), }; Assert.ThrowsExactly(() => new DiscordProvider(null, null, null, null, null, null)); Assert.ThrowsExactly(() => new DiscordProvider(mockJobManager, null, null, null, null, null)); var mockDel = Mock.Of(); Assert.ThrowsExactly(() => new DiscordProvider(mockJobManager, mockDel, null, null, null, null)); var mockLogger = Mock.Of>(); Assert.ThrowsExactly(() => new DiscordProvider(mockJobManager, mockDel, mockLogger, null, null, null)); var mockAss = Mock.Of(); Assert.ThrowsExactly(() => new DiscordProvider(mockJobManager, mockDel, mockLogger, mockAss, null, null)); var mockGen = Mock.Of>(); Assert.ThrowsExactly(() => new DiscordProvider(mockJobManager, mockDel, mockLogger, mockAss, mockGen, null)); await new DiscordProvider(mockJobManager, mockDel, mockLogger, mockAss, mockGen, bot).DisposeAsync(); } static ValueTask InvokeConnect(IProvider provider, CancellationToken cancellationToken = default) => (ValueTask)provider.GetType().GetMethod("Connect", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(provider, new object[] { cancellationToken }); [TestMethod] public async Task TestConnectWithFakeTokenFails() { var mockLogger = new Mock>(); await using var provider = new DiscordProvider(mockJobManager, Mock.Of(), mockLogger.Object, Mock.Of(), Mock.Of>(), new ChatBot { ReconnectionInterval = 1, ConnectionString = "asdf", Instance = new Models.Instance(), }); await Assert.ThrowsExactlyAsync(async () => await InvokeConnect(provider)); Assert.IsFalse(provider.Connected); } [TestMethod] public async Task TestConnectAndDisconnect() { if (testToken1 == null) Assert.Inconclusive("Required environment variable TGS_TEST_DISCORD_TOKEN isn't set!"); if (!new DiscordConnectionStringBuilder(testToken1.ConnectionString).Valid) Assert.Fail("TGS_TEST_DISCORD_TOKEN is not a valid Discord connection string!"); var mockLogger = new Mock>(); await using var provider = new DiscordProvider(mockJobManager, Mock.Of(), mockLogger.Object, Mock.Of(), Mock.Of>(), testToken1); Assert.IsFalse(provider.Connected); await InvokeConnect(provider); Assert.IsTrue(provider.Connected); await provider.Disconnect(default); Assert.IsFalse(provider.Connected); } } }