mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-09-17 17:14:18 +02:00
Running Integration Tests against Postgres Database (#838)
* Allow configuring postgres with environment variables (cherry picked from commit 8439df78fea25656a9a1275d2a2fe3f0df0528c7) * Fix process provider when environment variables alread exist [common] (cherry picked from commit 66e5b4025974e081c1406f01a860b1ac52949c22) * First bash at running integration tests on postgres (cherry picked from commit f950e80c7e4f9b088ec6a149386160eab83b61c3) * Postgres integration tests running as part of the build pipeline (cherry picked from commit 9ca8616f5098778e9b5e6ce09d2aa11224018fab) * Fixed: Register PostgresOptions when running in utility mode * fixup! * fixup! * fixup! * fixup! * fixup! Co-authored-by: ta264 <ta264@users.noreply.github.com> Co-authored-by: Qstick <qstick@gmail.com>
This commit is contained in:
@@ -507,6 +507,58 @@ stages:
|
|||||||
testRunTitle: '$(testName) Unit Tests'
|
testRunTitle: '$(testName) Unit Tests'
|
||||||
failTaskOnFailedTests: true
|
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: 'Prowlarr.*.linux-core-x64.tar.gz'
|
||||||
|
artifactName: LinuxCoreTests
|
||||||
|
Prowlarr__Postgres__Host: 'localhost'
|
||||||
|
Prowlarr__Postgres__Port: '5432'
|
||||||
|
Prowlarr__Postgres__User: 'prowlarr'
|
||||||
|
Prowlarr__Postgres__Password: 'prowlarr'
|
||||||
|
|
||||||
|
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: find ${TESTSFOLDER} -name "Prowlarr.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=prowlarr \
|
||||||
|
-e POSTGRES_USER=prowlarr \
|
||||||
|
-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
|
- stage: Integration
|
||||||
displayName: Integration
|
displayName: Integration
|
||||||
dependsOn: Packages
|
dependsOn: Packages
|
||||||
@@ -590,6 +642,67 @@ stages:
|
|||||||
failTaskOnFailedTests: true
|
failTaskOnFailedTests: true
|
||||||
displayName: Publish Test Results
|
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: 'Prowlarr.*.linux-core-x64.tar.gz'
|
||||||
|
Prowlarr__Postgres__Host: 'localhost'
|
||||||
|
Prowlarr__Postgres__Port: '5432'
|
||||||
|
Prowlarr__Postgres__User: 'prowlarr'
|
||||||
|
Prowlarr__Postgres__Password: 'prowlarr'
|
||||||
|
|
||||||
|
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/Prowlarr/. ./bin/
|
||||||
|
displayName: Move Package Contents
|
||||||
|
- bash: |
|
||||||
|
docker run -d --name=postgres14 \
|
||||||
|
-e POSTGRES_PASSWORD=prowlarr \
|
||||||
|
-e POSTGRES_USER=prowlarr \
|
||||||
|
-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
|
- job: Integration_FreeBSD
|
||||||
displayName: Integration Native FreeBSD
|
displayName: Integration Native FreeBSD
|
||||||
dependsOn: Prepare
|
dependsOn: Prepare
|
||||||
|
@@ -44,7 +44,7 @@ namespace NzbDrone.Automation.Test
|
|||||||
|
|
||||||
driver.Manage().Window.Size = new System.Drawing.Size(1920, 1080);
|
driver.Manage().Window.Size = new System.Drawing.Size(1920, 1080);
|
||||||
|
|
||||||
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger());
|
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger(), null);
|
||||||
_runner.KillAll();
|
_runner.KillAll();
|
||||||
_runner.Start();
|
_runner.Start();
|
||||||
|
|
||||||
|
@@ -170,7 +170,7 @@ namespace NzbDrone.Common.Test
|
|||||||
var processStarted = new ManualResetEventSlim();
|
var processStarted = new ManualResetEventSlim();
|
||||||
|
|
||||||
string suffix;
|
string suffix;
|
||||||
if (OsInfo.IsWindows || PlatformInfo.IsMono)
|
if (OsInfo.IsWindows)
|
||||||
{
|
{
|
||||||
suffix = ".exe";
|
suffix = ".exe";
|
||||||
}
|
}
|
||||||
|
@@ -4,11 +4,13 @@ using DryIoc.Microsoft.DependencyInjection;
|
|||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common.Composition.Extensions;
|
using NzbDrone.Common.Composition.Extensions;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Instrumentation.Extensions;
|
using NzbDrone.Common.Instrumentation.Extensions;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Datastore.Extensions;
|
using NzbDrone.Core.Datastore.Extensions;
|
||||||
using NzbDrone.Core.Lifecycle;
|
using NzbDrone.Core.Lifecycle;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
@@ -29,7 +31,8 @@ namespace NzbDrone.Common.Test
|
|||||||
.AddDummyDatabase()
|
.AddDummyDatabase()
|
||||||
.AddStartupContext(new StartupContext("first", "second"));
|
.AddStartupContext(new StartupContext("first", "second"));
|
||||||
|
|
||||||
container.RegisterInstance<IHostLifetime>(new Mock<IHostLifetime>().Object);
|
container.RegisterInstance(new Mock<IHostLifetime>().Object);
|
||||||
|
container.RegisterInstance(new Mock<IOptions<PostgresOptions>>().Object);
|
||||||
|
|
||||||
var serviceProvider = container.GetServiceProvider();
|
var serviceProvider = container.GetServiceProvider();
|
||||||
|
|
||||||
|
@@ -127,7 +127,18 @@ namespace NzbDrone.Common.Processes
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.Trace("Setting environment variable '{0}' to '{1}'", environmentVariable.Key, environmentVariable.Value);
|
_logger.Trace("Setting environment variable '{0}' to '{1}'", environmentVariable.Key, environmentVariable.Value);
|
||||||
startInfo.EnvironmentVariables.Add(environmentVariable.Key.ToString(), environmentVariable.Value.ToString());
|
|
||||||
|
var key = environmentVariable.Key.ToString();
|
||||||
|
var value = environmentVariable.Value?.ToString();
|
||||||
|
|
||||||
|
if (startInfo.EnvironmentVariables.ContainsKey(key))
|
||||||
|
{
|
||||||
|
startInfo.EnvironmentVariables[key] = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
startInfo.EnvironmentVariables.Add(key, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.Datastore
|
|||||||
public void SingleOrDefault_should_return_null_on_empty_db()
|
public void SingleOrDefault_should_return_null_on_empty_db()
|
||||||
{
|
{
|
||||||
Mocker.Resolve<IDatabase>()
|
Mocker.Resolve<IDatabase>()
|
||||||
.OpenConnection().Query<IndexerDefinition>("SELECT * FROM Indexers")
|
.OpenConnection().Query<IndexerDefinition>("SELECT * FROM \"Indexers\"")
|
||||||
.SingleOrDefault()
|
.SingleOrDefault()
|
||||||
.Should()
|
.Should()
|
||||||
.BeNull();
|
.BeNull();
|
||||||
|
@@ -5,10 +5,14 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Npgsql;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using NzbDrone.Test.Common.Datastore;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.Framework
|
namespace NzbDrone.Core.Test.Framework
|
||||||
{
|
{
|
||||||
@@ -49,6 +53,7 @@ namespace NzbDrone.Core.Test.Framework
|
|||||||
public abstract class DbTest : CoreTest
|
public abstract class DbTest : CoreTest
|
||||||
{
|
{
|
||||||
private ITestDatabase _db;
|
private ITestDatabase _db;
|
||||||
|
private DatabaseType _databaseType;
|
||||||
|
|
||||||
protected virtual MigrationType MigrationType => MigrationType.Main;
|
protected virtual MigrationType MigrationType => MigrationType.Main;
|
||||||
|
|
||||||
@@ -101,17 +106,39 @@ namespace NzbDrone.Core.Test.Framework
|
|||||||
|
|
||||||
private IDatabase CreateDatabase(MigrationContext migrationContext)
|
private IDatabase CreateDatabase(MigrationContext migrationContext)
|
||||||
{
|
{
|
||||||
|
if (_databaseType == DatabaseType.PostgreSQL)
|
||||||
|
{
|
||||||
|
CreatePostgresDb();
|
||||||
|
}
|
||||||
|
|
||||||
var factory = Mocker.Resolve<DbFactory>();
|
var factory = Mocker.Resolve<DbFactory>();
|
||||||
|
|
||||||
// If a special migration test or log migration then create new
|
// 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 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
|
// Otherwise try to use a cached migrated db
|
||||||
var cachedDb = GetCachedDatabase(migrationContext.MigrationType);
|
var cachedDb = SqliteDatabase.GetCachedDb(migrationContext.MigrationType);
|
||||||
var testDb = GetTestDb(migrationContext.MigrationType);
|
var testDb = GetTestSqliteDb(migrationContext.MigrationType);
|
||||||
if (File.Exists(cachedDb))
|
if (File.Exists(cachedDb))
|
||||||
{
|
{
|
||||||
TestLogger.Info($"Using cached initial database {cachedDb}");
|
TestLogger.Info($"Using cached initial database {cachedDb}");
|
||||||
@@ -131,12 +158,7 @@ namespace NzbDrone.Core.Test.Framework
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetCachedDatabase(MigrationType type)
|
private string GetTestSqliteDb(MigrationType type)
|
||||||
{
|
|
||||||
return Path.Combine(TestContext.CurrentContext.TestDirectory, $"cached_{type}.db");
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetTestDb(MigrationType type)
|
|
||||||
{
|
{
|
||||||
return type == MigrationType.Main ? TestFolderInfo.GetDatabase() : TestFolderInfo.GetLogDatabase();
|
return type == MigrationType.Main ? TestFolderInfo.GetDatabase() : TestFolderInfo.GetLogDatabase();
|
||||||
}
|
}
|
||||||
@@ -151,6 +173,13 @@ namespace NzbDrone.Core.Test.Framework
|
|||||||
WithTempAsAppPath();
|
WithTempAsAppPath();
|
||||||
SetupLogging();
|
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<IConnectionStringFactory>(Mocker.Resolve<ConnectionStringFactory>());
|
||||||
Mocker.SetConstant<IMigrationController>(Mocker.Resolve<MigrationController>());
|
Mocker.SetConstant<IMigrationController>(Mocker.Resolve<MigrationController>());
|
||||||
|
|
||||||
@@ -171,11 +200,17 @@ namespace NzbDrone.Core.Test.Framework
|
|||||||
GC.Collect();
|
GC.Collect();
|
||||||
GC.WaitForPendingFinalizers();
|
GC.WaitForPendingFinalizers();
|
||||||
SQLiteConnection.ClearAllPools();
|
SQLiteConnection.ClearAllPools();
|
||||||
|
NpgsqlConnection.ClearAllPools();
|
||||||
|
|
||||||
if (TestFolderInfo != null)
|
if (TestFolderInfo != null)
|
||||||
{
|
{
|
||||||
DeleteTempFolder(TestFolderInfo.AppDataFolder);
|
DeleteTempFolder(TestFolderInfo.AppDataFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_databaseType == DatabaseType.PostgreSQL)
|
||||||
|
{
|
||||||
|
DropPostgresDb();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using NzbDrone.Test.Common.Datastore;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test
|
namespace NzbDrone.Core.Test
|
||||||
{
|
{
|
||||||
@@ -10,13 +12,13 @@ namespace NzbDrone.Core.Test
|
|||||||
[OneTimeTearDown]
|
[OneTimeTearDown]
|
||||||
public void ClearCachedDatabase()
|
public void ClearCachedDatabase()
|
||||||
{
|
{
|
||||||
var mainCache = Path.Combine(TestContext.CurrentContext.TestDirectory, $"cached_Main.db");
|
var mainCache = SqliteDatabase.GetCachedDb(MigrationType.Main);
|
||||||
if (File.Exists(mainCache))
|
if (File.Exists(mainCache))
|
||||||
{
|
{
|
||||||
File.Delete(mainCache);
|
File.Delete(mainCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
var logCache = Path.Combine(TestContext.CurrentContext.TestDirectory, $"cached_Log.db");
|
var logCache = SqliteDatabase.GetCachedDb(MigrationType.Log);
|
||||||
if (File.Exists(logCache))
|
if (File.Exists(logCache))
|
||||||
{
|
{
|
||||||
File.Delete(logCache);
|
File.Delete(logCache);
|
||||||
|
@@ -23,6 +23,7 @@ namespace NzbDrone.Core.Test.Framework
|
|||||||
where T : ModelBase, new();
|
where T : ModelBase, new();
|
||||||
IDirectDataMapper GetDirectDataMapper();
|
IDirectDataMapper GetDirectDataMapper();
|
||||||
IDbConnection OpenConnection();
|
IDbConnection OpenConnection();
|
||||||
|
DatabaseType DatabaseType { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TestDatabase : ITestDatabase
|
public class TestDatabase : ITestDatabase
|
||||||
@@ -30,6 +31,8 @@ namespace NzbDrone.Core.Test.Framework
|
|||||||
private readonly IDatabase _dbConnection;
|
private readonly IDatabase _dbConnection;
|
||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
|
|
||||||
|
public DatabaseType DatabaseType => _dbConnection.DatabaseType;
|
||||||
|
|
||||||
public TestDatabase(IDatabase dbConnection)
|
public TestDatabase(IDatabase dbConnection)
|
||||||
{
|
{
|
||||||
_eventAggregator = new Mock<IEventAggregator>().Object;
|
_eventAggregator = new Mock<IEventAggregator>().Object;
|
||||||
|
@@ -41,7 +41,8 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
|||||||
|
|
||||||
Subject.Clean();
|
Subject.Clean();
|
||||||
|
|
||||||
AllStoredModels.ToList().ForEach(t => t.LastExecution.Should().Be(expectedTime));
|
// BeCloseTo handles Postgres rounding times
|
||||||
|
AllStoredModels.ToList().ForEach(t => t.LastExecution.Should().BeCloseTo(expectedTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,12 +5,14 @@ using System.Linq;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using NzbDrone.Common.Cache;
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Authentication;
|
using NzbDrone.Core.Authentication;
|
||||||
using NzbDrone.Core.Configuration.Events;
|
using NzbDrone.Core.Configuration.Events;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Lifecycle;
|
using NzbDrone.Core.Lifecycle;
|
||||||
using NzbDrone.Core.Messaging.Commands;
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
@@ -67,6 +69,7 @@ namespace NzbDrone.Core.Configuration
|
|||||||
private readonly IEventAggregator _eventAggregator;
|
private readonly IEventAggregator _eventAggregator;
|
||||||
private readonly IDiskProvider _diskProvider;
|
private readonly IDiskProvider _diskProvider;
|
||||||
private readonly ICached<string> _cache;
|
private readonly ICached<string> _cache;
|
||||||
|
private readonly PostgresOptions _postgresOptions;
|
||||||
|
|
||||||
private readonly string _configFile;
|
private readonly string _configFile;
|
||||||
private static readonly Regex HiddenCharacterRegex = new Regex("[^a-z0-9]", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
private static readonly Regex HiddenCharacterRegex = new Regex("[^a-z0-9]", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
@@ -76,12 +79,14 @@ namespace NzbDrone.Core.Configuration
|
|||||||
public ConfigFileProvider(IAppFolderInfo appFolderInfo,
|
public ConfigFileProvider(IAppFolderInfo appFolderInfo,
|
||||||
ICacheManager cacheManager,
|
ICacheManager cacheManager,
|
||||||
IEventAggregator eventAggregator,
|
IEventAggregator eventAggregator,
|
||||||
IDiskProvider diskProvider)
|
IDiskProvider diskProvider,
|
||||||
|
IOptions<PostgresOptions> postgresOptions)
|
||||||
{
|
{
|
||||||
_cache = cacheManager.GetCache<string>(GetType());
|
_cache = cacheManager.GetCache<string>(GetType());
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_diskProvider = diskProvider;
|
_diskProvider = diskProvider;
|
||||||
_configFile = appFolderInfo.GetConfigPath();
|
_configFile = appFolderInfo.GetConfigPath();
|
||||||
|
_postgresOptions = postgresOptions.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<string, object> GetConfigDictionary()
|
public Dictionary<string, object> GetConfigDictionary()
|
||||||
@@ -195,13 +200,13 @@ namespace NzbDrone.Core.Configuration
|
|||||||
|
|
||||||
public string LogLevel => GetValue("LogLevel", "info").ToLowerInvariant();
|
public string LogLevel => GetValue("LogLevel", "info").ToLowerInvariant();
|
||||||
public string ConsoleLogLevel => GetValue("ConsoleLogLevel", string.Empty, persist: false);
|
public string ConsoleLogLevel => GetValue("ConsoleLogLevel", string.Empty, persist: false);
|
||||||
public string PostgresHost => GetValue("PostgresHost", string.Empty, persist: false);
|
public string PostgresHost => _postgresOptions?.Host ?? GetValue("PostgresHost", string.Empty, persist: false);
|
||||||
public string PostgresUser => GetValue("PostgresUser", string.Empty, persist: false);
|
public string PostgresUser => _postgresOptions?.User ?? GetValue("PostgresUser", string.Empty, persist: false);
|
||||||
public string PostgresPassword => GetValue("PostgresPassword", string.Empty, persist: false);
|
public string PostgresPassword => _postgresOptions?.Password ?? GetValue("PostgresPassword", string.Empty, persist: false);
|
||||||
public string PostgresMainDb => GetValue("PostgresMainDb", "prowlarr-main", persist: false);
|
public string PostgresMainDb => _postgresOptions?.MainDb ?? GetValue("PostgresMainDb", "prowlarr-main", persist: false);
|
||||||
public string PostgresLogDb => GetValue("PostgresLogDb", "prowlarr-log", persist: false);
|
public string PostgresLogDb => _postgresOptions?.LogDb ?? GetValue("PostgresLogDb", "prowlarr-log", persist: false);
|
||||||
|
public int PostgresPort => (_postgresOptions?.Port ?? 0) != 0 ? _postgresOptions.Port : GetValueInt("PostgresPort", 5432, persist: false);
|
||||||
public string Theme => GetValue("Theme", "light", persist: false);
|
public string Theme => GetValue("Theme", "light", persist: false);
|
||||||
public int PostgresPort => GetValueInt("PostgresPort", 5432, persist: false);
|
|
||||||
public bool LogSql => GetValueBoolean("LogSql", false, persist: false);
|
public bool LogSql => GetValueBoolean("LogSql", false, persist: false);
|
||||||
public int LogRotate => GetValueInt("LogRotate", 50, persist: false);
|
public int LogRotate => GetValueInt("LogRotate", 50, persist: false);
|
||||||
public bool FilterSentryEvents => GetValueBoolean("FilterSentryEvents", true, persist: false);
|
public bool FilterSentryEvents => GetValueBoolean("FilterSentryEvents", true, persist: false);
|
||||||
|
@@ -167,14 +167,12 @@ namespace NzbDrone.Core.Datastore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_database.DatabaseType == DatabaseType.SQLite)
|
if (_database.DatabaseType == DatabaseType.PostgreSQL)
|
||||||
{
|
|
||||||
return $"INSERT INTO {_table} ({sbColumnList.ToString()}) VALUES ({sbParameterList.ToString()}); SELECT last_insert_rowid() id";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
return $"INSERT INTO \"{_table}\" ({sbColumnList.ToString()}) VALUES ({sbParameterList.ToString()}) RETURNING \"Id\"";
|
return $"INSERT INTO \"{_table}\" ({sbColumnList.ToString()}) VALUES ({sbParameterList.ToString()}) RETURNING \"Id\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $"INSERT INTO {_table} ({sbColumnList.ToString()}) VALUES ({sbParameterList.ToString()}); SELECT last_insert_rowid() id";
|
||||||
}
|
}
|
||||||
|
|
||||||
private TModel Insert(IDbConnection connection, IDbTransaction transaction, TModel model)
|
private TModel Insert(IDbConnection connection, IDbTransaction transaction, TModel model)
|
||||||
|
26
src/NzbDrone.Core/Datastore/PostgresOptions.cs
Normal file
26
src/NzbDrone.Core/Datastore/PostgresOptions.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore
|
||||||
|
{
|
||||||
|
public class PostgresOptions
|
||||||
|
{
|
||||||
|
public string Host { get; set; }
|
||||||
|
public int Port { get; set; }
|
||||||
|
public string User { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
public string MainDb { get; set; }
|
||||||
|
public string LogDb { get; set; }
|
||||||
|
|
||||||
|
public static PostgresOptions GetOptions()
|
||||||
|
{
|
||||||
|
var config = new ConfigurationBuilder()
|
||||||
|
.AddEnvironmentVariables()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var postgresOptions = new PostgresOptions();
|
||||||
|
config.GetSection("Prowlarr:Postgres").Bind(postgresOptions);
|
||||||
|
|
||||||
|
return postgresOptions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -313,7 +313,20 @@ namespace NzbDrone.Core.Datastore
|
|||||||
|
|
||||||
_sb.Append(" = ANY (");
|
_sb.Append(" = ANY (");
|
||||||
|
|
||||||
|
// hardcode the integer list if it exists to bypass parameter limit
|
||||||
|
if (item.Type == typeof(int) && TryGetRightValue(list, out var value))
|
||||||
|
{
|
||||||
|
var items = (IEnumerable<int>)value;
|
||||||
|
_sb.Append("('{");
|
||||||
|
_sb.Append(string.Join(", ", items));
|
||||||
|
_sb.Append("}')");
|
||||||
|
|
||||||
|
_gotConcreteValue = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
Visit(list);
|
Visit(list);
|
||||||
|
}
|
||||||
|
|
||||||
_sb.Append("))");
|
_sb.Append("))");
|
||||||
}
|
}
|
||||||
@@ -324,7 +337,7 @@ namespace NzbDrone.Core.Datastore
|
|||||||
|
|
||||||
Visit(body.Object);
|
Visit(body.Object);
|
||||||
|
|
||||||
_sb.Append(" LIKE '%' || ");
|
_sb.Append(" ILIKE '%' || ");
|
||||||
|
|
||||||
Visit(body.Arguments[0]);
|
Visit(body.Arguments[0]);
|
||||||
|
|
||||||
@@ -337,7 +350,7 @@ namespace NzbDrone.Core.Datastore
|
|||||||
|
|
||||||
Visit(body.Object);
|
Visit(body.Object);
|
||||||
|
|
||||||
_sb.Append(" LIKE ");
|
_sb.Append(" ILIKE ");
|
||||||
|
|
||||||
Visit(body.Arguments[0]);
|
Visit(body.Arguments[0]);
|
||||||
|
|
||||||
@@ -350,7 +363,7 @@ namespace NzbDrone.Core.Datastore
|
|||||||
|
|
||||||
Visit(body.Object);
|
Visit(body.Object);
|
||||||
|
|
||||||
_sb.Append(" LIKE '%' || ");
|
_sb.Append(" ILIKE '%' || ");
|
||||||
|
|
||||||
Visit(body.Arguments[0]);
|
Visit(body.Arguments[0]);
|
||||||
|
|
||||||
|
@@ -5,13 +5,16 @@ using DryIoc.Microsoft.DependencyInjection;
|
|||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common;
|
using NzbDrone.Common;
|
||||||
using NzbDrone.Common.Composition.Extensions;
|
using NzbDrone.Common.Composition.Extensions;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Instrumentation.Extensions;
|
using NzbDrone.Common.Instrumentation.Extensions;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Datastore.Extensions;
|
using NzbDrone.Core.Datastore.Extensions;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Jobs;
|
using NzbDrone.Core.Jobs;
|
||||||
using NzbDrone.Core.Lifecycle;
|
using NzbDrone.Core.Lifecycle;
|
||||||
@@ -43,6 +46,7 @@ namespace NzbDrone.App.Test
|
|||||||
// dummy lifetime and broadcaster so tests resolve
|
// dummy lifetime and broadcaster so tests resolve
|
||||||
container.RegisterInstance<IHostLifetime>(new Mock<IHostLifetime>().Object);
|
container.RegisterInstance<IHostLifetime>(new Mock<IHostLifetime>().Object);
|
||||||
container.RegisterInstance<IBroadcastSignalRMessage>(new Mock<IBroadcastSignalRMessage>().Object);
|
container.RegisterInstance<IBroadcastSignalRMessage>(new Mock<IBroadcastSignalRMessage>().Object);
|
||||||
|
container.RegisterInstance<IOptions<PostgresOptions>>(new Mock<IOptions<PostgresOptions>>().Object);
|
||||||
|
|
||||||
_container = container.GetServiceProvider();
|
_container = container.GetServiceProvider();
|
||||||
}
|
}
|
||||||
@@ -53,6 +57,12 @@ namespace NzbDrone.App.Test
|
|||||||
_container.GetRequiredService<IEnumerable<IIndexer>>().Should().NotBeEmpty();
|
_container.GetRequiredService<IEnumerable<IIndexer>>().Should().NotBeEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_able_to_resolve_downloadclients()
|
||||||
|
{
|
||||||
|
_container.GetRequiredService<IEnumerable<IDownloadClient>>().Should().NotBeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void container_should_inject_itself()
|
public void container_should_inject_itself()
|
||||||
{
|
{
|
||||||
|
@@ -9,8 +9,11 @@ using System.Security.Cryptography.X509Certificates;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using DryIoc;
|
using DryIoc;
|
||||||
using DryIoc.Microsoft.DependencyInjection;
|
using DryIoc.Microsoft.DependencyInjection;
|
||||||
|
using FluentMigrator.Runner.Processors.Postgres;
|
||||||
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Hosting.WindowsServices;
|
using Microsoft.Extensions.Hosting.WindowsServices;
|
||||||
using NLog;
|
using NLog;
|
||||||
@@ -23,6 +26,8 @@ using NzbDrone.Common.Instrumentation;
|
|||||||
using NzbDrone.Common.Instrumentation.Extensions;
|
using NzbDrone.Common.Instrumentation.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Datastore.Extensions;
|
using NzbDrone.Core.Datastore.Extensions;
|
||||||
|
using NzbDrone.Host;
|
||||||
|
using PostgresOptions = NzbDrone.Core.Datastore.PostgresOptions;
|
||||||
|
|
||||||
namespace NzbDrone.Host
|
namespace NzbDrone.Host
|
||||||
{
|
{
|
||||||
@@ -52,6 +57,7 @@ namespace NzbDrone.Host
|
|||||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||||
|
|
||||||
var appMode = GetApplicationMode(startupContext);
|
var appMode = GetApplicationMode(startupContext);
|
||||||
|
var config = GetConfiguration(startupContext);
|
||||||
|
|
||||||
switch (appMode)
|
switch (appMode)
|
||||||
{
|
{
|
||||||
@@ -80,12 +86,22 @@ namespace NzbDrone.Host
|
|||||||
// Utility mode
|
// Utility mode
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
new Container(rules => rules.WithNzbDroneRules())
|
new HostBuilder()
|
||||||
.AutoAddServices(ASSEMBLIES)
|
.UseServiceProviderFactory(new DryIocServiceProviderFactory(new Container(rules => rules.WithNzbDroneRules())))
|
||||||
|
.ConfigureContainer<IContainer>(c =>
|
||||||
|
{
|
||||||
|
c.AutoAddServices(Bootstrap.ASSEMBLIES)
|
||||||
.AddNzbDroneLogger()
|
.AddNzbDroneLogger()
|
||||||
|
.AddDatabase()
|
||||||
.AddStartupContext(startupContext)
|
.AddStartupContext(startupContext)
|
||||||
.Resolve<UtilityModeRouter>()
|
.Resolve<UtilityModeRouter>()
|
||||||
.Route(appMode);
|
.Route(appMode);
|
||||||
|
})
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.Configure<PostgresOptions>(config.GetSection("Prowlarr:Postgres"));
|
||||||
|
}).Build();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,6 +151,10 @@ namespace NzbDrone.Host
|
|||||||
.AddDatabase()
|
.AddDatabase()
|
||||||
.AddStartupContext(context);
|
.AddStartupContext(context);
|
||||||
})
|
})
|
||||||
|
.ConfigureServices(services =>
|
||||||
|
{
|
||||||
|
services.Configure<PostgresOptions>(config.GetSection("Prowlarr:Postgres"));
|
||||||
|
})
|
||||||
.ConfigureWebHost(builder =>
|
.ConfigureWebHost(builder =>
|
||||||
{
|
{
|
||||||
builder.UseConfiguration(config);
|
builder.UseConfiguration(config);
|
||||||
@@ -205,6 +225,7 @@ namespace NzbDrone.Host
|
|||||||
return new ConfigurationBuilder()
|
return new ConfigurationBuilder()
|
||||||
.AddXmlFile(appFolder.GetConfigPath(), optional: true, reloadOnChange: false)
|
.AddXmlFile(appFolder.GetConfigPath(), optional: true, reloadOnChange: false)
|
||||||
.AddInMemoryCollection(new List<KeyValuePair<string, string>> { new ("dataProtectionFolder", appFolder.GetDataProtectionPath()) })
|
.AddInMemoryCollection(new List<KeyValuePair<string, string>> { new ("dataProtectionFolder", appFolder.GetDataProtectionPath()) })
|
||||||
|
.AddEnvironmentVariables()
|
||||||
.Build();
|
.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,9 +1,15 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using Npgsql;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
using NzbDrone.Core.Indexers.FileList;
|
using NzbDrone.Core.Indexers.FileList;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
using NzbDrone.Test.Common.Datastore;
|
||||||
using Prowlarr.Http.ClientSchema;
|
using Prowlarr.Http.ClientSchema;
|
||||||
|
|
||||||
namespace NzbDrone.Integration.Test
|
namespace NzbDrone.Integration.Test
|
||||||
@@ -19,6 +25,8 @@ namespace NzbDrone.Integration.Test
|
|||||||
|
|
||||||
protected int Port { get; private set; }
|
protected int Port { get; private set; }
|
||||||
|
|
||||||
|
protected PostgresOptions PostgresOptions { get; set; } = new ();
|
||||||
|
|
||||||
protected override string RootUrl => $"http://localhost:{Port}/";
|
protected override string RootUrl => $"http://localhost:{Port}/";
|
||||||
|
|
||||||
protected override string ApiKey => _runner.ApiKey;
|
protected override string ApiKey => _runner.ApiKey;
|
||||||
@@ -27,7 +35,14 @@ namespace NzbDrone.Integration.Test
|
|||||||
{
|
{
|
||||||
Port = Interlocked.Increment(ref StaticPort);
|
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.Kill();
|
||||||
|
|
||||||
_runner.Start();
|
_runner.Start();
|
||||||
@@ -56,6 +71,22 @@ namespace NzbDrone.Integration.Test
|
|||||||
protected override void StopTestTarget()
|
protected override void StopTestTarget()
|
||||||
{
|
{
|
||||||
_runner.Kill();
|
_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,14 +8,9 @@ using NzbDrone.Test.Common;
|
|||||||
namespace NzbDrone.Mono.Test.DiskProviderTests
|
namespace NzbDrone.Mono.Test.DiskProviderTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
[Platform("Mono")]
|
[Platform(Exclude = "Win")]
|
||||||
public class SymbolicLinkResolverFixture : TestBase<SymbolicLinkResolver>
|
public class SymbolicLinkResolverFixture : TestBase<SymbolicLinkResolver>
|
||||||
{
|
{
|
||||||
public SymbolicLinkResolverFixture()
|
|
||||||
{
|
|
||||||
MonoOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_follow_nested_symlinks()
|
public void should_follow_nested_symlinks()
|
||||||
{
|
{
|
||||||
|
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;
|
||||||
|
using System.Collections.Specialized;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -9,7 +10,9 @@ using NUnit.Framework;
|
|||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Processes;
|
using NzbDrone.Common.Processes;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
|
|
||||||
namespace NzbDrone.Test.Common
|
namespace NzbDrone.Test.Common
|
||||||
@@ -22,13 +25,15 @@ namespace NzbDrone.Test.Common
|
|||||||
|
|
||||||
public string AppData { get; private set; }
|
public string AppData { get; private set; }
|
||||||
public string ApiKey { get; private set; }
|
public string ApiKey { get; private set; }
|
||||||
|
public PostgresOptions PostgresOptions { get; private set; }
|
||||||
public int Port { get; private set; }
|
public int Port { get; private set; }
|
||||||
|
|
||||||
public NzbDroneRunner(Logger logger, int port = 9696)
|
public NzbDroneRunner(Logger logger, PostgresOptions postgresOptions, int port = 9696)
|
||||||
{
|
{
|
||||||
_processProvider = new ProcessProvider(logger);
|
_processProvider = new ProcessProvider(logger);
|
||||||
_restClient = new RestClient($"http://localhost:{port}/api/v1");
|
_restClient = new RestClient($"http://localhost:{port}/api/v1");
|
||||||
|
|
||||||
|
PostgresOptions = postgresOptions;
|
||||||
Port = port;
|
Port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,9 +138,23 @@ namespace NzbDrone.Test.Common
|
|||||||
|
|
||||||
private void Start(string outputProwlarrConsoleExe)
|
private void Start(string outputProwlarrConsoleExe)
|
||||||
{
|
{
|
||||||
|
StringDictionary envVars = new ();
|
||||||
|
if (PostgresOptions?.Host != null)
|
||||||
|
{
|
||||||
|
envVars.Add("Prowlarr__Postgres__Host", PostgresOptions.Host);
|
||||||
|
envVars.Add("Prowlarr__Postgres__Port", PostgresOptions.Port.ToString());
|
||||||
|
envVars.Add("Prowlarr__Postgres__User", PostgresOptions.User);
|
||||||
|
envVars.Add("Prowlarr__Postgres__Password", PostgresOptions.Password);
|
||||||
|
envVars.Add("Prowlarr__Postgres__MainDb", PostgresOptions.MainDb);
|
||||||
|
envVars.Add("Prowlarr__Postgres__LogDb", PostgresOptions.LogDb);
|
||||||
|
|
||||||
|
TestContext.Progress.WriteLine("Using env vars:\n{0}", envVars.ToJson());
|
||||||
|
}
|
||||||
|
|
||||||
TestContext.Progress.WriteLine("Starting instance from {0} on port {1}", outputProwlarrConsoleExe, Port);
|
TestContext.Progress.WriteLine("Starting instance from {0} on port {1}", outputProwlarrConsoleExe, Port);
|
||||||
|
|
||||||
var args = "-nobrowser -nosingleinstancecheck -data=\"" + AppData + "\"";
|
var args = "-nobrowser -nosingleinstancecheck -data=\"" + AppData + "\"";
|
||||||
_nzbDroneProcess = _processProvider.Start(outputProwlarrConsoleExe, args, null, OnOutputDataReceived, OnOutputDataReceived);
|
_nzbDroneProcess = _processProvider.Start(outputProwlarrConsoleExe, args, envVars, OnOutputDataReceived, OnOutputDataReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnOutputDataReceived(string data)
|
private void OnOutputDataReceived(string data)
|
||||||
|
@@ -166,14 +166,6 @@ namespace NzbDrone.Test.Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void MonoOnly()
|
|
||||||
{
|
|
||||||
if (!PlatformInfo.IsMono)
|
|
||||||
{
|
|
||||||
throw new IgnoreException("mono specific test");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void NotBsd()
|
protected void NotBsd()
|
||||||
{
|
{
|
||||||
if (OsInfo.Os == Os.Bsd)
|
if (OsInfo.Os == Os.Bsd)
|
||||||
|
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>
|
||||||
|
<Prowlarr__Postgres__Host>192.168.100.5</Prowlarr__Postgres__Host>
|
||||||
|
<Prowlarr__Postgres__Port>5432</Prowlarr__Postgres__Port>
|
||||||
|
<Prowlarr__Postgres__User>abc</Prowlarr__Postgres__User>
|
||||||
|
<Prowlarr__Postgres__Password>abc</Prowlarr__Postgres__Password>
|
||||||
|
</EnvironmentVariables>
|
||||||
|
</RunConfiguration>
|
||||||
|
</RunSettings>
|
Reference in New Issue
Block a user