diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index f6c3cd2bd..6fd2d382a 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -534,6 +534,62 @@ 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: 'Lidarr.*.linux-core-x64.tar.gz'
+ artifactName: linux-x64-tests
+ Lidarr__Postgres__Host: 'localhost'
+ Lidarr__Postgres__Port: '5432'
+ Lidarr__Postgres__User: 'lidarr'
+ Lidarr__Postgres__Password: 'lidarr'
+
+ pool:
+ vmImage: ${{ variables.linuxImage }}
+
+ 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/fpcalc
+ displayName: Make fpcalc Executable
+ condition: and(succeeded(), ne(variables['osName'], 'Windows'))
+ - bash: find ${TESTSFOLDER} -name "Lidarr.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=lidarr \
+ -e POSTGRES_USER=lidarr \
+ -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
@@ -617,6 +673,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: 'Lidarr.*.linux-core-x64.tar.gz'
+ Lidarr__Postgres__Host: 'localhost'
+ Lidarr__Postgres__Port: '5432'
+ Lidarr__Postgres__User: 'lidarr'
+ Lidarr__Postgres__Password: 'lidarr'
+
+ pool:
+ vmImage: ${{ variables.linuxImage }}
+
+ steps:
+ - task: UseDotNet@2
+ displayName: 'Install .net core'
+ inputs:
+ version: $(dotnetVersion)
+ - checkout: none
+ - task: DownloadPipelineArtifact@2
+ displayName: Download Test Artifact
+ inputs:
+ buildType: 'current'
+ artifactName: 'linux-x64-tests'
+ 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/Lidarr/. ./bin/
+ displayName: Move Package Contents
+ - bash: |
+ docker run -d --name=postgres14 \
+ -e POSTGRES_PASSWORD=lidarr \
+ -e POSTGRES_USER=lidarr \
+ -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
diff --git a/frontend/src/System/Status/About/About.js b/frontend/src/System/Status/About/About.js
index 1acd44b11..4635fef68 100644
--- a/frontend/src/System/Status/About/About.js
+++ b/frontend/src/System/Status/About/About.js
@@ -23,6 +23,8 @@ class About extends Component {
isDocker,
runtimeVersion,
migrationVersion,
+ databaseVersion,
+ databaseType,
appData,
startupPath,
mode,
@@ -68,6 +70,11 @@ class About extends Component {
data={migrationVersion}
/>
+
+
(new Mock().Object);
+ container.RegisterInstance(new Mock().Object);
+ container.RegisterInstance(new Mock>().Object);
var serviceProvider = container.GetServiceProvider();
diff --git a/src/NzbDrone.Common/Instrumentation/CleanseLogMessage.cs b/src/NzbDrone.Common/Instrumentation/CleanseLogMessage.cs
index df0f49e1e..aa9692fb0 100644
--- a/src/NzbDrone.Common/Instrumentation/CleanseLogMessage.cs
+++ b/src/NzbDrone.Common/Instrumentation/CleanseLogMessage.cs
@@ -18,6 +18,7 @@ namespace NzbDrone.Common.Instrumentation
new Regex(@"iptorrents\.com/[/a-z0-9?&;]*?(?:[?&;](u|tp)=(?[^&=;]+?))+(?= |;|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"/fetch/[a-z0-9]{32}/(?[a-z0-9]{32})", RegexOptions.Compiled),
new Regex(@"getnzb.*?(?<=\?|&)(r)=(?[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
+ new Regex(@"\b(\w*)?(_?(?[^&=]+?)(?= |&|$|;)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
// Trackers Announce Keys; Designed for Qbit Json; should work for all in theory
new Regex(@"announce(\.php)?(/|%2f|%3fpasskey%3d)(?[a-z0-9]{16,})|(?[a-z0-9]{16,})(/|%2f)announce"),
diff --git a/src/NzbDrone.Common/Processes/ProcessProvider.cs b/src/NzbDrone.Common/Processes/ProcessProvider.cs
index 9336248bc..27fd09299 100644
--- a/src/NzbDrone.Common/Processes/ProcessProvider.cs
+++ b/src/NzbDrone.Common/Processes/ProcessProvider.cs
@@ -127,7 +127,18 @@ namespace NzbDrone.Common.Processes
try
{
_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)
{
diff --git a/src/NzbDrone.Core.Test/Datastore/DatabaseFixture.cs b/src/NzbDrone.Core.Test/Datastore/DatabaseFixture.cs
index 807057837..f6c182660 100644
--- a/src/NzbDrone.Core.Test/Datastore/DatabaseFixture.cs
+++ b/src/NzbDrone.Core.Test/Datastore/DatabaseFixture.cs
@@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.Datastore
public void SingleOrDefault_should_return_null_on_empty_db()
{
Mocker.Resolve()
- .OpenConnection().Query("SELECT * FROM Artists")
+ .OpenConnection().Query("SELECT * FROM \"Artists\"")
.SingleOrDefault(c => c.CleanName == "SomeTitle")
.Should()
.BeNull();
diff --git a/src/NzbDrone.Core.Test/Datastore/DatabaseRelationshipFixture.cs b/src/NzbDrone.Core.Test/Datastore/DatabaseRelationshipFixture.cs
index ab17a1550..6c073b18f 100644
--- a/src/NzbDrone.Core.Test/Datastore/DatabaseRelationshipFixture.cs
+++ b/src/NzbDrone.Core.Test/Datastore/DatabaseRelationshipFixture.cs
@@ -2,7 +2,9 @@ using System;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
+using FluentAssertions.Equivalency;
using NUnit.Framework;
+using NzbDrone.Core.Datastore;
using NzbDrone.Core.History;
using NzbDrone.Core.Music;
using NzbDrone.Core.Qualities;
@@ -13,6 +15,17 @@ namespace NzbDrone.Core.Test.Datastore
[TestFixture]
public class DatabaseRelationshipFixture : DbTest
{
+ [SetUp]
+ public void Setup()
+ {
+ AssertionOptions.AssertEquivalencyUsing(options =>
+ {
+ options.Using(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation.ToUniversalTime())).WhenTypeIs();
+ options.Using(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation.Value.ToUniversalTime())).WhenTypeIs();
+ return options;
+ });
+ }
+
[Test]
public void one_to_one()
{
@@ -33,13 +46,7 @@ namespace NzbDrone.Core.Test.Datastore
var loadedAlbum = Db.Single().Album.Value;
loadedAlbum.Should().NotBeNull();
- loadedAlbum.Should().BeEquivalentTo(album,
- options => options
- .IncludingAllRuntimeProperties()
- .Excluding(c => c.Artist)
- .Excluding(c => c.ArtistId)
- .Excluding(c => c.ArtistMetadata)
- .Excluding(c => c.AlbumReleases));
+ loadedAlbum.Should().BeEquivalentTo(album, AlbumComparerOptions);
}
[Test]
@@ -86,5 +93,9 @@ namespace NzbDrone.Core.Test.Datastore
returnedHistory[0].Quality.Quality.Should().Be(Quality.MP3_320);
}
+
+ private EquivalencyAssertionOptions AlbumComparerOptions(EquivalencyAssertionOptions opts) => opts.ComparingByMembers()
+ .Excluding(ctx => ctx.SelectedMemberInfo.MemberType.IsGenericType && ctx.SelectedMemberInfo.MemberType.GetGenericTypeDefinition() == typeof(LazyLoaded<>))
+ .Excluding(x => x.ArtistId);
}
}
diff --git a/src/NzbDrone.Core.Test/Datastore/LazyLoadingFixture.cs b/src/NzbDrone.Core.Test/Datastore/LazyLoadingFixture.cs
index 5241eefcd..427f62f2b 100644
--- a/src/NzbDrone.Core.Test/Datastore/LazyLoadingFixture.cs
+++ b/src/NzbDrone.Core.Test/Datastore/LazyLoadingFixture.cs
@@ -104,7 +104,7 @@ namespace NzbDrone.Core.Test.Datastore
public void should_lazy_load_artist_for_trackfile()
{
var db = Mocker.Resolve();
- var tracks = db.Query(new SqlBuilder()).ToList();
+ var tracks = db.Query(new SqlBuilder(db.DatabaseType)).ToList();
Assert.IsNotEmpty(tracks);
foreach (var track in tracks)
@@ -120,7 +120,7 @@ namespace NzbDrone.Core.Test.Datastore
public void should_lazy_load_trackfile_if_not_joined()
{
var db = Mocker.Resolve();
- var tracks = db.Query