Fixed: All the tests

pull/928/head
ta264 5 years ago committed by Qstick
parent 9392c13364
commit ee7d47d044

@ -281,6 +281,7 @@ stages:
testResultsFormat: 'NUnit' testResultsFormat: 'NUnit'
testResultsFiles: '**/TestResult.xml' testResultsFiles: '**/TestResult.xml'
testRunTitle: '$(osName) Unit Tests' testRunTitle: '$(osName) Unit Tests'
failTaskOnFailedTests: true
- stage: Integration_Automation - stage: Integration_Automation
displayName: Integration / Automation displayName: Integration / Automation
@ -294,6 +295,10 @@ stages:
osName: 'Linux' osName: 'Linux'
imageName: 'ubuntu-16.04' imageName: 'ubuntu-16.04'
pattern: 'Lidarr.**.linux.tar.gz' pattern: 'Lidarr.**.linux.tar.gz'
Mac:
osName: 'Mac'
imageName: 'macos-10.13'
pattern: 'Lidarr.**.osx.tar.gz'
Windows: Windows:
osName: 'Windows' osName: 'Windows'
imageName: 'vs2017-win2016' imageName: 'vs2017-win2016'
@ -308,6 +313,14 @@ stages:
sudo tar xf chromaprint-fpcalc-1.4.3-linux-x86_64.tar.gz --strip-components=1 --directory /usr/bin sudo tar xf chromaprint-fpcalc-1.4.3-linux-x86_64.tar.gz --strip-components=1 --directory /usr/bin
displayName: Install fpcalc displayName: Install fpcalc
condition: and(succeeded(), eq(variables['osName'], 'Linux')) condition: and(succeeded(), eq(variables['osName'], 'Linux'))
- bash: |
SYMLINK=5_18_1
MONOPREFIX=/Library/Frameworks/Mono.framework/Versions/$SYMLINK
echo "##vso[task.setvariable variable=DYLD_FALLBACK_LIBRARY_PATH;].:$MONOPREFIX/lib:/lib:/usr/lib:$DYLD_LIBRARY_FALLBACK_PATH"
echo "##vso[task.setvariable variable=PKG_CONFIG_PATH;]$MONOPREFIX/lib/pkgconfig:$MONOPREFIX/share/pkgconfig:$PKG_CONFIG_PATH"
echo "##vso[task.setvariable variable=PATH;]$MONOPREFIX/bin:$PATH"
displayName: Set Mono Version
condition: and(succeeded(), eq(variables['osName'], 'Mac'))
- checkout: none - checkout: none
- task: DownloadPipelineArtifact@2 - task: DownloadPipelineArtifact@2
displayName: Download Test Artifact displayName: Download Test Artifact
@ -342,6 +355,7 @@ stages:
testResultsFormat: 'NUnit' testResultsFormat: 'NUnit'
testResultsFiles: '**/TestResult.xml' testResultsFiles: '**/TestResult.xml'
testRunTitle: '$(osName) Integration Tests' testRunTitle: '$(osName) Integration Tests'
failTaskOnFailedTests: true
displayName: Publish Test Results displayName: Publish Test Results
- job: Automation - job: Automation
@ -351,14 +365,17 @@ stages:
osName: 'Linux' osName: 'Linux'
imageName: 'ubuntu-16.04' imageName: 'ubuntu-16.04'
pattern: 'Lidarr.**.linux.tar.gz' pattern: 'Lidarr.**.linux.tar.gz'
failBuild: true
Mac: Mac:
osName: 'Mac' osName: 'Mac'
imageName: 'macos-10.13' # Fails due to firefox not being installed on image imageName: 'macos-10.13' # Fails due to firefox not being installed on image
pattern: 'Lidarr.**.osx.tar.gz' pattern: 'Lidarr.**.osx.tar.gz'
failBuild: false
Windows: Windows:
osName: 'Windows' osName: 'Windows'
imageName: 'vs2017-win2016' imageName: 'vs2017-win2016'
pattern: 'Lidarr.**.windows.zip' pattern: 'Lidarr.**.windows.zip'
failBuild: true
pool: pool:
vmImage: $(imageName) vmImage: $(imageName)
@ -413,6 +430,7 @@ stages:
testResultsFormat: 'NUnit' testResultsFormat: 'NUnit'
testResultsFiles: '**/TestResult.xml' testResultsFiles: '**/TestResult.xml'
testRunTitle: '$(osName) Automation Tests' testRunTitle: '$(osName) Automation Tests'
failTaskOnFailedTests: $(failBuild)
displayName: Publish Test Results displayName: Publish Test Results
- stage: Analyze - stage: Analyze

@ -6,6 +6,7 @@ using Nancy.Responses;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using Lidarr.Http; using Lidarr.Http;
using NLog;
namespace Lidarr.Api.V1.Logs namespace Lidarr.Api.V1.Logs
{ {
@ -54,6 +55,8 @@ namespace Lidarr.Api.V1.Logs
private Response GetLogFileResponse(string filename) private Response GetLogFileResponse(string filename)
{ {
LogManager.Flush();
var filePath = GetLogFilePath(filename); var filePath = GetLogFilePath(filename);
if (!_diskProvider.FileExists(filePath)) if (!_diskProvider.FileExists(filePath))

@ -245,14 +245,20 @@ namespace NzbDrone.Common.Test.DiskTests
} }
[Test] [Test]
[Ignore("No longer behaving this way in a Windows 10 Feature Update")]
public void should_not_be_able_to_rename_open_hardlinks_with_fileshare_none() public void should_not_be_able_to_rename_open_hardlinks_with_fileshare_none()
{ {
WindowsOnly();
Assert.Throws<IOException>(() => DoHardLinkRename(FileShare.None)); Assert.Throws<IOException>(() => DoHardLinkRename(FileShare.None));
} }
[Test] [Test]
[Ignore("No longer behaving this way in a Windows 10 Feature Update")]
public void should_not_be_able_to_rename_open_hardlinks_with_fileshare_write() public void should_not_be_able_to_rename_open_hardlinks_with_fileshare_write()
{ {
WindowsOnly();
Assert.Throws<IOException>(() => DoHardLinkRename(FileShare.Read)); Assert.Throws<IOException>(() => DoHardLinkRename(FileShare.Read));
} }
} }

