1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-10-30 07:22:35 +01:00

Updated db migration testing framework so we only run migrations up to the one we're testing.

fixes #902
This commit is contained in:
Taloth Saldono 2016-02-13 22:23:37 +01:00
parent 8818e39c63
commit bdb1076100
30 changed files with 710 additions and 333 deletions

View File

@ -2,11 +2,7 @@
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Datastore.Migration; using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Tags;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
@ -16,7 +12,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[Test] [Test]
public void should_migrate_old_delays() public void should_migrate_old_delays()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Profiles").Row(new c.Insert.IntoTable("Profiles").Row(new
{ {
@ -35,10 +31,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var allProfiles = Mocker.Resolve<DelayProfileRepository>().All().ToList(); var allProfiles = db.Query<DelayProfile70>("SELECT * FROM DelayProfiles");
allProfiles.Should().HaveCount(3); allProfiles.Should().HaveCount(3);
allProfiles.Should().OnlyContain(c => c.PreferredProtocol == DownloadProtocol.Usenet); allProfiles.Should().OnlyContain(c => c.PreferredProtocol == 1);
allProfiles.Should().OnlyContain(c => c.TorrentDelay == 0); allProfiles.Should().OnlyContain(c => c.TorrentDelay == 0);
allProfiles.Should().Contain(c => c.UsenetDelay == 60); allProfiles.Should().Contain(c => c.UsenetDelay == 60);
allProfiles.Should().Contain(c => c.UsenetDelay == 120); allProfiles.Should().Contain(c => c.UsenetDelay == 120);
@ -47,17 +43,18 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[Test] [Test]
public void should_create_tag_for_delay_profile() public void should_create_tag_for_delay_profile()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Profiles").Row(new c.Insert.IntoTable("Profiles").Row(new
{ {
GrabDelay = 1, GrabDelay = 1,
Name = "OneHour", Name = "OneHour",
Cutoff = 0, Cutoff = 0,
Items = "[]" Items = "[]"
}) });
); });
var tags = Mocker.Resolve<TagRepository>().All().ToList(); var tags = db.Query<Tag69>("SELECT * FROM Tags");
tags.Should().HaveCount(1); tags.Should().HaveCount(1);
tags.First().Label.Should().Be("delay-60"); tags.First().Label.Should().Be("delay-60");
@ -66,7 +63,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[Test] [Test]
public void should_add_tag_to_series_that_had_a_profile_with_delay_attached() public void should_add_tag_to_series_that_had_a_profile_with_delay_attached()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Profiles").Row(new c.Insert.IntoTable("Profiles").Row(new
{ {
@ -95,12 +92,11 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var tag = Mocker.Resolve<TagRepository>().All().ToList().First(); var tag = db.Query<Tag69>("SELECT Id, Label FROM Tags").Single();
var series = Mocker.Resolve<SeriesRepository>().All().ToList(); var series = db.Query<Series69>("SELECT Tags FROM Series");
series.Should().HaveCount(1); series.Should().HaveCount(1);
series.First().Tags.Should().HaveCount(1); series.First().Tags.Should().BeEquivalentTo(tag.Id);
series.First().Tags.First().Should().Be(tag.Id);
} }
} }
} }

View File

@ -2,12 +2,7 @@
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Datastore.Migration; using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Tags;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
@ -17,10 +12,11 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[Test] [Test]
public void should_add_unknown_to_old_profile() public void should_add_unknown_to_old_profile()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Profiles").Row(new c.Insert.IntoTable("Profiles").Row(new
{ {
Id = 0,
Name = "SDTV", Name = "SDTV",
Cutoff = 1, Cutoff = 1,
Items = "[ { \"quality\": 1, \"allowed\": true } ]", Items = "[ { \"quality\": 1, \"allowed\": true } ]",
@ -28,11 +24,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var allProfiles = Mocker.Resolve<ProfileRepository>().All().ToList(); var profiles = db.Query<Profile70>("SELECT Items FROM Profiles LIMIT 1");
allProfiles.Should().HaveCount(1); var items = profiles.First().Items;
allProfiles.First().Items.Should().HaveCount(2); items.Should().HaveCount(2);
allProfiles.First().Items.Should().Contain(i => i.Quality.Id == 0 && i.Allowed == false); items.First().Quality.Should().Be(0);
items.First().Allowed.Should().Be(false);
} }
} }
} }

View File

