mirror of
https://github.com/Radarr/Radarr.git
synced 2024-10-05 15:47:20 +02:00
Set up tests on postgres
This commit is contained in:
parent
bd53092f0c
commit
9b21408a03
@ -516,6 +516,61 @@ 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: '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
|
- stage: Integration
|
||||||
displayName: Integration
|
displayName: Integration
|
||||||
dependsOn: Packages
|
dependsOn: Packages
|
||||||
@ -599,6 +654,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: '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
|
- job: Integration_FreeBSD
|
||||||
displayName: Integration Native FreeBSD
|
displayName: Integration Native FreeBSD
|
||||||
dependsOn: Prepare
|
dependsOn: Prepare
|
||||||
|
@ -44,7 +44,7 @@ public void SmokeTestSetup()
|
|||||||
|
|
||||||
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();
|
||||||
|
|
||||||
|
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.Collections.Generic;
|
||||||
using System.Data.SQLite;
|
using System.Data.SQLite;
|
||||||
using System.IO;
|
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 @@ protected TSubject Subject
|
|||||||
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 @@ protected virtual ITestDatabase WithTestDb(MigrationContext migrationContext)
|
|||||||
|
|
||||||
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 @@ private IDatabase CreateDatabase(MigrationContext migrationContext)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 @@ protected void SetupContainer()
|
|||||||
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>());
|
||||||
|
|
||||||
@ -170,12 +199,19 @@ public void TearDown()
|
|||||||
// Make sure there are no lingering connections. (When this happens it means we haven't disposed something properly)
|
// Make sure there are no lingering connections. (When this happens it means we haven't disposed something properly)
|
||||||
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 @@ public class RemoveCachedDatabase
|
|||||||
[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 @@ void Delete<T>(T childModel)
|
|||||||
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 @@ public class TestDatabase : ITestDatabase
|
|||||||
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;
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Exceptions;
|
using NzbDrone.Common.Exceptions;
|
||||||
using NzbDrone.Common.Instrumentation;
|
using NzbDrone.Common.Instrumentation;
|
||||||
using NzbDrone.Core.Configuration;
|
|
||||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Datastore
|
namespace NzbDrone.Core.Datastore
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Datastore
|
namespace NzbDrone.Core.Datastore
|
||||||
{
|
{
|
||||||
public class PostgresOptions
|
public class PostgresOptions
|
||||||
@ -8,5 +10,17 @@ public class PostgresOptions
|
|||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
public string MainDb { get; set; }
|
public string MainDb { get; set; }
|
||||||
public string LogDb { 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 @@ protected override Expression VisitMemberAccess(MemberExpression expression)
|
|||||||
// Only use the SQL condition if the expression didn't resolve to an actual value
|
// Only use the SQL condition if the expression didn't resolve to an actual value
|
||||||
if (tableName != null && !gotValue)
|
if (tableName != null && !gotValue)
|
||||||
{
|
{
|
||||||
_sb.Append($"\"{tableName}\".\"{expression.Member.Name.ToLower()}\"");
|
_sb.Append($"\"{tableName}\".\"{expression.Member.Name}\"");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -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.Newznab;
|
using NzbDrone.Core.Indexers.Newznab;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
using NzbDrone.Test.Common.Datastore;
|
||||||
using Radarr.Http.ClientSchema;
|
using Radarr.Http.ClientSchema;
|
||||||
|
|
||||||
namespace NzbDrone.Integration.Test
|
namespace NzbDrone.Integration.Test
|
||||||
@ -19,6 +25,8 @@ public abstract class IntegrationTest : IntegrationTestBase
|
|||||||
|
|
||||||
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 @@ protected override void StartTestTarget()
|
|||||||
{
|
{
|
||||||
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();
|
||||||
@ -59,6 +74,22 @@ protected override void InitializeTestTarget()
|
|||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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 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 @@ public class NzbDroneRunner
|
|||||||
|
|
||||||
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 = 7878)
|
public NzbDroneRunner(Logger logger, PostgresOptions postgresOptions, int port = 7878)
|
||||||
{
|
{
|
||||||
_processProvider = new ProcessProvider(logger);
|
_processProvider = new ProcessProvider(logger);
|
||||||
_restClient = new RestClient($"http://localhost:{port}/api/v3");
|
_restClient = new RestClient($"http://localhost:{port}/api/v3");
|
||||||
|
|
||||||
|
PostgresOptions = postgresOptions;
|
||||||
Port = port;
|
Port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,9 +137,23 @@ public void KillAll()
|
|||||||
|
|
||||||
private void Start(string outputRadarrConsoleExe)
|
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);
|
TestContext.Progress.WriteLine("Starting instance from {0} on port {1}", outputRadarrConsoleExe, Port);
|
||||||
|
|
||||||
var args = "-nobrowser -nosingleinstancecheck -data=\"" + AppData + "\"";
|
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)
|
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…
Reference in New Issue
Block a user