@ -64,6 +64,7 @@ namespace NzbDrone.Common.Test
} }
[Test] [Test]
[Platform(Exclude="MacOsX")]
public void Should_be_able_to_start_process() public void Should_be_able_to_start_process()
{ {
var process = StartDummyProcess(); var process = StartDummyProcess();
@ -79,6 +80,7 @@ namespace NzbDrone.Common.Test
[Test] [Test]
[Platform(Exclude="MacOsX")]
public void kill_all_should_kill_all_process_with_name() public void kill_all_should_kill_all_process_with_name()
{ {
var dummy1 = StartDummyProcess(); var dummy1 = StartDummyProcess();
@ -92,7 +94,8 @@ namespace NzbDrone.Common.Test
private Process StartDummyProcess() private Process StartDummyProcess()
{ {
return Subject.Start(Path.Combine(TestContext.CurrentContext.TestDirectory, DummyApp.DUMMY_PROCCESS_NAME + ".exe")); var path = Path.Combine(TestContext.CurrentContext.TestDirectory, DummyApp.DUMMY_PROCCESS_NAME + ".exe");
return Subject.Start(path);
} }
[Test] [Test]

@ -1,4 +1,5 @@
using System; using System;
using System.Security.Principal;
using System.ServiceProcess; using System.ServiceProcess;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
@ -61,6 +62,10 @@ namespace NzbDrone.Common.Test
[Test] [Test]
public void Service_should_be_installed_and_then_uninstalled() public void Service_should_be_installed_and_then_uninstalled()
{ {
if (!IsAnAdministrator())
{
Assert.Inconclusive("Can't run test without Administrator rights");
}
Subject.ServiceExist(TEMP_SERVICE_NAME).Should().BeFalse("Service already installed"); Subject.ServiceExist(TEMP_SERVICE_NAME).Should().BeFalse("Service already installed");
Subject.Install(TEMP_SERVICE_NAME); Subject.Install(TEMP_SERVICE_NAME);
@ -100,8 +105,13 @@ namespace NzbDrone.Common.Test
} }
[Test] [Test]
public void should_throw_if_starting_a_running_serivce() public void should_throw_if_starting_a_running_service()
{ {
if (!IsAnAdministrator())
{
Assert.Inconclusive("Can't run test without Administrator rights");
}
Subject.GetService(ALWAYS_INSTALLED_SERVICE).Status Subject.GetService(ALWAYS_INSTALLED_SERVICE).Status
.Should().NotBe(ServiceControllerStatus.Running); .Should().NotBe(ServiceControllerStatus.Running);
@ -127,5 +137,10 @@ namespace NzbDrone.Common.Test
ExceptionVerification.ExpectedWarns(1); ExceptionVerification.ExpectedWarns(1);
} }
private static bool IsAnAdministrator()
{
var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
} }
} }

@ -142,7 +142,7 @@ namespace NzbDrone.Common.EnvironmentInfo
} }
var lowerCurrentDir = Directory.GetCurrentDirectory().ToLower(); var lowerCurrentDir = Directory.GetCurrentDirectory().ToLower();
if (lowerCurrentDir.Contains("teamcity")) return false; if (lowerCurrentDir.Contains("vsts")) return false;
if (lowerCurrentDir.Contains("buildagent")) return false; if (lowerCurrentDir.Contains("buildagent")) return false;
if (lowerCurrentDir.Contains("_output")) return false; if (lowerCurrentDir.Contains("_output")) return false;

@ -328,6 +328,8 @@ namespace NzbDrone.Common.Processes
var monoProcesses = Process.GetProcessesByName("mono") var monoProcesses = Process.GetProcessesByName("mono")
.Union(Process.GetProcessesByName("mono-sgen")) .Union(Process.GetProcessesByName("mono-sgen"))
.Union(Process.GetProcessesByName("mono-sgen32"))
.Union(Process.GetProcessesByName("mono-sgen64"))
.Where(process => .Where(process =>
process.Modules.Cast<ProcessModule>() process.Modules.Cast<ProcessModule>()
.Any(module => .Any(module =>

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.SQLite;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using FluentMigrator.Runner; using FluentMigrator.Runner;
@ -115,21 +116,14 @@ namespace NzbDrone.Core.Test.Framework
[TearDown] [TearDown]
public void TearDown() public void TearDown()
{ {
if (TestFolderInfo != null && Directory.Exists(TestFolderInfo.AppDataFolder)) // Make sure there are no lingering connections. (When this happens it means we haven't disposed something properly)
GC.Collect();
GC.WaitForPendingFinalizers();
SQLiteConnection.ClearAllPools();
if (TestFolderInfo != null)
{ {
var files = Directory.GetFiles(TestFolderInfo.AppDataFolder); DeleteTempFolder(TestFolderInfo.AppDataFolder);
foreach (var file in files)
{
try
{
File.Delete(file);
}
catch (Exception)
{
}
}
} }
} }
} }

@ -40,7 +40,7 @@ namespace NzbDrone.Core.Test.Instrumentation
{ {
_logger.Info(_uniqueMessage); _logger.Info(_uniqueMessage);
Thread.Sleep(600); Thread.Sleep(1000);
StoredModel.Message.Should().Be(_uniqueMessage); StoredModel.Message.Should().Be(_uniqueMessage);
VerifyLog(StoredModel, LogLevel.Info); VerifyLog(StoredModel, LogLevel.Info);
@ -57,7 +57,7 @@ namespace NzbDrone.Core.Test.Instrumentation
_logger.Info(message); _logger.Info(message);
Thread.Sleep(600); Thread.Sleep(1000);
StoredModel.Message.Should().HaveLength(message.Length); StoredModel.Message.Should().HaveLength(message.Length);
StoredModel.Message.Should().Be(message); StoredModel.Message.Should().Be(message);
@ -76,7 +76,7 @@ namespace NzbDrone.Core.Test.Instrumentation
_logger.Info(Guid.NewGuid()); _logger.Info(Guid.NewGuid());
} }
Thread.Sleep(600); Thread.Sleep(1000);
MapRepository.Instance.EnableTraceLogging = true; MapRepository.Instance.EnableTraceLogging = true;
} }
@ -88,7 +88,7 @@ namespace NzbDrone.Core.Test.Instrumentation
_logger.Error(ex, _uniqueMessage); _logger.Error(ex, _uniqueMessage);
Thread.Sleep(600); Thread.Sleep(1000);
VerifyLog(StoredModel, LogLevel.Error); VerifyLog(StoredModel, LogLevel.Error);
StoredModel.Message.Should().Be(_uniqueMessage + ": " + ex.Message); StoredModel.Message.Should().Be(_uniqueMessage + ": " + ex.Message);
@ -106,7 +106,7 @@ namespace NzbDrone.Core.Test.Instrumentation
_logger.Error(ex, _uniqueMessage); _logger.Error(ex, _uniqueMessage);
Thread.Sleep(600); Thread.Sleep(1000);
StoredModel.Message.Should().Be(ex.Message); StoredModel.Message.Should().Be(ex.Message);
@ -121,7 +121,7 @@ namespace NzbDrone.Core.Test.Instrumentation
var epFile = new TrackFile(); var epFile = new TrackFile();
_logger.Debug("File {0} no longer exists on disk. removing from database.", epFile.Path); _logger.Debug("File {0} no longer exists on disk. removing from database.", epFile.Path);
Thread.Sleep(600); Thread.Sleep(1000);
epFile.Path.Should().BeNull(); epFile.Path.Should().BeNull();
} }