@ -6,7 +6,6 @@ using FluentMigrator;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Migration; using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.History;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
@ -17,7 +16,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[Test] [Test]
public void should_move_grab_id_from_date_to_columns() public void should_move_grab_id_from_date_to_columns()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
InsertHistory(c, new Dictionary<string, string> InsertHistory(c, new Dictionary<string, string>
{ {
@ -33,19 +32,19 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
var allProfiles = Mocker.Resolve<HistoryRepository>().All().ToList(); var history = db.Query<History72>("SELECT DownloadId, Data FROM History");
allProfiles.Should().HaveCount(2); history.Should().HaveCount(2);
allProfiles.Should().NotContain(c => c.Data.ContainsKey("downloadClientId")); history.Should().NotContain(c => c.Data.ContainsKey("downloadClientId"));
allProfiles.Should().Contain(c => c.DownloadId == "123"); history.Should().Contain(c => c.DownloadId == "123");
allProfiles.Should().Contain(c => c.DownloadId == "abc"); history.Should().Contain(c => c.DownloadId == "abc");
} }
[Test] [Test]
public void should_leave_items_with_no_grabid() public void should_leave_items_with_no_grabid()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
InsertHistory(c, new Dictionary<string, string> InsertHistory(c, new Dictionary<string, string>
{ {
@ -60,18 +59,18 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
var allProfiles = Mocker.Resolve<HistoryRepository>().All().ToList(); var history = db.Query<History72>("SELECT DownloadId, Data FROM History");
allProfiles.Should().HaveCount(2); history.Should().HaveCount(2);
allProfiles.Should().NotContain(c => c.Data.ContainsKey("downloadClientId")); history.Should().NotContain(c => c.Data.ContainsKey("downloadClientId"));
allProfiles.Should().Contain(c => c.DownloadId == "123"); history.Should().Contain(c => c.DownloadId == "123");
allProfiles.Should().Contain(c => c.DownloadId == null); history.Should().Contain(c => c.DownloadId == null);
} }
[Test] [Test]
public void should_leave_other_data() public void should_leave_other_data()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
InsertHistory(c, new Dictionary<string, string> InsertHistory(c, new Dictionary<string, string>
{ {
@ -81,16 +80,15 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var allProfiles = Mocker.Resolve<HistoryRepository>().All().Single(); var history = db.Query<History72>("SELECT DownloadId, Data FROM History").Single();
allProfiles.Data.Should().NotContainKey("downloadClientId"); history.Data.Should().NotContainKey("downloadClientId");
allProfiles.Data.Should().Contain(new KeyValuePair<string, string>("indexer", "test")); history.Data.Should().Contain(new KeyValuePair<string, string>("indexer", "test"));
allProfiles.Data.Should().Contain(new KeyValuePair<string, string>("group", "test2")); history.Data.Should().Contain(new KeyValuePair<string, string>("group", "test2"));
allProfiles.DownloadId.Should().Be("123"); history.DownloadId.Should().Be("123");
} }
private void InsertHistory(MigrationBase migrationBase, Dictionary<string, string> data) private void InsertHistory(MigrationBase migrationBase, Dictionary<string, string> data)
{ {
migrationBase.Insert.IntoTable("History").Row(new migrationBase.Insert.IntoTable("History").Row(new

View File

@ -1,29 +1,28 @@
using System.Linq; using System.Linq;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv; using NzbDrone.Core.Datastore.Migration;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
[TestFixture] [TestFixture]
public class force_lib_updateFixture : MigrationTest<Core.Datastore.Migration.force_lib_update> public class force_lib_updateFixture : MigrationTest<force_lib_update>
{ {
[Test] [Test]
public void should_not_fail_on_empty_db() public void should_not_fail_on_empty_db()
{ {
WithTestDb(c => { }); var db = WithMigrationTestDb();
Mocker.Resolve<ScheduledTaskRepository>().All().Should().BeEmpty(); db.Query("SELECT * FROM ScheduledTasks").Should().BeEmpty();
Mocker.Resolve<SeriesRepository>().All().Should().BeEmpty(); db.Query("SELECT * FROM Series").Should().BeEmpty();
} }
[Test] [Test]
public void should_reset_job_last_execution_time() public void should_reset_job_last_execution_time()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("ScheduledTasks").Row(new c.Insert.IntoTable("ScheduledTasks").Row(new
{ {
@ -40,7 +39,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var jobs = Mocker.Resolve<ScheduledTaskRepository>().All().ToList(); var jobs = db.Query<ScheduledTasks75>("SELECT TypeName, LastExecution FROM ScheduledTasks");
jobs.Single(c => c.TypeName == "NzbDrone.Core.Tv.Commands.RefreshSeriesCommand") jobs.Single(c => c.TypeName == "NzbDrone.Core.Tv.Commands.RefreshSeriesCommand")
.LastExecution.Year.Should() .LastExecution.Year.Should()
@ -51,11 +50,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
.Be(2000); .Be(2000);
} }
[Test] [Test]
public void should_reset_series_last_sync_time() public void should_reset_series_last_sync_time()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Series").Row(new c.Insert.IntoTable("Series").Row(new
{ {
@ -92,9 +90,9 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var jobs = Mocker.Resolve<SeriesRepository>().All().ToList(); var series = db.Query<Series69>("SELECT LastInfoSync FROM Series");
jobs.Should().OnlyContain(c => c.LastInfoSync.Value.Year == 2014); series.Should().OnlyContain(c => c.LastInfoSync.Value.Year == 2014);
} }
} }
} }

View File

@ -1,21 +1,18 @@
using System; using System.Linq;
using System.Linq;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Jobs; using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Tags;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
[TestFixture] [TestFixture]
public class dedupe_tagsFixture : MigrationTest<Core.Datastore.Migration.dedupe_tags> public class dedupe_tagsFixture : MigrationTest<dedupe_tags>
{ {
[Test] [Test]
public void should_not_fail_if_series_tags_are_null() public void should_not_fail_if_series_tags_are_null()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Series").Row(new c.Insert.IntoTable("Series").Row(new
{ {
@ -40,13 +37,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
Mocker.Resolve<TagRepository>().All().Should().HaveCount(1); var tags = db.Query<Tag69>("SELECT * FROM Tags");
tags.Should().HaveCount(1);
} }
[Test] [Test]
public void should_not_fail_if_series_tags_are_empty() public void should_not_fail_if_series_tags_are_empty()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Series").Row(new c.Insert.IntoTable("Series").Row(new
{ {
@ -72,13 +70,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
Mocker.Resolve<TagRepository>().All().Should().HaveCount(1); var tags = db.Query<Tag69>("SELECT * FROM Tags");
tags.Should().HaveCount(1);
} }
[Test] [Test]
public void should_remove_duplicate_labels_from_tags() public void should_remove_duplicate_labels_from_tags()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Tags").Row(new c.Insert.IntoTable("Tags").Row(new
{ {
@ -91,13 +90,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
Mocker.Resolve<TagRepository>().All().Should().HaveCount(1); var tags = db.Query<Tag69>("SELECT * FROM Tags");
tags.Should().HaveCount(1);
} }
[Test] [Test]
public void should_not_allow_duplicate_tag_to_be_inserted() public void should_not_allow_duplicate_tag_to_be_inserted()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Tags").Row(new c.Insert.IntoTable("Tags").Row(new
{ {
@ -105,13 +105,13 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
Assert.That(() => Mocker.Resolve<TagRepository>().Insert(new Tag { Label = "test" }), Throws.Exception); Assert.That(() => db.Query("INSERT INTO Tags (Label) VALUES ('test')"), Throws.Exception);
} }
[Test] [Test]
public void should_replace_duplicated_tag_with_proper_tag() public void should_replace_duplicated_tag_with_proper_tag()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Series").Row(new c.Insert.IntoTable("Series").Row(new
{ {
@ -142,13 +142,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
Mocker.Resolve<SeriesRepository>().Get(1).Tags.First().Should().Be(1); var series = db.Query<Series69>("SELECT Tags FROM Series WHERE Id = 1").Single();
series.Tags.First().Should().Be(1);
} }
[Test] [Test]
public void should_only_update_affected_series() public void should_only_update_affected_series()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Series").Row(new c.Insert.IntoTable("Series").Row(new
{ {
@ -197,7 +198,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
Mocker.Resolve<SeriesRepository>().Get(2).Tags.Should().BeEmpty(); var series = db.Query<Series69>("SELECT Tags FROM Series WHERE Id = 2").Single();
series.Tags.Should().BeEmpty();
} }
} }
} }

View File

@ -3,27 +3,25 @@ using System.Linq;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Sabnzbd;
using NzbDrone.Core.Download.Clients.Transmission;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Datastore.Migration;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
[TestFixture] [TestFixture]
public class move_dot_prefix_to_transmission_categoryFixture : MigrationTest<Core.Datastore.Migration.move_dot_prefix_to_transmission_category> public class move_dot_prefix_to_transmission_categoryFixture : MigrationTest<move_dot_prefix_to_transmission_category>
{ {
[Test] [Test]
public void should_not_fail_if_no_transmission() public void should_not_fail_if_no_transmission()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("DownloadClients").Row(new c.Insert.IntoTable("DownloadClients").Row(new
{ {
Enable = 1, Enable = 1,
Name = "Sab", Name = "Sab",
Implementation = "Sabnzbd", Implementation = "Sabnzbd",
Settings = new SabnzbdSettings Settings = new
{ {
Host = "127.0.0.1", Host = "127.0.0.1",
TvCategory = "abc" TvCategory = "abc"
@ -32,24 +30,23 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var items = Mocker.Resolve<DownloadClientRepository>().All(); var downloadClients = db.Query<DownloadClientDefinition81>("SELECT Settings FROM DownloadClients");
items.Should().HaveCount(1); downloadClients.Should().HaveCount(1);
downloadClients.First().Settings.ToObject<SabnzbdSettings81>().TvCategory.Should().Be("abc");
items.First().Settings.As<SabnzbdSettings>().TvCategory.Should().Be("abc");
} }
[Test] [Test]
public void should_be_updated_for_transmission() public void should_be_updated_for_transmission()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("DownloadClients").Row(new c.Insert.IntoTable("DownloadClients").Row(new
{ {
Enable = 1, Enable = 1,
Name = "Trans", Name = "Trans",
Implementation = "Transmission", Implementation = "Transmission",
Settings = new TransmissionSettings Settings = new
{ {
Host = "127.0.0.1", Host = "127.0.0.1",
TvCategory = "abc" TvCategory = "abc"
@ -58,24 +55,23 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var items = Mocker.Resolve<DownloadClientRepository>().All(); var downloadClients = db.Query<DownloadClientDefinition81>("SELECT Settings FROM DownloadClients");
items.Should().HaveCount(1); downloadClients.Should().HaveCount(1);
downloadClients.First().Settings.ToObject<TransmissionSettings81>().TvCategory.Should().Be(".abc");
items.First().Settings.As<TransmissionSettings>().TvCategory.Should().Be(".abc");
} }
[Test] [Test]
public void should_leave_empty_category_untouched() public void should_leave_empty_category_untouched()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("DownloadClients").Row(new c.Insert.IntoTable("DownloadClients").Row(new
{ {
Enable = 1, Enable = 1,
Name = "Trans", Name = "Trans",
Implementation = "Transmission", Implementation = "Transmission",
Settings = new TransmissionSettings Settings = new
{ {
Host = "127.0.0.1", Host = "127.0.0.1",
TvCategory = "" TvCategory = ""
@ -84,11 +80,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var items = Mocker.Resolve<DownloadClientRepository>().All(); var downloadClients = db.Query<DownloadClientDefinition81>("SELECT Settings FROM DownloadClients");
items.Should().HaveCount(1); downloadClients.Should().HaveCount(1);
downloadClients.First().Settings.ToObject<TransmissionSettings81>().TvCategory.Should().Be("");
items.First().Settings.As<TransmissionSettings>().TvCategory.Should().Be("");
} }
} }
} }

View File

@ -1,32 +1,28 @@
using System; using System.Linq;
using System.Linq;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Qualities; using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
[TestFixture] [TestFixture]
public class update_quality_minmax_sizeFixture : MigrationTest<Core.Datastore.Migration.update_quality_minmax_size> public class update_quality_minmax_sizeFixture : MigrationTest<update_quality_minmax_size>
{ {
[Test] [Test]
public void should_not_fail_if_empty() public void should_not_fail_if_empty()
{ {
WithTestDb(c => var db = WithMigrationTestDb();
{
}); var qualityDefinitions = db.Query<QualityDefinition84>("SELECT * FROM QualityDefinitions");
var items = Mocker.Resolve<QualityDefinitionRepository>().All(); qualityDefinitions.Should().BeEmpty();
items.Should().HaveCount(0);
} }
[Test] [Test]
public void should_set_rawhd_to_null() public void should_set_rawhd_to_null()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("QualityDefinitions").Row(new c.Insert.IntoTable("QualityDefinitions").Row(new
{ {
@ -44,17 +40,16 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var items = Mocker.Resolve<QualityDefinitionRepository>().All(); var qualityDefinitions = db.Query<QualityDefinition84>("SELECT * FROM QualityDefinitions");
items.Should().HaveCount(2); qualityDefinitions.Should().HaveCount(2);
qualityDefinitions.First(v => v.Quality == 10).MaxSize.Should().NotHaveValue();
items.First(v => v.Quality.Id == 10).MaxSize.Should().NotHaveValue();
} }
[Test] [Test]
public void should_set_zero_maxsize_to_null() public void should_set_zero_maxsize_to_null()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("QualityDefinitions").Row(new c.Insert.IntoTable("QualityDefinitions").Row(new
{ {
@ -65,17 +60,16 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var items = Mocker.Resolve<QualityDefinitionRepository>().All(); var qualityDefinitions = db.Query<QualityDefinition84>("SELECT * FROM QualityDefinitions");
items.Should().HaveCount(1); qualityDefinitions.Should().HaveCount(1);
qualityDefinitions.First(v => v.Quality == 1).MaxSize.Should().NotHaveValue();
items.First(v => v.Quality.Id == 1).MaxSize.Should().NotHaveValue();
} }
[Test] [Test]
public void should_preserve_values() public void should_preserve_values()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("QualityDefinitions").Row(new c.Insert.IntoTable("QualityDefinitions").Row(new
{ {
@ -93,11 +87,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var items = Mocker.Resolve<QualityDefinitionRepository>().All(); var qualityDefinitions = db.Query<QualityDefinition84>("SELECT * FROM QualityDefinitions");
items.Should().HaveCount(2); qualityDefinitions.Should().HaveCount(2);
qualityDefinitions.First(v => v.Quality == 1).MaxSize.Should().Be(100);
items.First(v => v.Quality.Id == 1).MaxSize.Should().Be(100);
} }
} }
} }

View File

@ -1,30 +1,26 @@
using System; using System.Linq;
using System.Linq;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download; using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Download.Clients.Deluge;
using NzbDrone.Core.Download.Clients.Sabnzbd;
using NzbDrone.Core.Download.Clients.Transmission;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using System.Drawing;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
[TestFixture] [TestFixture]
public class expand_transmission_urlbaseFixture : MigrationTest<Core.Datastore.Migration.expand_transmission_urlbase> public class expand_transmission_urlbaseFixture : MigrationTest<expand_transmission_urlbase>
{ {
[Test] [Test]
public void should_not_fail_if_no_transmission() public void should_not_fail_if_no_transmission()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("DownloadClients").Row(new c.Insert.IntoTable("DownloadClients").Row(new
{ {
Enable = 1, Enable = 1,
Name = "Deluge", Name = "Deluge",
Implementation = "Deluge", Implementation = "Deluge",
Settings = new DelugeSettings Settings = new DelugeSettings85
{ {
Host = "127.0.0.1", Host = "127.0.0.1",
TvCategory = "abc", TvCategory = "abc",
@ -34,51 +30,48 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var items = Mocker.Resolve<DownloadClientRepository>().All(); var items = db.Query<DownloadClientDefinition81>("SELECT * FROM DownloadClients");
items.Should().HaveCount(1); items.Should().HaveCount(1);
items.First().Settings.ToObject<DelugeSettings85>().UrlBase.Should().Be("/my/");
items.First().Settings.As<DelugeSettings>().UrlBase.Should().Be("/my/");
} }
[Test] [Test]
public void should_be_updated_for_transmission() public void should_be_updated_for_transmission()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("DownloadClients").Row(new c.Insert.IntoTable("DownloadClients").Row(new
{ {
Enable = 1, Enable = 1,
Name = "Trans", Name = "Trans",
Implementation = "Transmission", Implementation = "Transmission",
Settings = new TransmissionSettings Settings = new TransmissionSettings81
{ {
Host = "127.0.0.1", Host = "127.0.0.1",
TvCategory = "abc", TvCategory = "abc"
UrlBase = null
}.ToJson(), }.ToJson(),
ConfigContract = "TransmissionSettings" ConfigContract = "TransmissionSettings"
}); });
}); });
var items = Mocker.Resolve<DownloadClientRepository>().All(); var items = db.Query<DownloadClientDefinition81>("SELECT * FROM DownloadClients");
items.Should().HaveCount(1); items.Should().HaveCount(1);
items.First().Settings.ToObject<TransmissionSettings81>().UrlBase.Should().Be("/transmission/");
items.First().Settings.As<TransmissionSettings>().UrlBase.Should().Be("/transmission/");
} }
[Test] [Test]
public void should_be_append_to_existing_urlbase() public void should_be_append_to_existing_urlbase()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("DownloadClients").Row(new c.Insert.IntoTable("DownloadClients").Row(new
{ {
Enable = 1, Enable = 1,
Name = "Trans", Name = "Trans",
Implementation = "Transmission", Implementation = "Transmission",
Settings = new TransmissionSettings Settings = new TransmissionSettings81
{ {
Host = "127.0.0.1", Host = "127.0.0.1",
TvCategory = "abc", TvCategory = "abc",
@ -88,11 +81,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var items = Mocker.Resolve<DownloadClientRepository>().All(); var items = db.Query<DownloadClientDefinition81>("SELECT * FROM DownloadClients");
items.Should().HaveCount(1); items.Should().HaveCount(1);
items.First().Settings.ToObject<TransmissionSettings81>().UrlBase.Should().Be("/my/url/transmission/");
items.First().Settings.As<TransmissionSettings>().UrlBase.Should().Be("/my/url/transmission/");
} }
} }
} }

View File

@ -2,19 +2,18 @@
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Notifications; using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Notifications.PushBullet;
using NzbDrone.Core.Notifications.Pushover;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
[TestFixture] [TestFixture]
public class pushbullet_device_idsFixture : MigrationTest<Core.Datastore.Migration.pushbullet_device_ids> public class pushbullet_device_idsFixture : MigrationTest<pushbullet_device_ids>
{ {
[Test] [Test]
public void should_not_fail_if_no_pushbullet() public void should_not_fail_if_no_pushbullet()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Notifications").Row(new c.Insert.IntoTable("Notifications").Row(new
{ {
@ -23,12 +22,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration
OnUpgrade = false, OnUpgrade = false,
Name = "Pushover", Name = "Pushover",
Implementation = "Pushover", Implementation = "Pushover",
Settings = new PushoverSettings().ToJson(), Settings = "{}",
ConfigContract = "PushoverSettings" ConfigContract = "PushoverSettings"
}); });
}); });
var items = Mocker.Resolve<NotificationRepository>().All(); var items = db.Query<Notification86>("SELECT * FROM Notifications");
items.Should().HaveCount(1); items.Should().HaveCount(1);
} }
@ -36,7 +35,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[Test] [Test]
public void should_not_fail_if_deviceId_is_not_set() public void should_not_fail_if_deviceId_is_not_set()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Notifications").Row(new c.Insert.IntoTable("Notifications").Row(new
{ {
@ -47,13 +46,13 @@ namespace NzbDrone.Core.Test.Datastore.Migration
Implementation = "PushBullet", Implementation = "PushBullet",
Settings = new Settings = new
{ {
ApiKey = "my_api_key", ApiKey = "my_api_key"
}.ToJson(), }.ToJson(),
ConfigContract = "PushBulletSettings" ConfigContract = "PushBulletSettings"
}); });
}); });
var items = Mocker.Resolve<NotificationRepository>().All(); var items = db.Query<Notification86>("SELECT * FROM Notifications");
items.Should().HaveCount(1); items.Should().HaveCount(1);
} }
@ -63,7 +62,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
{ {
var deviceId = "device_id"; var deviceId = "device_id";
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Notifications").Row(new c.Insert.IntoTable("Notifications").Row(new
{ {
@ -81,10 +80,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var items = Mocker.Resolve<NotificationRepository>().All(); var items = db.Query<Notification86>("SELECT * FROM Notifications");
items.Should().HaveCount(1); items.Should().HaveCount(1);
items.First().Settings.As<PushBulletSettings>().DeviceIds.First().Should().Be(deviceId); items.First().Settings.ToObject<PushBulletSettings86>().DeviceIds.First().Should().Be(deviceId);
} }
} }
} }

View File

@ -2,19 +2,18 @@
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Notifications; using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Notifications.PushBullet;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
{ {
[TestFixture] [TestFixture]
public class pushbullet_devices_channels : MigrationTest<Core.Datastore.Migration.pushbullet_devices_channels_list> public class pushbullet_devices_channels_listFixture : MigrationTest<pushbullet_devices_channels_list>
{ {
[Test] [Test]
public void should_convert_comma_separted_string_to_list() public void should_convert_comma_separted_string_to_list()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Notifications").Row(new c.Insert.IntoTable("Notifications").Row(new
{ {
@ -32,11 +31,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var items = Mocker.Resolve<NotificationRepository>().All(); var items = db.Query<Notification86>("SELECT * FROM Notifications");
items.Should().HaveCount(1); items.Should().HaveCount(1);
var settings = items.First().Settings.As<PushBulletSettings>(); items.First().Settings.ToObject<PushBulletSettings88>().ChannelTags.Should().HaveCount(2);
settings.ChannelTags.Should().HaveCount(2);
} }
} }
} }

View File

@ -3,8 +3,6 @@ using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Migration; using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.KickassTorrents;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration namespace NzbDrone.Core.Test.Datastore.Migration
@ -20,13 +18,13 @@ namespace NzbDrone.Core.Test.Datastore.Migration
// [TestCase("HTTP://KICKASS.SO")] Not sure if there is an easy way to do this, not sure if worth it. // [TestCase("HTTP://KICKASS.SO")] Not sure if there is an easy way to do this, not sure if worth it.
public void should_replace_old_url(string oldUrl) public void should_replace_old_url(string oldUrl)
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Indexers").Row(new c.Insert.IntoTable("Indexers").Row(new
{ {
Name = "Kickass_wrong_url", Name = "Kickass_wrong_url",
Implementation = "KickassTorrents", Implementation = "KickassTorrents",
Settings = new KickassTorrentsSettings Settings = new KickassTorrentsSettings90
{ {
BaseUrl = oldUrl BaseUrl = oldUrl
}.ToJson(), }.ToJson(),
@ -34,22 +32,22 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var items = Mocker.Resolve<IndexerRepository>().All().ToList(); var items = db.Query<IndexerDefinition90>("SELECT * FROM Indexers");
items.Should().HaveCount(1); items.Should().HaveCount(1);
items.First().Settings.As<KickassTorrentsSettings>().BaseUrl.Should().Be("https://kat.cr"); items.First().Settings.ToObject<KickassTorrentsSettings90>().BaseUrl.Should().Be("https://kat.cr");
} }
[Test] [Test]
public void should_not_replace_other_indexers() public void should_not_replace_other_indexers()
{ {
WithTestDb(c => var db = WithMigrationTestDb(c =>
{ {
c.Insert.IntoTable("Indexers").Row(new c.Insert.IntoTable("Indexers").Row(new
{ {
Name = "not_kickass", Name = "not_kickass",
Implementation = "NotKickassTorrents", Implementation = "NotKickassTorrents",
Settings = new KickassTorrentsSettings Settings = new KickassTorrentsSettings90
{ {
BaseUrl = "kickass.so", BaseUrl = "kickass.so",
}.ToJson(), }.ToJson(),
@ -57,10 +55,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
}); });
}); });
var items = Mocker.Resolve<IndexerRepository>().All().ToList(); var items = db.Query<IndexerDefinition90>("SELECT * FROM Indexers");
items.Should().HaveCount(1); items.Should().HaveCount(1);
items.First().Settings.As<KickassTorrentsSettings>().BaseUrl.Should().Be("kickass.so"); items.First().Settings.ToObject<KickassTorrentsSettings90>().BaseUrl.Should().Be("kickass.so");
} }
} }
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using FluentMigrator; using FluentMigrator;
@ -7,11 +8,11 @@ using FluentMigrator.Runner;
using Marr.Data; using Marr.Data;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Migration.Framework; using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Test.Framework namespace NzbDrone.Core.Test.Framework
{ {
public abstract class DbTest<TSubject, TModel> : DbTest public abstract class DbTest<TSubject, TModel> : DbTest
@ -70,7 +71,6 @@ namespace NzbDrone.Core.Test.Framework
get get
{ {
return MigrationType.Main; return MigrationType.Main;
} }
} }
@ -85,10 +85,10 @@ namespace NzbDrone.Core.Test.Framework
} }
} }
protected virtual TestDatabase WithTestDb(Action<MigrationBase> beforeMigration) protected virtual ITestDatabase WithTestDb(MigrationContext migrationContext)
{ {
var factory = Mocker.Resolve<DbFactory>(); var factory = Mocker.Resolve<DbFactory>();
var database = factory.Create(MigrationType, beforeMigration); var database = factory.Create(migrationContext);
Mocker.SetConstant(database); Mocker.SetConstant(database);
switch (MigrationType) switch (MigrationType)
@ -118,7 +118,6 @@ namespace NzbDrone.Core.Test.Framework
return testDb; return testDb;
} }
protected void SetupContainer() protected void SetupContainer()
{ {
WithTempAsAppPath(); WithTempAsAppPath();
@ -134,7 +133,7 @@ namespace NzbDrone.Core.Test.Framework
public virtual void SetupDb() public virtual void SetupDb()
{ {
SetupContainer(); SetupContainer();
_db = WithTestDb(null); _db = WithTestDb(new MigrationContext(MigrationType));
} }
[TearDown] [TearDown]
@ -158,57 +157,4 @@ namespace NzbDrone.Core.Test.Framework
} }
} }
} }
public interface ITestDatabase
{
void InsertMany<T>(IEnumerable<T> items) where T : ModelBase, new();
T Insert<T>(T item) where T : ModelBase, new();
List<T> All<T>() where T : ModelBase, new();
T Single<T>() where T : ModelBase, new();
void Update<T>(T childModel) where T : ModelBase, new();
void Delete<T>(T childModel) where T : ModelBase, new();
}
public class TestDatabase : ITestDatabase
{
private readonly IDatabase _dbConnection;
private IEventAggregator _eventAggregator;
public TestDatabase(IDatabase dbConnection)
{
_eventAggregator = new Mock<IEventAggregator>().Object;
_dbConnection = dbConnection;
}
public void InsertMany<T>(IEnumerable<T> items) where T : ModelBase, new()
{
new BasicRepository<T>(_dbConnection, _eventAggregator).InsertMany(items.ToList());
}
public T Insert<T>(T item) where T : ModelBase, new()
{
return new BasicRepository<T>(_dbConnection, _eventAggregator).Insert(item);
}
public List<T> All<T>() where T : ModelBase, new()
{
return new BasicRepository<T>(_dbConnection, _eventAggregator).All().ToList();
}
public T Single<T>() where T : ModelBase, new()
{
return All<T>().SingleOrDefault();
}
public void Update<T>(T childModel) where T : ModelBase, new()
{
new BasicRepository<T>(_dbConnection, _eventAggregator).Update(childModel);
}
public void Delete<T>(T childModel) where T : ModelBase, new()
{
new BasicRepository<T>(_dbConnection, _eventAggregator).Delete(childModel);
}
}
} }

