From 46d8e5830a1c5fe7a54fe16738c770f29c9acea3 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sat, 18 Aug 2018 10:54:13 -0700 Subject: [PATCH] Fixed: Concurrent manual imports silently failing --- .../CommandEqualityComparerFixture.cs | 52 ++++++++++++++++++- .../EpisodeImport/Manual/ManualImportFile.cs | 36 ++++++++++++- .../Commands/CommandEqualityComparer.cs | 9 ++-- 3 files changed, 91 insertions(+), 6 deletions(-) diff --git a/src/NzbDrone.Core.Test/Messaging/Commands/CommandEqualityComparerFixture.cs b/src/NzbDrone.Core.Test/Messaging/Commands/CommandEqualityComparerFixture.cs index 8154c7a24..364e62a48 100644 --- a/src/NzbDrone.Core.Test/Messaging/Commands/CommandEqualityComparerFixture.cs +++ b/src/NzbDrone.Core.Test/Messaging/Commands/CommandEqualityComparerFixture.cs @@ -1,17 +1,29 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Indexers; using NzbDrone.Core.IndexerSearch; using NzbDrone.Core.MediaFiles.Commands; +using NzbDrone.Core.MediaFiles.EpisodeImport.Manual; using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Update.Commands; +using NzbDrone.Test.Common; namespace NzbDrone.Core.Test.Messaging.Commands { [TestFixture] public class CommandEqualityComparerFixture { + private string GivenRandomPath() + { + return Path.Combine(@"C:\Tesst\", Guid.NewGuid().ToString()).AsOsAgnostic(); + } + [Test] public void should_return_true_when_there_are_no_properties() { @@ -107,5 +119,43 @@ namespace NzbDrone.Core.Test.Messaging.Commands CommandEqualityComparer.Instance.Equals(command1, command2).Should().BeFalse(); } + + [Test] + public void should_return_true_when_commands_list_for_non_primitive_type_match() + { + var files1 = Builder.CreateListOfSize(2) + .All() + .With(m => m.Path = GivenRandomPath()) + .Build() + .ToList(); + + var files2 = files1.JsonClone(); + + var command1 = new ManualImportCommand { Files = files1 }; + var command2 = new ManualImportCommand { Files = files2 }; + + CommandEqualityComparer.Instance.Equals(command1, command2).Should().BeTrue(); + } + + [Test] + public void should_return_false_when_commands_list_for_non_primitive_type_dont_match() + { + var files1 = Builder.CreateListOfSize(2) + .All() + .With(m => m.Path = GivenRandomPath()) + .Build() + .ToList(); + + var files2 = Builder.CreateListOfSize(2) + .All() + .With(m => m.Path = GivenRandomPath()) + .Build() + .ToList(); + + var command1 = new ManualImportCommand { Files = files1 }; + var command2 = new ManualImportCommand { Files = files2 }; + + CommandEqualityComparer.Instance.Equals(command1, command2).Should().BeFalse(); + } } } diff --git a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Manual/ManualImportFile.cs b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Manual/ManualImportFile.cs index f0d42b21d..318b7ff7d 100644 --- a/src/NzbDrone.Core/MediaFiles/EpisodeImport/Manual/ManualImportFile.cs +++ b/src/NzbDrone.Core/MediaFiles/EpisodeImport/Manual/ManualImportFile.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Qualities; namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual { - public class ManualImportFile + public class ManualImportFile : IEquatable { public string Path { get; set; } public string FolderName { get; set; } @@ -11,5 +13,35 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual public List EpisodeIds { get; set; } public QualityModel Quality { get; set; } public string DownloadId { get; set; } + + public bool Equals(ManualImportFile other) + { + if (other == null) + { + return false; + } + + return Path.PathEquals(other.Path); + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + + if (obj.GetType() != GetType()) + { + return false; + } + + return Path.PathEquals(((ManualImportFile)obj).Path); + } + + public override int GetHashCode() + { + return Path != null ? Path.GetHashCode() : 0; + } } } diff --git a/src/NzbDrone.Core/Messaging/Commands/CommandEqualityComparer.cs b/src/NzbDrone.Core/Messaging/Commands/CommandEqualityComparer.cs index eabbec15f..65f21b935 100644 --- a/src/NzbDrone.Core/Messaging/Commands/CommandEqualityComparer.cs +++ b/src/NzbDrone.Core/Messaging/Commands/CommandEqualityComparer.cs @@ -49,10 +49,13 @@ namespace NzbDrone.Core.Messaging.Commands if (typeof(IEnumerable).IsAssignableFrom(xProperty.PropertyType)) { - var xValueCollection = ((IEnumerable)xValue).Cast().OrderBy(t => t); - var yValueCollection = ((IEnumerable)yValue).Cast().OrderBy(t => t); + var xValueCollection = ((IEnumerable)xValue).Cast(); + var yValueCollection = ((IEnumerable)yValue).Cast(); - if (!xValueCollection.SequenceEqual(yValueCollection)) + var xNotY = xValueCollection.Except(yValueCollection); + var yNotX = yValueCollection.Except(xValueCollection); + + if (xNotY.Any() || yNotX.Any()) { return false; }