@ -18,7 +18,6 @@ namespace NzbDrone.Core.Test.Messaging.Commands
private CommandQueue _commandQueue; private CommandQueue _commandQueue;
private Mock<IExecute<CommandA>> _executorA; private Mock<IExecute<CommandA>> _executorA;
private Mock<IExecute<CommandB>> _executorB; private Mock<IExecute<CommandB>> _executorB;
private bool _commandExecuted = false;
[SetUp] [SetUp]
public void Setup() public void Setup()
@ -53,26 +52,34 @@ namespace NzbDrone.Core.Test.Messaging.Commands
.Returns(_commandQueue.GetConsumingEnumerable); .Returns(_commandQueue.GetConsumingEnumerable);
} }
private void QueueAndWaitForExecution(CommandModel commandModel) private void QueueAndWaitForExecution(CommandModel commandModel, bool waitPublish = false)
{ {
Thread.Sleep(10); var waitEventComplete = new ManualResetEventSlim();
var waitEventPublish = new ManualResetEventSlim();
Mocker.GetMock<IManageCommandQueue>() Mocker.GetMock<IManageCommandQueue>()
.Setup(s => s.Complete(It.Is<CommandModel>(c => c == commandModel), It.IsAny<string>())) .Setup(s => s.Complete(It.Is<CommandModel>(c => c == commandModel), It.IsAny<string>()))
.Callback(() => _commandExecuted = true); .Callback(() => waitEventComplete.Set());
Mocker.GetMock<IManageCommandQueue>() Mocker.GetMock<IManageCommandQueue>()
.Setup(s => s.Fail(It.Is<CommandModel>(c => c == commandModel), It.IsAny<string>(), It.IsAny<Exception>())) .Setup(s => s.Fail(It.Is<CommandModel>(c => c == commandModel), It.IsAny<string>(), It.IsAny<Exception>()))
.Callback(() => _commandExecuted = true); .Callback(() => waitEventComplete.Set());
Mocker.GetMock<IEventAggregator>()
.Setup(s => s.PublishEvent<CommandExecutedEvent>(It.IsAny<CommandExecutedEvent>()))
.Callback(() => waitEventPublish.Set());
_commandQueue.Add(commandModel); _commandQueue.Add(commandModel);
while (!_commandExecuted) if (!waitEventComplete.Wait(2000))
{ {
Thread.Sleep(100); Assert.Fail("Command did not Complete/Fail within 2 sec");
} }
Thread.Sleep(10); if (waitPublish && !waitEventPublish.Wait(500))
{
Assert.Fail("Command did not Publish within 500 msec");
}
} }
[Test] [Test]
@ -138,9 +145,7 @@ namespace NzbDrone.Core.Test.Messaging.Commands
VerifyEventPublished<CommandExecutedEvent>(); VerifyEventPublished<CommandExecutedEvent>();
Thread.Sleep(10); ExceptionVerification.WaitForErrors(1, 500);
ExceptionVerification.ExpectedErrors(1);
} }
[Test] [Test]
@ -175,18 +180,17 @@ namespace NzbDrone.Core.Test.Messaging.Commands
QueueAndWaitForExecution(commandModel); QueueAndWaitForExecution(commandModel);
Mocker.GetMock<IManageCommandQueue>() Mocker.GetMock<IManageCommandQueue>()
.Setup(s => s.Complete(It.Is<CommandModel>(c => c == commandModel), commandA.CompletionMessage)) .Verify(s => s.Complete(It.Is<CommandModel>(c => c == commandModel), commandA.CompletionMessage), Times.Once());
.Callback(() => _commandExecuted = true);
} }
[Test] [Test]
public void should_use_last_progress_message_if_completion_message_is_null() public void should_use_last_progress_message_if_completion_message_is_null()
{ {
GivenCommandQueue(); GivenCommandQueue();
var commandA = new CommandA(); var commandB = new CommandB();
var commandModel = new CommandModel var commandModel = new CommandModel
{ {
Body = commandA, Body = commandB,
Message = "Do work" Message = "Do work"
}; };
@ -195,8 +199,7 @@ namespace NzbDrone.Core.Test.Messaging.Commands
QueueAndWaitForExecution(commandModel); QueueAndWaitForExecution(commandModel);
Mocker.GetMock<IManageCommandQueue>() Mocker.GetMock<IManageCommandQueue>()
.Setup(s => s.Complete(It.Is<CommandModel>(c => c == commandModel), commandModel.Message)) .Verify(s => s.Complete(It.Is<CommandModel>(c => c == commandModel), commandModel.Message), Times.Once());
.Callback(() => _commandExecuted = true);
} }
} }

@ -7,6 +7,7 @@ using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Music; using NzbDrone.Core.Music;
using NzbDrone.Core.Validation.Paths; using NzbDrone.Core.Validation.Paths;
using NzbDrone.Test.Common; using NzbDrone.Test.Common;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Core.Test.ValidationTests namespace NzbDrone.Core.Test.ValidationTests
{ {
@ -52,8 +53,9 @@ namespace NzbDrone.Core.Test.ValidationTests
{ {
MonoOnly(); MonoOnly();
var bin = OsInfo.IsOsx ? "/System" : "/bin";
var artist = Builder<Artist>.CreateNew() var artist = Builder<Artist>.CreateNew()
.With(s => s.Path = "/bin") .With(s => s.Path = bin)
.Build(); .Build();
_validator.Validate(artist).IsValid.Should().BeFalse(); _validator.Validate(artist).IsValid.Should().BeFalse();
@ -64,9 +66,10 @@ namespace NzbDrone.Core.Test.ValidationTests
{ {
MonoOnly(); MonoOnly();
var bin = OsInfo.IsOsx ? "/System" : "/bin";
var artist = Builder<Artist>.CreateNew() var artist = Builder<Artist>.CreateNew()
.With(s => s.Path = "/bin/test") .With(s => s.Path = Path.Combine(bin, "test"))
.Build(); .Build();
_validator.Validate(artist).IsValid.Should().BeFalse(); _validator.Validate(artist).IsValid.Should().BeFalse();
} }

@ -50,6 +50,8 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
{ {
runner.MigrateUp(true); runner.MigrateUp(true);
} }
processor.Dispose();
} }
catch (SQLiteException) catch (SQLiteException)
{ {
@ -57,7 +59,6 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
SQLiteConnection.ClearAllPools(); SQLiteConnection.ClearAllPools();
throw; throw;
} }
sw.Stop(); sw.Stop();

@ -23,27 +23,27 @@ namespace NzbDrone.Integration.Test.ApiTests
[Test] [Test]
public void should_be_able_to_get_albums() public void should_be_able_to_get_albums()
{ {
var artist = EnsureArtist("aaaa_aaaaa_asaaaaa", "Alien Ant Farm", true); var artist = EnsureArtist("cc2c9c3c-b7bc-4b8b-84d8-4fbd8779e493", "Adele", true);
var request = Calendar.BuildRequest(); var request = Calendar.BuildRequest();
request.AddParameter("start", new DateTime(2015, 10, 1).ToString("s") + "Z"); request.AddParameter("start", new DateTime(2015, 11, 19).ToString("s") + "Z");
request.AddParameter("end", new DateTime(2015, 10, 3).ToString("s") + "Z"); request.AddParameter("end", new DateTime(2015, 11, 21).ToString("s") + "Z");
var items = Calendar.Get<List<AlbumResource>>(request); var items = Calendar.Get<List<AlbumResource>>(request);
items = items.Where(v => v.ArtistId == artist.Id).ToList(); items = items.Where(v => v.ArtistId == artist.Id).ToList();
items.Should().HaveCount(1); items.Should().HaveCount(1);
items.First().Title.Should().Be("The Troll Farmer"); items.First().Title.Should().Be("25");
} }
[Test] [Test]
public void should_not_be_able_to_get_unmonitored_albums() public void should_not_be_able_to_get_unmonitored_albums()
{ {
var artist = EnsureArtist("aaaa_aaaaa_asaaaaa", "Alien Ant Farm", false); var artist = EnsureArtist("cc2c9c3c-b7bc-4b8b-84d8-4fbd8779e493", "Adele", false);
var request = Calendar.BuildRequest(); var request = Calendar.BuildRequest();
request.AddParameter("start", new DateTime(2015, 10, 1).ToString("s") + "Z"); request.AddParameter("start", new DateTime(2015, 11, 19).ToString("s") + "Z");
request.AddParameter("end", new DateTime(2015, 10, 3).ToString("s") + "Z"); request.AddParameter("end", new DateTime(2015, 11, 21).ToString("s") + "Z");
request.AddParameter("unmonitored", "false"); request.AddParameter("unmonitored", "false");
var items = Calendar.Get<List<AlbumResource>>(request); var items = Calendar.Get<List<AlbumResource>>(request);
@ -55,18 +55,18 @@ namespace NzbDrone.Integration.Test.ApiTests
[Test] [Test]
public void should_be_able_to_get_unmonitored_albums() public void should_be_able_to_get_unmonitored_albums()
{ {
var artist = EnsureArtist("aaaa_aaaaa_asaaaaa", "Alien Ant Farm", false); var artist = EnsureArtist("cc2c9c3c-b7bc-4b8b-84d8-4fbd8779e493", "Adele", false);
var request = Calendar.BuildRequest(); var request = Calendar.BuildRequest();
request.AddParameter("start", new DateTime(2015, 10, 1).ToString("s") + "Z"); request.AddParameter("start", new DateTime(2015, 11, 19).ToString("s") + "Z");
request.AddParameter("end", new DateTime(2015, 10, 3).ToString("s") + "Z"); request.AddParameter("end", new DateTime(2015, 11, 21).ToString("s") + "Z");
request.AddParameter("unmonitored", "true"); request.AddParameter("unmonitored", "true");
var items = Calendar.Get<List<AlbumResource>>(request); var items = Calendar.Get<List<AlbumResource>>(request);
items = items.Where(v => v.ArtistId == artist.Id).ToList(); items = items.Where(v => v.ArtistId == artist.Id).ToList();
items.Should().HaveCount(1); items.Should().HaveCount(1);
items.First().Title.Should().Be("The Troll Farmer"); items.First().Title.Should().Be("25");
} }
} }
} }