View File

@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Test.Framework
{
public interface IDirectDataMapper
{
List<Dictionary<string, object>> Query(string sql);
List<T> Query<T>(string sql) where T : new();
}
public class DirectDataMapper : IDirectDataMapper
{
private readonly DbProviderFactory _providerFactory;
private readonly string _connectionString;
public DirectDataMapper(IDatabase database)
{
var dataMapper = database.GetDataMapper();
_providerFactory = dataMapper.ProviderFactory;
_connectionString = dataMapper.ConnectionString;
}
private DbConnection OpenConnection()
{
var connection = _providerFactory.CreateConnection();
connection.ConnectionString = _connectionString;
connection.Open();
return connection;
}
public DataTable GetDataTable(string sql)
{
using (var connection = OpenConnection())
{
using (var cmd = connection.CreateCommand())
{
var dataTable = new DataTable();
cmd.CommandText = sql;
dataTable.Load(cmd.ExecuteReader());
return dataTable;
}
}
}
public List<Dictionary<string, object>> Query(string sql)
{
var dataTable = GetDataTable(sql);
return dataTable.Rows.Cast<DataRow>().Select(MapToDictionary).ToList();
}
public List<T> Query<T>(string sql) where T : new()
{
var dataTable = GetDataTable(sql);
return dataTable.Rows.Cast<DataRow>().Select(MapToObject<T>).ToList();
}
protected Dictionary<string, object> MapToDictionary(DataRow dataRow)
{
var item = new Dictionary<string, object>();
for (var i = 0; i < dataRow.Table.Columns.Count; i++)
{
var columnName = dataRow.Table.Columns[i].ColumnName;
object value;
if (dataRow.ItemArray[i] == DBNull.Value)
{
value = null;
}
else
{
value = dataRow.ItemArray[i];
}
item[columnName] = dataRow.ItemArray[i];
}
return item;
}
protected T MapToObject<T>(DataRow dataRow) where T : new()
{
var item = new T();
for (var i = 0; i < dataRow.Table.Columns.Count; i++)
{
var columnName = dataRow.Table.Columns[i].ColumnName;
var propertyInfo = typeof(T).GetProperty(columnName);
if (propertyInfo == null)
{
throw new Exception(string.Format("Column {0} doesn't exist on type {1}.", columnName, typeof(T)));
}
var propertyType = propertyInfo.PropertyType;
if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
propertyType = propertyType.GetGenericArguments()[0];
}
object value;
if (dataRow.ItemArray[i] == DBNull.Value)
{
value = null;
}
else if (dataRow.Table.Columns[i].DataType == typeof(string) && propertyType != typeof(string))
{
value = Json.Deserialize((string)dataRow.ItemArray[i], propertyType);
}
else
{
value = Convert.ChangeType(dataRow.ItemArray[i], propertyType);
}
propertyInfo.SetValue(item, value, null);
}
return item;
}
}
}

