mirror of
https://github.com/Radarr/Radarr.git
synced 2025-04-24 06:27:08 -04:00
Set up tests on postgres
This commit is contained in:
parent
bd53092f0c
commit
9b21408a03
14 changed files with 538 additions and 18 deletions
|
@ -515,6 +515,61 @@ stages:
|
|||
testResultsFiles: '**/TestResult.xml'
|
||||
testRunTitle: '$(testName) Unit Tests'
|
||||
failTaskOnFailedTests: true
|
||||
|
||||
- job: Unit_LinuxCore_Postgres
|
||||
displayName: Unit Native LinuxCore with Postgres Database
|
||||
dependsOn: Prepare
|
||||
condition: and(succeeded(), eq(dependencies.Prepare.outputs['setVar.backendNotUpdated'], '0'))
|
||||
variables:
|
||||
pattern: 'Radarr.*.linux-core-x64.tar.gz'
|
||||
artifactName: LinuxCoreTests
|
||||
Radarr__Postgres__Host: 'localhost'
|
||||
Radarr__Postgres__Port: '5432'
|
||||
Radarr__Postgres__User: 'radarr'
|
||||
Radarr__Postgres__Password: 'radarr'
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-18.04'
|
||||
|
||||
timeoutInMinutes: 10
|
||||
|
||||
steps:
|
||||
- task: UseDotNet@2
|
||||
displayName: 'Install .net core'
|
||||
inputs:
|
||||
version: $(dotnetVersion)
|
||||
- checkout: none
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download Test Artifact
|
||||
inputs:
|
||||
buildType: 'current'
|
||||
artifactName: $(artifactName)
|
||||
targetPath: $(testsFolder)
|
||||
- bash: |
|
||||
chmod a+x _tests/ffprobe
|
||||
displayName: Make ffprobe Executable
|
||||
- bash: find ${TESTSFOLDER} -name "Radarr.Test.Dummy" -exec chmod a+x {} \;
|
||||
displayName: Make Test Dummy Executable
|
||||
condition: and(succeeded(), ne(variables['osName'], 'Windows'))
|
||||
- bash: |
|
||||
docker run -d --name=postgres14 \
|
||||
-e POSTGRES_PASSWORD=radarr \
|
||||
-e POSTGRES_USER=radarr \
|
||||
-p 5432:5432/tcp \
|
||||
postgres:14
|
||||
displayName: Start postgres
|
||||
- bash: |
|
||||
chmod a+x ${TESTSFOLDER}/test.sh
|
||||
ls -lR ${TESTSFOLDER}
|
||||
${TESTSFOLDER}/test.sh Linux Unit Test
|
||||
displayName: Run Tests
|
||||
- task: PublishTestResults@2
|
||||
displayName: Publish Test Results
|
||||
inputs:
|
||||
testResultsFormat: 'NUnit'
|
||||
testResultsFiles: '**/TestResult.xml'
|
||||
testRunTitle: 'LinuxCore Postgres Unit Tests'
|
||||
failTaskOnFailedTests: true
|
||||
|
||||
- stage: Integration
|
||||
displayName: Integration
|
||||
|
@ -599,6 +654,67 @@ stages:
|
|||
failTaskOnFailedTests: true
|
||||
displayName: Publish Test Results
|
||||
|
||||
- job: Integration_LinuxCore_Postgres
|
||||
displayName: Integration Native LinuxCore with Postgres Database
|
||||
dependsOn: Prepare
|
||||
condition: and(succeeded(), eq(dependencies.Prepare.outputs['setVar.backendNotUpdated'], '0'))
|
||||
variables:
|
||||
pattern: 'Radarr.*.linux-core-x64.tar.gz'
|
||||
Radarr__Postgres__Host: 'localhost'
|
||||
Radarr__Postgres__Port: '5432'
|
||||
Radarr__Postgres__User: 'radarr'
|
||||
Radarr__Postgres__Password: 'radarr'
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-18.04'
|
||||
|
||||
steps:
|
||||
- task: UseDotNet@2
|
||||
displayName: 'Install .net core'
|
||||
inputs:
|
||||
version: $(dotnetVersion)
|
||||
- checkout: none
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download Test Artifact
|
||||
inputs:
|
||||
buildType: 'current'
|
||||
artifactName: 'LinuxCoreTests'
|
||||
targetPath: $(testsFolder)
|
||||
- task: DownloadPipelineArtifact@2
|
||||
displayName: Download Build Artifact
|
||||
inputs:
|
||||
buildType: 'current'
|
||||
artifactName: Packages
|
||||
itemPattern: '**/$(pattern)'
|
||||
targetPath: $(Build.ArtifactStagingDirectory)
|
||||
- task: ExtractFiles@1
|
||||
inputs:
|
||||
archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)'
|
||||
destinationFolder: '$(Build.ArtifactStagingDirectory)/bin'
|
||||
displayName: Extract Package
|
||||
- bash: |
|
||||
mkdir -p ./bin/
|
||||
cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Radarr/. ./bin/
|
||||
displayName: Move Package Contents
|
||||
- bash: |
|
||||
docker run -d --name=postgres14 \
|
||||
-e POSTGRES_PASSWORD=radarr \
|
||||
-e POSTGRES_USER=radarr \
|
||||
-p 5432:5432/tcp \
|
||||
postgres:14
|
||||
displayName: Start postgres
|
||||
- bash: |
|
||||
chmod a+x ${TESTSFOLDER}/test.sh
|
||||
${TESTSFOLDER}/test.sh Linux Integration Test
|
||||
displayName: Run Integration Tests
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
testResultsFormat: 'NUnit'
|
||||
testResultsFiles: '**/TestResult.xml'
|
||||
testRunTitle: 'Integration LinuxCore Postgres Database Integration Tests'
|
||||
failTaskOnFailedTests: true
|
||||
displayName: Publish Test Results
|
||||
|
||||
- job: Integration_FreeBSD
|
||||
displayName: Integration Native FreeBSD
|
||||
dependsOn: Prepare
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace NzbDrone.Automation.Test
|
|||
|
||||
driver.Manage().Window.Size = new System.Drawing.Size(1920, 1080);
|
||||
|
||||
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger());
|
||||
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger(), null);
|
||||
_runner.KillAll();
|
||||
_runner.Start();
|
||||
|
||||
|
|
206
src/NzbDrone.Core.Test/Datastore/WhereBuilderPostgresFixture.cs
Normal file
206
src/NzbDrone.Core.Test/Datastore/WhereBuilderPostgresFixture.cs
Normal file
|
@ -0,0 +1,206 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.Datastore
|
||||
{
|
||||
[TestFixture]
|
||||
public class WhereBuilderPostgresFixture : CoreTest
|
||||
{
|
||||
private WhereBuilderPostgres _subject;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void MapTables()
|
||||
{
|
||||
// Generate table mapping
|
||||
Mocker.Resolve<DbFactory>();
|
||||
}
|
||||
|
||||
private WhereBuilderPostgres Where(Expression<Func<Movie, bool>> filter)
|
||||
{
|
||||
return new WhereBuilderPostgres(filter, true, 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_equal_const()
|
||||
{
|
||||
_subject = Where(x => x.Id == 10);
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"Id\" = @Clause1_P1)");
|
||||
_subject.Parameters.Get<int>("Clause1_P1").Should().Be(10);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_equal_variable()
|
||||
{
|
||||
var id = 10;
|
||||
_subject = Where(x => x.Id == id);
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"Id\" = @Clause1_P1)");
|
||||
_subject.Parameters.Get<int>("Clause1_P1").Should().Be(id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_equal_property()
|
||||
{
|
||||
var movie = new Movie { Id = 10 };
|
||||
_subject = Where(x => x.Id == movie.Id);
|
||||
|
||||
_subject.Parameters.ParameterNames.Should().HaveCount(1);
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"Id\" = @Clause1_P1)");
|
||||
_subject.Parameters.Get<int>("Clause1_P1").Should().Be(movie.Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_equal_joined_property()
|
||||
{
|
||||
_subject = Where(x => x.Profile.Id == 1);
|
||||
|
||||
_subject.Parameters.ParameterNames.Should().HaveCount(1);
|
||||
_subject.ToString().Should().Be($"(\"Profiles\".\"Id\" = @Clause1_P1)");
|
||||
_subject.Parameters.Get<int>("Clause1_P1").Should().Be(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_throws_without_concrete_condition_if_requiresConcreteCondition()
|
||||
{
|
||||
Expression<Func<Movie, Movie, bool>> filter = (x, y) => x.Id == y.Id;
|
||||
_subject = new WhereBuilderPostgres(filter, true, 0);
|
||||
Assert.Throws<InvalidOperationException>(() => _subject.ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_allows_abstract_condition_if_not_requiresConcreteCondition()
|
||||
{
|
||||
Expression<Func<Movie, Movie, bool>> filter = (x, y) => x.Id == y.Id;
|
||||
_subject = new WhereBuilderPostgres(filter, false, 0);
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"Id\" = \"Movies\".\"Id\")");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_string_is_null()
|
||||
{
|
||||
_subject = Where(x => x.CleanTitle == null);
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_string_is_null_value()
|
||||
{
|
||||
string cleanTitle = null;
|
||||
_subject = Where(x => x.CleanTitle == cleanTitle);
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_equal_null_property()
|
||||
{
|
||||
var movie = new Movie { CleanTitle = null };
|
||||
_subject = Where(x => x.CleanTitle == movie.CleanTitle);
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" IS NULL)");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_column_contains_string()
|
||||
{
|
||||
var test = "small";
|
||||
_subject = Where(x => x.CleanTitle.Contains(test));
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" ILIKE '%' || @Clause1_P1 || '%')");
|
||||
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_string_contains_column()
|
||||
{
|
||||
var test = "small";
|
||||
_subject = Where(x => test.Contains(x.CleanTitle));
|
||||
|
||||
_subject.ToString().Should().Be($"(@Clause1_P1 ILIKE '%' || \"Movies\".\"CleanTitle\" || '%')");
|
||||
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_column_starts_with_string()
|
||||
{
|
||||
var test = "small";
|
||||
_subject = Where(x => x.CleanTitle.StartsWith(test));
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" ILIKE @Clause1_P1 || '%')");
|
||||
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_column_ends_with_string()
|
||||
{
|
||||
var test = "small";
|
||||
_subject = Where(x => x.CleanTitle.EndsWith(test));
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" ILIKE '%' || @Clause1_P1)");
|
||||
_subject.Parameters.Get<string>("Clause1_P1").Should().Be(test);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_in_list()
|
||||
{
|
||||
var list = new List<int> { 1, 2, 3 };
|
||||
_subject = Where(x => list.Contains(x.Id));
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"Id\" = ANY (('{{1, 2, 3}}')))");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_in_list_2()
|
||||
{
|
||||
var list = new List<int> { 1, 2, 3 };
|
||||
_subject = Where(x => x.CleanTitle == "test" && list.Contains(x.Id));
|
||||
|
||||
_subject.ToString().Should().Be($"((\"Movies\".\"CleanTitle\" = @Clause1_P1) AND (\"Movies\".\"Id\" = ANY (('{{1, 2, 3}}'))))");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void postgres_where_in_string_list()
|
||||
{
|
||||
var list = new List<string> { "first", "second", "third" };
|
||||
|
||||
_subject = Where(x => list.Contains(x.CleanTitle));
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"CleanTitle\" = ANY (@Clause1_P1))");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void enum_as_int()
|
||||
{
|
||||
_subject = Where(x => x.Status == MovieStatusType.Announced);
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = @Clause1_P1)");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void enum_in_list()
|
||||
{
|
||||
var allowed = new List<MovieStatusType> { MovieStatusType.Announced, MovieStatusType.InCinemas };
|
||||
_subject = Where(x => allowed.Contains(x.Status));
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = ANY (@Clause1_P1))");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void enum_in_array()
|
||||
{
|
||||
var allowed = new MovieStatusType[] { MovieStatusType.Announced, MovieStatusType.InCinemas };
|
||||
_subject = Where(x => allowed.Contains(x.Status));
|
||||
|
||||
_subject.ToString().Should().Be($"(\"Movies\".\"Status\" = ANY (@Clause1_P1))");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,18 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SQLite;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Npgsql;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using NzbDrone.Test.Common.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Test.Framework
|
||||
{
|
||||
|
@ -49,6 +53,7 @@ namespace NzbDrone.Core.Test.Framework
|
|||
public abstract class DbTest : CoreTest
|
||||
{
|
||||
private ITestDatabase _db;
|
||||
private DatabaseType _databaseType;
|
||||
|
||||
protected virtual MigrationType MigrationType => MigrationType.Main;
|
||||
|
||||
|
@ -101,17 +106,39 @@ namespace NzbDrone.Core.Test.Framework
|
|||
|
||||
private IDatabase CreateDatabase(MigrationContext migrationContext)
|
||||
{
|
||||
if (_databaseType == DatabaseType.PostgreSQL)
|
||||
{
|
||||
CreatePostgresDb();
|
||||
}
|
||||
|
||||
var factory = Mocker.Resolve<DbFactory>();
|
||||
|
||||
// If a special migration test or log migration then create new
|
||||
if (migrationContext.BeforeMigration != null)
|
||||
if (migrationContext.BeforeMigration != null || _databaseType == DatabaseType.PostgreSQL)
|
||||
{
|
||||
return factory.Create(migrationContext);
|
||||
}
|
||||
|
||||
return CreateSqliteDatabase(factory, migrationContext);
|
||||
}
|
||||
|
||||
private void CreatePostgresDb()
|
||||
{
|
||||
var options = Mocker.Resolve<IOptions<PostgresOptions>>().Value;
|
||||
PostgresDatabase.Create(options, MigrationType);
|
||||
}
|
||||
|
||||
private void DropPostgresDb()
|
||||
{
|
||||
var options = Mocker.Resolve<IOptions<PostgresOptions>>().Value;
|
||||
PostgresDatabase.Drop(options, MigrationType);
|
||||
}
|
||||
|
||||
private IDatabase CreateSqliteDatabase(IDbFactory factory, MigrationContext migrationContext)
|
||||
{
|
||||
// Otherwise try to use a cached migrated db
|
||||
var cachedDb = GetCachedDatabase(migrationContext.MigrationType);
|
||||
var testDb = GetTestDb(migrationContext.MigrationType);
|
||||
var cachedDb = SqliteDatabase.GetCachedDb(migrationContext.MigrationType);
|
||||
var testDb = GetTestSqliteDb(migrationContext.MigrationType);
|
||||
if (File.Exists(cachedDb))
|
||||
{
|
||||
TestLogger.Info($"Using cached initial database {cachedDb}");
|
||||
|
@ -131,12 +158,7 @@ namespace NzbDrone.Core.Test.Framework
|
|||
}
|
||||
}
|
||||
|
||||
private string GetCachedDatabase(MigrationType type)
|
||||
{
|
||||
return Path.Combine(TestContext.CurrentContext.TestDirectory, $"cached_{type}.db");
|
||||
}
|
||||
|
||||
private string GetTestDb(MigrationType type)
|
||||
private string GetTestSqliteDb(MigrationType type)
|
||||
{
|
||||
return type == MigrationType.Main ? TestFolderInfo.GetDatabase() : TestFolderInfo.GetLogDatabase();
|
||||
}
|
||||
|
@ -151,6 +173,13 @@ namespace NzbDrone.Core.Test.Framework
|
|||
WithTempAsAppPath();
|
||||
SetupLogging();
|
||||
|
||||
// populate the possible postgres options
|
||||
var postgresOptions = PostgresDatabase.GetTestOptions();
|
||||
_databaseType = postgresOptions.Host.IsNotNullOrWhiteSpace() ? DatabaseType.PostgreSQL : DatabaseType.SQLite;
|
||||
|
||||
// Set up remaining container services
|
||||
Mocker.SetConstant(Options.Create(postgresOptions));
|
||||
Mocker.SetConstant<IConfigFileProvider>(Mocker.Resolve<ConfigFileProvider>());
|
||||
Mocker.SetConstant<IConnectionStringFactory>(Mocker.Resolve<ConnectionStringFactory>());
|
||||
Mocker.SetConstant<IMigrationController>(Mocker.Resolve<MigrationController>());
|
||||
|
||||
|
@ -170,12 +199,19 @@ namespace NzbDrone.Core.Test.Framework
|
|||
// Make sure there are no lingering connections. (When this happens it means we haven't disposed something properly)
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
|
||||
SQLiteConnection.ClearAllPools();
|
||||
NpgsqlConnection.ClearAllPools();
|
||||
|
||||
if (TestFolderInfo != null)
|
||||
{
|
||||
DeleteTempFolder(TestFolderInfo.AppDataFolder);
|
||||
}
|
||||
|
||||
if (_databaseType == DatabaseType.PostgreSQL)
|
||||
{
|
||||
DropPostgresDb();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using NzbDrone.Test.Common.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Test
|
||||
{
|
||||
|
@ -10,13 +12,13 @@ namespace NzbDrone.Core.Test
|
|||
[OneTimeTearDown]
|
||||
public void ClearCachedDatabase()
|
||||
{
|
||||
var mainCache = Path.Combine(TestContext.CurrentContext.TestDirectory, $"cached_Main.db");
|
||||
var mainCache = SqliteDatabase.GetCachedDb(MigrationType.Main);
|
||||
if (File.Exists(mainCache))
|
||||
{
|
||||
File.Delete(mainCache);
|
||||
}
|
||||
|
||||
var logCache = Path.Combine(TestContext.CurrentContext.TestDirectory, $"cached_Log.db");
|
||||
var logCache = SqliteDatabase.GetCachedDb(MigrationType.Log);
|
||||
if (File.Exists(logCache))
|
||||
{
|
||||
File.Delete(logCache);
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace NzbDrone.Core.Test.Framework
|
|||
where T : ModelBase, new();
|
||||
IDirectDataMapper GetDirectDataMapper();
|
||||
IDbConnection OpenConnection();
|
||||
DatabaseType DatabaseType { get; }
|
||||
}
|
||||
|
||||
public class TestDatabase : ITestDatabase
|
||||
|
@ -30,6 +31,8 @@ namespace NzbDrone.Core.Test.Framework
|
|||
private readonly IDatabase _dbConnection;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
|
||||
public DatabaseType DatabaseType => _dbConnection.DatabaseType;
|
||||
|
||||
public TestDatabase(IDatabase dbConnection)
|
||||
{
|
||||
_eventAggregator = new Mock<IEventAggregator>().Object;
|
||||
|
|
|
@ -7,7 +7,6 @@ using NzbDrone.Common.Disk;
|
|||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Exceptions;
|
||||
using NzbDrone.Common.Instrumentation;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace NzbDrone.Core.Datastore
|
||||
{
|
||||
public class PostgresOptions
|
||||
|
@ -8,5 +10,17 @@ namespace NzbDrone.Core.Datastore
|
|||
public string Password { get; set; }
|
||||
public string MainDb { get; set; }
|
||||
public string LogDb { get; set; }
|
||||
|
||||
public static PostgresOptions GetOptions()
|
||||
{
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables("Radarr__")
|
||||
.Build();
|
||||
|
||||
var postgresOptions = new PostgresOptions();
|
||||
config.GetSection("Postgres").Bind(postgresOptions);
|
||||
|
||||
return postgresOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace NzbDrone.Core.Datastore
|
|||
// Only use the SQL condition if the expression didn't resolve to an actual value
|
||||
if (tableName != null && !gotValue)
|
||||
{
|
||||
_sb.Append($"\"{tableName}\".\"{expression.Member.Name.ToLower()}\"");
|
||||
_sb.Append($"\"{tableName}\".\"{expression.Member.Name}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using NLog;
|
||||
using Npgsql;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
using NzbDrone.Core.Indexers.Newznab;
|
||||
using NzbDrone.Test.Common;
|
||||
using NzbDrone.Test.Common.Datastore;
|
||||
using Radarr.Http.ClientSchema;
|
||||
|
||||
namespace NzbDrone.Integration.Test
|
||||
|
@ -19,6 +25,8 @@ namespace NzbDrone.Integration.Test
|
|||
|
||||
protected int Port { get; private set; }
|
||||
|
||||
protected PostgresOptions PostgresOptions { get; set; } = new ();
|
||||
|
||||
protected override string RootUrl => $"http://localhost:{Port}/";
|
||||
|
||||
protected override string ApiKey => _runner.ApiKey;
|
||||
|
@ -27,7 +35,14 @@ namespace NzbDrone.Integration.Test
|
|||
{
|
||||
Port = Interlocked.Increment(ref StaticPort);
|
||||
|
||||
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger(), Port);
|
||||
PostgresOptions = PostgresDatabase.GetTestOptions();
|
||||
|
||||
if (PostgresOptions?.Host != null)
|
||||
{
|
||||
CreatePostgresDb(PostgresOptions);
|
||||
}
|
||||
|
||||
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger(), PostgresOptions, Port);
|
||||
_runner.Kill();
|
||||
|
||||
_runner.Start();
|
||||
|
@ -59,6 +74,22 @@ namespace NzbDrone.Integration.Test
|
|||
protected override void StopTestTarget()
|
||||
{
|
||||
_runner.Kill();
|
||||
if (PostgresOptions?.Host != null)
|
||||
{
|
||||
DropPostgresDb(PostgresOptions);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreatePostgresDb(PostgresOptions options)
|
||||
{
|
||||
PostgresDatabase.Create(options, MigrationType.Main);
|
||||
PostgresDatabase.Create(options, MigrationType.Log);
|
||||
}
|
||||
|
||||
private static void DropPostgresDb(PostgresOptions options)
|
||||
{
|
||||
PostgresDatabase.Drop(options, MigrationType.Main);
|
||||
PostgresDatabase.Drop(options, MigrationType.Log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
69
src/NzbDrone.Test.Common/Datastore/PostgresDatabase.cs
Normal file
69
src/NzbDrone.Test.Common/Datastore/PostgresDatabase.cs
Normal file
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
using Npgsql;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Test.Common.Datastore
|
||||
{
|
||||
public static class PostgresDatabase
|
||||
{
|
||||
public static PostgresOptions GetTestOptions()
|
||||
{
|
||||
var options = PostgresOptions.GetOptions();
|
||||
|
||||
var uid = TestBase.GetUID();
|
||||
options.MainDb = uid + "_main";
|
||||
options.LogDb = uid + "_log";
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
public static void Create(PostgresOptions options, MigrationType migrationType)
|
||||
{
|
||||
var db = GetDatabaseName(options, migrationType);
|
||||
var connectionString = GetConnectionString(options);
|
||||
using var conn = new NpgsqlConnection(connectionString);
|
||||
conn.Open();
|
||||
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = $"CREATE DATABASE \"{db}\" WITH OWNER = {options.User} ENCODING = 'UTF8' CONNECTION LIMIT = -1;";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
public static void Drop(PostgresOptions options, MigrationType migrationType)
|
||||
{
|
||||
var db = GetDatabaseName(options, migrationType);
|
||||
var connectionString = GetConnectionString(options);
|
||||
using var conn = new NpgsqlConnection(connectionString);
|
||||
conn.Open();
|
||||
|
||||
using var cmd = conn.CreateCommand();
|
||||
cmd.CommandText = $"DROP DATABASE \"{db}\" WITH (FORCE);";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
private static string GetConnectionString(PostgresOptions options)
|
||||
{
|
||||
var builder = new NpgsqlConnectionStringBuilder()
|
||||
{
|
||||
Host = options.Host,
|
||||
Port = options.Port,
|
||||
Username = options.User,
|
||||
Password = options.Password,
|
||||
Enlist = false
|
||||
};
|
||||
|
||||
return builder.ConnectionString;
|
||||
}
|
||||
|
||||
private static string GetDatabaseName(PostgresOptions options, MigrationType migrationType)
|
||||
{
|
||||
return migrationType switch
|
||||
{
|
||||
MigrationType.Main => options.MainDb,
|
||||
MigrationType.Log => options.LogDb,
|
||||
_ => throw new NotImplementedException("Unknown migration type")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
14
src/NzbDrone.Test.Common/Datastore/SqliteDatabase.cs
Normal file
14
src/NzbDrone.Test.Common/Datastore/SqliteDatabase.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Test.Common.Datastore
|
||||
{
|
||||
public static class SqliteDatabase
|
||||
{
|
||||
public static string GetCachedDb(MigrationType type)
|
||||
{
|
||||
return Path.Combine(TestContext.CurrentContext.TestDirectory, $"cached_{type}.db");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
@ -9,7 +10,9 @@ using NUnit.Framework;
|
|||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Processes;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using RestSharp;
|
||||
|
||||
namespace NzbDrone.Test.Common
|
||||
|
@ -22,13 +25,15 @@ namespace NzbDrone.Test.Common
|
|||
|
||||
public string AppData { get; private set; }
|
||||
public string ApiKey { get; private set; }
|
||||
public PostgresOptions PostgresOptions { get; private set; }
|
||||
public int Port { get; private set; }
|
||||
|
||||
public NzbDroneRunner(Logger logger, int port = 7878)
|
||||
public NzbDroneRunner(Logger logger, PostgresOptions postgresOptions, int port = 7878)
|
||||
{
|
||||
_processProvider = new ProcessProvider(logger);
|
||||
_restClient = new RestClient($"http://localhost:{port}/api/v3");
|
||||
|
||||
PostgresOptions = postgresOptions;
|
||||
Port = port;
|
||||
}
|
||||
|
||||
|
@ -132,9 +137,23 @@ namespace NzbDrone.Test.Common
|
|||
|
||||
private void Start(string outputRadarrConsoleExe)
|
||||
{
|
||||
StringDictionary envVars = new ();
|
||||
if (PostgresOptions?.Host != null)
|
||||
{
|
||||
envVars.Add("Radarr__Postgres__Host", PostgresOptions.Host);
|
||||
envVars.Add("Radarr__Postgres__Port", PostgresOptions.Port.ToString());
|
||||
envVars.Add("Radarr__Postgres__User", PostgresOptions.User);
|
||||
envVars.Add("Radarr__Postgres__Password", PostgresOptions.Password);
|
||||
envVars.Add("Radarr__Postgres__MainDb", PostgresOptions.MainDb);
|
||||
envVars.Add("Radarr__Postgres__LogDb", PostgresOptions.LogDb);
|
||||
|
||||
TestContext.Progress.WriteLine("Using env vars:\n{0}", envVars.ToJson());
|
||||
}
|
||||
|
||||
TestContext.Progress.WriteLine("Starting instance from {0} on port {1}", outputRadarrConsoleExe, Port);
|
||||
|
||||
var args = "-nobrowser -nosingleinstancecheck -data=\"" + AppData + "\"";
|
||||
_nzbDroneProcess = _processProvider.Start(outputRadarrConsoleExe, args, null, OnOutputDataReceived, OnOutputDataReceived);
|
||||
_nzbDroneProcess = _processProvider.Start(outputRadarrConsoleExe, args, envVars, OnOutputDataReceived, OnOutputDataReceived);
|
||||
}
|
||||
|
||||
private void OnOutputDataReceived(string data)
|
||||
|
|
11
src/postgres.runsettings
Normal file
11
src/postgres.runsettings
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RunSettings>
|
||||
<RunConfiguration>
|
||||
<EnvironmentVariables>
|
||||
<Radarr__Postgres__Host>192.168.100.5</Radarr__Postgres__Host>
|
||||
<Radarr__Postgres__Port>5432</Radarr__Postgres__Port>
|
||||
<Radarr__Postgres__User>abc</Radarr__Postgres__User>
|
||||
<Radarr__Postgres__Password>abc</Radarr__Postgres__Password>
|
||||
</EnvironmentVariables>
|
||||
</RunConfiguration>
|
||||
</RunSettings>
|
Loading…
Add table
Add a link
Reference in a new issue