@ -1,6 +1,6 @@
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using Lidarr.Api.V1.Commands; using NzbDrone.Integration.Test.Client;
namespace NzbDrone.Integration.Test.ApiTests namespace NzbDrone.Integration.Test.ApiTests
{ {
@ -11,7 +11,7 @@ namespace NzbDrone.Integration.Test.ApiTests
[Test] [Test]
public void should_be_able_to_run_rss_sync() public void should_be_able_to_run_rss_sync()
{ {
var response = Commands.Post(new CommandResource { Name = "rsssync" }); var response = Commands.Post(new SimpleCommandResource { Name = "rsssync" });
response.Id.Should().NotBe(0); response.Id.Should().NotBe(0);
} }

@ -3,7 +3,6 @@ using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using Lidarr.Api.V1.Artist; using Lidarr.Api.V1.Artist;
using System.Linq; using System.Linq;
using NzbDrone.Test.Common;
namespace NzbDrone.Integration.Test.ApiTests namespace NzbDrone.Integration.Test.ApiTests
{ {
@ -15,30 +14,16 @@ namespace NzbDrone.Integration.Test.ApiTests
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_artist = GivenArtistWithTracks(); _artist = EnsureArtist("8ac6cc32-8ddf-43b1-9ac4-4b04f9053176", "Alien Ant Farm");
} }
private ArtistResource GivenArtistWithTracks() [Test, Order(0)]
{
var newArtist = Artist.Lookup("archer").Single(c => c.ForeignArtistId == "110381");
newArtist.QualityProfileId = 1;
newArtist.Path = @"C:\Test\Archer".AsOsAgnostic();
newArtist = Artist.Post(newArtist);
WaitForCompletion(() => Tracks.GetTracksInArtist(newArtist.Id).Count > 0);
return newArtist;
}
[Test]
public void should_be_able_to_get_all_tracks_in_artist() public void should_be_able_to_get_all_tracks_in_artist()
{ {
Tracks.GetTracksInArtist(_artist.Id).Count.Should().BeGreaterThan(0); Tracks.GetTracksInArtist(_artist.Id).Count.Should().BeGreaterThan(0);
} }
[Test] [Test, Order(1)]
public void should_be_able_to_get_a_single_track() public void should_be_able_to_get_a_single_track()
{ {
var tracks = Tracks.GetTracksInArtist(_artist.Id); var tracks = Tracks.GetTracksInArtist(_artist.Id);

@ -36,15 +36,15 @@ namespace NzbDrone.Integration.Test.ApiTests
var result = WantedMissing.GetPaged(0, 15, "releaseDate", "desc"); var result = WantedMissing.GetPaged(0, 15, "releaseDate", "desc");
result.Records.First().Artist.Should().NotBeNull(); result.Records.First().Artist.Should().NotBeNull();
result.Records.First().Artist.ArtistName.Should().Be("The Blacklist"); result.Records.First().Artist.ArtistName.Should().Be("Alien Ant Farm");
} }
[Test, Order(1)] [Test, Order(1)]
public void cutoff_should_have_monitored_items() public void cutoff_should_have_monitored_items()
{ {
EnsureProfileCutoff(1, Quality.MP3_256); EnsureProfileCutoff(1, "Lossless");
var artist = EnsureArtist("8ac6cc32-8ddf-43b1-9ac4-4b04f9053176", "Alien Ant Farm", true); var artist = EnsureArtist("8ac6cc32-8ddf-43b1-9ac4-4b04f9053176", "Alien Ant Farm", true);
EnsureTrackFile(artist, 1, 1, Quality.MP3_192); EnsureTrackFile(artist, 1, 1, 1, Quality.MP3_192);
var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc"); var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc");
@ -64,9 +64,9 @@ namespace NzbDrone.Integration.Test.ApiTests
[Test, Order(1)] [Test, Order(1)]
public void cutoff_should_not_have_unmonitored_items() public void cutoff_should_not_have_unmonitored_items()
{ {
EnsureProfileCutoff(1, Quality.MP3_256); EnsureProfileCutoff(1, "Lossless");
var artist = EnsureArtist("8ac6cc32-8ddf-43b1-9ac4-4b04f9053176", "Alien Ant Farm", false); var artist = EnsureArtist("8ac6cc32-8ddf-43b1-9ac4-4b04f9053176", "Alien Ant Farm", false);
EnsureTrackFile(artist, 1, 1, Quality.MP3_192); EnsureTrackFile(artist, 1, 1, 1, Quality.MP3_192);
var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc"); var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc");
@ -76,9 +76,9 @@ namespace NzbDrone.Integration.Test.ApiTests
[Test, Order(1)] [Test, Order(1)]
public void cutoff_should_have_artist() public void cutoff_should_have_artist()
{ {
EnsureProfileCutoff(1, Quality.MP3_256); EnsureProfileCutoff(1, "Lossless");
var artist = EnsureArtist("8ac6cc32-8ddf-43b1-9ac4-4b04f9053176", "Alien Ant Farm", true); var artist = EnsureArtist("8ac6cc32-8ddf-43b1-9ac4-4b04f9053176", "Alien Ant Farm", true);
EnsureTrackFile(artist, 1, 1, Quality.MP3_192); EnsureTrackFile(artist, 1, 1, 1, Quality.MP3_192);
var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc"); var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc");
@ -99,9 +99,9 @@ namespace NzbDrone.Integration.Test.ApiTests
[Test, Order(2)] [Test, Order(2)]
public void cutoff_should_have_unmonitored_items() public void cutoff_should_have_unmonitored_items()
{ {
EnsureProfileCutoff(1, Quality.MP3_256); EnsureProfileCutoff(1, "Lossless");
var artist = EnsureArtist("8ac6cc32-8ddf-43b1-9ac4-4b04f9053176", "Alien Ant Farm", false); var artist = EnsureArtist("8ac6cc32-8ddf-43b1-9ac4-4b04f9053176", "Alien Ant Farm", false);
EnsureTrackFile(artist, 1, 1, Quality.MP3_192); EnsureTrackFile(artist, 1, 1, 1, Quality.MP3_192);
var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc", "monitored", "false"); var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc", "monitored", "false");

@ -40,7 +40,7 @@ namespace NzbDrone.Integration.Test.Client
return request; return request;
} }
public T Execute<T>(IRestRequest request, HttpStatusCode statusCode) where T : class, new() public string Execute(IRestRequest request, HttpStatusCode statusCode)
{ {
_logger.Info("{0}: {1}", request.Method, _restClient.BuildUri(request)); _logger.Info("{0}: {1}", request.Method, _restClient.BuildUri(request));
@ -58,7 +58,14 @@ namespace NzbDrone.Integration.Test.Client
response.StatusCode.Should().Be(statusCode); response.StatusCode.Should().Be(statusCode);
return Json.Deserialize<T>(response.Content); return response.Content;
}
public T Execute<T>(IRestRequest request, HttpStatusCode statusCode) where T : class, new()
{
var content = Execute(request, statusCode);
return Json.Deserialize<T>(content);
} }
private static void AssertDisableCache(IList<Parameter> headers) private static void AssertDisableCache(IList<Parameter> headers)

@ -1,23 +1,47 @@
using Lidarr.Api.V1.Commands;
using RestSharp; using RestSharp;
using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Commands;
using FluentAssertions; using FluentAssertions;
using System.Threading; using System.Threading;
using NUnit.Framework; using NUnit.Framework;
using System.Linq; using System.Linq;
using System;
using Lidarr.Http.REST;
using Newtonsoft.Json;
namespace NzbDrone.Integration.Test.Client namespace NzbDrone.Integration.Test.Client
{ {
public class CommandClient : ClientBase<CommandResource> public class SimpleCommandResource : RestResource
{
public string Name { get; set; }
public string CommandName { get; set; }
public string Message { get; set; }
public CommandPriority Priority { get; set; }
public CommandStatus Status { get; set; }
public DateTime Queued { get; set; }
public DateTime? Started { get; set; }
public DateTime? Ended { get; set; }
public TimeSpan? Duration { get; set; }
public string Exception { get; set; }
public CommandTrigger Trigger { get; set; }
[JsonIgnore]
public Command Body { get; set; }
[JsonProperty("body")]
public Command BodyReadOnly { get { return Body; } }
}
public class CommandClient : ClientBase<SimpleCommandResource>
{ {
public CommandClient(IRestClient restClient, string apiKey) public CommandClient(IRestClient restClient, string apiKey)
: base(restClient, apiKey) : base(restClient, apiKey, "command")
{ {
} }
public CommandResource PostAndWait(CommandResource command) public SimpleCommandResource PostAndWait<T>(T command) where T : Command, new()
{ {
var result = Post(command); var request = BuildRequest();
request.AddBody(command);
var result = Post<SimpleCommandResource>(request);
result.Id.Should().NotBe(0); result.Id.Should().NotBe(0);
for (var i = 0; i < 50; i++) for (var i = 0; i < 50; i++)

@ -0,0 +1,24 @@
using System;
using RestSharp;
namespace NzbDrone.Integration.Test.Client
{
public class LogsClient : ClientBase
{
public LogsClient(IRestClient restClient, string apiKey)
: base(restClient, apiKey, "log/file")
{
}
public string[] GetLogFileLines(string filename)
{
var request = BuildRequest(filename);
var content = Execute(request, System.Net.HttpStatusCode.OK);
var lines = content.Split('\n');
lines = Array.ConvertAll(lines, s => s.TrimEnd('\r'));
Array.Resize(ref lines, lines.Length - 1);
return lines;
}
}
}

@ -1,4 +1,4 @@
using System.IO; using System;
using System.Linq; using System.Linq;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
@ -15,16 +15,20 @@ namespace NzbDrone.Integration.Test
config.LogLevel = "Trace"; config.LogLevel = "Trace";
HostConfig.Put(config); HostConfig.Put(config);
var logFile = Path.Combine(_runner.AppData, "logs", "Lidarr.trace.txt"); var resultGet = Artist.All();
var logLines = File.ReadAllLines(logFile);
var logFile = "Lidarr.trace.txt";
var logLines = Logs.GetLogFileLines(logFile);
var result = Artist.InvalidPost(new Lidarr.Api.V1.Artist.ArtistResource()); var result = Artist.InvalidPost(new Lidarr.Api.V1.Artist.ArtistResource());
logLines = File.ReadAllLines(logFile).Skip(logLines.Length).ToArray(); // Skip 2 and 1 to ignore the logs endpoint
logLines = Logs.GetLogFileLines(logFile).Skip(logLines.Length + 2).ToArray();
Array.Resize(ref logLines, logLines.Length - 1);
logLines.Should().Contain(v => v.Contains("|Trace|Http|Req")); logLines.Should().Contain(v => v.Contains("|Trace|Http|Req") && v.Contains("/api/v1/artist/"));
logLines.Should().Contain(v => v.Contains("|Trace|Http|Res")); logLines.Should().Contain(v => v.Contains("|Trace|Http|Res") && v.Contains("/api/v1/artist/: 400.BadRequest"));
logLines.Should().Contain(v => v.Contains("|Debug|Api|")); logLines.Should().Contain(v => v.Contains("|Debug|Api|") && v.Contains("/api/v1/artist/: 400.BadRequest"));
} }
} }
} }

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
@ -30,6 +31,8 @@ using NzbDrone.Integration.Test.Client;
using NzbDrone.SignalR; using NzbDrone.SignalR;
using NzbDrone.Test.Common.Categories; using NzbDrone.Test.Common.Categories;
using RestSharp; using RestSharp;
using NzbDrone.Core.MediaFiles.TrackImport.Manual;
using NzbDrone.Test.Common;
namespace NzbDrone.Integration.Test namespace NzbDrone.Integration.Test
{ {
@ -46,6 +49,7 @@ namespace NzbDrone.Integration.Test
public ClientBase<HistoryResource> History; public ClientBase<HistoryResource> History;
public ClientBase<HostConfigResource> HostConfig; public ClientBase<HostConfigResource> HostConfig;
public IndexerClient Indexers; public IndexerClient Indexers;
public LogsClient Logs;
public ClientBase<NamingConfigResource> NamingConfig; public ClientBase<NamingConfigResource> NamingConfig;
public NotificationClient Notifications; public NotificationClient Notifications;
public ClientBase<QualityProfileResource> Profiles; public ClientBase<QualityProfileResource> Profiles;
@ -108,6 +112,7 @@ namespace NzbDrone.Integration.Test
History = new ClientBase<HistoryResource>(RestClient, ApiKey); History = new ClientBase<HistoryResource>(RestClient, ApiKey);
HostConfig = new ClientBase<HostConfigResource>(RestClient, ApiKey, "config/host"); HostConfig = new ClientBase<HostConfigResource>(RestClient, ApiKey, "config/host");
Indexers = new IndexerClient(RestClient, ApiKey); Indexers = new IndexerClient(RestClient, ApiKey);
Logs = new LogsClient(RestClient, ApiKey);
NamingConfig = new ClientBase<NamingConfigResource>(RestClient, ApiKey, "config/naming"); NamingConfig = new ClientBase<NamingConfigResource>(RestClient, ApiKey, "config/naming");
Notifications = new NotificationClient(RestClient, ApiKey); Notifications = new NotificationClient(RestClient, ApiKey);
Profiles = new ClientBase<QualityProfileResource>(RestClient, ApiKey); Profiles = new ClientBase<QualityProfileResource>(RestClient, ApiKey);
@ -129,7 +134,10 @@ namespace NzbDrone.Integration.Test
[SetUp] [SetUp]
public void IntegrationSetUp() public void IntegrationSetUp()
{ {
TempDirectory = Path.Combine(TestContext.CurrentContext.TestDirectory, "_test_" + DateTime.UtcNow.Ticks); TempDirectory = Path.Combine(TestContext.CurrentContext.TestDirectory, "_test_" + TestBase.GetUID());
// Wait for things to get quiet, otherwise the previous test might influence the current one.
Commands.WaitAll();
} }
[TearDown] [TearDown]
@ -150,6 +158,17 @@ namespace NzbDrone.Integration.Test
_signalrConnection = null; _signalrConnection = null;
_signalRReceived = new List<SignalRMessage>(); _signalRReceived = new List<SignalRMessage>();
} }
if (Directory.Exists(TempDirectory))
{
try
{
Directory.Delete(TempDirectory, true);
}
catch
{
}
}
} }
public string GetTempDirectory(params string[] args) public string GetTempDirectory(params string[] args)
@ -227,19 +246,27 @@ namespace NzbDrone.Integration.Test
WaitForCompletion(() => Tracks.GetTracksInArtist(result.Id).Count > 0); WaitForCompletion(() => Tracks.GetTracksInArtist(result.Id).Count > 0);
} }
var changed = false;
if (result.RootFolderPath != ArtistRootFolder)
{
changed = true;
result.RootFolderPath = ArtistRootFolder;
result.Path = Path.Combine(ArtistRootFolder, result.ArtistName);
}
if (monitored.HasValue) if (monitored.HasValue)
{ {
var changed = false;
if (result.Monitored != monitored.Value) if (result.Monitored != monitored.Value)
{ {
result.Monitored = monitored.Value; result.Monitored = monitored.Value;
changed = true; changed = true;
} }
}
if (changed) if (changed)
{ {
Artist.Put(result); Artist.Put(result);
}
} }
return result; return result;
@ -256,35 +283,45 @@ namespace NzbDrone.Integration.Test
} }
} }
public TrackFileResource EnsureTrackFile(ArtistResource artist, int albumId, int track, Quality quality) public void EnsureTrackFile(ArtistResource artist, int albumId, int albumReleaseId, int trackId, Quality quality)
{ {
var result = Tracks.GetTracksInArtist(artist.Id).Single(v => v.AlbumId == albumId && v.AbsoluteTrackNumber == track); var result = Tracks.GetTracksInArtist(artist.Id).Single(v => v.Id == trackId);
if (result.TrackFile == null) if (result.TrackFile == null)
{ {
var path = Path.Combine(ArtistRootFolder, artist.ArtistName, string.Format("{0} - {1} - Track.mp3", track, artist.ArtistName)); var path = Path.Combine(ArtistRootFolder, artist.ArtistName, "Track.mp3");
Directory.CreateDirectory(Path.GetDirectoryName(path)); Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllText(path, "Fake Track"); File.WriteAllText(path, "Fake Track");
Commands.PostAndWait(new CommandResource { Name = "refreshartist", Body = new RefreshArtistCommand(artist.Id) }); Commands.PostAndWait(new ManualImportCommand {
Files = new List<ManualImportFile> {
new ManualImportFile {
Path = path,
ArtistId = artist.Id,
AlbumId = albumId,
AlbumReleaseId = albumReleaseId,
TrackIds = new List<int> { trackId },
Quality = new QualityModel(quality)
}
}
});
Commands.WaitAll(); Commands.WaitAll();
result = Tracks.GetTracksInArtist(artist.Id).Single(v => v.AlbumId == albumId && v.AbsoluteTrackNumber == track); var track = Tracks.GetTracksInArtist(artist.Id).Single(x => x.Id == trackId);
result.TrackFile.Should().NotBeNull(); track.TrackFileId.Should().NotBe(0);
} }
return result.TrackFile;
} }
public QualityProfileResource EnsureProfileCutoff(int profileId, Quality cutoff) public QualityProfileResource EnsureProfileCutoff(int profileId, string cutoff)
{ {
var profile = Profiles.Get(profileId); var profile = Profiles.Get(profileId);
var cutoffItem = profile.Items.First(x => x.Name == cutoff);
if (profile.Cutoff != cutoff.Id) if (profile.Cutoff != cutoffItem.Id)
{ {
profile.Cutoff = cutoff.Id; profile.Cutoff = cutoffItem.Id;
profile = Profiles.Put(profile); profile = Profiles.Put(profile);
} }

@ -74,6 +74,7 @@
<Compile Include="Client\CommandClient.cs" /> <Compile Include="Client\CommandClient.cs" />
<Compile Include="Client\ReleaseClient.cs" /> <Compile Include="Client\ReleaseClient.cs" />
<Compile Include="Client\ArtistClient.cs" /> <Compile Include="Client\ArtistClient.cs" />
<Compile Include="Client\LogsClient.cs" />
<Compile Include="ApiTests\CommandFixture.cs" /> <Compile Include="ApiTests\CommandFixture.cs" />
<Compile Include="CorsFixture.cs" /> <Compile Include="CorsFixture.cs" />
<Compile Include="ApiTests\TrackFixture.cs" /> <Compile Include="ApiTests\TrackFixture.cs" />
@ -190,4 +191,4 @@
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>

@ -8,7 +8,7 @@ using NzbDrone.Test.Common;
namespace NzbDrone.Mono.Test.EnvironmentInfo namespace NzbDrone.Mono.Test.EnvironmentInfo
{ {
[TestFixture] [TestFixture]
[Platform("Mono")] [Platform("Linux")]
public class ReleaseFileVersionAdapterFixture : TestBase<ReleaseFileVersionAdapter> public class ReleaseFileVersionAdapterFixture : TestBase<ReleaseFileVersionAdapter>
{ {
[SetUp] [SetUp]
@ -26,4 +26,4 @@ namespace NzbDrone.Mono.Test.EnvironmentInfo
info.Version.Should().NotBeNullOrWhiteSpace(); info.Version.Should().NotBeNullOrWhiteSpace();
} }
} }
} }