View File

@ -1,23 +1,41 @@
using System; using System;
using System.Data;
using FluentMigrator; using FluentMigrator;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Test.Common.AutoMoq;
namespace NzbDrone.Core.Test.Framework namespace NzbDrone.Core.Test.Framework
{ {
[Category("DbMigrationTest")] [Category("DbMigrationTest")]
[Category("DbTest")] [Category("DbTest")]
public abstract class MigrationTest<TMigration> : DbTest where TMigration : MigrationBase public abstract class MigrationTest<TMigration> : DbTest where TMigration : NzbDroneMigrationBase
{ {
protected override TestDatabase WithTestDb(Action<MigrationBase> beforeMigration) protected long MigrationVersion
{ {
return base.WithTestDb(m => get
{ {
if (m.GetType() == typeof(TMigration)) var attrib = (MigrationAttribute)Attribute.GetCustomAttribute(typeof(TMigration), typeof(MigrationAttribute));
return attrib.Version;
}
}
protected virtual IDirectDataMapper WithMigrationTestDb(Action<TMigration> beforeMigration = null)
{
var db = WithTestDb(new MigrationContext(MigrationType, MigrationVersion)
{
BeforeMigration = m =>
{ {
beforeMigration(m); var migration = m as TMigration;
if (beforeMigration != null && migration is TMigration)
{
beforeMigration(migration);
}
} }
}); });
return db.GetDirectDataMapper();
} }
[SetUp] [SetUp]
@ -25,5 +43,11 @@ namespace NzbDrone.Core.Test.Framework
{ {
SetupContainer(); SetupContainer();
} }
[Obsolete("Don't use Mocker/Repositories in MigrationTests, query the DB.", true)]
public new AutoMoqer Mocker
{
get { return base.Mocker; }
}
} }
} }

