From 4ec37b9d3a8593eb6149912b5c59db07726289a7 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 13 Nov 2014 13:05:27 +1100 Subject: [PATCH] Fixes: U4-5391 Create config to explicitly set the 'base url' for a website that is not running as a load balanced site - used for scheduled tasks/publishing/keepalive --- .../UmbracoSettings/IScheduledTasksSection.cs | 2 + .../UmbracoSettings/ScheduledTasksElement.cs | 6 + .../Sync/ServerEnvironmentHelper.cs | 34 +- .../GlobalSettingsTests.cs | 237 ++- .../PluginControllerAreaTests.cs | 177 ++- .../DistributedCacheTests.cs | 419 +++--- .../QueryableExtensionTests.cs | 320 ++--- .../{ => Macros}/MacroEngineFactoryTests.cs | 276 ++-- .../HtmlHelperExtensionMethodsTests.cs | 64 +- .../{ => Plugins}/PluginManagerExtensions.cs | 32 +- .../{ => Plugins}/PluginManagerTests.cs | 778 +++++----- .../{ => Plugins}/TypeFinderTests.cs | 1277 ++++++++--------- .../{ => Plugins}/TypeHelperTests.cs | 149 +- .../ServerEnvironmentHelperTests.cs | 92 ++ .../BaseContentTreeTests.cs | 250 ++-- .../BaseMediaTreeTests.cs | 128 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 29 +- src/Umbraco.Web/Scheduling/KeepAlive.cs | 2 +- .../Scheduling/ScheduledPublishing.cs | 2 +- 19 files changed, 2178 insertions(+), 2096 deletions(-) rename src/Umbraco.Tests/{ => Configurations}/GlobalSettingsTests.cs (95%) rename src/Umbraco.Tests/{Surface => Controllers}/PluginControllerAreaTests.cs (92%) rename src/Umbraco.Tests/{Sync => DistributedCache}/DistributedCacheTests.cs (89%) rename src/Umbraco.Tests/{Dynamics => DynamicsAndReflection}/QueryableExtensionTests.cs (95%) rename src/Umbraco.Tests/{ => Macros}/MacroEngineFactoryTests.cs (95%) rename src/Umbraco.Tests/{ => Mvc}/HtmlHelperExtensionMethodsTests.cs (93%) rename src/Umbraco.Tests/{ => Plugins}/PluginManagerExtensions.cs (89%) rename src/Umbraco.Tests/{ => Plugins}/PluginManagerTests.cs (96%) rename src/Umbraco.Tests/{ => Plugins}/TypeFinderTests.cs (97%) rename src/Umbraco.Tests/{ => Plugins}/TypeHelperTests.cs (90%) create mode 100644 src/Umbraco.Tests/ServerEnvironmentHelperTests.cs rename src/Umbraco.Tests/{Trees => TreesAndSections}/BaseContentTreeTests.cs (92%) rename src/Umbraco.Tests/{Trees => TreesAndSections}/BaseMediaTreeTests.cs (93%) diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IScheduledTasksSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IScheduledTasksSection.cs index 9d01549a5c..8b25e11e91 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IScheduledTasksSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IScheduledTasksSection.cs @@ -5,5 +5,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings public interface IScheduledTasksSection : IUmbracoConfigurationSection { IEnumerable Tasks { get; } + + string BaseUrl { get; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ScheduledTasksElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ScheduledTasksElement.cs index 3571e2d7ed..0598aeec9e 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ScheduledTasksElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ScheduledTasksElement.cs @@ -16,5 +16,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings { get { return Tasks; } } + + [ConfigurationProperty("baseUrl", IsRequired = false, DefaultValue = null)] + public string BaseUrl + { + get { return (string)base["baseUrl"]; } + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Sync/ServerEnvironmentHelper.cs b/src/Umbraco.Core/Sync/ServerEnvironmentHelper.cs index 48f3cfecd6..52480a1ca7 100644 --- a/src/Umbraco.Core/Sync/ServerEnvironmentHelper.cs +++ b/src/Umbraco.Core/Sync/ServerEnvironmentHelper.cs @@ -26,22 +26,18 @@ namespace Umbraco.Core.Sync if (status == CurrentServerEnvironmentStatus.Single) { - // single install, return null if no original url, else use original url as base + // single install, return null if no config/original url, else use config/original url as base // use http or https as appropriate - return string.IsNullOrWhiteSpace(appContext.OriginalRequestUrl) - ? null // not initialized yet - : string.Format("http{0}://{1}", GlobalSettings.UseSSL ? "s" : "", appContext.OriginalRequestUrl); + return GetBaseUrl(appContext, settings); } var servers = settings.DistributedCall.Servers.ToArray(); if (servers.Any() == false) { - // cannot be determined, return null if no original url, else use original url as base + // cannot be determined, return null if no config/original url, else use config/original url as base // use http or https as appropriate - return string.IsNullOrWhiteSpace(appContext.OriginalRequestUrl) - ? null // not initialized yet - : string.Format("http{0}://{1}", GlobalSettings.UseSSL ? "s" : "", appContext.OriginalRequestUrl); + return GetBaseUrl(appContext, settings); } foreach (var server in servers) @@ -66,11 +62,9 @@ namespace Umbraco.Core.Sync } } - // cannot be determined, return null if no original url, else use original url as base + // cannot be determined, return null if no config/original url, else use config/original url as base // use http or https as appropriate - return string.IsNullOrWhiteSpace(appContext.OriginalRequestUrl) - ? null // not initialized yet - : string.Format("http{0}://{1}", GlobalSettings.UseSSL ? "s" : "", appContext.OriginalRequestUrl); + return GetBaseUrl(appContext, settings); } /// @@ -119,5 +113,21 @@ namespace Umbraco.Core.Sync return CurrentServerEnvironmentStatus.Slave; } + + private static string GetBaseUrl(ApplicationContext appContext, IUmbracoSettingsSection settings) + { + return ( + // is config empty? + settings.ScheduledTasks.BaseUrl.IsNullOrWhiteSpace() + // is the orig req empty? + ? appContext.OriginalRequestUrl.IsNullOrWhiteSpace() + // we've got nothing + ? null + //the orig req url is not null, use that + : string.Format("http{0}://{1}", GlobalSettings.UseSSL ? "s" : "", appContext.OriginalRequestUrl) + // the config has been specified, use that + : string.Format("http{0}://{1}", GlobalSettings.UseSSL ? "s" : "", settings.ScheduledTasks.BaseUrl)) + .EnsureEndsWith('/'); + } } } \ No newline at end of file diff --git a/src/Umbraco.Tests/GlobalSettingsTests.cs b/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs similarity index 95% rename from src/Umbraco.Tests/GlobalSettingsTests.cs rename to src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs index 7f97466bae..b320c979ef 100644 --- a/src/Umbraco.Tests/GlobalSettingsTests.cs +++ b/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs @@ -1,120 +1,119 @@ -using System.Configuration; -using System.Web.Routing; -using NUnit.Framework; -using Umbraco.Core.Configuration; -using Umbraco.Core.IO; -using Umbraco.Tests.TestHelpers; -using System.Web.Mvc; - -namespace Umbraco.Tests -{ - [TestFixture] - public class GlobalSettingsTests : BaseWebTest - { - - public override void Initialize() - { - base.Initialize(); - SettingsForTests.UmbracoPath = "~/umbraco"; - } - - public override void TearDown() - { - //ensure this is reset - SystemDirectories.Root = null; - SettingsForTests.UmbracoPath = "~/umbraco"; - //reset the app config - base.TearDown(); - - } - - [Test] - public void Is_Debug_Mode() - { - Assert.That(Umbraco.Core.Configuration.GlobalSettings.DebugMode, Is.EqualTo(true)); - } - - [Ignore] - [Test] - public void Is_Version_From_Assembly_Correct() - { - Assert.That(UmbracoVersion.Current.ToString(3), Is.EqualTo("6.0.0")); - } - - [TestCase("~/umbraco", "/", "umbraco")] - [TestCase("~/umbraco", "/MyVirtualDir", "umbraco")] - [TestCase("~/customPath", "/MyVirtualDir/", "custompath")] - [TestCase("~/some-wacky/nestedPath", "/MyVirtualDir", "some-wacky-nestedpath")] - [TestCase("~/some-wacky/nestedPath", "/MyVirtualDir/NestedVDir/", "some-wacky-nestedpath")] - public void Umbraco_Mvc_Area(string path, string rootPath, string outcome) - { - SettingsForTests.UmbracoPath = path; - SystemDirectories.Root = rootPath; - Assert.AreEqual(outcome, Umbraco.Core.Configuration.GlobalSettings.UmbracoMvcArea); - } - - [TestCase("/umbraco/umbraco.aspx")] - [TestCase("/umbraco/editContent.aspx")] - [TestCase("/install/default.aspx")] - [TestCase("/install/")] - [TestCase("/install")] - [TestCase("/install/?installStep=asdf")] - [TestCase("/install/test.aspx")] - [TestCase("/config/splashes/booting.aspx")] - public void Is_Reserved_Path_Or_Url(string url) - { - Assert.IsTrue(Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url)); - } - - [TestCase("/umbraco_client/Tree/treeIcons.css")] - [TestCase("/umbraco_client/Tree/Themes/umbraco/style.css")] - [TestCase("/umbraco_client/scrollingmenu/style.css")] - [TestCase("/base/somebasehandler")] - [TestCase("/")] - [TestCase("/home.aspx")] - [TestCase("/umbraco-test")] - [TestCase("/install-test")] - [TestCase("/install.aspx")] - public void Is_Not_Reserved_Path_Or_Url(string url) - { - Assert.IsFalse(Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url)); - } - - - [TestCase("/Do/Not/match", false)] - [TestCase("/Umbraco/RenderMvcs", false)] - [TestCase("/Umbraco/RenderMvc", true)] - [TestCase("/Umbraco/RenderMvc/Index", true)] - [TestCase("/Umbraco/RenderMvc/Index/1234", true)] - [TestCase("/Umbraco/RenderMvc/Index/1234/9876", false)] - [TestCase("/api", true)] - [TestCase("/api/WebApiTest", true)] - [TestCase("/api/WebApiTest/1234", true)] - [TestCase("/api/WebApiTest/Index/1234", false)] - public void Is_Reserved_By_Route(string url, bool shouldMatch) - { - //reset the app config, we only want to test routes not the hard coded paths - Umbraco.Core.Configuration.GlobalSettings.ReservedPaths = ""; - Umbraco.Core.Configuration.GlobalSettings.ReservedUrls = ""; - - var routes = new RouteCollection(); - - routes.MapRoute( - "Umbraco_default", - "Umbraco/RenderMvc/{action}/{id}", - new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional }); - routes.MapRoute( - "WebAPI", - "api/{controller}/{id}", - new { controller = "WebApiTestController", action = "Index", id = UrlParameter.Optional }); - - - var context = new FakeHttpContextFactory(url); - - - Assert.AreEqual( - shouldMatch, - Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url, context.HttpContext, routes)); - } - } +using System.Web.Mvc; +using System.Web.Routing; +using NUnit.Framework; +using Umbraco.Core.Configuration; +using Umbraco.Core.IO; +using Umbraco.Tests.TestHelpers; + +namespace Umbraco.Tests.Configurations +{ + [TestFixture] + public class GlobalSettingsTests : BaseWebTest + { + + public override void Initialize() + { + base.Initialize(); + SettingsForTests.UmbracoPath = "~/umbraco"; + } + + public override void TearDown() + { + //ensure this is reset + SystemDirectories.Root = null; + SettingsForTests.UmbracoPath = "~/umbraco"; + //reset the app config + base.TearDown(); + + } + + [Test] + public void Is_Debug_Mode() + { + Assert.That(Umbraco.Core.Configuration.GlobalSettings.DebugMode, Is.EqualTo(true)); + } + + [Ignore] + [Test] + public void Is_Version_From_Assembly_Correct() + { + Assert.That(UmbracoVersion.Current.ToString(3), Is.EqualTo("6.0.0")); + } + + [TestCase("~/umbraco", "/", "umbraco")] + [TestCase("~/umbraco", "/MyVirtualDir", "umbraco")] + [TestCase("~/customPath", "/MyVirtualDir/", "custompath")] + [TestCase("~/some-wacky/nestedPath", "/MyVirtualDir", "some-wacky-nestedpath")] + [TestCase("~/some-wacky/nestedPath", "/MyVirtualDir/NestedVDir/", "some-wacky-nestedpath")] + public void Umbraco_Mvc_Area(string path, string rootPath, string outcome) + { + SettingsForTests.UmbracoPath = path; + SystemDirectories.Root = rootPath; + Assert.AreEqual(outcome, Umbraco.Core.Configuration.GlobalSettings.UmbracoMvcArea); + } + + [TestCase("/umbraco/umbraco.aspx")] + [TestCase("/umbraco/editContent.aspx")] + [TestCase("/install/default.aspx")] + [TestCase("/install/")] + [TestCase("/install")] + [TestCase("/install/?installStep=asdf")] + [TestCase("/install/test.aspx")] + [TestCase("/config/splashes/booting.aspx")] + public void Is_Reserved_Path_Or_Url(string url) + { + Assert.IsTrue(Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url)); + } + + [TestCase("/umbraco_client/Tree/treeIcons.css")] + [TestCase("/umbraco_client/Tree/Themes/umbraco/style.css")] + [TestCase("/umbraco_client/scrollingmenu/style.css")] + [TestCase("/base/somebasehandler")] + [TestCase("/")] + [TestCase("/home.aspx")] + [TestCase("/umbraco-test")] + [TestCase("/install-test")] + [TestCase("/install.aspx")] + public void Is_Not_Reserved_Path_Or_Url(string url) + { + Assert.IsFalse(Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url)); + } + + + [TestCase("/Do/Not/match", false)] + [TestCase("/Umbraco/RenderMvcs", false)] + [TestCase("/Umbraco/RenderMvc", true)] + [TestCase("/Umbraco/RenderMvc/Index", true)] + [TestCase("/Umbraco/RenderMvc/Index/1234", true)] + [TestCase("/Umbraco/RenderMvc/Index/1234/9876", false)] + [TestCase("/api", true)] + [TestCase("/api/WebApiTest", true)] + [TestCase("/api/WebApiTest/1234", true)] + [TestCase("/api/WebApiTest/Index/1234", false)] + public void Is_Reserved_By_Route(string url, bool shouldMatch) + { + //reset the app config, we only want to test routes not the hard coded paths + Umbraco.Core.Configuration.GlobalSettings.ReservedPaths = ""; + Umbraco.Core.Configuration.GlobalSettings.ReservedUrls = ""; + + var routes = new RouteCollection(); + + routes.MapRoute( + "Umbraco_default", + "Umbraco/RenderMvc/{action}/{id}", + new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional }); + routes.MapRoute( + "WebAPI", + "api/{controller}/{id}", + new { controller = "WebApiTestController", action = "Index", id = UrlParameter.Optional }); + + + var context = new FakeHttpContextFactory(url); + + + Assert.AreEqual( + shouldMatch, + Umbraco.Core.Configuration.GlobalSettings.IsReservedPathOrUrl(url, context.HttpContext, routes)); + } + } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Surface/PluginControllerAreaTests.cs b/src/Umbraco.Tests/Controllers/PluginControllerAreaTests.cs similarity index 92% rename from src/Umbraco.Tests/Surface/PluginControllerAreaTests.cs rename to src/Umbraco.Tests/Controllers/PluginControllerAreaTests.cs index 2ed7bf9876..a2ad7220a5 100644 --- a/src/Umbraco.Tests/Surface/PluginControllerAreaTests.cs +++ b/src/Umbraco.Tests/Controllers/PluginControllerAreaTests.cs @@ -1,90 +1,87 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using Umbraco.Tests.TestHelpers; -using Umbraco.Web; -using Umbraco.Web.Mvc; - -namespace Umbraco.Tests.Surface -{ - [TestFixture] - public class PluginControllerAreaTests : BaseWebTest - { - - [Test] - public void Ensure_Same_Area1() - { - Assert.Throws(() => - new PluginControllerArea(new PluginControllerMetadata[] - { - PluginController.GetMetadata(typeof(Plugin1Controller)), - PluginController.GetMetadata(typeof(Plugin2Controller)), - PluginController.GetMetadata(typeof(Plugin3Controller)) //not same area - })); - } - - [Test] - public void Ensure_Same_Area3() - { - Assert.Throws(() => - new PluginControllerArea(new PluginControllerMetadata[] - { - PluginController.GetMetadata(typeof(Plugin1Controller)), - PluginController.GetMetadata(typeof(Plugin2Controller)), - PluginController.GetMetadata(typeof(Plugin4Controller)) //no area assigned - })); - } - - [Test] - public void Ensure_Same_Area2() - { - var area = new PluginControllerArea(new PluginControllerMetadata[] - { - PluginController.GetMetadata(typeof(Plugin1Controller)), - PluginController.GetMetadata(typeof(Plugin2Controller)) - }); - Assert.Pass(); - } - - #region Test classes - - [PluginController("Area1")] - public class Plugin1Controller : PluginController - { - public Plugin1Controller(UmbracoContext umbracoContext) : base(umbracoContext) - { - } - } - - [PluginController("Area1")] - public class Plugin2Controller : PluginController - { - public Plugin2Controller(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - } - - [PluginController("Area2")] - public class Plugin3Controller : PluginController - { - public Plugin3Controller(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - } - - public class Plugin4Controller : PluginController - { - public Plugin4Controller(UmbracoContext umbracoContext) - : base(umbracoContext) - { - } - } - - #endregion - - } -} +using System; +using NUnit.Framework; +using Umbraco.Tests.TestHelpers; +using Umbraco.Web; +using Umbraco.Web.Mvc; + +namespace Umbraco.Tests.Controllers +{ + [TestFixture] + public class PluginControllerAreaTests : BaseWebTest + { + + [Test] + public void Ensure_Same_Area1() + { + Assert.Throws(() => + new PluginControllerArea(new PluginControllerMetadata[] + { + PluginController.GetMetadata(typeof(Plugin1Controller)), + PluginController.GetMetadata(typeof(Plugin2Controller)), + PluginController.GetMetadata(typeof(Plugin3Controller)) //not same area + })); + } + + [Test] + public void Ensure_Same_Area3() + { + Assert.Throws(() => + new PluginControllerArea(new PluginControllerMetadata[] + { + PluginController.GetMetadata(typeof(Plugin1Controller)), + PluginController.GetMetadata(typeof(Plugin2Controller)), + PluginController.GetMetadata(typeof(Plugin4Controller)) //no area assigned + })); + } + + [Test] + public void Ensure_Same_Area2() + { + var area = new PluginControllerArea(new PluginControllerMetadata[] + { + PluginController.GetMetadata(typeof(Plugin1Controller)), + PluginController.GetMetadata(typeof(Plugin2Controller)) + }); + Assert.Pass(); + } + + #region Test classes + + [PluginController("Area1")] + public class Plugin1Controller : PluginController + { + public Plugin1Controller(UmbracoContext umbracoContext) : base(umbracoContext) + { + } + } + + [PluginController("Area1")] + public class Plugin2Controller : PluginController + { + public Plugin2Controller(UmbracoContext umbracoContext) + : base(umbracoContext) + { + } + } + + [PluginController("Area2")] + public class Plugin3Controller : PluginController + { + public Plugin3Controller(UmbracoContext umbracoContext) + : base(umbracoContext) + { + } + } + + public class Plugin4Controller : PluginController + { + public Plugin4Controller(UmbracoContext umbracoContext) + : base(umbracoContext) + { + } + } + + #endregion + + } +} diff --git a/src/Umbraco.Tests/Sync/DistributedCacheTests.cs b/src/Umbraco.Tests/DistributedCache/DistributedCacheTests.cs similarity index 89% rename from src/Umbraco.Tests/Sync/DistributedCacheTests.cs rename to src/Umbraco.Tests/DistributedCache/DistributedCacheTests.cs index a897f59dae..c714cd0a2e 100644 --- a/src/Umbraco.Tests/Sync/DistributedCacheTests.cs +++ b/src/Umbraco.Tests/DistributedCache/DistributedCacheTests.cs @@ -1,211 +1,210 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Core.ObjectResolution; -using Umbraco.Core.Sync; -using Umbraco.Web.Cache; -using umbraco.interfaces; - -namespace Umbraco.Tests.Sync -{ - /// - /// Ensures that calls to DistributedCache methods carry through to the IServerMessenger correctly - /// - [TestFixture] - public class DistributedCacheTests - { - [SetUp] - public void Setup() - { - ServerRegistrarResolver.Current = new ServerRegistrarResolver( - new TestServerRegistrar()); - ServerMessengerResolver.Current = new ServerMessengerResolver( - new TestServerMessenger()); - CacheRefreshersResolver.Current = new CacheRefreshersResolver(() => new[] { typeof(TestCacheRefresher) }); - Resolution.Freeze(); - } - - [TearDown] - public void Teardown() - { - ServerRegistrarResolver.Reset(); - ServerMessengerResolver.Reset(); - CacheRefreshersResolver.Reset(); - } - - [Test] - public void RefreshIntId() - { - for (var i = 1; i < 11; i++) - { - DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i); - } - Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count); - } - - [Test] - public void RefreshIntIdFromObject() - { - for (var i = 0; i < 10; i++) - { - DistributedCache.Instance.Refresh( - Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), - x => x.Id, - new TestObjectWithId{Id = i}); - } - Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count); - } - - [Test] - public void RefreshGuidId() - { - for (var i = 0; i < 11; i++) - { - DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), Guid.NewGuid()); - } - Assert.AreEqual(11, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).GuidIdsRefreshed.Count); - } - - [Test] - public void RemoveIds() - { - for (var i = 1; i < 13; i++) - { - DistributedCache.Instance.Remove(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i); - } - Assert.AreEqual(12, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRemoved.Count); - } - - [Test] - public void FullRefreshes() - { - for (var i = 0; i < 13; i++) - { - DistributedCache.Instance.RefreshAll(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73")); - } - Assert.AreEqual(13, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).CountOfFullRefreshes); - } - - #region internal test classes - - internal class TestObjectWithId - { - public int Id { get; set; } - } - - internal class TestCacheRefresher : ICacheRefresher - { - public Guid UniqueIdentifier - { - get { return Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"); } - } - public string Name - { - get { return "Test"; } - } - public void RefreshAll() - { - - } - - public void Refresh(int id) - { - - } - - public void Remove(int id) - { - - } - - public void Refresh(Guid id) - { - - } - } - - internal class TestServerMessenger : IServerMessenger - { - //used for tests - public List IntIdsRefreshed = new List(); - public List GuidIdsRefreshed = new List(); - public List IntIdsRemoved = new List(); - public List PayloadsRemoved = new List(); - public List PayloadsRefreshed = new List(); - public int CountOfFullRefreshes = 0; - - - public void PerformRefresh(IEnumerable servers, ICacheRefresher refresher, string jsonPayload) - { - PayloadsRefreshed.Add(jsonPayload); - } - - public void PerformRefresh(IEnumerable servers, ICacheRefresher refresher, Func getNumericId, params T[] instances) - { - IntIdsRefreshed.AddRange(instances.Select(getNumericId)); - } - - public void PerformRefresh(IEnumerable servers, ICacheRefresher refresher, Func getGuidId, params T[] instances) - { - GuidIdsRefreshed.AddRange(instances.Select(getGuidId)); - } - - public void PerformRemove(IEnumerable servers, ICacheRefresher refresher, string jsonPayload) - { - PayloadsRemoved.Add(jsonPayload); - } - - public void PerformRemove(IEnumerable servers, ICacheRefresher refresher, Func getNumericId, params T[] instances) - { - IntIdsRemoved.AddRange(instances.Select(getNumericId)); - } - - public void PerformRemove(IEnumerable servers, ICacheRefresher refresher, params int[] numericIds) - { - IntIdsRemoved.AddRange(numericIds); - } - - public void PerformRefresh(IEnumerable servers, ICacheRefresher refresher, params int[] numericIds) - { - IntIdsRefreshed.AddRange(numericIds); - } - - public void PerformRefresh(IEnumerable servers, ICacheRefresher refresher, params Guid[] guidIds) - { - GuidIdsRefreshed.AddRange(guidIds); - } - - public void PerformRefreshAll(IEnumerable servers, ICacheRefresher refresher) - { - CountOfFullRefreshes++; - } - } - - internal class TestServerRegistrar : IServerRegistrar - { - public IEnumerable Registrations - { - get - { - return new List() - { - new TestServerAddress("localhost") - }; - } - } - } - - public class TestServerAddress : IServerAddress - { - public TestServerAddress(string address) - { - ServerAddress = address; - } - public string ServerAddress { get; private set; } - } - - #endregion - } +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.ObjectResolution; +using Umbraco.Core.Sync; +using umbraco.interfaces; + +namespace Umbraco.Tests.DistributedCache +{ + /// + /// Ensures that calls to DistributedCache methods carry through to the IServerMessenger correctly + /// + [TestFixture] + public class DistributedCacheTests + { + [SetUp] + public void Setup() + { + ServerRegistrarResolver.Current = new ServerRegistrarResolver( + new TestServerRegistrar()); + ServerMessengerResolver.Current = new ServerMessengerResolver( + new TestServerMessenger()); + CacheRefreshersResolver.Current = new CacheRefreshersResolver(() => new[] { typeof(TestCacheRefresher) }); + Resolution.Freeze(); + } + + [TearDown] + public void Teardown() + { + ServerRegistrarResolver.Reset(); + ServerMessengerResolver.Reset(); + CacheRefreshersResolver.Reset(); + } + + [Test] + public void RefreshIntId() + { + for (var i = 1; i < 11; i++) + { + Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i); + } + Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count); + } + + [Test] + public void RefreshIntIdFromObject() + { + for (var i = 0; i < 10; i++) + { + Web.Cache.DistributedCache.Instance.Refresh( + Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), + x => x.Id, + new TestObjectWithId{Id = i}); + } + Assert.AreEqual(10, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRefreshed.Count); + } + + [Test] + public void RefreshGuidId() + { + for (var i = 0; i < 11; i++) + { + Web.Cache.DistributedCache.Instance.Refresh(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), Guid.NewGuid()); + } + Assert.AreEqual(11, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).GuidIdsRefreshed.Count); + } + + [Test] + public void RemoveIds() + { + for (var i = 1; i < 13; i++) + { + Web.Cache.DistributedCache.Instance.Remove(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"), i); + } + Assert.AreEqual(12, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).IntIdsRemoved.Count); + } + + [Test] + public void FullRefreshes() + { + for (var i = 0; i < 13; i++) + { + Web.Cache.DistributedCache.Instance.RefreshAll(Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73")); + } + Assert.AreEqual(13, ((TestServerMessenger)ServerMessengerResolver.Current.Messenger).CountOfFullRefreshes); + } + + #region internal test classes + + internal class TestObjectWithId + { + public int Id { get; set; } + } + + internal class TestCacheRefresher : ICacheRefresher + { + public Guid UniqueIdentifier + { + get { return Guid.Parse("E0F452CB-DCB2-4E84-B5A5-4F01744C5C73"); } + } + public string Name + { + get { return "Test"; } + } + public void RefreshAll() + { + + } + + public void Refresh(int id) + { + + } + + public void Remove(int id) + { + + } + + public void Refresh(Guid id) + { + + } + } + + internal class TestServerMessenger : IServerMessenger + { + //used for tests + public List IntIdsRefreshed = new List(); + public List GuidIdsRefreshed = new List(); + public List IntIdsRemoved = new List(); + public List PayloadsRemoved = new List(); + public List PayloadsRefreshed = new List(); + public int CountOfFullRefreshes = 0; + + + public void PerformRefresh(IEnumerable servers, ICacheRefresher refresher, string jsonPayload) + { + PayloadsRefreshed.Add(jsonPayload); + } + + public void PerformRefresh(IEnumerable servers, ICacheRefresher refresher, Func getNumericId, params T[] instances) + { + IntIdsRefreshed.AddRange(instances.Select(getNumericId)); + } + + public void PerformRefresh(IEnumerable servers, ICacheRefresher refresher, Func getGuidId, params T[] instances) + { + GuidIdsRefreshed.AddRange(instances.Select(getGuidId)); + } + + public void PerformRemove(IEnumerable servers, ICacheRefresher refresher, string jsonPayload) + { + PayloadsRemoved.Add(jsonPayload); + } + + public void PerformRemove(IEnumerable servers, ICacheRefresher refresher, Func getNumericId, params T[] instances) + { + IntIdsRemoved.AddRange(instances.Select(getNumericId)); + } + + public void PerformRemove(IEnumerable servers, ICacheRefresher refresher, params int[] numericIds) + { + IntIdsRemoved.AddRange(numericIds); + } + + public void PerformRefresh(IEnumerable servers, ICacheRefresher refresher, params int[] numericIds) + { + IntIdsRefreshed.AddRange(numericIds); + } + + public void PerformRefresh(IEnumerable servers, ICacheRefresher refresher, params Guid[] guidIds) + { + GuidIdsRefreshed.AddRange(guidIds); + } + + public void PerformRefreshAll(IEnumerable servers, ICacheRefresher refresher) + { + CountOfFullRefreshes++; + } + } + + internal class TestServerRegistrar : IServerRegistrar + { + public IEnumerable Registrations + { + get + { + return new List() + { + new TestServerAddress("localhost") + }; + } + } + } + + public class TestServerAddress : IServerAddress + { + public TestServerAddress(string address) + { + ServerAddress = address; + } + public string ServerAddress { get; private set; } + } + + #endregion + } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Dynamics/QueryableExtensionTests.cs b/src/Umbraco.Tests/DynamicsAndReflection/QueryableExtensionTests.cs similarity index 95% rename from src/Umbraco.Tests/Dynamics/QueryableExtensionTests.cs rename to src/Umbraco.Tests/DynamicsAndReflection/QueryableExtensionTests.cs index d5343ff521..c2544421a0 100644 --- a/src/Umbraco.Tests/Dynamics/QueryableExtensionTests.cs +++ b/src/Umbraco.Tests/DynamicsAndReflection/QueryableExtensionTests.cs @@ -1,162 +1,158 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using NUnit.Framework; -using Umbraco.Core.Dynamics; -using Umbraco.Web.Dynamics; -using Umbraco.Core.Models; - -namespace Umbraco.Tests.Dynamics -{ - //NOTE: there's libraries in both Umbraco.Core.Dynamics and Umbraco.Web.Dynamics - the reason for this is that the Web.Dynamics - // started with the razor macro implementation and is modified with hard coded references to dynamic node and dynamic null, though it seems - // to still work for other regular classes I don't want to move it to the core without removing these references but that would require a lot of work. - - [TestFixture] - public class QueryableExtensionTests - { - - [Test] - public void Order_By_Test_Int() - { - var items = new List - { - new TestModel {Age = 10, Name = "test1", Female = false}, - new TestModel {Age = 31, Name = "someguy", Female = true}, - new TestModel {Age = 11, Name = "test2", Female = true}, - new TestModel {Age = 20, Name = "anothertest", Female = false}, - new TestModel {Age = 55, Name = "blah", Female = false}, - new TestModel {Age = 12, Name = "test3", Female = false} - }; - - var result = items.AsQueryable().OrderBy("Age").ToArray(); - - Assert.AreEqual(10, result.ElementAt(0).Age); - Assert.AreEqual(11, result.ElementAt(1).Age); - Assert.AreEqual(12, result.ElementAt(2).Age); - Assert.AreEqual(20, result.ElementAt(3).Age); - Assert.AreEqual(31, result.ElementAt(4).Age); - Assert.AreEqual(55, result.ElementAt(5).Age); - - } - - [Test] - public void Order_By_Test_String() - { - var items = new List - { - new TestModel {Age = 10, Name = "test1", Female = false}, - new TestModel {Age = 31, Name = "someguy", Female = true}, - new TestModel {Age = 11, Name = "test2", Female = true}, - new TestModel {Age = 20, Name = "anothertest", Female = false}, - new TestModel {Age = 55, Name = "blah", Female = false}, - new TestModel {Age = 12, Name = "test3", Female = false} - }; - - var result = items.AsQueryable().OrderBy("Name").ToArray(); - - Assert.AreEqual("anothertest", result.ElementAt(0).Name); - Assert.AreEqual("blah", result.ElementAt(1).Name); - Assert.AreEqual("someguy", result.ElementAt(2).Name); - Assert.AreEqual("test1", result.ElementAt(3).Name); - Assert.AreEqual("test2", result.ElementAt(4).Name); - Assert.AreEqual("test3", result.ElementAt(5).Name); - - } - - [Test] - public void Where_Test_String() - { - var items = new List - { - new TestModel {Age = 10, Name = "test1", Female = false}, - new TestModel {Age = 31, Name = "someguy", Female = true}, - new TestModel {Age = 11, Name = "test2", Female = true}, - new TestModel {Age = 20, Name = "anothertest", Female = false}, - new TestModel {Age = 55, Name = "blah", Female = false}, - new TestModel {Age = 12, Name = "test3", Female = false} - }; - - var result = items.AsQueryable().Where("Name = \"test1\"").ToArray(); - - Assert.AreEqual(1, result.Count()); - Assert.AreEqual("test1", result.ElementAt(0).Name); - - - } - - [Test] - public void Where_Test_String_With_Params() - { - var items = new List - { - new TestModel {Age = 10, Name = "test1", Female = false}, - new TestModel {Age = 31, Name = "someguy", Female = true}, - new TestModel {Age = 11, Name = "test2", Female = true}, - new TestModel {Age = 20, Name = "anothertest", Female = false}, - new TestModel {Age = 55, Name = "blah", Female = false}, - new TestModel {Age = 12, Name = "test3", Female = false} - }; - - //NOTE: Currently the object query structure is not supported - //var result = items.AsQueryable().Where("Name = @name", new {name = "test1"}).ToArray(); - var result = items.AsQueryable().Where("Name = @Name", new Dictionary { { "Name", "test1" } }).ToArray(); - - Assert.AreEqual(1, result.Count()); - Assert.AreEqual("test1", result.ElementAt(0).Name); - - - } - - [Test] - public void Where_Test_Int_With_Params() - { - var items = new List - { - new TestModel {Age = 10, Name = "test1", Female = false}, - new TestModel {Age = 31, Name = "someguy", Female = true}, - new TestModel {Age = 11, Name = "test2", Female = true}, - new TestModel {Age = 20, Name = "anothertest", Female = false}, - new TestModel {Age = 55, Name = "blah", Female = false}, - new TestModel {Age = 12, Name = "test3", Female = false} - }; - - var result = items.AsQueryable().Where("Age = @Age", new Dictionary { { "Age", 10 } }).ToArray(); - - Assert.AreEqual(1, result.Count()); - Assert.AreEqual("test1", result.ElementAt(0).Name); - - - } - - [Test] - public void Where_Test_Bool_With_Params() - { - var items = new List - { - new TestModel {Age = 10, Name = "test1", Female = false}, - new TestModel {Age = 31, Name = "someguy", Female = true}, - new TestModel {Age = 11, Name = "test2", Female = true}, - new TestModel {Age = 20, Name = "anothertest", Female = false}, - new TestModel {Age = 55, Name = "blah", Female = false}, - new TestModel {Age = 12, Name = "test3", Female = false} - }; - - var result = items.AsQueryable().Where("Female = @Female", new Dictionary { { "Female", true } }).ToArray(); - - Assert.AreEqual(2, result.Count()); - - - } - - private class TestModel - { - public string Name { get; set; } - public int Age { get; set; } - public bool Female { get; set; } - } - - } -} +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using Umbraco.Core.Dynamics; +using Umbraco.Web.Dynamics; + +namespace Umbraco.Tests.DynamicsAndReflection +{ + //NOTE: there's libraries in both Umbraco.Core.Dynamics and Umbraco.Web.Dynamics - the reason for this is that the Web.Dynamics + // started with the razor macro implementation and is modified with hard coded references to dynamic node and dynamic null, though it seems + // to still work for other regular classes I don't want to move it to the core without removing these references but that would require a lot of work. + + [TestFixture] + public class QueryableExtensionTests + { + + [Test] + public void Order_By_Test_Int() + { + var items = new List + { + new TestModel {Age = 10, Name = "test1", Female = false}, + new TestModel {Age = 31, Name = "someguy", Female = true}, + new TestModel {Age = 11, Name = "test2", Female = true}, + new TestModel {Age = 20, Name = "anothertest", Female = false}, + new TestModel {Age = 55, Name = "blah", Female = false}, + new TestModel {Age = 12, Name = "test3", Female = false} + }; + + var result = items.AsQueryable().OrderBy("Age").ToArray(); + + Assert.AreEqual(10, result.ElementAt(0).Age); + Assert.AreEqual(11, result.ElementAt(1).Age); + Assert.AreEqual(12, result.ElementAt(2).Age); + Assert.AreEqual(20, result.ElementAt(3).Age); + Assert.AreEqual(31, result.ElementAt(4).Age); + Assert.AreEqual(55, result.ElementAt(5).Age); + + } + + [Test] + public void Order_By_Test_String() + { + var items = new List + { + new TestModel {Age = 10, Name = "test1", Female = false}, + new TestModel {Age = 31, Name = "someguy", Female = true}, + new TestModel {Age = 11, Name = "test2", Female = true}, + new TestModel {Age = 20, Name = "anothertest", Female = false}, + new TestModel {Age = 55, Name = "blah", Female = false}, + new TestModel {Age = 12, Name = "test3", Female = false} + }; + + var result = items.AsQueryable().OrderBy("Name").ToArray(); + + Assert.AreEqual("anothertest", result.ElementAt(0).Name); + Assert.AreEqual("blah", result.ElementAt(1).Name); + Assert.AreEqual("someguy", result.ElementAt(2).Name); + Assert.AreEqual("test1", result.ElementAt(3).Name); + Assert.AreEqual("test2", result.ElementAt(4).Name); + Assert.AreEqual("test3", result.ElementAt(5).Name); + + } + + [Test] + public void Where_Test_String() + { + var items = new List + { + new TestModel {Age = 10, Name = "test1", Female = false}, + new TestModel {Age = 31, Name = "someguy", Female = true}, + new TestModel {Age = 11, Name = "test2", Female = true}, + new TestModel {Age = 20, Name = "anothertest", Female = false}, + new TestModel {Age = 55, Name = "blah", Female = false}, + new TestModel {Age = 12, Name = "test3", Female = false} + }; + + var result = items.AsQueryable().Where("Name = \"test1\"").ToArray(); + + Assert.AreEqual(1, result.Count()); + Assert.AreEqual("test1", result.ElementAt(0).Name); + + + } + + [Test] + public void Where_Test_String_With_Params() + { + var items = new List + { + new TestModel {Age = 10, Name = "test1", Female = false}, + new TestModel {Age = 31, Name = "someguy", Female = true}, + new TestModel {Age = 11, Name = "test2", Female = true}, + new TestModel {Age = 20, Name = "anothertest", Female = false}, + new TestModel {Age = 55, Name = "blah", Female = false}, + new TestModel {Age = 12, Name = "test3", Female = false} + }; + + //NOTE: Currently the object query structure is not supported + //var result = items.AsQueryable().Where("Name = @name", new {name = "test1"}).ToArray(); + var result = items.AsQueryable().Where("Name = @Name", new Dictionary { { "Name", "test1" } }).ToArray(); + + Assert.AreEqual(1, result.Count()); + Assert.AreEqual("test1", result.ElementAt(0).Name); + + + } + + [Test] + public void Where_Test_Int_With_Params() + { + var items = new List + { + new TestModel {Age = 10, Name = "test1", Female = false}, + new TestModel {Age = 31, Name = "someguy", Female = true}, + new TestModel {Age = 11, Name = "test2", Female = true}, + new TestModel {Age = 20, Name = "anothertest", Female = false}, + new TestModel {Age = 55, Name = "blah", Female = false}, + new TestModel {Age = 12, Name = "test3", Female = false} + }; + + var result = items.AsQueryable().Where("Age = @Age", new Dictionary { { "Age", 10 } }).ToArray(); + + Assert.AreEqual(1, result.Count()); + Assert.AreEqual("test1", result.ElementAt(0).Name); + + + } + + [Test] + public void Where_Test_Bool_With_Params() + { + var items = new List + { + new TestModel {Age = 10, Name = "test1", Female = false}, + new TestModel {Age = 31, Name = "someguy", Female = true}, + new TestModel {Age = 11, Name = "test2", Female = true}, + new TestModel {Age = 20, Name = "anothertest", Female = false}, + new TestModel {Age = 55, Name = "blah", Female = false}, + new TestModel {Age = 12, Name = "test3", Female = false} + }; + + var result = items.AsQueryable().Where("Female = @Female", new Dictionary { { "Female", true } }).ToArray(); + + Assert.AreEqual(2, result.Count()); + + + } + + private class TestModel + { + public string Name { get; set; } + public int Age { get; set; } + public bool Female { get; set; } + } + + } +} diff --git a/src/Umbraco.Tests/MacroEngineFactoryTests.cs b/src/Umbraco.Tests/Macros/MacroEngineFactoryTests.cs similarity index 95% rename from src/Umbraco.Tests/MacroEngineFactoryTests.cs rename to src/Umbraco.Tests/Macros/MacroEngineFactoryTests.cs index e8d35e8255..2ab4c9f04e 100644 --- a/src/Umbraco.Tests/MacroEngineFactoryTests.cs +++ b/src/Umbraco.Tests/Macros/MacroEngineFactoryTests.cs @@ -1,139 +1,139 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Tests.TestHelpers; -using umbraco.cms.businesslogic.macro; -using umbraco.interfaces; - -namespace Umbraco.Tests -{ - [TestFixture] - public class MacroEngineFactoryTests - { - [SetUp] - public void Initialize() - { - TestHelper.SetupLog4NetForTests(); - - //this ensures its reset - PluginManager.Current = new PluginManager(false); - - //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - PluginManager.Current.AssembliesToScan = new[] - { - this.GetType().Assembly - }; - } - - [TearDown] - public void TearDown() - { - PluginManager.Current = null; - } - - [Test] - public void Get_All() - { - var engines = MacroEngineFactory.GetAll(); - Assert.AreEqual(2, engines.Count()); - } - - [Test] - public void Get_Engine() - { - var engine1 = MacroEngineFactory.GetEngine("MacroEngine1"); - Assert.IsNotNull(engine1); - } - - [Test] - public void Get_By_Filename() - { - var engine1 = MacroEngineFactory.GetByFilename("test.me1"); - var engine2 = MacroEngineFactory.GetByFilename("test.me2"); - Assert.IsNotNull(engine1); - Assert.IsNotNull(engine2); - Assert.Throws(() => MacroEngineFactory.GetByFilename("test.blah")); - - } - - [Test] - public void Get_By_Extension() - { - var engine1 = MacroEngineFactory.GetByExtension("me1"); - var engine2 = MacroEngineFactory.GetByExtension("me2"); - Assert.IsNotNull(engine1); - Assert.IsNotNull(engine2); - Assert.Throws(() => MacroEngineFactory.GetByExtension("blah")); - } - - #region Classes for tests - public class MacroEngine1 : IMacroEngine - { - public string Name - { - get { return "MacroEngine1"; } - } - - public IEnumerable SupportedExtensions - { - get { return new[] {"me1"}; } - } - - public IEnumerable SupportedUIExtensions - { - get { throw new NotImplementedException(); } - } - - public Dictionary SupportedProperties - { - get { throw new NotImplementedException(); } - } - - public bool Validate(string code, string tempFileName, INode currentPage, out string errorMessage) - { - throw new NotImplementedException(); - } - - public string Execute(MacroModel macro, INode currentPage) - { - throw new NotImplementedException(); - } - } - - public class MacroEngine2 : IMacroEngine - { - public string Name - { - get { return "MacroEngine2"; } - } - - public IEnumerable SupportedExtensions - { - get { return new[] { "me2" }; } - } - - public IEnumerable SupportedUIExtensions - { - get { throw new NotImplementedException(); } - } - - public Dictionary SupportedProperties - { - get { throw new NotImplementedException(); } - } - - public bool Validate(string code, string tempFileName, INode currentPage, out string errorMessage) - { - throw new NotImplementedException(); - } - - public string Execute(MacroModel macro, INode currentPage) - { - throw new NotImplementedException(); - } - } - #endregion - } +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using umbraco.cms.businesslogic.macro; +using Umbraco.Core; +using umbraco.interfaces; +using Umbraco.Tests.TestHelpers; + +namespace Umbraco.Tests.Macros +{ + [TestFixture] + public class MacroEngineFactoryTests + { + [SetUp] + public void Initialize() + { + TestHelper.SetupLog4NetForTests(); + + //this ensures its reset + PluginManager.Current = new PluginManager(false); + + //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver + PluginManager.Current.AssembliesToScan = new[] + { + this.GetType().Assembly + }; + } + + [TearDown] + public void TearDown() + { + PluginManager.Current = null; + } + + [Test] + public void Get_All() + { + var engines = MacroEngineFactory.GetAll(); + Assert.AreEqual(2, engines.Count()); + } + + [Test] + public void Get_Engine() + { + var engine1 = MacroEngineFactory.GetEngine("MacroEngine1"); + Assert.IsNotNull(engine1); + } + + [Test] + public void Get_By_Filename() + { + var engine1 = MacroEngineFactory.GetByFilename("test.me1"); + var engine2 = MacroEngineFactory.GetByFilename("test.me2"); + Assert.IsNotNull(engine1); + Assert.IsNotNull(engine2); + Assert.Throws(() => MacroEngineFactory.GetByFilename("test.blah")); + + } + + [Test] + public void Get_By_Extension() + { + var engine1 = MacroEngineFactory.GetByExtension("me1"); + var engine2 = MacroEngineFactory.GetByExtension("me2"); + Assert.IsNotNull(engine1); + Assert.IsNotNull(engine2); + Assert.Throws(() => MacroEngineFactory.GetByExtension("blah")); + } + + #region Classes for tests + public class MacroEngine1 : IMacroEngine + { + public string Name + { + get { return "MacroEngine1"; } + } + + public IEnumerable SupportedExtensions + { + get { return new[] {"me1"}; } + } + + public IEnumerable SupportedUIExtensions + { + get { throw new NotImplementedException(); } + } + + public Dictionary SupportedProperties + { + get { throw new NotImplementedException(); } + } + + public bool Validate(string code, string tempFileName, INode currentPage, out string errorMessage) + { + throw new NotImplementedException(); + } + + public string Execute(MacroModel macro, INode currentPage) + { + throw new NotImplementedException(); + } + } + + public class MacroEngine2 : IMacroEngine + { + public string Name + { + get { return "MacroEngine2"; } + } + + public IEnumerable SupportedExtensions + { + get { return new[] { "me2" }; } + } + + public IEnumerable SupportedUIExtensions + { + get { throw new NotImplementedException(); } + } + + public Dictionary SupportedProperties + { + get { throw new NotImplementedException(); } + } + + public bool Validate(string code, string tempFileName, INode currentPage, out string errorMessage) + { + throw new NotImplementedException(); + } + + public string Execute(MacroModel macro, INode currentPage) + { + throw new NotImplementedException(); + } + } + #endregion + } } \ No newline at end of file diff --git a/src/Umbraco.Tests/HtmlHelperExtensionMethodsTests.cs b/src/Umbraco.Tests/Mvc/HtmlHelperExtensionMethodsTests.cs similarity index 93% rename from src/Umbraco.Tests/HtmlHelperExtensionMethodsTests.cs rename to src/Umbraco.Tests/Mvc/HtmlHelperExtensionMethodsTests.cs index 5efabd891e..beb51fa651 100644 --- a/src/Umbraco.Tests/HtmlHelperExtensionMethodsTests.cs +++ b/src/Umbraco.Tests/Mvc/HtmlHelperExtensionMethodsTests.cs @@ -1,33 +1,33 @@ -using System.Web.Mvc; -using NUnit.Framework; -using Umbraco.Web; - -namespace Umbraco.Tests -{ - [TestFixture] - public class HtmlHelperExtensionMethodsTests - { - [SetUp] - public virtual void Initialize() - { - //create an empty htmlHelper - _htmlHelper = new HtmlHelper(new ViewContext(), new ViewPage()); - } - - private HtmlHelper _htmlHelper; - - [Test] - public void Wrap_Simple() - { - var output = _htmlHelper.Wrap("div", "hello world"); - Assert.AreEqual("
hello world
", output.ToHtmlString()); - } - - [Test] - public void Wrap_Object_Attributes() - { - var output = _htmlHelper.Wrap("div", "hello world", new {style = "color:red;", onclick = "void();"}); - Assert.AreEqual("
hello world
", output.ToHtmlString()); - } - } +using System.Web.Mvc; +using NUnit.Framework; +using Umbraco.Web; + +namespace Umbraco.Tests.Mvc +{ + [TestFixture] + public class HtmlHelperExtensionMethodsTests + { + [SetUp] + public virtual void Initialize() + { + //create an empty htmlHelper + _htmlHelper = new HtmlHelper(new ViewContext(), new ViewPage()); + } + + private HtmlHelper _htmlHelper; + + [Test] + public void Wrap_Simple() + { + var output = _htmlHelper.Wrap("div", "hello world"); + Assert.AreEqual("
hello world
", output.ToHtmlString()); + } + + [Test] + public void Wrap_Object_Attributes() + { + var output = _htmlHelper.Wrap("div", "hello world", new {style = "color:red;", onclick = "void();"}); + Assert.AreEqual("
hello world
", output.ToHtmlString()); + } + } } \ No newline at end of file diff --git a/src/Umbraco.Tests/PluginManagerExtensions.cs b/src/Umbraco.Tests/Plugins/PluginManagerExtensions.cs similarity index 89% rename from src/Umbraco.Tests/PluginManagerExtensions.cs rename to src/Umbraco.Tests/Plugins/PluginManagerExtensions.cs index 0daad7be44..b8ff7d20c2 100644 --- a/src/Umbraco.Tests/PluginManagerExtensions.cs +++ b/src/Umbraco.Tests/Plugins/PluginManagerExtensions.cs @@ -1,17 +1,17 @@ -using System; -using System.Collections.Generic; -using Umbraco.Core; - -namespace Umbraco.Tests -{ - /// - /// Used for PluginTypeResolverTests - /// - internal static class PluginManagerExtensions - { - public static IEnumerable ResolveFindMeTypes(this PluginManager resolver) - { - return resolver.ResolveTypes(); - } - } +using System; +using System.Collections.Generic; +using Umbraco.Core; + +namespace Umbraco.Tests.Plugins +{ + /// + /// Used for PluginTypeResolverTests + /// + internal static class PluginManagerExtensions + { + public static IEnumerable ResolveFindMeTypes(this PluginManager resolver) + { + return resolver.ResolveTypes(); + } + } } \ No newline at end of file diff --git a/src/Umbraco.Tests/PluginManagerTests.cs b/src/Umbraco.Tests/Plugins/PluginManagerTests.cs similarity index 96% rename from src/Umbraco.Tests/PluginManagerTests.cs rename to src/Umbraco.Tests/Plugins/PluginManagerTests.cs index 0adaaefc06..ac85090207 100644 --- a/src/Umbraco.Tests/PluginManagerTests.cs +++ b/src/Umbraco.Tests/Plugins/PluginManagerTests.cs @@ -1,392 +1,388 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Web.Compilation; -using NUnit.Framework; -using SqlCE4Umbraco; -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Core.PropertyEditors; -using Umbraco.Tests.TestHelpers; -using Umbraco.Web; -using Umbraco.Web.PropertyEditors; -using umbraco; -using umbraco.DataLayer; -using umbraco.MacroEngines; -using umbraco.businesslogic; -using umbraco.cms.businesslogic; -using umbraco.editorControls; -using umbraco.interfaces; -using umbraco.uicontrols; -using umbraco.cms; - -namespace Umbraco.Tests -{ - - [TestFixture] - public class PluginManagerTests - { - - [SetUp] - public void Initialize() - { - TestHelper.SetupLog4NetForTests(); - - //this ensures its reset - PluginManager.Current = new PluginManager(false); - - //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver - //TODO: Should probably update this so it only searches this assembly and add custom types to be found - PluginManager.Current.AssembliesToScan = new[] - { - this.GetType().Assembly, - typeof(ApplicationStartupHandler).Assembly, - typeof(SqlCEHelper).Assembly, - typeof(CMSNode).Assembly, - typeof(System.Guid).Assembly, - typeof(NUnit.Framework.Assert).Assembly, - typeof(Microsoft.CSharp.CSharpCodeProvider).Assembly, - typeof(System.Xml.NameTable).Assembly, - typeof(System.Configuration.GenericEnumConverter).Assembly, - typeof(System.Web.SiteMap).Assembly, - typeof(TabPage).Assembly, - typeof(System.Web.Mvc.ActionResult).Assembly, - typeof(TypeFinder).Assembly, - typeof(ISqlHelper).Assembly, - typeof(ICultureDictionary).Assembly, - typeof(UmbracoContext).Assembly, - typeof(BaseDataType).Assembly - }; - } - - [TearDown] - public void TearDown() - { - PluginManager.Current = null; - } - - private DirectoryInfo PrepareFolder() - { - var assDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory; - var dir = Directory.CreateDirectory(Path.Combine(assDir.FullName, "PluginManager", Guid.NewGuid().ToString("N"))); - foreach (var f in dir.GetFiles()) - { - f.Delete(); - } - return dir; - } - - //[Test] - //public void Scan_Vs_Load_Benchmark() - //{ - // var pluginManager = new PluginManager(false); - // var watch = new Stopwatch(); - // watch.Start(); - // for (var i = 0; i < 1000; i++) - // { - // var type2 = Type.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); - // var type3 = Type.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); - // var type4 = Type.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); - // var type5 = Type.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); - // } - // watch.Stop(); - // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds); - // watch.Start(); - // for (var i = 0; i < 1000; i++) - // { - // var type2 = BuildManager.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); - // var type3 = BuildManager.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); - // var type4 = BuildManager.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); - // var type5 = BuildManager.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); - // } - // watch.Stop(); - // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds); - // watch.Reset(); - // watch.Start(); - // for (var i = 0; i < 1000; i++) - // { - // var refreshers = pluginManager.ResolveTypes(false); - // } - // watch.Stop(); - // Debug.WriteLine("TOTAL TIME (2nd round): " + watch.ElapsedMilliseconds); - //} - - ////NOTE: This test shows that Type.GetType is 100% faster than Assembly.Load(..).GetType(...) so we'll use that :) - //[Test] - //public void Load_Type_Benchmark() - //{ - // var watch = new Stopwatch(); - // watch.Start(); - // for (var i = 0; i < 1000; i++) - // { - // var type2 = Type.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); - // var type3 = Type.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); - // var type4 = Type.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); - // var type5 = Type.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); - // } - // watch.Stop(); - // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds); - // watch.Reset(); - // watch.Start(); - // for (var i = 0; i < 1000; i++) - // { - // var type2 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null") - // .GetType("umbraco.macroCacheRefresh"); - // var type3 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null") - // .GetType("umbraco.templateCacheRefresh"); - // var type4 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null") - // .GetType("umbraco.presentation.cache.MediaLibraryRefreshers"); - // var type5 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null") - // .GetType("umbraco.presentation.cache.pageRefresher"); - // } - // watch.Stop(); - // Debug.WriteLine("TOTAL TIME (2nd round): " + watch.ElapsedMilliseconds); - // watch.Reset(); - // watch.Start(); - // for (var i = 0; i < 1000; i++) - // { - // var type2 = BuildManager.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); - // var type3 = BuildManager.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); - // var type4 = BuildManager.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); - // var type5 = BuildManager.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); - // } - // watch.Stop(); - // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds); - //} - - [Test] - public void Detect_Legacy_Plugin_File_List() - { - var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache"); - var manager = new PluginManager(false); - var filePath= Path.Combine(tempFolder, string.Format("umbraco-plugins.{0}.list", NetworkHelper.FileSafeMachineName)); - - File.WriteAllText(filePath, @" - - - - -"); - - Assert.IsTrue(manager.DetectLegacyPluginListFile()); - - File.Delete(filePath); - - //now create a valid one - File.WriteAllText(filePath, @" - - - - -"); - - Assert.IsFalse(manager.DetectLegacyPluginListFile()); - } - - [Test] - public void Create_Cached_Plugin_File() - { - var types = new[] { typeof(PluginManager), typeof(PluginManagerTests), typeof(UmbracoContext) }; - - var manager = new PluginManager(false); - //yes this is silly, none of these types inherit from string, but this is just to test the xml file format - manager.UpdateCachedPluginsFile(types, PluginManager.TypeResolutionKind.FindAllTypes); - - var plugins = manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAllTypes); - var diffType = manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAttributedTypes); - - Assert.IsTrue(plugins.Success); - //this will be false since there is no cache of that type resolution kind - Assert.IsFalse(diffType.Success); - - Assert.AreEqual(3, plugins.Result.Count()); - var shouldContain = types.Select(x => x.AssemblyQualifiedName); - //ensure they are all found - Assert.IsTrue(plugins.Result.ContainsAll(shouldContain)); - } - - [Test] - public void PluginHash_From_String() - { - var s = "hello my name is someone".GetHashCode().ToString("x", CultureInfo.InvariantCulture); - var output = PluginManager.ConvertPluginsHashFromHex(s); - Assert.AreNotEqual(0, output); - } - - [Test] - public void Get_Plugins_Hash() - { - //Arrange - var dir = PrepareFolder(); - var d1 = dir.CreateSubdirectory("1"); - var d2 = dir.CreateSubdirectory("2"); - var d3 = dir.CreateSubdirectory("3"); - var d4 = dir.CreateSubdirectory("4"); - var f1 = new FileInfo(Path.Combine(d1.FullName, "test1.dll")); - var f2 = new FileInfo(Path.Combine(d1.FullName, "test2.dll")); - var f3 = new FileInfo(Path.Combine(d2.FullName, "test1.dll")); - var f4 = new FileInfo(Path.Combine(d2.FullName, "test2.dll")); - var f5 = new FileInfo(Path.Combine(d3.FullName, "test1.dll")); - var f6 = new FileInfo(Path.Combine(d3.FullName, "test2.dll")); - var f7 = new FileInfo(Path.Combine(d4.FullName, "test1.dll")); - f1.CreateText().Close(); - f2.CreateText().Close(); - f3.CreateText().Close(); - f4.CreateText().Close(); - f5.CreateText().Close(); - f6.CreateText().Close(); - f7.CreateText().Close(); - var list1 = new[] { f1, f2, f3, f4, f5, f6 }; - var list2 = new[] { f1, f3, f5 }; - var list3 = new[] { f1, f3, f5, f7 }; - - //Act - var hash1 = PluginManager.GetFileHash(list1); - var hash2 = PluginManager.GetFileHash(list2); - var hash3 = PluginManager.GetFileHash(list3); - - //Assert - Assert.AreNotEqual(hash1, hash2); - Assert.AreNotEqual(hash1, hash3); - Assert.AreNotEqual(hash2, hash3); - - Assert.AreEqual(hash1, PluginManager.GetFileHash(list1)); - } - - [Test] - public void Ensure_Only_One_Type_List_Created() - { - var foundTypes1 = PluginManager.Current.ResolveFindMeTypes(); - var foundTypes2 = PluginManager.Current.ResolveFindMeTypes(); - Assert.AreEqual(1, - PluginManager.Current.GetTypeLists() - .Count(x => x.IsTypeList(PluginManager.TypeResolutionKind.FindAllTypes))); - } - - [Test] - public void Resolves_Assigned_Mappers() - { - var foundTypes1 = PluginManager.Current.ResolveAssignedMapperTypes(); - Assert.AreEqual(22, foundTypes1.Count()); - } - - [Test] - public void Resolves_Types() - { - var foundTypes1 = PluginManager.Current.ResolveFindMeTypes(); - Assert.AreEqual(2, foundTypes1.Count()); - } - - [Test] - public void Resolves_Attributed_Trees() - { - var trees = PluginManager.Current.ResolveAttributedTrees(); - Assert.AreEqual(19, trees.Count()); - } - - [Test] - public void Resolves_Actions() - { - var actions = PluginManager.Current.ResolveActions(); - Assert.AreEqual(36, actions.Count()); - } - - [Test] - public void Resolves_Trees() - { - var trees = PluginManager.Current.ResolveTrees(); - Assert.AreEqual(39, trees.Count()); - } - - [Test] - public void Resolves_Applications() - { - var apps = PluginManager.Current.ResolveApplications(); - Assert.AreEqual(7, apps.Count()); - } - - [Test] - public void Resolves_DataTypes() - { - var types = PluginManager.Current.ResolveDataTypes(); - Assert.AreEqual(35, types.Count()); - } - - [Test] - public void Resolves_RazorDataTypeModels() - { - var types = PluginManager.Current.ResolveRazorDataTypeModels(); - Assert.AreEqual(2, types.Count()); - } - - [Test] - public void Resolves_RestExtensions() - { - var types = PluginManager.Current.ResolveRestExtensions(); - Assert.AreEqual(3, types.Count()); - } - - [Test] - public void Resolves_XsltExtensions() - { - var types = PluginManager.Current.ResolveXsltExtensions(); - Assert.AreEqual(3, types.Count()); - } - - /// - /// This demonstrates this issue: http://issues.umbraco.org/issue/U4-3505 - the TypeList was returning a list of assignable types - /// not explicit types which is sort of ideal but is confusing so we'll do it the less confusing way. - /// - [Test] - public void TypeList_Resolves_Explicit_Types() - { - var types = new HashSet(); - - var propEditors = new PluginManager.TypeList(PluginManager.TypeResolutionKind.FindAllTypes); - propEditors.AddType(typeof(LabelPropertyEditor)); - types.Add(propEditors); - - var found = types.SingleOrDefault(x => x.IsTypeList(PluginManager.TypeResolutionKind.FindAllTypes)); - - Assert.IsNotNull(found); - - //This should not find a type list of this type - var shouldNotFind = types.SingleOrDefault(x => x.IsTypeList(PluginManager.TypeResolutionKind.FindAllTypes)); - - Assert.IsNull(shouldNotFind); - } - - [XsltExtension("Blah.Blah")] - public class MyXsltExtension - { - - } - - - [Umbraco.Web.BaseRest.RestExtension("Blah")] - public class MyRestExtesion - { - - } - - public interface IFindMe - { - - } - - public class FindMe1 : IFindMe - { - - } - - public class FindMe2 : IFindMe - { - - } - - } +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using NUnit.Framework; +using SqlCE4Umbraco; +using umbraco; +using umbraco.businesslogic; +using umbraco.cms.businesslogic; +using Umbraco.Core; +using Umbraco.Core.IO; +using Umbraco.Core.PropertyEditors; +using umbraco.DataLayer; +using umbraco.editorControls; +using umbraco.MacroEngines; +using Umbraco.Tests.TestHelpers; +using umbraco.uicontrols; +using Umbraco.Web; +using Umbraco.Web.PropertyEditors; + +namespace Umbraco.Tests.Plugins +{ + + [TestFixture] + public class PluginManagerTests + { + + [SetUp] + public void Initialize() + { + TestHelper.SetupLog4NetForTests(); + + //this ensures its reset + PluginManager.Current = new PluginManager(false); + + //for testing, we'll specify which assemblies are scanned for the PluginTypeResolver + //TODO: Should probably update this so it only searches this assembly and add custom types to be found + PluginManager.Current.AssembliesToScan = new[] + { + this.GetType().Assembly, + typeof(ApplicationStartupHandler).Assembly, + typeof(SqlCEHelper).Assembly, + typeof(CMSNode).Assembly, + typeof(System.Guid).Assembly, + typeof(NUnit.Framework.Assert).Assembly, + typeof(Microsoft.CSharp.CSharpCodeProvider).Assembly, + typeof(System.Xml.NameTable).Assembly, + typeof(System.Configuration.GenericEnumConverter).Assembly, + typeof(System.Web.SiteMap).Assembly, + typeof(TabPage).Assembly, + typeof(System.Web.Mvc.ActionResult).Assembly, + typeof(TypeFinder).Assembly, + typeof(ISqlHelper).Assembly, + typeof(ICultureDictionary).Assembly, + typeof(UmbracoContext).Assembly, + typeof(BaseDataType).Assembly + }; + } + + [TearDown] + public void TearDown() + { + PluginManager.Current = null; + } + + private DirectoryInfo PrepareFolder() + { + var assDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory; + var dir = Directory.CreateDirectory(Path.Combine(assDir.FullName, "PluginManager", Guid.NewGuid().ToString("N"))); + foreach (var f in dir.GetFiles()) + { + f.Delete(); + } + return dir; + } + + //[Test] + //public void Scan_Vs_Load_Benchmark() + //{ + // var pluginManager = new PluginManager(false); + // var watch = new Stopwatch(); + // watch.Start(); + // for (var i = 0; i < 1000; i++) + // { + // var type2 = Type.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); + // var type3 = Type.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); + // var type4 = Type.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); + // var type5 = Type.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); + // } + // watch.Stop(); + // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds); + // watch.Start(); + // for (var i = 0; i < 1000; i++) + // { + // var type2 = BuildManager.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); + // var type3 = BuildManager.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); + // var type4 = BuildManager.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); + // var type5 = BuildManager.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); + // } + // watch.Stop(); + // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds); + // watch.Reset(); + // watch.Start(); + // for (var i = 0; i < 1000; i++) + // { + // var refreshers = pluginManager.ResolveTypes(false); + // } + // watch.Stop(); + // Debug.WriteLine("TOTAL TIME (2nd round): " + watch.ElapsedMilliseconds); + //} + + ////NOTE: This test shows that Type.GetType is 100% faster than Assembly.Load(..).GetType(...) so we'll use that :) + //[Test] + //public void Load_Type_Benchmark() + //{ + // var watch = new Stopwatch(); + // watch.Start(); + // for (var i = 0; i < 1000; i++) + // { + // var type2 = Type.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); + // var type3 = Type.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); + // var type4 = Type.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); + // var type5 = Type.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null"); + // } + // watch.Stop(); + // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds); + // watch.Reset(); + // watch.Start(); + // for (var i = 0; i < 1000; i++) + // { + // var type2 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null") + // .GetType("umbraco.macroCacheRefresh"); + // var type3 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null") + // .GetType("umbraco.templateCacheRefresh"); + // var type4 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null") + // .GetType("umbraco.presentation.cache.MediaLibraryRefreshers"); + // var type5 = Assembly.Load("umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null") + // .GetType("umbraco.presentation.cache.pageRefresher"); + // } + // watch.Stop(); + // Debug.WriteLine("TOTAL TIME (2nd round): " + watch.ElapsedMilliseconds); + // watch.Reset(); + // watch.Start(); + // for (var i = 0; i < 1000; i++) + // { + // var type2 = BuildManager.GetType("umbraco.macroCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); + // var type3 = BuildManager.GetType("umbraco.templateCacheRefresh, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); + // var type4 = BuildManager.GetType("umbraco.presentation.cache.MediaLibraryRefreshers, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); + // var type5 = BuildManager.GetType("umbraco.presentation.cache.pageRefresher, umbraco, Version=1.0.4698.259, Culture=neutral, PublicKeyToken=null", true); + // } + // watch.Stop(); + // Debug.WriteLine("TOTAL TIME (1st round): " + watch.ElapsedMilliseconds); + //} + + [Test] + public void Detect_Legacy_Plugin_File_List() + { + var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache"); + var manager = new PluginManager(false); + var filePath= Path.Combine(tempFolder, string.Format("umbraco-plugins.{0}.list", NetworkHelper.FileSafeMachineName)); + + File.WriteAllText(filePath, @" + + + + +"); + + Assert.IsTrue(manager.DetectLegacyPluginListFile()); + + File.Delete(filePath); + + //now create a valid one + File.WriteAllText(filePath, @" + + + + +"); + + Assert.IsFalse(manager.DetectLegacyPluginListFile()); + } + + [Test] + public void Create_Cached_Plugin_File() + { + var types = new[] { typeof(PluginManager), typeof(PluginManagerTests), typeof(UmbracoContext) }; + + var manager = new PluginManager(false); + //yes this is silly, none of these types inherit from string, but this is just to test the xml file format + manager.UpdateCachedPluginsFile(types, PluginManager.TypeResolutionKind.FindAllTypes); + + var plugins = manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAllTypes); + var diffType = manager.TryGetCachedPluginsFromFile(PluginManager.TypeResolutionKind.FindAttributedTypes); + + Assert.IsTrue(plugins.Success); + //this will be false since there is no cache of that type resolution kind + Assert.IsFalse(diffType.Success); + + Assert.AreEqual(3, plugins.Result.Count()); + var shouldContain = types.Select(x => x.AssemblyQualifiedName); + //ensure they are all found + Assert.IsTrue(plugins.Result.ContainsAll(shouldContain)); + } + + [Test] + public void PluginHash_From_String() + { + var s = "hello my name is someone".GetHashCode().ToString("x", CultureInfo.InvariantCulture); + var output = PluginManager.ConvertPluginsHashFromHex(s); + Assert.AreNotEqual(0, output); + } + + [Test] + public void Get_Plugins_Hash() + { + //Arrange + var dir = PrepareFolder(); + var d1 = dir.CreateSubdirectory("1"); + var d2 = dir.CreateSubdirectory("2"); + var d3 = dir.CreateSubdirectory("3"); + var d4 = dir.CreateSubdirectory("4"); + var f1 = new FileInfo(Path.Combine(d1.FullName, "test1.dll")); + var f2 = new FileInfo(Path.Combine(d1.FullName, "test2.dll")); + var f3 = new FileInfo(Path.Combine(d2.FullName, "test1.dll")); + var f4 = new FileInfo(Path.Combine(d2.FullName, "test2.dll")); + var f5 = new FileInfo(Path.Combine(d3.FullName, "test1.dll")); + var f6 = new FileInfo(Path.Combine(d3.FullName, "test2.dll")); + var f7 = new FileInfo(Path.Combine(d4.FullName, "test1.dll")); + f1.CreateText().Close(); + f2.CreateText().Close(); + f3.CreateText().Close(); + f4.CreateText().Close(); + f5.CreateText().Close(); + f6.CreateText().Close(); + f7.CreateText().Close(); + var list1 = new[] { f1, f2, f3, f4, f5, f6 }; + var list2 = new[] { f1, f3, f5 }; + var list3 = new[] { f1, f3, f5, f7 }; + + //Act + var hash1 = PluginManager.GetFileHash(list1); + var hash2 = PluginManager.GetFileHash(list2); + var hash3 = PluginManager.GetFileHash(list3); + + //Assert + Assert.AreNotEqual(hash1, hash2); + Assert.AreNotEqual(hash1, hash3); + Assert.AreNotEqual(hash2, hash3); + + Assert.AreEqual(hash1, PluginManager.GetFileHash(list1)); + } + + [Test] + public void Ensure_Only_One_Type_List_Created() + { + var foundTypes1 = PluginManager.Current.ResolveFindMeTypes(); + var foundTypes2 = PluginManager.Current.ResolveFindMeTypes(); + Assert.AreEqual(1, + PluginManager.Current.GetTypeLists() + .Count(x => x.IsTypeList(PluginManager.TypeResolutionKind.FindAllTypes))); + } + + [Test] + public void Resolves_Assigned_Mappers() + { + var foundTypes1 = PluginManager.Current.ResolveAssignedMapperTypes(); + Assert.AreEqual(22, foundTypes1.Count()); + } + + [Test] + public void Resolves_Types() + { + var foundTypes1 = PluginManager.Current.ResolveFindMeTypes(); + Assert.AreEqual(2, foundTypes1.Count()); + } + + [Test] + public void Resolves_Attributed_Trees() + { + var trees = PluginManager.Current.ResolveAttributedTrees(); + Assert.AreEqual(19, trees.Count()); + } + + [Test] + public void Resolves_Actions() + { + var actions = PluginManager.Current.ResolveActions(); + Assert.AreEqual(36, actions.Count()); + } + + [Test] + public void Resolves_Trees() + { + var trees = PluginManager.Current.ResolveTrees(); + Assert.AreEqual(39, trees.Count()); + } + + [Test] + public void Resolves_Applications() + { + var apps = PluginManager.Current.ResolveApplications(); + Assert.AreEqual(7, apps.Count()); + } + + [Test] + public void Resolves_DataTypes() + { + var types = PluginManager.Current.ResolveDataTypes(); + Assert.AreEqual(35, types.Count()); + } + + [Test] + public void Resolves_RazorDataTypeModels() + { + var types = PluginManager.Current.ResolveRazorDataTypeModels(); + Assert.AreEqual(2, types.Count()); + } + + [Test] + public void Resolves_RestExtensions() + { + var types = PluginManager.Current.ResolveRestExtensions(); + Assert.AreEqual(3, types.Count()); + } + + [Test] + public void Resolves_XsltExtensions() + { + var types = PluginManager.Current.ResolveXsltExtensions(); + Assert.AreEqual(3, types.Count()); + } + + /// + /// This demonstrates this issue: http://issues.umbraco.org/issue/U4-3505 - the TypeList was returning a list of assignable types + /// not explicit types which is sort of ideal but is confusing so we'll do it the less confusing way. + /// + [Test] + public void TypeList_Resolves_Explicit_Types() + { + var types = new HashSet(); + + var propEditors = new PluginManager.TypeList(PluginManager.TypeResolutionKind.FindAllTypes); + propEditors.AddType(typeof(LabelPropertyEditor)); + types.Add(propEditors); + + var found = types.SingleOrDefault(x => x.IsTypeList(PluginManager.TypeResolutionKind.FindAllTypes)); + + Assert.IsNotNull(found); + + //This should not find a type list of this type + var shouldNotFind = types.SingleOrDefault(x => x.IsTypeList(PluginManager.TypeResolutionKind.FindAllTypes)); + + Assert.IsNull(shouldNotFind); + } + + [XsltExtension("Blah.Blah")] + public class MyXsltExtension + { + + } + + + [Umbraco.Web.BaseRest.RestExtension("Blah")] + public class MyRestExtesion + { + + } + + public interface IFindMe + { + + } + + public class FindMe1 : IFindMe + { + + } + + public class FindMe2 : IFindMe + { + + } + + } } \ No newline at end of file diff --git a/src/Umbraco.Tests/TypeFinderTests.cs b/src/Umbraco.Tests/Plugins/TypeFinderTests.cs similarity index 97% rename from src/Umbraco.Tests/TypeFinderTests.cs rename to src/Umbraco.Tests/Plugins/TypeFinderTests.cs index d9952a9ac0..8611570ef3 100644 --- a/src/Umbraco.Tests/TypeFinderTests.cs +++ b/src/Umbraco.Tests/Plugins/TypeFinderTests.cs @@ -1,641 +1,638 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Security; -using System.Text; -using System.Threading; -using System.Web; -using System.Web.Compilation; -using NUnit.Framework; -using SqlCE4Umbraco; -using Umbraco.Core; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Tests; -using Umbraco.Tests.TestHelpers; -using Umbraco.Web.BaseRest; -using umbraco; -using umbraco.DataLayer; -using umbraco.MacroEngines; -using umbraco.businesslogic; -using umbraco.cms.businesslogic; -using umbraco.editorControls.tags; -using umbraco.interfaces; -using umbraco.uicontrols; - -namespace Umbraco.Tests -{ - - /// - /// Tests for typefinder - /// - [TestFixture] - public class TypeFinderTests - { - /// - /// List of assemblies to scan - /// - private Assembly[] _assemblies; - - [SetUp] - public void Initialize() - { - TestHelper.SetupLog4NetForTests(); - - _assemblies = new[] - { - this.GetType().Assembly, - typeof(ApplicationStartupHandler).Assembly, - typeof(SqlCEHelper).Assembly, - typeof(CMSNode).Assembly, - typeof(System.Guid).Assembly, - typeof(NUnit.Framework.Assert).Assembly, - typeof(Microsoft.CSharp.CSharpCodeProvider).Assembly, - typeof(System.Xml.NameTable).Assembly, - typeof(System.Configuration.GenericEnumConverter).Assembly, - typeof(System.Web.SiteMap).Assembly, - typeof(TabPage).Assembly, - typeof(System.Web.Mvc.ActionResult).Assembly, - typeof(TypeFinder).Assembly, - typeof(ISqlHelper).Assembly, - typeof(ICultureDictionary).Assembly, - typeof(Tag).Assembly, - typeof(global::UmbracoExamine.BaseUmbracoIndexer).Assembly - }; - - } - - [Test] - public void Find_Class_Of_Type_With_Attribute() - { - - var typesFound = TypeFinder.FindClassesOfTypeWithAttribute(_assemblies); - Assert.AreEqual(2, typesFound.Count()); - } - - [Test] - public void Find_Classes_Of_Type() - { - var typesFound = TypeFinder.FindClassesOfType(_assemblies); - var originalTypesFound = TypeFinderOriginal.FindClassesOfType(_assemblies); - - Assert.AreEqual(originalTypesFound.Count(), typesFound.Count()); - Assert.AreEqual(5, typesFound.Count()); - Assert.AreEqual(5, originalTypesFound.Count()); - } - - [Test] - public void Find_Classes_With_Attribute() - { - var typesFound = TypeFinder.FindClassesWithAttribute(_assemblies); - Assert.AreEqual(1, typesFound.Count()); - } - - [Ignore] - [Test] - public void Benchmark_Original_Finder() - { - using (DisposableTimer.TraceDuration("Starting test", "Finished test")) - { - using (DisposableTimer.TraceDuration("Starting FindClassesOfType", "Finished FindClassesOfType")) - { - for (var i = 0; i < 1000; i++) - { - Assert.Greater(TypeFinderOriginal.FindClassesOfType(_assemblies).Count(), 0); - } - } - using (DisposableTimer.TraceDuration("Starting FindClassesOfTypeWithAttribute", "Finished FindClassesOfTypeWithAttribute")) - { - for (var i = 0; i < 1000; i++) - { - Assert.Greater(TypeFinderOriginal.FindClassesOfTypeWithAttribute(_assemblies).Count(), 0); - } - } - using (DisposableTimer.TraceDuration("Starting FindClassesWithAttribute", "Finished FindClassesWithAttribute")) - { - for (var i = 0; i < 1000; i++) - { - Assert.Greater(TypeFinderOriginal.FindClassesWithAttribute(_assemblies).Count(), 0); - } - } - } - - } - - [Ignore] - [Test] - public void Benchmark_New_Finder() - { - using (DisposableTimer.TraceDuration("Starting test", "Finished test")) - { - using (DisposableTimer.TraceDuration("Starting FindClassesOfType", "Finished FindClassesOfType")) - { - for (var i = 0; i < 1000; i++) - { - Assert.Greater(TypeFinder.FindClassesOfType(_assemblies).Count(), 0); - } - } - using (DisposableTimer.TraceDuration("Starting FindClassesOfTypeWithAttribute", "Finished FindClassesOfTypeWithAttribute")) - { - for (var i = 0; i < 1000; i++) - { - Assert.Greater(TypeFinder.FindClassesOfTypeWithAttribute(_assemblies).Count(), 0); - } - } - using (DisposableTimer.TraceDuration("Starting FindClassesWithAttribute", "Finished FindClassesWithAttribute")) - { - for (var i = 0; i < 1000; i++) - { - Assert.Greater(TypeFinder.FindClassesWithAttribute(_assemblies).Count(), 0); - } - } - } - - } - - public class MyTag : ITag - { - public int Id { get; private set; } - public string TagCaption { get; private set; } - public string Group { get; private set; } - } - - public class MySuperTag : MyTag - { - - } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] - public class MyTestAttribute : Attribute - { - - } - - public abstract class TestEditor - { - - } - - [MyTestAttribute] - public class BenchmarkTestEditor : TestEditor - { - - } - - [MyTestAttribute] - public class MyOtherTestEditor : TestEditor - { - - } - - //USED FOR THE ABOVE TESTS - // see this issue for details: http://issues.umbraco.org/issue/U4-1187 - internal static class TypeFinderOriginal - { - - private static readonly ConcurrentBag LocalFilteredAssemblyCache = new ConcurrentBag(); - private static readonly ReaderWriterLockSlim LocalFilteredAssemblyCacheLocker = new ReaderWriterLockSlim(); - private static ReadOnlyCollection _allAssemblies = null; - private static ReadOnlyCollection _binFolderAssemblies = null; - private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(); - - /// - /// lazily load a reference to all assemblies and only local assemblies. - /// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder - /// - /// - /// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been - /// loaded in the CLR, not all assemblies. - /// See these threads: - /// http://issues.umbraco.org/issue/U5-198 - /// http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app - /// http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl - /// - internal static IEnumerable GetAllAssemblies() - { - if (_allAssemblies == null) - { - using (new WriteLock(Locker)) - { - List assemblies = null; - try - { - var isHosted = HttpContext.Current != null; - - try - { - if (isHosted) - { - assemblies = new List(BuildManager.GetReferencedAssemblies().Cast()); - } - } - catch (InvalidOperationException e) - { - if (!(e.InnerException is SecurityException)) - throw; - } - - - if (assemblies == null) - { - //NOTE: we cannot use AppDomain.CurrentDomain.GetAssemblies() because this only returns assemblies that have - // already been loaded in to the app domain, instead we will look directly into the bin folder and load each one. - var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory; - var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList(); - assemblies = new List(); - foreach (var a in binAssemblyFiles) - { - try - { - var assName = AssemblyName.GetAssemblyName(a); - var ass = Assembly.Load(assName); - assemblies.Add(ass); - } - catch (Exception e) - { - if (e is SecurityException || e is BadImageFormatException) - { - //swallow these exceptions - } - else - { - throw; - } - } - } - } - - //if for some reason they are still no assemblies, then use the AppDomain to load in already loaded assemblies. - if (!assemblies.Any()) - { - assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies().ToList()); - } - - //here we are trying to get the App_Code assembly - var fileExtensions = new[] { ".cs", ".vb" }; //only vb and cs files are supported - var appCodeFolder = new DirectoryInfo(IOHelper.MapPath(IOHelper.ResolveUrl("~/App_code"))); - //check if the folder exists and if there are any files in it with the supported file extensions - if (appCodeFolder.Exists && (fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any()))) - { - var appCodeAssembly = Assembly.Load("App_Code"); - if (!assemblies.Contains(appCodeAssembly)) // BuildManager will find App_Code already - assemblies.Add(appCodeAssembly); - } - - //now set the _allAssemblies - _allAssemblies = new ReadOnlyCollection(assemblies); - - } - catch (InvalidOperationException e) - { - if (!(e.InnerException is SecurityException)) - throw; - - _binFolderAssemblies = _allAssemblies; - } - } - } - - return _allAssemblies; - } - - /// - /// Returns only assemblies found in the bin folder that have been loaded into the app domain. - /// - /// - /// - /// This will be used if we implement App_Plugins from Umbraco v5 but currently it is not used. - /// - internal static IEnumerable GetBinAssemblies() - { - - if (_binFolderAssemblies == null) - { - using (new WriteLock(Locker)) - { - var assemblies = GetAssembliesWithKnownExclusions().ToArray(); - var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory; - var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList(); - var domainAssemblyNames = binAssemblyFiles.Select(AssemblyName.GetAssemblyName); - var safeDomainAssemblies = new List(); - var binFolderAssemblies = new List(); - - foreach (var a in assemblies) - { - try - { - //do a test to see if its queryable in med trust - var assemblyFile = a.GetAssemblyFile(); - safeDomainAssemblies.Add(a); - } - catch (SecurityException) - { - //we will just ignore this because this will fail - //in medium trust for system assemblies, we get an exception but we just want to continue until we get to - //an assembly that is ok. - } - } - - foreach (var assemblyName in domainAssemblyNames) - { - try - { - var foundAssembly = safeDomainAssemblies.FirstOrDefault(a => a.GetAssemblyFile() == assemblyName.GetAssemblyFile()); - if (foundAssembly != null) - { - binFolderAssemblies.Add(foundAssembly); - } - } - catch (SecurityException) - { - //we will just ignore this because if we are trying to do a call to: - // AssemblyName.ReferenceMatchesDefinition(a.GetName(), assemblyName))) - //in medium trust for system assemblies, we get an exception but we just want to continue until we get to - //an assembly that is ok. - } - } - - _binFolderAssemblies = new ReadOnlyCollection(binFolderAssemblies); - } - } - return _binFolderAssemblies; - } - - /// - /// Return a list of found local Assemblies excluding the known assemblies we don't want to scan - /// and exluding the ones passed in and excluding the exclusion list filter, the results of this are - /// cached for perforance reasons. - /// - /// - /// - internal static IEnumerable GetAssembliesWithKnownExclusions( - IEnumerable excludeFromResults = null) - { - if (LocalFilteredAssemblyCache.Any()) return LocalFilteredAssemblyCache; - using (new WriteLock(LocalFilteredAssemblyCacheLocker)) - { - var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter); - assemblies.ForEach(LocalFilteredAssemblyCache.Add); - } - return LocalFilteredAssemblyCache; - } - - /// - /// Return a list of found local Assemblies and exluding the ones passed in and excluding the exclusion list filter - /// - /// - /// - /// - private static IEnumerable GetFilteredAssemblies( - IEnumerable excludeFromResults = null, - string[] exclusionFilter = null) - { - if (excludeFromResults == null) - excludeFromResults = new List(); - if (exclusionFilter == null) - exclusionFilter = new string[] { }; - - return GetAllAssemblies() - .Where(x => !excludeFromResults.Contains(x) - && !x.GlobalAssemblyCache - && !exclusionFilter.Any(f => x.FullName.StartsWith(f))); - } - - /// - /// this is our assembly filter to filter out known types that def dont contain types we'd like to find or plugins - /// - /// - /// NOTE the comma vs period... comma delimits the name in an Assembly FullName property so if it ends with comma then its an exact name match - /// - internal static readonly string[] KnownAssemblyExclusionFilter = new[] - { - "mscorlib,", - "System.", - "Antlr3.", - "Autofac.", - "Autofac,", - "Castle.", - "ClientDependency.", - "DataAnnotationsExtensions.", - "DataAnnotationsExtensions,", - "Dynamic,", - "HtmlDiff,", - "Iesi.Collections,", - "log4net,", - "Microsoft.", - "Newtonsoft.", - "NHibernate.", - "NHibernate,", - "NuGet.", - "RouteDebugger,", - "SqlCE4Umbraco,", - "umbraco.datalayer,", - "umbraco.interfaces,", - "umbraco.providers,", - "Umbraco.Web.UI,", - "umbraco.webservices", - "Lucene.", - "Examine,", - "Examine.", - "ServiceStack.", - "MySql.", - "HtmlAgilityPack.", - "TidyNet.", - "ICSharpCode.", - "CookComputing.", - /* Mono */ - "MonoDevelop.NUnit" - }; - - public static IEnumerable FindClassesOfTypeWithAttribute() - where TAttribute : Attribute - { - return FindClassesOfTypeWithAttribute(GetAssembliesWithKnownExclusions(), true); - } - - public static IEnumerable FindClassesOfTypeWithAttribute(IEnumerable assemblies) - where TAttribute : Attribute - { - return FindClassesOfTypeWithAttribute(assemblies, true); - } - - public static IEnumerable FindClassesOfTypeWithAttribute(IEnumerable assemblies, bool onlyConcreteClasses) - where TAttribute : Attribute - { - if (assemblies == null) throw new ArgumentNullException("assemblies"); - - var l = new List(); - foreach (var a in assemblies) - { - var types = from t in GetTypesWithFormattedException(a) - where !t.IsInterface - && typeof(T).IsAssignableFrom(t) - && t.GetCustomAttributes(false).Any() - && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract)) - select t; - l.AddRange(types); - } - - return l; - } - - /// - /// Searches all filtered local assemblies specified for classes of the type passed in. - /// - /// - /// - public static IEnumerable FindClassesOfType() - { - return FindClassesOfType(GetAssembliesWithKnownExclusions(), true); - } - - /// - /// Returns all types found of in the assemblies specified of type T - /// - /// - /// - /// - /// - public static IEnumerable FindClassesOfType(IEnumerable assemblies, bool onlyConcreteClasses) - { - if (assemblies == null) throw new ArgumentNullException("assemblies"); - - return GetAssignablesFromType(assemblies, onlyConcreteClasses); - } - - /// - /// Returns all types found of in the assemblies specified of type T - /// - /// - /// - /// - public static IEnumerable FindClassesOfType(IEnumerable assemblies) - { - return FindClassesOfType(assemblies, true); - } - - /// - /// Finds the classes with attribute. - /// - /// - /// The assemblies. - /// if set to true only concrete classes. - /// - public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies, bool onlyConcreteClasses) - where T : Attribute - { - return FindClassesWithAttribute(typeof(T), assemblies, onlyConcreteClasses); - } - - /// - /// Finds the classes with attribute. - /// - /// The attribute type - /// The assemblies. - /// if set to true only concrete classes. - /// - public static IEnumerable FindClassesWithAttribute(Type type, IEnumerable assemblies, bool onlyConcreteClasses) - { - if (assemblies == null) throw new ArgumentNullException("assemblies"); - if (!TypeHelper.IsTypeAssignableFrom(type)) - throw new ArgumentException("The type specified: " + type + " is not an Attribute type"); - - var l = new List(); - foreach (var a in assemblies) - { - var types = from t in GetTypesWithFormattedException(a) - where !t.IsInterface && t.GetCustomAttributes(type, false).Any() && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract)) - select t; - l.AddRange(types); - } - - return l; - } - - /// - /// Finds the classes with attribute. - /// - /// - /// The assemblies. - /// - public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies) - where T : Attribute - { - return FindClassesWithAttribute(assemblies, true); - } - - /// - /// Finds the classes with attribute in filtered local assemblies - /// - /// - /// - public static IEnumerable FindClassesWithAttribute() - where T : Attribute - { - return FindClassesWithAttribute(GetAssembliesWithKnownExclusions()); - } - - - #region Private methods - - /// - /// Gets a collection of assignables of type T from a collection of assemblies - /// - /// - /// - /// - /// - private static IEnumerable GetAssignablesFromType(IEnumerable assemblies, bool onlyConcreteClasses) - { - return GetTypes(typeof(T), assemblies, onlyConcreteClasses); - } - - private static IEnumerable GetTypes(Type assignTypeFrom, IEnumerable assemblies, bool onlyConcreteClasses) - { - var l = new List(); - foreach (var a in assemblies) - { - var types = from t in GetTypesWithFormattedException(a) - where !t.IsInterface && assignTypeFrom.IsAssignableFrom(t) && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract)) - select t; - l.AddRange(types); - } - return l; - } - - private static IEnumerable GetTypesWithFormattedException(Assembly a) - { - //if the assembly is dynamic, do not try to scan it - if (a.IsDynamic) - return Enumerable.Empty(); - - try - { - return a.GetExportedTypes(); - } - catch (ReflectionTypeLoadException ex) - { - var sb = new StringBuilder(); - sb.AppendLine("Could not load types from assembly " + a.FullName + ", errors:"); - foreach (var loaderException in ex.LoaderExceptions.WhereNotNull()) - { - sb.AppendLine("Exception: " + loaderException.ToString()); - } - throw new ReflectionTypeLoadException(ex.Types, ex.LoaderExceptions, sb.ToString()); - } - } - - #endregion - - - - } - } - - +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Security; +using System.Text; +using System.Threading; +using System.Web; +using System.Web.Compilation; +using NUnit.Framework; +using SqlCE4Umbraco; +using umbraco; +using umbraco.businesslogic; +using umbraco.cms.businesslogic; +using Umbraco.Core; +using Umbraco.Core.IO; +using umbraco.DataLayer; +using umbraco.editorControls.tags; +using umbraco.interfaces; +using umbraco.MacroEngines; +using Umbraco.Tests.TestHelpers; +using umbraco.uicontrols; +using Umbraco.Web.BaseRest; + +namespace Umbraco.Tests.Plugins +{ + + /// + /// Tests for typefinder + /// + [TestFixture] + public class TypeFinderTests + { + /// + /// List of assemblies to scan + /// + private Assembly[] _assemblies; + + [SetUp] + public void Initialize() + { + TestHelper.SetupLog4NetForTests(); + + _assemblies = new[] + { + this.GetType().Assembly, + typeof(ApplicationStartupHandler).Assembly, + typeof(SqlCEHelper).Assembly, + typeof(CMSNode).Assembly, + typeof(System.Guid).Assembly, + typeof(NUnit.Framework.Assert).Assembly, + typeof(Microsoft.CSharp.CSharpCodeProvider).Assembly, + typeof(System.Xml.NameTable).Assembly, + typeof(System.Configuration.GenericEnumConverter).Assembly, + typeof(System.Web.SiteMap).Assembly, + typeof(TabPage).Assembly, + typeof(System.Web.Mvc.ActionResult).Assembly, + typeof(TypeFinder).Assembly, + typeof(ISqlHelper).Assembly, + typeof(ICultureDictionary).Assembly, + typeof(Tag).Assembly, + typeof(global::UmbracoExamine.BaseUmbracoIndexer).Assembly + }; + + } + + [Test] + public void Find_Class_Of_Type_With_Attribute() + { + + var typesFound = TypeFinder.FindClassesOfTypeWithAttribute(_assemblies); + Assert.AreEqual(2, typesFound.Count()); + } + + [Test] + public void Find_Classes_Of_Type() + { + var typesFound = TypeFinder.FindClassesOfType(_assemblies); + var originalTypesFound = TypeFinderOriginal.FindClassesOfType(_assemblies); + + Assert.AreEqual(originalTypesFound.Count(), typesFound.Count()); + Assert.AreEqual(5, typesFound.Count()); + Assert.AreEqual(5, originalTypesFound.Count()); + } + + [Test] + public void Find_Classes_With_Attribute() + { + var typesFound = TypeFinder.FindClassesWithAttribute(_assemblies); + Assert.AreEqual(1, typesFound.Count()); + } + + [Ignore] + [Test] + public void Benchmark_Original_Finder() + { + using (DisposableTimer.TraceDuration("Starting test", "Finished test")) + { + using (DisposableTimer.TraceDuration("Starting FindClassesOfType", "Finished FindClassesOfType")) + { + for (var i = 0; i < 1000; i++) + { + Assert.Greater(TypeFinderOriginal.FindClassesOfType(_assemblies).Count(), 0); + } + } + using (DisposableTimer.TraceDuration("Starting FindClassesOfTypeWithAttribute", "Finished FindClassesOfTypeWithAttribute")) + { + for (var i = 0; i < 1000; i++) + { + Assert.Greater(TypeFinderOriginal.FindClassesOfTypeWithAttribute(_assemblies).Count(), 0); + } + } + using (DisposableTimer.TraceDuration("Starting FindClassesWithAttribute", "Finished FindClassesWithAttribute")) + { + for (var i = 0; i < 1000; i++) + { + Assert.Greater(TypeFinderOriginal.FindClassesWithAttribute(_assemblies).Count(), 0); + } + } + } + + } + + [Ignore] + [Test] + public void Benchmark_New_Finder() + { + using (DisposableTimer.TraceDuration("Starting test", "Finished test")) + { + using (DisposableTimer.TraceDuration("Starting FindClassesOfType", "Finished FindClassesOfType")) + { + for (var i = 0; i < 1000; i++) + { + Assert.Greater(TypeFinder.FindClassesOfType(_assemblies).Count(), 0); + } + } + using (DisposableTimer.TraceDuration("Starting FindClassesOfTypeWithAttribute", "Finished FindClassesOfTypeWithAttribute")) + { + for (var i = 0; i < 1000; i++) + { + Assert.Greater(TypeFinder.FindClassesOfTypeWithAttribute(_assemblies).Count(), 0); + } + } + using (DisposableTimer.TraceDuration("Starting FindClassesWithAttribute", "Finished FindClassesWithAttribute")) + { + for (var i = 0; i < 1000; i++) + { + Assert.Greater(TypeFinder.FindClassesWithAttribute(_assemblies).Count(), 0); + } + } + } + + } + + public class MyTag : ITag + { + public int Id { get; private set; } + public string TagCaption { get; private set; } + public string Group { get; private set; } + } + + public class MySuperTag : MyTag + { + + } + + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] + public class MyTestAttribute : Attribute + { + + } + + public abstract class TestEditor + { + + } + + [MyTest] + public class BenchmarkTestEditor : TestEditor + { + + } + + [MyTest] + public class MyOtherTestEditor : TestEditor + { + + } + + //USED FOR THE ABOVE TESTS + // see this issue for details: http://issues.umbraco.org/issue/U4-1187 + internal static class TypeFinderOriginal + { + + private static readonly ConcurrentBag LocalFilteredAssemblyCache = new ConcurrentBag(); + private static readonly ReaderWriterLockSlim LocalFilteredAssemblyCacheLocker = new ReaderWriterLockSlim(); + private static ReadOnlyCollection _allAssemblies = null; + private static ReadOnlyCollection _binFolderAssemblies = null; + private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(); + + /// + /// lazily load a reference to all assemblies and only local assemblies. + /// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder + /// + /// + /// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been + /// loaded in the CLR, not all assemblies. + /// See these threads: + /// http://issues.umbraco.org/issue/U5-198 + /// http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app + /// http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl + /// + internal static IEnumerable GetAllAssemblies() + { + if (_allAssemblies == null) + { + using (new WriteLock(Locker)) + { + List assemblies = null; + try + { + var isHosted = HttpContext.Current != null; + + try + { + if (isHosted) + { + assemblies = new List(BuildManager.GetReferencedAssemblies().Cast()); + } + } + catch (InvalidOperationException e) + { + if (!(e.InnerException is SecurityException)) + throw; + } + + + if (assemblies == null) + { + //NOTE: we cannot use AppDomain.CurrentDomain.GetAssemblies() because this only returns assemblies that have + // already been loaded in to the app domain, instead we will look directly into the bin folder and load each one. + var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory; + var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList(); + assemblies = new List(); + foreach (var a in binAssemblyFiles) + { + try + { + var assName = AssemblyName.GetAssemblyName(a); + var ass = Assembly.Load(assName); + assemblies.Add(ass); + } + catch (Exception e) + { + if (e is SecurityException || e is BadImageFormatException) + { + //swallow these exceptions + } + else + { + throw; + } + } + } + } + + //if for some reason they are still no assemblies, then use the AppDomain to load in already loaded assemblies. + if (!assemblies.Any()) + { + assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies().ToList()); + } + + //here we are trying to get the App_Code assembly + var fileExtensions = new[] { ".cs", ".vb" }; //only vb and cs files are supported + var appCodeFolder = new DirectoryInfo(IOHelper.MapPath(IOHelper.ResolveUrl("~/App_code"))); + //check if the folder exists and if there are any files in it with the supported file extensions + if (appCodeFolder.Exists && (fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any()))) + { + var appCodeAssembly = Assembly.Load("App_Code"); + if (!assemblies.Contains(appCodeAssembly)) // BuildManager will find App_Code already + assemblies.Add(appCodeAssembly); + } + + //now set the _allAssemblies + _allAssemblies = new ReadOnlyCollection(assemblies); + + } + catch (InvalidOperationException e) + { + if (!(e.InnerException is SecurityException)) + throw; + + _binFolderAssemblies = _allAssemblies; + } + } + } + + return _allAssemblies; + } + + /// + /// Returns only assemblies found in the bin folder that have been loaded into the app domain. + /// + /// + /// + /// This will be used if we implement App_Plugins from Umbraco v5 but currently it is not used. + /// + internal static IEnumerable GetBinAssemblies() + { + + if (_binFolderAssemblies == null) + { + using (new WriteLock(Locker)) + { + var assemblies = GetAssembliesWithKnownExclusions().ToArray(); + var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory; + var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList(); + var domainAssemblyNames = binAssemblyFiles.Select(AssemblyName.GetAssemblyName); + var safeDomainAssemblies = new List(); + var binFolderAssemblies = new List(); + + foreach (var a in assemblies) + { + try + { + //do a test to see if its queryable in med trust + var assemblyFile = a.GetAssemblyFile(); + safeDomainAssemblies.Add(a); + } + catch (SecurityException) + { + //we will just ignore this because this will fail + //in medium trust for system assemblies, we get an exception but we just want to continue until we get to + //an assembly that is ok. + } + } + + foreach (var assemblyName in domainAssemblyNames) + { + try + { + var foundAssembly = safeDomainAssemblies.FirstOrDefault(a => a.GetAssemblyFile() == assemblyName.GetAssemblyFile()); + if (foundAssembly != null) + { + binFolderAssemblies.Add(foundAssembly); + } + } + catch (SecurityException) + { + //we will just ignore this because if we are trying to do a call to: + // AssemblyName.ReferenceMatchesDefinition(a.GetName(), assemblyName))) + //in medium trust for system assemblies, we get an exception but we just want to continue until we get to + //an assembly that is ok. + } + } + + _binFolderAssemblies = new ReadOnlyCollection(binFolderAssemblies); + } + } + return _binFolderAssemblies; + } + + /// + /// Return a list of found local Assemblies excluding the known assemblies we don't want to scan + /// and exluding the ones passed in and excluding the exclusion list filter, the results of this are + /// cached for perforance reasons. + /// + /// + /// + internal static IEnumerable GetAssembliesWithKnownExclusions( + IEnumerable excludeFromResults = null) + { + if (LocalFilteredAssemblyCache.Any()) return LocalFilteredAssemblyCache; + using (new WriteLock(LocalFilteredAssemblyCacheLocker)) + { + var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter); + assemblies.ForEach(LocalFilteredAssemblyCache.Add); + } + return LocalFilteredAssemblyCache; + } + + /// + /// Return a list of found local Assemblies and exluding the ones passed in and excluding the exclusion list filter + /// + /// + /// + /// + private static IEnumerable GetFilteredAssemblies( + IEnumerable excludeFromResults = null, + string[] exclusionFilter = null) + { + if (excludeFromResults == null) + excludeFromResults = new List(); + if (exclusionFilter == null) + exclusionFilter = new string[] { }; + + return GetAllAssemblies() + .Where(x => !excludeFromResults.Contains(x) + && !x.GlobalAssemblyCache + && !exclusionFilter.Any(f => x.FullName.StartsWith(f))); + } + + /// + /// this is our assembly filter to filter out known types that def dont contain types we'd like to find or plugins + /// + /// + /// NOTE the comma vs period... comma delimits the name in an Assembly FullName property so if it ends with comma then its an exact name match + /// + internal static readonly string[] KnownAssemblyExclusionFilter = new[] + { + "mscorlib,", + "System.", + "Antlr3.", + "Autofac.", + "Autofac,", + "Castle.", + "ClientDependency.", + "DataAnnotationsExtensions.", + "DataAnnotationsExtensions,", + "Dynamic,", + "HtmlDiff,", + "Iesi.Collections,", + "log4net,", + "Microsoft.", + "Newtonsoft.", + "NHibernate.", + "NHibernate,", + "NuGet.", + "RouteDebugger,", + "SqlCE4Umbraco,", + "umbraco.datalayer,", + "umbraco.interfaces,", + "umbraco.providers,", + "Umbraco.Web.UI,", + "umbraco.webservices", + "Lucene.", + "Examine,", + "Examine.", + "ServiceStack.", + "MySql.", + "HtmlAgilityPack.", + "TidyNet.", + "ICSharpCode.", + "CookComputing.", + /* Mono */ + "MonoDevelop.NUnit" + }; + + public static IEnumerable FindClassesOfTypeWithAttribute() + where TAttribute : Attribute + { + return FindClassesOfTypeWithAttribute(GetAssembliesWithKnownExclusions(), true); + } + + public static IEnumerable FindClassesOfTypeWithAttribute(IEnumerable assemblies) + where TAttribute : Attribute + { + return FindClassesOfTypeWithAttribute(assemblies, true); + } + + public static IEnumerable FindClassesOfTypeWithAttribute(IEnumerable assemblies, bool onlyConcreteClasses) + where TAttribute : Attribute + { + if (assemblies == null) throw new ArgumentNullException("assemblies"); + + var l = new List(); + foreach (var a in assemblies) + { + var types = from t in GetTypesWithFormattedException(a) + where !t.IsInterface + && typeof(T).IsAssignableFrom(t) + && t.GetCustomAttributes(false).Any() + && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract)) + select t; + l.AddRange(types); + } + + return l; + } + + /// + /// Searches all filtered local assemblies specified for classes of the type passed in. + /// + /// + /// + public static IEnumerable FindClassesOfType() + { + return FindClassesOfType(GetAssembliesWithKnownExclusions(), true); + } + + /// + /// Returns all types found of in the assemblies specified of type T + /// + /// + /// + /// + /// + public static IEnumerable FindClassesOfType(IEnumerable assemblies, bool onlyConcreteClasses) + { + if (assemblies == null) throw new ArgumentNullException("assemblies"); + + return GetAssignablesFromType(assemblies, onlyConcreteClasses); + } + + /// + /// Returns all types found of in the assemblies specified of type T + /// + /// + /// + /// + public static IEnumerable FindClassesOfType(IEnumerable assemblies) + { + return FindClassesOfType(assemblies, true); + } + + /// + /// Finds the classes with attribute. + /// + /// + /// The assemblies. + /// if set to true only concrete classes. + /// + public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies, bool onlyConcreteClasses) + where T : Attribute + { + return FindClassesWithAttribute(typeof(T), assemblies, onlyConcreteClasses); + } + + /// + /// Finds the classes with attribute. + /// + /// The attribute type + /// The assemblies. + /// if set to true only concrete classes. + /// + public static IEnumerable FindClassesWithAttribute(Type type, IEnumerable assemblies, bool onlyConcreteClasses) + { + if (assemblies == null) throw new ArgumentNullException("assemblies"); + if (!TypeHelper.IsTypeAssignableFrom(type)) + throw new ArgumentException("The type specified: " + type + " is not an Attribute type"); + + var l = new List(); + foreach (var a in assemblies) + { + var types = from t in GetTypesWithFormattedException(a) + where !t.IsInterface && t.GetCustomAttributes(type, false).Any() && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract)) + select t; + l.AddRange(types); + } + + return l; + } + + /// + /// Finds the classes with attribute. + /// + /// + /// The assemblies. + /// + public static IEnumerable FindClassesWithAttribute(IEnumerable assemblies) + where T : Attribute + { + return FindClassesWithAttribute(assemblies, true); + } + + /// + /// Finds the classes with attribute in filtered local assemblies + /// + /// + /// + public static IEnumerable FindClassesWithAttribute() + where T : Attribute + { + return FindClassesWithAttribute(GetAssembliesWithKnownExclusions()); + } + + + #region Private methods + + /// + /// Gets a collection of assignables of type T from a collection of assemblies + /// + /// + /// + /// + /// + private static IEnumerable GetAssignablesFromType(IEnumerable assemblies, bool onlyConcreteClasses) + { + return GetTypes(typeof(T), assemblies, onlyConcreteClasses); + } + + private static IEnumerable GetTypes(Type assignTypeFrom, IEnumerable assemblies, bool onlyConcreteClasses) + { + var l = new List(); + foreach (var a in assemblies) + { + var types = from t in GetTypesWithFormattedException(a) + where !t.IsInterface && assignTypeFrom.IsAssignableFrom(t) && (!onlyConcreteClasses || (t.IsClass && !t.IsAbstract)) + select t; + l.AddRange(types); + } + return l; + } + + private static IEnumerable GetTypesWithFormattedException(Assembly a) + { + //if the assembly is dynamic, do not try to scan it + if (a.IsDynamic) + return Enumerable.Empty(); + + try + { + return a.GetExportedTypes(); + } + catch (ReflectionTypeLoadException ex) + { + var sb = new StringBuilder(); + sb.AppendLine("Could not load types from assembly " + a.FullName + ", errors:"); + foreach (var loaderException in ex.LoaderExceptions.WhereNotNull()) + { + sb.AppendLine("Exception: " + loaderException.ToString()); + } + throw new ReflectionTypeLoadException(ex.Types, ex.LoaderExceptions, sb.ToString()); + } + } + + #endregion + + + + } + } + + } \ No newline at end of file diff --git a/src/Umbraco.Tests/TypeHelperTests.cs b/src/Umbraco.Tests/Plugins/TypeHelperTests.cs similarity index 90% rename from src/Umbraco.Tests/TypeHelperTests.cs rename to src/Umbraco.Tests/Plugins/TypeHelperTests.cs index 9b8d38aec7..404dc00eaa 100644 --- a/src/Umbraco.Tests/TypeHelperTests.cs +++ b/src/Umbraco.Tests/Plugins/TypeHelperTests.cs @@ -1,79 +1,72 @@ -using System; -using System.ComponentModel; -using System.Data.Common; -using System.Data.Odbc; -using System.Data.OleDb; -using System.Data.SqlClient; -using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Web; -using Umbraco.Web.Cache; -using Umbraco.Web.Scheduling; -using UmbracoExamine; -using UmbracoExamine.DataServices; -using umbraco; -using umbraco.presentation; -using umbraco.presentation.nodeFactory; -using umbraco.presentation.umbraco.Search; - -namespace Umbraco.Tests -{ - /// - /// Tests for TypeHelper - /// - [TestFixture] - public class TypeHelperTests - { - - [Test] - public void Is_Static_Class() - { - Assert.IsTrue(TypeHelper.IsStaticClass(typeof(TypeHelper))); - Assert.IsFalse(TypeHelper.IsStaticClass(typeof(TypeHelperTests))); - } - - [Test] - public void Find_Common_Base_Class() - { - var t1 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand), - typeof (OdbcCommand), - typeof (SqlCommand)); - Assert.IsFalse(t1.Success); - - var t2 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand), - typeof (OdbcCommand), - typeof (SqlCommand), - typeof (Component)); - Assert.IsTrue(t2.Success); - Assert.AreEqual(typeof(Component), t2.Result); - - var t3 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand), - typeof (OdbcCommand), - typeof (SqlCommand), - typeof (Component), - typeof (Component).BaseType); - Assert.IsTrue(t3.Success); - Assert.AreEqual(typeof(MarshalByRefObject), t3.Result); - - var t4 = TypeHelper.GetLowestBaseType(typeof(OleDbCommand), - typeof(OdbcCommand), - typeof(SqlCommand), - typeof(Component), - typeof(Component).BaseType, - typeof(int)); - Assert.IsFalse(t4.Success); - - var t5 = TypeHelper.GetLowestBaseType(typeof(PropertyAliasDto)); - Assert.IsTrue(t5.Success); - Assert.AreEqual(typeof(PropertyAliasDto), t5.Result); - - var t6 = TypeHelper.GetLowestBaseType(typeof (IApplicationEventHandler), - typeof (Scheduler), - typeof(CacheRefresherEventHandler)); - Assert.IsTrue(t6.Success); - Assert.AreEqual(typeof(IApplicationEventHandler), t6.Result); - - } - - } +using System; +using System.ComponentModel; +using System.Data.Odbc; +using System.Data.OleDb; +using System.Data.SqlClient; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Web.Cache; +using Umbraco.Web.Scheduling; +using UmbracoExamine.DataServices; + +namespace Umbraco.Tests.Plugins +{ + /// + /// Tests for TypeHelper + /// + [TestFixture] + public class TypeHelperTests + { + + [Test] + public void Is_Static_Class() + { + Assert.IsTrue(TypeHelper.IsStaticClass(typeof(TypeHelper))); + Assert.IsFalse(TypeHelper.IsStaticClass(typeof(TypeHelperTests))); + } + + [Test] + public void Find_Common_Base_Class() + { + var t1 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand), + typeof (OdbcCommand), + typeof (SqlCommand)); + Assert.IsFalse(t1.Success); + + var t2 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand), + typeof (OdbcCommand), + typeof (SqlCommand), + typeof (Component)); + Assert.IsTrue(t2.Success); + Assert.AreEqual(typeof(Component), t2.Result); + + var t3 = TypeHelper.GetLowestBaseType(typeof (OleDbCommand), + typeof (OdbcCommand), + typeof (SqlCommand), + typeof (Component), + typeof (Component).BaseType); + Assert.IsTrue(t3.Success); + Assert.AreEqual(typeof(MarshalByRefObject), t3.Result); + + var t4 = TypeHelper.GetLowestBaseType(typeof(OleDbCommand), + typeof(OdbcCommand), + typeof(SqlCommand), + typeof(Component), + typeof(Component).BaseType, + typeof(int)); + Assert.IsFalse(t4.Success); + + var t5 = TypeHelper.GetLowestBaseType(typeof(PropertyAliasDto)); + Assert.IsTrue(t5.Success); + Assert.AreEqual(typeof(PropertyAliasDto), t5.Result); + + var t6 = TypeHelper.GetLowestBaseType(typeof (IApplicationEventHandler), + typeof (Scheduler), + typeof(CacheRefresherEventHandler)); + Assert.IsTrue(t6.Success); + Assert.AreEqual(typeof(IApplicationEventHandler), t6.Result); + + } + + } } \ No newline at end of file diff --git a/src/Umbraco.Tests/ServerEnvironmentHelperTests.cs b/src/Umbraco.Tests/ServerEnvironmentHelperTests.cs new file mode 100644 index 0000000000..237c6cb17d --- /dev/null +++ b/src/Umbraco.Tests/ServerEnvironmentHelperTests.cs @@ -0,0 +1,92 @@ +using System.Configuration; +using System.Linq; +using Moq; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Sync; + +namespace Umbraco.Tests +{ + [TestFixture] + public class ServerEnvironmentHelperTests + { + [Test] + public void Get_Base_Url_Single_Server_Orig_Request_Url_No_SSL() + { + var appContext = new ApplicationContext(null) + { + OriginalRequestUrl = "test.com" + }; + + ConfigurationManager.AppSettings.Set("umbracoUseSSL", "false"); + + var result = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl( + appContext, + Mock.Of( + section => + section.DistributedCall == Mock.Of(callSection => callSection.Servers == Enumerable.Empty()) + && section.ScheduledTasks == Mock.Of())); + + + Assert.AreEqual("http://test.com/", result); + } + + [Test] + public void Get_Base_Url_Single_Server_Orig_Request_Url_With_SSL() + { + var appContext = new ApplicationContext(null) + { + OriginalRequestUrl = "test.com" + }; + + ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); + + var result = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl( + appContext, + Mock.Of( + section => + section.DistributedCall == Mock.Of(callSection => callSection.Servers == Enumerable.Empty()) + && section.ScheduledTasks == Mock.Of())); + + + Assert.AreEqual("https://test.com/", result); + } + + [Test] + public void Get_Base_Url_Single_Server_Via_Config_Url_No_SSL() + { + var appContext = new ApplicationContext(null); + + ConfigurationManager.AppSettings.Set("umbracoUseSSL", "false"); + + var result = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl( + appContext, + Mock.Of( + section => + section.DistributedCall == Mock.Of(callSection => callSection.Servers == Enumerable.Empty()) + && section.ScheduledTasks == Mock.Of(tasksSection => tasksSection.BaseUrl == "mycoolhost.com/hello/world"))); + + + Assert.AreEqual("http://mycoolhost.com/hello/world/", result); + } + + [Test] + public void Get_Base_Url_Single_Server_Via_Config_Url_With_SSL() + { + var appContext = new ApplicationContext(null); + + ConfigurationManager.AppSettings.Set("umbracoUseSSL", "true"); + + var result = ServerEnvironmentHelper.GetCurrentServerUmbracoBaseUrl( + appContext, + Mock.Of( + section => + section.DistributedCall == Mock.Of(callSection => callSection.Servers == Enumerable.Empty()) + && section.ScheduledTasks == Mock.Of(tasksSection => tasksSection.BaseUrl == "mycoolhost.com/hello/world"))); + + + Assert.AreEqual("https://mycoolhost.com/hello/world/", result); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Tests/Trees/BaseContentTreeTests.cs b/src/Umbraco.Tests/TreesAndSections/BaseContentTreeTests.cs similarity index 92% rename from src/Umbraco.Tests/Trees/BaseContentTreeTests.cs rename to src/Umbraco.Tests/TreesAndSections/BaseContentTreeTests.cs index 63a9f9f14d..57a974fc95 100644 --- a/src/Umbraco.Tests/Trees/BaseContentTreeTests.cs +++ b/src/Umbraco.Tests/TreesAndSections/BaseContentTreeTests.cs @@ -1,127 +1,123 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using NUnit.Framework; -using umbraco.cms.presentation.Trees; - -namespace Umbraco.Tests.Trees -{ - [TestFixture] - public class BaseContentTreeTests - { - - [TearDown] - public void TestTearDown() - { - BaseTree.AfterTreeRender -= EventHandler; - BaseTree.BeforeTreeRender -= EventHandler; - } - - [Test] - public void Run_Optimized() - { - var tree1 = new MyOptimizedContentTree1("content"); - var tree2 = new MyOptimizedContentTree2("content"); - - Assert.IsTrue(tree1.UseOptimizedRendering); - Assert.IsTrue(tree2.UseOptimizedRendering); - } - - [Test] - public void Not_Optimized_Events_AfterRender() - { - var tree = new MyOptimizedContentTree1("content"); - - BaseTree.AfterTreeRender += EventHandler; - - Assert.IsFalse(tree.UseOptimizedRendering); - } - - [Test] - public void Not_Optimized_Events_BeforeRender() - { - var tree = new MyOptimizedContentTree1("content"); - - BaseTree.BeforeTreeRender += EventHandler; - - Assert.IsFalse(tree.UseOptimizedRendering); - } - - [Test] - public void Not_Optimized_Overriden_Method() - { - var tree = new MyNotOptimizedContentTree("content"); - - Assert.IsFalse(tree.UseOptimizedRendering); - } - - private void EventHandler(object sender, TreeEventArgs treeEventArgs) - { - - } - - //optimized because we are not overriding OnRenderNode - public class MyOptimizedContentTree1 : BaseContentTree - { - public MyOptimizedContentTree1(string application) - : base(application) - { - } - - protected override void CreateRootNode(ref XmlTreeNode rootNode) - { - - } - } - - public class MyOptimizedContentTree2 : BaseContentTree - { - public MyOptimizedContentTree2(string application) - : base(application) - { - } - - protected override bool LoadMinimalDocument - { - get { return true; } - } - - protected override void CreateRootNode(ref XmlTreeNode rootNode) - { - - } - - //even if we override it will still be optimized because of the LoadMinimalDocument flag - protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc) - { - base.OnRenderNode(ref xNode, doc); - } - } - - public class MyNotOptimizedContentTree : BaseContentTree - { - public MyNotOptimizedContentTree(string application) - : base(application) - { - } - - protected override void CreateRootNode(ref XmlTreeNode rootNode) - { - - } - - protected override bool LoadMinimalDocument - { - get { return false; } - } - - protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc) - { - base.OnRenderNode(ref xNode, doc); - } - } - - - } -} +using NUnit.Framework; +using umbraco.cms.presentation.Trees; + +namespace Umbraco.Tests.TreesAndSections +{ + [TestFixture] + public class BaseContentTreeTests + { + + [TearDown] + public void TestTearDown() + { + BaseTree.AfterTreeRender -= EventHandler; + BaseTree.BeforeTreeRender -= EventHandler; + } + + [Test] + public void Run_Optimized() + { + var tree1 = new MyOptimizedContentTree1("content"); + var tree2 = new MyOptimizedContentTree2("content"); + + Assert.IsTrue(tree1.UseOptimizedRendering); + Assert.IsTrue(tree2.UseOptimizedRendering); + } + + [Test] + public void Not_Optimized_Events_AfterRender() + { + var tree = new MyOptimizedContentTree1("content"); + + BaseTree.AfterTreeRender += EventHandler; + + Assert.IsFalse(tree.UseOptimizedRendering); + } + + [Test] + public void Not_Optimized_Events_BeforeRender() + { + var tree = new MyOptimizedContentTree1("content"); + + BaseTree.BeforeTreeRender += EventHandler; + + Assert.IsFalse(tree.UseOptimizedRendering); + } + + [Test] + public void Not_Optimized_Overriden_Method() + { + var tree = new MyNotOptimizedContentTree("content"); + + Assert.IsFalse(tree.UseOptimizedRendering); + } + + private void EventHandler(object sender, TreeEventArgs treeEventArgs) + { + + } + + //optimized because we are not overriding OnRenderNode + public class MyOptimizedContentTree1 : BaseContentTree + { + public MyOptimizedContentTree1(string application) + : base(application) + { + } + + protected override void CreateRootNode(ref XmlTreeNode rootNode) + { + + } + } + + public class MyOptimizedContentTree2 : BaseContentTree + { + public MyOptimizedContentTree2(string application) + : base(application) + { + } + + protected override bool LoadMinimalDocument + { + get { return true; } + } + + protected override void CreateRootNode(ref XmlTreeNode rootNode) + { + + } + + //even if we override it will still be optimized because of the LoadMinimalDocument flag + protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc) + { + base.OnRenderNode(ref xNode, doc); + } + } + + public class MyNotOptimizedContentTree : BaseContentTree + { + public MyNotOptimizedContentTree(string application) + : base(application) + { + } + + protected override void CreateRootNode(ref XmlTreeNode rootNode) + { + + } + + protected override bool LoadMinimalDocument + { + get { return false; } + } + + protected override void OnRenderNode(ref XmlTreeNode xNode, umbraco.cms.businesslogic.web.Document doc) + { + base.OnRenderNode(ref xNode, doc); + } + } + + + } +} diff --git a/src/Umbraco.Tests/Trees/BaseMediaTreeTests.cs b/src/Umbraco.Tests/TreesAndSections/BaseMediaTreeTests.cs similarity index 93% rename from src/Umbraco.Tests/Trees/BaseMediaTreeTests.cs rename to src/Umbraco.Tests/TreesAndSections/BaseMediaTreeTests.cs index 5aa0840edf..49049d10ec 100644 --- a/src/Umbraco.Tests/Trees/BaseMediaTreeTests.cs +++ b/src/Umbraco.Tests/TreesAndSections/BaseMediaTreeTests.cs @@ -1,65 +1,65 @@ -using NUnit.Framework; -using umbraco.cms.presentation.Trees; - -namespace Umbraco.Tests.Trees -{ - [TestFixture] - public class BaseMediaTreeTests - { - - [TearDown] - public void TestTearDown() - { - BaseTree.AfterTreeRender -= EventHandler; - BaseTree.BeforeTreeRender -= EventHandler; - } - - [Test] - public void Run_Optimized() - { - var tree = new MyOptimizedMediaTree("media"); - - Assert.IsTrue(tree.UseOptimizedRendering); - } - - [Test] - public void Not_Optimized_Events_AfterRender() - { - var tree = new MyOptimizedMediaTree("media"); - - BaseTree.AfterTreeRender += EventHandler; - - Assert.IsFalse(tree.UseOptimizedRendering); - } - - [Test] - public void Not_Optimized_Events_BeforeRender() - { - var tree = new MyOptimizedMediaTree("media"); - - BaseTree.BeforeTreeRender += EventHandler; - - Assert.IsFalse(tree.UseOptimizedRendering); - } - - private void EventHandler(object sender, TreeEventArgs treeEventArgs) - { - - } - - public class MyOptimizedMediaTree : BaseMediaTree - { - public MyOptimizedMediaTree(string application) - : base(application) - { - } - - protected override void CreateRootNode(ref XmlTreeNode rootNode) - { - - } - } - - - } +using NUnit.Framework; +using umbraco.cms.presentation.Trees; + +namespace Umbraco.Tests.TreesAndSections +{ + [TestFixture] + public class BaseMediaTreeTests + { + + [TearDown] + public void TestTearDown() + { + BaseTree.AfterTreeRender -= EventHandler; + BaseTree.BeforeTreeRender -= EventHandler; + } + + [Test] + public void Run_Optimized() + { + var tree = new MyOptimizedMediaTree("media"); + + Assert.IsTrue(tree.UseOptimizedRendering); + } + + [Test] + public void Not_Optimized_Events_AfterRender() + { + var tree = new MyOptimizedMediaTree("media"); + + BaseTree.AfterTreeRender += EventHandler; + + Assert.IsFalse(tree.UseOptimizedRendering); + } + + [Test] + public void Not_Optimized_Events_BeforeRender() + { + var tree = new MyOptimizedMediaTree("media"); + + BaseTree.BeforeTreeRender += EventHandler; + + Assert.IsFalse(tree.UseOptimizedRendering); + } + + private void EventHandler(object sender, TreeEventArgs treeEventArgs) + { + + } + + public class MyOptimizedMediaTree : BaseMediaTree + { + public MyOptimizedMediaTree(string application) + : base(application) + { + } + + protected override void CreateRootNode(ref XmlTreeNode rootNode) + { + + } + } + + + } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 92b02b1b3e..11c2021210 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -276,7 +276,7 @@ - + @@ -312,6 +312,7 @@ + @@ -376,7 +377,7 @@ - + @@ -463,15 +464,15 @@ ImportResources.resx - - + + - + @@ -489,11 +490,11 @@ - - + + - + @@ -513,11 +514,11 @@ - + - - + + @@ -527,7 +528,7 @@ - + @@ -697,9 +698,7 @@ - - - + diff --git a/src/Umbraco.Web/Scheduling/KeepAlive.cs b/src/Umbraco.Web/Scheduling/KeepAlive.cs index 40e6ae0ecb..67a2f4a448 100644 --- a/src/Umbraco.Web/Scheduling/KeepAlive.cs +++ b/src/Umbraco.Web/Scheduling/KeepAlive.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Scheduling } else { - var url = string.Format("{0}/ping.aspx", umbracoBaseUrl); + var url = string.Format("{0}ping.aspx", umbracoBaseUrl.EnsureEndsWith('/')); try { diff --git a/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs b/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs index bc303851f7..48cf69b39d 100644 --- a/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs +++ b/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs @@ -52,7 +52,7 @@ namespace Umbraco.Web.Scheduling } else { - var url = string.Format("{0}/RestServices/ScheduledPublish/Index", umbracoBaseUrl); + var url = string.Format("{0}RestServices/ScheduledPublish/Index", umbracoBaseUrl.EnsureEndsWith('/')); using (var wc = new WebClient()) { //pass custom the authorization header