Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -403,10 +403,12 @@ static bool HasImplicitValueWhenNotSpecified(ParameterInfo paramInfo)
{
return paramInfo.HasDefaultValue
// parameters of type IConfiguration are implicitly populated with provided Configuration
|| paramInfo.ParameterType == typeof(IConfiguration);
|| paramInfo.ParameterType == typeof(IConfiguration)
|| paramInfo.IsDefined(typeof(ParamArrayAttribute), false)
|| paramInfo.CustomAttributes.Any(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.ParamCollectionAttribute");
}

object? GetImplicitValueForNotSpecifiedKey(ParameterInfo parameter, MethodInfo methodToInvoke)
internal object? GetImplicitValueForNotSpecifiedKey(ParameterInfo parameter, MethodInfo methodToInvoke)
{
if (!HasImplicitValueWhenNotSpecified(parameter))
{
Expand All @@ -429,7 +431,12 @@ static bool HasImplicitValueWhenNotSpecified(ParameterInfo paramInfo)
$"This is not supported when only a `IConfigSection` has been provided. (method '{methodToInvoke}')");
}

return parameter.DefaultValue;
if (parameter.IsDefined(typeof(ParamArrayAttribute), false) && parameter.ParameterType.GetElementType() is { } elementType)
{
return Array.CreateInstance(elementType, 0);
}

return parameter.HasDefaultValue ? parameter.DefaultValue : null;
}

internal static MethodInfo? SelectConfigurationMethod(IReadOnlyCollection<MethodInfo> candidateMethods, string name, IReadOnlyCollection<string> suppliedArgumentNames)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,4 +329,67 @@ public void ParseLogEventLevelThrowsForInvalidValues(string value)
{
Assert.Throws<InvalidOperationException>(() => ConfigurationReader.ParseLogEventLevel(value));
}

[Fact]
public void ParamsStringArrayParameter_WithNoArgsSupplied_IsMatchedAsOptional()
{
var candidateMethods = typeof(DummyLoggerConfigurationExtensions)
.GetTypeInfo()
.DeclaredMethods
.ToList();

var selected = ConfigurationReader.SelectConfigurationMethod(
candidateMethods, "DummyParamsArray", Array.Empty<string>());

Assert.NotNull(selected);
}

[Fact]
public void ParamsStringArrayParameter_ImplicitValueIsEmptyArray()
{
var reader = new ConfigurationReader(
JsonStringConfigSource.LoadSection("{}", "Serilog"),
AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies),
new ConfigurationReaderOptions());

var method = typeof(DummyLoggerConfigurationExtensions).GetMethod("DummyParamsArray")!;
var param = method.GetParameters().Last(); // params string[] values

var result = reader.GetImplicitValueForNotSpecifiedKey(param, method);

var array = Assert.IsType<string[]>(result);
Assert.Empty(array);
}

[Fact]
public void ParamsEnumerableParameter_GracefullyReturnsDefaultValue()
{
var reader = new ConfigurationReader(
JsonStringConfigSource.LoadSection("{}", "Serilog"),
AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies),
new ConfigurationReaderOptions());

var method = typeof(DummyLoggerConfigurationExtensions).GetMethod("DummyParamsEnumerable")!;
var param = method.GetParameters().Last(); // params IEnumerable<string>

var result = reader.GetImplicitValueForNotSpecifiedKey(param, method);

Assert.Null(result);
}

[Fact]
public void ParamsSpanParameter_GracefullyReturnsDefaultValue()
{
var reader = new ConfigurationReader(
JsonStringConfigSource.LoadSection("{}", "Serilog"),
AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies),
new ConfigurationReaderOptions());

var method = typeof(DummyLoggerConfigurationExtensions).GetMethod("DummyParamsSpan")!;
var param = method.GetParameters().Last(); // params ReadOnlySpan<string>

var result = reader.GetImplicitValueForNotSpecifiedKey(param, method);

Assert.Null(result);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Serilog.Configuration;
using Serilog.Events;
using Serilog.Formatting;
using TestDummies;

namespace Serilog.Settings.Configuration.Tests;

Expand All @@ -24,4 +25,25 @@ static class DummyLoggerConfigurationExtensions
{
return null;
}

public static LoggerConfiguration DummyParamsArray(
this LoggerSinkConfiguration loggerSinkConfiguration,
params string[] values)
{
return loggerSinkConfiguration.Sink(new DummyParamsSink(values));
}

public static LoggerConfiguration DummyParamsEnumerable(
this LoggerSinkConfiguration loggerSinkConfiguration,
params IEnumerable<string> values)
{
return loggerSinkConfiguration.Sink(new DummyParamsSink(values.ToArray()));
}

public static LoggerConfiguration DummyParamsSpan(
this LoggerSinkConfiguration loggerSinkConfiguration,
params ReadOnlySpan<string> values)
{
return loggerSinkConfiguration.Sink(new DummyParamsSink(values.ToArray()));
}
}
21 changes: 21 additions & 0 deletions test/Serilog.Settings.Configuration.Tests/DummyParamsSink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Serilog.Core;
using Serilog.Events;

namespace TestDummies;

public class DummyParamsSink : ILogEventSink
{
public static string[]? LastValues { get; private set; }

public DummyParamsSink(params string[] values)
{
LastValues = values;
}

public void Emit(LogEvent logEvent) { }

public static void Reset()
{
LastValues = null;
}
}
Loading