View File

@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Moq;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Test.Framework
{
public interface ITestDatabase
{
void InsertMany<T>(IEnumerable<T> items) where T : ModelBase, new();
T Insert<T>(T item) where T : ModelBase, new();
List<T> All<T>() where T : ModelBase, new();
T Single<T>() where T : ModelBase, new();
void Update<T>(T childModel) where T : ModelBase, new();
void Delete<T>(T childModel) where T : ModelBase, new();
IDirectDataMapper GetDirectDataMapper();
}
public class TestDatabase : ITestDatabase
{
private readonly IDatabase _dbConnection;
private readonly IEventAggregator _eventAggregator;
public TestDatabase(IDatabase dbConnection)
{
_eventAggregator = new Mock<IEventAggregator>().Object;
_dbConnection = dbConnection;
}
public void InsertMany<T>(IEnumerable<T> items) where T : ModelBase, new()
{
new BasicRepository<T>(_dbConnection, _eventAggregator).InsertMany(items.ToList());
}
public T Insert<T>(T item) where T : ModelBase, new()
{
return new BasicRepository<T>(_dbConnection, _eventAggregator).Insert(item);
}
public List<T> All<T>() where T : ModelBase, new()
{
return new BasicRepository<T>(_dbConnection, _eventAggregator).All().ToList();
}
public T Single<T>() where T : ModelBase, new()
{
return All<T>().SingleOrDefault();
}
public void Update<T>(T childModel) where T : ModelBase, new()
{
new BasicRepository<T>(_dbConnection, _eventAggregator).Update(childModel);
}
public void Delete<T>(T childModel) where T : ModelBase, new()
{
new BasicRepository<T>(_dbConnection, _eventAggregator).Delete(childModel);
}
public IDirectDataMapper GetDirectDataMapper()
{
return new DirectDataMapper(_dbConnection);
}
}
}

