From d62b301fa149ab7ea2f2e716d80693292b5ef99b Mon Sep 17 00:00:00 2001 From: ZLoo Date: Wed, 31 Jul 2024 22:51:16 +0300 Subject: [PATCH 1/2] CA1062#Aspire.Hosting.Nats --- .../NatsBuilderExtensions.cs | 26 ++++- src/Aspire.Hosting.Nats/NatsServerResource.cs | 8 +- .../NatsPublicApiTests.cs | 101 ++++++++++++++++++ 3 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 tests/Aspire.Hosting.Nats.Tests/NatsPublicApiTests.cs diff --git a/src/Aspire.Hosting.Nats/NatsBuilderExtensions.cs b/src/Aspire.Hosting.Nats/NatsBuilderExtensions.cs index 470d03f261b..1929ef06ddd 100644 --- a/src/Aspire.Hosting.Nats/NatsBuilderExtensions.cs +++ b/src/Aspire.Hosting.Nats/NatsBuilderExtensions.cs @@ -21,6 +21,9 @@ public static class NatsBuilderExtensions /// The . public static IResourceBuilder AddNats(this IDistributedApplicationBuilder builder, string name, int? port = null) { + ArgumentNullException.ThrowIfNull(builder); + ArgumentNullException.ThrowIfNull(name); + var nats = new NatsServerResource(name); return builder.AddResource(nats) .WithEndpoint(targetPort: 4222, port: port, name: NatsServerResource.PrimaryEndpointName) @@ -54,7 +57,11 @@ public static IResourceBuilder WithJetStream(this IResourceB /// The resource builder. /// The . public static IResourceBuilder WithJetStream(this IResourceBuilder builder) - => builder.WithArgs("-js"); + { + ArgumentNullException.ThrowIfNull(builder); + + return builder.WithArgs("-js"); + } /// /// Adds a named volume for the data folder to a NATS container resource. @@ -64,8 +71,13 @@ public static IResourceBuilder WithJetStream(this IResourceB /// A flag that indicates if this is a read-only volume. /// The . public static IResourceBuilder WithDataVolume(this IResourceBuilder builder, string? name = null, bool isReadOnly = false) - => builder.WithVolume(name ?? VolumeNameGenerator.CreateVolumeName(builder, "data"), "/var/lib/nats", isReadOnly) - .WithArgs("-sd", "/var/lib/nats"); + { + ArgumentNullException.ThrowIfNull(builder); + + return builder.WithVolume(name ?? VolumeNameGenerator.CreateVolumeName(builder, "data"), "/var/lib/nats", + isReadOnly) + .WithArgs("-sd", "/var/lib/nats"); + } /// /// Adds a bind mount for the data folder to a NATS container resource. @@ -75,7 +87,11 @@ public static IResourceBuilder WithDataVolume(this IResource /// A flag that indicates if this is a read-only mount. /// The . public static IResourceBuilder WithDataBindMount(this IResourceBuilder builder, string source, bool isReadOnly = false) - => builder.WithBindMount(source, "/var/lib/nats", isReadOnly) - .WithArgs("-sd", "/var/lib/nats"); + { + ArgumentNullException.ThrowIfNull(builder); + ArgumentNullException.ThrowIfNull(source); + return builder.WithBindMount(source, "/var/lib/nats", isReadOnly) + .WithArgs("-sd", "/var/lib/nats"); + } } diff --git a/src/Aspire.Hosting.Nats/NatsServerResource.cs b/src/Aspire.Hosting.Nats/NatsServerResource.cs index de5937c1587..38ef0db7a2a 100644 --- a/src/Aspire.Hosting.Nats/NatsServerResource.cs +++ b/src/Aspire.Hosting.Nats/NatsServerResource.cs @@ -8,7 +8,7 @@ namespace Aspire.Hosting.ApplicationModel; /// /// The name of the resource. -public class NatsServerResource(string name) : ContainerResource(name), IResourceWithConnectionString +public class NatsServerResource(string name) : ContainerResource(PassThroughNonNull(name)), IResourceWithConnectionString { internal const string PrimaryEndpointName = "tcp"; internal const string PrimaryNatsSchemeName = "nats"; @@ -26,4 +26,10 @@ public class NatsServerResource(string name) : ContainerResource(name), IResourc public ReferenceExpression ConnectionStringExpression => ReferenceExpression.Create( $"{PrimaryNatsSchemeName}://{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}"); + + private static string PassThroughNonNull(string name) + { + ArgumentNullException.ThrowIfNull(name); + return name; + } } diff --git a/tests/Aspire.Hosting.Nats.Tests/NatsPublicApiTests.cs b/tests/Aspire.Hosting.Nats.Tests/NatsPublicApiTests.cs new file mode 100644 index 00000000000..7c8fc01eb6c --- /dev/null +++ b/tests/Aspire.Hosting.Nats.Tests/NatsPublicApiTests.cs @@ -0,0 +1,101 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Aspire.Hosting.ApplicationModel; +using Aspire.Hosting.Utils; +using Xunit; + +namespace Aspire.Hosting.Nats.Tests; + +public class NatsPublicApiTests +{ + #region NatsBuilderExtensions + + [Fact] + public void AddNatsContainerShouldThrowWhenBuilderIsNull() + { + IDistributedApplicationBuilder builder = null!; + const string name = "Nats"; + + var action = () => builder.AddNats(name); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(builder), exception.ParamName); + } + + [Fact] + public void AddNatsContainerShouldThrowWhenNameIsNull() + { + var builder = TestDistributedApplicationBuilder.Create(); + string name = null!; + + var action = () => builder.AddNats(name); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(name), exception.ParamName); + } + + [Fact] + public void WithJetStreamShouldThrowWhenBuilderIsNull() + { + IResourceBuilder builder = null!; + + var action = () => builder.WithJetStream(); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(builder), exception.ParamName); + } + + [Fact] + public void WithDataVolumeShouldThrowWhenBuilderIsNull() + { + IResourceBuilder builder = null!; + + var action = () => builder.WithDataVolume(); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(builder), exception.ParamName); + } + + [Fact] + public void WithDataBindMountShouldThrowWhenBuilderIsNull() + { + IResourceBuilder builder = null!; + const string source = "/data"; + + var action = () => builder.WithDataBindMount(source); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(builder), exception.ParamName); + } + + [Fact] + public void WithDataBindMountShouldThrowWhenSourceIsNull() + { + var builder = TestDistributedApplicationBuilder.Create(); + var nats = builder.AddNats("Nats"); + string source = null!; + + var action = () => nats.WithDataBindMount(source); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(source), exception.ParamName); + } + + #endregion + + #region NatsServerResource + + [Fact] + public void CtorNatsServerResourceShouldThrowWhenNameIsNull() + { + string name = null!; + + var action = () => new NatsServerResource(name); + + var exception = Assert.Throws(action); + Assert.Equal(nameof(name), exception.ParamName); + } + + #endregion +} From 2fd846ab01d1ed6e06aade4f87e7cd0d3b9c5d59 Mon Sep 17 00:00:00 2001 From: ZLoo Date: Thu, 1 Aug 2024 23:11:43 +0300 Subject: [PATCH 2/2] Remove Address --- src/Aspire.Hosting.Nats/NatsServerResource.cs | 12 ++++++------ .../Aspire.Hosting.Nats.Tests/NatsPublicApiTests.cs | 8 -------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/Aspire.Hosting.Nats/NatsServerResource.cs b/src/Aspire.Hosting.Nats/NatsServerResource.cs index 38ef0db7a2a..a4d60962e6a 100644 --- a/src/Aspire.Hosting.Nats/NatsServerResource.cs +++ b/src/Aspire.Hosting.Nats/NatsServerResource.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; + namespace Aspire.Hosting.ApplicationModel; /// @@ -8,7 +11,7 @@ namespace Aspire.Hosting.ApplicationModel; /// /// The name of the resource. -public class NatsServerResource(string name) : ContainerResource(PassThroughNonNull(name)), IResourceWithConnectionString +public class NatsServerResource(string name) : ContainerResource(ThrowIfNull(name)), IResourceWithConnectionString { internal const string PrimaryEndpointName = "tcp"; internal const string PrimaryNatsSchemeName = "nats"; @@ -27,9 +30,6 @@ public class NatsServerResource(string name) : ContainerResource(PassThroughNonN ReferenceExpression.Create( $"{PrimaryNatsSchemeName}://{PrimaryEndpoint.Property(EndpointProperty.Host)}:{PrimaryEndpoint.Property(EndpointProperty.Port)}"); - private static string PassThroughNonNull(string name) - { - ArgumentNullException.ThrowIfNull(name); - return name; - } + private static string ThrowIfNull([NotNull] string? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null) + => argument ?? throw new ArgumentNullException(paramName); } diff --git a/tests/Aspire.Hosting.Nats.Tests/NatsPublicApiTests.cs b/tests/Aspire.Hosting.Nats.Tests/NatsPublicApiTests.cs index 7c8fc01eb6c..e26f63b27cf 100644 --- a/tests/Aspire.Hosting.Nats.Tests/NatsPublicApiTests.cs +++ b/tests/Aspire.Hosting.Nats.Tests/NatsPublicApiTests.cs @@ -9,8 +9,6 @@ namespace Aspire.Hosting.Nats.Tests; public class NatsPublicApiTests { - #region NatsBuilderExtensions - [Fact] public void AddNatsContainerShouldThrowWhenBuilderIsNull() { @@ -82,10 +80,6 @@ public void WithDataBindMountShouldThrowWhenSourceIsNull() Assert.Equal(nameof(source), exception.ParamName); } - #endregion - - #region NatsServerResource - [Fact] public void CtorNatsServerResourceShouldThrowWhenNameIsNull() { @@ -96,6 +90,4 @@ public void CtorNatsServerResourceShouldThrowWhenNameIsNull() var exception = Assert.Throws(action); Assert.Equal(nameof(name), exception.ParamName); } - - #endregion }