diff --git a/product/roundhouse.console/Program.cs b/product/roundhouse.console/Program.cs index f7e439d7..14f833c3 100644 --- a/product/roundhouse.console/Program.cs +++ b/product/roundhouse.console/Program.cs @@ -284,6 +284,10 @@ private static void parse_arguments_and_set_up_configuration(ConfigurationProper .Add("dc|dnc|donotcreatedatabase", "DoNotCreateDatabase - This instructs RH to not create a database if it does not exists. Defaults to false.", option => configuration.DoNotCreateDatabase = option != null) + //don't alter the database (e.g. to avoid needing master DB login) + .Add("da|dna|donotalterdatabase", + "DoNotAlterDatabase - This instructs RH to not alter the database. Defaults to false.", + option => configuration.DoNotAlterDatabase = option != null) //output .Add("o=|output=|outputpath=", string.Format( diff --git a/product/roundhouse.tasks/Roundhouse.cs b/product/roundhouse.tasks/Roundhouse.cs index 348bfd1c..c0cf2a20 100644 --- a/product/roundhouse.tasks/Roundhouse.cs +++ b/product/roundhouse.tasks/Roundhouse.cs @@ -126,6 +126,8 @@ bool ITask.Execute() public bool DoNotCreateDatabase { get; set; } + public bool DoNotAlterDatabase { get; set; } + public string OutputPath { get; set; } public bool WarnOnOneTimeScriptChanges { get; set; } diff --git a/product/roundhouse.tests/DummyDatabase.cs b/product/roundhouse.tests/DummyDatabase.cs new file mode 100644 index 00000000..cf03146f --- /dev/null +++ b/product/roundhouse.tests/DummyDatabase.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace roundhouse.tests +{ + class DummyDatabase + { + } +} diff --git a/product/roundhouse.tests/MockKnownFolders.cs b/product/roundhouse.tests/MockKnownFolders.cs new file mode 100644 index 00000000..4321fc85 --- /dev/null +++ b/product/roundhouse.tests/MockKnownFolders.cs @@ -0,0 +1,102 @@ +using roundhouse.folders; + +namespace roundhouse.tests +{ + class MockKnownFolders: KnownFolders + { + public MigrationsFolder alter_database + { + get { return get_migrationsfolder("alter_database"); } + } + + public MigrationsFolder run_after_create_database + { + get { return get_migrationsfolder("run_after_create_database"); } + } + public MigrationsFolder run_before_up + { + get { return get_migrationsfolder("run_before_up"); } + } + public MigrationsFolder up + { + get { return get_migrationsfolder("up"); } + } + public MigrationsFolder down + { + get { return get_migrationsfolder("down"); } + } + public MigrationsFolder run_first_after_up + { + get { return get_migrationsfolder("run_first_afte_up"); } + } + public MigrationsFolder functions + { + get { return get_migrationsfolder("functions"); } + } + public MigrationsFolder views + { + get { return get_migrationsfolder("views"); } + } + public MigrationsFolder sprocs + { + get { return get_migrationsfolder("sprocs"); } + } + public MigrationsFolder triggers + { + get { return get_migrationsfolder("triggers"); } + } + public MigrationsFolder indexes + { + get { return get_migrationsfolder("indexes"); } + } + public MigrationsFolder run_after_other_any_time_scripts + { + get { return get_migrationsfolder("run_after_other_any_time_scrips"); } + } + public MigrationsFolder permissions + { + get { return get_migrationsfolder("permissions"); } + } + public MigrationsFolder before_migration + { + get { return get_migrationsfolder("before_migration"); } + } + public MigrationsFolder after_migration + { + get { return get_migrationsfolder("after_migration"); } + } + public Folder change_drop + { + get { return get_migrationsfolder("change_drop"); } + } + + private MigrationsFolder get_migrationsfolder(string name) + { + return new MockMigrationsFolder(name); + } + + public class MockMigrationsFolder: MigrationsFolder + { + public MockMigrationsFolder(string folder_name) + { + this.folder_name = folder_name; + this.folder_path = "folder_prefix\\" + folder_name; + this.folder_full_path = "drive_and_source_structure\\" + folder_path; + this.friendly_name = "friendly " + folder_name; + } + + public string folder_name { get; set; } + + public string folder_path { get; private set; } + + public string folder_full_path { get; private set; } + + public bool should_run_items_in_folder_once { get; private set; } + + public bool should_run_items_in_folder_every_time { get; private set; } + + public string friendly_name { get; private set; } + } + + } +} diff --git a/product/roundhouse.tests/infrastructure/logging/LogSpecs.cs b/product/roundhouse.tests/infrastructure/logging/LogSpecs.cs index 09185bf9..6af77d11 100644 --- a/product/roundhouse.tests/infrastructure/logging/LogSpecs.cs +++ b/product/roundhouse.tests/infrastructure/logging/LogSpecs.cs @@ -56,7 +56,7 @@ public override void Context() public override void Because() { - result = Log.bound_to(typeof(StructureMapContainer)); + result = Log.bound_to(new StructureMapContainer(null)); } [Observation] diff --git a/product/roundhouse.tests/migrators/DefaultDatabaseMigratorSpecs.cs b/product/roundhouse.tests/migrators/DefaultDatabaseMigratorSpecs.cs index 959ced6b..75c47057 100644 --- a/product/roundhouse.tests/migrators/DefaultDatabaseMigratorSpecs.cs +++ b/product/roundhouse.tests/migrators/DefaultDatabaseMigratorSpecs.cs @@ -1,13 +1,11 @@ +using roundhouse.consoles; using roundhouse.databases; +using roundhouse.environments; +using roundhouse.migrators; using Should; -namespace roundhouse.tests.infrastructure.containers +namespace roundhouse.tests.migrators { - using consoles; - - using environments; - using migrators; - public class DefaultDatabaseMigratorSpecs { public abstract class concern_for_database_migrator : TinySpec diff --git a/product/roundhouse.tests/packages.config b/product/roundhouse.tests/packages.config index 29659638..1d57dcdf 100644 --- a/product/roundhouse.tests/packages.config +++ b/product/roundhouse.tests/packages.config @@ -1,4 +1,4 @@ - + @@ -7,5 +7,5 @@ - + \ No newline at end of file diff --git a/product/roundhouse.tests/roundhouse.tests.csproj b/product/roundhouse.tests/roundhouse.tests.csproj index 5f405a39..fa0b2aed 100644 --- a/product/roundhouse.tests/roundhouse.tests.csproj +++ b/product/roundhouse.tests/roundhouse.tests.csproj @@ -46,6 +46,7 @@ x86 AllRules.ruleset false + 5 pdbonly @@ -70,7 +71,7 @@ - ..\..\packages\Castle.Core.4.1.0\lib\net45\Castle.Core.dll + ..\..\packages\Castle.Core.4.1.0\lib\net35\Castle.Core.dll False @@ -80,7 +81,7 @@ ..\..\packages\Moq.4.7.49\lib\net45\Moq.dll - ..\..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll + ..\..\packages\NUnit.3.7.1\lib\net35\nunit.framework.dll ..\..\packages\Should.1.1.12.0\lib\Should.dll @@ -107,6 +108,7 @@ Properties\SolutionVersion.cs + @@ -120,9 +122,11 @@ + + diff --git a/product/roundhouse.tests/runners/RoundhouseMigratorRunnerSpecs.cs b/product/roundhouse.tests/runners/RoundhouseMigratorRunnerSpecs.cs new file mode 100644 index 00000000..a3468b29 --- /dev/null +++ b/product/roundhouse.tests/runners/RoundhouseMigratorRunnerSpecs.cs @@ -0,0 +1,149 @@ +using Moq; +using roundhouse.consoles; +using roundhouse.databases; +using roundhouse.environments; +using roundhouse.infrastructure.containers; +using roundhouse.infrastructure.containers.custom; +using roundhouse.infrastructure.filesystem; +using roundhouse.infrastructure.logging; +using roundhouse.infrastructure.logging.custom; +using roundhouse.migrators; +using roundhouse.resolvers; +using roundhouse.runners; + +namespace roundhouse.tests.runners +{ + public class RoundhouseMigratorRunnerSpecs + { + public abstract class concern_for_migrator_runner : TinySpec + { + protected object result; + protected DefaultEnvironment environment; + protected readonly DefaultConfiguration configuration; + private RoundhouseMigrationRunner default_database_migrator; + + protected Mock database_migrator_mock; + + protected concern_for_migrator_runner() + { + configuration = new DefaultConfiguration + { + EnvironmentName = "TEST", + Drop = false , + Silent = true + }; + + var database_mock = new Mock(); + var filesystem_mock = new Mock(); + var version_resolver_mock = new Mock(); + + var known_folders_mock = new MockKnownFolders(); + + var environment_mock = Mock.Of(); + + database_migrator_mock = new Mock(); + database_migrator_mock.Setup(m => m.database).Returns(database_mock.Object); + + default_database_migrator = + new RoundhouseMigrationRunner( + configuration.RepositoryPath, + environment_mock, + known_folders_mock, + filesystem_mock.Object, + database_migrator_mock.Object, + version_resolver_mock.Object, + configuration.Silent, + configuration.Drop, + configuration.DoNotCreateDatabase, + configuration.WithTransaction, + configuration.RecoveryModeSimple, + configuration); + + var container_mock = new Mock(); + + setup_logging(container_mock); + + var the_container = container_mock.Object; + Container.initialize_with(the_container); + } + + private static void setup_logging(Mock container_mock) + { + var mock_log_factory = new Mock(); + var log_factory = mock_log_factory.Object; + + var logger = get_logger(); + + mock_log_factory.Setup(x => x.create_logger_bound_to(typeof(RoundhouseMigrationRunner))) + .Returns(logger); + + container_mock.Setup(x => x.Resolve()) + .Returns(log_factory); + } + + private static Logger get_logger() + { + return new TraceLogger(true); + } + + public override void AfterEachSpec() + { + Container.initialize_with(null); + } + + protected override RoundhouseMigrationRunner sut + { + get { return default_database_migrator;} + set { default_database_migrator = value; } + } + } + + [Concern(typeof(RoundhouseMigrationRunner))] + public class when_setting_do_not_alter_database : concern_for_migrator_runner + { + public when_setting_do_not_alter_database(): base() + { + configuration.DoNotAlterDatabase = true; + } + + public override void Context() + {} + + public override void Because() + { + sut.run(); + } + + [Observation] + public void no_connection_to_admin_connection_is_made() + { + database_migrator_mock.Verify(m => m.open_admin_connection(), Times.Never); + } + } + + [Concern(typeof(RoundhouseMigrationRunner))] + public class when_not_setting_do_not_alter_database : concern_for_migrator_runner + { + + public when_not_setting_do_not_alter_database(): base() + { + configuration.DoNotAlterDatabase = false; + sut.run(); + } + + public override void Context() + {} + + public override void Because() + { + } + + [Observation] + public void a_connection_to_admin_connection_is_made() + { + database_migrator_mock.Verify(m => m.open_admin_connection(), Times.Once); + } + } + + } +} \ No newline at end of file diff --git a/product/roundhouse/consoles/DefaultConfiguration.cs b/product/roundhouse/consoles/DefaultConfiguration.cs index 751a069f..84f9046a 100644 --- a/product/roundhouse/consoles/DefaultConfiguration.cs +++ b/product/roundhouse/consoles/DefaultConfiguration.cs @@ -53,6 +53,7 @@ public sealed class DefaultConfiguration : ConfigurationPropertyHolder public string DatabaseType { get; set; } public bool Drop { get; set; } public bool DoNotCreateDatabase { get; set; } + public bool DoNotAlterDatabase { get; set; } public bool WithTransaction { get; set; } public RecoveryMode RecoveryMode { get; set; } [Obsolete("Use RecoveryMode = Simple")] diff --git a/product/roundhouse/folders/DefaultMigrationsFolder.cs b/product/roundhouse/folders/DefaultMigrationsFolder.cs index d4981a2f..c4196ff8 100644 --- a/product/roundhouse/folders/DefaultMigrationsFolder.cs +++ b/product/roundhouse/folders/DefaultMigrationsFolder.cs @@ -1,19 +1,19 @@ -namespace roundhouse.folders -{ - using infrastructure.filesystem; - - public class DefaultMigrationsFolder : DefaultFolder, MigrationsFolder - { - public DefaultMigrationsFolder(FileSystemAccess file_system, string folder_path, string folder_name, bool should_run_items_in_folder_once,bool should_run_items_every_time, string friendly_name) - : base(file_system, folder_path, folder_name) - { - this.should_run_items_in_folder_once = should_run_items_in_folder_once; +namespace roundhouse.folders +{ + using infrastructure.filesystem; + + public class DefaultMigrationsFolder : DefaultFolder, MigrationsFolder + { + public DefaultMigrationsFolder(FileSystemAccess file_system, string folder_path, string folder_name, bool should_run_items_in_folder_once,bool should_run_items_every_time, string friendly_name) + : base(file_system, folder_path, folder_name) + { + this.should_run_items_in_folder_once = should_run_items_in_folder_once; should_run_items_in_folder_every_time = should_run_items_every_time; this.friendly_name = friendly_name; - } - - public bool should_run_items_in_folder_once { get; private set; } + } + + public bool should_run_items_in_folder_once { get; private set; } public bool should_run_items_in_folder_every_time { get; private set; } public string friendly_name { get; private set; } - } + } } \ No newline at end of file diff --git a/product/roundhouse/folders/MigrationsFolder.cs b/product/roundhouse/folders/MigrationsFolder.cs index f69b28f7..ced76af8 100644 --- a/product/roundhouse/folders/MigrationsFolder.cs +++ b/product/roundhouse/folders/MigrationsFolder.cs @@ -1,9 +1,9 @@ -namespace roundhouse.folders -{ - public interface MigrationsFolder : Folder - { - bool should_run_items_in_folder_once { get; } +namespace roundhouse.folders +{ + public interface MigrationsFolder : Folder + { + bool should_run_items_in_folder_once { get; } bool should_run_items_in_folder_every_time { get; } string friendly_name { get; } - } + } } \ No newline at end of file diff --git a/product/roundhouse/infrastructure.app/ConfigurationPropertyHolder.cs b/product/roundhouse/infrastructure.app/ConfigurationPropertyHolder.cs index 8249fd43..ad1bcec9 100644 --- a/product/roundhouse/infrastructure.app/ConfigurationPropertyHolder.cs +++ b/product/roundhouse/infrastructure.app/ConfigurationPropertyHolder.cs @@ -53,6 +53,7 @@ public interface ConfigurationPropertyHolder string DatabaseType { get; set; } bool Drop { get; set; } bool DoNotCreateDatabase { get; set; } + bool DoNotAlterDatabase { get; set; } bool WithTransaction { get; set; } RecoveryMode RecoveryMode { get; set; } [Obsolete("Use RecoveryMode = Simple")] diff --git a/product/roundhouse/infrastructure/logging/Log.cs b/product/roundhouse/infrastructure/logging/Log.cs index 102b2adb..886d0acf 100644 --- a/product/roundhouse/infrastructure/logging/Log.cs +++ b/product/roundhouse/infrastructure/logging/Log.cs @@ -15,7 +15,7 @@ public static Logger bound_to(object object_that_needs_logging) Logger logger; try { - logger = Container.get_an_instance_of().create_logger_bound_to(object_that_needs_logging); + logger = Container.get_an_instance_of().create_logger_bound_to(object_that_needs_logging.GetType()); } catch(Exception) { diff --git a/product/roundhouse/infrastructure/logging/custom/TraceLogger.cs b/product/roundhouse/infrastructure/logging/custom/TraceLogger.cs new file mode 100644 index 00000000..53a823dc --- /dev/null +++ b/product/roundhouse/infrastructure/logging/custom/TraceLogger.cs @@ -0,0 +1,51 @@ +using System.Diagnostics; + +namespace roundhouse.infrastructure.logging.custom +{ + public class TraceLogger : Logger + { + private readonly bool debugging; + + public TraceLogger() : this(false) { } + + public TraceLogger(bool debugging) + { + this.debugging = debugging; + } + + private void log_message(string message) + { + Trace.WriteLine(message); + } + + public void log_a_debug_event_containing(string message, params object[] args) + { + if (debugging) log_message("[DEBUG]: " + string.Format(message, args)); + } + + public void log_an_info_event_containing(string message, params object[] args) + { + log_message("[INFO]: " + string.Format(message, args)); + } + + public void log_a_warning_event_containing(string message, params object[] args) + { + log_message("[WARN]: " + string.Format(message, args)); + } + + public void log_an_error_event_containing(string message, params object[] args) + { + log_message("[ERROR]: " + string.Format(message, args)); + } + + public void log_a_fatal_event_containing(string message, params object[] args) + { + log_message("[FATAL]: " + string.Format(message, args)); + } + + public object underlying_type + { + get { return new object(); } + } + } +} \ No newline at end of file diff --git a/product/roundhouse/roundhouse.csproj b/product/roundhouse/roundhouse.csproj index 5c9d2846..1609a492 100644 --- a/product/roundhouse/roundhouse.csproj +++ b/product/roundhouse/roundhouse.csproj @@ -46,6 +46,7 @@ x86 AllRules.ruleset false + 5 none @@ -135,6 +136,7 @@ + diff --git a/product/roundhouse/runners/RoundhouseMigrationRunner.cs b/product/roundhouse/runners/RoundhouseMigrationRunner.cs index d6d37078..fc2f268e 100644 --- a/product/roundhouse/runners/RoundhouseMigrationRunner.cs +++ b/product/roundhouse/runners/RoundhouseMigrationRunner.cs @@ -11,7 +11,7 @@ namespace roundhouse.runners using infrastructure.logging; using migrators; using resolvers; - using environments; + using roundhouse.environments; public sealed class RoundhouseMigrationRunner : IRunner { @@ -24,6 +24,7 @@ public sealed class RoundhouseMigrationRunner : IRunner public bool silent { get; set; } public bool dropping_the_database { get; set; } private readonly bool dont_create_the_database; + private readonly bool dont_alter_the_database; private bool run_in_a_transaction; private readonly bool use_simple_recovery; private readonly ConfigurationPropertyHolder configuration; @@ -131,10 +132,13 @@ public void run() Log.bound_to(this).log_an_info_event_containing("{0}", "=".PadRight(50, '=')); run_out_side_of_transaction_folder(known_folders.before_migration, version_id, new_version); - - database_migrator.open_admin_connection(); - log_and_traverse(known_folders.alter_database, version_id, new_version, ConnectionType.Admin); - database_migrator.close_admin_connection(); + + if (!configuration.DoNotAlterDatabase) + { + database_migrator.open_admin_connection(); + log_and_traverse(known_folders.alter_database, version_id, new_version, ConnectionType.Admin); + database_migrator.close_admin_connection(); + } if (database_was_created) { diff --git a/roundhouse.sln b/roundhouse.sln index 69483763..e532848e 100644 --- a/roundhouse.sln +++ b/roundhouse.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.27004.2002 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{807C6B2C-496F-4A41-ABFE-EA5478EB9CFF}" EndProject @@ -153,4 +153,7 @@ Global {41CE538E-E6F1-4AB6-AB66-508DEF669A39} = {BCFAF88B-B6C0-48C1-B23E-FCC95B75588C} {3447F080-CF50-4B02-9521-671E7AEE8D34} = {BCFAF88B-B6C0-48C1-B23E-FCC95B75588C} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {54AD825C-DC48-4C69-88E5-356B43AC3674} + EndGlobalSection EndGlobal