View File

@ -1,7 +0,0 @@
namespace NzbDrone.Core.Test.Framework
{
internal static class TestDbHelper
{
}
}

View File

@ -120,9 +120,9 @@
<Compile Include="Datastore\MappingExtentionFixture.cs" /> <Compile Include="Datastore\MappingExtentionFixture.cs" />
<Compile Include="Datastore\MarrDataLazyLoadingFixture.cs" /> <Compile Include="Datastore\MarrDataLazyLoadingFixture.cs" />
<Compile Include="Datastore\Migration\071_unknown_quality_in_profileFixture.cs" /> <Compile Include="Datastore\Migration\071_unknown_quality_in_profileFixture.cs" />
<Compile Include="Datastore\Migration\072_history_grabIdFixture.cs" /> <Compile Include="Datastore\Migration\072_history_downloadIdFixture.cs" />
<Compile Include="Datastore\Migration\070_delay_profileFixture.cs" /> <Compile Include="Datastore\Migration\070_delay_profileFixture.cs" />
<Compile Include="Datastore\Migration\088_pushbullet_devices_channels.cs" /> <Compile Include="Datastore\Migration\088_pushbullet_devices_channels_listFixture.cs" />
<Compile Include="Datastore\Migration\086_pushbullet_device_idsFixture.cs" /> <Compile Include="Datastore\Migration\086_pushbullet_device_idsFixture.cs" />
<Compile Include="Datastore\Migration\085_expand_transmission_urlbaseFixture.cs" /> <Compile Include="Datastore\Migration\085_expand_transmission_urlbaseFixture.cs" />
<Compile Include="Datastore\Migration\084_update_quality_minmax_sizeFixture.cs" /> <Compile Include="Datastore\Migration\084_update_quality_minmax_sizeFixture.cs" />
@ -186,9 +186,10 @@
<Compile Include="FluentTest.cs" /> <Compile Include="FluentTest.cs" />
<Compile Include="Framework\CoreTest.cs" /> <Compile Include="Framework\CoreTest.cs" />
<Compile Include="Framework\DbTest.cs" /> <Compile Include="Framework\DbTest.cs" />
<Compile Include="Framework\DirectDataMapper.cs" />
<Compile Include="Framework\MigrationTest.cs" /> <Compile Include="Framework\MigrationTest.cs" />
<Compile Include="Framework\NBuilderExtensions.cs" /> <Compile Include="Framework\NBuilderExtensions.cs" />
<Compile Include="Framework\TestDbHelper.cs" /> <Compile Include="Framework\TestDatabase.cs" />
<Compile Include="HealthCheck\Checks\DeleteBadMediaCovers.cs" /> <Compile Include="HealthCheck\Checks\DeleteBadMediaCovers.cs" />
<Compile Include="HealthCheck\Checks\AppDataLocationFixture.cs" /> <Compile Include="HealthCheck\Checks\AppDataLocationFixture.cs" />
<Compile Include="HealthCheck\Checks\DownloadClientCheckFixture.cs" /> <Compile Include="HealthCheck\Checks\DownloadClientCheckFixture.cs" />

View File

@ -12,7 +12,8 @@ namespace NzbDrone.Core.Datastore
{ {
public interface IDbFactory public interface IDbFactory
{ {
IDatabase Create(MigrationType migrationType = MigrationType.Main, Action<NzbDroneMigrationBase> beforeMigration = null); IDatabase Create(MigrationType migrationType = MigrationType.Main);
IDatabase Create(MigrationContext migrationContext);
} }
public class DbFactory : IDbFactory public class DbFactory : IDbFactory
@ -43,12 +44,17 @@ namespace NzbDrone.Core.Datastore
_connectionStringFactory = connectionStringFactory; _connectionStringFactory = connectionStringFactory;
} }
public IDatabase Create(MigrationType migrationType = MigrationType.Main, Action<NzbDroneMigrationBase> beforeMigration = null) public IDatabase Create(MigrationType migrationType = MigrationType.Main)
{
return Create(new MigrationContext(migrationType));
}
public IDatabase Create(MigrationContext migrationContext)
{ {
string connectionString; string connectionString;
switch (migrationType) switch (migrationContext.MigrationType)
{ {
case MigrationType.Main: case MigrationType.Main:
{ {
@ -66,9 +72,9 @@ namespace NzbDrone.Core.Datastore
} }
} }
_migrationController.MigrateToLatest(connectionString, migrationType, beforeMigration); _migrationController.Migrate(connectionString, migrationContext);
var db = new Database(migrationType.ToString(), () => var db = new Database(migrationContext.MigrationType.ToString(), () =>
{ {
var dataMapper = new DataMapper(SQLiteFactory.Instance, connectionString) var dataMapper = new DataMapper(SQLiteFactory.Instance, connectionString)
{ {

View File

@ -74,9 +74,9 @@ namespace NzbDrone.Core.Datastore.Migration
} }
} }
private List<Profile70> GetProfiles(IDbConnection conn, IDbTransaction tran) private List<Profile69> GetProfiles(IDbConnection conn, IDbTransaction tran)
{ {
var profiles = new List<Profile70>(); var profiles = new List<Profile69>();
using (IDbCommand getProfilesCmd = conn.CreateCommand()) using (IDbCommand getProfilesCmd = conn.CreateCommand())
{ {
@ -90,7 +90,7 @@ namespace NzbDrone.Core.Datastore.Migration
var id = profileReader.GetInt32(0); var id = profileReader.GetInt32(0);
var delay = profileReader.GetInt32(1); var delay = profileReader.GetInt32(1);
profiles.Add(new Profile70 profiles.Add(new Profile69
{ {
Id = id, Id = id,
GrabDelay = delay * 60 GrabDelay = delay * 60
@ -145,21 +145,38 @@ namespace NzbDrone.Core.Datastore.Migration
} }
} }
} }
getSeriesCmd.ExecuteNonQuery();
} }
} }
}
private class Profile70 public class Profile69
{ {
public int Id { get; set; } public int Id { get; set; }
public int GrabDelay { get; set; } public int GrabDelay { get; set; }
} }
private class Series70 public class Series69
{ {
public int Id { get; set; } public int Id { get; set; }
public HashSet<int> Tags { get; set; } public List<int> Tags { get; set; }
} public DateTime? LastInfoSync { get; set; }
}
public class Tag69
{
public int Id { get; set; }
public string Label { get; set; }
}
public class DelayProfile70
{
public int Id { get; set; }
public bool EnableUsenet { get; set; }
public bool EnableTorrent { get; set; }
public int PreferredProtocol { get; set; }
public int UsenetDelay { get; set; }
public int TorrentDelay { get; set; }
public int Order { get; set; }
public List<int> Tags { get; set; }
} }
} }