@ -15,7 +15,7 @@ namespace NzbDrone.Mono.Test.EnvironmentInfo.VersionAdapters
{ {
[Test] [Test]
[IntegrationTest] [IntegrationTest]
[Platform("Mono")] [Platform("Linux")]
public void should_get_version_info_from_actual_linux() public void should_get_version_info_from_actual_linux()
{ {
Mocker.SetConstant<IDiskProvider>(Mocker.Resolve<DiskProvider>()); Mocker.SetConstant<IDiskProvider>(Mocker.Resolve<DiskProvider>());
@ -79,4 +79,4 @@ namespace NzbDrone.Mono.Test.EnvironmentInfo.VersionAdapters
} }
} }
} }

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using NLog; using NLog;
using NLog.Targets; using NLog.Targets;
using NUnit.Framework; using NUnit.Framework;
@ -11,17 +12,27 @@ namespace NzbDrone.Test.Common
{ {
private static List<LogEventInfo> _logs = new List<LogEventInfo>(); private static List<LogEventInfo> _logs = new List<LogEventInfo>();
private static ManualResetEventSlim _waitEvent = new ManualResetEventSlim();
protected override void Write(LogEventInfo logEvent) protected override void Write(LogEventInfo logEvent)
{ {
if (logEvent.Level >= LogLevel.Warn) lock (_logs)
{ {
_logs.Add(logEvent); if (logEvent.Level >= LogLevel.Warn)
{
_logs.Add(logEvent);
_waitEvent.Set();
}
} }
} }
public static void Reset() public static void Reset()
{ {
_logs = new List<LogEventInfo>(); lock (_logs)
{
_logs.Clear();
_waitEvent.Reset();
}
} }
public static void AssertNoUnexpectedLogs() public static void AssertNoUnexpectedLogs()
@ -47,6 +58,29 @@ namespace NzbDrone.Test.Common
return errors; return errors;
} }
public static void WaitForErrors(int count, int msec)
{
while (true)
{
lock (_logs)
{
var levelLogs = _logs.Where(l => l.Level == LogLevel.Error).ToList();
if (levelLogs.Count >= count)
{
break;
}
_waitEvent.Reset();
}
if (!_waitEvent.Wait(msec))
break;
}
Expected(LogLevel.Error, count);
}
public static void ExpectedErrors(int count) public static void ExpectedErrors(int count)
{ {
Expected(LogLevel.Error, count); Expected(LogLevel.Error, count);
@ -74,50 +108,62 @@ namespace NzbDrone.Test.Common
public static void MarkInconclusive(Type exception) public static void MarkInconclusive(Type exception)
{ {
var inconclusiveLogs = _logs.Where(l => l.Exception != null && l.Exception.GetType() == exception).ToList(); lock (_logs)
if (inconclusiveLogs.Any())
{ {
inconclusiveLogs.ForEach(c => _logs.Remove(c)); var inconclusiveLogs = _logs.Where(l => l.Exception != null && l.Exception.GetType() == exception).ToList();
Assert.Inconclusive(GetLogsString(inconclusiveLogs));
if (inconclusiveLogs.Any())
{
inconclusiveLogs.ForEach(c => _logs.Remove(c));
Assert.Inconclusive(GetLogsString(inconclusiveLogs));
}
} }
} }
public static void MarkInconclusive(string text) public static void MarkInconclusive(string text)
{ {
var inconclusiveLogs = _logs.Where(l => l.FormattedMessage.ToLower().Contains(text.ToLower())).ToList(); lock (_logs)
if (inconclusiveLogs.Any())
{ {
inconclusiveLogs.ForEach(c => _logs.Remove(c)); var inconclusiveLogs = _logs.Where(l => l.FormattedMessage.ToLower().Contains(text.ToLower())).ToList();
Assert.Inconclusive(GetLogsString(inconclusiveLogs));
if (inconclusiveLogs.Any())
{
inconclusiveLogs.ForEach(c => _logs.Remove(c));
Assert.Inconclusive(GetLogsString(inconclusiveLogs));
}
} }
} }
private static void Expected(LogLevel level, int count) private static void Expected(LogLevel level, int count)
{ {
var levelLogs = _logs.Where(l => l.Level == level).ToList(); lock (_logs)
if (levelLogs.Count != count)
{ {
var levelLogs = _logs.Where(l => l.Level == level).ToList();
if (levelLogs.Count != count)
{
var message = string.Format("{0} {1}(s) were expected but {2} were logged.\n\r{3}", var message = string.Format("{0} {1}(s) were expected but {2} were logged.\n\r{3}",
count, level, levelLogs.Count, GetLogsString(levelLogs)); count, level, levelLogs.Count, GetLogsString(levelLogs));
message = "\n\r****************************************************************************************\n\r" message = "\n\r****************************************************************************************\n\r"
+ message + + message +
"\n\r****************************************************************************************"; "\n\r****************************************************************************************";
Assert.Fail(message); Assert.Fail(message);
} }
levelLogs.ForEach(c => _logs.Remove(c)); levelLogs.ForEach(c => _logs.Remove(c));
}
} }
private static void Ignore(LogLevel level) private static void Ignore(LogLevel level)
{ {
var levelLogs = _logs.Where(l => l.Level == level).ToList(); lock (_logs)
levelLogs.ForEach(c => _logs.Remove(c)); {
var levelLogs = _logs.Where(l => l.Level == level).ToList();
levelLogs.ForEach(c => _logs.Remove(c));
}
} }
} }
} }

