@ -2,7 +2,7 @@ using System.IO.Abstractions;
using System.IO.Abstractions.Extensions ;
using System.IO.Abstractions.TestingHelpers ;
using System.Text ;
using Auto Fixture.NUnit3 ;
using Auto fac ;
using Common ;
using Common.Extensions ;
using FluentAssertions ;
@ -12,7 +12,10 @@ using NSubstitute;
using NUnit.Framework ;
using Recyclarr.Config ;
using Recyclarr.TestLibrary ;
using Serilog.Sinks.TestCorrelator ;
using TestLibrary ;
using TestLibrary.AutoFixture ;
using TrashLib.Config.Secrets ;
using TrashLib.Services.Sonarr.Config ;
using TrashLib.TestLibrary ;
using YamlDotNet.Core ;
@ -29,6 +32,12 @@ public class ConfigurationLoaderTest : IntegrationFixture
return new StringReader ( testData . ReadData ( file ) ) ;
}
protected override void RegisterExtraTypes ( ContainerBuilder builder )
{
base . RegisterExtraTypes ( builder ) ;
builder . RegisterMockFor < IValidator < TestConfig > > ( ) ;
}
[Test]
public void Load_many_iterations_of_config ( )
{
@ -44,7 +53,8 @@ public class ConfigurationLoaderTest : IntegrationFixture
var fileData = new ( string , string ) [ ]
{
( baseDir . File ( "config1.yml" ) . FullName , MockYaml ( 1 , 2 ) ) ,
( baseDir . File ( "config2.yml" ) . FullName , MockYaml ( 3 ) )
( baseDir . File ( "config2.yml" ) . FullName , MockYaml ( 3 ) ) ,
( baseDir . File ( "config3.yml" ) . FullName , "bad yaml" )
} ;
foreach ( var ( file , data ) in fileData )
@ -101,32 +111,43 @@ public class ConfigurationLoaderTest : IntegrationFixture
} ) ;
}
[Test , AutoMockData ]
public void Throw_when_validation_fails(
[Frozen] IValidator < TestConfig > validator ,
ConfigurationLoader < TestConfig > configLoader )
[Test ]
public void Skip_when_validation_fails( )
// [Frozen] IValidator<TestConfig> validator ,
// ConfigurationLoader<TestConfig> configLoader )
{
var validator = Resolve < IValidator < TestConfig > > ( ) ;
var sut = Resolve < ConfigurationLoader < TestConfig > > ( ) ;
// force the validator to return a validation error
validator . Validate ( Arg . Any < TestConfig > ( ) ) . Returns ( new ValidationResult
{
Errors = { new ValidationFailure ( "PropertyName" , "Test Validation Failure" ) }
Errors =
{
new ValidationFailure ( "PropertyName" , "Test Validation Failure" ) ,
new ValidationFailure ( "Another" , "This is yet another failure" )
}
} ) ;
const string testYml = @ "
fubar :
- api_key : abc
instance1 :
api_key : abc
";
Action act = ( ) = > configLoader . LoadFromStream ( new StringReader ( testYml ) , "fubar" ) ;
var result = sut . LoadFromStream ( new StringReader ( testYml ) , "fubar" ) ;
act. Should ( ) . Throw < ConfigurationException > ( ) ;
result. Should ( ) . BeEmpty ( ) ;
}
[Test , AutoMockData ]
public void Validation_success_does_not_throw ( ConfigurationLoader < TestConfig > configLoader )
[Test ]
public void Validation_success_does_not_throw ( )
{
var configLoader = Resolve < ConfigurationLoader < TestConfig > > ( ) ;
const string testYml = @ "
fubar :
- api_key : abc
instanceA :
api_key : abc
";
Action act = ( ) = > configLoader . LoadFromStream ( new StringReader ( testYml ) , "fubar" ) ;
act . Should ( ) . NotThrow ( ) ;
@ -139,9 +160,10 @@ fubar:
const string testYml = @ "
sonarr :
- api_key : ! secret api_key
base_url : ! secret 123 GARBAGE_
release_profiles :
instance1 :
api_key : ! secret api_key
base_url : ! secret 123 GARBAGE_
release_profiles :
- trash_ids :
- ! secret secret_rp
";
@ -157,6 +179,7 @@ secret_rp: 1234567
{
new ( )
{
Name = "instance1" ,
ApiKey = "95283e6b156c42f3af8a9b16173f876b" ,
BaseUrl = "https://radarr:7878" ,
ReleaseProfiles = new List < ReleaseProfileConfig >
@ -176,48 +199,55 @@ secret_rp: 1234567
[Test]
public void Throw_when_referencing_invalid_secret ( )
{
using var logContext = TestCorrelator . CreateContext ( ) ;
var configLoader = Resolve < ConfigurationLoader < SonarrConfiguration > > ( ) ;
const string testYml = @ "
sonarr :
- api_key : ! secret api_key
base_url : fake_url
instance2 :
api_key : ! secret api_key
base_url : fake_url
";
const string secretsYml = @ "
no_api_key : 95283e6 b156c42f3af8a9b16173f876b
";
const string secretsYml = "no_api_key: 95283e6b156c42f3af8a9b16173f876b" ;
Fs . AddFile ( Paths . SecretsPath . FullName , new MockFileData ( secretsYml ) ) ;
Action act = ( ) = > configLoader . LoadFromStream ( new StringReader ( testYml ) , "sonarr" ) ;
act . Should ( ) . Throw < YamlException > ( ) . WithMessage ( "api_key is not defined in secrets.yml." ) ;
var act = ( ) = > configLoader . LoadFromStream ( new StringReader ( testYml ) , "sonarr" ) ;
act . Should ( ) . Throw < YamlException > ( )
. WithInnerException < SecretNotFoundException > ( )
. WithMessage ( "*api_key is not defined in secrets.yml" ) ;
}
[Test]
public void Throw_when_referencing_secret_without_secrets_file ( )
{
var configLoader = Resolve < ConfigurationLoader < SonarrConfiguration > > ( ) ;
var configLoader = Resolve < ConfigurationLoader < TestConfig > > ( ) ;
const string testYml = @ "
sonarr :
- api_key : ! secret api_key
base_url : fake_url
instance3 :
api_key : ! secret api_key
base_url : fake_url
";
Action act = ( ) = > configLoader . LoadFromStream ( new StringReader ( testYml ) , "sonarr" ) ;
act . Should ( ) . Throw < YamlException > ( ) . WithMessage ( "api_key is not defined in secrets.yml." ) ;
act . Should ( ) . Throw < YamlException > ( )
. WithInnerException < SecretNotFoundException > ( )
. WithMessage ( "*api_key is not defined in secrets.yml" ) ;
}
[Test]
public void Throw_when_secret_value_is_not_scalar ( )
{
var configLoader = Resolve < ConfigurationLoader < SonarrConfiguration > > ( ) ;
var configLoader = Resolve < ConfigurationLoader < TestConfig > > ( ) ;
const string testYml = @ "
sonarr :
- api_key : ! secret { property : value }
base_url : fake_url
instance4 :
api_key : ! secret { property : value }
base_url : fake_url
";
Action act = ( ) = > configLoader . LoadFromStream ( new StringReader ( testYml ) , "sonarr" ) ;
@ -231,17 +261,26 @@ sonarr:
const string testYml = @ "
sonarr :
- api_key : fake_key
base_url : fake_url
release_profiles : ! secret bogus_profile
instance5 :
api_key : fake_key
base_url : fake_url
release_profiles : ! secret bogus_profile
";
const string secretsYml = @ "
bogus_profile : 95283e6 b156c42f3af8a9b16173f876b
";
const string secretsYml = @"bogus_profile: 95283e6b156c42f3af8a9b16173f876b" ;
Fs . AddFile ( Paths . SecretsPath . FullName , new MockFileData ( secretsYml ) ) ;
Action act = ( ) = > configLoader . LoadFromStream ( new StringReader ( testYml ) , "sonarr" ) ;
act . Should ( ) . Throw < YamlException > ( ) . WithMessage ( "Exception during deserialization" ) ;
}
[Test, AutoMockData]
public void Yaml_file_with_only_comment_should_be_skipped ( ConfigurationLoader < TestConfig > sut )
{
const string testYml = "# YAML with nothing but this comment" ;
var result = sut . LoadFromStream ( new StringReader ( testYml ) , "fubar" ) ;
result . Should ( ) . BeEmpty ( ) ;
}
}