View File

@ -19,54 +19,156 @@ namespace NzbDrone.Core.Datastore.Migration
private void ConvertProfile(IDbConnection conn, IDbTransaction tran) private void ConvertProfile(IDbConnection conn, IDbTransaction tran)
{ {
var profiles = GetProfiles(conn, tran); var updater = new ProfileUpdater70(conn, tran);
updater.PrependQuality(0);
updater.Commit();
}
}
public class Profile70
{
public int Id { get; set; }
public string Name { get; set; }
public int Cutoff { get; set; }
public List<ProfileItem70> Items { get; set; }
public int Language { get; set; }
}
foreach (var profile in profiles) public class ProfileItem70
{
public int Quality { get; set; }
public bool Allowed { get; set; }
}
public class ProfileUpdater70
{
private readonly IDbConnection _connection;
private readonly IDbTransaction _transaction;
private List<Profile70> _profiles;
private HashSet<Profile70> _changedProfiles = new HashSet<Profile70>();
public ProfileUpdater70(IDbConnection conn, IDbTransaction tran)
{
_connection = conn;
_transaction = tran;
_profiles = GetProfiles();
}
public void Commit()
{
foreach (var profile in _changedProfiles)
{ {
if (profile.Items.Any(p => p.Quality == 0)) continue; using (var updateProfileCmd = _connection.CreateCommand())
profile.Items.Insert(0, new ProfileItem71
{
Quality = 0,
Allowed = false
});
var itemsJson = profile.Items.ToJson();
using (IDbCommand updateProfileCmd = conn.CreateCommand())
{ {
updateProfileCmd.Transaction = tran; updateProfileCmd.Transaction = _transaction;
updateProfileCmd.CommandText = "UPDATE Profiles SET Items = ? WHERE Id = ?"; updateProfileCmd.CommandText = "UPDATE Profiles SET Name = ?, Cutoff = ?, Items = ?, Language = ? WHERE Id = ?";
updateProfileCmd.AddParameter(itemsJson); updateProfileCmd.AddParameter(profile.Name);
updateProfileCmd.AddParameter(profile.Cutoff);
updateProfileCmd.AddParameter(profile.Items.ToJson());
updateProfileCmd.AddParameter(profile.Language);
updateProfileCmd.AddParameter(profile.Id); updateProfileCmd.AddParameter(profile.Id);
updateProfileCmd.ExecuteNonQuery(); updateProfileCmd.ExecuteNonQuery();
} }
} }
_changedProfiles.Clear();
} }
private List<Profile71> GetProfiles(IDbConnection conn, IDbTransaction tran) public void PrependQuality(int quality)
{ {
var profiles = new List<Profile71>(); foreach (var profile in _profiles)
using (IDbCommand getProfilesCmd = conn.CreateCommand())
{ {
getProfilesCmd.Transaction = tran; if (profile.Items.Any(v => v.Quality == quality)) continue;
getProfilesCmd.CommandText = @"SELECT Id, Items FROM Profiles";
using (IDataReader profileReader = getProfilesCmd.ExecuteReader()) profile.Items.Insert(0, new ProfileItem70
{
Quality = quality,
Allowed = false
});
_changedProfiles.Add(profile);
}
}
public void AppendQuality(int quality)
{
foreach (var profile in _profiles)
{
if (profile.Items.Any(v => v.Quality == quality)) continue;
profile.Items.Add(new ProfileItem70
{
Quality = quality,
Allowed = false
});
_changedProfiles.Add(profile);
}
}
public void SplitQualityPrepend(int find, int quality)
{
foreach (var profile in _profiles)
{
if (profile.Items.Any(v => v.Quality == quality)) continue;
var findIndex = profile.Items.FindIndex(v => v.Quality == find);
profile.Items.Insert(findIndex, new ProfileItem70
{
Quality = quality,
Allowed = profile.Items[findIndex].Allowed
});
if (profile.Cutoff == find)
{
profile.Cutoff = quality;
}
_changedProfiles.Add(profile);
}
}
public void SplitQualityAppend(int find, int quality)
{
foreach (var profile in _profiles)
{
if (profile.Items.Any(v => v.Quality == quality)) continue;
var findIndex = profile.Items.FindIndex(v => v.Quality == find);
profile.Items.Insert(findIndex + 1, new ProfileItem70
{
Quality = quality,
Allowed = false
});
_changedProfiles.Add(profile);
}
}
private List<Profile70> GetProfiles()
{
var profiles = new List<Profile70>();
using (var getProfilesCmd = _connection.CreateCommand())
{
getProfilesCmd.Transaction = _transaction;
getProfilesCmd.CommandText = @"SELECT Id, Name, Cutoff, Items, Language FROM Profiles";
using (var profileReader = getProfilesCmd.ExecuteReader())
{ {
while (profileReader.Read()) while (profileReader.Read())
{ {
var id = profileReader.GetInt32(0); profiles.Add(new Profile70
var itemsJson = profileReader.GetString(1);
var items = Json.Deserialize<List<ProfileItem71>>(itemsJson);
profiles.Add(new Profile71
{ {
Id = id, Id = profileReader.GetInt32(0),
Items = items Name = profileReader.GetString(1),
Cutoff = profileReader.GetInt32(2),
Items = Json.Deserialize<List<ProfileItem70>>(profileReader.GetString(3)),
Language = profileReader.GetInt32(4)
}); });
} }
} }
@ -74,17 +176,5 @@ namespace NzbDrone.Core.Datastore.Migration
return profiles; return profiles;
} }
private class Profile71
{
public int Id { get; set; }
public List<ProfileItem71> Items { get; set; }
}
private class ProfileItem71
{
public int Quality { get; set; }
public bool Allowed { get; set; }
}
} }
} }

View File

@ -52,7 +52,7 @@ namespace NzbDrone.Core.Datastore.Migration
using (var updateHistoryCmd = conn.CreateCommand()) using (var updateHistoryCmd = conn.CreateCommand())
{ {
updateHistoryCmd.Transaction = tran; updateHistoryCmd.Transaction = tran;
updateHistoryCmd.CommandText = @"UPDATE History SET DownloadId = ? , Data = ? WHERE Id = ?"; updateHistoryCmd.CommandText = @"UPDATE History SET DownloadId = ?, Data = ? WHERE Id = ?";
updateHistoryCmd.AddParameter(downloadId); updateHistoryCmd.AddParameter(downloadId);
updateHistoryCmd.AddParameter(dic.ToJson()); updateHistoryCmd.AddParameter(dic.ToJson());
@ -63,4 +63,17 @@ namespace NzbDrone.Core.Datastore.Migration
} }
} }
} }
public class History72
{
public int EpisodeId { get; set; }
public int SeriesId { get; set; }
public string SourceTitle { get; set; }
public string Quality { get; set; }
public DateTime Date { get; set; }
public int EventType { get; set; }
public Dictionary<string, string> Data { get; set; }
public string DownloadId { get; set; }
}
} }

View File