@ -9,6 +9,7 @@ using NLog;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Processes; using NzbDrone.Common.Processes;
using NzbDrone.Core.Configuration;
using RestSharp; using RestSharp;
namespace NzbDrone.Test.Common namespace NzbDrone.Test.Common
@ -30,13 +31,16 @@ namespace NzbDrone.Test.Common
public void Start() public void Start()
{ {
AppData = Path.Combine(TestContext.CurrentContext.TestDirectory, "_intg_" + DateTime.Now.Ticks); AppData = Path.Combine(TestContext.CurrentContext.TestDirectory, "_intg_" + TestBase.GetUID());
Directory.CreateDirectory(AppData);
GenerateConfigFile();
var lidarrConsoleExe = OsInfo.IsWindows ? "Lidarr.Console.exe" : "Lidarr.exe"; var lidarrConsoleExe = OsInfo.IsWindows ? "Lidarr.Console.exe" : "Lidarr.exe";
if (BuildInfo.IsDebug) if (BuildInfo.IsDebug)
{ {
Start(Path.Combine(TestContext.CurrentContext.TestDirectory, "..\\..\\..\\..\\..\\_output\\Lidarr.Console.exe")); Start(Path.Combine(TestContext.CurrentContext.TestDirectory, "..", "..", "..", "..", "..", "_output", "Lidarr.Console.exe"));
} }
else else
{ {
@ -52,8 +56,6 @@ namespace NzbDrone.Test.Common
Assert.Fail("Process has exited"); Assert.Fail("Process has exited");
} }
SetApiKey();
var request = new RestRequest("system/status"); var request = new RestRequest("system/status");
request.AddHeader("Authorization", ApiKey); request.AddHeader("Authorization", ApiKey);
request.AddHeader("X-Api-Key", ApiKey); request.AddHeader("X-Api-Key", ApiKey);
@ -74,13 +76,22 @@ namespace NzbDrone.Test.Common
public void KillAll() public void KillAll()
{ {
if (_nzbDroneProcess != null) try
{
if (_nzbDroneProcess != null)
{
_processProvider.Kill(_nzbDroneProcess.Id);
}
_processProvider.KillAll(ProcessProvider.LIDARR_CONSOLE_PROCESS_NAME);
_processProvider.KillAll(ProcessProvider.LIDARR_PROCESS_NAME);
}
catch (InvalidOperationException)
{ {
_processProvider.Kill(_nzbDroneProcess.Id); // May happen if the process closes while being closed
} }
_processProvider.KillAll(ProcessProvider.LIDARR_CONSOLE_PROCESS_NAME); TestBase.DeleteTempFolder(AppData);
_processProvider.KillAll(ProcessProvider.LIDARR_PROCESS_NAME);
} }
private void Start(string outputNzbdroneConsoleExe) private void Start(string outputNzbdroneConsoleExe)
@ -100,33 +111,26 @@ namespace NzbDrone.Test.Common
} }
} }
private void SetApiKey() private void GenerateConfigFile()
{ {
var configFile = Path.Combine(AppData, "config.xml"); var configFile = Path.Combine(AppData, "config.xml");
var attempts = 0;
while (ApiKey == null && attempts < 50) // Generate and set the api key so we don't have to poll the config file
{ var apiKey = Guid.NewGuid().ToString().Replace("-", "");
try
{
if (File.Exists(configFile))
{
var apiKeyElement = XDocument.Load(configFile)
.XPathSelectElement("Config/ApiKey");
if (apiKeyElement != null)
{
ApiKey = apiKeyElement.Value;
}
}
}
catch (XmlException ex)
{
Console.WriteLine("Error getting API Key from XML file: " + ex.Message, ex);
}
attempts++; var xDoc = new XDocument(
Thread.Sleep(1000); new XDeclaration("1.0", "utf-8", "yes"),
} new XElement(ConfigFileProvider.CONFIG_ELEMENT_NAME,
new XElement(nameof(ConfigFileProvider.ApiKey), apiKey),
new XElement(nameof(ConfigFileProvider.AnalyticsEnabled), false)
)
);
var data = xDoc.ToString();
File.WriteAllText(configFile, data);
ApiKey = apiKey;
} }
} }
} }

