From ee7d47d0443f742a450708c590d5488166177d3e Mon Sep 17 00:00:00 2001 From: ta264 Date: Thu, 22 Aug 2019 21:15:25 +0100 Subject: [PATCH] Fixed: All the tests --- azure-pipelines.yml | 18 ++++ src/Lidarr.Api.V1/Logs/LogFileModuleBase.cs | 3 + .../DiskTests/DiskProviderFixtureBase.cs | 6 ++ .../ProcessProviderTests.cs | 5 +- .../ServiceProviderTests.cs | 17 +++- .../EnvironmentInfo/RuntimeInfo.cs | 2 +- .../Processes/ProcessProvider.cs | 2 + src/NzbDrone.Core.Test/Framework/DbTest.cs | 22 ++--- .../Instrumentation/DatabaseTargetFixture.cs | 12 +-- .../Commands/CommandExecutorFixture.cs | 37 +++---- .../SystemFolderValidatorFixture.cs | 9 +- .../Framework/MigrationController.cs | 3 +- .../ApiTests/CalendarFixture.cs | 22 ++--- .../ApiTests/CommandFixture.cs | 4 +- .../ApiTests/TrackFixture.cs | 21 +--- .../ApiTests/WantedFixture.cs | 18 ++-- .../Client/ClientBase.cs | 11 ++- .../Client/CommandClient.cs | 34 ++++++- .../Client/LogsClient.cs | 24 +++++ .../HttpLogFixture.cs | 18 ++-- .../IntegrationTestBase.cs | 71 ++++++++++---- .../NzbDrone.Integration.Test.csproj | 3 +- .../ReleaseFileVersionAdapterFixture.cs | 4 +- .../ReleaseFileVersionAdapterFixture.cs | 4 +- .../ExceptionVerification.cs | 98 ++++++++++++++----- src/NzbDrone.Test.Common/NzbDroneRunner.cs | 66 +++++++------ src/NzbDrone.Test.Common/TestBase.cs | 41 ++++++-- .../StartNzbDroneService.cs | 7 +- test.sh | 24 +---- 29 files changed, 397 insertions(+), 209 deletions(-) create mode 100644 src/NzbDrone.Integration.Test/Client/LogsClient.cs diff --git a/azure-pipelines.yml b/azure-pipelines.yml index fe7113712..d4fee4c7a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -281,6 +281,7 @@ stages: testResultsFormat: 'NUnit' testResultsFiles: '**/TestResult.xml' testRunTitle: '$(osName) Unit Tests' + failTaskOnFailedTests: true - stage: Integration_Automation displayName: Integration / Automation @@ -294,6 +295,10 @@ stages: osName: 'Linux' imageName: 'ubuntu-16.04' pattern: 'Lidarr.**.linux.tar.gz' + Mac: + osName: 'Mac' + imageName: 'macos-10.13' + pattern: 'Lidarr.**.osx.tar.gz' Windows: osName: 'Windows' 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 displayName: Install fpcalc 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 - task: DownloadPipelineArtifact@2 displayName: Download Test Artifact @@ -342,6 +355,7 @@ stages: testResultsFormat: 'NUnit' testResultsFiles: '**/TestResult.xml' testRunTitle: '$(osName) Integration Tests' + failTaskOnFailedTests: true displayName: Publish Test Results - job: Automation @@ -351,14 +365,17 @@ stages: osName: 'Linux' imageName: 'ubuntu-16.04' pattern: 'Lidarr.**.linux.tar.gz' + failBuild: true Mac: osName: 'Mac' imageName: 'macos-10.13' # Fails due to firefox not being installed on image pattern: 'Lidarr.**.osx.tar.gz' + failBuild: false Windows: osName: 'Windows' imageName: 'vs2017-win2016' pattern: 'Lidarr.**.windows.zip' + failBuild: true pool: vmImage: $(imageName) @@ -413,6 +430,7 @@ stages: testResultsFormat: 'NUnit' testResultsFiles: '**/TestResult.xml' testRunTitle: '$(osName) Automation Tests' + failTaskOnFailedTests: $(failBuild) displayName: Publish Test Results - stage: Analyze diff --git a/src/Lidarr.Api.V1/Logs/LogFileModuleBase.cs b/src/Lidarr.Api.V1/Logs/LogFileModuleBase.cs index 36d11b6a3..9ccd1807b 100644 --- a/src/Lidarr.Api.V1/Logs/LogFileModuleBase.cs +++ b/src/Lidarr.Api.V1/Logs/LogFileModuleBase.cs @@ -6,6 +6,7 @@ using Nancy.Responses; using NzbDrone.Common.Disk; using NzbDrone.Core.Configuration; using Lidarr.Http; +using NLog; namespace Lidarr.Api.V1.Logs { @@ -54,6 +55,8 @@ namespace Lidarr.Api.V1.Logs private Response GetLogFileResponse(string filename) { + LogManager.Flush(); + var filePath = GetLogFilePath(filename); if (!_diskProvider.FileExists(filePath)) diff --git a/src/NzbDrone.Common.Test/DiskTests/DiskProviderFixtureBase.cs b/src/NzbDrone.Common.Test/DiskTests/DiskProviderFixtureBase.cs index 1d750e6c6..df228193f 100644 --- a/src/NzbDrone.Common.Test/DiskTests/DiskProviderFixtureBase.cs +++ b/src/NzbDrone.Common.Test/DiskTests/DiskProviderFixtureBase.cs @@ -245,14 +245,20 @@ namespace NzbDrone.Common.Test.DiskTests } [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() { + WindowsOnly(); + Assert.Throws(() => DoHardLinkRename(FileShare.None)); } [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() { + WindowsOnly(); + Assert.Throws(() => DoHardLinkRename(FileShare.Read)); } } diff --git a/src/NzbDrone.Common.Test/ProcessProviderTests.cs b/src/NzbDrone.Common.Test/ProcessProviderTests.cs index c62185170..34526d9e1 100644 --- a/src/NzbDrone.Common.Test/ProcessProviderTests.cs +++ b/src/NzbDrone.Common.Test/ProcessProviderTests.cs @@ -64,6 +64,7 @@ namespace NzbDrone.Common.Test } [Test] + [Platform(Exclude="MacOsX")] public void Should_be_able_to_start_process() { var process = StartDummyProcess(); @@ -79,6 +80,7 @@ namespace NzbDrone.Common.Test [Test] + [Platform(Exclude="MacOsX")] public void kill_all_should_kill_all_process_with_name() { var dummy1 = StartDummyProcess(); @@ -92,7 +94,8 @@ namespace NzbDrone.Common.Test 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] diff --git a/src/NzbDrone.Common.Test/ServiceProviderTests.cs b/src/NzbDrone.Common.Test/ServiceProviderTests.cs index 4ebf15c93..23645a2d1 100644 --- a/src/NzbDrone.Common.Test/ServiceProviderTests.cs +++ b/src/NzbDrone.Common.Test/ServiceProviderTests.cs @@ -1,4 +1,5 @@ using System; +using System.Security.Principal; using System.ServiceProcess; using FluentAssertions; using NUnit.Framework; @@ -61,6 +62,10 @@ namespace NzbDrone.Common.Test [Test] 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.Install(TEMP_SERVICE_NAME); @@ -100,8 +105,13 @@ namespace NzbDrone.Common.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 .Should().NotBe(ServiceControllerStatus.Running); @@ -127,5 +137,10 @@ namespace NzbDrone.Common.Test ExceptionVerification.ExpectedWarns(1); } + private static bool IsAnAdministrator() + { + var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent()); + return principal.IsInRole(WindowsBuiltInRole.Administrator); + } } } diff --git a/src/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs b/src/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs index 0c6369a07..47cae6010 100644 --- a/src/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs +++ b/src/NzbDrone.Common/EnvironmentInfo/RuntimeInfo.cs @@ -142,7 +142,7 @@ namespace NzbDrone.Common.EnvironmentInfo } 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("_output")) return false; diff --git a/src/NzbDrone.Common/Processes/ProcessProvider.cs b/src/NzbDrone.Common/Processes/ProcessProvider.cs index 4f483b478..d69d90bf9 100644 --- a/src/NzbDrone.Common/Processes/ProcessProvider.cs +++ b/src/NzbDrone.Common/Processes/ProcessProvider.cs @@ -328,6 +328,8 @@ namespace NzbDrone.Common.Processes var monoProcesses = Process.GetProcessesByName("mono") .Union(Process.GetProcessesByName("mono-sgen")) + .Union(Process.GetProcessesByName("mono-sgen32")) + .Union(Process.GetProcessesByName("mono-sgen64")) .Where(process => process.Modules.Cast() .Any(module => diff --git a/src/NzbDrone.Core.Test/Framework/DbTest.cs b/src/NzbDrone.Core.Test/Framework/DbTest.cs index 7ae33e059..1eb68a55f 100644 --- a/src/NzbDrone.Core.Test/Framework/DbTest.cs +++ b/src/NzbDrone.Core.Test/Framework/DbTest.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Data.SQLite; using System.IO; using System.Linq; using FluentMigrator.Runner; @@ -115,21 +116,14 @@ namespace NzbDrone.Core.Test.Framework [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); - - foreach (var file in files) - { - try - { - File.Delete(file); - } - catch (Exception) - { - - } - } + DeleteTempFolder(TestFolderInfo.AppDataFolder); } } } diff --git a/src/NzbDrone.Core.Test/Instrumentation/DatabaseTargetFixture.cs b/src/NzbDrone.Core.Test/Instrumentation/DatabaseTargetFixture.cs index 41c4707ea..c575e3fdd 100644 --- a/src/NzbDrone.Core.Test/Instrumentation/DatabaseTargetFixture.cs +++ b/src/NzbDrone.Core.Test/Instrumentation/DatabaseTargetFixture.cs @@ -40,7 +40,7 @@ namespace NzbDrone.Core.Test.Instrumentation { _logger.Info(_uniqueMessage); - Thread.Sleep(600); + Thread.Sleep(1000); StoredModel.Message.Should().Be(_uniqueMessage); VerifyLog(StoredModel, LogLevel.Info); @@ -57,7 +57,7 @@ namespace NzbDrone.Core.Test.Instrumentation _logger.Info(message); - Thread.Sleep(600); + Thread.Sleep(1000); StoredModel.Message.Should().HaveLength(message.Length); StoredModel.Message.Should().Be(message); @@ -76,7 +76,7 @@ namespace NzbDrone.Core.Test.Instrumentation _logger.Info(Guid.NewGuid()); } - Thread.Sleep(600); + Thread.Sleep(1000); MapRepository.Instance.EnableTraceLogging = true; } @@ -88,7 +88,7 @@ namespace NzbDrone.Core.Test.Instrumentation _logger.Error(ex, _uniqueMessage); - Thread.Sleep(600); + Thread.Sleep(1000); VerifyLog(StoredModel, LogLevel.Error); StoredModel.Message.Should().Be(_uniqueMessage + ": " + ex.Message); @@ -106,7 +106,7 @@ namespace NzbDrone.Core.Test.Instrumentation _logger.Error(ex, _uniqueMessage); - Thread.Sleep(600); + Thread.Sleep(1000); StoredModel.Message.Should().Be(ex.Message); @@ -121,7 +121,7 @@ namespace NzbDrone.Core.Test.Instrumentation var epFile = new TrackFile(); _logger.Debug("File {0} no longer exists on disk. removing from database.", epFile.Path); - Thread.Sleep(600); + Thread.Sleep(1000); epFile.Path.Should().BeNull(); } diff --git a/src/NzbDrone.Core.Test/Messaging/Commands/CommandExecutorFixture.cs b/src/NzbDrone.Core.Test/Messaging/Commands/CommandExecutorFixture.cs index 8b57f70c1..733e00240 100644 --- a/src/NzbDrone.Core.Test/Messaging/Commands/CommandExecutorFixture.cs +++ b/src/NzbDrone.Core.Test/Messaging/Commands/CommandExecutorFixture.cs @@ -18,7 +18,6 @@ namespace NzbDrone.Core.Test.Messaging.Commands private CommandQueue _commandQueue; private Mock> _executorA; private Mock> _executorB; - private bool _commandExecuted = false; [SetUp] public void Setup() @@ -53,26 +52,34 @@ namespace NzbDrone.Core.Test.Messaging.Commands .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() .Setup(s => s.Complete(It.Is(c => c == commandModel), It.IsAny())) - .Callback(() => _commandExecuted = true); + .Callback(() => waitEventComplete.Set()); Mocker.GetMock() .Setup(s => s.Fail(It.Is(c => c == commandModel), It.IsAny(), It.IsAny())) - .Callback(() => _commandExecuted = true); + .Callback(() => waitEventComplete.Set()); + + Mocker.GetMock() + .Setup(s => s.PublishEvent(It.IsAny())) + .Callback(() => waitEventPublish.Set()); _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] @@ -138,9 +145,7 @@ namespace NzbDrone.Core.Test.Messaging.Commands VerifyEventPublished(); - Thread.Sleep(10); - - ExceptionVerification.ExpectedErrors(1); + ExceptionVerification.WaitForErrors(1, 500); } [Test] @@ -175,18 +180,17 @@ namespace NzbDrone.Core.Test.Messaging.Commands QueueAndWaitForExecution(commandModel); Mocker.GetMock() - .Setup(s => s.Complete(It.Is(c => c == commandModel), commandA.CompletionMessage)) - .Callback(() => _commandExecuted = true); + .Verify(s => s.Complete(It.Is(c => c == commandModel), commandA.CompletionMessage), Times.Once()); } [Test] public void should_use_last_progress_message_if_completion_message_is_null() { GivenCommandQueue(); - var commandA = new CommandA(); + var commandB = new CommandB(); var commandModel = new CommandModel { - Body = commandA, + Body = commandB, Message = "Do work" }; @@ -195,8 +199,7 @@ namespace NzbDrone.Core.Test.Messaging.Commands QueueAndWaitForExecution(commandModel); Mocker.GetMock() - .Setup(s => s.Complete(It.Is(c => c == commandModel), commandModel.Message)) - .Callback(() => _commandExecuted = true); + .Verify(s => s.Complete(It.Is(c => c == commandModel), commandModel.Message), Times.Once()); } } diff --git a/src/NzbDrone.Core.Test/ValidationTests/SystemFolderValidatorFixture.cs b/src/NzbDrone.Core.Test/ValidationTests/SystemFolderValidatorFixture.cs index 89bd34078..f6e4e4fb1 100644 --- a/src/NzbDrone.Core.Test/ValidationTests/SystemFolderValidatorFixture.cs +++ b/src/NzbDrone.Core.Test/ValidationTests/SystemFolderValidatorFixture.cs @@ -7,6 +7,7 @@ using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Music; using NzbDrone.Core.Validation.Paths; using NzbDrone.Test.Common; +using NzbDrone.Common.EnvironmentInfo; namespace NzbDrone.Core.Test.ValidationTests { @@ -52,8 +53,9 @@ namespace NzbDrone.Core.Test.ValidationTests { MonoOnly(); + var bin = OsInfo.IsOsx ? "/System" : "/bin"; var artist = Builder.CreateNew() - .With(s => s.Path = "/bin") + .With(s => s.Path = bin) .Build(); _validator.Validate(artist).IsValid.Should().BeFalse(); @@ -64,9 +66,10 @@ namespace NzbDrone.Core.Test.ValidationTests { MonoOnly(); + var bin = OsInfo.IsOsx ? "/System" : "/bin"; var artist = Builder.CreateNew() - .With(s => s.Path = "/bin/test") - .Build(); + .With(s => s.Path = Path.Combine(bin, "test")) + .Build(); _validator.Validate(artist).IsValid.Should().BeFalse(); } diff --git a/src/NzbDrone.Core/Datastore/Migration/Framework/MigrationController.cs b/src/NzbDrone.Core/Datastore/Migration/Framework/MigrationController.cs index 793725e9f..69d33e7e6 100644 --- a/src/NzbDrone.Core/Datastore/Migration/Framework/MigrationController.cs +++ b/src/NzbDrone.Core/Datastore/Migration/Framework/MigrationController.cs @@ -50,6 +50,8 @@ namespace NzbDrone.Core.Datastore.Migration.Framework { runner.MigrateUp(true); } + + processor.Dispose(); } catch (SQLiteException) { @@ -57,7 +59,6 @@ namespace NzbDrone.Core.Datastore.Migration.Framework SQLiteConnection.ClearAllPools(); throw; } - sw.Stop(); diff --git a/src/NzbDrone.Integration.Test/ApiTests/CalendarFixture.cs b/src/NzbDrone.Integration.Test/ApiTests/CalendarFixture.cs index ea9249636..c386aacf2 100644 --- a/src/NzbDrone.Integration.Test/ApiTests/CalendarFixture.cs +++ b/src/NzbDrone.Integration.Test/ApiTests/CalendarFixture.cs @@ -23,27 +23,27 @@ namespace NzbDrone.Integration.Test.ApiTests [Test] 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(); - request.AddParameter("start", new DateTime(2015, 10, 1).ToString("s") + "Z"); - request.AddParameter("end", new DateTime(2015, 10, 3).ToString("s") + "Z"); + request.AddParameter("start", new DateTime(2015, 11, 19).ToString("s") + "Z"); + request.AddParameter("end", new DateTime(2015, 11, 21).ToString("s") + "Z"); var items = Calendar.Get>(request); items = items.Where(v => v.ArtistId == artist.Id).ToList(); items.Should().HaveCount(1); - items.First().Title.Should().Be("The Troll Farmer"); + items.First().Title.Should().Be("25"); } [Test] 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(); - request.AddParameter("start", new DateTime(2015, 10, 1).ToString("s") + "Z"); - request.AddParameter("end", new DateTime(2015, 10, 3).ToString("s") + "Z"); + request.AddParameter("start", new DateTime(2015, 11, 19).ToString("s") + "Z"); + request.AddParameter("end", new DateTime(2015, 11, 21).ToString("s") + "Z"); request.AddParameter("unmonitored", "false"); var items = Calendar.Get>(request); @@ -55,18 +55,18 @@ namespace NzbDrone.Integration.Test.ApiTests [Test] 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(); - request.AddParameter("start", new DateTime(2015, 10, 1).ToString("s") + "Z"); - request.AddParameter("end", new DateTime(2015, 10, 3).ToString("s") + "Z"); + request.AddParameter("start", new DateTime(2015, 11, 19).ToString("s") + "Z"); + request.AddParameter("end", new DateTime(2015, 11, 21).ToString("s") + "Z"); request.AddParameter("unmonitored", "true"); var items = Calendar.Get>(request); items = items.Where(v => v.ArtistId == artist.Id).ToList(); items.Should().HaveCount(1); - items.First().Title.Should().Be("The Troll Farmer"); + items.First().Title.Should().Be("25"); } } } diff --git a/src/NzbDrone.Integration.Test/ApiTests/CommandFixture.cs b/src/NzbDrone.Integration.Test/ApiTests/CommandFixture.cs index d70ed4cd4..4f40de1ae 100644 --- a/src/NzbDrone.Integration.Test/ApiTests/CommandFixture.cs +++ b/src/NzbDrone.Integration.Test/ApiTests/CommandFixture.cs @@ -1,6 +1,6 @@ using FluentAssertions; using NUnit.Framework; -using Lidarr.Api.V1.Commands; +using NzbDrone.Integration.Test.Client; namespace NzbDrone.Integration.Test.ApiTests { @@ -11,7 +11,7 @@ namespace NzbDrone.Integration.Test.ApiTests [Test] 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); } diff --git a/src/NzbDrone.Integration.Test/ApiTests/TrackFixture.cs b/src/NzbDrone.Integration.Test/ApiTests/TrackFixture.cs index 78907d481..e398fb801 100644 --- a/src/NzbDrone.Integration.Test/ApiTests/TrackFixture.cs +++ b/src/NzbDrone.Integration.Test/ApiTests/TrackFixture.cs @@ -3,7 +3,6 @@ using FluentAssertions; using NUnit.Framework; using Lidarr.Api.V1.Artist; using System.Linq; -using NzbDrone.Test.Common; namespace NzbDrone.Integration.Test.ApiTests { @@ -15,30 +14,16 @@ namespace NzbDrone.Integration.Test.ApiTests [SetUp] public void Setup() { - _artist = GivenArtistWithTracks(); + _artist = EnsureArtist("8ac6cc32-8ddf-43b1-9ac4-4b04f9053176", "Alien Ant Farm"); } - private ArtistResource GivenArtistWithTracks() - { - 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] + [Test, Order(0)] public void should_be_able_to_get_all_tracks_in_artist() { Tracks.GetTracksInArtist(_artist.Id).Count.Should().BeGreaterThan(0); } - [Test] + [Test, Order(1)] public void should_be_able_to_get_a_single_track() { var tracks = Tracks.GetTracksInArtist(_artist.Id); diff --git a/src/NzbDrone.Integration.Test/ApiTests/WantedFixture.cs b/src/NzbDrone.Integration.Test/ApiTests/WantedFixture.cs index ae699e66b..a3d54d564 100644 --- a/src/NzbDrone.Integration.Test/ApiTests/WantedFixture.cs +++ b/src/NzbDrone.Integration.Test/ApiTests/WantedFixture.cs @@ -36,15 +36,15 @@ namespace NzbDrone.Integration.Test.ApiTests var result = WantedMissing.GetPaged(0, 15, "releaseDate", "desc"); 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)] 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); - EnsureTrackFile(artist, 1, 1, Quality.MP3_192); + EnsureTrackFile(artist, 1, 1, 1, Quality.MP3_192); var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc"); @@ -64,9 +64,9 @@ namespace NzbDrone.Integration.Test.ApiTests [Test, Order(1)] 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); - EnsureTrackFile(artist, 1, 1, Quality.MP3_192); + EnsureTrackFile(artist, 1, 1, 1, Quality.MP3_192); var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc"); @@ -76,9 +76,9 @@ namespace NzbDrone.Integration.Test.ApiTests [Test, Order(1)] 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); - EnsureTrackFile(artist, 1, 1, Quality.MP3_192); + EnsureTrackFile(artist, 1, 1, 1, Quality.MP3_192); var result = WantedCutoffUnmet.GetPaged(0, 15, "releaseDate", "desc"); @@ -99,9 +99,9 @@ namespace NzbDrone.Integration.Test.ApiTests [Test, Order(2)] 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); - 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"); diff --git a/src/NzbDrone.Integration.Test/Client/ClientBase.cs b/src/NzbDrone.Integration.Test/Client/ClientBase.cs index de26b5a81..41963cbc8 100644 --- a/src/NzbDrone.Integration.Test/Client/ClientBase.cs +++ b/src/NzbDrone.Integration.Test/Client/ClientBase.cs @@ -40,7 +40,7 @@ namespace NzbDrone.Integration.Test.Client return request; } - public T Execute(IRestRequest request, HttpStatusCode statusCode) where T : class, new() + public string Execute(IRestRequest request, HttpStatusCode statusCode) { _logger.Info("{0}: {1}", request.Method, _restClient.BuildUri(request)); @@ -58,7 +58,14 @@ namespace NzbDrone.Integration.Test.Client response.StatusCode.Should().Be(statusCode); - return Json.Deserialize(response.Content); + return response.Content; + } + + public T Execute(IRestRequest request, HttpStatusCode statusCode) where T : class, new() + { + var content = Execute(request, statusCode); + + return Json.Deserialize(content); } private static void AssertDisableCache(IList headers) diff --git a/src/NzbDrone.Integration.Test/Client/CommandClient.cs b/src/NzbDrone.Integration.Test/Client/CommandClient.cs index c4cc528ba..940a28ed6 100644 --- a/src/NzbDrone.Integration.Test/Client/CommandClient.cs +++ b/src/NzbDrone.Integration.Test/Client/CommandClient.cs @@ -1,23 +1,47 @@ -using Lidarr.Api.V1.Commands; using RestSharp; using NzbDrone.Core.Messaging.Commands; using FluentAssertions; using System.Threading; using NUnit.Framework; using System.Linq; +using System; +using Lidarr.Http.REST; +using Newtonsoft.Json; namespace NzbDrone.Integration.Test.Client { - public class CommandClient : ClientBase + 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 { public CommandClient(IRestClient restClient, string apiKey) - : base(restClient, apiKey) + : base(restClient, apiKey, "command") { } - public CommandResource PostAndWait(CommandResource command) + public SimpleCommandResource PostAndWait(T command) where T : Command, new() { - var result = Post(command); + var request = BuildRequest(); + request.AddBody(command); + var result = Post(request); result.Id.Should().NotBe(0); for (var i = 0; i < 50; i++) diff --git a/src/NzbDrone.Integration.Test/Client/LogsClient.cs b/src/NzbDrone.Integration.Test/Client/LogsClient.cs new file mode 100644 index 000000000..b64ec2971 --- /dev/null +++ b/src/NzbDrone.Integration.Test/Client/LogsClient.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/src/NzbDrone.Integration.Test/HttpLogFixture.cs b/src/NzbDrone.Integration.Test/HttpLogFixture.cs index 29274c802..15e9fa949 100644 --- a/src/NzbDrone.Integration.Test/HttpLogFixture.cs +++ b/src/NzbDrone.Integration.Test/HttpLogFixture.cs @@ -1,4 +1,4 @@ -using System.IO; +using System; using System.Linq; using FluentAssertions; using NUnit.Framework; @@ -15,16 +15,20 @@ namespace NzbDrone.Integration.Test config.LogLevel = "Trace"; HostConfig.Put(config); - var logFile = Path.Combine(_runner.AppData, "logs", "Lidarr.trace.txt"); - var logLines = File.ReadAllLines(logFile); + var resultGet = Artist.All(); + + var logFile = "Lidarr.trace.txt"; + var logLines = Logs.GetLogFileLines(logFile); 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|Res")); - logLines.Should().Contain(v => v.Contains("|Debug|Api|")); + logLines.Should().Contain(v => v.Contains("|Trace|Http|Req") && v.Contains("/api/v1/artist/")); + logLines.Should().Contain(v => v.Contains("|Trace|Http|Res") && v.Contains("/api/v1/artist/: 400.BadRequest")); + logLines.Should().Contain(v => v.Contains("|Debug|Api|") && v.Contains("/api/v1/artist/: 400.BadRequest")); } } } diff --git a/src/NzbDrone.Integration.Test/IntegrationTestBase.cs b/src/NzbDrone.Integration.Test/IntegrationTestBase.cs index 66a663e5f..8d10c2b70 100644 --- a/src/NzbDrone.Integration.Test/IntegrationTestBase.cs +++ b/src/NzbDrone.Integration.Test/IntegrationTestBase.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; @@ -30,6 +31,8 @@ using NzbDrone.Integration.Test.Client; using NzbDrone.SignalR; using NzbDrone.Test.Common.Categories; using RestSharp; +using NzbDrone.Core.MediaFiles.TrackImport.Manual; +using NzbDrone.Test.Common; namespace NzbDrone.Integration.Test { @@ -46,6 +49,7 @@ namespace NzbDrone.Integration.Test public ClientBase History; public ClientBase HostConfig; public IndexerClient Indexers; + public LogsClient Logs; public ClientBase NamingConfig; public NotificationClient Notifications; public ClientBase Profiles; @@ -108,6 +112,7 @@ namespace NzbDrone.Integration.Test History = new ClientBase(RestClient, ApiKey); HostConfig = new ClientBase(RestClient, ApiKey, "config/host"); Indexers = new IndexerClient(RestClient, ApiKey); + Logs = new LogsClient(RestClient, ApiKey); NamingConfig = new ClientBase(RestClient, ApiKey, "config/naming"); Notifications = new NotificationClient(RestClient, ApiKey); Profiles = new ClientBase(RestClient, ApiKey); @@ -129,7 +134,10 @@ namespace NzbDrone.Integration.Test [SetUp] 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] @@ -150,6 +158,17 @@ namespace NzbDrone.Integration.Test _signalrConnection = null; _signalRReceived = new List(); } + + if (Directory.Exists(TempDirectory)) + { + try + { + Directory.Delete(TempDirectory, true); + } + catch + { + } + } } public string GetTempDirectory(params string[] args) @@ -227,19 +246,27 @@ namespace NzbDrone.Integration.Test 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) { - var changed = false; if (result.Monitored != monitored.Value) { result.Monitored = monitored.Value; changed = true; } + } - if (changed) - { - Artist.Put(result); - } + if (changed) + { + Artist.Put(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) { - 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)); File.WriteAllText(path, "Fake Track"); - Commands.PostAndWait(new CommandResource { Name = "refreshartist", Body = new RefreshArtistCommand(artist.Id) }); + Commands.PostAndWait(new ManualImportCommand { + Files = new List { + new ManualImportFile { + Path = path, + ArtistId = artist.Id, + AlbumId = albumId, + AlbumReleaseId = albumReleaseId, + TrackIds = new List { trackId }, + Quality = new QualityModel(quality) + } + } + }); 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 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); } diff --git a/src/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj b/src/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj index 77ce247c5..e195b363b 100644 --- a/src/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj +++ b/src/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj @@ -74,6 +74,7 @@ + @@ -190,4 +191,4 @@ --> - \ No newline at end of file + diff --git a/src/NzbDrone.Mono.Test/EnvironmentInfo/ReleaseFileVersionAdapterFixture.cs b/src/NzbDrone.Mono.Test/EnvironmentInfo/ReleaseFileVersionAdapterFixture.cs index c2772e215..126b8ab86 100644 --- a/src/NzbDrone.Mono.Test/EnvironmentInfo/ReleaseFileVersionAdapterFixture.cs +++ b/src/NzbDrone.Mono.Test/EnvironmentInfo/ReleaseFileVersionAdapterFixture.cs @@ -8,7 +8,7 @@ using NzbDrone.Test.Common; namespace NzbDrone.Mono.Test.EnvironmentInfo { [TestFixture] - [Platform("Mono")] + [Platform("Linux")] public class ReleaseFileVersionAdapterFixture : TestBase { [SetUp] @@ -26,4 +26,4 @@ namespace NzbDrone.Mono.Test.EnvironmentInfo info.Version.Should().NotBeNullOrWhiteSpace(); } } -} \ No newline at end of file +} diff --git a/src/NzbDrone.Mono.Test/EnvironmentInfo/VersionAdapters/ReleaseFileVersionAdapterFixture.cs b/src/NzbDrone.Mono.Test/EnvironmentInfo/VersionAdapters/ReleaseFileVersionAdapterFixture.cs index 2979b1544..f3f9d28a5 100644 --- a/src/NzbDrone.Mono.Test/EnvironmentInfo/VersionAdapters/ReleaseFileVersionAdapterFixture.cs +++ b/src/NzbDrone.Mono.Test/EnvironmentInfo/VersionAdapters/ReleaseFileVersionAdapterFixture.cs @@ -15,7 +15,7 @@ namespace NzbDrone.Mono.Test.EnvironmentInfo.VersionAdapters { [Test] [IntegrationTest] - [Platform("Mono")] + [Platform("Linux")] public void should_get_version_info_from_actual_linux() { Mocker.SetConstant(Mocker.Resolve()); @@ -79,4 +79,4 @@ namespace NzbDrone.Mono.Test.EnvironmentInfo.VersionAdapters } } -} \ No newline at end of file +} diff --git a/src/NzbDrone.Test.Common/ExceptionVerification.cs b/src/NzbDrone.Test.Common/ExceptionVerification.cs index b86220f7c..a60d1297b 100644 --- a/src/NzbDrone.Test.Common/ExceptionVerification.cs +++ b/src/NzbDrone.Test.Common/ExceptionVerification.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using NLog; using NLog.Targets; using NUnit.Framework; @@ -11,17 +12,27 @@ namespace NzbDrone.Test.Common { private static List _logs = new List(); + private static ManualResetEventSlim _waitEvent = new ManualResetEventSlim(); + 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() { - _logs = new List(); + lock (_logs) + { + _logs.Clear(); + _waitEvent.Reset(); + } } public static void AssertNoUnexpectedLogs() @@ -47,6 +58,29 @@ namespace NzbDrone.Test.Common 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) { Expected(LogLevel.Error, count); @@ -74,50 +108,62 @@ namespace NzbDrone.Test.Common public static void MarkInconclusive(Type exception) { - var inconclusiveLogs = _logs.Where(l => l.Exception != null && l.Exception.GetType() == exception).ToList(); - - if (inconclusiveLogs.Any()) + lock (_logs) { - inconclusiveLogs.ForEach(c => _logs.Remove(c)); - Assert.Inconclusive(GetLogsString(inconclusiveLogs)); + var inconclusiveLogs = _logs.Where(l => l.Exception != null && l.Exception.GetType() == exception).ToList(); + + if (inconclusiveLogs.Any()) + { + inconclusiveLogs.ForEach(c => _logs.Remove(c)); + Assert.Inconclusive(GetLogsString(inconclusiveLogs)); + } } } public static void MarkInconclusive(string text) { - var inconclusiveLogs = _logs.Where(l => l.FormattedMessage.ToLower().Contains(text.ToLower())).ToList(); - - if (inconclusiveLogs.Any()) + lock (_logs) { - inconclusiveLogs.ForEach(c => _logs.Remove(c)); - Assert.Inconclusive(GetLogsString(inconclusiveLogs)); + var inconclusiveLogs = _logs.Where(l => l.FormattedMessage.ToLower().Contains(text.ToLower())).ToList(); + + if (inconclusiveLogs.Any()) + { + inconclusiveLogs.ForEach(c => _logs.Remove(c)); + Assert.Inconclusive(GetLogsString(inconclusiveLogs)); + } } } private static void Expected(LogLevel level, int count) { - var levelLogs = _logs.Where(l => l.Level == level).ToList(); - - if (levelLogs.Count != count) + lock (_logs) { + 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}", - count, level, levelLogs.Count, GetLogsString(levelLogs)); + var message = string.Format("{0} {1}(s) were expected but {2} were logged.\n\r{3}", + count, level, levelLogs.Count, GetLogsString(levelLogs)); - message = "\n\r****************************************************************************************\n\r" - + message + - "\n\r****************************************************************************************"; + message = "\n\r****************************************************************************************\n\r" + + message + + "\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) { - var levelLogs = _logs.Where(l => l.Level == level).ToList(); - levelLogs.ForEach(c => _logs.Remove(c)); + lock (_logs) + { + var levelLogs = _logs.Where(l => l.Level == level).ToList(); + levelLogs.ForEach(c => _logs.Remove(c)); + } } } } \ No newline at end of file diff --git a/src/NzbDrone.Test.Common/NzbDroneRunner.cs b/src/NzbDrone.Test.Common/NzbDroneRunner.cs index 229683abd..2bc76a070 100644 --- a/src/NzbDrone.Test.Common/NzbDroneRunner.cs +++ b/src/NzbDrone.Test.Common/NzbDroneRunner.cs @@ -9,6 +9,7 @@ using NLog; using NUnit.Framework; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Processes; +using NzbDrone.Core.Configuration; using RestSharp; namespace NzbDrone.Test.Common @@ -30,13 +31,16 @@ namespace NzbDrone.Test.Common 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"; if (BuildInfo.IsDebug) { - Start(Path.Combine(TestContext.CurrentContext.TestDirectory, "..\\..\\..\\..\\..\\_output\\Lidarr.Console.exe")); + Start(Path.Combine(TestContext.CurrentContext.TestDirectory, "..", "..", "..", "..", "..", "_output", "Lidarr.Console.exe")); } else { @@ -52,8 +56,6 @@ namespace NzbDrone.Test.Common Assert.Fail("Process has exited"); } - SetApiKey(); - var request = new RestRequest("system/status"); request.AddHeader("Authorization", ApiKey); request.AddHeader("X-Api-Key", ApiKey); @@ -74,13 +76,22 @@ namespace NzbDrone.Test.Common 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); - _processProvider.KillAll(ProcessProvider.LIDARR_PROCESS_NAME); + TestBase.DeleteTempFolder(AppData); } 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 attempts = 0; - while (ApiKey == null && attempts < 50) - { - 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); - } + // Generate and set the api key so we don't have to poll the config file + var apiKey = Guid.NewGuid().ToString().Replace("-", ""); - attempts++; - Thread.Sleep(1000); - } + var xDoc = new XDocument( + 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; } } } diff --git a/src/NzbDrone.Test.Common/TestBase.cs b/src/NzbDrone.Test.Common/TestBase.cs index eb9436991..9e21ab010 100644 --- a/src/NzbDrone.Test.Common/TestBase.cs +++ b/src/NzbDrone.Test.Common/TestBase.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.IO; using System.Threading; using FluentAssertions; @@ -43,8 +44,8 @@ namespace NzbDrone.Test.Common public abstract class TestBase : LoggingTest { - private static readonly Random _random = new Random(); + private static int _nextUid; private 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] public void TestBaseSetup() @@ -93,9 +108,7 @@ namespace NzbDrone.Test.Common LogManager.ReconfigExistingLoggers(); - TempFolder = Path.Combine(TestContext.CurrentContext.TestDirectory, "_temp_" + DateTime.Now.Ticks); - - Directory.CreateDirectory(TempFolder); + _tempFolder = null; } [TearDown] @@ -103,9 +116,25 @@ namespace NzbDrone.Test.Common { _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 { - var tempFolder = new DirectoryInfo(TempFolder); + var tempFolder = new DirectoryInfo(folder); if (tempFolder.Exists) { foreach (var file in tempFolder.GetFiles("*", SearchOption.AllDirectories)) diff --git a/src/NzbDrone.Update.Test/StartNzbDroneService.cs b/src/NzbDrone.Update.Test/StartNzbDroneService.cs index 087cecb16..439cac23a 100644 --- a/src/NzbDrone.Update.Test/StartNzbDroneService.cs +++ b/src/NzbDrone.Update.Test/StartNzbDroneService.cs @@ -16,7 +16,7 @@ namespace NzbDrone.Update.Test [Test] 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); @@ -26,13 +26,14 @@ namespace NzbDrone.Update.Test [Test] 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().Setup(c => c.Start(ServiceProvider.SERVICE_NAME)).Throws(new InvalidOperationException()); Subject.Start(AppType.Service, targetFolder); - Mocker.GetMock().Verify(c => c.SpawnNewProcess("c:\\Lidarr\\Lidarr.Console.exe", "/" + StartupContext.NO_BROWSER, null, false), Times.Once()); + Mocker.GetMock().Verify(c => c.SpawnNewProcess(targetProcess, "/" + StartupContext.NO_BROWSER, null, false), Times.Once()); ExceptionVerification.ExpectedWarns(1); } diff --git a/test.sh b/test.sh index 9cb45d057..28ecfb08c 100755 --- a/test.sh +++ b/test.sh @@ -29,29 +29,7 @@ NUNIT_PARAMS="--workers=1" if [ "$PLATFORM" = "Mac" ]; then - #set up environment - 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" + export DYLD_FALLBACK_LIBRARY_PATH="$TEST_DIR:/usr/local/lib:/lib:/usr/lib" echo $LD_LIBRARY_PATH echo $DYLD_LIBRARY_PATH echo $DYLD_FALLBACK_LIBRARY_PATH