2023-04-14 15:47:27 +02:00
|
|
|
|
using System.Collections.Generic;
|
2023-03-30 15:45:13 +02:00
|
|
|
|
using System.Text;
|
2022-11-21 17:10:48 +01:00
|
|
|
|
using System.Threading;
|
2022-11-21 16:59:09 +01:00
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using FluentAssertions;
|
2023-03-30 15:45:13 +02:00
|
|
|
|
using RabbitMQ.Client;
|
2022-11-21 16:59:09 +01:00
|
|
|
|
using Tapeti.Connection;
|
2022-11-22 13:20:47 +01:00
|
|
|
|
using Tapeti.Default;
|
|
|
|
|
using Tapeti.Exceptions;
|
2022-11-21 16:59:09 +01:00
|
|
|
|
using Tapeti.Tests.Mock;
|
|
|
|
|
using Xunit;
|
|
|
|
|
using Xunit.Abstractions;
|
|
|
|
|
|
|
|
|
|
namespace Tapeti.Tests.Client
|
|
|
|
|
{
|
|
|
|
|
[Collection(RabbitMQCollection.Name)]
|
2022-11-23 09:19:01 +01:00
|
|
|
|
[Trait("Category", "Requires Docker")]
|
2022-11-22 13:20:47 +01:00
|
|
|
|
public class TapetiClientTests : IAsyncLifetime
|
2022-11-21 16:59:09 +01:00
|
|
|
|
{
|
|
|
|
|
private readonly RabbitMQFixture fixture;
|
|
|
|
|
private readonly MockDependencyResolver dependencyResolver = new();
|
|
|
|
|
|
2022-11-23 09:13:38 +01:00
|
|
|
|
private TapetiClient client = null!;
|
2022-11-22 13:20:47 +01:00
|
|
|
|
|
|
|
|
|
|
2022-11-21 16:59:09 +01:00
|
|
|
|
public TapetiClientTests(RabbitMQFixture fixture, ITestOutputHelper testOutputHelper)
|
|
|
|
|
{
|
|
|
|
|
this.fixture = fixture;
|
|
|
|
|
|
|
|
|
|
dependencyResolver.Set<ILogger>(new MockLogger(testOutputHelper));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-11-22 13:20:47 +01:00
|
|
|
|
public Task InitializeAsync()
|
|
|
|
|
{
|
|
|
|
|
client = CreateClient();
|
|
|
|
|
|
|
|
|
|
return Task.CompletedTask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public async Task DisposeAsync()
|
|
|
|
|
{
|
|
|
|
|
await client.Close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-11-21 16:59:09 +01:00
|
|
|
|
[Fact]
|
|
|
|
|
public void Fixture()
|
|
|
|
|
{
|
|
|
|
|
fixture.RabbitMQPort.Should().BeGreaterThan(0);
|
|
|
|
|
fixture.RabbitMQManagementPort.Should().BeGreaterThan(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public async Task DynamicQueueDeclareNoPrefix()
|
|
|
|
|
{
|
|
|
|
|
var queueName = await client.DynamicQueueDeclare(null, null, CancellationToken.None);
|
|
|
|
|
queueName.Should().NotBeNullOrEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[Fact]
|
|
|
|
|
public async Task DynamicQueueDeclarePrefix()
|
|
|
|
|
{
|
|
|
|
|
var queueName = await client.DynamicQueueDeclare("dynamicprefix", null, CancellationToken.None);
|
|
|
|
|
queueName.Should().StartWith("dynamicprefix");
|
2022-11-22 13:20:47 +01:00
|
|
|
|
}
|
2022-11-21 16:59:09 +01:00
|
|
|
|
|
2022-11-22 13:20:47 +01:00
|
|
|
|
|
2023-03-30 15:45:13 +02:00
|
|
|
|
[Fact]
|
|
|
|
|
public async Task DurableQueueDeclareIncompatibleArguments()
|
|
|
|
|
{
|
|
|
|
|
using var rabbitmqClient = CreateRabbitMQClient();
|
|
|
|
|
using var model = rabbitmqClient.CreateModel();
|
|
|
|
|
|
|
|
|
|
var ok = model.QueueDeclare("incompatibleargs", true, false, false, new Dictionary<string, object>
|
|
|
|
|
{
|
|
|
|
|
{ "x-dead-letter-exchange", "d34db33f" }
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
model.Close();
|
|
|
|
|
rabbitmqClient.Close();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ok.Should().NotBeNull();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await client.DurableQueueDeclare("incompatibleargs", new QueueBinding[]
|
|
|
|
|
{
|
|
|
|
|
new("test", "#")
|
|
|
|
|
}, null, CancellationToken.None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-11-22 13:20:47 +01:00
|
|
|
|
[Fact]
|
|
|
|
|
public async Task PublishHandleOverflow()
|
|
|
|
|
{
|
|
|
|
|
var queue1 = await client.DynamicQueueDeclare(null, new RabbitMQArguments
|
|
|
|
|
{
|
|
|
|
|
{ "x-max-length", 5 },
|
|
|
|
|
{ "x-overflow", "reject-publish" }
|
|
|
|
|
}, CancellationToken.None);
|
|
|
|
|
|
|
|
|
|
var queue2 = await client.DynamicQueueDeclare(null, null, CancellationToken.None);
|
|
|
|
|
|
|
|
|
|
var body = Encoding.UTF8.GetBytes("Hello world!");
|
|
|
|
|
var properties = new MessageProperties();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < 5; i++)
|
|
|
|
|
await client.Publish(body, properties, null, queue1, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var publishOverMaxLength = () => client.Publish(body, properties, null, queue1, true);
|
|
|
|
|
await publishOverMaxLength.Should().ThrowAsync<NackException>();
|
|
|
|
|
|
|
|
|
|
// The channel should recover and allow further publishing
|
|
|
|
|
await client.Publish(body, properties, null, queue2, true);
|
2022-11-21 16:59:09 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO test the other methods
|
|
|
|
|
|
2023-03-30 15:45:13 +02:00
|
|
|
|
private RabbitMQ.Client.IConnection CreateRabbitMQClient()
|
|
|
|
|
{
|
|
|
|
|
var connectionFactory = new ConnectionFactory
|
|
|
|
|
{
|
|
|
|
|
HostName = "127.0.0.1",
|
|
|
|
|
Port = fixture.RabbitMQPort,
|
|
|
|
|
UserName = RabbitMQFixture.RabbitMQUsername,
|
|
|
|
|
Password = RabbitMQFixture.RabbitMQPassword,
|
|
|
|
|
AutomaticRecoveryEnabled = false,
|
|
|
|
|
TopologyRecoveryEnabled = false
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return connectionFactory.CreateConnection();
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-21 16:59:09 +01:00
|
|
|
|
|
2022-11-22 13:20:47 +01:00
|
|
|
|
private TapetiClient CreateClient()
|
2022-11-21 16:59:09 +01:00
|
|
|
|
{
|
|
|
|
|
return new TapetiClient(
|
|
|
|
|
new TapetiConfig.Config(dependencyResolver),
|
|
|
|
|
new TapetiConnectionParams
|
|
|
|
|
{
|
|
|
|
|
HostName = "127.0.0.1",
|
|
|
|
|
Port = fixture.RabbitMQPort,
|
|
|
|
|
ManagementPort = fixture.RabbitMQManagementPort,
|
|
|
|
|
Username = RabbitMQFixture.RabbitMQUsername,
|
|
|
|
|
Password = RabbitMQFixture.RabbitMQPassword,
|
|
|
|
|
PrefetchCount = 50
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-23 09:19:01 +01:00
|
|
|
|
}
|