From 96f2ad1e6df35ae402c0af2125702c9f5c20dad7 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 16:31:15 +0200 Subject: [PATCH 01/33] Update PolicyDefinition.cs --- .../Model/PolicyDefinition.cs | 62 +++++++++++++++---- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs b/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs index dfabe221..3d63f0bb 100644 --- a/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs +++ b/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs @@ -4,6 +4,25 @@ namespace EasyNetQ.Management.Client.Model; public record PolicyDefinition ( + // Queues [All types] + [property: JsonPropertyName("max-length")] + uint? MaxLength = null, + [property: JsonPropertyName("max-length-bytes")] + long? MaxLengthBytes = null, + [property: JsonPropertyName("overflow")] + Overflow? Overflow = null, + [property: JsonPropertyName("expires")] + uint? Expires = null, + [property: JsonPropertyName("dead-letter-exchange")] + string? DeadLetterExchange = null, + [property: JsonPropertyName("dead-letter-routing-key")] + string? DeadLetterRoutingKey = null, + [property: JsonPropertyName("message-ttl")] + uint? MessageTtl = null, + [property: JsonPropertyName("consumer-timeout")] + uint? ConsumerTimeout = null, + + // Queues [Classic] [property: JsonPropertyName("ha-mode")] HaMode? HaMode = null, [property: JsonPropertyName("ha-params")] @@ -12,22 +31,39 @@ public record PolicyDefinition HaSyncMode? HaSyncMode = null, [property: JsonPropertyName("ha-sync-batch-size")] int? HaSyncBatchSize = null, + [property: JsonPropertyName("ha-promote-on-shutdown")] + HaPromote? HaPromoteOnShutdown = null, + [property: JsonPropertyName("ha-promote-on-failure")] + HaPromote? HaPromoteOnFailure = null, + [property: JsonPropertyName("queue-version")] + uint? QueueVersion = null, + [property: JsonPropertyName("queue-master-locator")] + QueueLocator? QueueMasterLocator = null, + + // Queues [Quorum] + [property: JsonPropertyName("delivery-limit")] + uint? DeliveryLimit = null, + [property: JsonPropertyName("dead-letter-strategy")] + DeadLetterStrategy? DeadLetterStrategy = null, + [property: JsonPropertyName("queue-leader-locator")] + QueueLocator? QueueLeaderLocator = null, + + // Streams + [property: JsonPropertyName("max-age")] + string? MaxAge = null, + [property: JsonPropertyName("stream-max-segment-size-bytes")] + uint? StreamMaxSegmentSizeBytes = null, + + // Exchanges + [property: JsonPropertyName("alternate-exchange")] + string? AlternateExchange = null, + + // Federation [property: JsonPropertyName("federation-upstream")] string? FederationUpstream = null, [property: JsonPropertyName("federation-upstream-set")] string? FederationUpstreamSet = null, - [property: JsonPropertyName("alternate-exchange")] - string? AlternateExchange = null, - [property: JsonPropertyName("dead-letter-exchange")] - string? DeadLetterExchange = null, - [property: JsonPropertyName("dead-letter-routing-key")] - string? DeadLetterRoutingKey = null, + [property: JsonPropertyName("queue-mode")] - string? QueueMode = null, - [property: JsonPropertyName("message-ttl")] - uint? MessageTtl = null, - [property: JsonPropertyName("expires")] - uint? Expires = null, - [property: JsonPropertyName("max-length")] - uint? MaxLength = null + string? QueueMode = null ); From 90c185b3c552cdfc2c107264cdd63b04283063e8 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 16:36:11 +0200 Subject: [PATCH 02/33] Create Overflow.cs --- Source/EasyNetQ.Management.Client/Model/Overflow.cs | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Source/EasyNetQ.Management.Client/Model/Overflow.cs diff --git a/Source/EasyNetQ.Management.Client/Model/Overflow.cs b/Source/EasyNetQ.Management.Client/Model/Overflow.cs new file mode 100644 index 00000000..c9911136 --- /dev/null +++ b/Source/EasyNetQ.Management.Client/Model/Overflow.cs @@ -0,0 +1,8 @@ +namespace EasyNetQ.Management.Client.Model; + +public enum Overflow +{ + DropHead, + RejectPublish, + RejectPublishDlx +} From 9a3e7138ca40fbea69d202d3aa286c938944cc6f Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 17:01:11 +0200 Subject: [PATCH 03/33] Update Overflow.cs --- Source/EasyNetQ.Management.Client/Model/Overflow.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/EasyNetQ.Management.Client/Model/Overflow.cs b/Source/EasyNetQ.Management.Client/Model/Overflow.cs index c9911136..d86d5529 100644 --- a/Source/EasyNetQ.Management.Client/Model/Overflow.cs +++ b/Source/EasyNetQ.Management.Client/Model/Overflow.cs @@ -2,7 +2,10 @@ public enum Overflow { + [EnumMember(Value = "drop-head")] DropHead, + [EnumMember(Value = "reject-publish")] RejectPublish, + [EnumMember(Value = "reject-publish-dlx")] RejectPublishDlx } From 11bffc00e61d8965109a351b1e7d8508d2fa5749 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 17:03:39 +0200 Subject: [PATCH 04/33] Update Overflow.cs --- Source/EasyNetQ.Management.Client/Model/Overflow.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/EasyNetQ.Management.Client/Model/Overflow.cs b/Source/EasyNetQ.Management.Client/Model/Overflow.cs index d86d5529..023a783a 100644 --- a/Source/EasyNetQ.Management.Client/Model/Overflow.cs +++ b/Source/EasyNetQ.Management.Client/Model/Overflow.cs @@ -1,4 +1,6 @@ -namespace EasyNetQ.Management.Client.Model; +using System.Runtime.Serialization; + +namespace EasyNetQ.Management.Client.Model; public enum Overflow { From 6f60947c552618580f0d35be321b573c6c337b2f Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 17:07:19 +0200 Subject: [PATCH 05/33] Create HaPromote.cs --- Source/EasyNetQ.Management.Client/Model/HaPromote.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 Source/EasyNetQ.Management.Client/Model/HaPromote.cs diff --git a/Source/EasyNetQ.Management.Client/Model/HaPromote.cs b/Source/EasyNetQ.Management.Client/Model/HaPromote.cs new file mode 100644 index 00000000..59bf0475 --- /dev/null +++ b/Source/EasyNetQ.Management.Client/Model/HaPromote.cs @@ -0,0 +1,11 @@ +using System.Runtime.Serialization; + +namespace EasyNetQ.Management.Client.Model; + +public enum HaPromote +{ + [EnumMember(Value = "when-synced")] + WhenSynced, + [EnumMember(Value = "always")] + Always +} From 9758935aed5551dd328b99572def9c4acfb03171 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 17:09:18 +0200 Subject: [PATCH 06/33] Create QueueLocator.cs --- .../EasyNetQ.Management.Client/Model/QueueLocator.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 Source/EasyNetQ.Management.Client/Model/QueueLocator.cs diff --git a/Source/EasyNetQ.Management.Client/Model/QueueLocator.cs b/Source/EasyNetQ.Management.Client/Model/QueueLocator.cs new file mode 100644 index 00000000..838a0729 --- /dev/null +++ b/Source/EasyNetQ.Management.Client/Model/QueueLocator.cs @@ -0,0 +1,11 @@ +using System.Runtime.Serialization; + +namespace EasyNetQ.Management.Client.Model; + +public enum QueueLocator +{ + [EnumMember(Value = "client-local")] + ClientLocal, + [EnumMember(Value = "balanced")] + Balanced +} From 3c1ddde1a7a0a59640ab2d19f944fc8886ca36a6 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 17:11:16 +0200 Subject: [PATCH 07/33] Create DeadLetterStrategy.cs --- .../Model/DeadLetterStrategy.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 Source/EasyNetQ.Management.Client/Model/DeadLetterStrategy.cs diff --git a/Source/EasyNetQ.Management.Client/Model/DeadLetterStrategy.cs b/Source/EasyNetQ.Management.Client/Model/DeadLetterStrategy.cs new file mode 100644 index 00000000..1eefcf6b --- /dev/null +++ b/Source/EasyNetQ.Management.Client/Model/DeadLetterStrategy.cs @@ -0,0 +1,11 @@ +using System.Runtime.Serialization; + +namespace EasyNetQ.Management.Client.Model; + +public enum DeadLetterStrategy +{ + [EnumMember(Value = "at-most-once")] + AtMostOnce, + [EnumMember(Value = "at-least-once")] + AtLeastOnce +} From 2ca400ba68f168a4d35951824923c63ee025f4b8 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 23:20:08 +0200 Subject: [PATCH 08/33] Update ManagementClientTests.cs --- .../ManagementClientTests.cs | 2669 +++++++++-------- 1 file changed, 1379 insertions(+), 1290 deletions(-) diff --git a/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs b/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs index 98333fbb..848de695 100644 --- a/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs +++ b/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs @@ -1,1292 +1,1381 @@ -using EasyNetQ.Management.Client.Model; - -namespace EasyNetQ.Management.Client.IntegrationTests; - -[Collection("RabbitMQ")] -public class ManagementClientTests -{ - private readonly RabbitMqFixture fixture; - private readonly ITestOutputHelper output; - private static readonly Vhost Vhost = new(Name: "/"); - - public ManagementClientTests(RabbitMqFixture fixture, ITestOutputHelper output) - { - this.fixture = fixture; - this.output = output; - } - - private const string TestExchange = "management_api_test_exchange"; - private const string TestExchange2 = "management_api_test_exchange2"; - private const string TestExchangeTestQueueWithPlusChar = "management_api_test_exchange+plus+test"; - private const string TestQueue = "management_api_test_queue"; - private const string TestQueueWithPlusChar = "management_api_test_queue+plus+test"; - private const string TestUser = "mikey"; - - private async Task CreateExchange(string exchangeName) - { - await fixture.ManagementClient.CreateExchangeAsync(new ExchangeInfo(exchangeName, "direct"), Vhost); - return await fixture.ManagementClient.GetExchangeAsync(Vhost, exchangeName); - } - - private async Task EnsureQueueExists(string managementApiTestQueue) - { - return (await fixture.ManagementClient.GetQueuesAsync()) - .SingleOrDefault(x => x.Name == managementApiTestQueue) - ?? await CreateTestQueue(managementApiTestQueue); - } - - private async Task CreateTestQueue(string queueName) - { - var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - return await CreateTestQueueInVhost(queueName, vhost); - } - - private async Task CreateTestQueueInVhost(string queueName, Vhost vhost) - { - var queueInfo = new QueueInfo(queueName); - await fixture.ManagementClient.CreateQueueAsync(queueInfo, vhost); - return await fixture.ManagementClient.GetQueueAsync(vhost, queueName); - } - - private async Task EnsureExchangeExists(string exchangeName) - { - return (await fixture.ManagementClient.GetExchangesAsync()) - .SingleOrDefault(x => x.Name == exchangeName) ?? await CreateExchange(exchangeName); - } - - private const string TestVHost = "management_test_virtual_host"; - - [Fact] - public async Task Should_be_able_to_change_the_password_of_a_user() - { - var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Monitoring).AddTag(UserTags.Management); - await fixture.ManagementClient.CreateUserAsync(userInfo); - - var user = await fixture.ManagementClient.GetUserAsync(TestUser); - - await fixture.ManagementClient.ChangeUserPasswordAsync(TestUser, "newPassword"); - - var updatedUser = await fixture.ManagementClient.GetUserAsync(TestUser); - updatedUser.Name.Should().Be(user.Name); - updatedUser.Tags.Should().BeEquivalentTo(user.Tags); - updatedUser.PasswordHash.Should().NotBe(user.PasswordHash); - } - - [Fact(Skip = "Requires at least a connection")] - public async Task Should_be_able_to_close_connection() - { - // first get a connection - var connections = await fixture.ManagementClient.GetConnectionsAsync(); - - // then close it - await fixture.ManagementClient.CloseConnectionAsync(connections.First()); - } - - [Fact] - public async Task Should_be_able_to_configure_request() - { - using var client = new ManagementClient( - fixture.Endpoint, fixture.User, fixture.Password, configureHttpRequestMessage: req => req.Headers.Add("x-not-used", "some_value") - ); - - await client.GetOverviewAsync(); - } - - [Fact] - public async Task Should_be_able_to_create_a_queue() - { - await fixture.ManagementClient.CreateQueueAsync(new QueueInfo(TestQueue), Vhost); - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue); - - queue.Name.Should().Be(TestQueue); - } - - [Fact] - public async Task Should_be_able_to_create_a_queue_with_arguments() - { - const string exchangeName = "test-dead-letter-exchange"; - const string argumentKey = "x-dead-letter-exchange"; - var queueInfo = new QueueInfo(Name: $"{TestQueue}1", Arguments: new Dictionary { { argumentKey, exchangeName } }); - - await fixture.ManagementClient.CreateQueueAsync(queueInfo, Vhost); - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, queueInfo.Name); - queue.Arguments[argumentKey].Should().NotBeNull(); - queue.Arguments[argumentKey].Should().Be(exchangeName); - } - - [Fact] - public async Task Should_be_able_to_create_a_queue_with_plus_char_in_the_name() - { - var queueInfo = new QueueInfo(TestQueueWithPlusChar); - - await fixture.ManagementClient.CreateQueueAsync(queueInfo, Vhost); - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueueWithPlusChar); - - queue.Name.Should().Be(TestQueueWithPlusChar); - } - - [Fact] - public async Task Should_be_able_to_check_cluster_alarms() - { - var result = await fixture.ManagementClient.HaveAnyClusterAlarmsAsync(); - result.Should().BeFalse(); - } - - [Fact] - public async Task Should_be_able_to_check_local_alarms() - { - var result = await fixture.ManagementClient.HaveAnyClusterAlarmsAsync(); - result.Should().BeFalse(); - } - - [Fact] - public async Task Should_be_able_to_check_classic_queues_without_synchronised_mirrors() - { - var result = await fixture.ManagementClient.HaveAnyClassicQueuesWithoutSynchronisedMirrorsAsync(); - result.Should().BeFalse(); - } - - [Fact] - public async Task Should_be_able_to_check_quorum_queues_is_critical_state() - { - var result = await fixture.ManagementClient.HaveAnyQuorumQueuesInCriticalStateAsync(); - result.Should().BeFalse(); - } - - [Fact] - public async Task Should_be_able_to_rebalance_queues() - { - await fixture.ManagementClient.RebalanceQueuesAsync(); - } - - [Fact] - public async Task Should_be_able_to_create_a_user() - { - var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Administrator); - - await fixture.ManagementClient.CreateUserAsync(userInfo); - var user = await fixture.ManagementClient.GetUserAsync(TestUser); - - user.Name.Should().Be(TestUser); - user.Tags.Should().Contain(UserTags.Administrator); - } - - [Fact] - public async Task Should_be_able_to_create_a_user_with_password_hash() - { - var testUser = "hash_user"; - // Hash calculated using RabbitMq hash computing algorithm using Sha256 - // See https://www.rabbitmq.com/passwords.html - var passwordHash = "Qlp9Dgrqvx1S1VkuYsoWwgUD2XW2gZLuqQwreE+PAsPZETgo"; //"topSecret" - var userInfo = UserInfo.ByPasswordHash(testUser, passwordHash).AddTag(UserTags.Administrator); - - await fixture.ManagementClient.CreateUserAsync(userInfo); - var user = await fixture.ManagementClient.GetUserAsync(testUser); - - user.Name.Should().Be(testUser); - } - - [Fact] - public async Task Should_be_able_to_create_a_user_with_the_policymaker_tag() - { - var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Policymaker); - - await fixture.ManagementClient.CreateUserAsync(userInfo); - var user = await fixture.ManagementClient.GetUserAsync(TestUser); - - user.Name.Should().Be(TestUser); - } - - [Fact] - public async Task Should_be_able_to_create_a_user_without_password() - { - var testUser = "empty"; - var userInfo = UserInfo.ByPassword(testUser, "").AddTag(UserTags.Administrator); - - await fixture.ManagementClient.CreateUserAsync(userInfo); - var user = await fixture.ManagementClient.GetUserAsync(testUser); - - user.Name.Should().Be(testUser); - } - - [Fact] - public async Task Should_be_able_to_create_all_the_definitions_in_a_policy() - { - const string policyName = "a-sample-all-definitions-in-a-policy"; - const int priority = 999; - const HaMode haMode = HaMode.All; - const HaSyncMode haSyncMode = HaSyncMode.Automatic; - const string alternateExchange = "a-sample-alternate-exchange"; - const string deadLetterExchange = "a-sample-dead-letter-exchange"; - const string deadLetterRoutingKey = "a-sample-dead-letter-exchange-key"; - const uint messageTtl = 5000; - const uint expires = 10000; - const uint maxLength = 500; - - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - HaMode: haMode, - HaSyncMode: haSyncMode, - AlternateExchange: alternateExchange, - DeadLetterExchange: deadLetterExchange, - DeadLetterRoutingKey: deadLetterRoutingKey, - MessageTtl: messageTtl, - Expires: expires, - MaxLength: maxLength - ), - Priority: priority - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Priority == priority - && p.Definition.HaMode == haMode - && p.Definition.HaSyncMode == haSyncMode - && p.Definition.AlternateExchange == alternateExchange - && p.Definition.DeadLetterExchange == deadLetterExchange - && p.Definition.DeadLetterRoutingKey == deadLetterRoutingKey - && p.Definition.MessageTtl == messageTtl - && p.Definition.Expires == expires - && p.Definition.MaxLength == maxLength) - ); - } - - [Fact] - public async Task Should_be_able_to_create_alternate_exchange_policy() - { - const string policyName = "a-sample-alternate-exchange-policy"; - const string alternateExchange = "a-sample-alternate-exchange"; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - AlternateExchange: alternateExchange - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.AlternateExchange == alternateExchange) - ); - } - - [Fact] - public async Task Should_be_able_to_create_an_exchange() - { - var exchange = await CreateExchange(TestExchange); - exchange.Name.Should().Be(TestExchange); - } - - [Fact] - public async Task Should_be_able_to_create_an_exchange_with_plus_char_in_the_name() - { - var exchangeInfo = new ExchangeInfo(TestExchangeTestQueueWithPlusChar, "direct"); - - await fixture.ManagementClient.CreateExchangeAsync(exchangeInfo, Vhost); - var exchange = await fixture.ManagementClient.GetExchangeAsync(Vhost, TestExchangeTestQueueWithPlusChar); - - exchange.Name.Should().Be(TestExchangeTestQueueWithPlusChar); - } - - [Fact] - public async Task Should_be_able_to_create_dead_letter_exchange_policy() - { - const string policyName = "a-sample-dead-letter-exchange"; - const string deadLetterExchange = "a-sample-dead-letter-exchange"; - const string deadLetterRoutingKey = "a-sample-dead-letter-exchange-key"; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - DeadLetterExchange: deadLetterExchange, - DeadLetterRoutingKey: deadLetterRoutingKey - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.DeadLetterExchange == deadLetterExchange - && p.Definition.DeadLetterRoutingKey == deadLetterRoutingKey) - ); - } - - [Fact] - public async Task Should_be_able_to_create_exchanges_only_policies() - { - const string policyName = "asamplepolicy-exchange-only"; - const HaMode haMode = HaMode.All; - const HaSyncMode haSyncMode = HaSyncMode.Automatic; - - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - ApplyTo: ApplyMode.Exchanges, - Definition: new PolicyDefinition( - HaMode: haMode, - HaSyncMode: haSyncMode - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.ApplyTo == ApplyMode.Exchanges - && p.Definition.HaMode == haMode - && p.Definition.HaSyncMode == haSyncMode) - ); - } - - [Fact] - public async Task Should_be_able_to_create_expires_policy() - { - const string policyName = "a-sample-expires"; - const uint expires = 10000; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - Expires: expires - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.Expires == expires) - ); - } - - [Fact] - public async Task Should_be_able_to_create_federation_upstream_policy() - { - const string policyName = "a-sample-federation-upstream-policy"; - - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - FederationUpstream: "my-upstream" - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.FederationUpstream == "my-upstream") - ); - } - - [Fact] - public async Task Should_be_able_to_create_federation_upstream_set_policy() - { - const string policyName = "a-sample-federation-upstream-set-policy"; - - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - FederationUpstreamSet: "my-upstream-set" - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.FederationUpstreamSet == "my-upstream-set") - ); - } - - [Fact] - public async Task Should_be_able_to_create_max_length_policy() - { - const string policyName = "a-sample-max-length"; - const uint maxLength = 500; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - MaxLength: maxLength - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.MaxLength == maxLength) - ); - } - - [Fact] - public async Task Should_be_able_to_create_message_ttl_policy() - { - const string policyName = "a-sample-message-ttl"; - const uint messageTtl = 5000; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - MessageTtl: messageTtl - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.MessageTtl == messageTtl) - ); - } - - [Fact] - public async Task Should_be_able_to_create_federation_upstream_parameter() - { - await fixture.ManagementClient.CreateParameterAsync( - new Parameter - ( - Component: "federation-upstream", - Name: "myfakefederationupstream1", - Vhost: Vhost.Name, - Value: new { Uri = $"amqp://{fixture.User}:{fixture.Password}@{fixture.Endpoint.Host}" } - ) - ); - Assert.Contains(await fixture.ManagementClient.GetParametersAsync(), p => p.Name == "myfakefederationupstream1"); - } - - [Fact] - public async Task Should_be_able_to_create_federation_upstream_parameter_with_extension_method() - { - var amqpUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); - - await fixture.ManagementClient.CreateFederationUpstreamAsync( - vhostName: Vhost.Name, - federationUpstreamName: "myfakefederationupstream-extension", - federationUpstreamDescription: new ParameterFederationValue(amqpUri, Expires: 3600000) - ); - - var parameter = await fixture.ManagementClient.GetFederationUpstreamAsync(Vhost.Name, "myfakefederationupstream-extension"); - Assert.Equal("myfakefederationupstream-extension", parameter.Name); - } - - [Fact] - public async Task Should_be_able_to_create_permissions() - { - var user = (await fixture.ManagementClient.GetUsersAsync()).SingleOrDefault(x => x.Name == TestUser); - if (user == null) - throw new EasyNetQTestException($"user '{TestUser}' hasn't been created"); - - var vhost = (await fixture.ManagementClient.GetVhostsAsync()).SingleOrDefault(x => x.Name == TestVHost); - if (vhost == null) - throw new EasyNetQTestException($"Test vhost: '{TestVHost}' has not been created"); - - var permissionInfo = new PermissionInfo(user.Name); - await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); - } - - [Fact] - public async Task Should_be_able_to_create_permissions_in_default_Vhost() - { - //create user if it does not exists - var user = (await fixture.ManagementClient.GetUsersAsync()).SingleOrDefault(x => x.Name == TestUser) - ?? await fixture.ManagementClient.GetUserAsync(TestUser); - - var vhost = (await fixture.ManagementClient.GetVhostsAsync()).SingleOrDefault(x => x.Name == Vhost.Name); - if (vhost == null) - throw new EasyNetQTestException($"Default vhost: '{TestVHost}' has not been created"); - - var permissionInfo = new PermissionInfo(user.Name); - await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); - } - - [Fact] - public async Task Should_be_able_to_create_policies() - { - const string policyName = "asamplepolicy"; - const HaMode haMode = HaMode.All; - const HaSyncMode haSyncMode = HaSyncMode.Automatic; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - HaMode: haMode, - HaSyncMode: haSyncMode - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.ApplyTo == ApplyMode.All - && p.Definition.HaMode == haMode - && p.Definition.HaSyncMode == haSyncMode) - ); - } - - [Fact] - public async Task Should_be_able_to_create_queues_only_policies() - { - const string policyName = "asamplepolicy-queue-only"; - const HaMode haMode = HaMode.All; - const HaSyncMode haSyncMode = HaSyncMode.Automatic; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - ApplyTo: ApplyMode.Queues, - Definition: new PolicyDefinition( - HaMode: haMode, - HaSyncMode: haSyncMode - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.ApplyTo == ApplyMode.Queues - && p.Definition.HaMode == haMode - && p.Definition.HaSyncMode == haSyncMode) - ); - } - - [Fact] - public async Task Should_be_able_to_delete_a_queue() - { - var queue = await CreateTestQueue(TestQueue); - await fixture.ManagementClient.DeleteQueueAsync(queue); - } - - [Fact] - public async Task Should_be_able_to_delete_a_user() - { - var user = await fixture.ManagementClient.GetUserAsync(TestUser); - await fixture.ManagementClient.DeleteUserAsync(user); - } - - [Fact] - public async Task Should_be_able_to_delete_an_exchange() - { - const string exchangeName = "delete-xcg"; - var exchange = await CreateExchange(exchangeName); - - await fixture.ManagementClient.DeleteExchangeAsync(exchange); - } - - [Fact] - public async Task Should_be_able_to_delete_an_exchange_with_pluses() - { - var exchange = await CreateExchange(TestExchangeTestQueueWithPlusChar); - await fixture.ManagementClient.DeleteExchangeAsync(exchange); - } - - [Fact] - public async Task Should_be_able_to_delete_permissions() - { - var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Monitoring).AddTag(UserTags.Management); - await fixture.ManagementClient.CreateUserAsync(userInfo); - var user = await fixture.ManagementClient.GetUserAsync(TestUser); - await fixture.ManagementClient.CreateVhostAsync(TestVHost); - var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); - var permissionInfo = new PermissionInfo(user.Name); - await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); - - var permission = (await fixture.ManagementClient.GetPermissionsAsync()) - .SingleOrDefault(x => x.User == TestUser && x.Vhost == TestVHost); - - if (permission == null) - throw new EasyNetQTestException($"No permission for vhost: {TestVHost} and user: {TestUser}"); - - await fixture.ManagementClient.DeletePermissionAsync(permission); - } - - [Fact] - public async Task Should_be_able_to_delete_policies() - { - const string policyName = "asamplepolicy"; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - HaMode: HaMode.All, - HaSyncMode: HaSyncMode.Automatic - ) - ) - ); - Assert.Equal( - 1, - (await fixture.ManagementClient.GetPoliciesAsync()).Count(p => p.Name == policyName && p.Vhost == Vhost.Name) - ); - await fixture.ManagementClient.DeletePolicyAsync(Vhost.Name, policyName); - Assert.Equal( - 0, - (await fixture.ManagementClient.GetPoliciesAsync()).Count(p => p.Name == policyName && p.Vhost == Vhost.Name) - ); - } - - [Fact] - public async Task Should_be_able_to_get_a_list_of_bindings_between_an_exchange_and_a_queue() - { - var queue = await EnsureQueueExists(TestQueue); - - var exchange = await EnsureExchangeExists(TestExchange); - - var bindings = (await fixture.ManagementClient.GetQueueBindingsAsync(exchange, queue)).ToArray(); - - bindings.Length.Should().Be(0); - } - - [Fact] - public async Task Should_be_able_to_get_a_list_of_bindings_between_an_exchange_and_an_exchange() - { - var exchange1 = await EnsureExchangeExists(TestExchange); - var exchange2 = await EnsureExchangeExists(TestExchange2); - - var bindings = await fixture.ManagementClient.GetExchangeBindingsAsync(exchange1, exchange2); - - bindings.Count.Should().Be(0); - } - - [Fact] - public async Task Should_be_able_to_get_a_queue_by_name() - { - await CreateTestQueue(TestQueue); - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue); - queue.Name.Should().Be(TestQueue); - } - - [Fact] - public async Task Should_be_able_to_get_a_queue_by_name_with_all_detailed_information() - { - const int age = 10; - const int increment = 1; - await CreateTestQueue(TestQueue); - await Task.Delay(TimeSpan.FromSeconds(10)); - - var queue = await fixture.ManagementClient.GetQueueAsync( - Vhost, - TestQueue, - new LengthsCriteria(age, increment), - new RatesCriteria(age, increment) - ); - - queue.Name.Should().Be(TestQueue); - queue.MessagesDetails.Samples.Count.Should().BeGreaterThan(0); - queue.MessagesReadyDetails.Samples.Count.Should().BeGreaterThan(0); - queue.MessagesUnacknowledgedDetails.Samples.Count.Should().BeGreaterThan(0); - } - - [Fact] - public async Task Should_be_able_to_get_a_queue_by_name_with_detailed_length_information() - { - const int age = 10; - const int increment = 1; - await CreateTestQueue(TestQueue); - await Task.Delay(TimeSpan.FromSeconds(10)); - - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue, new LengthsCriteria(age, increment)); - - queue.Name.Should().Be(TestQueue); - queue.MessagesDetails.Samples.Count.Should().BeGreaterThan(0); - queue.MessagesReadyDetails.Samples.Count.Should().BeGreaterThan(0); - queue.MessagesUnacknowledgedDetails.Samples.Count.Should().BeGreaterThan(0); - } - - [Fact] - public async Task Should_be_able_to_get_a_queue_by_name_with_detailed_rates_information() - { - const int age = 60; - const int increment = 10; - await CreateTestQueue(TestQueue); - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue, ratesCriteria: new RatesCriteria(age, increment)); - queue.Name.Should().Be(TestQueue); - } - - [Fact] - public async Task Should_be_able_to_get_a_queue_by_name_with_plus_char() - { - await CreateTestQueue(TestQueueWithPlusChar); - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueueWithPlusChar); - queue.Name.Should().Be(TestQueueWithPlusChar); - } - - [Fact] - public async Task Should_be_able_to_get_a_user_by_name() - { - var userInfo = UserInfo.ByPassword(TestUser, "topSecret"); - await fixture.ManagementClient.CreateUserAsync(userInfo); - (await fixture.ManagementClient.GetUserAsync(TestUser)).Name.Should().Be(TestUser); - } - - [Fact] - public async Task Should_be_able_to_get_all_the_bindings_for_a_queue() - { - var queue = await CreateTestQueue(TestQueue); - var bindings = await fixture.ManagementClient.GetBindingsForQueueAsync(queue); - Assert.NotEmpty(bindings.ToList()); - } - - [Fact] - public async Task Should_be_able_to_get_an_individual_exchange_by_name() - { - var vhost = new Vhost(Name: Vhost.Name); - var exchange = await fixture.ManagementClient.GetExchangeAsync(vhost, TestExchange); - - exchange.Name.Should().Be(TestExchange); - } - - [Fact] - public async Task Should_be_able_to_get_an_individual_vhost() - { - await fixture.ManagementClient.CreateVhostAsync(TestVHost); - var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); - vhost.Name.Should().Be(TestVHost); - } - - [Fact] - public async Task Should_be_able_to_get_messages_from_a_queue() - { - var queue = await CreateTestQueue(TestQueue); - - var publishInfo = new PublishInfo( - TestQueue, - "Hello World", - PayloadEncoding.String, - new Dictionary - { - { "app_id", "management-test" } - } - ); - - await fixture.ManagementClient.PublishAsync("/", "amq.default", publishInfo); - - var messages = await fixture.ManagementClient.GetMessagesFromQueueAsync(queue, new GetMessagesFromQueueInfo(1, AckMode.AckRequeueFalse)); - foreach (var message in messages) - { - output.WriteLine("message.Payload = {0}", message.Payload); - foreach (var property in message.Properties) - output.WriteLine("key: '{0}', value: '{1}'", property.Key, property.Value); - } - } - - [Fact] - public void Should_be_able_to_get_policies_list() - { - var policies = fixture.ManagementClient.GetPoliciesAsync(); - Assert.NotNull(policies); - } - - [Fact] - public async Task Should_be_able_to_list_parameters() - { - var parameters = await fixture.ManagementClient.GetParametersAsync(); - Assert.NotNull(parameters); - } - - [Fact] - public async Task Should_be_able_to_publish_to_an_exchange() - { - var exchange = await CreateExchange(TestExchange); - - var publishInfo = new PublishInfo(TestQueue, "Hello World"); - var result = await fixture.ManagementClient.PublishAsync(exchange, publishInfo); - - // the testExchange isn't bound to a queue - result.Routed.Should().BeFalse(); - } - - [Fact] - public async Task Should_check_that_the_broker_is_alive() - { - await fixture.ManagementClient.CreateVhostAsync(TestVHost); - var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); - var user = (await fixture.ManagementClient.GetUsersAsync()).Single(x => x.Name == fixture.User); - var permissionInfo = new PermissionInfo(user.Name); - await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); - (await fixture.ManagementClient.IsAliveAsync(vhost)).Should().BeTrue(); - } - - [Fact] - public async Task Should_create_a_virtual_host() - { - await fixture.ManagementClient.CreateVhostAsync(TestVHost); - var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); - vhost.Name.Should().Be(TestVHost); - } - - [Fact] - public async Task Should_create_binding() - { - var queue = await CreateTestQueue(TestQueue); - var exchange = await CreateExchange(TestExchange); - - var bindingInfo = new BindingInfo(RoutingKey: TestQueue); - - await fixture.ManagementClient.CreateQueueBindingAsync(exchange, queue, bindingInfo); - } - - [Fact] - public async Task Should_create_exchange_to_exchange_binding() - { - const string sourceExchangeName = "management_api_test_source_exchange"; - const string destinationExchangeName = "management_api_test_destination_exchange"; - - var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - var sourceExchangeInfo = new ExchangeInfo(sourceExchangeName, "direct"); - var destinationExchangeInfo = new ExchangeInfo(destinationExchangeName, "direct"); - - await fixture.ManagementClient.CreateExchangeAsync(sourceExchangeInfo, vhost); - var sourceExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, sourceExchangeInfo.Name); - - await fixture.ManagementClient.CreateExchangeAsync(destinationExchangeInfo, vhost); - var destinationExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, destinationExchangeInfo.Name); - - await fixture.ManagementClient.CreateExchangeBindingAsync(sourceExchange, destinationExchange, new BindingInfo(RoutingKey: "#")); - - var binding = (await fixture.ManagementClient.GetBindingsWithSourceAsync(sourceExchange))[0]; - - await fixture.ManagementClient.DeleteExchangeAsync(sourceExchange); - await fixture.ManagementClient.DeleteExchangeAsync(destinationExchange); - - Assert.Equal("exchange", binding.DestinationType); - Assert.Equal(destinationExchangeName, binding.Destination); - Assert.Equal("#", binding.RoutingKey); - } - - [Fact] - public async Task Should_delete_a_virtual_host() - { - var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); - await fixture.ManagementClient.DeleteVhostAsync(vhost); - } - - [Fact] - public async Task Should_delete_binding() - { - var sourceXchange = await CreateExchange("sourceXcg"); - var queue = await CreateTestQueue(TestQueue); - var bindingInfo = new BindingInfo(RoutingKey: "#"); - await fixture.ManagementClient.CreateQueueBindingAsync(sourceXchange, queue, bindingInfo); - var binding = (await fixture.ManagementClient.GetQueueBindingsAsync(sourceXchange, queue))[0]; - await fixture.ManagementClient.DeleteBindingAsync(binding); - await fixture.ManagementClient.DeleteExchangeAsync(sourceXchange); - await fixture.ManagementClient.DeleteQueueAsync(queue); - } - - [Fact] - public async Task Should_delete_exchange_to_exchange_binding() - { - const string sourceExchangeName = "management_api_test_source_exchange"; - const string destinationExchangeName = "management_api_test_destination_exchange"; - - var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - var sourceExchangeInfo = new ExchangeInfo(sourceExchangeName, "direct"); - var destinationExchangeInfo = new ExchangeInfo(destinationExchangeName, "direct"); - - await fixture.ManagementClient.CreateExchangeAsync(sourceExchangeInfo, vhost); - var sourceExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, sourceExchangeInfo.Name); - - await fixture.ManagementClient.CreateExchangeAsync(destinationExchangeInfo, vhost); - var destinationExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, destinationExchangeInfo.Name); - - await fixture.ManagementClient.CreateExchangeBindingAsync(sourceExchange, destinationExchange, new BindingInfo(RoutingKey: "#")); - - var binding = (await fixture.ManagementClient.GetExchangeBindingsAsync(sourceExchange, destinationExchange))[0]; - - await fixture.ManagementClient.DeleteBindingAsync(binding); - await fixture.ManagementClient.DeleteExchangeAsync(sourceExchange); - await fixture.ManagementClient.DeleteExchangeAsync(destinationExchange); - } - - [Fact] - public async Task Should_disable_tracing() - { - var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - await fixture.ManagementClient.DisableTracingAsync(vhost); - var vhostAfterUpdate = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - Assert.False(vhostAfterUpdate.Tracing); - } - - [Fact] - public async Task Should_enable_tracing() - { - var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - await fixture.ManagementClient.EnableTracingAsync(vhost); - var vhostAfterUpdate = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - Assert.True(vhostAfterUpdate.Tracing); - } - - [Fact] - public async Task Should_get_all_bindings_for_which_the_exchange_is_the_destination() - { - var sourceXchange = await CreateExchange("sourceXcg"); - var destinationXchange = await CreateExchange("destinationXcg"); - var bindingInfo = new BindingInfo(RoutingKey: "#"); - await fixture.ManagementClient.CreateExchangeBindingAsync(sourceXchange, destinationXchange, bindingInfo); - - Assert.NotEmpty((await fixture.ManagementClient.GetBindingsWithDestinationAsync(destinationXchange)).ToList()); - } - - [Fact] - public async Task Should_get_all_bindings_for_which_the_exchange_is_the_source() - { - var sourceXchange = await CreateExchange("sourceXcg"); - var destinationXchange = await CreateExchange("destinationXcg"); - var bindingInfo = new BindingInfo(RoutingKey: "#"); - await fixture.ManagementClient.CreateExchangeBindingAsync(sourceXchange, destinationXchange, bindingInfo); - Assert.NotEmpty((await fixture.ManagementClient.GetBindingsWithSourceAsync(sourceXchange)).ToList()); - } - - [Fact] - public async Task Should_get_bindings() - { - foreach (var binding in await fixture.ManagementClient.GetBindingsAsync()) - { - output.WriteLine("binding.Destination = {0}", binding.Destination); - output.WriteLine("binding.Source = {0}", binding.Source); - output.WriteLine("binding.PropertiesKey = {0}", binding.PropertiesKey); - } - } - - [Fact(Skip = "Requires at least a consumer")] - public async Task Should_get_consumers() - { - foreach (var consumer in await fixture.ManagementClient.GetConsumersAsync()) - { - output.WriteLine("consumer.ConsumerTag = {0}", consumer.ConsumerTag); - output.WriteLine("consumer.ChannelDetails.ConnectionName = {0}", consumer.ChannelDetails.ConnectionName); - output.WriteLine("consumer.ChannelDetails.ConnectionName = {0}", consumer.ChannelDetails.ConnectionName); - output.WriteLine("consumer.ChannelDetails.Node = {0}", consumer.ChannelDetails.Node); - } - } - - [Fact] - public async Task Should_get_channels() - { - var channels = await fixture.ManagementClient.GetChannelsAsync(); - - foreach (var channel in channels) - { - output.WriteLine("channel.Name = {0}", channel.Name); - output.WriteLine("channel.User = {0}", channel.User); - output.WriteLine("channel.PrefetchCount = {0}", channel.PrefetchCount); - } - } - - [Fact] - public async Task Should_get_channels_per_connection() - { - using var bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=True"); - - await Task.Delay(TimeSpan.FromSeconds(10)); - - await bus.Advanced.ConnectAsync(); - await bus.Advanced.PublishAsync(Topology.Exchange.Default, "#", false, new MessageProperties(), ReadOnlyMemory.Empty); - - await Task.Delay(TimeSpan.FromSeconds(10)); - - var connections = await fixture.ManagementClient.GetConnectionsAsync(); - foreach (var connection in connections) - { - output.WriteLine("connection.Name = {0}", connection.Name); - var channels = await fixture.ManagementClient.GetChannelsAsync(connection); - - foreach (var channel in channels) output.WriteLine("\tchannel.Name = {0}", channel.Name); - } - } - - [Fact] - public async Task Should_get_connections() - { - using var bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=True"); - - await Task.Delay(TimeSpan.FromSeconds(10)); - - await bus.Advanced.ConnectAsync(); - - foreach (var connection in await fixture.ManagementClient.GetConnectionsAsync()) - { - output.WriteLine("Connection.Name: {0}", connection.Name); - output.WriteLine("Connection.ClientProperties: {0}", connection.ClientProperties); - } - } - - [Fact] - public async Task Should_get_definitions() - { - var definitions = await fixture.ManagementClient.GetDefinitionsAsync(); - - definitions.RabbitVersion[0].Should().Be('3'); - } - - [Fact] - public async Task Should_get_exchanges() - { - var exchanges = await fixture.ManagementClient.GetExchangesAsync(); - - foreach (var exchange in exchanges) output.WriteLine("exchange.Name = {0}", exchange.Name); - } - - [Fact] - public async Task Should_get_exchanges_with_pagination() - { - var page = await fixture.ManagementClient.GetExchangesByPageAsync(new PageCriteria(1, 7, "amq")); - - page.Items.Count.Should().BeGreaterThan(0); - } - - [Fact(Skip = "Requires at least an active federation")] - public async Task Should_get_federations() - { - var federations = await fixture.ManagementClient.GetFederationsAsync(); - - federations.Single().Node.Should().Be($"rabbit@{fixture.Endpoint}"); - } - - [Fact] - public async Task Should_get_nodes() - { - var nodes = (await fixture.ManagementClient.GetNodesAsync()).ToList(); - - nodes.Count.Should().NotBe(0); - nodes[0].Name.Should().Be("rabbit@easynetq"); - } - - [Fact] - public async Task Should_get_overview() - { - using var bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=True"); - - await Task.Delay(TimeSpan.FromSeconds(10)); - - await bus.Advanced.ConnectAsync(); - - var overview = await fixture.ManagementClient.GetOverviewAsync(); - - output.WriteLine("overview.ManagementVersion = {0}", overview.ManagementVersion); - foreach (var exchangeType in overview.ExchangeTypes) - output.WriteLine("exchangeType.Name = {0}", exchangeType.Name); - foreach (var listener in overview.Listeners) - output.WriteLine("listener.IpAddress = {0}", listener.IpAddress); - - output.WriteLine("overview.Messages = {0}", overview.QueueTotals?.Messages ?? 0); - - foreach (var context in overview.Contexts) - output.WriteLine("context.Description = {0}", context.Description); - } - - [Fact] - public async Task Should_get_permissions() - { - var permissions = await fixture.ManagementClient.GetPermissionsAsync(); - - foreach (var permission in permissions) - { - output.WriteLine("permission.User = {0}", permission.User); - output.WriteLine("permission.Vhost = {0}", permission.Vhost); - output.WriteLine("permission.Configure = {0}", permission.Configure); - output.WriteLine("permission.Read = {0}", permission.Read); - output.WriteLine("permission.Write = {0}", permission.Write); - } - } - - [Fact] - public async Task Should_get_queues() - { - await CreateTestQueue(TestQueue); - (await fixture.ManagementClient.GetQueuesAsync()).Count.Should().BeGreaterThan(0); - } - - - [Fact] - public async Task Should_get_queues_with_pagination() - { - foreach (var queue in await fixture.ManagementClient.GetQueuesAsync()) - await fixture.ManagementClient.DeleteQueueAsync(queue); - - await CreateTestQueue("1"); - await CreateTestQueue("2"); - - var firstPage = await fixture.ManagementClient.GetQueuesByPageAsync(new PageCriteria(1, 1)); - firstPage.Items.Count.Should().Be(1); - - var secondPage = await fixture.ManagementClient.GetQueuesByPageAsync(new PageCriteria(2, 1)); - secondPage.Items.Count.Should().Be(1); - } - - [Fact] - public async Task Should_get_queues_by_vhost() - { - await fixture.ManagementClient.CreateVhostAsync(TestVHost); - var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); - vhost.Name.Should().Be(TestVHost); - - await CreateTestQueueInVhost($"{TestVHost}_{TestQueue}", vhost); - (await fixture.ManagementClient.GetQueuesAsync(vhost)).Count.Should().BeGreaterThan(0); - } - - [Fact] - public async Task Should_get_users() - { - var users = await fixture.ManagementClient.GetUsersAsync(); - - foreach (var user in users) output.WriteLine("user.Name = {0}", user.Name); - } - - [Fact] - public async Task Should_get_vhosts() - { - var vhosts = await fixture.ManagementClient.GetVhostsAsync(); - - foreach (var vhost in vhosts) output.WriteLine("vhost.Name = {0}", vhost.Name); - } - - [Fact] - public async Task Should_purge_a_queue() - { - var queue = await CreateTestQueue(TestQueue); - await fixture.ManagementClient.PurgeAsync(queue); - } - - [Fact] - public async Task Should_throw_when_trying_to_close_unknown_connection() - { - try - { - await fixture.ManagementClient.CloseConnectionAsync("unknown"); - } - catch (Exception e) - { - Assert.IsType(e); - } - } - - [Fact] - public async Task Should_be_able_to_create_shovel_parameter_on_queue() - { - var srcUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); - var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); - - var shovelName = "queue-shovel"; - - await fixture.ManagementClient.CreateShovelAsync( - vhostName: Vhost.Name, - shovelName, - new ParameterShovelValue - ( - SrcProtocol: AmqpProtocol.AMQP091, - SrcUri: srcUri.ToString(), - SrcQueue: "test-queue-src", - SrcExchange: null, - SrcExchangeKey: null, - SrcDeleteAfter: "never", - DestProtocol: AmqpProtocol.AMQP091, - DestUri: destUri.ToString(), - DestQueue: "test-queue-dest", - DestExchange: null, - AckMode: "on-confirm", - AddForwardHeaders: false - ) - ); - - var parameter = await fixture.ManagementClient.GetShovelAsync(Vhost.Name, shovelName); - - Assert.Equal(shovelName, parameter.Name); - } - - [Fact] - public async Task Should_be_able_to_create_shovel_parameter_on_exchange() - { - var srcUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); +using EasyNetQ.Management.Client.Model; + +namespace EasyNetQ.Management.Client.IntegrationTests; + +[Collection("RabbitMQ")] +public class ManagementClientTests +{ + private readonly RabbitMqFixture fixture; + private readonly ITestOutputHelper output; + private static readonly Vhost Vhost = new(Name: "/"); + + public ManagementClientTests(RabbitMqFixture fixture, ITestOutputHelper output) + { + this.fixture = fixture; + this.output = output; + } + + private const string TestExchange = "management_api_test_exchange"; + private const string TestExchange2 = "management_api_test_exchange2"; + private const string TestExchangeTestQueueWithPlusChar = "management_api_test_exchange+plus+test"; + private const string TestQueue = "management_api_test_queue"; + private const string TestQueueWithPlusChar = "management_api_test_queue+plus+test"; + private const string TestUser = "mikey"; + + private async Task CreateExchange(string exchangeName) + { + await fixture.ManagementClient.CreateExchangeAsync(new ExchangeInfo(exchangeName, "direct"), Vhost); + return await fixture.ManagementClient.GetExchangeAsync(Vhost, exchangeName); + } + + private async Task EnsureQueueExists(string managementApiTestQueue) + { + return (await fixture.ManagementClient.GetQueuesAsync()) + .SingleOrDefault(x => x.Name == managementApiTestQueue) + ?? await CreateTestQueue(managementApiTestQueue); + } + + private async Task CreateTestQueue(string queueName) + { + var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + return await CreateTestQueueInVhost(queueName, vhost); + } + + private async Task CreateTestQueueInVhost(string queueName, Vhost vhost) + { + var queueInfo = new QueueInfo(queueName); + await fixture.ManagementClient.CreateQueueAsync(queueInfo, vhost); + return await fixture.ManagementClient.GetQueueAsync(vhost, queueName); + } + + private async Task EnsureExchangeExists(string exchangeName) + { + return (await fixture.ManagementClient.GetExchangesAsync()) + .SingleOrDefault(x => x.Name == exchangeName) ?? await CreateExchange(exchangeName); + } + + private const string TestVHost = "management_test_virtual_host"; + + [Fact] + public async Task Should_be_able_to_change_the_password_of_a_user() + { + var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Monitoring).AddTag(UserTags.Management); + await fixture.ManagementClient.CreateUserAsync(userInfo); + + var user = await fixture.ManagementClient.GetUserAsync(TestUser); + + await fixture.ManagementClient.ChangeUserPasswordAsync(TestUser, "newPassword"); + + var updatedUser = await fixture.ManagementClient.GetUserAsync(TestUser); + updatedUser.Name.Should().Be(user.Name); + updatedUser.Tags.Should().BeEquivalentTo(user.Tags); + updatedUser.PasswordHash.Should().NotBe(user.PasswordHash); + } + + [Fact(Skip = "Requires at least a connection")] + public async Task Should_be_able_to_close_connection() + { + // first get a connection + var connections = await fixture.ManagementClient.GetConnectionsAsync(); + + // then close it + await fixture.ManagementClient.CloseConnectionAsync(connections.First()); + } + + [Fact] + public async Task Should_be_able_to_configure_request() + { + using var client = new ManagementClient( + fixture.Endpoint, fixture.User, fixture.Password, configureHttpRequestMessage: req => req.Headers.Add("x-not-used", "some_value") + ); + + await client.GetOverviewAsync(); + } + + [Fact] + public async Task Should_be_able_to_create_a_queue() + { + await fixture.ManagementClient.CreateQueueAsync(new QueueInfo(TestQueue), Vhost); + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue); + + queue.Name.Should().Be(TestQueue); + } + + [Fact] + public async Task Should_be_able_to_create_a_queue_with_arguments() + { + const string exchangeName = "test-dead-letter-exchange"; + const string argumentKey = "x-dead-letter-exchange"; + var queueInfo = new QueueInfo(Name: $"{TestQueue}1", Arguments: new Dictionary { { argumentKey, exchangeName } }); + + await fixture.ManagementClient.CreateQueueAsync(queueInfo, Vhost); + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, queueInfo.Name); + queue.Arguments[argumentKey].Should().NotBeNull(); + queue.Arguments[argumentKey].Should().Be(exchangeName); + } + + [Fact] + public async Task Should_be_able_to_create_a_queue_with_plus_char_in_the_name() + { + var queueInfo = new QueueInfo(TestQueueWithPlusChar); + + await fixture.ManagementClient.CreateQueueAsync(queueInfo, Vhost); + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueueWithPlusChar); + + queue.Name.Should().Be(TestQueueWithPlusChar); + } + + [Fact] + public async Task Should_be_able_to_check_cluster_alarms() + { + var result = await fixture.ManagementClient.HaveAnyClusterAlarmsAsync(); + result.Should().BeFalse(); + } + + [Fact] + public async Task Should_be_able_to_check_local_alarms() + { + var result = await fixture.ManagementClient.HaveAnyClusterAlarmsAsync(); + result.Should().BeFalse(); + } + + [Fact] + public async Task Should_be_able_to_check_classic_queues_without_synchronised_mirrors() + { + var result = await fixture.ManagementClient.HaveAnyClassicQueuesWithoutSynchronisedMirrorsAsync(); + result.Should().BeFalse(); + } + + [Fact] + public async Task Should_be_able_to_check_quorum_queues_is_critical_state() + { + var result = await fixture.ManagementClient.HaveAnyQuorumQueuesInCriticalStateAsync(); + result.Should().BeFalse(); + } + + [Fact] + public async Task Should_be_able_to_rebalance_queues() + { + await fixture.ManagementClient.RebalanceQueuesAsync(); + } + + [Fact] + public async Task Should_be_able_to_create_a_user() + { + var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Administrator); + + await fixture.ManagementClient.CreateUserAsync(userInfo); + var user = await fixture.ManagementClient.GetUserAsync(TestUser); + + user.Name.Should().Be(TestUser); + user.Tags.Should().Contain(UserTags.Administrator); + } + + [Fact] + public async Task Should_be_able_to_create_a_user_with_password_hash() + { + var testUser = "hash_user"; + // Hash calculated using RabbitMq hash computing algorithm using Sha256 + // See https://www.rabbitmq.com/passwords.html + var passwordHash = "Qlp9Dgrqvx1S1VkuYsoWwgUD2XW2gZLuqQwreE+PAsPZETgo"; //"topSecret" + var userInfo = UserInfo.ByPasswordHash(testUser, passwordHash).AddTag(UserTags.Administrator); + + await fixture.ManagementClient.CreateUserAsync(userInfo); + var user = await fixture.ManagementClient.GetUserAsync(testUser); + + user.Name.Should().Be(testUser); + } + + [Fact] + public async Task Should_be_able_to_create_a_user_with_the_policymaker_tag() + { + var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Policymaker); + + await fixture.ManagementClient.CreateUserAsync(userInfo); + var user = await fixture.ManagementClient.GetUserAsync(TestUser); + + user.Name.Should().Be(TestUser); + } + + [Fact] + public async Task Should_be_able_to_create_a_user_without_password() + { + var testUser = "empty"; + var userInfo = UserInfo.ByPassword(testUser, "").AddTag(UserTags.Administrator); + + await fixture.ManagementClient.CreateUserAsync(userInfo); + var user = await fixture.ManagementClient.GetUserAsync(testUser); + + user.Name.Should().Be(testUser); + } + + [Fact] + public async Task Should_be_able_to_create_all_the_definitions_in_a_policy() + { + const string policyName = "a-sample-all-definitions-in-a-policy"; + const int priority = 999; + const HaMode haMode = HaMode.All; + const HaSyncMode haSyncMode = HaSyncMode.Automatic; + const HaPromote haPromoteOnFailure = HaPromote.Always; + const HaPromote haPromoteOnShutdown = HaPromote.WhenSynced; + const uint queueVersion = 1; + const QueueLocator queueMasterLocator = QueueLocator.ClientLocal; + const uint deliveryLimit = 3; + const Model.DeadLetterStrategy deadLetterStrategy = Model.DeadLetterStrategy.AtLeastOnce; + const QueueLocator queueLeaderLocator = QueueLocator.Balanced; + const string maxAge = "1h"; + const uint streamMaxSegmentSizeBytes = 50000; + const string alternateExchange = "a-sample-alternate-exchange"; + const string deadLetterExchange = "a-sample-dead-letter-exchange"; + const string deadLetterRoutingKey = "a-sample-dead-letter-exchange-key"; + const uint messageTtl = 5000; + const uint expires = 10000; + const uint maxLength = 500; + const long maxLengthBytes = 5000; + const Overflow overflow = Overflow.RejectPublish; + uint? consumerTimeout = fixture.RabbitmqVersion >= new Version("3.12") ? 3600000 : null; + + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + HaMode: haMode, + HaSyncMode: haSyncMode, + HaPromoteOnFailure: haPromoteOnFailure, + HaPromoteOnShutdown: haPromoteOnShutdown, + QueueVersion: queueVersion, + QueueMasterLocator: queueMasterLocator, + + DeliveryLimit: deliveryLimit, + DeadLetterStrategy: deadLetterStrategy, + QueueLeaderLocator: queueLeaderLocator, + + MaxAge: maxAge, + StreamMaxSegmentSizeBytes: streamMaxSegmentSizeBytes, + + AlternateExchange: alternateExchange, + + DeadLetterExchange: deadLetterExchange, + DeadLetterRoutingKey: deadLetterRoutingKey, + MessageTtl: messageTtl, + Expires: expires, + MaxLength: maxLength, + MaxLengthBytes: maxLengthBytes, + Overflow: overflow, + ConsumerTimeout: consumerTimeout + ), + Priority: priority + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Priority == priority + && p.Definition.HaMode == haMode + && p.Definition.HaSyncMode == haSyncMode + && p.Definition.HaPromoteOnFailure == haPromoteOnFailure + && p.Definition.HaPromoteOnShutdown == haPromoteOnShutdown + && p.Definition.QueueVersion == queueVersion + && p.Definition.QueueMasterLocator == queueMasterLocator + && p.Definition.DeliveryLimit == deliveryLimit + && p.Definition.DeadLetterStrategy == deadLetterStrategy + && p.Definition.QueueLeaderLocator == queueLeaderLocator + && p.Definition.MaxAge == maxAge + && p.Definition.StreamMaxSegmentSizeBytes == streamMaxSegmentSizeBytes + && p.Definition.AlternateExchange == alternateExchange + && p.Definition.DeadLetterExchange == deadLetterExchange + && p.Definition.DeadLetterRoutingKey == deadLetterRoutingKey + && p.Definition.MessageTtl == messageTtl + && p.Definition.Expires == expires + && p.Definition.MaxLength == maxLength + && p.Definition.MaxLengthBytes == maxLengthBytes + && p.Definition.Overflow == overflow + && p.Definition.ConsumerTimeout == consumerTimeout) + ); + } + + [Fact] + public async Task Should_be_able_to_create_alternate_exchange_policy() + { + const string policyName = "a-sample-alternate-exchange-policy"; + const string alternateExchange = "a-sample-alternate-exchange"; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + AlternateExchange: alternateExchange + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.AlternateExchange == alternateExchange) + ); + } + + [Fact] + public async Task Should_be_able_to_create_an_exchange() + { + var exchange = await CreateExchange(TestExchange); + exchange.Name.Should().Be(TestExchange); + } + + [Fact] + public async Task Should_be_able_to_create_an_exchange_with_plus_char_in_the_name() + { + var exchangeInfo = new ExchangeInfo(TestExchangeTestQueueWithPlusChar, "direct"); + + await fixture.ManagementClient.CreateExchangeAsync(exchangeInfo, Vhost); + var exchange = await fixture.ManagementClient.GetExchangeAsync(Vhost, TestExchangeTestQueueWithPlusChar); + + exchange.Name.Should().Be(TestExchangeTestQueueWithPlusChar); + } + + [Fact] + public async Task Should_be_able_to_create_dead_letter_exchange_policy() + { + const string policyName = "a-sample-dead-letter-exchange"; + const string deadLetterExchange = "a-sample-dead-letter-exchange"; + const string deadLetterRoutingKey = "a-sample-dead-letter-exchange-key"; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + DeadLetterExchange: deadLetterExchange, + DeadLetterRoutingKey: deadLetterRoutingKey + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.DeadLetterExchange == deadLetterExchange + && p.Definition.DeadLetterRoutingKey == deadLetterRoutingKey) + ); + } + + [Fact] + public async Task Should_be_able_to_create_exchanges_only_policies() + { + const string policyName = "asamplepolicy-exchange-only"; + const HaMode haMode = HaMode.All; + const HaSyncMode haSyncMode = HaSyncMode.Automatic; + + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + ApplyTo: ApplyMode.Exchanges, + Definition: new PolicyDefinition( + HaMode: haMode, + HaSyncMode: haSyncMode + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.ApplyTo == ApplyMode.Exchanges + && p.Definition.HaMode == haMode + && p.Definition.HaSyncMode == haSyncMode) + ); + } + + [Fact] + public async Task Should_be_able_to_create_expires_policy() + { + const string policyName = "a-sample-expires"; + const uint expires = 10000; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + Expires: expires + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.Expires == expires) + ); + } + + [Fact] + public async Task Should_be_able_to_create_federation_upstream_policy() + { + const string policyName = "a-sample-federation-upstream-policy"; + + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + FederationUpstream: "my-upstream" + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.FederationUpstream == "my-upstream") + ); + } + + [Fact] + public async Task Should_be_able_to_create_federation_upstream_set_policy() + { + const string policyName = "a-sample-federation-upstream-set-policy"; + + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + FederationUpstreamSet: "my-upstream-set" + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.FederationUpstreamSet == "my-upstream-set") + ); + } + + [Fact] + public async Task Should_be_able_to_create_max_length_policy() + { + const string policyName = "a-sample-max-length"; + const uint maxLength = 500; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + MaxLength: maxLength + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.MaxLength == maxLength) + ); + } + + [Fact] + public async Task Should_be_able_to_create_max_length_bytes_policy() + { + const string policyName = "a-sample-max-length-bytes"; + const uint maxLengthBytes = 500; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + MaxLengthBytes: maxLengthBytes + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.MaxLengthBytes == maxLengthBytes) + ); + } + + [Fact] + public async Task Should_be_able_to_create_overflow_policy() + { + foreach (Overflow overflow in Enum.GetValues(typeof(Overflow))) + { + const string policyName = "a-sample-overflow"; + const uint maxLengthBytes = 500; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + MaxLengthBytes: maxLengthBytes, + Overflow: overflow + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.MaxLengthBytes == maxLengthBytes + && p.Definition.Overflow == overflow) + ); + } + } + + [Fact] + public async Task Should_be_able_to_create_message_ttl_policy() + { + const string policyName = "a-sample-message-ttl"; + const uint messageTtl = 5000; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + MessageTtl: messageTtl + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.MessageTtl == messageTtl) + ); + } + + [Fact] + public async Task Should_be_able_to_create_federation_upstream_parameter() + { + await fixture.ManagementClient.CreateParameterAsync( + new Parameter + ( + Component: "federation-upstream", + Name: "myfakefederationupstream1", + Vhost: Vhost.Name, + Value: new { Uri = $"amqp://{fixture.User}:{fixture.Password}@{fixture.Endpoint.Host}" } + ) + ); + Assert.Contains(await fixture.ManagementClient.GetParametersAsync(), p => p.Name == "myfakefederationupstream1"); + } + + [Fact] + public async Task Should_be_able_to_create_federation_upstream_parameter_with_extension_method() + { + var amqpUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); + + await fixture.ManagementClient.CreateFederationUpstreamAsync( + vhostName: Vhost.Name, + federationUpstreamName: "myfakefederationupstream-extension", + federationUpstreamDescription: new ParameterFederationValue(amqpUri, Expires: 3600000) + ); + + var parameter = await fixture.ManagementClient.GetFederationUpstreamAsync(Vhost.Name, "myfakefederationupstream-extension"); + Assert.Equal("myfakefederationupstream-extension", parameter.Name); + } + + [Fact] + public async Task Should_be_able_to_create_permissions() + { + var user = (await fixture.ManagementClient.GetUsersAsync()).SingleOrDefault(x => x.Name == TestUser); + if (user == null) + throw new EasyNetQTestException($"user '{TestUser}' hasn't been created"); + + var vhost = (await fixture.ManagementClient.GetVhostsAsync()).SingleOrDefault(x => x.Name == TestVHost); + if (vhost == null) + throw new EasyNetQTestException($"Test vhost: '{TestVHost}' has not been created"); + + var permissionInfo = new PermissionInfo(user.Name); + await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); + } + + [Fact] + public async Task Should_be_able_to_create_permissions_in_default_Vhost() + { + //create user if it does not exists + var user = (await fixture.ManagementClient.GetUsersAsync()).SingleOrDefault(x => x.Name == TestUser) + ?? await fixture.ManagementClient.GetUserAsync(TestUser); + + var vhost = (await fixture.ManagementClient.GetVhostsAsync()).SingleOrDefault(x => x.Name == Vhost.Name); + if (vhost == null) + throw new EasyNetQTestException($"Default vhost: '{TestVHost}' has not been created"); + + var permissionInfo = new PermissionInfo(user.Name); + await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); + } + + [Fact] + public async Task Should_be_able_to_create_policies() + { + const string policyName = "asamplepolicy"; + const HaMode haMode = HaMode.All; + const HaSyncMode haSyncMode = HaSyncMode.Automatic; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + HaMode: haMode, + HaSyncMode: haSyncMode + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.ApplyTo == ApplyMode.All + && p.Definition.HaMode == haMode + && p.Definition.HaSyncMode == haSyncMode) + ); + } + + [Fact] + public async Task Should_be_able_to_create_queues_only_policies() + { + const string policyName = "asamplepolicy-queue-only"; + const HaMode haMode = HaMode.All; + const HaSyncMode haSyncMode = HaSyncMode.Automatic; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + ApplyTo: ApplyMode.Queues, + Definition: new PolicyDefinition( + HaMode: haMode, + HaSyncMode: haSyncMode + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.ApplyTo == ApplyMode.Queues + && p.Definition.HaMode == haMode + && p.Definition.HaSyncMode == haSyncMode) + ); + } + + [Fact] + public async Task Should_be_able_to_delete_a_queue() + { + var queue = await CreateTestQueue(TestQueue); + await fixture.ManagementClient.DeleteQueueAsync(queue); + } + + [Fact] + public async Task Should_be_able_to_delete_a_user() + { + var user = await fixture.ManagementClient.GetUserAsync(TestUser); + await fixture.ManagementClient.DeleteUserAsync(user); + } + + [Fact] + public async Task Should_be_able_to_delete_an_exchange() + { + const string exchangeName = "delete-xcg"; + var exchange = await CreateExchange(exchangeName); + + await fixture.ManagementClient.DeleteExchangeAsync(exchange); + } + + [Fact] + public async Task Should_be_able_to_delete_an_exchange_with_pluses() + { + var exchange = await CreateExchange(TestExchangeTestQueueWithPlusChar); + await fixture.ManagementClient.DeleteExchangeAsync(exchange); + } + + [Fact] + public async Task Should_be_able_to_delete_permissions() + { + var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Monitoring).AddTag(UserTags.Management); + await fixture.ManagementClient.CreateUserAsync(userInfo); + var user = await fixture.ManagementClient.GetUserAsync(TestUser); + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + var permissionInfo = new PermissionInfo(user.Name); + await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); + + var permission = (await fixture.ManagementClient.GetPermissionsAsync()) + .SingleOrDefault(x => x.User == TestUser && x.Vhost == TestVHost); + + if (permission == null) + throw new EasyNetQTestException($"No permission for vhost: {TestVHost} and user: {TestUser}"); + + await fixture.ManagementClient.DeletePermissionAsync(permission); + } + + [Fact] + public async Task Should_be_able_to_delete_policies() + { + const string policyName = "asamplepolicy"; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + HaMode: HaMode.All, + HaSyncMode: HaSyncMode.Automatic + ) + ) + ); + Assert.Equal( + 1, + (await fixture.ManagementClient.GetPoliciesAsync()).Count(p => p.Name == policyName && p.Vhost == Vhost.Name) + ); + await fixture.ManagementClient.DeletePolicyAsync(Vhost.Name, policyName); + Assert.Equal( + 0, + (await fixture.ManagementClient.GetPoliciesAsync()).Count(p => p.Name == policyName && p.Vhost == Vhost.Name) + ); + } + + [Fact] + public async Task Should_be_able_to_get_a_list_of_bindings_between_an_exchange_and_a_queue() + { + var queue = await EnsureQueueExists(TestQueue); + + var exchange = await EnsureExchangeExists(TestExchange); + + var bindings = (await fixture.ManagementClient.GetQueueBindingsAsync(exchange, queue)).ToArray(); + + bindings.Length.Should().Be(0); + } + + [Fact] + public async Task Should_be_able_to_get_a_list_of_bindings_between_an_exchange_and_an_exchange() + { + var exchange1 = await EnsureExchangeExists(TestExchange); + var exchange2 = await EnsureExchangeExists(TestExchange2); + + var bindings = await fixture.ManagementClient.GetExchangeBindingsAsync(exchange1, exchange2); + + bindings.Count.Should().Be(0); + } + + [Fact] + public async Task Should_be_able_to_get_a_queue_by_name() + { + await CreateTestQueue(TestQueue); + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue); + queue.Name.Should().Be(TestQueue); + } + + [Fact] + public async Task Should_be_able_to_get_a_queue_by_name_with_all_detailed_information() + { + const int age = 10; + const int increment = 1; + await CreateTestQueue(TestQueue); + await Task.Delay(TimeSpan.FromSeconds(10)); + + var queue = await fixture.ManagementClient.GetQueueAsync( + Vhost, + TestQueue, + new LengthsCriteria(age, increment), + new RatesCriteria(age, increment) + ); + + queue.Name.Should().Be(TestQueue); + queue.MessagesDetails.Samples.Count.Should().BeGreaterThan(0); + queue.MessagesReadyDetails.Samples.Count.Should().BeGreaterThan(0); + queue.MessagesUnacknowledgedDetails.Samples.Count.Should().BeGreaterThan(0); + } + + [Fact] + public async Task Should_be_able_to_get_a_queue_by_name_with_detailed_length_information() + { + const int age = 10; + const int increment = 1; + await CreateTestQueue(TestQueue); + await Task.Delay(TimeSpan.FromSeconds(10)); + + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue, new LengthsCriteria(age, increment)); + + queue.Name.Should().Be(TestQueue); + queue.MessagesDetails.Samples.Count.Should().BeGreaterThan(0); + queue.MessagesReadyDetails.Samples.Count.Should().BeGreaterThan(0); + queue.MessagesUnacknowledgedDetails.Samples.Count.Should().BeGreaterThan(0); + } + + [Fact] + public async Task Should_be_able_to_get_a_queue_by_name_with_detailed_rates_information() + { + const int age = 60; + const int increment = 10; + await CreateTestQueue(TestQueue); + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue, ratesCriteria: new RatesCriteria(age, increment)); + queue.Name.Should().Be(TestQueue); + } + + [Fact] + public async Task Should_be_able_to_get_a_queue_by_name_with_plus_char() + { + await CreateTestQueue(TestQueueWithPlusChar); + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueueWithPlusChar); + queue.Name.Should().Be(TestQueueWithPlusChar); + } + + [Fact] + public async Task Should_be_able_to_get_a_user_by_name() + { + var userInfo = UserInfo.ByPassword(TestUser, "topSecret"); + await fixture.ManagementClient.CreateUserAsync(userInfo); + (await fixture.ManagementClient.GetUserAsync(TestUser)).Name.Should().Be(TestUser); + } + + [Fact] + public async Task Should_be_able_to_get_all_the_bindings_for_a_queue() + { + var queue = await CreateTestQueue(TestQueue); + var bindings = await fixture.ManagementClient.GetBindingsForQueueAsync(queue); + Assert.NotEmpty(bindings.ToList()); + } + + [Fact] + public async Task Should_be_able_to_get_an_individual_exchange_by_name() + { + var vhost = new Vhost(Name: Vhost.Name); + var exchange = await fixture.ManagementClient.GetExchangeAsync(vhost, TestExchange); + + exchange.Name.Should().Be(TestExchange); + } + + [Fact] + public async Task Should_be_able_to_get_an_individual_vhost() + { + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + vhost.Name.Should().Be(TestVHost); + } + + [Fact] + public async Task Should_be_able_to_get_messages_from_a_queue() + { + var queue = await CreateTestQueue(TestQueue); + + var publishInfo = new PublishInfo( + TestQueue, + "Hello World", + PayloadEncoding.String, + new Dictionary + { + { "app_id", "management-test" } + } + ); + + await fixture.ManagementClient.PublishAsync("/", "amq.default", publishInfo); + + var messages = await fixture.ManagementClient.GetMessagesFromQueueAsync(queue, new GetMessagesFromQueueInfo(1, AckMode.AckRequeueFalse)); + foreach (var message in messages) + { + output.WriteLine("message.Payload = {0}", message.Payload); + foreach (var property in message.Properties) + output.WriteLine("key: '{0}', value: '{1}'", property.Key, property.Value); + } + } + + [Fact] + public void Should_be_able_to_get_policies_list() + { + var policies = fixture.ManagementClient.GetPoliciesAsync(); + Assert.NotNull(policies); + } + + [Fact] + public async Task Should_be_able_to_list_parameters() + { + var parameters = await fixture.ManagementClient.GetParametersAsync(); + Assert.NotNull(parameters); + } + + [Fact] + public async Task Should_be_able_to_publish_to_an_exchange() + { + var exchange = await CreateExchange(TestExchange); + + var publishInfo = new PublishInfo(TestQueue, "Hello World"); + var result = await fixture.ManagementClient.PublishAsync(exchange, publishInfo); + + // the testExchange isn't bound to a queue + result.Routed.Should().BeFalse(); + } + + [Fact] + public async Task Should_check_that_the_broker_is_alive() + { + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + var user = (await fixture.ManagementClient.GetUsersAsync()).Single(x => x.Name == fixture.User); + var permissionInfo = new PermissionInfo(user.Name); + await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); + (await fixture.ManagementClient.IsAliveAsync(vhost)).Should().BeTrue(); + } + + [Fact] + public async Task Should_create_a_virtual_host() + { + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + vhost.Name.Should().Be(TestVHost); + } + + [Fact] + public async Task Should_create_binding() + { + var queue = await CreateTestQueue(TestQueue); + var exchange = await CreateExchange(TestExchange); + + var bindingInfo = new BindingInfo(RoutingKey: TestQueue); + + await fixture.ManagementClient.CreateQueueBindingAsync(exchange, queue, bindingInfo); + } + + [Fact] + public async Task Should_create_exchange_to_exchange_binding() + { + const string sourceExchangeName = "management_api_test_source_exchange"; + const string destinationExchangeName = "management_api_test_destination_exchange"; + + var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + var sourceExchangeInfo = new ExchangeInfo(sourceExchangeName, "direct"); + var destinationExchangeInfo = new ExchangeInfo(destinationExchangeName, "direct"); + + await fixture.ManagementClient.CreateExchangeAsync(sourceExchangeInfo, vhost); + var sourceExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, sourceExchangeInfo.Name); + + await fixture.ManagementClient.CreateExchangeAsync(destinationExchangeInfo, vhost); + var destinationExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, destinationExchangeInfo.Name); + + await fixture.ManagementClient.CreateExchangeBindingAsync(sourceExchange, destinationExchange, new BindingInfo(RoutingKey: "#")); + + var binding = (await fixture.ManagementClient.GetBindingsWithSourceAsync(sourceExchange))[0]; + + await fixture.ManagementClient.DeleteExchangeAsync(sourceExchange); + await fixture.ManagementClient.DeleteExchangeAsync(destinationExchange); + + Assert.Equal("exchange", binding.DestinationType); + Assert.Equal(destinationExchangeName, binding.Destination); + Assert.Equal("#", binding.RoutingKey); + } + + [Fact] + public async Task Should_delete_a_virtual_host() + { + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + await fixture.ManagementClient.DeleteVhostAsync(vhost); + } + + [Fact] + public async Task Should_delete_binding() + { + var sourceXchange = await CreateExchange("sourceXcg"); + var queue = await CreateTestQueue(TestQueue); + var bindingInfo = new BindingInfo(RoutingKey: "#"); + await fixture.ManagementClient.CreateQueueBindingAsync(sourceXchange, queue, bindingInfo); + var binding = (await fixture.ManagementClient.GetQueueBindingsAsync(sourceXchange, queue))[0]; + await fixture.ManagementClient.DeleteBindingAsync(binding); + await fixture.ManagementClient.DeleteExchangeAsync(sourceXchange); + await fixture.ManagementClient.DeleteQueueAsync(queue); + } + + [Fact] + public async Task Should_delete_exchange_to_exchange_binding() + { + const string sourceExchangeName = "management_api_test_source_exchange"; + const string destinationExchangeName = "management_api_test_destination_exchange"; + + var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + var sourceExchangeInfo = new ExchangeInfo(sourceExchangeName, "direct"); + var destinationExchangeInfo = new ExchangeInfo(destinationExchangeName, "direct"); + + await fixture.ManagementClient.CreateExchangeAsync(sourceExchangeInfo, vhost); + var sourceExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, sourceExchangeInfo.Name); + + await fixture.ManagementClient.CreateExchangeAsync(destinationExchangeInfo, vhost); + var destinationExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, destinationExchangeInfo.Name); + + await fixture.ManagementClient.CreateExchangeBindingAsync(sourceExchange, destinationExchange, new BindingInfo(RoutingKey: "#")); + + var binding = (await fixture.ManagementClient.GetExchangeBindingsAsync(sourceExchange, destinationExchange))[0]; + + await fixture.ManagementClient.DeleteBindingAsync(binding); + await fixture.ManagementClient.DeleteExchangeAsync(sourceExchange); + await fixture.ManagementClient.DeleteExchangeAsync(destinationExchange); + } + + [Fact] + public async Task Should_disable_tracing() + { + var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + await fixture.ManagementClient.DisableTracingAsync(vhost); + var vhostAfterUpdate = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + Assert.False(vhostAfterUpdate.Tracing); + } + + [Fact] + public async Task Should_enable_tracing() + { + var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + await fixture.ManagementClient.EnableTracingAsync(vhost); + var vhostAfterUpdate = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + Assert.True(vhostAfterUpdate.Tracing); + } + + [Fact] + public async Task Should_get_all_bindings_for_which_the_exchange_is_the_destination() + { + var sourceXchange = await CreateExchange("sourceXcg"); + var destinationXchange = await CreateExchange("destinationXcg"); + var bindingInfo = new BindingInfo(RoutingKey: "#"); + await fixture.ManagementClient.CreateExchangeBindingAsync(sourceXchange, destinationXchange, bindingInfo); + + Assert.NotEmpty((await fixture.ManagementClient.GetBindingsWithDestinationAsync(destinationXchange)).ToList()); + } + + [Fact] + public async Task Should_get_all_bindings_for_which_the_exchange_is_the_source() + { + var sourceXchange = await CreateExchange("sourceXcg"); + var destinationXchange = await CreateExchange("destinationXcg"); + var bindingInfo = new BindingInfo(RoutingKey: "#"); + await fixture.ManagementClient.CreateExchangeBindingAsync(sourceXchange, destinationXchange, bindingInfo); + Assert.NotEmpty((await fixture.ManagementClient.GetBindingsWithSourceAsync(sourceXchange)).ToList()); + } + + [Fact] + public async Task Should_get_bindings() + { + foreach (var binding in await fixture.ManagementClient.GetBindingsAsync()) + { + output.WriteLine("binding.Destination = {0}", binding.Destination); + output.WriteLine("binding.Source = {0}", binding.Source); + output.WriteLine("binding.PropertiesKey = {0}", binding.PropertiesKey); + } + } + + [Fact(Skip = "Requires at least a consumer")] + public async Task Should_get_consumers() + { + foreach (var consumer in await fixture.ManagementClient.GetConsumersAsync()) + { + output.WriteLine("consumer.ConsumerTag = {0}", consumer.ConsumerTag); + output.WriteLine("consumer.ChannelDetails.ConnectionName = {0}", consumer.ChannelDetails.ConnectionName); + output.WriteLine("consumer.ChannelDetails.ConnectionName = {0}", consumer.ChannelDetails.ConnectionName); + output.WriteLine("consumer.ChannelDetails.Node = {0}", consumer.ChannelDetails.Node); + } + } + + [Fact] + public async Task Should_get_channels() + { + var channels = await fixture.ManagementClient.GetChannelsAsync(); + + foreach (var channel in channels) + { + output.WriteLine("channel.Name = {0}", channel.Name); + output.WriteLine("channel.User = {0}", channel.User); + output.WriteLine("channel.PrefetchCount = {0}", channel.PrefetchCount); + } + } + + [Fact] + public async Task Should_get_channels_per_connection() + { + using var bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=True"); + + await Task.Delay(TimeSpan.FromSeconds(10)); + + await bus.Advanced.ConnectAsync(); + await bus.Advanced.PublishAsync(Topology.Exchange.Default, "#", false, new MessageProperties(), ReadOnlyMemory.Empty); + + await Task.Delay(TimeSpan.FromSeconds(10)); + + var connections = await fixture.ManagementClient.GetConnectionsAsync(); + foreach (var connection in connections) + { + output.WriteLine("connection.Name = {0}", connection.Name); + var channels = await fixture.ManagementClient.GetChannelsAsync(connection); + + foreach (var channel in channels) output.WriteLine("\tchannel.Name = {0}", channel.Name); + } + } + + [Fact] + public async Task Should_get_connections() + { + using var bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=True"); + + await Task.Delay(TimeSpan.FromSeconds(10)); + + await bus.Advanced.ConnectAsync(); + + foreach (var connection in await fixture.ManagementClient.GetConnectionsAsync()) + { + output.WriteLine("Connection.Name: {0}", connection.Name); + output.WriteLine("Connection.ClientProperties: {0}", connection.ClientProperties); + } + } + + [Fact] + public async Task Should_get_definitions() + { + var definitions = await fixture.ManagementClient.GetDefinitionsAsync(); + + definitions.RabbitVersion[0].Should().Be('3'); + } + + [Fact] + public async Task Should_get_exchanges() + { + var exchanges = await fixture.ManagementClient.GetExchangesAsync(); + + foreach (var exchange in exchanges) output.WriteLine("exchange.Name = {0}", exchange.Name); + } + + [Fact] + public async Task Should_get_exchanges_with_pagination() + { + var page = await fixture.ManagementClient.GetExchangesByPageAsync(new PageCriteria(1, 7, "amq")); + + page.Items.Count.Should().BeGreaterThan(0); + } + + [Fact(Skip = "Requires at least an active federation")] + public async Task Should_get_federations() + { + var federations = await fixture.ManagementClient.GetFederationsAsync(); + + federations.Single().Node.Should().Be($"rabbit@{fixture.Endpoint}"); + } + + [Fact] + public async Task Should_get_nodes() + { + var nodes = (await fixture.ManagementClient.GetNodesAsync()).ToList(); + + nodes.Count.Should().NotBe(0); + nodes[0].Name.Should().Be("rabbit@easynetq"); + } + + [Fact] + public async Task Should_get_overview() + { + using var bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=True"); + + await Task.Delay(TimeSpan.FromSeconds(10)); + + await bus.Advanced.ConnectAsync(); + + var overview = await fixture.ManagementClient.GetOverviewAsync(); + + output.WriteLine("overview.ManagementVersion = {0}", overview.ManagementVersion); + foreach (var exchangeType in overview.ExchangeTypes) + output.WriteLine("exchangeType.Name = {0}", exchangeType.Name); + foreach (var listener in overview.Listeners) + output.WriteLine("listener.IpAddress = {0}", listener.IpAddress); + + output.WriteLine("overview.Messages = {0}", overview.QueueTotals?.Messages ?? 0); + + foreach (var context in overview.Contexts) + output.WriteLine("context.Description = {0}", context.Description); + } + + [Fact] + public async Task Should_get_permissions() + { + var permissions = await fixture.ManagementClient.GetPermissionsAsync(); + + foreach (var permission in permissions) + { + output.WriteLine("permission.User = {0}", permission.User); + output.WriteLine("permission.Vhost = {0}", permission.Vhost); + output.WriteLine("permission.Configure = {0}", permission.Configure); + output.WriteLine("permission.Read = {0}", permission.Read); + output.WriteLine("permission.Write = {0}", permission.Write); + } + } + + [Fact] + public async Task Should_get_queues() + { + await CreateTestQueue(TestQueue); + (await fixture.ManagementClient.GetQueuesAsync()).Count.Should().BeGreaterThan(0); + } + + + [Fact] + public async Task Should_get_queues_with_pagination() + { + foreach (var queue in await fixture.ManagementClient.GetQueuesAsync()) + await fixture.ManagementClient.DeleteQueueAsync(queue); + + await CreateTestQueue("1"); + await CreateTestQueue("2"); + + var firstPage = await fixture.ManagementClient.GetQueuesByPageAsync(new PageCriteria(1, 1)); + firstPage.Items.Count.Should().Be(1); + + var secondPage = await fixture.ManagementClient.GetQueuesByPageAsync(new PageCriteria(2, 1)); + secondPage.Items.Count.Should().Be(1); + } + + [Fact] + public async Task Should_get_queues_by_vhost() + { + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + vhost.Name.Should().Be(TestVHost); + + await CreateTestQueueInVhost($"{TestVHost}_{TestQueue}", vhost); + (await fixture.ManagementClient.GetQueuesAsync(vhost)).Count.Should().BeGreaterThan(0); + } + + [Fact] + public async Task Should_get_users() + { + var users = await fixture.ManagementClient.GetUsersAsync(); + + foreach (var user in users) output.WriteLine("user.Name = {0}", user.Name); + } + + [Fact] + public async Task Should_get_vhosts() + { + var vhosts = await fixture.ManagementClient.GetVhostsAsync(); + + foreach (var vhost in vhosts) output.WriteLine("vhost.Name = {0}", vhost.Name); + } + + [Fact] + public async Task Should_purge_a_queue() + { + var queue = await CreateTestQueue(TestQueue); + await fixture.ManagementClient.PurgeAsync(queue); + } + + [Fact] + public async Task Should_throw_when_trying_to_close_unknown_connection() + { + try + { + await fixture.ManagementClient.CloseConnectionAsync("unknown"); + } + catch (Exception e) + { + Assert.IsType(e); + } + } + + [Fact] + public async Task Should_be_able_to_create_shovel_parameter_on_queue() + { + var srcUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); + var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); + + var shovelName = "queue-shovel"; + + await fixture.ManagementClient.CreateShovelAsync( + vhostName: Vhost.Name, + shovelName, + new ParameterShovelValue + ( + SrcProtocol: AmqpProtocol.AMQP091, + SrcUri: srcUri.ToString(), + SrcQueue: "test-queue-src", + SrcExchange: null, + SrcExchangeKey: null, + SrcDeleteAfter: "never", + DestProtocol: AmqpProtocol.AMQP091, + DestUri: destUri.ToString(), + DestQueue: "test-queue-dest", + DestExchange: null, + AckMode: "on-confirm", + AddForwardHeaders: false + ) + ); + + var parameter = await fixture.ManagementClient.GetShovelAsync(Vhost.Name, shovelName); + + Assert.Equal(shovelName, parameter.Name); + } + + [Fact] + public async Task Should_be_able_to_create_shovel_parameter_on_exchange() + { + var srcUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); + var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); + + var shovelName = "exchange-shovel"; + + await fixture.ManagementClient.CreateShovelAsync( + vhostName: Vhost.Name, + shovelName, + new ParameterShovelValue + ( + SrcProtocol: AmqpProtocol.AMQP091, + SrcUri: srcUri.ToString(), + SrcExchange: "test-exchange-src", + SrcExchangeKey: null, + SrcQueue: null, + SrcDeleteAfter: "never", + DestProtocol: AmqpProtocol.AMQP091, + DestUri: destUri.ToString(), + DestExchange: "test-exchange-dest", + DestQueue: null, + AckMode: "on-confirm", + AddForwardHeaders: false + ) + ); + + var parameters = await fixture.ManagementClient.GetParametersAsync(); + + Assert.Contains(parameters, p => p.Name == shovelName); + } + + [Fact] + public async Task Should_be_able_to_throw_on_non_existant_shovel() + { + await Assert.ThrowsAsync(async () + => await fixture.ManagementClient.GetShovelAsync(Vhost.Name, "non-existant-shovel")); + } + + [Fact] + public async Task Should_be_able_to_get_existant_shovel() + { + var srcUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); - var shovelName = "exchange-shovel"; - - await fixture.ManagementClient.CreateShovelAsync( - vhostName: Vhost.Name, - shovelName, - new ParameterShovelValue - ( - SrcProtocol: AmqpProtocol.AMQP091, - SrcUri: srcUri.ToString(), - SrcExchange: "test-exchange-src", - SrcExchangeKey: null, - SrcQueue: null, - SrcDeleteAfter: "never", - DestProtocol: AmqpProtocol.AMQP091, - DestUri: destUri.ToString(), - DestExchange: "test-exchange-dest", - DestQueue: null, - AckMode: "on-confirm", - AddForwardHeaders: false - ) - ); - - var parameters = await fixture.ManagementClient.GetParametersAsync(); - - Assert.Contains(parameters, p => p.Name == shovelName); - } - - [Fact] - public async Task Should_be_able_to_throw_on_non_existant_shovel() - { - await Assert.ThrowsAsync(async () - => await fixture.ManagementClient.GetShovelAsync(Vhost.Name, "non-existant-shovel")); - } - - [Fact] - public async Task Should_be_able_to_get_existant_shovel() - { - var srcUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); - var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); - - var shovelName = "exchange-shovel"; - - await fixture.ManagementClient.CreateShovelAsync( - vhostName: Vhost.Name, - shovelName: shovelName, - new ParameterShovelValue - ( - SrcProtocol: AmqpProtocol.AMQP091, - SrcUri: srcUri.ToString(), - SrcExchange: "test-exchange-src", - SrcExchangeKey: null, - SrcQueue: null, - SrcDeleteAfter: "never", - DestProtocol: AmqpProtocol.AMQP091, - DestUri: destUri.ToString(), - DestExchange: "test-exchange-dest", - DestQueue: null, - AckMode: "on-confirm", - AddForwardHeaders: false - ) - ); - - var shovel = await fixture.ManagementClient.GetShovelAsync(Vhost.Name, shovelName); - Assert.Contains(shovelName, shovel.Name); - } -} + var shovelName = "exchange-shovel"; + + await fixture.ManagementClient.CreateShovelAsync( + vhostName: Vhost.Name, + shovelName: shovelName, + new ParameterShovelValue + ( + SrcProtocol: AmqpProtocol.AMQP091, + SrcUri: srcUri.ToString(), + SrcExchange: "test-exchange-src", + SrcExchangeKey: null, + SrcQueue: null, + SrcDeleteAfter: "never", + DestProtocol: AmqpProtocol.AMQP091, + DestUri: destUri.ToString(), + DestExchange: "test-exchange-dest", + DestQueue: null, + AckMode: "on-confirm", + AddForwardHeaders: false + ) + ); + + var shovel = await fixture.ManagementClient.GetShovelAsync(Vhost.Name, shovelName); + Assert.Contains(shovelName, shovel.Name); + } +} From 31b2278059269274a9b6463317d6d26b7db39695 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 23:20:41 +0200 Subject: [PATCH 09/33] Update RabbitMQFixture.cs --- .../RabbitMQFixture.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/EasyNetQ.Management.Client.IntegrationTests/RabbitMQFixture.cs b/Source/EasyNetQ.Management.Client.IntegrationTests/RabbitMQFixture.cs index fcbdee47..70a97436 100644 --- a/Source/EasyNetQ.Management.Client.IntegrationTests/RabbitMQFixture.cs +++ b/Source/EasyNetQ.Management.Client.IntegrationTests/RabbitMQFixture.cs @@ -28,6 +28,8 @@ public RabbitMqFixture() public IManagementClient ManagementClient { get; private set; } + public Version RabbitmqVersion { get; private set; } + public async Task InitializeAsync() { using var cts = new CancellationTokenSource(InitializationTimeout); @@ -45,6 +47,9 @@ public async Task InitializeAsync() ManagementClient = new ManagementClient(Endpoint, User, Password); await WaitForRabbitMqReadyAsync(cts.Token); + + var overview = await ManagementClient.GetOverviewAsync(); + RabbitmqVersion = new Version(overview.RabbitmqVersion); } public async Task DisposeAsync() From 494fdf28bebd8d5472577453a4cb38ffa9204978 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 23:21:26 +0200 Subject: [PATCH 10/33] Update PolicyDefinition.cs --- .../Model/PolicyDefinition.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs b/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs index 3d63f0bb..d1c3bc3f 100644 --- a/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs +++ b/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs @@ -1,4 +1,5 @@ -using System.Text.Json.Serialization; +using EasyNetQ.Management.Client.Serialization; +using System.Text.Json.Serialization; namespace EasyNetQ.Management.Client.Model; @@ -9,7 +10,7 @@ public record PolicyDefinition uint? MaxLength = null, [property: JsonPropertyName("max-length-bytes")] long? MaxLengthBytes = null, - [property: JsonPropertyName("overflow")] + [property: JsonPropertyName("overflow"), JsonConverter(typeof(JsonStringEnumConverterEx))] Overflow? Overflow = null, [property: JsonPropertyName("expires")] uint? Expires = null, @@ -31,21 +32,21 @@ public record PolicyDefinition HaSyncMode? HaSyncMode = null, [property: JsonPropertyName("ha-sync-batch-size")] int? HaSyncBatchSize = null, - [property: JsonPropertyName("ha-promote-on-shutdown")] + [property: JsonPropertyName("ha-promote-on-shutdown"), JsonConverter(typeof(JsonStringEnumConverterEx))] HaPromote? HaPromoteOnShutdown = null, - [property: JsonPropertyName("ha-promote-on-failure")] + [property: JsonPropertyName("ha-promote-on-failure"), JsonConverter(typeof(JsonStringEnumConverterEx))] HaPromote? HaPromoteOnFailure = null, [property: JsonPropertyName("queue-version")] uint? QueueVersion = null, - [property: JsonPropertyName("queue-master-locator")] + [property: JsonPropertyName("queue-master-locator"), JsonConverter(typeof(JsonStringEnumConverterEx))] QueueLocator? QueueMasterLocator = null, // Queues [Quorum] [property: JsonPropertyName("delivery-limit")] uint? DeliveryLimit = null, - [property: JsonPropertyName("dead-letter-strategy")] + [property: JsonPropertyName("dead-letter-strategy"), JsonConverter(typeof(JsonStringEnumConverterEx))] DeadLetterStrategy? DeadLetterStrategy = null, - [property: JsonPropertyName("queue-leader-locator")] + [property: JsonPropertyName("queue-leader-locator"), JsonConverter(typeof(JsonStringEnumConverterEx))] QueueLocator? QueueLeaderLocator = null, // Streams From 06232b8d06d6ae28fa8f054f5e2090a5e5f1aa09 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 23:22:58 +0200 Subject: [PATCH 11/33] Create JsonStringEnumConverterEx --- .../Serialization/JsonStringEnumConverterEx | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx diff --git a/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx b/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx new file mode 100644 index 00000000..a4b16289 --- /dev/null +++ b/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx @@ -0,0 +1,55 @@ +using System.Runtime.Serialization; +using System.Text.Json.Serialization; +using System.Text.Json; + +namespace EasyNetQ.Management.Client.Serialization +{ + public class JsonStringEnumConverterEx : JsonConverter where TEnum : struct, System.Enum + { + + private readonly Dictionary _enumToString = new Dictionary(); + private readonly Dictionary _stringToEnum = new Dictionary(); + + public JsonStringEnumConverterEx() + { + var type = typeof(TEnum); + var values = System.Enum.GetValues(type); + + foreach (TEnum value in values) + { + var enumMember = type.GetMember(value.ToString())[0]; + var attr = enumMember.GetCustomAttributes(typeof(EnumMemberAttribute), false) + .Cast() + .FirstOrDefault(); + + if (attr?.Value != null) + { + _enumToString.Add(value, attr.Value); + _stringToEnum.Add(attr.Value, value); + } + else + { + _enumToString.Add(value, value.ToString()); + _stringToEnum.Add(value.ToString(), value); + } + } + } + + public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var stringValue = reader.GetString(); + + if (stringValue != null && _stringToEnum.TryGetValue(stringValue, out var enumValue)) + { + return enumValue; + } + + return default; + } + + public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options) + { + writer.WriteStringValue(_enumToString[value]); + } + } +} From 50286ad359d82866326cc6b24f1d3b6756370959 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 23:27:15 +0200 Subject: [PATCH 12/33] Update ManagementClientTests.cs From d37ba2b85fa723fe8db7a1688dbb47721c5cb5aa Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 23:33:01 +0200 Subject: [PATCH 13/33] Create dsd --- .../dsd | 1381 +++++++++++++++++ 1 file changed, 1381 insertions(+) create mode 100644 Source/EasyNetQ.Management.Client.IntegrationTests/dsd diff --git a/Source/EasyNetQ.Management.Client.IntegrationTests/dsd b/Source/EasyNetQ.Management.Client.IntegrationTests/dsd new file mode 100644 index 00000000..d0354815 --- /dev/null +++ b/Source/EasyNetQ.Management.Client.IntegrationTests/dsd @@ -0,0 +1,1381 @@ +using EasyNetQ.Management.Client.Model; + +namespace EasyNetQ.Management.Client.IntegrationTests; + +[Collection("RabbitMQ")] +public class ManagementClientTests +{ + private readonly RabbitMqFixture fixture; + private readonly ITestOutputHelper output; + private static readonly Vhost Vhost = new(Name: "/"); + + public ManagementClientTests(RabbitMqFixture fixture, ITestOutputHelper output) + { + this.fixture = fixture; + this.output = output; + } + + private const string TestExchange = "management_api_test_exchange"; + private const string TestExchange2 = "management_api_test_exchange2"; + private const string TestExchangeTestQueueWithPlusChar = "management_api_test_exchange+plus+test"; + private const string TestQueue = "management_api_test_queue"; + private const string TestQueueWithPlusChar = "management_api_test_queue+plus+test"; + private const string TestUser = "mikey"; + + private async Task CreateExchange(string exchangeName) + { + await fixture.ManagementClient.CreateExchangeAsync(new ExchangeInfo(exchangeName, "direct"), Vhost); + return await fixture.ManagementClient.GetExchangeAsync(Vhost, exchangeName); + } + + private async Task EnsureQueueExists(string managementApiTestQueue) + { + return (await fixture.ManagementClient.GetQueuesAsync()) + .SingleOrDefault(x => x.Name == managementApiTestQueue) + ?? await CreateTestQueue(managementApiTestQueue); + } + + private async Task CreateTestQueue(string queueName) + { + var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + return await CreateTestQueueInVhost(queueName, vhost); + } + + private async Task CreateTestQueueInVhost(string queueName, Vhost vhost) + { + var queueInfo = new QueueInfo(queueName); + await fixture.ManagementClient.CreateQueueAsync(queueInfo, vhost); + return await fixture.ManagementClient.GetQueueAsync(vhost, queueName); + } + + private async Task EnsureExchangeExists(string exchangeName) + { + return (await fixture.ManagementClient.GetExchangesAsync()) + .SingleOrDefault(x => x.Name == exchangeName) ?? await CreateExchange(exchangeName); + } + + private const string TestVHost = "management_test_virtual_host"; + + [Fact] + public async Task Should_be_able_to_change_the_password_of_a_user() + { + var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Monitoring).AddTag(UserTags.Management); + await fixture.ManagementClient.CreateUserAsync(userInfo); + + var user = await fixture.ManagementClient.GetUserAsync(TestUser); + + await fixture.ManagementClient.ChangeUserPasswordAsync(TestUser, "newPassword"); + + var updatedUser = await fixture.ManagementClient.GetUserAsync(TestUser); + updatedUser.Name.Should().Be(user.Name); + updatedUser.Tags.Should().BeEquivalentTo(user.Tags); + updatedUser.PasswordHash.Should().NotBe(user.PasswordHash); + } + + [Fact(Skip = "Requires at least a connection")] + public async Task Should_be_able_to_close_connection() + { + // first get a connection + var connections = await fixture.ManagementClient.GetConnectionsAsync(); + + // then close it + await fixture.ManagementClient.CloseConnectionAsync(connections.First()); + } + + [Fact] + public async Task Should_be_able_to_configure_request() + { + using var client = new ManagementClient( + fixture.Endpoint, fixture.User, fixture.Password, configureHttpRequestMessage: req => req.Headers.Add("x-not-used", "some_value") + ); + + await client.GetOverviewAsync(); + } + + [Fact] + public async Task Should_be_able_to_create_a_queue() + { + await fixture.ManagementClient.CreateQueueAsync(new QueueInfo(TestQueue), Vhost); + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue); + + queue.Name.Should().Be(TestQueue); + } + + [Fact] + public async Task Should_be_able_to_create_a_queue_with_arguments() + { + const string exchangeName = "test-dead-letter-exchange"; + const string argumentKey = "x-dead-letter-exchange"; + var queueInfo = new QueueInfo(Name: $"{TestQueue}1", Arguments: new Dictionary { { argumentKey, exchangeName } }); + + await fixture.ManagementClient.CreateQueueAsync(queueInfo, Vhost); + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, queueInfo.Name); + queue.Arguments[argumentKey].Should().NotBeNull(); + queue.Arguments[argumentKey].Should().Be(exchangeName); + } + + [Fact] + public async Task Should_be_able_to_create_a_queue_with_plus_char_in_the_name() + { + var queueInfo = new QueueInfo(TestQueueWithPlusChar); + + await fixture.ManagementClient.CreateQueueAsync(queueInfo, Vhost); + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueueWithPlusChar); + + queue.Name.Should().Be(TestQueueWithPlusChar); + } + + [Fact] + public async Task Should_be_able_to_check_cluster_alarms() + { + var result = await fixture.ManagementClient.HaveAnyClusterAlarmsAsync(); + result.Should().BeFalse(); + } + + [Fact] + public async Task Should_be_able_to_check_local_alarms() + { + var result = await fixture.ManagementClient.HaveAnyClusterAlarmsAsync(); + result.Should().BeFalse(); + } + + [Fact] + public async Task Should_be_able_to_check_classic_queues_without_synchronised_mirrors() + { + var result = await fixture.ManagementClient.HaveAnyClassicQueuesWithoutSynchronisedMirrorsAsync(); + result.Should().BeFalse(); + } + + [Fact] + public async Task Should_be_able_to_check_quorum_queues_is_critical_state() + { + var result = await fixture.ManagementClient.HaveAnyQuorumQueuesInCriticalStateAsync(); + result.Should().BeFalse(); + } + + [Fact] + public async Task Should_be_able_to_rebalance_queues() + { + await fixture.ManagementClient.RebalanceQueuesAsync(); + } + + [Fact] + public async Task Should_be_able_to_create_a_user() + { + var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Administrator); + + await fixture.ManagementClient.CreateUserAsync(userInfo); + var user = await fixture.ManagementClient.GetUserAsync(TestUser); + + user.Name.Should().Be(TestUser); + user.Tags.Should().Contain(UserTags.Administrator); + } + + [Fact] + public async Task Should_be_able_to_create_a_user_with_password_hash() + { + var testUser = "hash_user"; + // Hash calculated using RabbitMq hash computing algorithm using Sha256 + // See https://www.rabbitmq.com/passwords.html + var passwordHash = "Qlp9Dgrqvx1S1VkuYsoWwgUD2XW2gZLuqQwreE+PAsPZETgo"; //"topSecret" + var userInfo = UserInfo.ByPasswordHash(testUser, passwordHash).AddTag(UserTags.Administrator); + + await fixture.ManagementClient.CreateUserAsync(userInfo); + var user = await fixture.ManagementClient.GetUserAsync(testUser); + + user.Name.Should().Be(testUser); + } + + [Fact] + public async Task Should_be_able_to_create_a_user_with_the_policymaker_tag() + { + var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Policymaker); + + await fixture.ManagementClient.CreateUserAsync(userInfo); + var user = await fixture.ManagementClient.GetUserAsync(TestUser); + + user.Name.Should().Be(TestUser); + } + + [Fact] + public async Task Should_be_able_to_create_a_user_without_password() + { + var testUser = "empty"; + var userInfo = UserInfo.ByPassword(testUser, "").AddTag(UserTags.Administrator); + + await fixture.ManagementClient.CreateUserAsync(userInfo); + var user = await fixture.ManagementClient.GetUserAsync(testUser); + + user.Name.Should().Be(testUser); + } + + [Fact] + public async Task Should_be_able_to_create_all_the_definitions_in_a_policy() + { + const string policyName = "a-sample-all-definitions-in-a-policy"; + const int priority = 999; + const HaMode haMode = HaMode.All; + const HaSyncMode haSyncMode = HaSyncMode.Automatic; + const HaPromote haPromoteOnFailure = HaPromote.Always; + const HaPromote haPromoteOnShutdown = HaPromote.WhenSynced; + const uint queueVersion = 1; + const QueueLocator queueMasterLocator = QueueLocator.ClientLocal; + const uint deliveryLimit = 3; + const Model.DeadLetterStrategy deadLetterStrategy = Model.DeadLetterStrategy.AtLeastOnce; + const QueueLocator queueLeaderLocator = QueueLocator.Balanced; + const string maxAge = "1h"; + const uint streamMaxSegmentSizeBytes = 50000; + const string alternateExchange = "a-sample-alternate-exchange"; + const string deadLetterExchange = "a-sample-dead-letter-exchange"; + const string deadLetterRoutingKey = "a-sample-dead-letter-exchange-key"; + const uint messageTtl = 5000; + const uint expires = 10000; + const uint maxLength = 500; + const long maxLengthBytes = 5000; + const Overflow overflow = Overflow.RejectPublish; + uint? consumerTimeout = fixture.RabbitmqVersion >= new Version("3.12") ? 3600000 : null; + + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + HaMode: haMode, + HaSyncMode: haSyncMode, + HaPromoteOnFailure: haPromoteOnFailure, + HaPromoteOnShutdown: haPromoteOnShutdown, + QueueVersion: queueVersion, + QueueMasterLocator: queueMasterLocator, + + DeliveryLimit: deliveryLimit, + DeadLetterStrategy: deadLetterStrategy, + QueueLeaderLocator: queueLeaderLocator, + + MaxAge: maxAge, + StreamMaxSegmentSizeBytes: streamMaxSegmentSizeBytes, + + AlternateExchange: alternateExchange, + + DeadLetterExchange: deadLetterExchange, + DeadLetterRoutingKey: deadLetterRoutingKey, + MessageTtl: messageTtl, + Expires: expires, + MaxLength: maxLength, + MaxLengthBytes: maxLengthBytes, + Overflow: overflow, + ConsumerTimeout: consumerTimeout + ), + Priority: priority + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Priority == priority + && p.Definition.HaMode == haMode + && p.Definition.HaSyncMode == haSyncMode + && p.Definition.HaPromoteOnFailure == haPromoteOnFailure + && p.Definition.HaPromoteOnShutdown == haPromoteOnShutdown + && p.Definition.QueueVersion == queueVersion + && p.Definition.QueueMasterLocator == queueMasterLocator + && p.Definition.DeliveryLimit == deliveryLimit + && p.Definition.DeadLetterStrategy == deadLetterStrategy + && p.Definition.QueueLeaderLocator == queueLeaderLocator + && p.Definition.MaxAge == maxAge + && p.Definition.StreamMaxSegmentSizeBytes == streamMaxSegmentSizeBytes + && p.Definition.AlternateExchange == alternateExchange + && p.Definition.DeadLetterExchange == deadLetterExchange + && p.Definition.DeadLetterRoutingKey == deadLetterRoutingKey + && p.Definition.MessageTtl == messageTtl + && p.Definition.Expires == expires + && p.Definition.MaxLength == maxLength + && p.Definition.MaxLengthBytes == maxLengthBytes + && p.Definition.Overflow == overflow + && p.Definition.ConsumerTimeout == consumerTimeout) + ); + } + + [Fact] + public async Task Should_be_able_to_create_alternate_exchange_policy() + { + const string policyName = "a-sample-alternate-exchange-policy"; + const string alternateExchange = "a-sample-alternate-exchange"; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + AlternateExchange: alternateExchange + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.AlternateExchange == alternateExchange) + ); + } + + [Fact] + public async Task Should_be_able_to_create_an_exchange() + { + var exchange = await CreateExchange(TestExchange); + exchange.Name.Should().Be(TestExchange); + } + + [Fact] + public async Task Should_be_able_to_create_an_exchange_with_plus_char_in_the_name() + { + var exchangeInfo = new ExchangeInfo(TestExchangeTestQueueWithPlusChar, "direct"); + + await fixture.ManagementClient.CreateExchangeAsync(exchangeInfo, Vhost); + var exchange = await fixture.ManagementClient.GetExchangeAsync(Vhost, TestExchangeTestQueueWithPlusChar); + + exchange.Name.Should().Be(TestExchangeTestQueueWithPlusChar); + } + + [Fact] + public async Task Should_be_able_to_create_dead_letter_exchange_policy() + { + const string policyName = "a-sample-dead-letter-exchange"; + const string deadLetterExchange = "a-sample-dead-letter-exchange"; + const string deadLetterRoutingKey = "a-sample-dead-letter-exchange-key"; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + DeadLetterExchange: deadLetterExchange, + DeadLetterRoutingKey: deadLetterRoutingKey + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.DeadLetterExchange == deadLetterExchange + && p.Definition.DeadLetterRoutingKey == deadLetterRoutingKey) + ); + } + + [Fact] + public async Task Should_be_able_to_create_exchanges_only_policies() + { + const string policyName = "asamplepolicy-exchange-only"; + const HaMode haMode = HaMode.All; + const HaSyncMode haSyncMode = HaSyncMode.Automatic; + + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + ApplyTo: ApplyMode.Exchanges, + Definition: new PolicyDefinition( + HaMode: haMode, + HaSyncMode: haSyncMode + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.ApplyTo == ApplyMode.Exchanges + && p.Definition.HaMode == haMode + && p.Definition.HaSyncMode == haSyncMode) + ); + } + + [Fact] + public async Task Should_be_able_to_create_expires_policy() + { + const string policyName = "a-sample-expires"; + const uint expires = 10000; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + Expires: expires + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.Expires == expires) + ); + } + + [Fact] + public async Task Should_be_able_to_create_federation_upstream_policy() + { + const string policyName = "a-sample-federation-upstream-policy"; + + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + FederationUpstream: "my-upstream" + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.FederationUpstream == "my-upstream") + ); + } + + [Fact] + public async Task Should_be_able_to_create_federation_upstream_set_policy() + { + const string policyName = "a-sample-federation-upstream-set-policy"; + + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + FederationUpstreamSet: "my-upstream-set" + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.FederationUpstreamSet == "my-upstream-set") + ); + } + + [Fact] + public async Task Should_be_able_to_create_max_length_policy() + { + const string policyName = "a-sample-max-length"; + const uint maxLength = 500; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + MaxLength: maxLength + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.MaxLength == maxLength) + ); + } + + [Fact] + public async Task Should_be_able_to_create_max_length_bytes_policy() + { + const string policyName = "a-sample-max-length-bytes"; + const uint maxLengthBytes = 500; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + MaxLengthBytes: maxLengthBytes + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.MaxLengthBytes == maxLengthBytes) + ); + } + + [Fact] + public async Task Should_be_able_to_create_overflow_policy() + { + foreach (Overflow overflow in Enum.GetValues(typeof(Overflow))) + { + const string policyName = "a-sample-overflow"; + const uint maxLengthBytes = 500; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + MaxLengthBytes: maxLengthBytes, + Overflow: overflow + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.MaxLengthBytes == maxLengthBytes + && p.Definition.Overflow == overflow) + ); + } + } + + [Fact] + public async Task Should_be_able_to_create_message_ttl_policy() + { + const string policyName = "a-sample-message-ttl"; + const uint messageTtl = 5000; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + MessageTtl: messageTtl + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.Definition.MessageTtl == messageTtl) + ); + } + + [Fact] + public async Task Should_be_able_to_create_federation_upstream_parameter() + { + await fixture.ManagementClient.CreateParameterAsync( + new Parameter + ( + Component: "federation-upstream", + Name: "myfakefederationupstream1", + Vhost: Vhost.Name, + Value: new { Uri = $"amqp://{fixture.User}:{fixture.Password}@{fixture.Endpoint.Host}" } + ) + ); + Assert.Contains(await fixture.ManagementClient.GetParametersAsync(), p => p.Name == "myfakefederationupstream1"); + } + + [Fact] + public async Task Should_be_able_to_create_federation_upstream_parameter_with_extension_method() + { + var amqpUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); + + await fixture.ManagementClient.CreateFederationUpstreamAsync( + vhostName: Vhost.Name, + federationUpstreamName: "myfakefederationupstream-extension", + federationUpstreamDescription: new ParameterFederationValue(amqpUri, Expires: 3600000) + ); + + var parameter = await fixture.ManagementClient.GetFederationUpstreamAsync(Vhost.Name, "myfakefederationupstream-extension"); + Assert.Equal("myfakefederationupstream-extension", parameter.Name); + } + + [Fact] + public async Task Should_be_able_to_create_permissions() + { + var user = (await fixture.ManagementClient.GetUsersAsync()).SingleOrDefault(x => x.Name == TestUser); + if (user == null) + throw new EasyNetQTestException($"user '{TestUser}' hasn't been created"); + + var vhost = (await fixture.ManagementClient.GetVhostsAsync()).SingleOrDefault(x => x.Name == TestVHost); + if (vhost == null) + throw new EasyNetQTestException($"Test vhost: '{TestVHost}' has not been created"); + + var permissionInfo = new PermissionInfo(user.Name); + await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); + } + + [Fact] + public async Task Should_be_able_to_create_permissions_in_default_Vhost() + { + //create user if it does not exists + var user = (await fixture.ManagementClient.GetUsersAsync()).SingleOrDefault(x => x.Name == TestUser) + ?? await fixture.ManagementClient.GetUserAsync(TestUser); + + var vhost = (await fixture.ManagementClient.GetVhostsAsync()).SingleOrDefault(x => x.Name == Vhost.Name); + if (vhost == null) + throw new EasyNetQTestException($"Default vhost: '{TestVHost}' has not been created"); + + var permissionInfo = new PermissionInfo(user.Name); + await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); + } + + [Fact] + public async Task Should_be_able_to_create_policies() + { + const string policyName = "asamplepolicy"; + const HaMode haMode = HaMode.All; + const HaSyncMode haSyncMode = HaSyncMode.Automatic; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + HaMode: haMode, + HaSyncMode: haSyncMode + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.ApplyTo == ApplyMode.All + && p.Definition.HaMode == haMode + && p.Definition.HaSyncMode == haSyncMode) + ); + } + + [Fact] + public async Task Should_be_able_to_create_queues_only_policies() + { + const string policyName = "asamplepolicy-queue-only"; + const HaMode haMode = HaMode.All; + const HaSyncMode haSyncMode = HaSyncMode.Automatic; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + ApplyTo: ApplyMode.Queues, + Definition: new PolicyDefinition( + HaMode: haMode, + HaSyncMode: haSyncMode + ) + ) + ); + Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( + p => p.Name == policyName + && p.Vhost == Vhost.Name + && p.ApplyTo == ApplyMode.Queues + && p.Definition.HaMode == haMode + && p.Definition.HaSyncMode == haSyncMode) + ); + } + + [Fact] + public async Task Should_be_able_to_delete_a_queue() + { + var queue = await CreateTestQueue(TestQueue); + await fixture.ManagementClient.DeleteQueueAsync(queue); + } + + [Fact] + public async Task Should_be_able_to_delete_a_user() + { + var user = await fixture.ManagementClient.GetUserAsync(TestUser); + await fixture.ManagementClient.DeleteUserAsync(user); + } + + [Fact] + public async Task Should_be_able_to_delete_an_exchange() + { + const string exchangeName = "delete-xcg"; + var exchange = await CreateExchange(exchangeName); + + await fixture.ManagementClient.DeleteExchangeAsync(exchange); + } + + [Fact] + public async Task Should_be_able_to_delete_an_exchange_with_pluses() + { + var exchange = await CreateExchange(TestExchangeTestQueueWithPlusChar); + await fixture.ManagementClient.DeleteExchangeAsync(exchange); + } + + [Fact] + public async Task Should_be_able_to_delete_permissions() + { + var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Monitoring).AddTag(UserTags.Management); + await fixture.ManagementClient.CreateUserAsync(userInfo); + var user = await fixture.ManagementClient.GetUserAsync(TestUser); + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + var permissionInfo = new PermissionInfo(user.Name); + await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); + + var permission = (await fixture.ManagementClient.GetPermissionsAsync()) + .SingleOrDefault(x => x.User == TestUser && x.Vhost == TestVHost); + + if (permission == null) + throw new EasyNetQTestException($"No permission for vhost: {TestVHost} and user: {TestUser}"); + + await fixture.ManagementClient.DeletePermissionAsync(permission); + } + + [Fact] + public async Task Should_be_able_to_delete_policies() + { + const string policyName = "asamplepolicy"; + await fixture.ManagementClient.CreatePolicyAsync( + new Policy( + Name: policyName, + Pattern: "averyuncommonpattern", + Vhost: Vhost.Name, + Definition: new PolicyDefinition( + HaMode: HaMode.All, + HaSyncMode: HaSyncMode.Automatic + ) + ) + ); + Assert.Equal( + 1, + (await fixture.ManagementClient.GetPoliciesAsync()).Count(p => p.Name == policyName && p.Vhost == Vhost.Name) + ); + await fixture.ManagementClient.DeletePolicyAsync(Vhost.Name, policyName); + Assert.Equal( + 0, + (await fixture.ManagementClient.GetPoliciesAsync()).Count(p => p.Name == policyName && p.Vhost == Vhost.Name) + ); + } + + [Fact] + public async Task Should_be_able_to_get_a_list_of_bindings_between_an_exchange_and_a_queue() + { + var queue = await EnsureQueueExists(TestQueue); + + var exchange = await EnsureExchangeExists(TestExchange); + + var bindings = (await fixture.ManagementClient.GetQueueBindingsAsync(exchange, queue)).ToArray(); + + bindings.Length.Should().Be(0); + } + + [Fact] + public async Task Should_be_able_to_get_a_list_of_bindings_between_an_exchange_and_an_exchange() + { + var exchange1 = await EnsureExchangeExists(TestExchange); + var exchange2 = await EnsureExchangeExists(TestExchange2); + + var bindings = await fixture.ManagementClient.GetExchangeBindingsAsync(exchange1, exchange2); + + bindings.Count.Should().Be(0); + } + + [Fact] + public async Task Should_be_able_to_get_a_queue_by_name() + { + await CreateTestQueue(TestQueue); + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue); + queue.Name.Should().Be(TestQueue); + } + + [Fact] + public async Task Should_be_able_to_get_a_queue_by_name_with_all_detailed_information() + { + const int age = 10; + const int increment = 1; + await CreateTestQueue(TestQueue); + await Task.Delay(TimeSpan.FromSeconds(10)); + + var queue = await fixture.ManagementClient.GetQueueAsync( + Vhost, + TestQueue, + new LengthsCriteria(age, increment), + new RatesCriteria(age, increment) + ); + + queue.Name.Should().Be(TestQueue); + queue.MessagesDetails.Samples.Count.Should().BeGreaterThan(0); + queue.MessagesReadyDetails.Samples.Count.Should().BeGreaterThan(0); + queue.MessagesUnacknowledgedDetails.Samples.Count.Should().BeGreaterThan(0); + } + + [Fact] + public async Task Should_be_able_to_get_a_queue_by_name_with_detailed_length_information() + { + const int age = 10; + const int increment = 1; + await CreateTestQueue(TestQueue); + await Task.Delay(TimeSpan.FromSeconds(10)); + + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue, new LengthsCriteria(age, increment)); + + queue.Name.Should().Be(TestQueue); + queue.MessagesDetails.Samples.Count.Should().BeGreaterThan(0); + queue.MessagesReadyDetails.Samples.Count.Should().BeGreaterThan(0); + queue.MessagesUnacknowledgedDetails.Samples.Count.Should().BeGreaterThan(0); + } + + [Fact] + public async Task Should_be_able_to_get_a_queue_by_name_with_detailed_rates_information() + { + const int age = 60; + const int increment = 10; + await CreateTestQueue(TestQueue); + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue, ratesCriteria: new RatesCriteria(age, increment)); + queue.Name.Should().Be(TestQueue); + } + + [Fact] + public async Task Should_be_able_to_get_a_queue_by_name_with_plus_char() + { + await CreateTestQueue(TestQueueWithPlusChar); + var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueueWithPlusChar); + queue.Name.Should().Be(TestQueueWithPlusChar); + } + + [Fact] + public async Task Should_be_able_to_get_a_user_by_name() + { + var userInfo = UserInfo.ByPassword(TestUser, "topSecret"); + await fixture.ManagementClient.CreateUserAsync(userInfo); + (await fixture.ManagementClient.GetUserAsync(TestUser)).Name.Should().Be(TestUser); + } + + [Fact] + public async Task Should_be_able_to_get_all_the_bindings_for_a_queue() + { + var queue = await CreateTestQueue(TestQueue); + var bindings = await fixture.ManagementClient.GetBindingsForQueueAsync(queue); + Assert.NotEmpty(bindings.ToList()); + } + + [Fact] + public async Task Should_be_able_to_get_an_individual_exchange_by_name() + { + var vhost = new Vhost(Name: Vhost.Name); + var exchange = await fixture.ManagementClient.GetExchangeAsync(vhost, TestExchange); + + exchange.Name.Should().Be(TestExchange); + } + + [Fact] + public async Task Should_be_able_to_get_an_individual_vhost() + { + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + vhost.Name.Should().Be(TestVHost); + } + + [Fact] + public async Task Should_be_able_to_get_messages_from_a_queue() + { + var queue = await CreateTestQueue(TestQueue); + + var publishInfo = new PublishInfo( + TestQueue, + "Hello World", + PayloadEncoding.String, + new Dictionary + { + { "app_id", "management-test" } + } + ); + + await fixture.ManagementClient.PublishAsync("/", "amq.default", publishInfo); + + var messages = await fixture.ManagementClient.GetMessagesFromQueueAsync(queue, new GetMessagesFromQueueInfo(1, AckMode.AckRequeueFalse)); + foreach (var message in messages) + { + output.WriteLine("message.Payload = {0}", message.Payload); + foreach (var property in message.Properties) + output.WriteLine("key: '{0}', value: '{1}'", property.Key, property.Value); + } + } + + [Fact] + public void Should_be_able_to_get_policies_list() + { + var policies = fixture.ManagementClient.GetPoliciesAsync(); + Assert.NotNull(policies); + } + + [Fact] + public async Task Should_be_able_to_list_parameters() + { + var parameters = await fixture.ManagementClient.GetParametersAsync(); + Assert.NotNull(parameters); + } + + [Fact] + public async Task Should_be_able_to_publish_to_an_exchange() + { + var exchange = await CreateExchange(TestExchange); + + var publishInfo = new PublishInfo(TestQueue, "Hello World"); + var result = await fixture.ManagementClient.PublishAsync(exchange, publishInfo); + + // the testExchange isn't bound to a queue + result.Routed.Should().BeFalse(); + } + + [Fact] + public async Task Should_check_that_the_broker_is_alive() + { + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + var user = (await fixture.ManagementClient.GetUsersAsync()).Single(x => x.Name == fixture.User); + var permissionInfo = new PermissionInfo(user.Name); + await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); + (await fixture.ManagementClient.IsAliveAsync(vhost)).Should().BeTrue(); + } + + [Fact] + public async Task Should_create_a_virtual_host() + { + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + vhost.Name.Should().Be(TestVHost); + } + + [Fact] + public async Task Should_create_binding() + { + var queue = await CreateTestQueue(TestQueue); + var exchange = await CreateExchange(TestExchange); + + var bindingInfo = new BindingInfo(RoutingKey: TestQueue); + + await fixture.ManagementClient.CreateQueueBindingAsync(exchange, queue, bindingInfo); + } + + [Fact] + public async Task Should_create_exchange_to_exchange_binding() + { + const string sourceExchangeName = "management_api_test_source_exchange"; + const string destinationExchangeName = "management_api_test_destination_exchange"; + + var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + var sourceExchangeInfo = new ExchangeInfo(sourceExchangeName, "direct"); + var destinationExchangeInfo = new ExchangeInfo(destinationExchangeName, "direct"); + + await fixture.ManagementClient.CreateExchangeAsync(sourceExchangeInfo, vhost); + var sourceExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, sourceExchangeInfo.Name); + + await fixture.ManagementClient.CreateExchangeAsync(destinationExchangeInfo, vhost); + var destinationExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, destinationExchangeInfo.Name); + + await fixture.ManagementClient.CreateExchangeBindingAsync(sourceExchange, destinationExchange, new BindingInfo(RoutingKey: "#")); + + var binding = (await fixture.ManagementClient.GetBindingsWithSourceAsync(sourceExchange))[0]; + + await fixture.ManagementClient.DeleteExchangeAsync(sourceExchange); + await fixture.ManagementClient.DeleteExchangeAsync(destinationExchange); + + Assert.Equal("exchange", binding.DestinationType); + Assert.Equal(destinationExchangeName, binding.Destination); + Assert.Equal("#", binding.RoutingKey); + } + + [Fact] + public async Task Should_delete_a_virtual_host() + { + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + await fixture.ManagementClient.DeleteVhostAsync(vhost); + } + + [Fact] + public async Task Should_delete_binding() + { + var sourceXchange = await CreateExchange("sourceXcg"); + var queue = await CreateTestQueue(TestQueue); + var bindingInfo = new BindingInfo(RoutingKey: "#"); + await fixture.ManagementClient.CreateQueueBindingAsync(sourceXchange, queue, bindingInfo); + var binding = (await fixture.ManagementClient.GetQueueBindingsAsync(sourceXchange, queue))[0]; + await fixture.ManagementClient.DeleteBindingAsync(binding); + await fixture.ManagementClient.DeleteExchangeAsync(sourceXchange); + await fixture.ManagementClient.DeleteQueueAsync(queue); + } + + [Fact] + public async Task Should_delete_exchange_to_exchange_binding() + { + const string sourceExchangeName = "management_api_test_source_exchange"; + const string destinationExchangeName = "management_api_test_destination_exchange"; + + var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + var sourceExchangeInfo = new ExchangeInfo(sourceExchangeName, "direct"); + var destinationExchangeInfo = new ExchangeInfo(destinationExchangeName, "direct"); + + await fixture.ManagementClient.CreateExchangeAsync(sourceExchangeInfo, vhost); + var sourceExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, sourceExchangeInfo.Name); + + await fixture.ManagementClient.CreateExchangeAsync(destinationExchangeInfo, vhost); + var destinationExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, destinationExchangeInfo.Name); + + await fixture.ManagementClient.CreateExchangeBindingAsync(sourceExchange, destinationExchange, new BindingInfo(RoutingKey: "#")); + + var binding = (await fixture.ManagementClient.GetExchangeBindingsAsync(sourceExchange, destinationExchange))[0]; + + await fixture.ManagementClient.DeleteBindingAsync(binding); + await fixture.ManagementClient.DeleteExchangeAsync(sourceExchange); + await fixture.ManagementClient.DeleteExchangeAsync(destinationExchange); + } + + [Fact] + public async Task Should_disable_tracing() + { + var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + await fixture.ManagementClient.DisableTracingAsync(vhost); + var vhostAfterUpdate = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + Assert.False(vhostAfterUpdate.Tracing); + } + + [Fact] + public async Task Should_enable_tracing() + { + var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + await fixture.ManagementClient.EnableTracingAsync(vhost); + var vhostAfterUpdate = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); + Assert.True(vhostAfterUpdate.Tracing); + } + + [Fact] + public async Task Should_get_all_bindings_for_which_the_exchange_is_the_destination() + { + var sourceXchange = await CreateExchange("sourceXcg"); + var destinationXchange = await CreateExchange("destinationXcg"); + var bindingInfo = new BindingInfo(RoutingKey: "#"); + await fixture.ManagementClient.CreateExchangeBindingAsync(sourceXchange, destinationXchange, bindingInfo); + + Assert.NotEmpty((await fixture.ManagementClient.GetBindingsWithDestinationAsync(destinationXchange)).ToList()); + } + + [Fact] + public async Task Should_get_all_bindings_for_which_the_exchange_is_the_source() + { + var sourceXchange = await CreateExchange("sourceXcg"); + var destinationXchange = await CreateExchange("destinationXcg"); + var bindingInfo = new BindingInfo(RoutingKey: "#"); + await fixture.ManagementClient.CreateExchangeBindingAsync(sourceXchange, destinationXchange, bindingInfo); + Assert.NotEmpty((await fixture.ManagementClient.GetBindingsWithSourceAsync(sourceXchange)).ToList()); + } + + [Fact] + public async Task Should_get_bindings() + { + foreach (var binding in await fixture.ManagementClient.GetBindingsAsync()) + { + output.WriteLine("binding.Destination = {0}", binding.Destination); + output.WriteLine("binding.Source = {0}", binding.Source); + output.WriteLine("binding.PropertiesKey = {0}", binding.PropertiesKey); + } + } + + [Fact(Skip = "Requires at least a consumer")] + public async Task Should_get_consumers() + { + foreach (var consumer in await fixture.ManagementClient.GetConsumersAsync()) + { + output.WriteLine("consumer.ConsumerTag = {0}", consumer.ConsumerTag); + output.WriteLine("consumer.ChannelDetails.ConnectionName = {0}", consumer.ChannelDetails.ConnectionName); + output.WriteLine("consumer.ChannelDetails.ConnectionName = {0}", consumer.ChannelDetails.ConnectionName); + output.WriteLine("consumer.ChannelDetails.Node = {0}", consumer.ChannelDetails.Node); + } + } + + [Fact] + public async Task Should_get_channels() + { + var channels = await fixture.ManagementClient.GetChannelsAsync(); + + foreach (var channel in channels) + { + output.WriteLine("channel.Name = {0}", channel.Name); + output.WriteLine("channel.User = {0}", channel.User); + output.WriteLine("channel.PrefetchCount = {0}", channel.PrefetchCount); + } + } + + [Fact] + public async Task Should_get_channels_per_connection() + { + using var bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=True"); + + await Task.Delay(TimeSpan.FromSeconds(10)); + + await bus.Advanced.ConnectAsync(); + await bus.Advanced.PublishAsync(Topology.Exchange.Default, "#", false, new MessageProperties(), ReadOnlyMemory.Empty); + + await Task.Delay(TimeSpan.FromSeconds(10)); + + var connections = await fixture.ManagementClient.GetConnectionsAsync(); + foreach (var connection in connections) + { + output.WriteLine("connection.Name = {0}", connection.Name); + var channels = await fixture.ManagementClient.GetChannelsAsync(connection); + + foreach (var channel in channels) output.WriteLine("\tchannel.Name = {0}", channel.Name); + } + } + + [Fact] + public async Task Should_get_connections() + { + using var bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=True"); + + await Task.Delay(TimeSpan.FromSeconds(10)); + + await bus.Advanced.ConnectAsync(); + + foreach (var connection in await fixture.ManagementClient.GetConnectionsAsync()) + { + output.WriteLine("Connection.Name: {0}", connection.Name); + output.WriteLine("Connection.ClientProperties: {0}", connection.ClientProperties); + } + } + + [Fact] + public async Task Should_get_definitions() + { + var definitions = await fixture.ManagementClient.GetDefinitionsAsync(); + + definitions.RabbitVersion[0].Should().Be('3'); + } + + [Fact] + public async Task Should_get_exchanges() + { + var exchanges = await fixture.ManagementClient.GetExchangesAsync(); + + foreach (var exchange in exchanges) output.WriteLine("exchange.Name = {0}", exchange.Name); + } + + [Fact] + public async Task Should_get_exchanges_with_pagination() + { + var page = await fixture.ManagementClient.GetExchangesByPageAsync(new PageCriteria(1, 7, "amq")); + + page.Items.Count.Should().BeGreaterThan(0); + } + + [Fact(Skip = "Requires at least an active federation")] + public async Task Should_get_federations() + { + var federations = await fixture.ManagementClient.GetFederationsAsync(); + + federations.Single().Node.Should().Be($"rabbit@{fixture.Endpoint}"); + } + + [Fact] + public async Task Should_get_nodes() + { + var nodes = (await fixture.ManagementClient.GetNodesAsync()).ToList(); + + nodes.Count.Should().NotBe(0); + nodes[0].Name.Should().Be("rabbit@easynetq"); + } + + [Fact] + public async Task Should_get_overview() + { + using var bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=True"); + + await Task.Delay(TimeSpan.FromSeconds(10)); + + await bus.Advanced.ConnectAsync(); + + var overview = await fixture.ManagementClient.GetOverviewAsync(); + + output.WriteLine("overview.ManagementVersion = {0}", overview.ManagementVersion); + foreach (var exchangeType in overview.ExchangeTypes) + output.WriteLine("exchangeType.Name = {0}", exchangeType.Name); + foreach (var listener in overview.Listeners) + output.WriteLine("listener.IpAddress = {0}", listener.IpAddress); + + output.WriteLine("overview.Messages = {0}", overview.QueueTotals?.Messages ?? 0); + + foreach (var context in overview.Contexts) + output.WriteLine("context.Description = {0}", context.Description); + } + + [Fact] + public async Task Should_get_permissions() + { + var permissions = await fixture.ManagementClient.GetPermissionsAsync(); + + foreach (var permission in permissions) + { + output.WriteLine("permission.User = {0}", permission.User); + output.WriteLine("permission.Vhost = {0}", permission.Vhost); + output.WriteLine("permission.Configure = {0}", permission.Configure); + output.WriteLine("permission.Read = {0}", permission.Read); + output.WriteLine("permission.Write = {0}", permission.Write); + } + } + + [Fact] + public async Task Should_get_queues() + { + await CreateTestQueue(TestQueue); + (await fixture.ManagementClient.GetQueuesAsync()).Count.Should().BeGreaterThan(0); + } + + + [Fact] + public async Task Should_get_queues_with_pagination() + { + foreach (var queue in await fixture.ManagementClient.GetQueuesAsync()) + await fixture.ManagementClient.DeleteQueueAsync(queue); + + await CreateTestQueue("1"); + await CreateTestQueue("2"); + + var firstPage = await fixture.ManagementClient.GetQueuesByPageAsync(new PageCriteria(1, 1)); + firstPage.Items.Count.Should().Be(1); + + var secondPage = await fixture.ManagementClient.GetQueuesByPageAsync(new PageCriteria(2, 1)); + secondPage.Items.Count.Should().Be(1); + } + + [Fact] + public async Task Should_get_queues_by_vhost() + { + await fixture.ManagementClient.CreateVhostAsync(TestVHost); + var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); + vhost.Name.Should().Be(TestVHost); + + await CreateTestQueueInVhost($"{TestVHost}_{TestQueue}", vhost); + (await fixture.ManagementClient.GetQueuesAsync(vhost)).Count.Should().BeGreaterThan(0); + } + + [Fact] + public async Task Should_get_users() + { + var users = await fixture.ManagementClient.GetUsersAsync(); + + foreach (var user in users) output.WriteLine("user.Name = {0}", user.Name); + } + + [Fact] + public async Task Should_get_vhosts() + { + var vhosts = await fixture.ManagementClient.GetVhostsAsync(); + + foreach (var vhost in vhosts) output.WriteLine("vhost.Name = {0}", vhost.Name); + } + + [Fact] + public async Task Should_purge_a_queue() + { + var queue = await CreateTestQueue(TestQueue); + await fixture.ManagementClient.PurgeAsync(queue); + } + + [Fact] + public async Task Should_throw_when_trying_to_close_unknown_connection() + { + try + { + await fixture.ManagementClient.CloseConnectionAsync("unknown"); + } + catch (Exception e) + { + Assert.IsType(e); + } + } + + [Fact] + public async Task Should_be_able_to_create_shovel_parameter_on_queue() + { + var srcUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); + var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); + + var shovelName = "queue-shovel"; + + await fixture.ManagementClient.CreateShovelAsync( + vhostName: Vhost.Name, + shovelName, + new ParameterShovelValue + ( + SrcProtocol: AmqpProtocol.AMQP091, + SrcUri: srcUri.ToString(), + SrcQueue: "test-queue-src", + SrcExchange: null, + SrcExchangeKey: null, + SrcDeleteAfter: "never", + DestProtocol: AmqpProtocol.AMQP091, + DestUri: destUri.ToString(), + DestQueue: "test-queue-dest", + DestExchange: null, + AckMode: "on-confirm", + AddForwardHeaders: false + ) + ); + + var parameter = await fixture.ManagementClient.GetShovelAsync(Vhost.Name, shovelName); + + Assert.Equal(shovelName, parameter.Name); + } + + [Fact] + public async Task Should_be_able_to_create_shovel_parameter_on_exchange() + { + var srcUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); + var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); + + var shovelName = "exchange-shovel"; + + await fixture.ManagementClient.CreateShovelAsync( + vhostName: Vhost.Name, + shovelName, + new ParameterShovelValue + ( + SrcProtocol: AmqpProtocol.AMQP091, + SrcUri: srcUri.ToString(), + SrcExchange: "test-exchange-src", + SrcExchangeKey: null, + SrcQueue: null, + SrcDeleteAfter: "never", + DestProtocol: AmqpProtocol.AMQP091, + DestUri: destUri.ToString(), + DestExchange: "test-exchange-dest", + DestQueue: null, + AckMode: "on-confirm", + AddForwardHeaders: false + ) + ); + + var parameters = await fixture.ManagementClient.GetParametersAsync(); + + Assert.Contains(parameters, p => p.Name == shovelName); + } + + [Fact] + public async Task Should_be_able_to_throw_on_non_existant_shovel() + { + await Assert.ThrowsAsync(async () + => await fixture.ManagementClient.GetShovelAsync(Vhost.Name, "non-existant-shovel")); + } + + [Fact] + public async Task Should_be_able_to_get_existant_shovel() + { + var srcUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); + var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); + + var shovelName = "exchange-shovel"; + + await fixture.ManagementClient.CreateShovelAsync( + vhostName: Vhost.Name, + shovelName: shovelName, + new ParameterShovelValue + ( + SrcProtocol: AmqpProtocol.AMQP091, + SrcUri: srcUri.ToString(), + SrcExchange: "test-exchange-src", + SrcExchangeKey: null, + SrcQueue: null, + SrcDeleteAfter: "never", + DestProtocol: AmqpProtocol.AMQP091, + DestUri: destUri.ToString(), + DestExchange: "test-exchange-dest", + DestQueue: null, + AckMode: "on-confirm", + AddForwardHeaders: false + ) + ); + + var shovel = await fixture.ManagementClient.GetShovelAsync(Vhost.Name, shovelName); + Assert.Contains(shovelName, shovel.Name); + } +} From 6dd6353147385d10ac1bd50118abe14423bc1fd9 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 23:34:00 +0200 Subject: [PATCH 14/33] Delete Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs --- .../ManagementClientTests.cs | 1381 ----------------- 1 file changed, 1381 deletions(-) delete mode 100644 Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs diff --git a/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs b/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs deleted file mode 100644 index 848de695..00000000 --- a/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs +++ /dev/null @@ -1,1381 +0,0 @@ -using EasyNetQ.Management.Client.Model; - -namespace EasyNetQ.Management.Client.IntegrationTests; - -[Collection("RabbitMQ")] -public class ManagementClientTests -{ - private readonly RabbitMqFixture fixture; - private readonly ITestOutputHelper output; - private static readonly Vhost Vhost = new(Name: "/"); - - public ManagementClientTests(RabbitMqFixture fixture, ITestOutputHelper output) - { - this.fixture = fixture; - this.output = output; - } - - private const string TestExchange = "management_api_test_exchange"; - private const string TestExchange2 = "management_api_test_exchange2"; - private const string TestExchangeTestQueueWithPlusChar = "management_api_test_exchange+plus+test"; - private const string TestQueue = "management_api_test_queue"; - private const string TestQueueWithPlusChar = "management_api_test_queue+plus+test"; - private const string TestUser = "mikey"; - - private async Task CreateExchange(string exchangeName) - { - await fixture.ManagementClient.CreateExchangeAsync(new ExchangeInfo(exchangeName, "direct"), Vhost); - return await fixture.ManagementClient.GetExchangeAsync(Vhost, exchangeName); - } - - private async Task EnsureQueueExists(string managementApiTestQueue) - { - return (await fixture.ManagementClient.GetQueuesAsync()) - .SingleOrDefault(x => x.Name == managementApiTestQueue) - ?? await CreateTestQueue(managementApiTestQueue); - } - - private async Task CreateTestQueue(string queueName) - { - var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - return await CreateTestQueueInVhost(queueName, vhost); - } - - private async Task CreateTestQueueInVhost(string queueName, Vhost vhost) - { - var queueInfo = new QueueInfo(queueName); - await fixture.ManagementClient.CreateQueueAsync(queueInfo, vhost); - return await fixture.ManagementClient.GetQueueAsync(vhost, queueName); - } - - private async Task EnsureExchangeExists(string exchangeName) - { - return (await fixture.ManagementClient.GetExchangesAsync()) - .SingleOrDefault(x => x.Name == exchangeName) ?? await CreateExchange(exchangeName); - } - - private const string TestVHost = "management_test_virtual_host"; - - [Fact] - public async Task Should_be_able_to_change_the_password_of_a_user() - { - var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Monitoring).AddTag(UserTags.Management); - await fixture.ManagementClient.CreateUserAsync(userInfo); - - var user = await fixture.ManagementClient.GetUserAsync(TestUser); - - await fixture.ManagementClient.ChangeUserPasswordAsync(TestUser, "newPassword"); - - var updatedUser = await fixture.ManagementClient.GetUserAsync(TestUser); - updatedUser.Name.Should().Be(user.Name); - updatedUser.Tags.Should().BeEquivalentTo(user.Tags); - updatedUser.PasswordHash.Should().NotBe(user.PasswordHash); - } - - [Fact(Skip = "Requires at least a connection")] - public async Task Should_be_able_to_close_connection() - { - // first get a connection - var connections = await fixture.ManagementClient.GetConnectionsAsync(); - - // then close it - await fixture.ManagementClient.CloseConnectionAsync(connections.First()); - } - - [Fact] - public async Task Should_be_able_to_configure_request() - { - using var client = new ManagementClient( - fixture.Endpoint, fixture.User, fixture.Password, configureHttpRequestMessage: req => req.Headers.Add("x-not-used", "some_value") - ); - - await client.GetOverviewAsync(); - } - - [Fact] - public async Task Should_be_able_to_create_a_queue() - { - await fixture.ManagementClient.CreateQueueAsync(new QueueInfo(TestQueue), Vhost); - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue); - - queue.Name.Should().Be(TestQueue); - } - - [Fact] - public async Task Should_be_able_to_create_a_queue_with_arguments() - { - const string exchangeName = "test-dead-letter-exchange"; - const string argumentKey = "x-dead-letter-exchange"; - var queueInfo = new QueueInfo(Name: $"{TestQueue}1", Arguments: new Dictionary { { argumentKey, exchangeName } }); - - await fixture.ManagementClient.CreateQueueAsync(queueInfo, Vhost); - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, queueInfo.Name); - queue.Arguments[argumentKey].Should().NotBeNull(); - queue.Arguments[argumentKey].Should().Be(exchangeName); - } - - [Fact] - public async Task Should_be_able_to_create_a_queue_with_plus_char_in_the_name() - { - var queueInfo = new QueueInfo(TestQueueWithPlusChar); - - await fixture.ManagementClient.CreateQueueAsync(queueInfo, Vhost); - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueueWithPlusChar); - - queue.Name.Should().Be(TestQueueWithPlusChar); - } - - [Fact] - public async Task Should_be_able_to_check_cluster_alarms() - { - var result = await fixture.ManagementClient.HaveAnyClusterAlarmsAsync(); - result.Should().BeFalse(); - } - - [Fact] - public async Task Should_be_able_to_check_local_alarms() - { - var result = await fixture.ManagementClient.HaveAnyClusterAlarmsAsync(); - result.Should().BeFalse(); - } - - [Fact] - public async Task Should_be_able_to_check_classic_queues_without_synchronised_mirrors() - { - var result = await fixture.ManagementClient.HaveAnyClassicQueuesWithoutSynchronisedMirrorsAsync(); - result.Should().BeFalse(); - } - - [Fact] - public async Task Should_be_able_to_check_quorum_queues_is_critical_state() - { - var result = await fixture.ManagementClient.HaveAnyQuorumQueuesInCriticalStateAsync(); - result.Should().BeFalse(); - } - - [Fact] - public async Task Should_be_able_to_rebalance_queues() - { - await fixture.ManagementClient.RebalanceQueuesAsync(); - } - - [Fact] - public async Task Should_be_able_to_create_a_user() - { - var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Administrator); - - await fixture.ManagementClient.CreateUserAsync(userInfo); - var user = await fixture.ManagementClient.GetUserAsync(TestUser); - - user.Name.Should().Be(TestUser); - user.Tags.Should().Contain(UserTags.Administrator); - } - - [Fact] - public async Task Should_be_able_to_create_a_user_with_password_hash() - { - var testUser = "hash_user"; - // Hash calculated using RabbitMq hash computing algorithm using Sha256 - // See https://www.rabbitmq.com/passwords.html - var passwordHash = "Qlp9Dgrqvx1S1VkuYsoWwgUD2XW2gZLuqQwreE+PAsPZETgo"; //"topSecret" - var userInfo = UserInfo.ByPasswordHash(testUser, passwordHash).AddTag(UserTags.Administrator); - - await fixture.ManagementClient.CreateUserAsync(userInfo); - var user = await fixture.ManagementClient.GetUserAsync(testUser); - - user.Name.Should().Be(testUser); - } - - [Fact] - public async Task Should_be_able_to_create_a_user_with_the_policymaker_tag() - { - var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Policymaker); - - await fixture.ManagementClient.CreateUserAsync(userInfo); - var user = await fixture.ManagementClient.GetUserAsync(TestUser); - - user.Name.Should().Be(TestUser); - } - - [Fact] - public async Task Should_be_able_to_create_a_user_without_password() - { - var testUser = "empty"; - var userInfo = UserInfo.ByPassword(testUser, "").AddTag(UserTags.Administrator); - - await fixture.ManagementClient.CreateUserAsync(userInfo); - var user = await fixture.ManagementClient.GetUserAsync(testUser); - - user.Name.Should().Be(testUser); - } - - [Fact] - public async Task Should_be_able_to_create_all_the_definitions_in_a_policy() - { - const string policyName = "a-sample-all-definitions-in-a-policy"; - const int priority = 999; - const HaMode haMode = HaMode.All; - const HaSyncMode haSyncMode = HaSyncMode.Automatic; - const HaPromote haPromoteOnFailure = HaPromote.Always; - const HaPromote haPromoteOnShutdown = HaPromote.WhenSynced; - const uint queueVersion = 1; - const QueueLocator queueMasterLocator = QueueLocator.ClientLocal; - const uint deliveryLimit = 3; - const Model.DeadLetterStrategy deadLetterStrategy = Model.DeadLetterStrategy.AtLeastOnce; - const QueueLocator queueLeaderLocator = QueueLocator.Balanced; - const string maxAge = "1h"; - const uint streamMaxSegmentSizeBytes = 50000; - const string alternateExchange = "a-sample-alternate-exchange"; - const string deadLetterExchange = "a-sample-dead-letter-exchange"; - const string deadLetterRoutingKey = "a-sample-dead-letter-exchange-key"; - const uint messageTtl = 5000; - const uint expires = 10000; - const uint maxLength = 500; - const long maxLengthBytes = 5000; - const Overflow overflow = Overflow.RejectPublish; - uint? consumerTimeout = fixture.RabbitmqVersion >= new Version("3.12") ? 3600000 : null; - - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - HaMode: haMode, - HaSyncMode: haSyncMode, - HaPromoteOnFailure: haPromoteOnFailure, - HaPromoteOnShutdown: haPromoteOnShutdown, - QueueVersion: queueVersion, - QueueMasterLocator: queueMasterLocator, - - DeliveryLimit: deliveryLimit, - DeadLetterStrategy: deadLetterStrategy, - QueueLeaderLocator: queueLeaderLocator, - - MaxAge: maxAge, - StreamMaxSegmentSizeBytes: streamMaxSegmentSizeBytes, - - AlternateExchange: alternateExchange, - - DeadLetterExchange: deadLetterExchange, - DeadLetterRoutingKey: deadLetterRoutingKey, - MessageTtl: messageTtl, - Expires: expires, - MaxLength: maxLength, - MaxLengthBytes: maxLengthBytes, - Overflow: overflow, - ConsumerTimeout: consumerTimeout - ), - Priority: priority - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Priority == priority - && p.Definition.HaMode == haMode - && p.Definition.HaSyncMode == haSyncMode - && p.Definition.HaPromoteOnFailure == haPromoteOnFailure - && p.Definition.HaPromoteOnShutdown == haPromoteOnShutdown - && p.Definition.QueueVersion == queueVersion - && p.Definition.QueueMasterLocator == queueMasterLocator - && p.Definition.DeliveryLimit == deliveryLimit - && p.Definition.DeadLetterStrategy == deadLetterStrategy - && p.Definition.QueueLeaderLocator == queueLeaderLocator - && p.Definition.MaxAge == maxAge - && p.Definition.StreamMaxSegmentSizeBytes == streamMaxSegmentSizeBytes - && p.Definition.AlternateExchange == alternateExchange - && p.Definition.DeadLetterExchange == deadLetterExchange - && p.Definition.DeadLetterRoutingKey == deadLetterRoutingKey - && p.Definition.MessageTtl == messageTtl - && p.Definition.Expires == expires - && p.Definition.MaxLength == maxLength - && p.Definition.MaxLengthBytes == maxLengthBytes - && p.Definition.Overflow == overflow - && p.Definition.ConsumerTimeout == consumerTimeout) - ); - } - - [Fact] - public async Task Should_be_able_to_create_alternate_exchange_policy() - { - const string policyName = "a-sample-alternate-exchange-policy"; - const string alternateExchange = "a-sample-alternate-exchange"; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - AlternateExchange: alternateExchange - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.AlternateExchange == alternateExchange) - ); - } - - [Fact] - public async Task Should_be_able_to_create_an_exchange() - { - var exchange = await CreateExchange(TestExchange); - exchange.Name.Should().Be(TestExchange); - } - - [Fact] - public async Task Should_be_able_to_create_an_exchange_with_plus_char_in_the_name() - { - var exchangeInfo = new ExchangeInfo(TestExchangeTestQueueWithPlusChar, "direct"); - - await fixture.ManagementClient.CreateExchangeAsync(exchangeInfo, Vhost); - var exchange = await fixture.ManagementClient.GetExchangeAsync(Vhost, TestExchangeTestQueueWithPlusChar); - - exchange.Name.Should().Be(TestExchangeTestQueueWithPlusChar); - } - - [Fact] - public async Task Should_be_able_to_create_dead_letter_exchange_policy() - { - const string policyName = "a-sample-dead-letter-exchange"; - const string deadLetterExchange = "a-sample-dead-letter-exchange"; - const string deadLetterRoutingKey = "a-sample-dead-letter-exchange-key"; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - DeadLetterExchange: deadLetterExchange, - DeadLetterRoutingKey: deadLetterRoutingKey - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.DeadLetterExchange == deadLetterExchange - && p.Definition.DeadLetterRoutingKey == deadLetterRoutingKey) - ); - } - - [Fact] - public async Task Should_be_able_to_create_exchanges_only_policies() - { - const string policyName = "asamplepolicy-exchange-only"; - const HaMode haMode = HaMode.All; - const HaSyncMode haSyncMode = HaSyncMode.Automatic; - - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - ApplyTo: ApplyMode.Exchanges, - Definition: new PolicyDefinition( - HaMode: haMode, - HaSyncMode: haSyncMode - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.ApplyTo == ApplyMode.Exchanges - && p.Definition.HaMode == haMode - && p.Definition.HaSyncMode == haSyncMode) - ); - } - - [Fact] - public async Task Should_be_able_to_create_expires_policy() - { - const string policyName = "a-sample-expires"; - const uint expires = 10000; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - Expires: expires - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.Expires == expires) - ); - } - - [Fact] - public async Task Should_be_able_to_create_federation_upstream_policy() - { - const string policyName = "a-sample-federation-upstream-policy"; - - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - FederationUpstream: "my-upstream" - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.FederationUpstream == "my-upstream") - ); - } - - [Fact] - public async Task Should_be_able_to_create_federation_upstream_set_policy() - { - const string policyName = "a-sample-federation-upstream-set-policy"; - - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - FederationUpstreamSet: "my-upstream-set" - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.FederationUpstreamSet == "my-upstream-set") - ); - } - - [Fact] - public async Task Should_be_able_to_create_max_length_policy() - { - const string policyName = "a-sample-max-length"; - const uint maxLength = 500; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - MaxLength: maxLength - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.MaxLength == maxLength) - ); - } - - [Fact] - public async Task Should_be_able_to_create_max_length_bytes_policy() - { - const string policyName = "a-sample-max-length-bytes"; - const uint maxLengthBytes = 500; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - MaxLengthBytes: maxLengthBytes - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.MaxLengthBytes == maxLengthBytes) - ); - } - - [Fact] - public async Task Should_be_able_to_create_overflow_policy() - { - foreach (Overflow overflow in Enum.GetValues(typeof(Overflow))) - { - const string policyName = "a-sample-overflow"; - const uint maxLengthBytes = 500; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - MaxLengthBytes: maxLengthBytes, - Overflow: overflow - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.MaxLengthBytes == maxLengthBytes - && p.Definition.Overflow == overflow) - ); - } - } - - [Fact] - public async Task Should_be_able_to_create_message_ttl_policy() - { - const string policyName = "a-sample-message-ttl"; - const uint messageTtl = 5000; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - MessageTtl: messageTtl - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.Definition.MessageTtl == messageTtl) - ); - } - - [Fact] - public async Task Should_be_able_to_create_federation_upstream_parameter() - { - await fixture.ManagementClient.CreateParameterAsync( - new Parameter - ( - Component: "federation-upstream", - Name: "myfakefederationupstream1", - Vhost: Vhost.Name, - Value: new { Uri = $"amqp://{fixture.User}:{fixture.Password}@{fixture.Endpoint.Host}" } - ) - ); - Assert.Contains(await fixture.ManagementClient.GetParametersAsync(), p => p.Name == "myfakefederationupstream1"); - } - - [Fact] - public async Task Should_be_able_to_create_federation_upstream_parameter_with_extension_method() - { - var amqpUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); - - await fixture.ManagementClient.CreateFederationUpstreamAsync( - vhostName: Vhost.Name, - federationUpstreamName: "myfakefederationupstream-extension", - federationUpstreamDescription: new ParameterFederationValue(amqpUri, Expires: 3600000) - ); - - var parameter = await fixture.ManagementClient.GetFederationUpstreamAsync(Vhost.Name, "myfakefederationupstream-extension"); - Assert.Equal("myfakefederationupstream-extension", parameter.Name); - } - - [Fact] - public async Task Should_be_able_to_create_permissions() - { - var user = (await fixture.ManagementClient.GetUsersAsync()).SingleOrDefault(x => x.Name == TestUser); - if (user == null) - throw new EasyNetQTestException($"user '{TestUser}' hasn't been created"); - - var vhost = (await fixture.ManagementClient.GetVhostsAsync()).SingleOrDefault(x => x.Name == TestVHost); - if (vhost == null) - throw new EasyNetQTestException($"Test vhost: '{TestVHost}' has not been created"); - - var permissionInfo = new PermissionInfo(user.Name); - await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); - } - - [Fact] - public async Task Should_be_able_to_create_permissions_in_default_Vhost() - { - //create user if it does not exists - var user = (await fixture.ManagementClient.GetUsersAsync()).SingleOrDefault(x => x.Name == TestUser) - ?? await fixture.ManagementClient.GetUserAsync(TestUser); - - var vhost = (await fixture.ManagementClient.GetVhostsAsync()).SingleOrDefault(x => x.Name == Vhost.Name); - if (vhost == null) - throw new EasyNetQTestException($"Default vhost: '{TestVHost}' has not been created"); - - var permissionInfo = new PermissionInfo(user.Name); - await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); - } - - [Fact] - public async Task Should_be_able_to_create_policies() - { - const string policyName = "asamplepolicy"; - const HaMode haMode = HaMode.All; - const HaSyncMode haSyncMode = HaSyncMode.Automatic; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - HaMode: haMode, - HaSyncMode: haSyncMode - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.ApplyTo == ApplyMode.All - && p.Definition.HaMode == haMode - && p.Definition.HaSyncMode == haSyncMode) - ); - } - - [Fact] - public async Task Should_be_able_to_create_queues_only_policies() - { - const string policyName = "asamplepolicy-queue-only"; - const HaMode haMode = HaMode.All; - const HaSyncMode haSyncMode = HaSyncMode.Automatic; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - ApplyTo: ApplyMode.Queues, - Definition: new PolicyDefinition( - HaMode: haMode, - HaSyncMode: haSyncMode - ) - ) - ); - Assert.Equal(1, (await fixture.ManagementClient.GetPoliciesAsync()).Count( - p => p.Name == policyName - && p.Vhost == Vhost.Name - && p.ApplyTo == ApplyMode.Queues - && p.Definition.HaMode == haMode - && p.Definition.HaSyncMode == haSyncMode) - ); - } - - [Fact] - public async Task Should_be_able_to_delete_a_queue() - { - var queue = await CreateTestQueue(TestQueue); - await fixture.ManagementClient.DeleteQueueAsync(queue); - } - - [Fact] - public async Task Should_be_able_to_delete_a_user() - { - var user = await fixture.ManagementClient.GetUserAsync(TestUser); - await fixture.ManagementClient.DeleteUserAsync(user); - } - - [Fact] - public async Task Should_be_able_to_delete_an_exchange() - { - const string exchangeName = "delete-xcg"; - var exchange = await CreateExchange(exchangeName); - - await fixture.ManagementClient.DeleteExchangeAsync(exchange); - } - - [Fact] - public async Task Should_be_able_to_delete_an_exchange_with_pluses() - { - var exchange = await CreateExchange(TestExchangeTestQueueWithPlusChar); - await fixture.ManagementClient.DeleteExchangeAsync(exchange); - } - - [Fact] - public async Task Should_be_able_to_delete_permissions() - { - var userInfo = UserInfo.ByPassword(TestUser, "topSecret").AddTag(UserTags.Monitoring).AddTag(UserTags.Management); - await fixture.ManagementClient.CreateUserAsync(userInfo); - var user = await fixture.ManagementClient.GetUserAsync(TestUser); - await fixture.ManagementClient.CreateVhostAsync(TestVHost); - var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); - var permissionInfo = new PermissionInfo(user.Name); - await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); - - var permission = (await fixture.ManagementClient.GetPermissionsAsync()) - .SingleOrDefault(x => x.User == TestUser && x.Vhost == TestVHost); - - if (permission == null) - throw new EasyNetQTestException($"No permission for vhost: {TestVHost} and user: {TestUser}"); - - await fixture.ManagementClient.DeletePermissionAsync(permission); - } - - [Fact] - public async Task Should_be_able_to_delete_policies() - { - const string policyName = "asamplepolicy"; - await fixture.ManagementClient.CreatePolicyAsync( - new Policy( - Name: policyName, - Pattern: "averyuncommonpattern", - Vhost: Vhost.Name, - Definition: new PolicyDefinition( - HaMode: HaMode.All, - HaSyncMode: HaSyncMode.Automatic - ) - ) - ); - Assert.Equal( - 1, - (await fixture.ManagementClient.GetPoliciesAsync()).Count(p => p.Name == policyName && p.Vhost == Vhost.Name) - ); - await fixture.ManagementClient.DeletePolicyAsync(Vhost.Name, policyName); - Assert.Equal( - 0, - (await fixture.ManagementClient.GetPoliciesAsync()).Count(p => p.Name == policyName && p.Vhost == Vhost.Name) - ); - } - - [Fact] - public async Task Should_be_able_to_get_a_list_of_bindings_between_an_exchange_and_a_queue() - { - var queue = await EnsureQueueExists(TestQueue); - - var exchange = await EnsureExchangeExists(TestExchange); - - var bindings = (await fixture.ManagementClient.GetQueueBindingsAsync(exchange, queue)).ToArray(); - - bindings.Length.Should().Be(0); - } - - [Fact] - public async Task Should_be_able_to_get_a_list_of_bindings_between_an_exchange_and_an_exchange() - { - var exchange1 = await EnsureExchangeExists(TestExchange); - var exchange2 = await EnsureExchangeExists(TestExchange2); - - var bindings = await fixture.ManagementClient.GetExchangeBindingsAsync(exchange1, exchange2); - - bindings.Count.Should().Be(0); - } - - [Fact] - public async Task Should_be_able_to_get_a_queue_by_name() - { - await CreateTestQueue(TestQueue); - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue); - queue.Name.Should().Be(TestQueue); - } - - [Fact] - public async Task Should_be_able_to_get_a_queue_by_name_with_all_detailed_information() - { - const int age = 10; - const int increment = 1; - await CreateTestQueue(TestQueue); - await Task.Delay(TimeSpan.FromSeconds(10)); - - var queue = await fixture.ManagementClient.GetQueueAsync( - Vhost, - TestQueue, - new LengthsCriteria(age, increment), - new RatesCriteria(age, increment) - ); - - queue.Name.Should().Be(TestQueue); - queue.MessagesDetails.Samples.Count.Should().BeGreaterThan(0); - queue.MessagesReadyDetails.Samples.Count.Should().BeGreaterThan(0); - queue.MessagesUnacknowledgedDetails.Samples.Count.Should().BeGreaterThan(0); - } - - [Fact] - public async Task Should_be_able_to_get_a_queue_by_name_with_detailed_length_information() - { - const int age = 10; - const int increment = 1; - await CreateTestQueue(TestQueue); - await Task.Delay(TimeSpan.FromSeconds(10)); - - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue, new LengthsCriteria(age, increment)); - - queue.Name.Should().Be(TestQueue); - queue.MessagesDetails.Samples.Count.Should().BeGreaterThan(0); - queue.MessagesReadyDetails.Samples.Count.Should().BeGreaterThan(0); - queue.MessagesUnacknowledgedDetails.Samples.Count.Should().BeGreaterThan(0); - } - - [Fact] - public async Task Should_be_able_to_get_a_queue_by_name_with_detailed_rates_information() - { - const int age = 60; - const int increment = 10; - await CreateTestQueue(TestQueue); - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueue, ratesCriteria: new RatesCriteria(age, increment)); - queue.Name.Should().Be(TestQueue); - } - - [Fact] - public async Task Should_be_able_to_get_a_queue_by_name_with_plus_char() - { - await CreateTestQueue(TestQueueWithPlusChar); - var queue = await fixture.ManagementClient.GetQueueAsync(Vhost, TestQueueWithPlusChar); - queue.Name.Should().Be(TestQueueWithPlusChar); - } - - [Fact] - public async Task Should_be_able_to_get_a_user_by_name() - { - var userInfo = UserInfo.ByPassword(TestUser, "topSecret"); - await fixture.ManagementClient.CreateUserAsync(userInfo); - (await fixture.ManagementClient.GetUserAsync(TestUser)).Name.Should().Be(TestUser); - } - - [Fact] - public async Task Should_be_able_to_get_all_the_bindings_for_a_queue() - { - var queue = await CreateTestQueue(TestQueue); - var bindings = await fixture.ManagementClient.GetBindingsForQueueAsync(queue); - Assert.NotEmpty(bindings.ToList()); - } - - [Fact] - public async Task Should_be_able_to_get_an_individual_exchange_by_name() - { - var vhost = new Vhost(Name: Vhost.Name); - var exchange = await fixture.ManagementClient.GetExchangeAsync(vhost, TestExchange); - - exchange.Name.Should().Be(TestExchange); - } - - [Fact] - public async Task Should_be_able_to_get_an_individual_vhost() - { - await fixture.ManagementClient.CreateVhostAsync(TestVHost); - var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); - vhost.Name.Should().Be(TestVHost); - } - - [Fact] - public async Task Should_be_able_to_get_messages_from_a_queue() - { - var queue = await CreateTestQueue(TestQueue); - - var publishInfo = new PublishInfo( - TestQueue, - "Hello World", - PayloadEncoding.String, - new Dictionary - { - { "app_id", "management-test" } - } - ); - - await fixture.ManagementClient.PublishAsync("/", "amq.default", publishInfo); - - var messages = await fixture.ManagementClient.GetMessagesFromQueueAsync(queue, new GetMessagesFromQueueInfo(1, AckMode.AckRequeueFalse)); - foreach (var message in messages) - { - output.WriteLine("message.Payload = {0}", message.Payload); - foreach (var property in message.Properties) - output.WriteLine("key: '{0}', value: '{1}'", property.Key, property.Value); - } - } - - [Fact] - public void Should_be_able_to_get_policies_list() - { - var policies = fixture.ManagementClient.GetPoliciesAsync(); - Assert.NotNull(policies); - } - - [Fact] - public async Task Should_be_able_to_list_parameters() - { - var parameters = await fixture.ManagementClient.GetParametersAsync(); - Assert.NotNull(parameters); - } - - [Fact] - public async Task Should_be_able_to_publish_to_an_exchange() - { - var exchange = await CreateExchange(TestExchange); - - var publishInfo = new PublishInfo(TestQueue, "Hello World"); - var result = await fixture.ManagementClient.PublishAsync(exchange, publishInfo); - - // the testExchange isn't bound to a queue - result.Routed.Should().BeFalse(); - } - - [Fact] - public async Task Should_check_that_the_broker_is_alive() - { - await fixture.ManagementClient.CreateVhostAsync(TestVHost); - var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); - var user = (await fixture.ManagementClient.GetUsersAsync()).Single(x => x.Name == fixture.User); - var permissionInfo = new PermissionInfo(user.Name); - await fixture.ManagementClient.CreatePermissionAsync(vhost, permissionInfo); - (await fixture.ManagementClient.IsAliveAsync(vhost)).Should().BeTrue(); - } - - [Fact] - public async Task Should_create_a_virtual_host() - { - await fixture.ManagementClient.CreateVhostAsync(TestVHost); - var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); - vhost.Name.Should().Be(TestVHost); - } - - [Fact] - public async Task Should_create_binding() - { - var queue = await CreateTestQueue(TestQueue); - var exchange = await CreateExchange(TestExchange); - - var bindingInfo = new BindingInfo(RoutingKey: TestQueue); - - await fixture.ManagementClient.CreateQueueBindingAsync(exchange, queue, bindingInfo); - } - - [Fact] - public async Task Should_create_exchange_to_exchange_binding() - { - const string sourceExchangeName = "management_api_test_source_exchange"; - const string destinationExchangeName = "management_api_test_destination_exchange"; - - var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - var sourceExchangeInfo = new ExchangeInfo(sourceExchangeName, "direct"); - var destinationExchangeInfo = new ExchangeInfo(destinationExchangeName, "direct"); - - await fixture.ManagementClient.CreateExchangeAsync(sourceExchangeInfo, vhost); - var sourceExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, sourceExchangeInfo.Name); - - await fixture.ManagementClient.CreateExchangeAsync(destinationExchangeInfo, vhost); - var destinationExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, destinationExchangeInfo.Name); - - await fixture.ManagementClient.CreateExchangeBindingAsync(sourceExchange, destinationExchange, new BindingInfo(RoutingKey: "#")); - - var binding = (await fixture.ManagementClient.GetBindingsWithSourceAsync(sourceExchange))[0]; - - await fixture.ManagementClient.DeleteExchangeAsync(sourceExchange); - await fixture.ManagementClient.DeleteExchangeAsync(destinationExchange); - - Assert.Equal("exchange", binding.DestinationType); - Assert.Equal(destinationExchangeName, binding.Destination); - Assert.Equal("#", binding.RoutingKey); - } - - [Fact] - public async Task Should_delete_a_virtual_host() - { - var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); - await fixture.ManagementClient.DeleteVhostAsync(vhost); - } - - [Fact] - public async Task Should_delete_binding() - { - var sourceXchange = await CreateExchange("sourceXcg"); - var queue = await CreateTestQueue(TestQueue); - var bindingInfo = new BindingInfo(RoutingKey: "#"); - await fixture.ManagementClient.CreateQueueBindingAsync(sourceXchange, queue, bindingInfo); - var binding = (await fixture.ManagementClient.GetQueueBindingsAsync(sourceXchange, queue))[0]; - await fixture.ManagementClient.DeleteBindingAsync(binding); - await fixture.ManagementClient.DeleteExchangeAsync(sourceXchange); - await fixture.ManagementClient.DeleteQueueAsync(queue); - } - - [Fact] - public async Task Should_delete_exchange_to_exchange_binding() - { - const string sourceExchangeName = "management_api_test_source_exchange"; - const string destinationExchangeName = "management_api_test_destination_exchange"; - - var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - var sourceExchangeInfo = new ExchangeInfo(sourceExchangeName, "direct"); - var destinationExchangeInfo = new ExchangeInfo(destinationExchangeName, "direct"); - - await fixture.ManagementClient.CreateExchangeAsync(sourceExchangeInfo, vhost); - var sourceExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, sourceExchangeInfo.Name); - - await fixture.ManagementClient.CreateExchangeAsync(destinationExchangeInfo, vhost); - var destinationExchange = await fixture.ManagementClient.GetExchangeAsync(vhost, destinationExchangeInfo.Name); - - await fixture.ManagementClient.CreateExchangeBindingAsync(sourceExchange, destinationExchange, new BindingInfo(RoutingKey: "#")); - - var binding = (await fixture.ManagementClient.GetExchangeBindingsAsync(sourceExchange, destinationExchange))[0]; - - await fixture.ManagementClient.DeleteBindingAsync(binding); - await fixture.ManagementClient.DeleteExchangeAsync(sourceExchange); - await fixture.ManagementClient.DeleteExchangeAsync(destinationExchange); - } - - [Fact] - public async Task Should_disable_tracing() - { - var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - await fixture.ManagementClient.DisableTracingAsync(vhost); - var vhostAfterUpdate = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - Assert.False(vhostAfterUpdate.Tracing); - } - - [Fact] - public async Task Should_enable_tracing() - { - var vhost = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - await fixture.ManagementClient.EnableTracingAsync(vhost); - var vhostAfterUpdate = await fixture.ManagementClient.GetVhostAsync(Vhost.Name); - Assert.True(vhostAfterUpdate.Tracing); - } - - [Fact] - public async Task Should_get_all_bindings_for_which_the_exchange_is_the_destination() - { - var sourceXchange = await CreateExchange("sourceXcg"); - var destinationXchange = await CreateExchange("destinationXcg"); - var bindingInfo = new BindingInfo(RoutingKey: "#"); - await fixture.ManagementClient.CreateExchangeBindingAsync(sourceXchange, destinationXchange, bindingInfo); - - Assert.NotEmpty((await fixture.ManagementClient.GetBindingsWithDestinationAsync(destinationXchange)).ToList()); - } - - [Fact] - public async Task Should_get_all_bindings_for_which_the_exchange_is_the_source() - { - var sourceXchange = await CreateExchange("sourceXcg"); - var destinationXchange = await CreateExchange("destinationXcg"); - var bindingInfo = new BindingInfo(RoutingKey: "#"); - await fixture.ManagementClient.CreateExchangeBindingAsync(sourceXchange, destinationXchange, bindingInfo); - Assert.NotEmpty((await fixture.ManagementClient.GetBindingsWithSourceAsync(sourceXchange)).ToList()); - } - - [Fact] - public async Task Should_get_bindings() - { - foreach (var binding in await fixture.ManagementClient.GetBindingsAsync()) - { - output.WriteLine("binding.Destination = {0}", binding.Destination); - output.WriteLine("binding.Source = {0}", binding.Source); - output.WriteLine("binding.PropertiesKey = {0}", binding.PropertiesKey); - } - } - - [Fact(Skip = "Requires at least a consumer")] - public async Task Should_get_consumers() - { - foreach (var consumer in await fixture.ManagementClient.GetConsumersAsync()) - { - output.WriteLine("consumer.ConsumerTag = {0}", consumer.ConsumerTag); - output.WriteLine("consumer.ChannelDetails.ConnectionName = {0}", consumer.ChannelDetails.ConnectionName); - output.WriteLine("consumer.ChannelDetails.ConnectionName = {0}", consumer.ChannelDetails.ConnectionName); - output.WriteLine("consumer.ChannelDetails.Node = {0}", consumer.ChannelDetails.Node); - } - } - - [Fact] - public async Task Should_get_channels() - { - var channels = await fixture.ManagementClient.GetChannelsAsync(); - - foreach (var channel in channels) - { - output.WriteLine("channel.Name = {0}", channel.Name); - output.WriteLine("channel.User = {0}", channel.User); - output.WriteLine("channel.PrefetchCount = {0}", channel.PrefetchCount); - } - } - - [Fact] - public async Task Should_get_channels_per_connection() - { - using var bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=True"); - - await Task.Delay(TimeSpan.FromSeconds(10)); - - await bus.Advanced.ConnectAsync(); - await bus.Advanced.PublishAsync(Topology.Exchange.Default, "#", false, new MessageProperties(), ReadOnlyMemory.Empty); - - await Task.Delay(TimeSpan.FromSeconds(10)); - - var connections = await fixture.ManagementClient.GetConnectionsAsync(); - foreach (var connection in connections) - { - output.WriteLine("connection.Name = {0}", connection.Name); - var channels = await fixture.ManagementClient.GetChannelsAsync(connection); - - foreach (var channel in channels) output.WriteLine("\tchannel.Name = {0}", channel.Name); - } - } - - [Fact] - public async Task Should_get_connections() - { - using var bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=True"); - - await Task.Delay(TimeSpan.FromSeconds(10)); - - await bus.Advanced.ConnectAsync(); - - foreach (var connection in await fixture.ManagementClient.GetConnectionsAsync()) - { - output.WriteLine("Connection.Name: {0}", connection.Name); - output.WriteLine("Connection.ClientProperties: {0}", connection.ClientProperties); - } - } - - [Fact] - public async Task Should_get_definitions() - { - var definitions = await fixture.ManagementClient.GetDefinitionsAsync(); - - definitions.RabbitVersion[0].Should().Be('3'); - } - - [Fact] - public async Task Should_get_exchanges() - { - var exchanges = await fixture.ManagementClient.GetExchangesAsync(); - - foreach (var exchange in exchanges) output.WriteLine("exchange.Name = {0}", exchange.Name); - } - - [Fact] - public async Task Should_get_exchanges_with_pagination() - { - var page = await fixture.ManagementClient.GetExchangesByPageAsync(new PageCriteria(1, 7, "amq")); - - page.Items.Count.Should().BeGreaterThan(0); - } - - [Fact(Skip = "Requires at least an active federation")] - public async Task Should_get_federations() - { - var federations = await fixture.ManagementClient.GetFederationsAsync(); - - federations.Single().Node.Should().Be($"rabbit@{fixture.Endpoint}"); - } - - [Fact] - public async Task Should_get_nodes() - { - var nodes = (await fixture.ManagementClient.GetNodesAsync()).ToList(); - - nodes.Count.Should().NotBe(0); - nodes[0].Name.Should().Be("rabbit@easynetq"); - } - - [Fact] - public async Task Should_get_overview() - { - using var bus = RabbitHutch.CreateBus("host=localhost;publisherConfirms=True"); - - await Task.Delay(TimeSpan.FromSeconds(10)); - - await bus.Advanced.ConnectAsync(); - - var overview = await fixture.ManagementClient.GetOverviewAsync(); - - output.WriteLine("overview.ManagementVersion = {0}", overview.ManagementVersion); - foreach (var exchangeType in overview.ExchangeTypes) - output.WriteLine("exchangeType.Name = {0}", exchangeType.Name); - foreach (var listener in overview.Listeners) - output.WriteLine("listener.IpAddress = {0}", listener.IpAddress); - - output.WriteLine("overview.Messages = {0}", overview.QueueTotals?.Messages ?? 0); - - foreach (var context in overview.Contexts) - output.WriteLine("context.Description = {0}", context.Description); - } - - [Fact] - public async Task Should_get_permissions() - { - var permissions = await fixture.ManagementClient.GetPermissionsAsync(); - - foreach (var permission in permissions) - { - output.WriteLine("permission.User = {0}", permission.User); - output.WriteLine("permission.Vhost = {0}", permission.Vhost); - output.WriteLine("permission.Configure = {0}", permission.Configure); - output.WriteLine("permission.Read = {0}", permission.Read); - output.WriteLine("permission.Write = {0}", permission.Write); - } - } - - [Fact] - public async Task Should_get_queues() - { - await CreateTestQueue(TestQueue); - (await fixture.ManagementClient.GetQueuesAsync()).Count.Should().BeGreaterThan(0); - } - - - [Fact] - public async Task Should_get_queues_with_pagination() - { - foreach (var queue in await fixture.ManagementClient.GetQueuesAsync()) - await fixture.ManagementClient.DeleteQueueAsync(queue); - - await CreateTestQueue("1"); - await CreateTestQueue("2"); - - var firstPage = await fixture.ManagementClient.GetQueuesByPageAsync(new PageCriteria(1, 1)); - firstPage.Items.Count.Should().Be(1); - - var secondPage = await fixture.ManagementClient.GetQueuesByPageAsync(new PageCriteria(2, 1)); - secondPage.Items.Count.Should().Be(1); - } - - [Fact] - public async Task Should_get_queues_by_vhost() - { - await fixture.ManagementClient.CreateVhostAsync(TestVHost); - var vhost = await fixture.ManagementClient.GetVhostAsync(TestVHost); - vhost.Name.Should().Be(TestVHost); - - await CreateTestQueueInVhost($"{TestVHost}_{TestQueue}", vhost); - (await fixture.ManagementClient.GetQueuesAsync(vhost)).Count.Should().BeGreaterThan(0); - } - - [Fact] - public async Task Should_get_users() - { - var users = await fixture.ManagementClient.GetUsersAsync(); - - foreach (var user in users) output.WriteLine("user.Name = {0}", user.Name); - } - - [Fact] - public async Task Should_get_vhosts() - { - var vhosts = await fixture.ManagementClient.GetVhostsAsync(); - - foreach (var vhost in vhosts) output.WriteLine("vhost.Name = {0}", vhost.Name); - } - - [Fact] - public async Task Should_purge_a_queue() - { - var queue = await CreateTestQueue(TestQueue); - await fixture.ManagementClient.PurgeAsync(queue); - } - - [Fact] - public async Task Should_throw_when_trying_to_close_unknown_connection() - { - try - { - await fixture.ManagementClient.CloseConnectionAsync("unknown"); - } - catch (Exception e) - { - Assert.IsType(e); - } - } - - [Fact] - public async Task Should_be_able_to_create_shovel_parameter_on_queue() - { - var srcUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); - var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); - - var shovelName = "queue-shovel"; - - await fixture.ManagementClient.CreateShovelAsync( - vhostName: Vhost.Name, - shovelName, - new ParameterShovelValue - ( - SrcProtocol: AmqpProtocol.AMQP091, - SrcUri: srcUri.ToString(), - SrcQueue: "test-queue-src", - SrcExchange: null, - SrcExchangeKey: null, - SrcDeleteAfter: "never", - DestProtocol: AmqpProtocol.AMQP091, - DestUri: destUri.ToString(), - DestQueue: "test-queue-dest", - DestExchange: null, - AckMode: "on-confirm", - AddForwardHeaders: false - ) - ); - - var parameter = await fixture.ManagementClient.GetShovelAsync(Vhost.Name, shovelName); - - Assert.Equal(shovelName, parameter.Name); - } - - [Fact] - public async Task Should_be_able_to_create_shovel_parameter_on_exchange() - { - var srcUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); - var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); - - var shovelName = "exchange-shovel"; - - await fixture.ManagementClient.CreateShovelAsync( - vhostName: Vhost.Name, - shovelName, - new ParameterShovelValue - ( - SrcProtocol: AmqpProtocol.AMQP091, - SrcUri: srcUri.ToString(), - SrcExchange: "test-exchange-src", - SrcExchangeKey: null, - SrcQueue: null, - SrcDeleteAfter: "never", - DestProtocol: AmqpProtocol.AMQP091, - DestUri: destUri.ToString(), - DestExchange: "test-exchange-dest", - DestQueue: null, - AckMode: "on-confirm", - AddForwardHeaders: false - ) - ); - - var parameters = await fixture.ManagementClient.GetParametersAsync(); - - Assert.Contains(parameters, p => p.Name == shovelName); - } - - [Fact] - public async Task Should_be_able_to_throw_on_non_existant_shovel() - { - await Assert.ThrowsAsync(async () - => await fixture.ManagementClient.GetShovelAsync(Vhost.Name, "non-existant-shovel")); - } - - [Fact] - public async Task Should_be_able_to_get_existant_shovel() - { - var srcUri = new AmqpUri(fixture.Endpoint.Host, fixture.Endpoint.Port, fixture.User, fixture.Password); - var destUri = new AmqpUri($"{fixture.Endpoint.Host}-1", fixture.Endpoint.Port, fixture.User, fixture.Password); - - var shovelName = "exchange-shovel"; - - await fixture.ManagementClient.CreateShovelAsync( - vhostName: Vhost.Name, - shovelName: shovelName, - new ParameterShovelValue - ( - SrcProtocol: AmqpProtocol.AMQP091, - SrcUri: srcUri.ToString(), - SrcExchange: "test-exchange-src", - SrcExchangeKey: null, - SrcQueue: null, - SrcDeleteAfter: "never", - DestProtocol: AmqpProtocol.AMQP091, - DestUri: destUri.ToString(), - DestExchange: "test-exchange-dest", - DestQueue: null, - AckMode: "on-confirm", - AddForwardHeaders: false - ) - ); - - var shovel = await fixture.ManagementClient.GetShovelAsync(Vhost.Name, shovelName); - Assert.Contains(shovelName, shovel.Name); - } -} From 458454f4cb72b21a6f1399ce665f8948c5dc6a54 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Sun, 10 Dec 2023 23:38:37 +0200 Subject: [PATCH 15/33] Rename dsd to ManagementClientTests.cs --- .../{dsd => ManagementClientTests.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Source/EasyNetQ.Management.Client.IntegrationTests/{dsd => ManagementClientTests.cs} (100%) diff --git a/Source/EasyNetQ.Management.Client.IntegrationTests/dsd b/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs similarity index 100% rename from Source/EasyNetQ.Management.Client.IntegrationTests/dsd rename to Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs From e9b1713d375437863fffa25741a3e7ee583e91af Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 10:21:22 +0200 Subject: [PATCH 16/33] Rename JsonStringEnumConverterEx to JsonStringEnumConverterEx.cs --- .../{JsonStringEnumConverterEx => JsonStringEnumConverterEx.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Source/EasyNetQ.Management.Client/Serialization/{JsonStringEnumConverterEx => JsonStringEnumConverterEx.cs} (100%) diff --git a/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx b/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx.cs similarity index 100% rename from Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx rename to Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx.cs From 7df6ce3e93642f72587d7ff622885ef3daad727b Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 10:29:42 +0200 Subject: [PATCH 17/33] Update JsonStringEnumConverterEx.cs --- .../JsonStringEnumConverterEx.cs | 71 +++++++++---------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx.cs b/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx.cs index a4b16289..27685f48 100644 --- a/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx.cs +++ b/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx.cs @@ -2,54 +2,53 @@ using System.Text.Json.Serialization; using System.Text.Json; -namespace EasyNetQ.Management.Client.Serialization +namespace EasyNetQ.Management.Client.Serialization; + +// https://github.com/dotnet/runtime/issues/31081#issuecomment-848697673 +public class JsonStringEnumConverterEx : JsonConverter where TEnum : struct, Enum { - public class JsonStringEnumConverterEx : JsonConverter where TEnum : struct, System.Enum - { + private readonly Dictionary _enumToString = new Dictionary(); + private readonly Dictionary _stringToEnum = new Dictionary(); - private readonly Dictionary _enumToString = new Dictionary(); - private readonly Dictionary _stringToEnum = new Dictionary(); + public JsonStringEnumConverterEx() + { + var type = typeof(TEnum); + var values = Enum.GetValues(type); - public JsonStringEnumConverterEx() + foreach (TEnum value in values) { - var type = typeof(TEnum); - var values = System.Enum.GetValues(type); + var enumMember = type.GetMember(value.ToString())[0]; + var attr = enumMember.GetCustomAttributes(typeof(EnumMemberAttribute), false) + .Cast() + .FirstOrDefault(); - foreach (TEnum value in values) + if (attr?.Value != null) { - var enumMember = type.GetMember(value.ToString())[0]; - var attr = enumMember.GetCustomAttributes(typeof(EnumMemberAttribute), false) - .Cast() - .FirstOrDefault(); - - if (attr?.Value != null) - { - _enumToString.Add(value, attr.Value); - _stringToEnum.Add(attr.Value, value); - } - else - { - _enumToString.Add(value, value.ToString()); - _stringToEnum.Add(value.ToString(), value); - } + _enumToString.Add(value, attr.Value); + _stringToEnum.Add(attr.Value, value); } - } - - public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var stringValue = reader.GetString(); - - if (stringValue != null && _stringToEnum.TryGetValue(stringValue, out var enumValue)) + else { - return enumValue; + _enumToString.Add(value, value.ToString()); + _stringToEnum.Add(value.ToString(), value); } - - return default; } + } + + public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var stringValue = reader.GetString(); - public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options) + if (stringValue != null && _stringToEnum.TryGetValue(stringValue, out var enumValue)) { - writer.WriteStringValue(_enumToString[value]); + return enumValue; } + + return default; + } + + public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options) + { + writer.WriteStringValue(_enumToString[value]); } } From c4265edf9121a156680960658041a1347a09ab2a Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 12:00:50 +0200 Subject: [PATCH 18/33] Update JsonStringEnumConverterEx.cs internal class JsonStringEnumConverterEx --- .../Serialization/JsonStringEnumConverterEx.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx.cs b/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx.cs index 27685f48..8face71c 100644 --- a/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx.cs +++ b/Source/EasyNetQ.Management.Client/Serialization/JsonStringEnumConverterEx.cs @@ -5,7 +5,7 @@ namespace EasyNetQ.Management.Client.Serialization; // https://github.com/dotnet/runtime/issues/31081#issuecomment-848697673 -public class JsonStringEnumConverterEx : JsonConverter where TEnum : struct, Enum +internal class JsonStringEnumConverterEx : JsonConverter where TEnum : struct, Enum { private readonly Dictionary _enumToString = new Dictionary(); private readonly Dictionary _stringToEnum = new Dictionary(); From 446a529a4fc49fd167a7885408ec96837b91bf1f Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 13:12:39 +0200 Subject: [PATCH 19/33] Create QueueVersion.cs --- Source/EasyNetQ.Management.Client/Model/QueueVersion.cs | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 Source/EasyNetQ.Management.Client/Model/QueueVersion.cs diff --git a/Source/EasyNetQ.Management.Client/Model/QueueVersion.cs b/Source/EasyNetQ.Management.Client/Model/QueueVersion.cs new file mode 100644 index 00000000..e3da357e --- /dev/null +++ b/Source/EasyNetQ.Management.Client/Model/QueueVersion.cs @@ -0,0 +1,7 @@ +namespace EasyNetQ.Management.Client.Model; + +public enum QueueVersion +{ + V1 = 1, + V2 = 2 +} From 2eb304921a219ed2283e1cd3f2fa13622d84b1d4 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 13:14:34 +0200 Subject: [PATCH 20/33] Create JsonNumberEnumConverter.cs --- .../Serialization/JsonNumberEnumConverter.cs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 Source/EasyNetQ.Management.Client/Serialization/JsonNumberEnumConverter.cs diff --git a/Source/EasyNetQ.Management.Client/Serialization/JsonNumberEnumConverter.cs b/Source/EasyNetQ.Management.Client/Serialization/JsonNumberEnumConverter.cs new file mode 100644 index 00000000..7468c30c --- /dev/null +++ b/Source/EasyNetQ.Management.Client/Serialization/JsonNumberEnumConverter.cs @@ -0,0 +1,38 @@ +#if !NET8_0_OR_GREATER + +namespace System.Text.Json.Serialization; + +internal sealed class JsonNumberEnumConverter : JsonConverter where TEnum : struct, Enum +{ + private static readonly TypeCode s_enumTypeCode = Type.GetTypeCode(typeof(TEnum)); + static JsonNumberEnumConverter() + { + switch (s_enumTypeCode) + { + case TypeCode.Int32: break; + default: throw new NotImplementedException($"{typeof(JsonNumberEnumConverter)}: underlying type {s_enumTypeCode} is not supported"); + } + } + + public JsonNumberEnumConverter() { } + + public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + switch (s_enumTypeCode) + { + case TypeCode.Int32: return (TEnum)(object)reader.GetInt32(); + default: throw new NotImplementedException(); + } + } + + public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options) + { + switch (s_enumTypeCode) + { + case TypeCode.Int32: writer.WriteNumberValue((int)(object)value); break; + default: throw new NotImplementedException(); + } + } +} + +#endif From c5d6d7ea5a7e6d75802d81e85f32ad85afe8a7de Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 13:15:23 +0200 Subject: [PATCH 21/33] Update PolicyDefinition.cs --- Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs b/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs index d1c3bc3f..d04c3687 100644 --- a/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs +++ b/Source/EasyNetQ.Management.Client/Model/PolicyDefinition.cs @@ -36,8 +36,8 @@ public record PolicyDefinition HaPromote? HaPromoteOnShutdown = null, [property: JsonPropertyName("ha-promote-on-failure"), JsonConverter(typeof(JsonStringEnumConverterEx))] HaPromote? HaPromoteOnFailure = null, - [property: JsonPropertyName("queue-version")] - uint? QueueVersion = null, + [property: JsonPropertyName("queue-version"), JsonConverter(typeof(JsonNumberEnumConverter))] + QueueVersion? QueueVersion = null, [property: JsonPropertyName("queue-master-locator"), JsonConverter(typeof(JsonStringEnumConverterEx))] QueueLocator? QueueMasterLocator = null, From 135b9a4544e7759fea11fed912dac730139fa881 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 13:16:04 +0200 Subject: [PATCH 22/33] Update ManagementClientTests.cs --- .../ManagementClientTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs b/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs index d0354815..92fee6d4 100644 --- a/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs +++ b/Source/EasyNetQ.Management.Client.IntegrationTests/ManagementClientTests.cs @@ -218,7 +218,7 @@ public async Task Should_be_able_to_create_all_the_definitions_in_a_policy() const HaSyncMode haSyncMode = HaSyncMode.Automatic; const HaPromote haPromoteOnFailure = HaPromote.Always; const HaPromote haPromoteOnShutdown = HaPromote.WhenSynced; - const uint queueVersion = 1; + QueueVersion queueVersion = fixture.RabbitmqVersion >= new Version("3.12") ? QueueVersion.V2 : QueueVersion.V1; const QueueLocator queueMasterLocator = QueueLocator.ClientLocal; const uint deliveryLimit = 3; const Model.DeadLetterStrategy deadLetterStrategy = Model.DeadLetterStrategy.AtLeastOnce; From 39a523fe5a1a042d5f438d120ca216d694c83dce Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 13:17:17 +0200 Subject: [PATCH 23/33] Update EasyNetQ.Management.Client.approved.txt --- .../EasyNetQ.Management.Client.approved.txt | 95 ++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/Source/EasyNetQ.Management.Client.ApprovalTests/EasyNetQ.Management.Client.approved.txt b/Source/EasyNetQ.Management.Client.ApprovalTests/EasyNetQ.Management.Client.approved.txt index 9878a6cd..fe4cf430 100644 --- a/Source/EasyNetQ.Management.Client.ApprovalTests/EasyNetQ.Management.Client.approved.txt +++ b/Source/EasyNetQ.Management.Client.ApprovalTests/EasyNetQ.Management.Client.approved.txt @@ -545,6 +545,13 @@ namespace EasyNetQ.Management.Client.Model public int Credit { get; init; } public bool Drain { get; init; } } + public enum DeadLetterStrategy + { + [System.Runtime.Serialization.EnumMember(Value="at-most-once")] + AtMostOnce = 0, + [System.Runtime.Serialization.EnumMember(Value="at-least-once")] + AtLeastOnce = 1, + } public class Definitions : System.IEquatable { public Definitions(string RabbitVersion, System.Collections.Generic.IReadOnlyList Users, System.Collections.Generic.IReadOnlyList Vhosts, System.Collections.Generic.IReadOnlyList Permissions, System.Collections.Generic.IReadOnlyList Queues, System.Collections.Generic.IReadOnlyList Exchanges, System.Collections.Generic.IReadOnlyList Bindings) { } @@ -625,6 +632,13 @@ namespace EasyNetQ.Management.Client.Model public long? ExactlyCount { get; init; } public System.Collections.Generic.IReadOnlyList? Nodes { get; init; } } + public enum HaPromote + { + [System.Runtime.Serialization.EnumMember(Value="when-synced")] + WhenSynced = 0, + [System.Runtime.Serialization.EnumMember(Value="always")] + Always = 1, + } public enum HaSyncMode { Manual = 0, @@ -813,6 +827,15 @@ namespace EasyNetQ.Management.Client.Model public int Exchanges { get; init; } public int Queues { get; init; } } + public enum Overflow + { + [System.Runtime.Serialization.EnumMember(Value="drop-head")] + DropHead = 0, + [System.Runtime.Serialization.EnumMember(Value="reject-publish")] + RejectPublish = 1, + [System.Runtime.Serialization.EnumMember(Value="reject-publish-dlx")] + RejectPublishDlx = 2, + } public class Overview : System.IEquatable { public Overview(string ManagementVersion, System.Collections.Generic.IReadOnlyList ExchangeTypes, string RabbitmqVersion, string ErlangVersion, EasyNetQ.Management.Client.Model.MessageStats MessageStats, EasyNetQ.Management.Client.Model.QueueTotals QueueTotals, EasyNetQ.Management.Client.Model.ObjectTotals ObjectTotals, string Node, System.Collections.Generic.IReadOnlyList Listeners, System.Collections.Generic.IReadOnlyList Contexts) { } @@ -931,13 +954,45 @@ namespace EasyNetQ.Management.Client.Model } public class PolicyDefinition : System.IEquatable { - public PolicyDefinition(EasyNetQ.Management.Client.Model.HaMode? HaMode = default, EasyNetQ.Management.Client.Model.HaParams? HaParams = null, EasyNetQ.Management.Client.Model.HaSyncMode? HaSyncMode = default, int? HaSyncBatchSize = default, string? FederationUpstream = null, string? FederationUpstreamSet = null, string? AlternateExchange = null, string? DeadLetterExchange = null, string? DeadLetterRoutingKey = null, string? QueueMode = null, uint? MessageTtl = default, uint? Expires = default, uint? MaxLength = default) { } + public PolicyDefinition( + uint? MaxLength = default, + long? MaxLengthBytes = default, + EasyNetQ.Management.Client.Model.Overflow? Overflow = default, + uint? Expires = default, + string? DeadLetterExchange = null, + string? DeadLetterRoutingKey = null, + uint? MessageTtl = default, + uint? ConsumerTimeout = default, + EasyNetQ.Management.Client.Model.HaMode? HaMode = default, + EasyNetQ.Management.Client.Model.HaParams? HaParams = null, + EasyNetQ.Management.Client.Model.HaSyncMode? HaSyncMode = default, + int? HaSyncBatchSize = default, + EasyNetQ.Management.Client.Model.HaPromote? HaPromoteOnShutdown = default, + EasyNetQ.Management.Client.Model.HaPromote? HaPromoteOnFailure = default, + EasyNetQ.Management.Client.Model.QueueVersion? QueueVersion = default, + EasyNetQ.Management.Client.Model.QueueLocator? QueueMasterLocator = default, + uint? DeliveryLimit = default, + EasyNetQ.Management.Client.Model.DeadLetterStrategy? DeadLetterStrategy = default, + EasyNetQ.Management.Client.Model.QueueLocator? QueueLeaderLocator = default, + string? MaxAge = null, + uint? StreamMaxSegmentSizeBytes = default, + string? AlternateExchange = null, + string? FederationUpstream = null, + string? FederationUpstreamSet = null, + string? QueueMode = null) { } [System.Text.Json.Serialization.JsonPropertyName("alternate-exchange")] public string? AlternateExchange { get; init; } + [System.Text.Json.Serialization.JsonPropertyName("consumer-timeout")] + public uint? ConsumerTimeout { get; init; } [System.Text.Json.Serialization.JsonPropertyName("dead-letter-exchange")] public string? DeadLetterExchange { get; init; } [System.Text.Json.Serialization.JsonPropertyName("dead-letter-routing-key")] public string? DeadLetterRoutingKey { get; init; } + [System.Text.Json.Serialization.JsonConverter(typeof(EasyNetQ.Management.Client.Serialization.JsonStringEnumConverterEx?))] + [System.Text.Json.Serialization.JsonPropertyName("dead-letter-strategy")] + public EasyNetQ.Management.Client.Model.DeadLetterStrategy? DeadLetterStrategy { get; init; } + [System.Text.Json.Serialization.JsonPropertyName("delivery-limit")] + public uint? DeliveryLimit { get; init; } [System.Text.Json.Serialization.JsonPropertyName("expires")] public uint? Expires { get; init; } [System.Text.Json.Serialization.JsonPropertyName("federation-upstream-set")] @@ -948,16 +1003,40 @@ namespace EasyNetQ.Management.Client.Model public EasyNetQ.Management.Client.Model.HaMode? HaMode { get; init; } [System.Text.Json.Serialization.JsonPropertyName("ha-params")] public EasyNetQ.Management.Client.Model.HaParams? HaParams { get; init; } + [System.Text.Json.Serialization.JsonConverter(typeof(EasyNetQ.Management.Client.Serialization.JsonStringEnumConverterEx?))] + [System.Text.Json.Serialization.JsonPropertyName("ha-promote-on-failure")] + public EasyNetQ.Management.Client.Model.HaPromote? HaPromoteOnFailure { get; init; } + [System.Text.Json.Serialization.JsonConverter(typeof(EasyNetQ.Management.Client.Serialization.JsonStringEnumConverterEx?))] + [System.Text.Json.Serialization.JsonPropertyName("ha-promote-on-shutdown")] + public EasyNetQ.Management.Client.Model.HaPromote? HaPromoteOnShutdown { get; init; } [System.Text.Json.Serialization.JsonPropertyName("ha-sync-batch-size")] public int? HaSyncBatchSize { get; init; } [System.Text.Json.Serialization.JsonPropertyName("ha-sync-mode")] public EasyNetQ.Management.Client.Model.HaSyncMode? HaSyncMode { get; init; } + [System.Text.Json.Serialization.JsonPropertyName("max-age")] + public string? MaxAge { get; init; } + [System.Text.Json.Serialization.JsonPropertyName("max-length-bytes")] + public long? MaxLengthBytes { get; init; } [System.Text.Json.Serialization.JsonPropertyName("max-length")] public uint? MaxLength { get; init; } [System.Text.Json.Serialization.JsonPropertyName("message-ttl")] public uint? MessageTtl { get; init; } + [System.Text.Json.Serialization.JsonConverter(typeof(EasyNetQ.Management.Client.Serialization.JsonStringEnumConverterEx?))] + [System.Text.Json.Serialization.JsonPropertyName("overflow")] + public EasyNetQ.Management.Client.Model.Overflow? Overflow { get; init; } + [System.Text.Json.Serialization.JsonConverter(typeof(EasyNetQ.Management.Client.Serialization.JsonStringEnumConverterEx?))] + [System.Text.Json.Serialization.JsonPropertyName("queue-leader-locator")] + public EasyNetQ.Management.Client.Model.QueueLocator? QueueLeaderLocator { get; init; } + [System.Text.Json.Serialization.JsonConverter(typeof(EasyNetQ.Management.Client.Serialization.JsonStringEnumConverterEx?))] + [System.Text.Json.Serialization.JsonPropertyName("queue-master-locator")] + public EasyNetQ.Management.Client.Model.QueueLocator? QueueMasterLocator { get; init; } [System.Text.Json.Serialization.JsonPropertyName("queue-mode")] public string? QueueMode { get; init; } + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonNumberEnumConverter?))] + [System.Text.Json.Serialization.JsonPropertyName("queue-version")] + public EasyNetQ.Management.Client.Model.QueueVersion? QueueVersion { get; init; } + [System.Text.Json.Serialization.JsonPropertyName("stream-max-segment-size-bytes")] + public uint? StreamMaxSegmentSizeBytes { get; init; } } public class PolicyInfo : System.IEquatable { @@ -1047,6 +1126,13 @@ namespace EasyNetQ.Management.Client.Model public bool Durable { get; init; } public string Name { get; init; } } + public enum QueueLocator + { + [System.Runtime.Serialization.EnumMember(Value="client-local")] + ClientLocal = 0, + [System.Runtime.Serialization.EnumMember(Value="balanced")] + Balanced = 1, + } public class QueueName : System.IEquatable { public QueueName(string Name, string Vhost) { } @@ -1063,6 +1149,11 @@ namespace EasyNetQ.Management.Client.Model public long MessagesUnacknowledged { get; init; } public long Messages { get; init; } } + public enum QueueVersion + { + V1 = 1, + V2 = 2, + } public class RatesCriteria : System.IEquatable { public RatesCriteria(int MsgRatesAge, int MsgRatesIncr) { } @@ -1124,4 +1215,4 @@ namespace EasyNetQ.Management.Client.Model public string Name { get; init; } public bool Tracing { get; init; } } -} \ No newline at end of file +} From 8510488b919efc5aff24b224396cb70a52362526 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 18:05:22 +0200 Subject: [PATCH 24/33] Update EasyNetQ.Management.Client.approved.txt - remove last EOL From 260db21021139aafa3251b137cd2812618b3827a Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 18:09:01 +0200 Subject: [PATCH 25/33] Update EasyNetQ.Management.Client.approved.txt - EOL From 705b326b68ba06f1a10a1b0654d7b68bd255ec2a Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 18:54:40 +0200 Subject: [PATCH 26/33] Create .gitattributes --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..49726797 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.approved.txt whitespace=-blank-at-eof From ad345d281d04c295fb310163c9b5dffd1a716aec Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 18:55:16 +0200 Subject: [PATCH 27/33] Update EasyNetQ.Management.Client.approved.txt From 2a294933b4e13e99a86dc2365b7e0bec755bc072 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 21:38:05 +0200 Subject: [PATCH 28/33] Update .gitattributes --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 49726797..8b74fda4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -*.approved.txt whitespace=-blank-at-eof +*.approved.txt text -blank-at-eof From 35469bf1253492ba21b579859445312b8298fb01 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 21:38:29 +0200 Subject: [PATCH 29/33] Update EasyNetQ.Management.Client.approved.txt From e060f72f55e6713eb614cd7c8f36a2f952e737e4 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 21:44:00 +0200 Subject: [PATCH 30/33] Update .gitattributes --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 8b74fda4..4e57324b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -*.approved.txt text -blank-at-eof +*.approved.txt text eol=lf whitespace=blank-at-eol,-blank-at-eof From a8b9a1b40a496690f92773c4cf505c1ec7f6297a Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 21:44:23 +0200 Subject: [PATCH 31/33] Update EasyNetQ.Management.Client.approved.txt From 4e14634d6495c0d880839746c77801cc52c5b8c3 Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 21:53:29 +0200 Subject: [PATCH 32/33] remove eof eol --- .../EasyNetQ.Management.Client.approved.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/EasyNetQ.Management.Client.ApprovalTests/EasyNetQ.Management.Client.approved.txt b/Source/EasyNetQ.Management.Client.ApprovalTests/EasyNetQ.Management.Client.approved.txt index fe4cf430..2b9de93a 100644 --- a/Source/EasyNetQ.Management.Client.ApprovalTests/EasyNetQ.Management.Client.approved.txt +++ b/Source/EasyNetQ.Management.Client.ApprovalTests/EasyNetQ.Management.Client.approved.txt @@ -1215,4 +1215,4 @@ namespace EasyNetQ.Management.Client.Model public string Name { get; init; } public bool Tracing { get; init; } } -} +} \ No newline at end of file From 71d8cf85a5cc2826af92b011982403269eb678ff Mon Sep 17 00:00:00 2001 From: inikulshin Date: Mon, 11 Dec 2023 21:55:39 +0200 Subject: [PATCH 33/33] delete .gitattributes --- .gitattributes | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 4e57324b..00000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.approved.txt text eol=lf whitespace=blank-at-eol,-blank-at-eof