@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using FluentAssertions; using FluentAssertions;
@ -43,8 +44,8 @@ namespace NzbDrone.Test.Common
public abstract class TestBase : LoggingTest public abstract class TestBase : LoggingTest
{ {
private static readonly Random _random = new Random(); private static readonly Random _random = new Random();
private static int _nextUid;
private AutoMoqer _mocker; private AutoMoqer _mocker;
protected AutoMoqer Mocker protected AutoMoqer Mocker
@ -84,7 +85,21 @@ namespace NzbDrone.Test.Common
} }
} }
protected string TempFolder { get; private set; } private string _tempFolder;
protected string TempFolder
{
get
{
if (_tempFolder == null)
{
_tempFolder = Path.Combine(TestContext.CurrentContext.TestDirectory, "_temp_" + GetUID());
Directory.CreateDirectory(_tempFolder);
}
return _tempFolder;
}
}
[SetUp] [SetUp]
public void TestBaseSetup() public void TestBaseSetup()
@ -93,9 +108,7 @@ namespace NzbDrone.Test.Common
LogManager.ReconfigExistingLoggers(); LogManager.ReconfigExistingLoggers();
TempFolder = Path.Combine(TestContext.CurrentContext.TestDirectory, "_temp_" + DateTime.Now.Ticks); _tempFolder = null;
Directory.CreateDirectory(TempFolder);
} }
[TearDown] [TearDown]
@ -103,9 +116,25 @@ namespace NzbDrone.Test.Common
{ {
_mocker = null; _mocker = null;
DeleteTempFolder(_tempFolder);
}
public static string GetUID()
{
return Process.GetCurrentProcess().Id + "_" + DateTime.Now.Ticks + "_" + Interlocked.Increment(ref _nextUid);
}
public static void DeleteTempFolder(string folder)
{
if (folder == null)
{
return;
}
try try
{ {
var tempFolder = new DirectoryInfo(TempFolder); var tempFolder = new DirectoryInfo(folder);
if (tempFolder.Exists) if (tempFolder.Exists)
{ {
foreach (var file in tempFolder.GetFiles("*", SearchOption.AllDirectories)) foreach (var file in tempFolder.GetFiles("*", SearchOption.AllDirectories))

@ -16,7 +16,7 @@ namespace NzbDrone.Update.Test
[Test] [Test]
public void should_start_service_if_app_type_was_serivce() public void should_start_service_if_app_type_was_serivce()
{ {
const string targetFolder = "c:\\Lidarr\\"; string targetFolder = "c:\\Lidarr\\".AsOsAgnostic();
Subject.Start(AppType.Service, targetFolder); Subject.Start(AppType.Service, targetFolder);
@ -26,13 +26,14 @@ namespace NzbDrone.Update.Test
[Test] [Test]
public void should_start_console_if_app_type_was_service_but_start_failed_because_of_permissions() public void should_start_console_if_app_type_was_service_but_start_failed_because_of_permissions()
{ {
const string targetFolder = "c:\\Lidarr\\"; string targetFolder = "c:\\Lidarr\\".AsOsAgnostic();
string targetProcess = "c:\\Lidarr\\Lidarr.Console.exe".AsOsAgnostic();
Mocker.GetMock<IServiceProvider>().Setup(c => c.Start(ServiceProvider.SERVICE_NAME)).Throws(new InvalidOperationException()); Mocker.GetMock<IServiceProvider>().Setup(c => c.Start(ServiceProvider.SERVICE_NAME)).Throws(new InvalidOperationException());
Subject.Start(AppType.Service, targetFolder); Subject.Start(AppType.Service, targetFolder);
Mocker.GetMock<IProcessProvider>().Verify(c => c.SpawnNewProcess("c:\\Lidarr\\Lidarr.Console.exe", "/" + StartupContext.NO_BROWSER, null, false), Times.Once()); Mocker.GetMock<IProcessProvider>().Verify(c => c.SpawnNewProcess(targetProcess, "/" + StartupContext.NO_BROWSER, null, false), Times.Once());
ExceptionVerification.ExpectedWarns(1); ExceptionVerification.ExpectedWarns(1);
} }

@ -29,29 +29,7 @@ NUNIT_PARAMS="--workers=1"
if [ "$PLATFORM" = "Mac" ]; then if [ "$PLATFORM" = "Mac" ]; then
#set up environment export DYLD_FALLBACK_LIBRARY_PATH="$TEST_DIR:/usr/local/lib:/lib:/usr/lib"
if [[ -x '/opt/local/bin/mono' ]]; then
# Macports and mono-supplied installer path
export PATH="/opt/local/bin:$PATH"
elif [[ -x '/usr/local/bin/mono' ]]; then
# Homebrew-supplied path to mono
export PATH="/usr/local/bin:$PATH"
fi
echo $TEST_DIR
export DYLD_FALLBACK_LIBRARY_PATH="$TEST_DIR"
if [ -e /Library/Frameworks/Mono.framework ]; then
MONO_FRAMEWORK_PATH=/Library/Frameworks/Mono.framework/Versions/Current
export PATH="$MONO_FRAMEWORK_PATH/bin:$PATH"
export DYLD_FALLBACK_LIBRARY_PATH="$DYLD_FALLBACK_LIBRARY_PATH:$MONO_FRAMEWORK_PATH/lib"
fi
if [[ -f '/opt/local/lib/libsqlite3.0.dylib' ]]; then
export DYLD_FALLBACK_LIBRARY_PATH="/opt/local/lib:$DYLD_FALLBACK_LIBRARY_PATH"
fi
export DYLD_FALLBACK_LIBRARY_PATH="$DYLD_FALLBACK_LIBRARY_PATH:$HOME/lib:/usr/local/lib:/lib:/usr/lib"
echo $LD_LIBRARY_PATH echo $LD_LIBRARY_PATH
echo $DYLD_LIBRARY_PATH echo $DYLD_LIBRARY_PATH
echo $DYLD_FALLBACK_LIBRARY_PATH echo $DYLD_FALLBACK_LIBRARY_PATH

Loading…
Cancel
Save