@ -1,4 +1,5 @@
using FluentMigrator; using System;
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework; using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration namespace NzbDrone.Core.Datastore.Migration
@ -18,5 +19,11 @@ namespace NzbDrone.Core.Datastore.Migration
} }
} }
public class ScheduledTasks75
{
public int Id { get; set; }
public string TypeName { get; set; }
public int Interval { get; set; }
public DateTime LastExecution { get; set; }
}
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Data; using System.Data;
using System.Linq; using System.Linq;
using FluentMigrator; using FluentMigrator;
using Newtonsoft.Json.Linq;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Migration.Framework; using NzbDrone.Core.Datastore.Migration.Framework;
@ -53,4 +54,41 @@ namespace NzbDrone.Core.Datastore.Migration
} }
} }
} }
public class DownloadClientDefinition81
{
public int Id { get; set; }
public bool Enable { get; set; }
public string Name { get; set; }
public string Implementation { get; set; }
public JObject Settings { get; set; }
public string ConfigContract { get; set; }
}
public class SabnzbdSettings81
{
public string Host { get; set; }
public int Port { get; set; }
public string ApiKey { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string TvCategory { get; set; }
public int RecentTvPriority { get; set; }
public int OlderTvPriority { get; set; }
public bool UseSsl { get; set; }
}
public class TransmissionSettings81
{
public string Host { get; set; }
public int Port { get; set; }
public string UrlBase { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string TvCategory { get; set; }
public string TvDirectory { get; set; }
public int RecentTvPriority { get; set; }
public int OlderTvPriority { get; set; }
public bool UseSsl { get; set; }
}
} }

View File

@ -15,4 +15,13 @@ namespace NzbDrone.Core.Datastore.Migration
Execute.Sql("UPDATE QualityDefinitions SET MaxSize = NULL WHERE Quality = 10 OR MaxSize = 0"); Execute.Sql("UPDATE QualityDefinitions SET MaxSize = NULL WHERE Quality = 10 OR MaxSize = 0");
} }
} }
public class QualityDefinition84
{
public int Id { get; set; }
public int Quality { get; set; }
public string Title { get; set; }
public int? MinSize { get; set; }
public int? MaxSize { get; set; }
}
} }

View File

@ -58,4 +58,16 @@ namespace NzbDrone.Core.Datastore.Migration
} }
} }
} }
public class DelugeSettings85
{
public string Host { get; set; }
public int Port { get; set; }
public string UrlBase { get; set; }
public string Password { get; set; }
public string TvCategory { get; set; }
public int RecentTvPriority { get; set; }
public int OlderTvPriority { get; set; }
public bool UseSsl { get; set; }
}
} }

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using FluentMigrator; using FluentMigrator;
using Newtonsoft.Json.Linq;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Migration.Framework; using NzbDrone.Core.Datastore.Migration.Framework;
@ -34,7 +35,7 @@ namespace NzbDrone.Core.Datastore.Migration
{ {
var deviceId = settings.GetValueOrDefault("deviceId", "") as string; var deviceId = settings.GetValueOrDefault("deviceId", "") as string;
settings.Add("deviceIds", deviceId); settings.Add("deviceIds", new[] { deviceId });
settings.Remove("deviceId"); settings.Remove("deviceId");
using (var updateCmd = conn.CreateCommand()) using (var updateCmd = conn.CreateCommand())
@ -52,4 +53,25 @@ namespace NzbDrone.Core.Datastore.Migration
} }
} }
} }
public class Notification86
{
public int Id { get; set; }
public string Name { get; set; }
public int OnGrab { get; set; }
public int OnDownload { get; set; }
public JObject Settings { get; set; }
public string Implementation { get; set; }
public string ConfigContract { get; set; }
public int OnUpgrade { get; set; }
public List<int> Tags { get; set; }
}
public class PushBulletSettings86
{
public string ApiKey { get; set; }
public string[] DeviceIds { get; set; }
public string ChannelTags { get; set; }
public string SenderId { get; set; }
}
} }

View File

@ -69,4 +69,12 @@ namespace NzbDrone.Core.Datastore.Migration
} }
} }
} }
public class PushBulletSettings88
{
public string ApiKey { get; set; }
public string[] DeviceIds { get; set; }
public string[] ChannelTags { get; set; }
public string SenderId { get; set; }
}
} }

View File

@ -1,4 +1,5 @@
using FluentMigrator; using FluentMigrator;
using Newtonsoft.Json.Linq;
using NzbDrone.Core.Datastore.Migration.Framework; using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration namespace NzbDrone.Core.Datastore.Migration
@ -15,4 +16,21 @@ namespace NzbDrone.Core.Datastore.Migration
); );
} }
} }
public class IndexerDefinition90
{
public int Id { get; set; }
public string Name { get; set; }
public JObject Settings { get; set; }
public string Implementation { get; set; }
public string ConfigContract { get; set; }
public bool EnableRss { get; set; }
public bool EnableSearch { get; set; }
}
public class KickassTorrentsSettings90
{
public string BaseUrl { get; set; }
public bool VerifiedOnly { get; set; }
}
} }

View File

@ -5,14 +5,14 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
public class MigrationContext public class MigrationContext
{ {
public MigrationType MigrationType { get; private set; } public MigrationType MigrationType { get; private set; }
public long? DesiredVersion { get; set; }
public Action<NzbDroneMigrationBase> BeforeMigration { get; private set; } public Action<NzbDroneMigrationBase> BeforeMigration { get; set; }
public MigrationContext(MigrationType migrationType, Action<NzbDroneMigrationBase> beforeAction) public MigrationContext(MigrationType migrationType, long? desiredVersion = null)
{ {
MigrationType = migrationType; MigrationType = migrationType;
DesiredVersion = desiredVersion;
BeforeMigration = beforeAction;
} }
} }
} }

View File

@ -8,7 +8,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
{ {
public interface IMigrationController public interface IMigrationController
{ {
void MigrateToLatest(string connectionString, MigrationType migrationType, Action<NzbDroneMigrationBase> beforeMigration); void Migrate(string connectionString, MigrationContext migrationContext);
} }
public class MigrationController : IMigrationController public class MigrationController : IMigrationController
@ -20,7 +20,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
_announcer = announcer; _announcer = announcer;
} }
public void MigrateToLatest(string connectionString, MigrationType migrationType, Action<NzbDroneMigrationBase> beforeMigration) public void Migrate(string connectionString, MigrationContext migrationContext)
{ {
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
@ -28,17 +28,25 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
var assembly = Assembly.GetExecutingAssembly(); var assembly = Assembly.GetExecutingAssembly();
var migrationContext = new RunnerContext(_announcer) var runnerContext = new RunnerContext(_announcer)
{ {
Namespace = "NzbDrone.Core.Datastore.Migration", Namespace = "NzbDrone.Core.Datastore.Migration",
ApplicationContext = new MigrationContext(migrationType, beforeMigration) ApplicationContext = migrationContext
}; };
var options = new MigrationOptions { PreviewOnly = false, Timeout = 60 }; var options = new MigrationOptions { PreviewOnly = false, Timeout = 60 };
var factory = new NzbDroneSqliteProcessorFactory(); var factory = new NzbDroneSqliteProcessorFactory();
var processor = factory.Create(connectionString, _announcer, options); var processor = factory.Create(connectionString, _announcer, options);
var runner = new MigrationRunner(assembly, migrationContext, processor); var runner = new MigrationRunner(assembly, runnerContext, processor);
runner.MigrateUp(true);
if (migrationContext.DesiredVersion.HasValue)
{
runner.MigrateUp(migrationContext.DesiredVersion.Value, true);
}
else
{
runner.MigrateUp(true);
}
sw.Stop(); sw.Stop();