From a33d1b4fef4fc30144b2b29a0fd1d273a19ca9dd Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 9 Jan 2020 13:04:27 +0100 Subject: [PATCH 01/28] Added UnitTest project --- .../Builders/DictionaryItemBuilder.cs | 10 ++++++ .../Umbraco.Tests.Shared.csproj | 23 +++++++++++++ .../Models/DictionaryItemTests.cs | 18 ++++++++++ .../Umbraco.Tests.UnitTests.csproj | 34 +++++++++++++++++++ src/umbraco.sln | 14 ++++++++ 5 files changed, 99 insertions(+) create mode 100644 src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj create mode 100644 src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs create mode 100644 src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs new file mode 100644 index 0000000000..0bb16826e8 --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs @@ -0,0 +1,10 @@ +namespace Umbraco.Tests.Shared.Builders +{ + public class DictionaryItemBuilder + { + public object Build() + { + throw new System.NotImplementedException(); + } + } +} diff --git a/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj b/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj new file mode 100644 index 0000000000..65d17b16df --- /dev/null +++ b/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj @@ -0,0 +1,23 @@ + + + + netstandard2.0 + + + + + + + + + + + + + + + + + + + diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs new file mode 100644 index 0000000000..ac3283df5d --- /dev/null +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs @@ -0,0 +1,18 @@ +using NUnit.Framework; +using Umbraco.Tests.Shared.Builders; + +namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models +{ + [TestFixture] + public class DictionaryItemTests + { + [Test] + public void Can_Deep_Clone() + { + var builder = new DictionaryItemBuilder(); + + var item = builder + .Build(); + } + } +} diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj new file mode 100644 index 0000000000..8dad14e747 --- /dev/null +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj @@ -0,0 +1,34 @@ + + + + netcoreapp2.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/umbraco.sln b/src/umbraco.sln index c70f10bdb3..e0f20287bd 100644 --- a/src/umbraco.sln +++ b/src/umbraco.sln @@ -110,6 +110,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Infrastructure", "U EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Configuration", "Umbraco.Configuration\Umbraco.Configuration.csproj", "{FBE7C065-DAC0-4025-A78B-63B24D3AB00B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Tests.UnitTests", "Umbraco.Tests.UnitTests\Umbraco.Tests.UnitTests.csproj", "{9102ABDF-E537-4E46-B525-C9ED4833EED0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Tests.Shared", "Umbraco.Tests.Shared\Umbraco.Tests.Shared.csproj", "{58F1DFC6-5096-4B99-B57B-984F2EEDFADE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -158,6 +162,14 @@ Global {FBE7C065-DAC0-4025-A78B-63B24D3AB00B}.Debug|Any CPU.Build.0 = Debug|Any CPU {FBE7C065-DAC0-4025-A78B-63B24D3AB00B}.Release|Any CPU.ActiveCfg = Release|Any CPU {FBE7C065-DAC0-4025-A78B-63B24D3AB00B}.Release|Any CPU.Build.0 = Release|Any CPU + {9102ABDF-E537-4E46-B525-C9ED4833EED0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9102ABDF-E537-4E46-B525-C9ED4833EED0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9102ABDF-E537-4E46-B525-C9ED4833EED0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9102ABDF-E537-4E46-B525-C9ED4833EED0}.Release|Any CPU.Build.0 = Release|Any CPU + {58F1DFC6-5096-4B99-B57B-984F2EEDFADE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58F1DFC6-5096-4B99-B57B-984F2EEDFADE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58F1DFC6-5096-4B99-B57B-984F2EEDFADE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {58F1DFC6-5096-4B99-B57B-984F2EEDFADE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -170,6 +182,8 @@ Global {53594E5B-64A2-4545-8367-E3627D266AE8} = {FD962632-184C-4005-A5F3-E705D92FC645} {3A33ADC9-C6C0-4DB1-A613-A9AF0210DF3D} = {B5BD12C1-A454-435E-8A46-FF4A364C0382} {C7311C00-2184-409B-B506-52A5FAEA8736} = {FD962632-184C-4005-A5F3-E705D92FC645} + {9102ABDF-E537-4E46-B525-C9ED4833EED0} = {B5BD12C1-A454-435E-8A46-FF4A364C0382} + {58F1DFC6-5096-4B99-B57B-984F2EEDFADE} = {B5BD12C1-A454-435E-8A46-FF4A364C0382} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7A0F2E34-D2AF-4DAB-86A0-7D7764B3D0EC} From 997796758e55a736f533c8ed7b72604cb27a7f58 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 9 Jan 2020 14:24:20 +0100 Subject: [PATCH 02/28] Added Builders --- .../Builders/BuilderBase.cs | 7 ++ .../Builders/ChildBuilderBase.cs | 19 +++++ .../Builders/DictionaryItemBuilder.cs | 53 +++++++++++++- .../Builders/DictionaryTranslationBuilder.cs | 71 +++++++++++++++++++ .../Builders/LanguageBuilder.cs | 35 +++++++++ .../Umbraco.Tests.Shared.csproj | 10 +++ .../Models/DictionaryItemTests.cs | 55 +++++++++++++- 7 files changed, 245 insertions(+), 5 deletions(-) create mode 100644 src/Umbraco.Tests.Shared/Builders/BuilderBase.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/ChildBuilderBase.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs diff --git a/src/Umbraco.Tests.Shared/Builders/BuilderBase.cs b/src/Umbraco.Tests.Shared/Builders/BuilderBase.cs new file mode 100644 index 0000000000..d026999351 --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/BuilderBase.cs @@ -0,0 +1,7 @@ +namespace Umbraco.Tests.Shared.Builders +{ + public abstract class BuilderBase + { + public abstract T Build(); + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/ChildBuilderBase.cs b/src/Umbraco.Tests.Shared/Builders/ChildBuilderBase.cs new file mode 100644 index 0000000000..742b86d16e --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/ChildBuilderBase.cs @@ -0,0 +1,19 @@ +namespace Umbraco.Tests.Shared.Builders +{ + public abstract class ChildBuilderBase : BuilderBase + { + private readonly TParent _parentBuilder; + + protected ChildBuilderBase(TParent parentBuilder) + { + _parentBuilder = parentBuilder; + } + + + public TParent Done() + { + return _parentBuilder; + } + + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs index 0bb16826e8..64f74417a4 100644 --- a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs @@ -1,10 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Umbraco.Core.Models; + namespace Umbraco.Tests.Shared.Builders { public class DictionaryItemBuilder { - public object Build() + private string _itemkey = null; + private readonly List _translationBuilders = new List(); + private DateTime? _createDate; + private DateTime? _updateDate; + private int? _id = null; + + + public DictionaryItem Build() { - throw new System.NotImplementedException(); + var createDate = _createDate ?? DateTime.Now; + var updateDate = _updateDate ?? DateTime.Now; + var id = _id ?? 1; + + var result = new DictionaryItem(_itemkey ?? Guid.NewGuid().ToString()); + result.Translations = _translationBuilders.Select(x => x.Build()); + result.CreateDate = createDate; + result.UpdateDate = updateDate; + result.Id = id; + return result; + } + + public DictionaryTranslationBuilder AddTranslation() + { + var builder = new DictionaryTranslationBuilder(this); + + _translationBuilders.Add(builder); + + return builder; + } + + public DictionaryItemBuilder WithCreateData(DateTime createDate) + { + _createDate = createDate; + return this; + } + + public DictionaryItemBuilder WithUpdateData(DateTime updateDate) + { + _updateDate = updateDate; + return this; + } + + public DictionaryItemBuilder WithId(int id) + { + _id = id; + return this; } } } diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs new file mode 100644 index 0000000000..fb82133030 --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs @@ -0,0 +1,71 @@ +using System; +using System.Globalization; +using Umbraco.Core.Models; + +namespace Umbraco.Tests.Shared.Builders +{ + public class DictionaryTranslationBuilder : ChildBuilderBase + { + private string _value = null; + private Guid? _uniqueId = null; + private DateTime? _createDate; + private DateTime? _updateDate; + + + private LanguageBuilder _languageBuilder; + private int? _id = null; + + public DictionaryTranslationBuilder(DictionaryItemBuilder parentBuilder) : base(parentBuilder) + { + _languageBuilder = new LanguageBuilder(this); + + } + + public override IDictionaryTranslation Build() + { + var createDate = _createDate ?? DateTime.Now; + var updateDate = _updateDate ?? DateTime.Now; + var id = _id ?? 1; + + var result = new DictionaryTranslation( + _languageBuilder.Build(), + _value ?? Guid.NewGuid().ToString(), + _uniqueId ?? Guid.NewGuid()); + + result.CreateDate = createDate; + result.UpdateDate = updateDate; + result.Id = id; + + return result; + } + + public LanguageBuilder WithLanguage() + { + return _languageBuilder; + } + + public DictionaryTranslationBuilder WithValue(string value) + { + _value = value; + return this; + } + + public DictionaryTranslationBuilder WithCreateData(DateTime createDate) + { + _createDate = createDate; + return this; + } + + public DictionaryTranslationBuilder WithUpdateData(DateTime updateDate) + { + _updateDate = updateDate; + return this; + } + + public DictionaryTranslationBuilder WithId(int id) + { + _id = id; + return this; + } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs b/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs new file mode 100644 index 0000000000..3adc6262a2 --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs @@ -0,0 +1,35 @@ +using System.Globalization; +using Moq; +using Umbraco.Core.Configuration; +using Umbraco.Core.Models; + +namespace Umbraco.Tests.Shared.Builders +{ + public class LanguageBuilder : ChildBuilderBase + { + private int? _id = null; + private string _isoCode = null; + + public LanguageBuilder(TParent parentBuilder) : base(parentBuilder) + { + } + + public override ILanguage Build() + { + var culture = CultureInfo.GetCultureInfo("en-US"); + var isoCode = _isoCode ?? culture.Name; + return new Language(Mock.Of(), isoCode) + { + Id = _id ?? 1, + CultureName = culture.TwoLetterISOLanguageName, + IsoCode = new RegionInfo(culture.LCID).Name, + }; + } + + public LanguageBuilder WithId(int id) + { + _id = id; + return this; + } + } +} diff --git a/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj b/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj index 65d17b16df..93afb6f531 100644 --- a/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj +++ b/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj @@ -18,6 +18,16 @@ + + + + + + + + + + diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs index ac3283df5d..57ac00c026 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs @@ -1,4 +1,7 @@ +using System.Linq; +using Newtonsoft.Json; using NUnit.Framework; +using Umbraco.Core.Models; using Umbraco.Tests.Shared.Builders; namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models @@ -6,13 +9,59 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models [TestFixture] public class DictionaryItemTests { + private readonly DictionaryItemBuilder _builder = new DictionaryItemBuilder(); + [Test] public void Can_Deep_Clone() { - var builder = new DictionaryItemBuilder(); - - var item = builder + var item = _builder + .AddTranslation() + .WithValue("Colour") + .Done() + .AddTranslation() + .WithValue("Color") + .Done() .Build(); + + var clone = (DictionaryItem)item.DeepClone(); + + Assert.AreNotSame(clone, item); + Assert.AreEqual(clone, item); + Assert.AreEqual(clone.CreateDate, item.CreateDate); + Assert.AreEqual(clone.Id, item.Id); + Assert.AreEqual(clone.ItemKey, item.ItemKey); + Assert.AreEqual(clone.Key, item.Key); + Assert.AreEqual(clone.ParentId, item.ParentId); + Assert.AreEqual(clone.UpdateDate, item.UpdateDate); + Assert.AreEqual(clone.Translations.Count(), item.Translations.Count()); + for (var i = 0; i < item.Translations.Count(); i++) + { + Assert.AreNotSame(clone.Translations.ElementAt(i), item.Translations.ElementAt(i)); + Assert.AreEqual(clone.Translations.ElementAt(i), item.Translations.ElementAt(i)); + } + + //This double verifies by reflection + var allProps = clone.GetType().GetProperties(); + foreach (var propertyInfo in allProps) + { + Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null)); + } + + } + + [Test] + public void Can_Serialize_Without_Error() + { + var item = _builder + .AddTranslation() + .WithValue("Colour") + .Done() + .AddTranslation() + .WithValue("Color") + .Done() + .Build(); + + Assert.DoesNotThrow(() => JsonConvert.SerializeObject(item)); } } } From 9d6d43c2d0e66a1ca5b9a31947ed8d76d99c4f7e Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 9 Jan 2020 14:49:11 +0100 Subject: [PATCH 03/28] Added language tests --- .../Builders/DictionaryItemBuilder.cs | 9 ++++ .../Builders/LanguageBuilder.cs | 8 ++++ .../Models/DictionaryItemTests.cs | 14 +----- .../Models/LanguageTests.cs | 44 +++++++++++++++++++ 4 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/LanguageTests.cs diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs index 64f74417a4..992c197854 100644 --- a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs @@ -55,5 +55,14 @@ namespace Umbraco.Tests.Shared.Builders _id = id; return this; } + + public DictionaryItemBuilder WithRandomTranslations(int count) + { + for (var i = 0; i < count; i++) + { + AddTranslation().Done(); + } + return this; + } } } diff --git a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs b/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs index 3adc6262a2..82375434a6 100644 --- a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs @@ -5,6 +5,14 @@ using Umbraco.Core.Models; namespace Umbraco.Tests.Shared.Builders { + public class LanguageBuilder : LanguageBuilder + { + public LanguageBuilder() : base(null) + { + } + } + + public class LanguageBuilder : ChildBuilderBase { private int? _id = null; diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs index 57ac00c026..85c0e56089 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs @@ -15,12 +15,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models public void Can_Deep_Clone() { var item = _builder - .AddTranslation() - .WithValue("Colour") - .Done() - .AddTranslation() - .WithValue("Color") - .Done() + .WithRandomTranslations(2) .Build(); var clone = (DictionaryItem)item.DeepClone(); @@ -53,12 +48,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models public void Can_Serialize_Without_Error() { var item = _builder - .AddTranslation() - .WithValue("Colour") - .Done() - .AddTranslation() - .WithValue("Color") - .Done() + .WithRandomTranslations(2) .Build(); Assert.DoesNotThrow(() => JsonConvert.SerializeObject(item)); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/LanguageTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/LanguageTests.cs new file mode 100644 index 0000000000..57ed20310a --- /dev/null +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/LanguageTests.cs @@ -0,0 +1,44 @@ +using Newtonsoft.Json; +using NUnit.Framework; +using Umbraco.Core.Models; +using Umbraco.Tests.Shared.Builders; + +namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models +{ + [TestFixture] + public class LanguageTests + { + private readonly LanguageBuilder _builder = new LanguageBuilder(); + + [Test] + public void Can_Deep_Clone() + { + var item = _builder.Build(); + + var clone = (Language) item.DeepClone(); + Assert.AreNotSame(clone, item); + Assert.AreEqual(clone, item); + Assert.AreEqual(clone.CreateDate, item.CreateDate); + Assert.AreEqual(clone.CultureName, item.CultureName); + Assert.AreEqual(clone.Id, item.Id); + Assert.AreEqual(clone.IsoCode, item.IsoCode); + Assert.AreEqual(clone.Key, item.Key); + Assert.AreEqual(clone.UpdateDate, item.UpdateDate); + + //This double verifies by reflection + var allProps = clone.GetType().GetProperties(); + foreach (var propertyInfo in allProps) + { + Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null)); + } + } + + [Test] + public void Can_Serialize_Without_Error() + { + var item = _builder.Build(); + + Assert.DoesNotThrow(() => JsonConvert.SerializeObject(item)); + } + } +} From 728799b036d751d12f0d5828a11d5ec360da8a1d Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 9 Jan 2020 15:32:19 +0100 Subject: [PATCH 04/28] using extension methods to enforce consistency --- .../Builders/DataEditorBuilder.cs | 28 ++++++++++ .../Builders/DataTypeBuilder.cs | 33 +++++++++++ .../Builders/DictionaryItemBuilder.cs | 40 +++++++------ .../Builders/DictionaryTranslationBuilder.cs | 21 ++++--- .../Builders/Extensions/BuilderExtensions.cs | 28 ++++++++++ .../Builders/LanguageBuilder.cs | 11 ++-- .../Markers/IWithCreateDateBuilder.cs | 9 +++ .../Builders/Markers/IWithIdBuilder.cs | 7 +++ .../Markers/IWithUpdateDateBuilder.cs | 9 +++ .../Models/DataTypeTests.cs | 56 +++++++++++++++++++ 10 files changed, 205 insertions(+), 37 deletions(-) create mode 100644 src/Umbraco.Tests.Shared/Builders/DataEditorBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/Markers/IWithCreateDateBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/Markers/IWithIdBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/Markers/IWithUpdateDateBuilder.cs create mode 100644 src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs diff --git a/src/Umbraco.Tests.Shared/Builders/DataEditorBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DataEditorBuilder.cs new file mode 100644 index 0000000000..5a0b18cf9e --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/DataEditorBuilder.cs @@ -0,0 +1,28 @@ +using Moq; +using Umbraco.Core.Logging; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; +using Umbraco.Core.Strings; + +namespace Umbraco.Tests.Shared.Builders +{ + public class DataEditorBuilder : ChildBuilderBase + { + public DataEditorBuilder(TParent parentBuilder) : base(parentBuilder) + { + } + + public override IDataEditor Build() + { + var result = new DataEditor( + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of() + ); + + return result; + } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs new file mode 100644 index 0000000000..128990ab4e --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs @@ -0,0 +1,33 @@ +using Umbraco.Core.Models; + +namespace Umbraco.Tests.Shared.Builders +{ + public class DataTypeBuilder : BuilderBase, IWithIdBuilder + { + private readonly DataEditorBuilder _dataEditorBuilder; + private int? _id; + + public DataTypeBuilder() + { + _dataEditorBuilder = new DataEditorBuilder(this); + } + + public override DataType Build() + { + var editor = _dataEditorBuilder.Build(); + var id = _id ?? 1; + var result = new DataType(editor) + { + Id = id + }; + + return result; + } + + int? IWithIdBuilder.Id + { + get => _id; + set => _id = value; + } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs index 992c197854..5f88a636f7 100644 --- a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs @@ -1,12 +1,11 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using Umbraco.Core.Models; namespace Umbraco.Tests.Shared.Builders { - public class DictionaryItemBuilder + public class DictionaryItemBuilder : IWithIdBuilder, IWithCreateDateBuilder, IWithUpdateDateBuilder { private string _itemkey = null; private readonly List _translationBuilders = new List(); @@ -14,7 +13,6 @@ namespace Umbraco.Tests.Shared.Builders private DateTime? _updateDate; private int? _id = null; - public DictionaryItem Build() { var createDate = _createDate ?? DateTime.Now; @@ -38,24 +36,6 @@ namespace Umbraco.Tests.Shared.Builders return builder; } - public DictionaryItemBuilder WithCreateData(DateTime createDate) - { - _createDate = createDate; - return this; - } - - public DictionaryItemBuilder WithUpdateData(DateTime updateDate) - { - _updateDate = updateDate; - return this; - } - - public DictionaryItemBuilder WithId(int id) - { - _id = id; - return this; - } - public DictionaryItemBuilder WithRandomTranslations(int count) { for (var i = 0; i < count; i++) @@ -64,5 +44,23 @@ namespace Umbraco.Tests.Shared.Builders } return this; } + + int? IWithIdBuilder.Id + { + get => _id; + set => _id = value; + } + + DateTime? IWithCreateDateBuilder.CreateDate + { + get => _createDate; + set => _createDate = value; + } + + DateTime? IWithUpdateDateBuilder.UpdateDate + { + get => _updateDate; + set => _updateDate = value; + } } } diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs index fb82133030..3f471777c4 100644 --- a/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs @@ -1,10 +1,9 @@ using System; -using System.Globalization; using Umbraco.Core.Models; namespace Umbraco.Tests.Shared.Builders { - public class DictionaryTranslationBuilder : ChildBuilderBase + public class DictionaryTranslationBuilder : ChildBuilderBase, IWithIdBuilder, IWithCreateDateBuilder, IWithUpdateDateBuilder { private string _value = null; private Guid? _uniqueId = null; @@ -50,22 +49,22 @@ namespace Umbraco.Tests.Shared.Builders return this; } - public DictionaryTranslationBuilder WithCreateData(DateTime createDate) + int? IWithIdBuilder.Id { - _createDate = createDate; - return this; + get => _id; + set => _id = value; } - public DictionaryTranslationBuilder WithUpdateData(DateTime updateDate) + DateTime? IWithCreateDateBuilder.CreateDate { - _updateDate = updateDate; - return this; + get => _createDate; + set => _createDate = value; } - public DictionaryTranslationBuilder WithId(int id) + DateTime? IWithUpdateDateBuilder.UpdateDate { - _id = id; - return this; + get => _updateDate; + set => _updateDate = value; } } } diff --git a/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs b/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs new file mode 100644 index 0000000000..9b6a961c4f --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs @@ -0,0 +1,28 @@ +using System; + +namespace Umbraco.Tests.Shared.Builders.Extensions +{ + public static class BuilderExtensions + { + public static T WithId(this T builder, int id) + where T : IWithIdBuilder + { + builder.Id = id; + return builder; + } + + public static T WithCreateDate(this T builder, DateTime createDate) + where T : IWithCreateDateBuilder + { + builder.CreateDate = createDate; + return builder; + } + + public static T WithUpdateDate(this T builder, DateTime updateDate) + where T : IWithUpdateDateBuilder + { + builder.UpdateDate = updateDate; + return builder; + } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs b/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs index 82375434a6..d3855145f3 100644 --- a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs @@ -13,10 +13,11 @@ namespace Umbraco.Tests.Shared.Builders } - public class LanguageBuilder : ChildBuilderBase + public class LanguageBuilder : ChildBuilderBase, IWithIdBuilder { - private int? _id = null; + private string _isoCode = null; + private int? _id; public LanguageBuilder(TParent parentBuilder) : base(parentBuilder) { @@ -34,10 +35,10 @@ namespace Umbraco.Tests.Shared.Builders }; } - public LanguageBuilder WithId(int id) + int? IWithIdBuilder.Id { - _id = id; - return this; + get => _id; + set => _id = value; } } } diff --git a/src/Umbraco.Tests.Shared/Builders/Markers/IWithCreateDateBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Markers/IWithCreateDateBuilder.cs new file mode 100644 index 0000000000..3ea3b9e7cc --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/Markers/IWithCreateDateBuilder.cs @@ -0,0 +1,9 @@ +using System; + +namespace Umbraco.Tests.Shared.Builders +{ + public interface IWithCreateDateBuilder + { + DateTime? CreateDate { get; set; } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/Markers/IWithIdBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Markers/IWithIdBuilder.cs new file mode 100644 index 0000000000..7575d2429d --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/Markers/IWithIdBuilder.cs @@ -0,0 +1,7 @@ +namespace Umbraco.Tests.Shared.Builders +{ + public interface IWithIdBuilder + { + int? Id { get; set; } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/Markers/IWithUpdateDateBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Markers/IWithUpdateDateBuilder.cs new file mode 100644 index 0000000000..a0d4fe6258 --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/Markers/IWithUpdateDateBuilder.cs @@ -0,0 +1,9 @@ +using System; + +namespace Umbraco.Tests.Shared.Builders +{ + public interface IWithUpdateDateBuilder + { + DateTime? UpdateDate { get; set; } + } +} diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs new file mode 100644 index 0000000000..ecd4249bc6 --- /dev/null +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs @@ -0,0 +1,56 @@ +using Newtonsoft.Json; +using NUnit.Framework; +using Umbraco.Core.Models; +using Umbraco.Tests.Shared.Builders; +using Umbraco.Tests.Shared.Builders.Extensions; + +namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models +{ + [TestFixture] + public class DataTypeTests + { + + private readonly DataTypeBuilder _builder = new DataTypeBuilder(); + [Test] + public void Can_Deep_Clone() + { + var dtd = _builder + .WithId(3123) + .Build(); + + var clone = (DataType) dtd.DeepClone(); + + Assert.AreNotSame(clone, dtd); + Assert.AreEqual(clone, dtd); + Assert.AreEqual(clone.CreateDate, dtd.CreateDate); + Assert.AreEqual(clone.CreatorId, dtd.CreatorId); + Assert.AreEqual(clone.DatabaseType, dtd.DatabaseType); + Assert.AreEqual(clone.Id, dtd.Id); + Assert.AreEqual(clone.Key, dtd.Key); + Assert.AreEqual(clone.Level, dtd.Level); + Assert.AreEqual(clone.Name, dtd.Name); + Assert.AreEqual(clone.ParentId, dtd.ParentId); + Assert.AreEqual(clone.Path, dtd.Path); + Assert.AreEqual(clone.SortOrder, dtd.SortOrder); + Assert.AreEqual(clone.Trashed, dtd.Trashed); + Assert.AreEqual(clone.UpdateDate, dtd.UpdateDate); + + //This double verifies by reflection + var allProps = clone.GetType().GetProperties(); + foreach (var propertyInfo in allProps) + { + Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(dtd, null)); + } + } + + [Test] + public void Can_Serialize_Without_Error() + { + var item = _builder + .Build(); + + Assert.DoesNotThrow(() => JsonConvert.SerializeObject(item)); + } + + } +} From b786dd185b63c24ed63ee7ee6173922ad2b1d6bf Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 9 Jan 2020 15:48:28 +0100 Subject: [PATCH 05/28] Clean up --- .../Builders/Extensions/BuilderExtensions.cs | 2 +- .../Builders/{Markers => Interfaces}/IWithCreateDateBuilder.cs | 0 .../Builders/{Markers => Interfaces}/IWithIdBuilder.cs | 0 .../Builders/{Markers => Interfaces}/IWithUpdateDateBuilder.cs | 0 .../Umbraco.Infrastructure/Models/DataTypeTests.cs | 1 - 5 files changed, 1 insertion(+), 2 deletions(-) rename src/Umbraco.Tests.Shared/Builders/{Markers => Interfaces}/IWithCreateDateBuilder.cs (100%) rename src/Umbraco.Tests.Shared/Builders/{Markers => Interfaces}/IWithIdBuilder.cs (100%) rename src/Umbraco.Tests.Shared/Builders/{Markers => Interfaces}/IWithUpdateDateBuilder.cs (100%) diff --git a/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs b/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs index 9b6a961c4f..bab15761c1 100644 --- a/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs +++ b/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs @@ -1,6 +1,6 @@ using System; -namespace Umbraco.Tests.Shared.Builders.Extensions +namespace Umbraco.Tests.Shared.Builders { public static class BuilderExtensions { diff --git a/src/Umbraco.Tests.Shared/Builders/Markers/IWithCreateDateBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCreateDateBuilder.cs similarity index 100% rename from src/Umbraco.Tests.Shared/Builders/Markers/IWithCreateDateBuilder.cs rename to src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCreateDateBuilder.cs diff --git a/src/Umbraco.Tests.Shared/Builders/Markers/IWithIdBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithIdBuilder.cs similarity index 100% rename from src/Umbraco.Tests.Shared/Builders/Markers/IWithIdBuilder.cs rename to src/Umbraco.Tests.Shared/Builders/Interfaces/IWithIdBuilder.cs diff --git a/src/Umbraco.Tests.Shared/Builders/Markers/IWithUpdateDateBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithUpdateDateBuilder.cs similarity index 100% rename from src/Umbraco.Tests.Shared/Builders/Markers/IWithUpdateDateBuilder.cs rename to src/Umbraco.Tests.Shared/Builders/Interfaces/IWithUpdateDateBuilder.cs diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs index ecd4249bc6..d845e1b4a0 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs @@ -2,7 +2,6 @@ using NUnit.Framework; using Umbraco.Core.Models; using Umbraco.Tests.Shared.Builders; -using Umbraco.Tests.Shared.Builders.Extensions; namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models { From 76ed4ccc6c9838de3fea106cb6c5ec2c05bfde83 Mon Sep 17 00:00:00 2001 From: elitsa Date: Thu, 9 Jan 2020 16:37:24 +0100 Subject: [PATCH 06/28] Updating namespaces --- .../Builders/DataTypeBuilder.cs | 1 + .../Builders/DictionaryItemBuilder.cs | 1 + .../Builders/DictionaryTranslationBuilder.cs | 1 + .../Builders/Extensions/BuilderExtensions.cs | 15 +++++++++++++++ .../Builders/LanguageBuilder.cs | 1 + .../Builders/Markers/IWithCreateDateBuilder.cs | 2 +- .../Builders/Markers/IWithIdBuilder.cs | 2 +- .../Builders/Markers/IWithUpdateDateBuilder.cs | 2 +- 8 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs index 128990ab4e..b22b313a75 100644 --- a/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs @@ -1,4 +1,5 @@ using Umbraco.Core.Models; +using Umbraco.Tests.Shared.Builders.Markers; namespace Umbraco.Tests.Shared.Builders { diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs index 5f88a636f7..d978980e2a 100644 --- a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Umbraco.Core.Models; +using Umbraco.Tests.Shared.Builders.Markers; namespace Umbraco.Tests.Shared.Builders { diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs index 3f471777c4..d74b0b1730 100644 --- a/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs @@ -1,5 +1,6 @@ using System; using Umbraco.Core.Models; +using Umbraco.Tests.Shared.Builders.Markers; namespace Umbraco.Tests.Shared.Builders { diff --git a/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs b/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs index 9b6a961c4f..a307e89cb0 100644 --- a/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs +++ b/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs @@ -1,4 +1,5 @@ using System; +using Umbraco.Tests.Shared.Builders.Markers; namespace Umbraco.Tests.Shared.Builders.Extensions { @@ -24,5 +25,19 @@ namespace Umbraco.Tests.Shared.Builders.Extensions builder.UpdateDate = updateDate; return builder; } + + public static T WithAlias(this T builder, string alias) + where T : IWithAliasBuilder + { + builder.Alias = alias; + return builder; + } + + public static T WithName(this T builder, string name) + where T : IWithNameBuilder + { + builder.Name = name; + return builder; + } } } diff --git a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs b/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs index d3855145f3..f4ec69541d 100644 --- a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs @@ -2,6 +2,7 @@ using System.Globalization; using Moq; using Umbraco.Core.Configuration; using Umbraco.Core.Models; +using Umbraco.Tests.Shared.Builders.Markers; namespace Umbraco.Tests.Shared.Builders { diff --git a/src/Umbraco.Tests.Shared/Builders/Markers/IWithCreateDateBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Markers/IWithCreateDateBuilder.cs index 3ea3b9e7cc..6bc3c8c887 100644 --- a/src/Umbraco.Tests.Shared/Builders/Markers/IWithCreateDateBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/Markers/IWithCreateDateBuilder.cs @@ -1,6 +1,6 @@ using System; -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Shared.Builders.Markers { public interface IWithCreateDateBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Markers/IWithIdBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Markers/IWithIdBuilder.cs index 7575d2429d..da93d9ac1f 100644 --- a/src/Umbraco.Tests.Shared/Builders/Markers/IWithIdBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/Markers/IWithIdBuilder.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Shared.Builders.Markers { public interface IWithIdBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Markers/IWithUpdateDateBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Markers/IWithUpdateDateBuilder.cs index a0d4fe6258..5ced57fa4e 100644 --- a/src/Umbraco.Tests.Shared/Builders/Markers/IWithUpdateDateBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/Markers/IWithUpdateDateBuilder.cs @@ -1,6 +1,6 @@ using System; -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Shared.Builders.Markers { public interface IWithUpdateDateBuilder { From 3dbe0c2847e4b0ea405eb5ce380f9922aa5273cd Mon Sep 17 00:00:00 2001 From: elitsa Date: Thu, 9 Jan 2020 16:38:31 +0100 Subject: [PATCH 07/28] Fixing indentation --- .../Umbraco.Infrastructure/Models/DataTypeTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs index ecd4249bc6..ce984b3a79 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs @@ -46,8 +46,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models [Test] public void Can_Serialize_Without_Error() { - var item = _builder - .Build(); + var item = _builder.Build(); Assert.DoesNotThrow(() => JsonConvert.SerializeObject(item)); } From 0748fede869a3a9b93a8267abc0c0ef8a20f066a Mon Sep 17 00:00:00 2001 From: elitsa Date: Thu, 9 Jan 2020 16:39:28 +0100 Subject: [PATCH 08/28] Adding tests for RelationType --- .../Builders/Markers/IWithAliasBuilder.cs | 7 +++ .../Builders/Markers/IWithNameBuilder.cs | 7 +++ .../Builders/RelationTypeBuilder.cs | 61 +++++++++++++++++++ .../Models/RelationTypeTests.cs | 50 +++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 src/Umbraco.Tests.Shared/Builders/Markers/IWithAliasBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/Markers/IWithNameBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs create mode 100644 src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs diff --git a/src/Umbraco.Tests.Shared/Builders/Markers/IWithAliasBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Markers/IWithAliasBuilder.cs new file mode 100644 index 0000000000..1a754ccaaf --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/Markers/IWithAliasBuilder.cs @@ -0,0 +1,7 @@ +namespace Umbraco.Tests.Shared.Builders.Markers +{ + public interface IWithAliasBuilder + { + string Alias { get; set; } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/Markers/IWithNameBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Markers/IWithNameBuilder.cs new file mode 100644 index 0000000000..1170e7c446 --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/Markers/IWithNameBuilder.cs @@ -0,0 +1,7 @@ +namespace Umbraco.Tests.Shared.Builders.Markers +{ + public interface IWithNameBuilder + { + string Name { get; set; } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs b/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs new file mode 100644 index 0000000000..c00690650d --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs @@ -0,0 +1,61 @@ +using System; +using Umbraco.Core.Models; +using Umbraco.Tests.Shared.Builders.Markers; + +namespace Umbraco.Tests.Shared.Builders +{ + + public class RelationTypeBuilder : RelationTypeBuilder + { + public RelationTypeBuilder() : base(null) + { + } + } + + public class RelationTypeBuilder : ChildBuilderBase, IWithIdBuilder, IWithAliasBuilder, IWithNameBuilder + { + private int? _id; + private string _alias; + private string _name; + private readonly Guid? _parentObjectType = null; + private readonly Guid? _childObjectType = null; + + public RelationTypeBuilder(TParent parentBuilder) : base(parentBuilder) + { + } + + + public override IRelationType Build() + { + var alias = _alias ?? Guid.NewGuid().ToString(); + var name = _name ?? Guid.NewGuid().ToString(); + var parentObjectType = _parentObjectType ?? Guid.NewGuid(); + var childObjectType = _childObjectType ?? Guid.NewGuid(); + var id = _id ?? 1; + + return new RelationType(name, alias, false, parentObjectType, + childObjectType) + { + Id = id + }; + } + + int? IWithIdBuilder.Id + { + get => _id; + set => _id = value; + } + + string IWithAliasBuilder.Alias + { + get => _alias; + set => _alias = value; + } + + string IWithNameBuilder.Name + { + get => _name; + set => _name = value; + } + } +} diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs new file mode 100644 index 0000000000..da255926df --- /dev/null +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Newtonsoft.Json; +using NUnit.Framework; +using Umbraco.Core.Models; +using Umbraco.Tests.Shared.Builders; + +namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models +{ + [TestFixture] + public class RelationTypeTests + { + private readonly RelationTypeBuilder _builder = new RelationTypeBuilder(); + + [Test] + public void Can_Deep_Clone() + { + var item = _builder.Build(); + + var clone = (RelationType) item.DeepClone(); + + Assert.AreNotSame(clone, item); + Assert.AreEqual(clone, item); + Assert.AreEqual(clone.Alias, item.Alias); + Assert.AreEqual(clone.ChildObjectType, item.ChildObjectType); + Assert.AreEqual(clone.IsBidirectional, item.IsBidirectional); + Assert.AreEqual(clone.Id, item.Id); + Assert.AreEqual(clone.Key, item.Key); + Assert.AreEqual(clone.Name, item.Name); + Assert.AreNotSame(clone.ParentObjectType, item.ParentObjectType); + Assert.AreEqual(clone.UpdateDate, item.UpdateDate); + + //This double verifies by reflection + var allProps = clone.GetType().GetProperties(); + foreach (var propertyInfo in allProps) + { + Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null)); + } + } + + [Test] + public void Can_Serialize_Without_Error() + { + var item = _builder.Build(); + + Assert.DoesNotThrow(() => JsonConvert.SerializeObject(item)); + } + } +} From 7656072bd576b45128f275ab2f1189405d698a8a Mon Sep 17 00:00:00 2001 From: elitsa Date: Thu, 9 Jan 2020 16:45:46 +0100 Subject: [PATCH 09/28] Fixing namespaces and usings --- src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs | 2 +- src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs | 2 +- .../Builders/DictionaryTranslationBuilder.cs | 2 +- .../Builders/Extensions/BuilderExtensions.cs | 2 +- .../Builders/Interfaces/IWithAliasBuilder.cs | 2 +- .../Builders/Interfaces/IWithCreateDateBuilder.cs | 2 +- .../Builders/Interfaces/IWithIdBuilder.cs | 2 +- .../Builders/Interfaces/IWithNameBuilder.cs | 2 +- .../Builders/Interfaces/IWithUpdateDateBuilder.cs | 2 +- src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs | 2 +- src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs | 2 +- .../Umbraco.Infrastructure/Models/RelationTypeTests.cs | 5 +---- 12 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs index b22b313a75..ed225d53bd 100644 --- a/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs @@ -1,5 +1,5 @@ using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders.Markers; +using Umbraco.Tests.Shared.Builders.Interfaces; namespace Umbraco.Tests.Shared.Builders { diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs index d978980e2a..97837f6783 100644 --- a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders.Markers; +using Umbraco.Tests.Shared.Builders.Interfaces; namespace Umbraco.Tests.Shared.Builders { diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs index d74b0b1730..5d44488bab 100644 --- a/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs @@ -1,6 +1,6 @@ using System; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders.Markers; +using Umbraco.Tests.Shared.Builders.Interfaces; namespace Umbraco.Tests.Shared.Builders { diff --git a/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs b/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs index a307e89cb0..0180e9e54c 100644 --- a/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs +++ b/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs @@ -1,5 +1,5 @@ using System; -using Umbraco.Tests.Shared.Builders.Markers; +using Umbraco.Tests.Shared.Builders.Interfaces; namespace Umbraco.Tests.Shared.Builders.Extensions { diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithAliasBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithAliasBuilder.cs index 1a754ccaaf..3ab70123f4 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithAliasBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithAliasBuilder.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Tests.Shared.Builders.Markers +namespace Umbraco.Tests.Shared.Builders.Interfaces { public interface IWithAliasBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCreateDateBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCreateDateBuilder.cs index 6bc3c8c887..7a7b69fc95 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCreateDateBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCreateDateBuilder.cs @@ -1,6 +1,6 @@ using System; -namespace Umbraco.Tests.Shared.Builders.Markers +namespace Umbraco.Tests.Shared.Builders.Interfaces { public interface IWithCreateDateBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithIdBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithIdBuilder.cs index da93d9ac1f..a5a6175d8f 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithIdBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithIdBuilder.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Tests.Shared.Builders.Markers +namespace Umbraco.Tests.Shared.Builders.Interfaces { public interface IWithIdBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithNameBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithNameBuilder.cs index 1170e7c446..2ddcf65333 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithNameBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithNameBuilder.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Tests.Shared.Builders.Markers +namespace Umbraco.Tests.Shared.Builders.Interfaces { public interface IWithNameBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithUpdateDateBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithUpdateDateBuilder.cs index 5ced57fa4e..88a23d0275 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithUpdateDateBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithUpdateDateBuilder.cs @@ -1,6 +1,6 @@ using System; -namespace Umbraco.Tests.Shared.Builders.Markers +namespace Umbraco.Tests.Shared.Builders.Interfaces { public interface IWithUpdateDateBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs b/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs index f4ec69541d..4b196e169c 100644 --- a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs @@ -2,7 +2,7 @@ using System.Globalization; using Moq; using Umbraco.Core.Configuration; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders.Markers; +using Umbraco.Tests.Shared.Builders.Interfaces; namespace Umbraco.Tests.Shared.Builders { diff --git a/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs b/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs index c00690650d..55ec30fd77 100644 --- a/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs @@ -1,6 +1,6 @@ using System; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders.Markers; +using Umbraco.Tests.Shared.Builders.Interfaces; namespace Umbraco.Tests.Shared.Builders { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs index da255926df..4054f9d992 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Newtonsoft.Json; +using Newtonsoft.Json; using NUnit.Framework; using Umbraco.Core.Models; using Umbraco.Tests.Shared.Builders; From 2b0e9e8450d5f39d0a7e9fcc0c4b4e1303eb0859 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 13 Jan 2020 07:29:12 +0100 Subject: [PATCH 10/28] Added more options on the test builders --- .../Builders/ConfigurationEditorBuilder.cs | 33 +++ .../Builders/DataEditorBuilder.cs | 34 ++- .../Builders/DataTypeBuilder.cs | 138 ++++++++++- .../Builders/DataValueEditorBuilder.cs | 66 ++++++ .../Builders/DictionaryItemBuilder.cs | 105 +++++--- .../Builders/DictionaryTranslationBuilder.cs | 103 ++++---- .../Builders/Extensions/BuilderExtensions.cs | 7 + .../Builders/GlobalSettingsBuilder.cs | 224 ++++++++++++++++++ .../Interfaces/IWithCultureInfoBuilder.cs | 9 + .../Interfaces/IWithDeleteDateBuilder.cs | 9 + .../Builders/Interfaces/IWithKeyBuilder.cs | 9 + .../Builders/LanguageBuilder.cs | 101 +++++++- .../Builders/RelationTypeBuilder.cs | 116 ++++++--- .../Umbraco.Tests.Shared.csproj | 1 + .../Models/LanguageTests.cs | 1 + .../Models/RelationTypeTests.cs | 10 +- 16 files changed, 842 insertions(+), 124 deletions(-) create mode 100644 src/Umbraco.Tests.Shared/Builders/ConfigurationEditorBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/DataValueEditorBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/GlobalSettingsBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCultureInfoBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/Interfaces/IWithDeleteDateBuilder.cs create mode 100644 src/Umbraco.Tests.Shared/Builders/Interfaces/IWithKeyBuilder.cs diff --git a/src/Umbraco.Tests.Shared/Builders/ConfigurationEditorBuilder.cs b/src/Umbraco.Tests.Shared/Builders/ConfigurationEditorBuilder.cs new file mode 100644 index 0000000000..3abf683bf2 --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/ConfigurationEditorBuilder.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using Umbraco.Core.PropertyEditors; + +namespace Umbraco.Tests.Shared.Builders +{ + public class ConfigurationEditorBuilder : ChildBuilderBase + { + private IDictionary _defaultConfiguration; + + + public ConfigurationEditorBuilder(TParent parentBuilder) : base(parentBuilder) + { + } + + + public ConfigurationEditorBuilder WithDefaultConfiguration(IDictionary defaultConfiguration) + { + _defaultConfiguration = defaultConfiguration; + return this; + } + + public override IConfigurationEditor Build() + { + var defaultConfiguration = _defaultConfiguration ?? new Dictionary(); + + return new ConfigurationEditor() + { + DefaultConfiguration = defaultConfiguration, + }; + } + + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/DataEditorBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DataEditorBuilder.cs index 5a0b18cf9e..0a9e94a74e 100644 --- a/src/Umbraco.Tests.Shared/Builders/DataEditorBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DataEditorBuilder.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using Moq; using Umbraco.Core.Logging; using Umbraco.Core.PropertyEditors; @@ -8,21 +9,46 @@ namespace Umbraco.Tests.Shared.Builders { public class DataEditorBuilder : ChildBuilderBase { + private readonly ConfigurationEditorBuilder> _explicitConfigurationEditorBuilder; + private readonly DataValueEditorBuilder> _explicitValueEditorBuilder; + private IDictionary _defaultConfiguration; + public DataEditorBuilder(TParent parentBuilder) : base(parentBuilder) { + _explicitConfigurationEditorBuilder = new ConfigurationEditorBuilder>(this); + _explicitValueEditorBuilder = new DataValueEditorBuilder>(this); } + public DataEditorBuilder WithDefaultConfiguration(IDictionary defaultConfiguration) + { + _defaultConfiguration = defaultConfiguration; + return this; + } + + public ConfigurationEditorBuilder> AddExplicitConfigurationEditorBuilder() => + _explicitConfigurationEditorBuilder; + + public DataValueEditorBuilder> AddExplicitValueEditorBuilder() => + _explicitValueEditorBuilder; + public override IDataEditor Build() { - var result = new DataEditor( + var defaultConfiguration = _defaultConfiguration ?? new Dictionary(); + var explicitConfigurationEditor = _explicitConfigurationEditorBuilder.Build(); + var explicitValueEditor = _explicitValueEditorBuilder.Build(); + + return new DataEditor( Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of() - ); - - return result; + ) + { + DefaultConfiguration = defaultConfiguration, + ExplicitConfigurationEditor = explicitConfigurationEditor, + ExplicitValueEditor = explicitValueEditor + }; } } } diff --git a/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs index ed225d53bd..62e9e35ee0 100644 --- a/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs @@ -1,28 +1,124 @@ +using System; using Umbraco.Core.Models; using Umbraco.Tests.Shared.Builders.Interfaces; namespace Umbraco.Tests.Shared.Builders { - public class DataTypeBuilder : BuilderBase, IWithIdBuilder + public class DataTypeBuilder + : BuilderBase, + IWithIdBuilder, + IWithKeyBuilder, + IWithCreateDateBuilder, + IWithUpdateDateBuilder, + IWithDeleteDateBuilder, + IWithNameBuilder { private readonly DataEditorBuilder _dataEditorBuilder; private int? _id; + private int? _parentId; + private Guid? _key; + private DateTime? _createDate; + private DateTime? _updateDate; + private DateTime? _deleteDate; + private string _name; + private bool? _trashed; + // private object _configuration; + private int? _level; + private string _path; + private int? _creatorId; + private ValueStorageType? _databaseType; + private int? _sortOrder; public DataTypeBuilder() { _dataEditorBuilder = new DataEditorBuilder(this); } + public DataTypeBuilder WithParentId(int parentId) + { + _parentId = parentId; + return this; + } + + public DataTypeBuilder WithTrashed(bool trashed) + { + _trashed = trashed; + return this; + } + + // public DataTypeBuilder WithConfiguration(object configuration) + // { + // _configuration = configuration; + // return this; + // } + + public DataTypeBuilder WithLevel(int level) + { + _level = level; + return this; + } + + public DataTypeBuilder WithPath(string path) + { + _path = path; + return this; + } + + public DataTypeBuilder WithCreatorId(int creatorId) + { + _creatorId = creatorId; + return this; + } + + public DataTypeBuilder WithDatabaseType(ValueStorageType databaseType) + { + _databaseType = databaseType; + return this; + } + + public DataTypeBuilder WithSortOrder(int sortOrder) + { + _sortOrder = sortOrder; + return this; + } + + public DataEditorBuilder AddEditor() + { + return _dataEditorBuilder; + } + public override DataType Build() { var editor = _dataEditorBuilder.Build(); + var parentId = _parentId ?? -1; var id = _id ?? 1; - var result = new DataType(editor) - { - Id = id - }; + var key = _key ?? Guid.NewGuid(); + var createDate = _createDate ?? DateTime.Now; + var updateDate = _updateDate ?? DateTime.Now; + var deleteDate = _deleteDate ?? null; + var name = _name ?? Guid.NewGuid().ToString(); + // var configuration = _configuration ?? editor.GetConfigurationEditor().DefaultConfigurationObject; + var level = _level ?? 0; + var path = _path ?? string.Empty; + var creatorId = _creatorId ?? 1; + var databaseType = _databaseType ?? ValueStorageType.Ntext; + var sortOrder = _sortOrder ?? 0; - return result; + return new DataType(editor, parentId) + { + Id = id, + Key = key, + CreateDate = createDate, + UpdateDate = updateDate, + DeleteDate = deleteDate, + Name = name, + Trashed = _trashed ?? false, + Level = level, + Path = path, + CreatorId = creatorId, + DatabaseType = databaseType, + SortOrder = sortOrder, + }; } int? IWithIdBuilder.Id @@ -30,5 +126,35 @@ namespace Umbraco.Tests.Shared.Builders get => _id; set => _id = value; } + + Guid? IWithKeyBuilder.Key + { + get => _key; + set => _key = value; + } + + DateTime? IWithCreateDateBuilder.CreateDate + { + get => _createDate; + set => _createDate = value; + } + + DateTime? IWithUpdateDateBuilder.UpdateDate + { + get => _updateDate; + set => _updateDate = value; + } + + DateTime? IWithDeleteDateBuilder.DeleteDate + { + get => _deleteDate; + set => _deleteDate = value; + } + + string IWithNameBuilder.Name + { + get => _name; + set => _name = value; + } } } diff --git a/src/Umbraco.Tests.Shared/Builders/DataValueEditorBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DataValueEditorBuilder.cs new file mode 100644 index 0000000000..be26510934 --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/DataValueEditorBuilder.cs @@ -0,0 +1,66 @@ +using System; +using Moq; +using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Services; +using Umbraco.Core.Strings; + +namespace Umbraco.Tests.Shared.Builders +{ + public class DataValueEditorBuilder : ChildBuilderBase + { + private string _configuration; + private string _view; + private bool? _hideLabel; + private string _valueType; + + + public DataValueEditorBuilder(TParent parentBuilder) : base(parentBuilder) + { + } + + public DataValueEditorBuilder WithConfiguration(string configuration) + { + _configuration = configuration; + return this; + } + + public DataValueEditorBuilder WithView(string view) + { + _view = view; + return this; + } + + public DataValueEditorBuilder WithHideLabel(bool hideLabel) + { + _hideLabel = hideLabel; + return this; + } + + public DataValueEditorBuilder WithValueType(string valueType) + { + _valueType = valueType; + return this; + } + + public override IDataValueEditor Build() + { + var configuration = _configuration ?? null; + var view = _view ?? null; + var hideLabel = _hideLabel ?? false; + var valueType = _valueType ?? Guid.NewGuid().ToString(); + + return new DataValueEditor( + Mock.Of(), + Mock.Of(), + Mock.Of(), + Mock.Of() + ) + { + Configuration = configuration, + View = view, + HideLabel = hideLabel, + ValueType = valueType, + }; + } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs index 97837f6783..6baff80972 100644 --- a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs @@ -6,28 +6,90 @@ using Umbraco.Tests.Shared.Builders.Interfaces; namespace Umbraco.Tests.Shared.Builders { - public class DictionaryItemBuilder : IWithIdBuilder, IWithCreateDateBuilder, IWithUpdateDateBuilder + public class DictionaryItemBuilder + : BuilderBase, + IWithIdBuilder, + IWithCreateDateBuilder, + IWithUpdateDateBuilder, + IWithDeleteDateBuilder, + IWithKeyBuilder { - private string _itemkey = null; - private readonly List _translationBuilders = new List(); - private DateTime? _createDate; - private DateTime? _updateDate; - private int? _id = null; + private readonly List _translationBuilders = + new List(); - public DictionaryItem Build() + private DateTime? _createDate; + private DateTime? _deleteDate; + private int? _id; + private string _itemKey; + private Guid? _key; + private Guid? _parentId; + private DateTime? _updateDate; + + DateTime? IWithCreateDateBuilder.CreateDate + { + get => _createDate; + set => _createDate = value; + } + + DateTime? IWithDeleteDateBuilder.DeleteDate + { + get => _deleteDate; + set => _deleteDate = value; + } + + int? IWithIdBuilder.Id + { + get => _id; + set => _id = value; + } + + Guid? IWithKeyBuilder.Key + { + get => _key; + set => _key = value; + } + + DateTime? IWithUpdateDateBuilder.UpdateDate + { + get => _updateDate; + set => _updateDate = value; + } + + public override DictionaryItem Build() { var createDate = _createDate ?? DateTime.Now; var updateDate = _updateDate ?? DateTime.Now; + var deleteDate = _deleteDate ?? null; var id = _id ?? 1; + var key = _key ?? Guid.NewGuid(); + var parentId = _parentId ?? null; + var itemKey = _itemKey ?? Guid.NewGuid().ToString(); - var result = new DictionaryItem(_itemkey ?? Guid.NewGuid().ToString()); - result.Translations = _translationBuilders.Select(x => x.Build()); - result.CreateDate = createDate; - result.UpdateDate = updateDate; - result.Id = id; + var result = new DictionaryItem(itemKey) + { + Translations = _translationBuilders.Select(x => x.Build()), + CreateDate = createDate, + UpdateDate = updateDate, + DeleteDate = deleteDate, + Id = id, + ParentId = parentId, + Key = key, + }; return result; } + public DictionaryItemBuilder WithParentId(Guid parentId) + { + _parentId = parentId; + return this; + } + + public DictionaryItemBuilder WithItemKey(string itemKey) + { + _itemKey = itemKey; + return this; + } + public DictionaryTranslationBuilder AddTranslation() { var builder = new DictionaryTranslationBuilder(this); @@ -43,25 +105,8 @@ namespace Umbraco.Tests.Shared.Builders { AddTranslation().Done(); } + return this; } - - int? IWithIdBuilder.Id - { - get => _id; - set => _id = value; - } - - DateTime? IWithCreateDateBuilder.CreateDate - { - get => _createDate; - set => _createDate = value; - } - - DateTime? IWithUpdateDateBuilder.UpdateDate - { - get => _updateDate; - set => _updateDate = value; - } } } diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs b/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs index 5d44488bab..bd596383d1 100644 --- a/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs @@ -4,56 +4,27 @@ using Umbraco.Tests.Shared.Builders.Interfaces; namespace Umbraco.Tests.Shared.Builders { - public class DictionaryTranslationBuilder : ChildBuilderBase, IWithIdBuilder, IWithCreateDateBuilder, IWithUpdateDateBuilder + public class DictionaryTranslationBuilder + : ChildBuilderBase, + IWithIdBuilder, + IWithCreateDateBuilder, + IWithUpdateDateBuilder, + IWithDeleteDateBuilder, + IWithKeyBuilder { - private string _value = null; - private Guid? _uniqueId = null; + private readonly LanguageBuilder _languageBuilder; + private readonly Guid? _uniqueId = null; private DateTime? _createDate; + private DateTime? _deleteDate; + private int? _id; + private Guid? _key; private DateTime? _updateDate; + private string _value; - private LanguageBuilder _languageBuilder; - private int? _id = null; - public DictionaryTranslationBuilder(DictionaryItemBuilder parentBuilder) : base(parentBuilder) { _languageBuilder = new LanguageBuilder(this); - - } - - public override IDictionaryTranslation Build() - { - var createDate = _createDate ?? DateTime.Now; - var updateDate = _updateDate ?? DateTime.Now; - var id = _id ?? 1; - - var result = new DictionaryTranslation( - _languageBuilder.Build(), - _value ?? Guid.NewGuid().ToString(), - _uniqueId ?? Guid.NewGuid()); - - result.CreateDate = createDate; - result.UpdateDate = updateDate; - result.Id = id; - - return result; - } - - public LanguageBuilder WithLanguage() - { - return _languageBuilder; - } - - public DictionaryTranslationBuilder WithValue(string value) - { - _value = value; - return this; - } - - int? IWithIdBuilder.Id - { - get => _id; - set => _id = value; } DateTime? IWithCreateDateBuilder.CreateDate @@ -62,10 +33,58 @@ namespace Umbraco.Tests.Shared.Builders set => _createDate = value; } + DateTime? IWithDeleteDateBuilder.DeleteDate + { + get => _deleteDate; + set => _deleteDate = value; + } + + int? IWithIdBuilder.Id + { + get => _id; + set => _id = value; + } + + Guid? IWithKeyBuilder.Key + { + get => _key; + set => _key = value; + } + DateTime? IWithUpdateDateBuilder.UpdateDate { get => _updateDate; set => _updateDate = value; } + + public override IDictionaryTranslation Build() + { + var createDate = _createDate ?? DateTime.Now; + var updateDate = _updateDate ?? DateTime.Now; + var deleteDate = _deleteDate ?? null; + var id = _id ?? 1; + var key = _key ?? Guid.NewGuid(); + + var result = new DictionaryTranslation( + _languageBuilder.Build(), + _value ?? Guid.NewGuid().ToString(), + _uniqueId ?? key) + { + CreateDate = createDate, + UpdateDate = updateDate, + DeleteDate = deleteDate, + Id = id + }; + + return result; + } + + public LanguageBuilder AddLanguage() => _languageBuilder; + + public DictionaryTranslationBuilder WithValue(string value) + { + _value = value; + return this; + } } } diff --git a/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs b/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs index 0180e9e54c..702bb19bb2 100644 --- a/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs +++ b/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs @@ -39,5 +39,12 @@ namespace Umbraco.Tests.Shared.Builders.Extensions builder.Name = name; return builder; } + + public static T WithKey(this T builder, Guid key) + where T : IWithKeyBuilder + { + builder.Key = key; + return builder; + } } } diff --git a/src/Umbraco.Tests.Shared/Builders/GlobalSettingsBuilder.cs b/src/Umbraco.Tests.Shared/Builders/GlobalSettingsBuilder.cs new file mode 100644 index 0000000000..b3c8e90fa5 --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/GlobalSettingsBuilder.cs @@ -0,0 +1,224 @@ +using Umbraco.Core.Configuration; + +namespace Umbraco.Tests.Shared.Builders +{ + public class GlobalSettingsBuilder : GlobalSettingsBuilder + { + public GlobalSettingsBuilder() : base(null) + { + } + } + + public class GlobalSettingsBuilder : ChildBuilderBase + + { + private string _configurationStatus; + private string _databaseFactoryServerVersion; + private string _defaultUiLanguage; + private bool? _disableElectionForSingleServer; + private bool? _hideTopLevelNodeFromPath; + private bool? _installEmptyDatabase; + private bool? _installMissingDatabase; + private bool? _isSmtpServerConfigured; + private string _path; + private string _registerType; + private string _reservedPaths; + private string _reservedUrls; + private int? _timeOutInMinutes; + private string _umbracoCssPath; + private string _umbracoMediaPath; + private string _umbracoPath; + private string _umbracoScriptsPath; + private bool? _useHttps; + private int? _versionCheckPeriod; + + + public GlobalSettingsBuilder(TParent parentBuilder) : base(parentBuilder) + { + } + + public GlobalSettingsBuilder WithConfigurationStatus(string configurationStatus) + { + _configurationStatus = configurationStatus; + return this; + } + + public GlobalSettingsBuilder WithDatabaseFactoryServerVersion(string databaseFactoryServerVersion) + { + _databaseFactoryServerVersion = databaseFactoryServerVersion; + return this; + } + + public GlobalSettingsBuilder WithDefaultUiLanguage(string defaultUiLanguage) + { + _defaultUiLanguage = defaultUiLanguage; + return this; + } + + public GlobalSettingsBuilder WithDisableElectionForSingleServer(bool disableElectionForSingleServer) + { + _disableElectionForSingleServer = disableElectionForSingleServer; + return this; + } + + public GlobalSettingsBuilder WithHideTopLevelNodeFromPath(bool hideTopLevelNodeFromPath) + { + _hideTopLevelNodeFromPath = hideTopLevelNodeFromPath; + return this; + } + + public GlobalSettingsBuilder WithInstallEmptyDatabase(bool installEmptyDatabase) + { + _installEmptyDatabase = installEmptyDatabase; + return this; + } + + public GlobalSettingsBuilder WithInstallMissingDatabase(bool installMissingDatabase) + { + _installMissingDatabase = installMissingDatabase; + return this; + } + + public GlobalSettingsBuilder WithIsSmtpServerConfigured(bool isSmtpServerConfigured) + { + _isSmtpServerConfigured = isSmtpServerConfigured; + return this; + } + + public GlobalSettingsBuilder WithPath(string path) + { + _path = path; + return this; + } + + public GlobalSettingsBuilder WithRegisterType(string registerType) + { + _registerType = registerType; + return this; + } + + public GlobalSettingsBuilder WithReservedPaths(string reservedPaths) + { + _reservedPaths = reservedPaths; + return this; + } + + public GlobalSettingsBuilder WithReservedUrls(string reservedUrls) + { + _reservedUrls = reservedUrls; + return this; + } + + public GlobalSettingsBuilder WithUmbracoPath(string umbracoPath) + { + _umbracoPath = umbracoPath; + return this; + } + + public GlobalSettingsBuilder WithUseHttps(bool useHttps) + { + _useHttps = useHttps; + return this; + } + + public GlobalSettingsBuilder WithUmbracoCssPath(string umbracoCssPath) + { + _umbracoCssPath = umbracoCssPath; + return this; + } + + public GlobalSettingsBuilder WithUmbracoMediaPath(string umbracoMediaPath) + { + _umbracoMediaPath = umbracoMediaPath; + return this; + } + + public GlobalSettingsBuilder WithUmbracoScriptsPath(string umbracoScriptsPath) + { + _umbracoScriptsPath = umbracoScriptsPath; + return this; + } + + public GlobalSettingsBuilder WithVersionCheckPeriod(int versionCheckPeriod) + { + _versionCheckPeriod = versionCheckPeriod; + return this; + } + + public GlobalSettingsBuilder WithTimeOutInMinutes(int timeOutInMinutes) + { + _timeOutInMinutes = timeOutInMinutes; + return this; + } + + public override IGlobalSettings Build() + { + var configurationStatus = _configurationStatus ?? "9.0.0"; + var databaseFactoryServerVersion = _databaseFactoryServerVersion ?? null; + var defaultUiLanguage = _defaultUiLanguage ?? "en"; + var disableElectionForSingleServer = _disableElectionForSingleServer ?? false; + var hideTopLevelNodeFromPath = _hideTopLevelNodeFromPath ?? false; + var installEmptyDatabase = _installEmptyDatabase ?? false; + var installMissingDatabase = _installMissingDatabase ?? false; + var isSmtpServerConfigured = _isSmtpServerConfigured ?? false; + var path = _path ?? "/umbraco"; + var registerType = _registerType ?? null; + var reservedPaths = _reservedPaths ?? "~/app_plugins/,~/install/,~/mini-profiler-resources/,"; + var reservedUrls = _reservedUrls ?? "~/config/splashes/noNodes.aspx,~/.well-known,"; + var umbracoPath = _umbracoPath ?? "~/umbraco"; + var useHttps = _useHttps ?? false; + var umbracoCssPath = _umbracoCssPath ?? "~/css"; + var umbracoMediaPath = _umbracoMediaPath ?? "~/media"; + var umbracoScriptsPath = _umbracoScriptsPath ?? "~/scripts"; + var versionCheckPeriod = _versionCheckPeriod ?? 0; + var timeOutInMinutes = _timeOutInMinutes ?? 20; + + + return new TestGlobalSettings + { + ConfigurationStatus = configurationStatus, + DatabaseFactoryServerVersion = databaseFactoryServerVersion, + DefaultUILanguage = defaultUiLanguage, + DisableElectionForSingleServer = disableElectionForSingleServer, + HideTopLevelNodeFromPath = hideTopLevelNodeFromPath, + InstallEmptyDatabase = installEmptyDatabase, + InstallMissingDatabase = installMissingDatabase, + IsSmtpServerConfigured = isSmtpServerConfigured, + Path = path, + RegisterType = registerType, + ReservedPaths = reservedPaths, + ReservedUrls = reservedUrls, + UmbracoPath = umbracoPath, + UseHttps = useHttps, + UmbracoCssPath = umbracoCssPath, + UmbracoMediaPath = umbracoMediaPath, + UmbracoScriptsPath = umbracoScriptsPath, + VersionCheckPeriod = versionCheckPeriod, + TimeOutInMinutes = timeOutInMinutes + }; + } + + private class TestGlobalSettings : IGlobalSettings + { + public string ReservedUrls { get; set; } + public string ReservedPaths { get; set; } + public string Path { get; set; } + public string ConfigurationStatus { get; set; } + public int TimeOutInMinutes { get; set; } + public string DefaultUILanguage { get; set; } + public bool HideTopLevelNodeFromPath { get; set; } + public bool UseHttps { get; set; } + public int VersionCheckPeriod { get; set; } + public string UmbracoPath { get; set; } + public string UmbracoCssPath { get; set; } + public string UmbracoScriptsPath { get; set; } + public string UmbracoMediaPath { get; set; } + public bool IsSmtpServerConfigured { get; set; } + public bool InstallMissingDatabase { get; set; } + public bool InstallEmptyDatabase { get; set; } + public bool DisableElectionForSingleServer { get; set; } + public string RegisterType { get; set; } + public string DatabaseFactoryServerVersion { get; set; } + } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCultureInfoBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCultureInfoBuilder.cs new file mode 100644 index 0000000000..ee33d4549d --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCultureInfoBuilder.cs @@ -0,0 +1,9 @@ +using System.Globalization; + +namespace Umbraco.Tests.Shared.Builders.Interfaces +{ + public interface IWithCultureInfoBuilder + { + CultureInfo CultureInfo { get; set; } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithDeleteDateBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithDeleteDateBuilder.cs new file mode 100644 index 0000000000..3ae8ddfeed --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithDeleteDateBuilder.cs @@ -0,0 +1,9 @@ +using System; + +namespace Umbraco.Tests.Shared.Builders.Interfaces +{ + public interface IWithDeleteDateBuilder + { + DateTime? DeleteDate { get; set; } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithKeyBuilder.cs b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithKeyBuilder.cs new file mode 100644 index 0000000000..78da4dbc0b --- /dev/null +++ b/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithKeyBuilder.cs @@ -0,0 +1,9 @@ +using System; + +namespace Umbraco.Tests.Shared.Builders.Interfaces +{ + public interface IWithKeyBuilder + { + Guid? Key { get; set; } + } +} diff --git a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs b/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs index 4b196e169c..59e859dd3a 100644 --- a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs @@ -1,3 +1,4 @@ +using System; using System.Globalization; using Moq; using Umbraco.Core.Configuration; @@ -13,27 +14,45 @@ namespace Umbraco.Tests.Shared.Builders } } - - public class LanguageBuilder : ChildBuilderBase, IWithIdBuilder + public class LanguageBuilder + : ChildBuilderBase, + IWithIdBuilder, + IWithKeyBuilder, + IWithCreateDateBuilder, + IWithUpdateDateBuilder, + IWithDeleteDateBuilder, + IWithCultureInfoBuilder { - - private string _isoCode = null; + private DateTime? _createDate; + private CultureInfo _cultureInfo; + private DateTime? _deleteDate; + private int? _fallbackLanguageId; private int? _id; + private bool? _isDefault; + private bool? _isMandatory; + private Guid? _key; + private DateTime? _updateDate; public LanguageBuilder(TParent parentBuilder) : base(parentBuilder) { } - public override ILanguage Build() + DateTime? IWithCreateDateBuilder.CreateDate { - var culture = CultureInfo.GetCultureInfo("en-US"); - var isoCode = _isoCode ?? culture.Name; - return new Language(Mock.Of(), isoCode) - { - Id = _id ?? 1, - CultureName = culture.TwoLetterISOLanguageName, - IsoCode = new RegionInfo(culture.LCID).Name, - }; + get => _createDate; + set => _createDate = value; + } + + CultureInfo IWithCultureInfoBuilder.CultureInfo + { + get => _cultureInfo; + set => _cultureInfo = value; + } + + DateTime? IWithDeleteDateBuilder.DeleteDate + { + get => _deleteDate; + set => _deleteDate = value; } int? IWithIdBuilder.Id @@ -41,5 +60,61 @@ namespace Umbraco.Tests.Shared.Builders get => _id; set => _id = value; } + + Guid? IWithKeyBuilder.Key + { + get => _key; + set => _key = value; + } + + DateTime? IWithUpdateDateBuilder.UpdateDate + { + get => _updateDate; + set => _updateDate = value; + } + + public override ILanguage Build() + { + var cultureInfo = _cultureInfo ?? CultureInfo.GetCultureInfo("en-US"); + var key = _key ?? Guid.NewGuid(); + var createDate = _createDate ?? DateTime.Now; + var updateDate = _updateDate ?? DateTime.Now; + var deleteDate = _deleteDate ?? null; + var fallbackLanguageId = _fallbackLanguageId ?? null; + var isDefault = _isDefault ?? false; + var isMandatory = _isMandatory ?? false; + + return new Language(Mock.Of(), cultureInfo.Name) + { + Id = _id ?? 1, + CultureName = cultureInfo.TwoLetterISOLanguageName, + IsoCode = new RegionInfo(cultureInfo.LCID).Name, + Key = key, + CreateDate = createDate, + UpdateDate = updateDate, + DeleteDate = deleteDate, + IsDefault = isDefault, + IsMandatory = isMandatory, + FallbackLanguageId = fallbackLanguageId + }; + } + + public LanguageBuilder WithIsDefault(bool isDefault) + { + _isDefault = isDefault; + return this; + } + + public LanguageBuilder WithIsMandatory(bool isMandatory) + { + _isMandatory = isMandatory; + return this; + } + + public LanguageBuilder WithFallbackLanguageId(int fallbackLanguageId) + { + _fallbackLanguageId = fallbackLanguageId; + return this; + } } } diff --git a/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs b/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs index 55ec30fd77..2cb81688b7 100644 --- a/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs +++ b/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs @@ -4,7 +4,6 @@ using Umbraco.Tests.Shared.Builders.Interfaces; namespace Umbraco.Tests.Shared.Builders { - public class RelationTypeBuilder : RelationTypeBuilder { public RelationTypeBuilder() : base(null) @@ -12,39 +11,30 @@ namespace Umbraco.Tests.Shared.Builders } } - public class RelationTypeBuilder : ChildBuilderBase, IWithIdBuilder, IWithAliasBuilder, IWithNameBuilder + public class RelationTypeBuilder + : ChildBuilderBase, + IWithIdBuilder, + IWithAliasBuilder, + IWithNameBuilder, + IWithKeyBuilder, + IWithCreateDateBuilder, + IWithUpdateDateBuilder, + IWithDeleteDateBuilder { - private int? _id; private string _alias; + private Guid? _childObjectType; + private DateTime? _createDate; + private DateTime? _deleteDate; + private int? _id; + private bool? _isBidirectional; + private Guid? _key; private string _name; - private readonly Guid? _parentObjectType = null; - private readonly Guid? _childObjectType = null; + private Guid? _parentObjectType; + private DateTime? _updateDate; public RelationTypeBuilder(TParent parentBuilder) : base(parentBuilder) { } - - - public override IRelationType Build() - { - var alias = _alias ?? Guid.NewGuid().ToString(); - var name = _name ?? Guid.NewGuid().ToString(); - var parentObjectType = _parentObjectType ?? Guid.NewGuid(); - var childObjectType = _childObjectType ?? Guid.NewGuid(); - var id = _id ?? 1; - - return new RelationType(name, alias, false, parentObjectType, - childObjectType) - { - Id = id - }; - } - - int? IWithIdBuilder.Id - { - get => _id; - set => _id = value; - } string IWithAliasBuilder.Alias { @@ -52,10 +42,82 @@ namespace Umbraco.Tests.Shared.Builders set => _alias = value; } + DateTime? IWithCreateDateBuilder.CreateDate + { + get => _createDate; + set => _createDate = value; + } + + DateTime? IWithDeleteDateBuilder.DeleteDate + { + get => _deleteDate; + set => _deleteDate = value; + } + + int? IWithIdBuilder.Id + { + get => _id; + set => _id = value; + } + + Guid? IWithKeyBuilder.Key + { + get => _key; + set => _key = value; + } + string IWithNameBuilder.Name { get => _name; set => _name = value; } + + DateTime? IWithUpdateDateBuilder.UpdateDate + { + get => _updateDate; + set => _updateDate = value; + } + + public override IRelationType Build() + { + var alias = _alias ?? Guid.NewGuid().ToString(); + var name = _name ?? Guid.NewGuid().ToString(); + var parentObjectType = _parentObjectType ?? null; + var childObjectType = _childObjectType ?? null; + var id = _id ?? 1; + var key = _key ?? Guid.NewGuid(); + var isBidirectional = _isBidirectional ?? false; + var createDate = _createDate ?? DateTime.Now; + var updateDate = _updateDate ?? DateTime.Now; + var deleteDate = _deleteDate ?? null; + + return new RelationType(name, alias, isBidirectional, parentObjectType, + childObjectType) + { + Id = id, + Key = key, + CreateDate = createDate, + UpdateDate = updateDate, + DeleteDate = deleteDate + }; + } + + public RelationTypeBuilder WithIsBidirectional(bool isBidirectional) + { + _isBidirectional = isBidirectional; + return this; + } + + public RelationTypeBuilder WithChildObjectType(Guid childObjectType) + { + _childObjectType = childObjectType; + return this; + } + + public RelationTypeBuilder WithParentObjectType(Guid parentObjectType) + { + _parentObjectType = parentObjectType; + return this; + } } } diff --git a/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj b/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj index 93afb6f531..d18779a4fd 100644 --- a/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj +++ b/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj @@ -18,6 +18,7 @@ + diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/LanguageTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/LanguageTests.cs index 57ed20310a..6d80eac16f 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/LanguageTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/LanguageTests.cs @@ -2,6 +2,7 @@ using NUnit.Framework; using Umbraco.Core.Models; using Umbraco.Tests.Shared.Builders; +using Umbraco.Tests.Shared.Builders.Extensions; namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs index 4054f9d992..140b974b61 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs @@ -1,4 +1,5 @@ -using Newtonsoft.Json; +using System; +using Newtonsoft.Json; using NUnit.Framework; using Umbraco.Core.Models; using Umbraco.Tests.Shared.Builders; @@ -13,7 +14,10 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models [Test] public void Can_Deep_Clone() { - var item = _builder.Build(); + var item = _builder + .WithParentObjectType(Guid.NewGuid()) + .WithChildObjectType(Guid.NewGuid()) + .Build(); var clone = (RelationType) item.DeepClone(); @@ -21,11 +25,13 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models Assert.AreEqual(clone, item); Assert.AreEqual(clone.Alias, item.Alias); Assert.AreEqual(clone.ChildObjectType, item.ChildObjectType); + Assert.AreEqual(clone.ParentObjectType, item.ParentObjectType); Assert.AreEqual(clone.IsBidirectional, item.IsBidirectional); Assert.AreEqual(clone.Id, item.Id); Assert.AreEqual(clone.Key, item.Key); Assert.AreEqual(clone.Name, item.Name); Assert.AreNotSame(clone.ParentObjectType, item.ParentObjectType); + Assert.AreNotSame(clone.ChildObjectType, item.ChildObjectType); Assert.AreEqual(clone.UpdateDate, item.UpdateDate); //This double verifies by reflection From 8c8a9764cd7a88cea3ed3aea2c2193b96c90eee0 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 18 Mar 2020 07:42:35 +0100 Subject: [PATCH 11/28] Post merge + Added new SmtpSettingsBuilder --- .../Builders/BuilderBase.cs | 2 +- .../Builders/ChildBuilderBase.cs | 2 +- .../Builders/ConfigurationEditorBuilder.cs | 2 +- .../Builders/DataEditorBuilder.cs | 2 +- .../Builders/DataTypeBuilder.cs | 4 +- .../Builders/DataValueEditorBuilder.cs | 2 +- .../Builders/DictionaryItemBuilder.cs | 4 +- .../Builders/DictionaryTranslationBuilder.cs | 4 +- .../Builders/Extensions/BuilderExtensions.cs | 4 +- .../Builders/GlobalSettingsBuilder.cs | 31 +++- .../Builders/Interfaces/IWithAliasBuilder.cs | 2 +- .../Interfaces/IWithCreateDateBuilder.cs | 2 +- .../Interfaces/IWithCultureInfoBuilder.cs | 2 +- .../Interfaces/IWithDeleteDateBuilder.cs | 2 +- .../Builders/Interfaces/IWithIdBuilder.cs | 2 +- .../Builders/Interfaces/IWithKeyBuilder.cs | 2 +- .../Builders/Interfaces/IWithNameBuilder.cs | 2 +- .../Interfaces/IWithUpdateDateBuilder.cs | 2 +- .../Builders/LanguageBuilder.cs | 4 +- .../Builders/RelationTypeBuilder.cs | 4 +- .../Builders/SmtpSettingsBuilder.cs | 73 ++++++++++ .../Umbraco.Tests.Shared.csproj | 4 - .../Models/DataTypeTests.cs | 5 +- .../Models/DictionaryItemTests.cs | 2 +- .../Models/LanguageTests.cs | 3 +- .../Models/RelationTypeTests.cs | 2 +- .../Umbraco.Tests.UnitTests.csproj | 13 +- src/Umbraco.Tests/Models/DataTypeTests.cs | 85 ----------- .../Models/DictionaryItemTests.cs | 137 ------------------ src/Umbraco.Tests/Models/LanguageTests.cs | 66 --------- src/Umbraco.Tests/Models/RelationTypeTests.cs | 64 -------- src/Umbraco.Tests/Umbraco.Tests.csproj | 4 - src/Umbraco.Web.UI.Client/package-lock.json | 64 ++++---- src/umbraco.sln | 7 - 34 files changed, 163 insertions(+), 447 deletions(-) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/BuilderBase.cs (69%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/ChildBuilderBase.cs (89%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/ConfigurationEditorBuilder.cs (95%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/DataEditorBuilder.cs (98%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/DataTypeBuilder.cs (98%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/DataValueEditorBuilder.cs (97%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/DictionaryItemBuilder.cs (97%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/DictionaryTranslationBuilder.cs (96%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/Extensions/BuilderExtensions.cs (92%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/GlobalSettingsBuilder.cs (86%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/Interfaces/IWithAliasBuilder.cs (62%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/Interfaces/IWithCreateDateBuilder.cs (69%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/Interfaces/IWithCultureInfoBuilder.cs (73%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/Interfaces/IWithDeleteDateBuilder.cs (69%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/Interfaces/IWithIdBuilder.cs (61%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/Interfaces/IWithKeyBuilder.cs (66%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/Interfaces/IWithNameBuilder.cs (61%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/Interfaces/IWithUpdateDateBuilder.cs (69%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/LanguageBuilder.cs (97%) rename src/{Umbraco.Tests.Shared => Umbraco.Tests.Common}/Builders/RelationTypeBuilder.cs (97%) create mode 100644 src/Umbraco.Tests.Common/Builders/SmtpSettingsBuilder.cs delete mode 100644 src/Umbraco.Tests/Models/DataTypeTests.cs delete mode 100644 src/Umbraco.Tests/Models/DictionaryItemTests.cs delete mode 100644 src/Umbraco.Tests/Models/LanguageTests.cs delete mode 100644 src/Umbraco.Tests/Models/RelationTypeTests.cs diff --git a/src/Umbraco.Tests.Shared/Builders/BuilderBase.cs b/src/Umbraco.Tests.Common/Builders/BuilderBase.cs similarity index 69% rename from src/Umbraco.Tests.Shared/Builders/BuilderBase.cs rename to src/Umbraco.Tests.Common/Builders/BuilderBase.cs index d026999351..d8fc048d1b 100644 --- a/src/Umbraco.Tests.Shared/Builders/BuilderBase.cs +++ b/src/Umbraco.Tests.Common/Builders/BuilderBase.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Common.Builders { public abstract class BuilderBase { diff --git a/src/Umbraco.Tests.Shared/Builders/ChildBuilderBase.cs b/src/Umbraco.Tests.Common/Builders/ChildBuilderBase.cs similarity index 89% rename from src/Umbraco.Tests.Shared/Builders/ChildBuilderBase.cs rename to src/Umbraco.Tests.Common/Builders/ChildBuilderBase.cs index 742b86d16e..e1436ac1fe 100644 --- a/src/Umbraco.Tests.Shared/Builders/ChildBuilderBase.cs +++ b/src/Umbraco.Tests.Common/Builders/ChildBuilderBase.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Common.Builders { public abstract class ChildBuilderBase : BuilderBase { diff --git a/src/Umbraco.Tests.Shared/Builders/ConfigurationEditorBuilder.cs b/src/Umbraco.Tests.Common/Builders/ConfigurationEditorBuilder.cs similarity index 95% rename from src/Umbraco.Tests.Shared/Builders/ConfigurationEditorBuilder.cs rename to src/Umbraco.Tests.Common/Builders/ConfigurationEditorBuilder.cs index 3abf683bf2..7789090d16 100644 --- a/src/Umbraco.Tests.Shared/Builders/ConfigurationEditorBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/ConfigurationEditorBuilder.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using Umbraco.Core.PropertyEditors; -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Common.Builders { public class ConfigurationEditorBuilder : ChildBuilderBase { diff --git a/src/Umbraco.Tests.Shared/Builders/DataEditorBuilder.cs b/src/Umbraco.Tests.Common/Builders/DataEditorBuilder.cs similarity index 98% rename from src/Umbraco.Tests.Shared/Builders/DataEditorBuilder.cs rename to src/Umbraco.Tests.Common/Builders/DataEditorBuilder.cs index 0a9e94a74e..b3c3ff1b7e 100644 --- a/src/Umbraco.Tests.Shared/Builders/DataEditorBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/DataEditorBuilder.cs @@ -5,7 +5,7 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Core.Strings; -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Common.Builders { public class DataEditorBuilder : ChildBuilderBase { diff --git a/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs b/src/Umbraco.Tests.Common/Builders/DataTypeBuilder.cs similarity index 98% rename from src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs rename to src/Umbraco.Tests.Common/Builders/DataTypeBuilder.cs index 62e9e35ee0..20dc1bab81 100644 --- a/src/Umbraco.Tests.Shared/Builders/DataTypeBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/DataTypeBuilder.cs @@ -1,8 +1,8 @@ using System; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders.Interfaces; +using Umbraco.Tests.Common.Builders.Interfaces; -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Common.Builders { public class DataTypeBuilder : BuilderBase, diff --git a/src/Umbraco.Tests.Shared/Builders/DataValueEditorBuilder.cs b/src/Umbraco.Tests.Common/Builders/DataValueEditorBuilder.cs similarity index 97% rename from src/Umbraco.Tests.Shared/Builders/DataValueEditorBuilder.cs rename to src/Umbraco.Tests.Common/Builders/DataValueEditorBuilder.cs index be26510934..3d0b518ee7 100644 --- a/src/Umbraco.Tests.Shared/Builders/DataValueEditorBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/DataValueEditorBuilder.cs @@ -4,7 +4,7 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Core.Strings; -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Common.Builders { public class DataValueEditorBuilder : ChildBuilderBase { diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs b/src/Umbraco.Tests.Common/Builders/DictionaryItemBuilder.cs similarity index 97% rename from src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs rename to src/Umbraco.Tests.Common/Builders/DictionaryItemBuilder.cs index 6baff80972..206bccba80 100644 --- a/src/Umbraco.Tests.Shared/Builders/DictionaryItemBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/DictionaryItemBuilder.cs @@ -2,9 +2,9 @@ using System; using System.Collections.Generic; using System.Linq; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders.Interfaces; +using Umbraco.Tests.Common.Builders.Interfaces; -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Common.Builders { public class DictionaryItemBuilder : BuilderBase, diff --git a/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs b/src/Umbraco.Tests.Common/Builders/DictionaryTranslationBuilder.cs similarity index 96% rename from src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs rename to src/Umbraco.Tests.Common/Builders/DictionaryTranslationBuilder.cs index bd596383d1..37fb7c5b07 100644 --- a/src/Umbraco.Tests.Shared/Builders/DictionaryTranslationBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/DictionaryTranslationBuilder.cs @@ -1,8 +1,8 @@ using System; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders.Interfaces; +using Umbraco.Tests.Common.Builders.Interfaces; -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Common.Builders { public class DictionaryTranslationBuilder : ChildBuilderBase, diff --git a/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs b/src/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs similarity index 92% rename from src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs rename to src/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs index 702bb19bb2..c8f3f80bf1 100644 --- a/src/Umbraco.Tests.Shared/Builders/Extensions/BuilderExtensions.cs +++ b/src/Umbraco.Tests.Common/Builders/Extensions/BuilderExtensions.cs @@ -1,7 +1,7 @@ using System; -using Umbraco.Tests.Shared.Builders.Interfaces; +using Umbraco.Tests.Common.Builders.Interfaces; -namespace Umbraco.Tests.Shared.Builders.Extensions +namespace Umbraco.Tests.Common.Builders.Extensions { public static class BuilderExtensions { diff --git a/src/Umbraco.Tests.Shared/Builders/GlobalSettingsBuilder.cs b/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs similarity index 86% rename from src/Umbraco.Tests.Shared/Builders/GlobalSettingsBuilder.cs rename to src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs index b3c8e90fa5..56e242146c 100644 --- a/src/Umbraco.Tests.Shared/Builders/GlobalSettingsBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs @@ -1,6 +1,6 @@ using Umbraco.Core.Configuration; -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Common.Builders { public class GlobalSettingsBuilder : GlobalSettingsBuilder { @@ -10,7 +10,6 @@ namespace Umbraco.Tests.Shared.Builders } public class GlobalSettingsBuilder : ChildBuilderBase - { private string _configurationStatus; private string _databaseFactoryServerVersion; @@ -29,14 +28,20 @@ namespace Umbraco.Tests.Shared.Builders private string _umbracoMediaPath; private string _umbracoPath; private string _umbracoScriptsPath; + private string _mainDomLock; + private string _noNodesViewPath; private bool? _useHttps; private int? _versionCheckPeriod; + private readonly SmtpSettingsBuilder> _smtpSettingsBuilder; public GlobalSettingsBuilder(TParent parentBuilder) : base(parentBuilder) { + _smtpSettingsBuilder = new SmtpSettingsBuilder>(this); } + public SmtpSettingsBuilder> AddSmtpSettings() => _smtpSettingsBuilder; + public GlobalSettingsBuilder WithConfigurationStatus(string configurationStatus) { _configurationStatus = configurationStatus; @@ -139,6 +144,17 @@ namespace Umbraco.Tests.Shared.Builders return this; } + public GlobalSettingsBuilder WithMainDomLock(string mainDomLock) + { + _mainDomLock = mainDomLock; + return this; + } + + public GlobalSettingsBuilder WithNoNodesViewPath(string noNodesViewPath) + { + _noNodesViewPath = noNodesViewPath; + return this; + } public GlobalSettingsBuilder WithVersionCheckPeriod(int versionCheckPeriod) { _versionCheckPeriod = versionCheckPeriod; @@ -172,6 +188,9 @@ namespace Umbraco.Tests.Shared.Builders var umbracoScriptsPath = _umbracoScriptsPath ?? "~/scripts"; var versionCheckPeriod = _versionCheckPeriod ?? 0; var timeOutInMinutes = _timeOutInMinutes ?? 20; + var smtpSettings = _smtpSettingsBuilder.Build(); + var mainDomLock = _mainDomLock ?? string.Empty; + var noNodesViewPath = _noNodesViewPath ?? "~/config/splashes/NoNodes.cshtml"; return new TestGlobalSettings @@ -194,7 +213,10 @@ namespace Umbraco.Tests.Shared.Builders UmbracoMediaPath = umbracoMediaPath, UmbracoScriptsPath = umbracoScriptsPath, VersionCheckPeriod = versionCheckPeriod, - TimeOutInMinutes = timeOutInMinutes + TimeOutInMinutes = timeOutInMinutes, + SmtpSettings = smtpSettings, + MainDomLock = mainDomLock, + NoNodesViewPath = noNodesViewPath, }; } @@ -214,11 +236,14 @@ namespace Umbraco.Tests.Shared.Builders public string UmbracoScriptsPath { get; set; } public string UmbracoMediaPath { get; set; } public bool IsSmtpServerConfigured { get; set; } + public ISmtpSettings SmtpSettings { get; set; } public bool InstallMissingDatabase { get; set; } public bool InstallEmptyDatabase { get; set; } public bool DisableElectionForSingleServer { get; set; } public string RegisterType { get; set; } public string DatabaseFactoryServerVersion { get; set; } + public string MainDomLock { get; set; } + public string NoNodesViewPath { get; set; } } } } diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithAliasBuilder.cs b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithAliasBuilder.cs similarity index 62% rename from src/Umbraco.Tests.Shared/Builders/Interfaces/IWithAliasBuilder.cs rename to src/Umbraco.Tests.Common/Builders/Interfaces/IWithAliasBuilder.cs index 3ab70123f4..78bbbddec9 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithAliasBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithAliasBuilder.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Tests.Shared.Builders.Interfaces +namespace Umbraco.Tests.Common.Builders.Interfaces { public interface IWithAliasBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCreateDateBuilder.cs b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithCreateDateBuilder.cs similarity index 69% rename from src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCreateDateBuilder.cs rename to src/Umbraco.Tests.Common/Builders/Interfaces/IWithCreateDateBuilder.cs index 7a7b69fc95..47acaa9a52 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCreateDateBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithCreateDateBuilder.cs @@ -1,6 +1,6 @@ using System; -namespace Umbraco.Tests.Shared.Builders.Interfaces +namespace Umbraco.Tests.Common.Builders.Interfaces { public interface IWithCreateDateBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCultureInfoBuilder.cs b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithCultureInfoBuilder.cs similarity index 73% rename from src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCultureInfoBuilder.cs rename to src/Umbraco.Tests.Common/Builders/Interfaces/IWithCultureInfoBuilder.cs index ee33d4549d..a60fe3c23c 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithCultureInfoBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithCultureInfoBuilder.cs @@ -1,6 +1,6 @@ using System.Globalization; -namespace Umbraco.Tests.Shared.Builders.Interfaces +namespace Umbraco.Tests.Common.Builders.Interfaces { public interface IWithCultureInfoBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithDeleteDateBuilder.cs b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithDeleteDateBuilder.cs similarity index 69% rename from src/Umbraco.Tests.Shared/Builders/Interfaces/IWithDeleteDateBuilder.cs rename to src/Umbraco.Tests.Common/Builders/Interfaces/IWithDeleteDateBuilder.cs index 3ae8ddfeed..0fdeb6d69d 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithDeleteDateBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithDeleteDateBuilder.cs @@ -1,6 +1,6 @@ using System; -namespace Umbraco.Tests.Shared.Builders.Interfaces +namespace Umbraco.Tests.Common.Builders.Interfaces { public interface IWithDeleteDateBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithIdBuilder.cs b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithIdBuilder.cs similarity index 61% rename from src/Umbraco.Tests.Shared/Builders/Interfaces/IWithIdBuilder.cs rename to src/Umbraco.Tests.Common/Builders/Interfaces/IWithIdBuilder.cs index a5a6175d8f..c13343df15 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithIdBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithIdBuilder.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Tests.Shared.Builders.Interfaces +namespace Umbraco.Tests.Common.Builders.Interfaces { public interface IWithIdBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithKeyBuilder.cs b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithKeyBuilder.cs similarity index 66% rename from src/Umbraco.Tests.Shared/Builders/Interfaces/IWithKeyBuilder.cs rename to src/Umbraco.Tests.Common/Builders/Interfaces/IWithKeyBuilder.cs index 78da4dbc0b..a71bd2d114 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithKeyBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithKeyBuilder.cs @@ -1,6 +1,6 @@ using System; -namespace Umbraco.Tests.Shared.Builders.Interfaces +namespace Umbraco.Tests.Common.Builders.Interfaces { public interface IWithKeyBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithNameBuilder.cs b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithNameBuilder.cs similarity index 61% rename from src/Umbraco.Tests.Shared/Builders/Interfaces/IWithNameBuilder.cs rename to src/Umbraco.Tests.Common/Builders/Interfaces/IWithNameBuilder.cs index 2ddcf65333..d2ccb8dbbc 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithNameBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithNameBuilder.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Tests.Shared.Builders.Interfaces +namespace Umbraco.Tests.Common.Builders.Interfaces { public interface IWithNameBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithUpdateDateBuilder.cs b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithUpdateDateBuilder.cs similarity index 69% rename from src/Umbraco.Tests.Shared/Builders/Interfaces/IWithUpdateDateBuilder.cs rename to src/Umbraco.Tests.Common/Builders/Interfaces/IWithUpdateDateBuilder.cs index 88a23d0275..80a5aa4f61 100644 --- a/src/Umbraco.Tests.Shared/Builders/Interfaces/IWithUpdateDateBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/Interfaces/IWithUpdateDateBuilder.cs @@ -1,6 +1,6 @@ using System; -namespace Umbraco.Tests.Shared.Builders.Interfaces +namespace Umbraco.Tests.Common.Builders.Interfaces { public interface IWithUpdateDateBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs b/src/Umbraco.Tests.Common/Builders/LanguageBuilder.cs similarity index 97% rename from src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs rename to src/Umbraco.Tests.Common/Builders/LanguageBuilder.cs index 59e859dd3a..ae60920c9c 100644 --- a/src/Umbraco.Tests.Shared/Builders/LanguageBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/LanguageBuilder.cs @@ -3,9 +3,9 @@ using System.Globalization; using Moq; using Umbraco.Core.Configuration; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders.Interfaces; +using Umbraco.Tests.Common.Builders.Interfaces; -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Common.Builders { public class LanguageBuilder : LanguageBuilder { diff --git a/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs b/src/Umbraco.Tests.Common/Builders/RelationTypeBuilder.cs similarity index 97% rename from src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs rename to src/Umbraco.Tests.Common/Builders/RelationTypeBuilder.cs index 2cb81688b7..4ad39c6641 100644 --- a/src/Umbraco.Tests.Shared/Builders/RelationTypeBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/RelationTypeBuilder.cs @@ -1,8 +1,8 @@ using System; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders.Interfaces; +using Umbraco.Tests.Common.Builders.Interfaces; -namespace Umbraco.Tests.Shared.Builders +namespace Umbraco.Tests.Common.Builders { public class RelationTypeBuilder : RelationTypeBuilder { diff --git a/src/Umbraco.Tests.Common/Builders/SmtpSettingsBuilder.cs b/src/Umbraco.Tests.Common/Builders/SmtpSettingsBuilder.cs new file mode 100644 index 0000000000..3120cc95f6 --- /dev/null +++ b/src/Umbraco.Tests.Common/Builders/SmtpSettingsBuilder.cs @@ -0,0 +1,73 @@ +using Umbraco.Core.Configuration; + +namespace Umbraco.Tests.Common.Builders +{ + public class SmtpSettingsBuilder : SmtpSettingsBuilder + { + public SmtpSettingsBuilder() : base(null) + { + } + } + + public class SmtpSettingsBuilder + : ChildBuilderBase + { + private string _from; + private string _host; + private int? _port; + private string _pickupDirectoryLocation; + + public SmtpSettingsBuilder(TParent parentBuilder) : base(parentBuilder) + { + } + + public SmtpSettingsBuilder WithFrom(string from) + { + _from = from; + return this; + } + + public SmtpSettingsBuilder WithHost(string host) + { + _host = host; + return this; + } + + public SmtpSettingsBuilder WithPost(int port) + { + _port = port; + return this; + } + + public SmtpSettingsBuilder WithPickupDirectoryLocation(string pickupDirectoryLocation) + { + _pickupDirectoryLocation = pickupDirectoryLocation; + return this; + } + + + public override ISmtpSettings Build() + { + var from = _from ?? null; + var host = _host ?? null; + var port = _port ?? 25; + var pickupDirectoryLocation = _pickupDirectoryLocation ?? null; + + return new TestSmtpSettings() + { + From = from, + Host = host, + Port = port, + PickupDirectoryLocation = pickupDirectoryLocation, + }; + } + + private class TestSmtpSettings : ISmtpSettings + { + public string From { get; set; } + public string Host { get; set; } + public int Port { get; set; } + public string PickupDirectoryLocation { get; set; } + } + } +} diff --git a/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj b/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj index d18779a4fd..43cd79bd6e 100644 --- a/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj +++ b/src/Umbraco.Tests.Shared/Umbraco.Tests.Shared.csproj @@ -27,8 +27,4 @@ - - - - diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs index ce984b3a79..a097661a93 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DataTypeTests.cs @@ -1,8 +1,9 @@ using Newtonsoft.Json; using NUnit.Framework; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders; -using Umbraco.Tests.Shared.Builders.Extensions; +using Umbraco.Tests.Common.Builders; +using Umbraco.Tests.Common.Builders.Extensions; + namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs index 85c0e56089..28878a2463 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/DictionaryItemTests.cs @@ -2,7 +2,7 @@ using System.Linq; using Newtonsoft.Json; using NUnit.Framework; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/LanguageTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/LanguageTests.cs index 6d80eac16f..bb82e69fa6 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/LanguageTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/LanguageTests.cs @@ -1,8 +1,7 @@ using Newtonsoft.Json; using NUnit.Framework; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders; -using Umbraco.Tests.Shared.Builders.Extensions; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs index 140b974b61..29ad8251cc 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Models/RelationTypeTests.cs @@ -2,7 +2,7 @@ using Newtonsoft.Json; using NUnit.Framework; using Umbraco.Core.Models; -using Umbraco.Tests.Shared.Builders; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.UnitTests.Umbraco.Infrastructure.Models { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj index 8dad14e747..37ad3cae82 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj @@ -1,7 +1,9 @@  - netcoreapp2.1 + Exe + netcoreapp3.1 + false @@ -18,17 +20,14 @@ + - + - - - - - + diff --git a/src/Umbraco.Tests/Models/DataTypeTests.cs b/src/Umbraco.Tests/Models/DataTypeTests.cs deleted file mode 100644 index fe8a26e431..0000000000 --- a/src/Umbraco.Tests/Models/DataTypeTests.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Diagnostics; -using Moq; -using Newtonsoft.Json; -using NUnit.Framework; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Core.PropertyEditors; -using Umbraco.Core.Serialization; -using Umbraco.Core.Services; -using Umbraco.Core.Strings; - -namespace Umbraco.Tests.Models -{ - [TestFixture] - public class DataTypeTests - { - [Test] - public void Can_Deep_Clone() - { - var dtd = new DataType(new VoidEditor(Mock.Of(), Mock.Of(), Mock.Of(),Mock.Of(), Mock.Of()), 9) - { - CreateDate = DateTime.Now, - CreatorId = 5, - DatabaseType = ValueStorageType.Nvarchar, - Id = 4, - Key = Guid.NewGuid(), - Level = 7, - Name = "Test", - ParentId = 9, - Path = "-1,2", - SortOrder = 8, - Trashed = true, - UpdateDate = DateTime.Now - }; - var clone = (DataType) dtd.DeepClone(); - - Assert.AreNotSame(clone, dtd); - Assert.AreEqual(clone, dtd); - Assert.AreEqual(clone.CreateDate, dtd.CreateDate); - Assert.AreEqual(clone.CreatorId, dtd.CreatorId); - Assert.AreEqual(clone.DatabaseType, dtd.DatabaseType); - Assert.AreEqual(clone.Id, dtd.Id); - Assert.AreEqual(clone.Key, dtd.Key); - Assert.AreEqual(clone.Level, dtd.Level); - Assert.AreEqual(clone.Name, dtd.Name); - Assert.AreEqual(clone.ParentId, dtd.ParentId); - Assert.AreEqual(clone.Path, dtd.Path); - Assert.AreEqual(clone.SortOrder, dtd.SortOrder); - Assert.AreEqual(clone.Trashed, dtd.Trashed); - Assert.AreEqual(clone.UpdateDate, dtd.UpdateDate); - - //This double verifies by reflection - var allProps = clone.GetType().GetProperties(); - foreach (var propertyInfo in allProps) - { - Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(dtd, null)); - } - } - - [Test] - public void Can_Serialize_Without_Error() - { - var dtd = new DataType(new VoidEditor(Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(),Mock.Of()), 9) - { - CreateDate = DateTime.Now, - CreatorId = 5, - DatabaseType = ValueStorageType.Nvarchar, - Id = 4, - Key = Guid.NewGuid(), - Level = 7, - Name = "Test", - ParentId = 9, - Path = "-1,2", - SortOrder = 8, - Trashed = true, - UpdateDate = DateTime.Now - }; - - var json = JsonConvert.SerializeObject(dtd); - Debug.Print(json); - } - - } -} diff --git a/src/Umbraco.Tests/Models/DictionaryItemTests.cs b/src/Umbraco.Tests/Models/DictionaryItemTests.cs deleted file mode 100644 index 835cfd96f1..0000000000 --- a/src/Umbraco.Tests/Models/DictionaryItemTests.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Diagnostics; -using System.Linq; -using Newtonsoft.Json; -using NUnit.Framework; -using Umbraco.Core.Models; -using Umbraco.Core.Serialization; -using Umbraco.Tests.TestHelpers; - -namespace Umbraco.Tests.Models -{ - [TestFixture] - public class DictionaryItemTests - { - [Test] - public void Can_Deep_Clone() - { - var item = new DictionaryItem("blah") - { - CreateDate = DateTime.Now, - Id = 8, - ItemKey = "blah", - Key = Guid.NewGuid(), - ParentId = Guid.NewGuid(), - UpdateDate = DateTime.Now, - Translations = new[] - { - new DictionaryTranslation(new Language(SettingsForTests.GenerateMockGlobalSettings(),"en-AU") - { - CreateDate = DateTime.Now, - CultureName = "en", - Id = 11, - IsoCode = "AU", - Key = Guid.NewGuid(), - UpdateDate = DateTime.Now - }, "colour") - { - CreateDate = DateTime.Now, - Id = 88, - Key = Guid.NewGuid(), - UpdateDate = DateTime.Now - }, - new DictionaryTranslation(new Language(SettingsForTests.GenerateMockGlobalSettings(),"en-US") - { - CreateDate = DateTime.Now, - CultureName = "en", - Id = 12, - IsoCode = "US", - Key = Guid.NewGuid(), - UpdateDate = DateTime.Now - }, "color") - { - CreateDate = DateTime.Now, - Id = 89, - Key = Guid.NewGuid(), - UpdateDate = DateTime.Now - }, - } - }; - - var clone = (DictionaryItem)item.DeepClone(); - - Assert.AreNotSame(clone, item); - Assert.AreEqual(clone, item); - Assert.AreEqual(clone.CreateDate, item.CreateDate); - Assert.AreEqual(clone.Id, item.Id); - Assert.AreEqual(clone.ItemKey, item.ItemKey); - Assert.AreEqual(clone.Key, item.Key); - Assert.AreEqual(clone.ParentId, item.ParentId); - Assert.AreEqual(clone.UpdateDate, item.UpdateDate); - Assert.AreEqual(clone.Translations.Count(), item.Translations.Count()); - for (var i = 0; i < item.Translations.Count(); i++) - { - Assert.AreNotSame(clone.Translations.ElementAt(i), item.Translations.ElementAt(i)); - Assert.AreEqual(clone.Translations.ElementAt(i), item.Translations.ElementAt(i)); - } - - //This double verifies by reflection - var allProps = clone.GetType().GetProperties(); - foreach (var propertyInfo in allProps) - { - Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null)); - } - } - - [Test] - public void Can_Serialize_Without_Error() - { - var item = new DictionaryItem("blah") - { - CreateDate = DateTime.Now, - Id = 8, - ItemKey = "blah", - Key = Guid.NewGuid(), - ParentId = Guid.NewGuid(), - UpdateDate = DateTime.Now, - Translations = new[] - { - new DictionaryTranslation(new Language(SettingsForTests.GenerateMockGlobalSettings(),"en-AU") - { - CreateDate = DateTime.Now, - CultureName = "en", - Id = 11, - IsoCode = "AU", - Key = Guid.NewGuid(), - UpdateDate = DateTime.Now - }, "colour") - { - CreateDate = DateTime.Now, - Id = 88, - Key = Guid.NewGuid(), - UpdateDate = DateTime.Now - }, - new DictionaryTranslation(new Language(SettingsForTests.GenerateMockGlobalSettings(),"en-US") - { - CreateDate = DateTime.Now, - CultureName = "en", - Id = 12, - IsoCode = "US", - Key = Guid.NewGuid(), - UpdateDate = DateTime.Now - }, "color") - { - CreateDate = DateTime.Now, - Id = 89, - Key = Guid.NewGuid(), - UpdateDate = DateTime.Now - }, - } - }; - - - var json = JsonConvert.SerializeObject(item); - Debug.Print(json); - } - } -} diff --git a/src/Umbraco.Tests/Models/LanguageTests.cs b/src/Umbraco.Tests/Models/LanguageTests.cs deleted file mode 100644 index 36986d68ae..0000000000 --- a/src/Umbraco.Tests/Models/LanguageTests.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Diagnostics; -using Newtonsoft.Json; -using NUnit.Framework; -using Umbraco.Core.Configuration; -using Umbraco.Core.Models; -using Umbraco.Core.Serialization; -using Umbraco.Core.Strings; -using Umbraco.Tests.TestHelpers; - -namespace Umbraco.Tests.Models -{ - [TestFixture] - public class LanguageTests - { - private IGlobalSettings GlobalSettings { get; } = SettingsForTests.GenerateMockGlobalSettings(); - - [Test] - public void Can_Deep_Clone() - { - var item = new Language(GlobalSettings, "en-AU") - { - CreateDate = DateTime.Now, - CultureName = "AU", - Id = 11, - IsoCode = "en", - Key = Guid.NewGuid(), - UpdateDate = DateTime.Now - }; - - var clone = (Language) item.DeepClone(); - Assert.AreNotSame(clone, item); - Assert.AreEqual(clone, item); - Assert.AreEqual(clone.CreateDate, item.CreateDate); - Assert.AreEqual(clone.CultureName, item.CultureName); - Assert.AreEqual(clone.Id, item.Id); - Assert.AreEqual(clone.IsoCode, item.IsoCode); - Assert.AreEqual(clone.Key, item.Key); - Assert.AreEqual(clone.UpdateDate, item.UpdateDate); - - //This double verifies by reflection - var allProps = clone.GetType().GetProperties(); - foreach (var propertyInfo in allProps) - { - Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null)); - } - } - - [Test] - public void Can_Serialize_Without_Error() - { - var item = new Language(GlobalSettings, "en-AU") - { - CreateDate = DateTime.Now, - CultureName = "AU", - Id = 11, - IsoCode = "en", - Key = Guid.NewGuid(), - UpdateDate = DateTime.Now - }; - - var json = JsonConvert.SerializeObject(item); - Debug.Print(json); - } - } -} diff --git a/src/Umbraco.Tests/Models/RelationTypeTests.cs b/src/Umbraco.Tests/Models/RelationTypeTests.cs deleted file mode 100644 index bc5572d563..0000000000 --- a/src/Umbraco.Tests/Models/RelationTypeTests.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Diagnostics; -using Newtonsoft.Json; -using NUnit.Framework; -using Umbraco.Core.Models; -using Umbraco.Core.Serialization; - -namespace Umbraco.Tests.Models -{ - [TestFixture] - public class RelationTypeTests - { - [Test] - public void Can_Deep_Clone() - { - var item = new RelationType("test", "test", false, Guid.NewGuid(), Guid.NewGuid()) - { - Id = 66, - CreateDate = DateTime.Now, - IsBidirectional = true, - Key = Guid.NewGuid(), - Name = "Test", - UpdateDate = DateTime.Now - }; - - var clone = (RelationType)item.DeepClone(); - - Assert.AreNotSame(clone, item); - Assert.AreEqual(clone, item); - Assert.AreEqual(clone.Alias, item.Alias); - Assert.AreEqual(clone.ChildObjectType, item.ChildObjectType); - Assert.AreEqual(clone.IsBidirectional, item.IsBidirectional); - Assert.AreEqual(clone.Id, item.Id); - Assert.AreEqual(clone.Key, item.Key); - Assert.AreEqual(clone.Name, item.Name); - Assert.AreNotSame(clone.ParentObjectType, item.ParentObjectType); - Assert.AreEqual(clone.UpdateDate, item.UpdateDate); - - //This double verifies by reflection - var allProps = clone.GetType().GetProperties(); - foreach (var propertyInfo in allProps) - { - Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null)); - } - } - - [Test] - public void Can_Serialize_Without_Error() - { - var item = new RelationType("test", "test", false, Guid.NewGuid(), Guid.NewGuid()) - { - Id = 66, - CreateDate = DateTime.Now, - IsBidirectional = true, - Key = Guid.NewGuid(), - Name = "Test", - UpdateDate = DateTime.Now - }; - - var json = JsonConvert.SerializeObject(item); - Debug.Print(json); - } - } -} diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 29d69db0d2..001fe7bd2f 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -297,17 +297,13 @@ - - - - diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 2566f56244..60e70ea170 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -3775,7 +3775,7 @@ "domelementtype": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "integrity": "sha1-H4vf6R9aeAYydOgDtL3O326U+U0=", "dev": true } } @@ -4233,7 +4233,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "optional": true } @@ -4287,13 +4287,13 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=", "dev": true }, "glob-parent": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "integrity": "sha1-X0wdHnSNMM1zrSlEs1d6gbCB6MI=", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -4321,19 +4321,19 @@ "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=", "dev": true }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", "dev": true }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "integrity": "sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4=", "dev": true, "requires": { "ansi-regex": "^4.1.0" @@ -4833,7 +4833,7 @@ "braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "integrity": "sha1-NFThpGLujVmeI23zNs2epPiv4Qc=", "dev": true, "requires": { "fill-range": "^7.0.1" @@ -4842,7 +4842,7 @@ "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "integrity": "sha1-GRmmp8df44ssfHflGYU12prN2kA=", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -4851,7 +4851,7 @@ "glob-parent": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "integrity": "sha1-X0wdHnSNMM1zrSlEs1d6gbCB6MI=", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -4869,13 +4869,13 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "integrity": "sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=", "dev": true }, "micromatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "integrity": "sha1-T8sJmb+fvC/L3SEvbWKbmlbDklk=", "dev": true, "requires": { "braces": "^3.0.1", @@ -4885,7 +4885,7 @@ "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "integrity": "sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=", "dev": true, "requires": { "is-number": "^7.0.0" @@ -5203,7 +5203,7 @@ "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", "dev": true, "requires": { "ms": "^2.1.1" @@ -5400,14 +5400,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5422,20 +5420,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -5552,8 +5547,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -5565,7 +5559,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5580,7 +5573,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5588,14 +5580,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5614,7 +5604,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -5695,8 +5684,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -5708,7 +5696,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -5830,7 +5817,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6193,7 +6179,7 @@ "ignore": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", - "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "integrity": "sha1-hLez2+ZFUrbvDsqZ9nQ9vsbZet8=", "dev": true }, "slash": { @@ -8863,7 +8849,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=", "dev": true } } @@ -13046,13 +13032,13 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true }, "supports-color": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "integrity": "sha1-B2Srxpxj1ayELdSGfo0CXogN+PM=", "dev": true, "requires": { "has-flag": "^3.0.0" diff --git a/src/umbraco.sln b/src/umbraco.sln index 180f05a41e..79fa3bb7d2 100644 --- a/src/umbraco.sln +++ b/src/umbraco.sln @@ -125,8 +125,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Tests.Common", "Umb EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Tests.UnitTests", "Umbraco.Tests.UnitTests\Umbraco.Tests.UnitTests.csproj", "{9102ABDF-E537-4E46-B525-C9ED4833EED0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Tests.Shared", "Umbraco.Tests.Shared\Umbraco.Tests.Shared.csproj", "{58F1DFC6-5096-4B99-B57B-984F2EEDFADE}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -171,10 +169,6 @@ Global {9102ABDF-E537-4E46-B525-C9ED4833EED0}.Debug|Any CPU.Build.0 = Debug|Any CPU {9102ABDF-E537-4E46-B525-C9ED4833EED0}.Release|Any CPU.ActiveCfg = Release|Any CPU {9102ABDF-E537-4E46-B525-C9ED4833EED0}.Release|Any CPU.Build.0 = Release|Any CPU - {58F1DFC6-5096-4B99-B57B-984F2EEDFADE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {58F1DFC6-5096-4B99-B57B-984F2EEDFADE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {58F1DFC6-5096-4B99-B57B-984F2EEDFADE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {58F1DFC6-5096-4B99-B57B-984F2EEDFADE}.Release|Any CPU.Build.0 = Release|Any CPU {33085570-9BF2-4065-A9B0-A29D920D13BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {33085570-9BF2-4065-A9B0-A29D920D13BA}.Debug|Any CPU.Build.0 = Debug|Any CPU {33085570-9BF2-4065-A9B0-A29D920D13BA}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -220,7 +214,6 @@ Global {3A33ADC9-C6C0-4DB1-A613-A9AF0210DF3D} = {B5BD12C1-A454-435E-8A46-FF4A364C0382} {C7311C00-2184-409B-B506-52A5FAEA8736} = {FD962632-184C-4005-A5F3-E705D92FC645} {9102ABDF-E537-4E46-B525-C9ED4833EED0} = {B5BD12C1-A454-435E-8A46-FF4A364C0382} - {58F1DFC6-5096-4B99-B57B-984F2EEDFADE} = {B5BD12C1-A454-435E-8A46-FF4A364C0382} {FB5676ED-7A69-492C-B802-E7B24144C0FC} = {B5BD12C1-A454-435E-8A46-FF4A364C0382} {A499779C-1B3B-48A8-B551-458E582E6E96} = {B5BD12C1-A454-435E-8A46-FF4A364C0382} EndGlobalSection From 8986783cbc4a78cad9a3cbd1abe6a31c38252027 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 23 Mar 2020 14:31:21 +0100 Subject: [PATCH 12/28] Parse connection string provider --- .../Models/ConnectionStrings.cs | 43 +++++++++++++++++-- .../Models/ConnectionStringsTests.cs | 39 +++++++++++++++++ 2 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 src/Umbraco.Tests.UnitTests/Umbraco.Configuration/Models/ConnectionStringsTests.cs diff --git a/src/Umbraco.Configuration/Models/ConnectionStrings.cs b/src/Umbraco.Configuration/Models/ConnectionStrings.cs index 9fc546a88f..22a0bde571 100644 --- a/src/Umbraco.Configuration/Models/ConnectionStrings.cs +++ b/src/Umbraco.Configuration/Models/ConnectionStrings.cs @@ -1,12 +1,12 @@ using System; -using System.Linq; -using System.Text.Json.Serialization; +using System.Data.Common; using Microsoft.Extensions.Configuration; +using Umbraco.Core; using Umbraco.Core.Configuration; namespace Umbraco.Configuration.Models { - internal class ConnectionStrings : IConnectionStrings + public class ConnectionStrings : IConnectionStrings { private readonly IConfiguration _configuration; @@ -17,8 +17,43 @@ namespace Umbraco.Configuration.Models public ConfigConnectionString this[string key] { - get => new ConfigConnectionString(_configuration.GetConnectionString(key), "System.Data.SqlClient", key); + get + { + var connectionString = _configuration.GetConnectionString(key); + var provider = ParseProvider(connectionString); + return new ConfigConnectionString(connectionString, provider, key); + } set => throw new NotImplementedException(); } + + private string ParseProvider(string connectionString) + { + if (string.IsNullOrEmpty(connectionString)) + { + return null; + } + + var builder = new DbConnectionStringBuilder(); + + builder.ConnectionString = connectionString; + + if (builder.TryGetValue("Data Source", out var ds) && ds is string dataSource) + { + if (dataSource.EndsWith(".sdf")) + { + return Constants.DbProviderNames.SqlCe; + } + } + + if (builder.TryGetValue("Server", out var s) && s is string server && builder.TryGetValue("Database", out var db) && db is string database) + { + if (!string.IsNullOrEmpty(server) && !string.IsNullOrEmpty(database)) + { + return Constants.DbProviderNames.SqlServer; + } + } + + throw new ArgumentException("Cannot determine provider name from connection string", nameof(connectionString)); + } } } diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Configuration/Models/ConnectionStringsTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Configuration/Models/ConnectionStringsTests.cs new file mode 100644 index 0000000000..c5acba362b --- /dev/null +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Configuration/Models/ConnectionStringsTests.cs @@ -0,0 +1,39 @@ +using Microsoft.Extensions.Configuration; +using Moq; +using NUnit.Framework; +using Umbraco.Configuration.Models; +using Umbraco.Core; + +namespace Umbraco.Tests.UnitTests.Umbraco.Configuration.Models +{ + public class ConnectionStringsTests + { + [Test] + [TestCase("", ExpectedResult = null)] + [TestCase(null, ExpectedResult = null)] + [TestCase(@"Data Source=|DataDirectory|\Umbraco.sdf;Flush Interval=1;", ExpectedResult = Constants.DbProviderNames.SqlCe)] + [TestCase(@"Server=(LocalDb)\Umbraco;Database=NetCore;Integrated Security=true", ExpectedResult = Constants.DbProviderNames.SqlServer)] + public string ParseProviderName(string connectionString) + { + var key = Constants.System.UmbracoConnectionName; + var configuration = new Mock(); + + + //This is the underlying method that is called by Configuration.GetConnectionString(string) + if (connectionString != null) + { + configuration.Setup(x => x.GetSection("ConnectionStrings")[key]).Returns(connectionString); + } + + + var connectionStrings = new ConnectionStrings(configuration.Object); + + var actual = connectionStrings[key]; + + Assert.AreEqual(connectionString, actual.ConnectionString); + Assert.AreEqual(key, actual.Name); + + return connectionStrings[key].ProviderName; + } + } +} From 919d418920e0aabfbafe23a1baa70279dcb8198f Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 24 Mar 2020 11:53:56 +1100 Subject: [PATCH 13/28] Gets the DB installing in integration tests, changes integratino tests to use Generic Host builder --- src/Umbraco.Core/Composing/Composition.cs | 14 +- .../Composing/HostBuilderExtensions.cs | 7 +- .../Migrations/Install/DatabaseBuilder.cs | 2 +- .../Runtime/CoreInitialComposer.cs | 2 + .../Runtime/CoreRuntime.cs | 5 + .../Implementations/DelegateHostedService.cs | 38 +++++ .../Implementations/HostBuilderExtensions.cs | 55 +++++++ .../TestDbProviderFactoryCreator.cs | 34 ----- .../Implementations/TestHelper.cs | 3 +- .../Implementations/TestLifetime.cs | 18 +++ src/Umbraco.Tests.Integration/RuntimeTests.cs | 138 ++++++++++++++---- .../Testing/TestLocalDb.cs | 49 +++++++ .../Umbraco.Tests.Integration.csproj | 1 + ...coBackOfficeServiceCollectionExtensions.cs | 44 +++--- 14 files changed, 319 insertions(+), 91 deletions(-) create mode 100644 src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs create mode 100644 src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs delete mode 100644 src/Umbraco.Tests.Integration/Implementations/TestDbProviderFactoryCreator.cs create mode 100644 src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs create mode 100644 src/Umbraco.Tests.Integration/Testing/TestLocalDb.cs diff --git a/src/Umbraco.Core/Composing/Composition.cs b/src/Umbraco.Core/Composing/Composition.cs index 9a696c2dc0..05c7554eab 100644 --- a/src/Umbraco.Core/Composing/Composition.cs +++ b/src/Umbraco.Core/Composing/Composition.cs @@ -33,13 +33,13 @@ namespace Umbraco.Core.Composing /// An IOHelper public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, Configs configs, IIOHelper ioHelper, AppCaches appCaches) { - _register = register; - TypeLoader = typeLoader; - Logger = logger; - RuntimeState = runtimeState; - Configs = configs; - IOHelper = ioHelper; - AppCaches = appCaches; + _register = register ?? throw new ArgumentNullException(nameof(register)); + TypeLoader = typeLoader ?? throw new ArgumentNullException(nameof(typeLoader)); + Logger = logger ?? throw new ArgumentNullException(nameof(logger)); + RuntimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState)); + Configs = configs ?? throw new ArgumentNullException(nameof(configs)); + IOHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); + AppCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches)); } #region Services diff --git a/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs b/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs index d5355c136f..2099778185 100644 --- a/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs +++ b/src/Umbraco.Infrastructure/Composing/HostBuilderExtensions.cs @@ -13,8 +13,9 @@ namespace Umbraco.Core.Composing /// /// public static IHostBuilder UseUmbraco(this IHostBuilder builder) - { - return builder.UseServiceProviderFactory(new UmbracoServiceProviderFactory()); - } + => builder.UseUmbraco(new UmbracoServiceProviderFactory()); + + public static IHostBuilder UseUmbraco(this IHostBuilder builder, UmbracoServiceProviderFactory umbracoServiceProviderFactory) + => builder.UseServiceProviderFactory(umbracoServiceProviderFactory); } } diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs index 17192fd69b..8d5922028c 100644 --- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs +++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs @@ -46,7 +46,7 @@ namespace Umbraco.Core.Migrations.Install IIOHelper ioHelper, IUmbracoVersion umbracoVersion, IDbProviderFactoryCreator dbProviderFactoryCreator, - IConfigManipulator configManipulator) + IConfigManipulator configManipulator) { _scopeProvider = scopeProvider; _globalSettings = globalSettings; diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs index 9318b223df..67cfcded92 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs @@ -176,6 +176,8 @@ namespace Umbraco.Core.Runtime // Grid config is not a real config file as we know them composition.RegisterUnique(); + // Config manipulator + composition.RegisterUnique(); } } } diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs index 6c1a06ab6b..4a9441e535 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs @@ -115,6 +115,8 @@ namespace Umbraco.Core.Runtime /// public virtual IFactory Boot(IRegister register) { + if (register is null) throw new ArgumentNullException(nameof(register)); + // create and register the essential services // ie the bare minimum required to boot @@ -152,6 +154,9 @@ namespace Umbraco.Core.Runtime /// protected virtual IFactory Boot(IRegister register, DisposableTimer timer) { + if (register is null) throw new ArgumentNullException(nameof(register)); + if (timer is null) throw new ArgumentNullException(nameof(timer)); + Composition composition = null; try diff --git a/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs b/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs new file mode 100644 index 0000000000..9df7270350 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.Hosting; +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Umbraco.Tests.Integration +{ + /// + /// Executes arbitrary code on start/end + /// + public class DelegateHostedService : IHostedService + { + private readonly Action _start; + private readonly Action _end; + + public static DelegateHostedService Create(Action start, Action end) => new DelegateHostedService(start, end); + + private DelegateHostedService(Action start, Action end) + { + _start = start; + _end = end; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + _start(); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + _end?.Invoke(); + return Task.CompletedTask; + } + } + + +} diff --git a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs new file mode 100644 index 0000000000..2d86122770 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs @@ -0,0 +1,55 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Data.SqlClient; +using System.IO; +using Umbraco.Core.Persistence; +using Umbraco.Tests.Integration.Testing; + +namespace Umbraco.Tests.Integration +{ + public static class HostBuilderExtensions + { + + + /// + /// Ensures the lifetime of the host ends as soon as code executes + /// + /// + /// + public static IHostBuilder UseTestLifetime(this IHostBuilder hostBuilder) + { + hostBuilder.ConfigureServices((context, collection) => collection.AddSingleton()); + return hostBuilder; + } + + public static IHostBuilder UseLocalDb(this IHostBuilder hostBuilder, string dbFilePath) + { + // Need to register SqlClient manually + // TODO: Move this to someplace central + DbProviderFactories.RegisterFactory("System.Data.SqlClient", SqlClientFactory.Instance); + + hostBuilder.ConfigureAppConfiguration(x => + { + if (!Directory.Exists(dbFilePath)) + Directory.CreateDirectory(dbFilePath); + + var dbName = Guid.NewGuid().ToString("N"); + var instance = TestLocalDb.EnsureLocalDbInstanceAndDatabase(dbName, dbFilePath); + + x.AddInMemoryCollection(new[] + { + new KeyValuePair("ConnectionStrings:umbracoDbDSN", instance.GetConnectionString(dbName)) + }); + }); + return hostBuilder; + } + + + } + + +} diff --git a/src/Umbraco.Tests.Integration/Implementations/TestDbProviderFactoryCreator.cs b/src/Umbraco.Tests.Integration/Implementations/TestDbProviderFactoryCreator.cs deleted file mode 100644 index 9081c4ccb4..0000000000 --- a/src/Umbraco.Tests.Integration/Implementations/TestDbProviderFactoryCreator.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Data.Common; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.SqlSyntax; - -namespace Umbraco.Tests.Integration.Implementations -{ - public class TestDbProviderFactoryCreator : IDbProviderFactoryCreator - { - public IBulkSqlInsertProvider CreateBulkSqlInsertProvider(string providerName) - { - throw new System.NotImplementedException(); - } - - public void CreateDatabase() - { - throw new System.NotImplementedException(); - } - - public DbProviderFactory CreateFactory() - { - throw new System.NotImplementedException(); - } - - public DbProviderFactory CreateFactory(string providerName) - { - throw new System.NotImplementedException(); - } - - public ISqlSyntaxProvider GetSqlSyntaxProvider(string providerName) - { - throw new System.NotImplementedException(); - } - } -} diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index 5254892b23..4c37903b0c 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; using Moq; +using System.Data.Common; using System.Net; using Umbraco.Core; using Umbraco.Core.Cache; @@ -60,7 +61,7 @@ namespace Umbraco.Tests.Integration.Implementations public IWebHostEnvironment GetWebHostEnvironment() => _hostEnvironment; - public override IDbProviderFactoryCreator DbProviderFactoryCreator => new TestDbProviderFactoryCreator(); + public override IDbProviderFactoryCreator DbProviderFactoryCreator => new SqlServerDbProviderFactoryCreator("System.Data.SqlClient", DbProviderFactories.GetFactory); public override IBulkSqlInsertProvider BulkSqlInsertProvider => new SqlServerBulkSqlInsertProvider(); diff --git a/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs b/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs new file mode 100644 index 0000000000..063644490b --- /dev/null +++ b/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs @@ -0,0 +1,18 @@ +using Microsoft.Extensions.Hosting; +using System.Threading; +using System.Threading.Tasks; + +namespace Umbraco.Tests.Integration +{ + /// + /// Ensures the host lifetime ends as soon as code execution is done + /// + public class TestLifetime : IHostLifetime + { + public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; + + public Task WaitForStartAsync(CancellationToken cancellationToken) => Task.CompletedTask; + } + + +} diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index 4b5cb30544..198fd4831c 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -7,19 +7,36 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Moq; using NUnit.Framework; +using System.Collections.Generic; +using System.IO; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Logging; +using Umbraco.Core.Migrations.Install; +using Umbraco.Core.Persistence; using Umbraco.Core.Runtime; using Umbraco.Tests.Common; using Umbraco.Tests.Integration.Implementations; +using Umbraco.Tests.Integration.Testing; using Umbraco.Web.BackOffice.AspNetCore; +using static Umbraco.Core.Migrations.Install.DatabaseBuilder; namespace Umbraco.Tests.Integration { + [TestFixture] public class RuntimeTests { + [OneTimeTearDown] + public void FixtureTearDown() + { + TestLocalDb.Cleanup(); + } + + /// + /// Manually configure the containers/dependencies and call Boot on Core runtime + /// [Test] public void BootCoreRuntime() { @@ -52,40 +69,107 @@ namespace Umbraco.Tests.Integration Assert.IsTrue(MyComponent.IsTerminated); } + /// + /// Calling AddUmbracoCore to configure the container and boot the core runtime within a generic host + /// [Test] public void AddUmbracoCore() { + var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); + + var host = Host.CreateDefaultBuilder() + .UseTestLifetime() + .UseUmbraco(serviceProviderFactory) + .ConfigureServices((hostContext, services) => + { + var testHelper = new TestHelper(); + + AddRequiredNetCoreServices(services, testHelper); + + // Add it! + services.AddUmbracoConfiguration(); + services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + + // Run tests + services.AddHostedService(x => DelegateHostedService.Create(() => + { + // assert results + var runtimeState = umbracoContainer.GetInstance(); + var mainDom = umbracoContainer.GetInstance(); + + Assert.IsTrue(mainDom.IsMainDom); + Assert.IsNull(runtimeState.BootFailedException); + Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); + Assert.IsTrue(MyComposer.IsComposed); + + }, null)); + }) + .Build(); + + // NOTE: host.Run() could be used but that requires more work by manually calling IHostApplicationLifetime.StopApplication(). In these cases we don't need to wind down. + host.Start(); + } + + + [Test] + public void UseUmbracoCore() + { + var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); var testHelper = new TestHelper(); - // MSDI - var services = new ServiceCollection(); - // These services are required + var host = Host.CreateDefaultBuilder() + //TODO: Need to have a configured umb version for the runtime state + .UseLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb")) + .UseTestLifetime() + .UseUmbraco(serviceProviderFactory) + .ConfigureServices((hostContext, services) => + { + AddRequiredNetCoreServices(services, testHelper); + + // Add it! + services.AddUmbracoConfiguration(); + services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + + // Run tests + services.AddHostedService(x => DelegateHostedService.Create(() => + { + var runtimeState = (RuntimeState)umbracoContainer.GetInstance(); + Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); + + var dbBuilder = umbracoContainer.GetInstance(); + Assert.IsNotNull(dbBuilder); + + var canConnect = dbBuilder.CanConnectToDatabase; + Assert.IsTrue(canConnect); + + var dbResult = dbBuilder.CreateSchemaAndData(); + Assert.IsTrue(dbResult.Success); + + var dbFactory = umbracoContainer.GetInstance(); + var profilingLogger = umbracoContainer.GetInstance(); + runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger); + Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level); + + }, null)); + }) + .Build(); + + // NOTE: host.Run() could be used but that requires more work by manually calling IHostApplicationLifetime.StopApplication(). In these cases we don't need to wind down. + host.Start(); + } + + private LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory) + { + var container = new ServiceContainer(ContainerOptions.Default.Clone().WithMicrosoftSettings().WithAspNetCoreSettings()); + serviceProviderFactory = new UmbracoServiceProviderFactory(container); + var umbracoContainer = serviceProviderFactory.GetContainer(); + return umbracoContainer; + } + + private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper) + { services.AddSingleton(x => testHelper.GetHttpContextAccessor()); services.AddSingleton(x => testHelper.GetWebHostEnvironment()); - services.AddSingleton(x => Mock.Of()); - - // LightInject / Umbraco - var container = new ServiceContainer(ContainerOptions.Default.Clone().WithMicrosoftSettings().WithAspNetCoreSettings()); - var serviceProviderFactory = new UmbracoServiceProviderFactory(container); - var umbracoContainer = serviceProviderFactory.GetContainer(); - - // Some IConfiguration must exist in the container first - var configurationBuilder = new ConfigurationBuilder(); - configurationBuilder.AddEnvironmentVariables(); - services.AddSingleton(x => configurationBuilder.Build()); - - // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); - - // assert results - var runtimeState = umbracoContainer.GetInstance(); - var mainDom = umbracoContainer.GetInstance(); - - Assert.IsTrue(mainDom.IsMainDom); - Assert.IsNull(runtimeState.BootFailedException); - Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); - Assert.IsTrue(MyComposer.IsComposed); } [RuntimeLevel(MinLevel = RuntimeLevel.Install)] diff --git a/src/Umbraco.Tests.Integration/Testing/TestLocalDb.cs b/src/Umbraco.Tests.Integration/Testing/TestLocalDb.cs new file mode 100644 index 0000000000..8ee326783b --- /dev/null +++ b/src/Umbraco.Tests.Integration/Testing/TestLocalDb.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Umbraco.Core.Persistence; + +namespace Umbraco.Tests.Integration.Testing +{ + public static class TestLocalDb + { + private const string LocalDbInstanceName = "UmbTests"; + + private static LocalDb LocalDb { get; } = new LocalDb(); + + // TODO: We need to borrow logic from this old branch, this is the latest commit at the old branch where we had LocalDb + // working for tests. There's a lot of hoops to jump through to make it work 'fast'. Turns out it didn't actually run as + // fast as SqlCe due to the dropping/creating of DB instances since that is faster in SqlCe but this code was all heavily + // optimized to go as fast as possible. + // see https://github.com/umbraco/Umbraco-CMS/blob/3a8716ac7b1c48b51258724337086cd0712625a1/src/Umbraco.Tests/TestHelpers/LocalDbTestDatabase.cs + internal static LocalDb.Instance EnsureLocalDbInstanceAndDatabase(string dbName, string dbFilePath) + { + if (!LocalDb.InstanceExists(LocalDbInstanceName) && !LocalDb.CreateInstance(LocalDbInstanceName)) + { + throw new InvalidOperationException( + $"Failed to create LocalDb instance {LocalDbInstanceName}, assuming LocalDb is not really available."); + } + + var instance = LocalDb.GetInstance(LocalDbInstanceName); + + if (instance == null) + { + throw new InvalidOperationException( + $"Failed to get LocalDb instance {LocalDbInstanceName}, assuming LocalDb is not really available."); + } + + instance.CreateDatabase(dbName, dbFilePath); + + return instance; + } + + public static void Cleanup() + { + var instance = LocalDb.GetInstance(LocalDbInstanceName); + if (instance != null) + { + instance.DropDatabases(); + } + } + } +} diff --git a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj index 55b3e8cdca..320db33568 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj +++ b/src/Umbraco.Tests.Integration/Umbraco.Tests.Integration.csproj @@ -15,6 +15,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs index 697e8b7dc4..d668b8c1bc 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; @@ -63,26 +64,30 @@ namespace Umbraco.Web.BackOffice.AspNetCore public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IRegister umbContainer, Assembly entryAssembly) { + if (services is null) throw new ArgumentNullException(nameof(services)); + if (umbContainer is null) throw new ArgumentNullException(nameof(umbContainer)); + if (entryAssembly is null) throw new ArgumentNullException(nameof(entryAssembly)); + services.AddSingleton(); - CreateCompositionRoot(services); + CreateCompositionRoot(services, out var logger, out var configs, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler); // TODO: Get rid of this 'Current' requirement - var globalSettings = Current.Configs.Global(); + var globalSettings = configs.Global(); var umbracoVersion = new UmbracoVersion(globalSettings); // TODO: Currently we are not passing in any TypeFinderConfig (with ITypeFinderSettings) which we should do, however // this is not critical right now and would require loading in some config before boot time so just leaving this as-is for now. - var typeFinder = new TypeFinder(Current.Logger, new DefaultUmbracoAssemblyProvider(entryAssembly)); + var typeFinder = new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(entryAssembly)); var coreRuntime = GetCoreRuntime( - Current.Configs, + configs, umbracoVersion, - Current.IOHelper, - Current.Logger, - Current.Profiler, - Current.HostingEnvironment, - Current.BackOfficeInfo, + ioHelper, + logger, + profiler, + hostingEnvironment, + backOfficeInfo, typeFinder); var factory = coreRuntime.Boot(umbContainer); @@ -115,7 +120,9 @@ namespace Umbraco.Web.BackOffice.AspNetCore return coreRuntime; } - private static void CreateCompositionRoot(IServiceCollection services) + private static void CreateCompositionRoot(IServiceCollection services, + out ILogger logger, out Configs configs, out IIOHelper ioHelper, out Core.Hosting.IHostingEnvironment hostingEnvironment, + out IBackOfficeInfo backOfficeInfo, out IProfiler profiler) { // TODO: This isn't the best to have to resolve the services now but to avoid this will // require quite a lot of re-work. @@ -123,9 +130,12 @@ namespace Umbraco.Web.BackOffice.AspNetCore var httpContextAccessor = serviceProvider.GetRequiredService(); var webHostEnvironment = serviceProvider.GetRequiredService(); + // TODO: I'm unsure about this, by doing this it means we are resolving a "Different" instance to the one + // that controls the whole app because the instances comes from a different service provider. This + // could cause some issues with shutdowns, etc... we need to investigate. var hostApplicationLifetime = serviceProvider.GetRequiredService(); - var configs = serviceProvider.GetService(); + configs = serviceProvider.GetService(); if (configs == null) throw new InvalidOperationException($"Could not resolve type {typeof(Configs)} from the container, ensure {nameof(AddUmbracoConfiguration)} is called before calling {nameof(AddUmbracoCore)}"); @@ -133,17 +143,15 @@ namespace Umbraco.Web.BackOffice.AspNetCore var coreDebug = configs.CoreDebug(); var globalSettings = configs.Global(); - var hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor, hostApplicationLifetime); - var ioHelper = new IOHelper(hostingEnvironment, globalSettings); - var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, + hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor, hostApplicationLifetime); + ioHelper = new IOHelper(hostingEnvironment, globalSettings); + logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, new AspNetCoreSessionIdResolver(httpContextAccessor), () => serviceProvider.GetService(), coreDebug, ioHelper, new AspNetCoreMarchal()); - var backOfficeInfo = new AspNetCoreBackOfficeInfo(configs.Global()); - var profiler = new LogProfiler(logger); - - Current.Initialize(logger, configs, ioHelper, hostingEnvironment, backOfficeInfo, profiler); + backOfficeInfo = new AspNetCoreBackOfficeInfo(configs.Global()); + profiler = new LogProfiler(logger); } private class AspNetCoreBootPermissionsChecker : IUmbracoBootPermissionChecker From d0a204b984134e826dd78f68d6413cda9230dca6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 24 Mar 2020 14:48:32 +1100 Subject: [PATCH 14/28] Cleans up some unused code, fixes a merge issue causing duplicate runtimes to be created, register essential does what it's supposed to do, don't mix things with the webruntime. --- src/Umbraco.Core/Services/IRuntimeState.cs | 6 - .../CompositionExtensions_Essentials.cs | 12 +- .../Runtime/CoreRuntime.cs | 17 +-- src/Umbraco.Infrastructure/RuntimeState.cs | 5 - .../ContainerTests.cs | 5 +- .../Implementations/DelegateHostedService.cs | 38 ------ src/Umbraco.Tests.Integration/RuntimeTests.cs | 118 +++++++++++------- src/Umbraco.Tests/Runtimes/StandaloneTests.cs | 4 +- ...oBackOfficeApplicationBuilderExtensions.cs | 8 +- ...UmbracoCoreServiceCollectionExtensions.cs} | 53 ++++++-- src/Umbraco.Web/Runtime/WebInitialComposer.cs | 2 - src/Umbraco.Web/Umbraco.Web.csproj | 2 +- 12 files changed, 140 insertions(+), 130 deletions(-) delete mode 100644 src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs rename src/Umbraco.Web.BackOffice/AspNetCore/{UmbracoBackOfficeServiceCollectionExtensions.cs => UmbracoCoreServiceCollectionExtensions.cs} (82%) diff --git a/src/Umbraco.Core/Services/IRuntimeState.cs b/src/Umbraco.Core/Services/IRuntimeState.cs index 38da246cc1..565b2563e6 100644 --- a/src/Umbraco.Core/Services/IRuntimeState.cs +++ b/src/Umbraco.Core/Services/IRuntimeState.cs @@ -46,12 +46,6 @@ namespace Umbraco.Core /// This is eg "http://www.example.com". Uri ApplicationUrl { get; } - /// - /// Gets the Umbraco application virtual path. - /// - /// This is either "/" or eg "/virtual". - string ApplicationVirtualPath { get; } - /// /// Gets the runtime level of execution. /// diff --git a/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs b/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs index eb74d37590..02e5a6f5ee 100644 --- a/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs +++ b/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs @@ -1,6 +1,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -15,6 +16,9 @@ namespace Umbraco.Core /// /// Registers essential services. /// + /// + /// These services are all either created by the runtime or used to construct the runtime + /// public static void RegisterEssentials(this Composition composition, ILogger logger, IProfiler profiler, IProfilingLogger profilingLogger, IMainDom mainDom, @@ -25,8 +29,10 @@ namespace Umbraco.Core ITypeFinder typeFinder, IIOHelper ioHelper, IUmbracoVersion umbracoVersion, - IDbProviderFactoryCreator dbProviderFactoryCreator) - { + IDbProviderFactoryCreator dbProviderFactoryCreator, + IHostingEnvironment hostingEnvironment, + IBackOfficeInfo backOfficeInfo) + { composition.RegisterUnique(logger); composition.RegisterUnique(profiler); composition.RegisterUnique(profilingLogger); @@ -42,6 +48,8 @@ namespace Umbraco.Core composition.RegisterUnique(umbracoVersion); composition.RegisterUnique(dbProviderFactoryCreator); composition.RegisterUnique(factory => factory.GetInstance().BulkSqlInsertProvider); + composition.RegisterUnique(hostingEnvironment); + composition.RegisterUnique(backOfficeInfo); } } } diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs index 4a9441e535..5cd51a174a 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs @@ -69,7 +69,7 @@ namespace Umbraco.Core.Runtime Configs.Global(), new Lazy(() => mainDom), new Lazy(() => _factory.GetInstance()), - UmbracoVersion,HostingEnvironment, BackOfficeInfo) + UmbracoVersion, HostingEnvironment, BackOfficeInfo) { Level = RuntimeLevel.Boot }; @@ -82,7 +82,6 @@ namespace Umbraco.Core.Runtime protected IBackOfficeInfo BackOfficeInfo { get; } public IDbProviderFactoryCreator DbProviderFactoryCreator { get; } - //public IBulkSqlInsertProvider BulkSqlInsertProvider { get; } /// /// Gets the profiler. @@ -176,21 +175,9 @@ namespace Umbraco.Core.Runtime // type finder/loader var typeLoader = new TypeLoader(IOHelper, TypeFinder, appCaches.RuntimeCache, new DirectoryInfo(HostingEnvironment.LocalTempPath), ProfilingLogger); - // runtime state - // beware! must use '() => _factory.GetInstance()' and NOT '_factory.GetInstance' - // as the second one captures the current value (null) and therefore fails - _state = new RuntimeState(Logger, - Configs.Global(), - new Lazy(() => _factory.GetInstance()), - new Lazy(() => _factory.GetInstance()), - UmbracoVersion, HostingEnvironment, BackOfficeInfo) - { - Level = RuntimeLevel.Boot - }; - // create the composition composition = new Composition(register, typeLoader, ProfilingLogger, _state, Configs, IOHelper, appCaches); - composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, MainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper, UmbracoVersion, DbProviderFactoryCreator); + composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, MainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper, UmbracoVersion, DbProviderFactoryCreator, HostingEnvironment, BackOfficeInfo); // run handlers RuntimeOptions.DoRuntimeEssentials(composition, appCaches, typeLoader, databaseFactory); diff --git a/src/Umbraco.Infrastructure/RuntimeState.cs b/src/Umbraco.Infrastructure/RuntimeState.cs index eadb9fed21..420fba7ffc 100644 --- a/src/Umbraco.Infrastructure/RuntimeState.cs +++ b/src/Umbraco.Infrastructure/RuntimeState.cs @@ -43,8 +43,6 @@ namespace Umbraco.Core _umbracoVersion = umbracoVersion; _hostingEnvironment = hostingEnvironment; _backOfficeInfo = backOfficeInfo; - - ApplicationVirtualPath = _hostingEnvironment.ApplicationVirtualPath; } /// @@ -84,9 +82,6 @@ namespace Umbraco.Core /// public Uri ApplicationUrl { get; private set; } - /// - public string ApplicationVirtualPath { get; } - /// public string CurrentMigrationState { get; internal set; } diff --git a/src/Umbraco.Tests.Integration/ContainerTests.cs b/src/Umbraco.Tests.Integration/ContainerTests.cs index d190d1165d..f440944ab7 100644 --- a/src/Umbraco.Tests.Integration/ContainerTests.cs +++ b/src/Umbraco.Tests.Integration/ContainerTests.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Integration var testHelper = new TestHelper(); var runtimeState = Mock.Of(); var umbracoDatabaseFactory = Mock.Of(); - var dbProviderFactoryCreator = Mock.Of(); + var dbProviderFactoryCreator = Mock.Of(); var typeLoader = testHelper.GetMockedTypeLoader(); // Register in the container @@ -45,7 +45,8 @@ namespace Umbraco.Tests.Integration testHelper.Logger, runtimeState, testHelper.GetConfigs(), testHelper.IOHelper, testHelper.AppCaches); composition.RegisterEssentials(testHelper.Logger, testHelper.Profiler, testHelper.Logger, testHelper.MainDom, testHelper.AppCaches, umbracoDatabaseFactory, typeLoader, runtimeState, testHelper.GetTypeFinder(), - testHelper.IOHelper, testHelper.GetUmbracoVersion(), dbProviderFactoryCreator); + testHelper.IOHelper, testHelper.GetUmbracoVersion(), dbProviderFactoryCreator, + testHelper.GetHostingEnvironment(), testHelper.GetBackOfficeInfo()); // Cross wire - this would be called by the Host Builder at the very end of ConfigureServices var lightInjectServiceProvider = serviceProviderFactory.CreateServiceProvider(umbracoContainer.Container); diff --git a/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs b/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs deleted file mode 100644 index 9df7270350..0000000000 --- a/src/Umbraco.Tests.Integration/Implementations/DelegateHostedService.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Microsoft.Extensions.Hosting; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace Umbraco.Tests.Integration -{ - /// - /// Executes arbitrary code on start/end - /// - public class DelegateHostedService : IHostedService - { - private readonly Action _start; - private readonly Action _end; - - public static DelegateHostedService Create(Action start, Action end) => new DelegateHostedService(start, end); - - private DelegateHostedService(Action start, Action end) - { - _start = start; - _end = end; - } - - public Task StartAsync(CancellationToken cancellationToken) - { - _start(); - return Task.CompletedTask; - } - - public Task StopAsync(CancellationToken cancellationToken) - { - _end?.Invoke(); - return Task.CompletedTask; - } - } - - -} diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index fb7f6b427e..dae4d0cbb8 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -9,6 +9,7 @@ using Moq; using NUnit.Framework; using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Composing.LightInject; @@ -28,6 +29,13 @@ namespace Umbraco.Tests.Integration [TestFixture] public class RuntimeTests { + [TearDown] + public void TearDown() + { + MyComponent.Reset(); + MyComposer.Reset(); + } + [OneTimeTearDown] public void FixtureTearDown() { @@ -73,12 +81,11 @@ namespace Umbraco.Tests.Integration /// Calling AddUmbracoCore to configure the container and boot the core runtime within a generic host /// [Test] - public void AddUmbracoCore() + public async Task AddUmbracoCore() { var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); - var host = Host.CreateDefaultBuilder() - .UseTestLifetime() + var hostBuilder = new HostBuilder() .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => { @@ -89,38 +96,61 @@ namespace Umbraco.Tests.Integration // Add it! services.AddUmbracoConfiguration(); services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + }); - // Run tests - services.AddHostedService(x => DelegateHostedService.Create(() => - { - // assert results - var runtimeState = umbracoContainer.GetInstance(); - var mainDom = umbracoContainer.GetInstance(); + var host = await hostBuilder.StartAsync(); - Assert.IsTrue(mainDom.IsMainDom); - Assert.IsNull(runtimeState.BootFailedException); - Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); - Assert.IsTrue(MyComposer.IsComposed); + // assert results + var runtimeState = umbracoContainer.GetInstance(); + var mainDom = umbracoContainer.GetInstance(); - }, null)); - }) - .Build(); + Assert.IsTrue(mainDom.IsMainDom); + Assert.IsNull(runtimeState.BootFailedException); + Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); + Assert.IsTrue(MyComponent.IsInit); + Assert.IsFalse(MyComponent.IsTerminated); - // NOTE: host.Run() could be used but that requires more work by manually calling IHostApplicationLifetime.StopApplication(). In these cases we don't need to wind down. - host.Start(); + await host.StopAsync(); + + Assert.IsTrue(MyComponent.IsTerminated); } + [Ignore("This test just shows that resolving services from the container before the host is done resolves 2 different instances")] [Test] - public void UseUmbracoCore() + public async Task BuildServiceProvider() + { + var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); + + IHostApplicationLifetime lifetime1 = null; + + var hostBuilder = new HostBuilder() + .UseUmbraco(serviceProviderFactory) + .ConfigureServices((hostContext, services) => + { + lifetime1 = services.BuildServiceProvider().GetRequiredService(); + }); + + var host = await hostBuilder.StartAsync(); + + var lifetime2 = host.Services.GetRequiredService(); + + lifetime1.StopApplication(); + Assert.IsTrue(lifetime1.ApplicationStopping.IsCancellationRequested); + Assert.AreEqual(lifetime1.ApplicationStopping.IsCancellationRequested, lifetime2.ApplicationStopping.IsCancellationRequested); + + } + + [Test] + public async Task UseUmbracoCore() { var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); var testHelper = new TestHelper(); - var host = Host.CreateDefaultBuilder() + var hostBuilder = new HostBuilder() //TODO: Need to have a configured umb version for the runtime state .UseLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb")) - .UseTestLifetime() + //.UseTestLifetime() .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => { @@ -129,33 +159,26 @@ namespace Umbraco.Tests.Integration // Add it! services.AddUmbracoConfiguration(); services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + }); - // Run tests - services.AddHostedService(x => DelegateHostedService.Create(() => - { - var runtimeState = (RuntimeState)umbracoContainer.GetInstance(); - Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); + var host = await hostBuilder.StartAsync(); - var dbBuilder = umbracoContainer.GetInstance(); - Assert.IsNotNull(dbBuilder); + var runtimeState = (RuntimeState)umbracoContainer.GetInstance(); + Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); - var canConnect = dbBuilder.CanConnectToDatabase; - Assert.IsTrue(canConnect); + var dbBuilder = umbracoContainer.GetInstance(); + Assert.IsNotNull(dbBuilder); - var dbResult = dbBuilder.CreateSchemaAndData(); - Assert.IsTrue(dbResult.Success); + var canConnect = dbBuilder.CanConnectToDatabase; + Assert.IsTrue(canConnect); - var dbFactory = umbracoContainer.GetInstance(); - var profilingLogger = umbracoContainer.GetInstance(); - runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger); - Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level); + var dbResult = dbBuilder.CreateSchemaAndData(); + Assert.IsTrue(dbResult.Success); - }, null)); - }) - .Build(); - - // NOTE: host.Run() could be used but that requires more work by manually calling IHostApplicationLifetime.StopApplication(). In these cases we don't need to wind down. - host.Start(); + var dbFactory = umbracoContainer.GetInstance(); + var profilingLogger = umbracoContainer.GetInstance(); + runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger); + Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level); } private LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory) @@ -181,6 +204,11 @@ namespace Umbraco.Tests.Integration IsComposed = true; } + public static void Reset() + { + IsComposed = false; + } + public static bool IsComposed { get; private set; } } @@ -205,6 +233,12 @@ namespace Umbraco.Tests.Integration { IsTerminated = true; } + + public static void Reset() + { + IsTerminated = false; + IsInit = false; + } } } diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index 0cb3f3e2e1..99a5352a17 100644 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs @@ -80,7 +80,7 @@ namespace Umbraco.Tests.Runtimes // create the register and the composition var register = TestHelper.GetRegister(); var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, configs, ioHelper, appCaches); - composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator); + composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo); // create the core runtime and have it compose itself var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder); @@ -275,7 +275,7 @@ namespace Umbraco.Tests.Runtimes var register = TestHelper.GetRegister(); var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, configs, ioHelper, appCaches); var umbracoVersion = TestHelper.GetUmbracoVersion(); - composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator); + composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo); // create the core runtime and have it compose itself var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder); diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs index 1f06a818d6..a79838bd3e 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs @@ -1,5 +1,7 @@ using System; using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; namespace Umbraco.Web.BackOffice.AspNetCore { @@ -7,12 +9,10 @@ namespace Umbraco.Web.BackOffice.AspNetCore { public static IApplicationBuilder UseUmbracoBackOffice(this IApplicationBuilder app) { - if (app == null) - { - throw new ArgumentNullException(nameof(app)); - } + if (app == null) throw new ArgumentNullException(nameof(app)); return app; } + } } diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs similarity index 82% rename from src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs rename to src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs index 44fb9bc14f..6c3cecad28 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs @@ -6,14 +6,11 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Umbraco.Composing; using Umbraco.Configuration; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; @@ -24,9 +21,13 @@ namespace Umbraco.Web.BackOffice.AspNetCore { - public static class UmbracoBackOfficeServiceCollectionExtensions + public static class UmbracoCoreServiceCollectionExtensions { - + /// + /// Adds the Umbraco Configuration requirements + /// + /// + /// public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services) { var serviceProvider = services.BuildServiceProvider(); @@ -45,13 +46,10 @@ namespace Umbraco.Web.BackOffice.AspNetCore /// - /// Adds the Umbraco Back Core requirements + /// Adds the Umbraco Back Core requirements /// /// /// - /// - /// Must be called after all services are added to the application because we are cross-wiring the container (currently) - /// public static IServiceCollection AddUmbracoCore(this IServiceCollection services) { if (!UmbracoServiceProviderFactory.IsActive) @@ -62,6 +60,13 @@ namespace Umbraco.Web.BackOffice.AspNetCore return services.AddUmbracoCore(umbContainer, Assembly.GetEntryAssembly()); } + /// + /// Adds the Umbraco Back Core requirements + /// + /// + /// + /// + /// public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IRegister umbContainer, Assembly entryAssembly) { if (services is null) throw new ArgumentNullException(nameof(services)); @@ -90,6 +95,8 @@ namespace Umbraco.Web.BackOffice.AspNetCore backOfficeInfo, typeFinder); + hostingEnvironment.RegisterObject(new CoreRuntimeShutdown(coreRuntime)); + var factory = coreRuntime.Boot(umbContainer); return services; @@ -124,8 +131,8 @@ namespace Umbraco.Web.BackOffice.AspNetCore out ILogger logger, out Configs configs, out IIOHelper ioHelper, out Core.Hosting.IHostingEnvironment hostingEnvironment, out IBackOfficeInfo backOfficeInfo, out IProfiler profiler) { - // TODO: This isn't the best to have to resolve the services now but to avoid this will - // require quite a lot of re-work. + // TODO: Resolving services before the Host is done configuring this way means that the services resolved + // are not going to be the same instances that are going to be used within the application! var serviceProvider = services.BuildServiceProvider(); var httpContextAccessor = serviceProvider.GetRequiredService(); @@ -162,5 +169,29 @@ namespace Umbraco.Web.BackOffice.AspNetCore // nothing to check } } + + /// + /// Ensures the runtime is shutdown when the application is shutting down + /// + private class CoreRuntimeShutdown : IRegisteredObject + { + public CoreRuntimeShutdown(IRuntime runtime) + { + _runtime = runtime; + } + + private bool _completed = false; + private readonly IRuntime _runtime; + + public void Stop(bool immediate) + { + if (!_completed) + { + _completed = true; + _runtime.Terminate(); + } + + } + } } } diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index b81cafdb40..81aac30d2c 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -72,8 +72,6 @@ namespace Umbraco.Web.Runtime composition.Register(Lifetime.Singleton); - composition.Register(); - composition.Register(); composition.Register(Lifetime.Singleton); composition.Register(); composition.Register(Lifetime.Singleton); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index e8aaecdf4d..5eb60cb629 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -585,4 +585,4 @@ - + \ No newline at end of file From 900505704c264bbf561187a5128ba234ef2ed5be Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 14:54:45 +1100 Subject: [PATCH 15/28] Committing a namespaces change --- .gitignore | 1 + src/Umbraco.Core/Manifest/ManifestWatcher.cs | 2 +- src/Umbraco.Core/Net/IIpResolver.cs | 2 +- src/Umbraco.Core/Net/ISessionIdResolver.cs | 2 +- src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs | 2 +- src/Umbraco.Core/Net/IUserAgentProvider.cs | 2 +- src/Umbraco.Infrastructure/Intall/InstallHelper.cs | 2 +- .../Intall/InstallSteps/StarterKitDownloadStep.cs | 2 +- .../Intall/InstallSteps/StarterKitInstallStep.cs | 2 +- .../Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs | 2 +- .../Logging/Serilog/LoggerConfigExtensions.cs | 2 +- src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs | 2 +- src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs | 2 +- src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreMarchal.cs | 2 +- .../AspNetCore/AspNetCoreSessionIdResolver.cs | 2 +- .../AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs | 4 ++-- .../AspNetCore/AspNetCoreUserAgentProvider.cs | 2 +- src/Umbraco.Web/AspNet/AspNetIpResolver.cs | 2 +- src/Umbraco.Web/AspNet/AspNetSessionManager.cs | 2 +- src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs | 2 +- src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs | 2 +- src/Umbraco.Web/Compose/AuditEventsComponent.cs | 2 +- src/Umbraco.Web/Composing/Current.cs | 2 +- src/Umbraco.Web/Editors/PackageInstallController.cs | 2 +- src/Umbraco.Web/Runtime/WebInitialComposer.cs | 2 +- src/Umbraco.Web/Security/AppBuilderExtensions.cs | 2 +- src/Umbraco.Web/Security/BackOfficeUserManager.cs | 2 +- .../Security/Providers/MembersMembershipProvider.cs | 2 +- .../Security/Providers/UmbracoMembershipProvider.cs | 2 +- src/Umbraco.Web/UmbracoDefaultOwinStartup.cs | 2 +- 30 files changed, 31 insertions(+), 30 deletions(-) diff --git a/.gitignore b/.gitignore index 8ff5a8ef25..5390da67dd 100644 --- a/.gitignore +++ b/.gitignore @@ -166,3 +166,4 @@ build/temp/ /src/ApiDocs/api/* /src/Umbraco.Web.UI.NetCore/wwwroot/Media/* /src/Umbraco.Web.UI.NetCore/wwwroot/is-cache/* +/src/Umbraco.Tests.Integration/App_Data/* diff --git a/src/Umbraco.Core/Manifest/ManifestWatcher.cs b/src/Umbraco.Core/Manifest/ManifestWatcher.cs index 23caac3a1b..adf2be466b 100644 --- a/src/Umbraco.Core/Manifest/ManifestWatcher.cs +++ b/src/Umbraco.Core/Manifest/ManifestWatcher.cs @@ -4,7 +4,7 @@ using System.IO; using System.Linq; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Core.Manifest { diff --git a/src/Umbraco.Core/Net/IIpResolver.cs b/src/Umbraco.Core/Net/IIpResolver.cs index 7fb6b8a793..8a7d670723 100644 --- a/src/Umbraco.Core/Net/IIpResolver.cs +++ b/src/Umbraco.Core/Net/IIpResolver.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Net +namespace Umbraco.Core.Net { public interface IIpResolver { diff --git a/src/Umbraco.Core/Net/ISessionIdResolver.cs b/src/Umbraco.Core/Net/ISessionIdResolver.cs index 745be5a435..94cdfb454a 100644 --- a/src/Umbraco.Core/Net/ISessionIdResolver.cs +++ b/src/Umbraco.Core/Net/ISessionIdResolver.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Net +namespace Umbraco.Core.Net { public interface ISessionIdResolver { diff --git a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs index 10d5b10955..eb38c67e2e 100644 --- a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Net +namespace Umbraco.Core.Net { public interface IUmbracoApplicationLifetime { diff --git a/src/Umbraco.Core/Net/IUserAgentProvider.cs b/src/Umbraco.Core/Net/IUserAgentProvider.cs index 14246ea99e..d3f997c607 100644 --- a/src/Umbraco.Core/Net/IUserAgentProvider.cs +++ b/src/Umbraco.Core/Net/IUserAgentProvider.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Net +namespace Umbraco.Core.Net { public interface IUserAgentProvider { diff --git a/src/Umbraco.Infrastructure/Intall/InstallHelper.cs b/src/Umbraco.Infrastructure/Intall/InstallHelper.cs index a5b4f71d8e..7aca4af09f 100644 --- a/src/Umbraco.Infrastructure/Intall/InstallHelper.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallHelper.cs @@ -9,10 +9,10 @@ using Umbraco.Core.Cookie; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Models; +using Umbraco.Core.Net; using Umbraco.Core.Persistence; using Umbraco.Core.Serialization; using Umbraco.Core.Services; -using Umbraco.Net; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install diff --git a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs index d8986cacb7..a20637584f 100644 --- a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Umbraco.Core.Services; using Umbraco.Core.Configuration; using Umbraco.Core.Models.Packaging; -using Umbraco.Net; +using Umbraco.Core.Net; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps diff --git a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs index cc269408f4..0a6e67c829 100644 --- a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs @@ -2,8 +2,8 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using Umbraco.Core.Net; using Umbraco.Core.Services; -using Umbraco.Net; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs index 1558cdcf21..052775d918 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs @@ -1,7 +1,7 @@ using Serilog.Core; using Serilog.Events; using System; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Core.Logging.Serilog.Enrichers { diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs index f4e8f85281..59e0b8854f 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Hosting; using Umbraco.Core.Logging.Serilog.Enrichers; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Core.Logging.Serilog { diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs index bb77869e28..55b89d7996 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Diagnostics; using Umbraco.Core.Hosting; using Umbraco.Core.IO; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Core.Logging.Serilog { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs index cee43757d8..520fe6b8aa 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Http; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreMarchal.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreMarchal.cs index 98e040d338..247666090e 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreMarchal.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreMarchal.cs @@ -2,7 +2,7 @@ using System; using System.Runtime.InteropServices; using Umbraco.Core.Diagnostics; -namespace Umbraco.Web.BackOffice +namespace Umbraco.Web.BackOffice.AspNetCore { public class AspNetCoreMarchal : IMarchal diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs index cafb02d367..a27e378909 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs index 20cfef352d..e7aba5e2de 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs @@ -1,9 +1,9 @@ using System.Threading; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; -using Umbraco.Net; +using Umbraco.Core.Net; -namespace Umbraco.Web.AspNet +namespace Umbraco.Web.BackOffice.AspNetCore { public class AspNetCoreUmbracoApplicationLifetime : IUmbracoApplicationLifetime { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs index f9c9884704..a85970afaf 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Http; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web/AspNet/AspNetIpResolver.cs b/src/Umbraco.Web/AspNet/AspNetIpResolver.cs index 7eaca54663..026fb7ff12 100644 --- a/src/Umbraco.Web/AspNet/AspNetIpResolver.cs +++ b/src/Umbraco.Web/AspNet/AspNetIpResolver.cs @@ -1,6 +1,6 @@ using System.Web; using Umbraco.Core; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web { diff --git a/src/Umbraco.Web/AspNet/AspNetSessionManager.cs b/src/Umbraco.Web/AspNet/AspNetSessionManager.cs index bf7b1c05c3..9196cb137f 100644 --- a/src/Umbraco.Web/AspNet/AspNetSessionManager.cs +++ b/src/Umbraco.Web/AspNet/AspNetSessionManager.cs @@ -1,6 +1,6 @@ using System.Web; +using Umbraco.Core.Net; using Umbraco.Core.Session; -using Umbraco.Net; namespace Umbraco.Web.AspNet { diff --git a/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs b/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs index 245e8ea374..64988a20d9 100644 --- a/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs @@ -1,6 +1,6 @@ using System.Threading; using System.Web; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web.AspNet { diff --git a/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs b/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs index bd37b62531..4ba73292bb 100644 --- a/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs +++ b/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs @@ -1,4 +1,4 @@ -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web.AspNet { diff --git a/src/Umbraco.Web/Compose/AuditEventsComponent.cs b/src/Umbraco.Web/Compose/AuditEventsComponent.cs index fba6e754c8..d03f33d7ac 100644 --- a/src/Umbraco.Web/Compose/AuditEventsComponent.cs +++ b/src/Umbraco.Web/Compose/AuditEventsComponent.cs @@ -7,10 +7,10 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Net; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; -using Umbraco.Net; using Umbraco.Web.Security; namespace Umbraco.Core.Compose diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index eec3dcd1e3..4424de6771 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.Mapping; +using Umbraco.Core.Net; using Umbraco.Core.PackageActions; using Umbraco.Core.Packaging; using Umbraco.Core.PropertyEditors; @@ -18,7 +19,6 @@ using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Sync; -using Umbraco.Net; using Umbraco.Web.Actions; using Umbraco.Web.Cache; using Umbraco.Web.Editors; diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 672b47f1eb..178a5c96d9 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -14,11 +14,11 @@ using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Models.Editors; using Umbraco.Core.Models.Packaging; +using Umbraco.Core.Net; using Umbraco.Core.Packaging; using Umbraco.Core.Persistence; using Umbraco.Core.Services; using Umbraco.Core.Strings; -using Umbraco.Net; using Umbraco.Web.JavaScript; using Umbraco.Web.Models; using Umbraco.Web.Models.ContentEditing; diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index 81aac30d2c..1d7fc8fd6e 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -18,7 +18,6 @@ using Umbraco.Core.Runtime; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Sync; -using Umbraco.Net; using Umbraco.Web.Actions; using Umbraco.Web.Cache; using Umbraco.Web.Composing.CompositionExtensions; @@ -46,6 +45,7 @@ using Umbraco.Web.WebApi; using Umbraco.Web.PropertyEditors; using Umbraco.Examine; using Umbraco.Core.Models; +using Umbraco.Core.Net; using Umbraco.Core.Request; using Umbraco.Core.Session; using Umbraco.Web.AspNet; diff --git a/src/Umbraco.Web/Security/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/AppBuilderExtensions.cs index 8fab9f4ea8..5416683eab 100644 --- a/src/Umbraco.Web/Security/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/Security/AppBuilderExtensions.cs @@ -17,9 +17,9 @@ using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Mapping; using Umbraco.Core.Models.Identity; +using Umbraco.Core.Net; using Umbraco.Core.Security; using Umbraco.Core.Services; -using Umbraco.Net; using Umbraco.Web.Composing; using Umbraco.Web.Models.Identity; using Constants = Umbraco.Core.Constants; diff --git a/src/Umbraco.Web/Security/BackOfficeUserManager.cs b/src/Umbraco.Web/Security/BackOfficeUserManager.cs index 354b9c2dde..64b7054723 100644 --- a/src/Umbraco.Web/Security/BackOfficeUserManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeUserManager.cs @@ -9,9 +9,9 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Mapping; using Umbraco.Core.Models.Identity; +using Umbraco.Core.Net; using Umbraco.Core.Security; using Umbraco.Core.Services; -using Umbraco.Net; using Umbraco.Web.Models.Identity; using IPasswordHasher = Microsoft.AspNet.Identity.IPasswordHasher; diff --git a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs index d393078cc6..ffa9a1c967 100644 --- a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Services; using Umbraco.Core.Models.Membership; using Umbraco.Web.Composing; using System; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Web.Security.Providers { diff --git a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs index d2eeebaeaf..9466dd6732 100644 --- a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs @@ -10,10 +10,10 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Net; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Security; using Umbraco.Core.Services; -using Umbraco.Net; using Umbraco.Web.Composing; namespace Umbraco.Web.Security.Providers diff --git a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs index a69e6c6f8d..8fcdc2c542 100644 --- a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs +++ b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs @@ -7,8 +7,8 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Mapping; +using Umbraco.Core.Net; using Umbraco.Core.Services; -using Umbraco.Net; using Umbraco.Web; using Umbraco.Web.Composing; using Umbraco.Web.Security; From 612a47b16b9aebb63bfbe26f482e7e578cbcb178 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 15:06:22 +1100 Subject: [PATCH 16/28] Splits interfaces into separate ones, removes overlap between interfaces, injects the necessary bits, and much more --- .../DefaultUmbracoAssemblyProvider.cs | 1 + .../Hosting/IHostingEnvironment.cs | 3 - .../Hosting/IHostingEnvironmentLifetime.cs | 8 + src/Umbraco.Core/Runtime/IMainDom.cs | 10 +- src/Umbraco.Core/Runtime/MainDom.cs | 22 ++- src/Umbraco.Core/Scheduling/KeepAlive.cs | 16 +- .../Scheduling/TempFileCleanup.cs | 8 +- src/Umbraco.Core/Services/IRuntime.cs | 4 +- src/Umbraco.Core/Services/IRuntimeState.cs | 16 -- src/Umbraco.Core/SimpleMainDom.cs | 4 + .../BatchedDatabaseServerMessenger.cs | 5 +- ...aseServerRegistrarAndMessengerComponent.cs | 5 +- .../Compose/ManifestWatcherComponent.cs | 10 +- .../Runtime/CoreInitialComposer.cs | 5 +- .../Runtime/CoreRuntime.cs | 103 ++++++------ .../Runtime/WebRuntime.cs | 4 +- src/Umbraco.Infrastructure/RuntimeOptions.cs | 10 +- src/Umbraco.Infrastructure/RuntimeState.cs | 39 +---- .../Scheduling/BackgroundTaskRunner.cs | 10 +- .../Scheduling/HealthCheckNotifier.cs | 15 +- .../Scheduling/LogScrubber.cs | 12 +- .../Scheduling/ScheduledPublishing.cs | 10 +- .../Scheduling/SchedulerComponent.cs | 22 +-- .../Search/BackgroundIndexRebuilder.cs | 6 +- .../Sync/DatabaseServerMessenger.cs | 12 +- .../PureLiveModelFactory.cs | 11 +- src/Umbraco.Tests.Common/TestHelperBase.cs | 11 +- .../Implementations/HostBuilderExtensions.cs | 22 +-- .../Implementations/TestHelper.cs | 14 +- .../Implementations/TestHostingEnvironment.cs | 23 +++ .../Implementations/TestLifetime.cs | 6 +- src/Umbraco.Tests.Integration/RuntimeTests.cs | 158 ++++++++++++------ .../XmlPublishedSnapshotService.cs | 8 +- .../LegacyXmlPublishedCache/XmlStore.cs | 19 +-- .../Routing/UmbracoModuleTests.cs | 3 +- .../Runtimes/CoreRuntimeTests.cs | 38 ++--- src/Umbraco.Tests/Runtimes/StandaloneTests.cs | 4 +- .../Scheduling/BackgroundTaskRunnerTests.cs | 6 +- .../Scheduling/BackgroundTaskRunnerTests2.cs | 4 +- src/Umbraco.Tests/TestHelpers/TestHelper.cs | 9 +- .../TestHelpers/TestWithDatabaseBase.cs | 1 + src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 3 +- .../Web/Mvc/UmbracoViewPageTests.cs | 1 + .../AspNetCore/AspNetCoreComposer.cs | 27 +++ .../AspNetCoreHostingEnvironment.cs | 66 ++------ .../AspNetCoreHostingEnvironmentShutdown.cs | 59 +++++++ ...oBackOfficeApplicationBuilderExtensions.cs | 50 ++++++ .../UmbracoCoreServiceCollectionExtensions.cs | 42 +---- .../AspNet/AspNetHostingEnvironment.cs | 41 +---- .../AspNet/AspNetHostingLifetime.cs | 47 ++++++ .../Profiling/WebProfilingController.cs | 10 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 + src/Umbraco.Web/UmbracoApplication.cs | 2 +- src/Umbraco.Web/UmbracoApplicationBase.cs | 4 +- src/Umbraco.Web/UmbracoContext.cs | 2 +- src/Umbraco.Web/UrlHelperExtensions.cs | 4 +- 56 files changed, 614 insertions(+), 442 deletions(-) create mode 100644 src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs create mode 100644 src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs create mode 100644 src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs create mode 100644 src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.cs create mode 100644 src/Umbraco.Web/AspNet/AspNetHostingLifetime.cs diff --git a/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs b/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs index 61d7cff240..f7c81d6d7e 100644 --- a/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs +++ b/src/Umbraco.Core/Composing/DefaultUmbracoAssemblyProvider.cs @@ -18,6 +18,7 @@ namespace Umbraco.Core.Composing { "Umbraco.Core", "Umbraco.Web", + "Umbraco.Web.BackOffice", "Umbraco.Infrastructure", "Umbraco.PublishedCache.NuCache", "Umbraco.ModelsBuilder.Embedded", diff --git a/src/Umbraco.Core/Hosting/IHostingEnvironment.cs b/src/Umbraco.Core/Hosting/IHostingEnvironment.cs index 5b97d8e4f3..b12ffbc138 100644 --- a/src/Umbraco.Core/Hosting/IHostingEnvironment.cs +++ b/src/Umbraco.Core/Hosting/IHostingEnvironment.cs @@ -19,8 +19,5 @@ namespace Umbraco.Core.Hosting Version IISVersion { get; } string MapPath(string path); string ToAbsolute(string virtualPath, string root); - - void RegisterObject(IRegisteredObject registeredObject); - void UnregisterObject(IRegisteredObject registeredObject); } } diff --git a/src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs b/src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs new file mode 100644 index 0000000000..891cedad20 --- /dev/null +++ b/src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Core.Hosting +{ + public interface IHostingEnvironmentLifetime + { + void RegisterObject(IRegisteredObject registeredObject); + void UnregisterObject(IRegisteredObject registeredObject); + } +} diff --git a/src/Umbraco.Core/Runtime/IMainDom.cs b/src/Umbraco.Core/Runtime/IMainDom.cs index 444fc1c7d0..1b7f09bc89 100644 --- a/src/Umbraco.Core/Runtime/IMainDom.cs +++ b/src/Umbraco.Core/Runtime/IMainDom.cs @@ -1,4 +1,5 @@ using System; +using Umbraco.Core.Hosting; // TODO: Can't change namespace due to breaking changes, change in netcore namespace Umbraco.Core @@ -16,10 +17,17 @@ namespace Umbraco.Core /// Gets a value indicating whether the current domain is the main domain. /// /// - /// When the first call is made to this there will generally be some logic executed to acquire a distributed lock lease. + /// Acquire must be called first else this will always return false /// bool IsMainDom { get; } + /// + /// Tries to acquire the MainDom, returns true if successful else false + /// + /// + /// + bool Acquire(IHostingEnvironmentLifetime hostingEnvironment); + /// /// Registers a resource that requires the current AppDomain to be the main domain to function. /// diff --git a/src/Umbraco.Core/Runtime/MainDom.cs b/src/Umbraco.Core/Runtime/MainDom.cs index 2c56852095..0a4a250aa6 100644 --- a/src/Umbraco.Core/Runtime/MainDom.cs +++ b/src/Umbraco.Core/Runtime/MainDom.cs @@ -21,7 +21,7 @@ namespace Umbraco.Core.Runtime #region Vars private readonly ILogger _logger; - private readonly IHostingEnvironment _hostingEnvironment; + private IHostingEnvironmentLifetime _hostingEnvironment; private readonly IMainDomLock _mainDomLock; // our own lock for local consistency @@ -42,17 +42,24 @@ namespace Umbraco.Core.Runtime #region Ctor // initializes a new instance of MainDom - public MainDom(ILogger logger, IHostingEnvironment hostingEnvironment, IMainDomLock systemLock) + public MainDom(ILogger logger, IMainDomLock systemLock) { - hostingEnvironment.RegisterObject(this); - _logger = logger; - _hostingEnvironment = hostingEnvironment; _mainDomLock = systemLock; } #endregion + public bool Acquire(IHostingEnvironmentLifetime hostingEnvironment) + { + _hostingEnvironment = hostingEnvironment; + return LazyInitializer.EnsureInitialized(ref _isMainDom, ref _isInitialized, ref _locko, () => + { + hostingEnvironment.RegisterObject(this); + return Acquire(); + }); + } + /// /// Registers a resource that requires the current AppDomain to be the main domain to function. /// @@ -180,10 +187,9 @@ namespace Umbraco.Core.Runtime /// Gets a value indicating whether the current domain is the main domain. /// /// - /// The lazy initializer call will only call the Acquire callback when it's not been initialized, else it will just return - /// the value from _isMainDom which means when we set _isMainDom to false again after being signaled, this will return false; + /// Acquire must be called first else this will always return false /// - public bool IsMainDom => LazyInitializer.EnsureInitialized(ref _isMainDom, ref _isInitialized, ref _locko, () => Acquire()); + public bool IsMainDom => _isMainDom; // IRegisteredObject void IRegisteredObject.Stop(bool immediate) diff --git a/src/Umbraco.Core/Scheduling/KeepAlive.cs b/src/Umbraco.Core/Scheduling/KeepAlive.cs index 515251b105..1c4ef075ae 100644 --- a/src/Umbraco.Core/Scheduling/KeepAlive.cs +++ b/src/Umbraco.Core/Scheduling/KeepAlive.cs @@ -11,18 +11,22 @@ namespace Umbraco.Web.Scheduling { public class KeepAlive : RecurringTaskBase { - private readonly IRuntimeState _runtime; + private readonly IRuntimeState _runtimeState; + private readonly IMainDom _mainDom; private readonly IKeepAliveSettings _keepAliveSettings; private readonly IProfilingLogger _logger; + private readonly IServerRegistrar _serverRegistrar; private static HttpClient _httpClient; public KeepAlive(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - IRuntimeState runtime, IKeepAliveSettings keepAliveSettings, IProfilingLogger logger) + IRuntimeState runtimeState, IMainDom mainDom, IKeepAliveSettings keepAliveSettings, IProfilingLogger logger, IServerRegistrar serverRegistrar) : base(runner, delayMilliseconds, periodMilliseconds) { - _runtime = runtime; + _runtimeState = runtimeState; + _mainDom = mainDom; _keepAliveSettings = keepAliveSettings; _logger = logger; + _serverRegistrar = serverRegistrar; if (_httpClient == null) _httpClient = new HttpClient(); } @@ -30,7 +34,7 @@ namespace Umbraco.Web.Scheduling public override async Task PerformRunAsync(CancellationToken token) { // not on replicas nor unknown role servers - switch (_runtime.ServerRole) + switch (_serverRegistrar.GetCurrentServerRole()) { case ServerRole.Replica: _logger.Debug("Does not run on replica servers."); @@ -41,7 +45,7 @@ namespace Umbraco.Web.Scheduling } // ensure we do not run if not main domain, but do NOT lock it - if (_runtime.IsMainDom == false) + if (_mainDom.IsMainDom == false) { _logger.Debug("Does not run if not MainDom."); return false; // do NOT repeat, going down @@ -54,7 +58,7 @@ namespace Umbraco.Web.Scheduling { if (keepAlivePingUrl.Contains("{umbracoApplicationUrl}")) { - var umbracoAppUrl = _runtime.ApplicationUrl.ToString(); + var umbracoAppUrl = _runtimeState.ApplicationUrl.ToString(); if (umbracoAppUrl.IsNullOrWhiteSpace()) { _logger.Warn("No umbracoApplicationUrl for service (yet), skip."); diff --git a/src/Umbraco.Core/Scheduling/TempFileCleanup.cs b/src/Umbraco.Core/Scheduling/TempFileCleanup.cs index aefaf605db..90bf4ee9eb 100644 --- a/src/Umbraco.Core/Scheduling/TempFileCleanup.cs +++ b/src/Umbraco.Core/Scheduling/TempFileCleanup.cs @@ -14,26 +14,26 @@ namespace Umbraco.Web.Scheduling { private readonly DirectoryInfo[] _tempFolders; private readonly TimeSpan _age; - private readonly IRuntimeState _runtime; + private readonly IMainDom _mainDom; private readonly IProfilingLogger _logger; public TempFileCleanup(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, IEnumerable tempFolders, TimeSpan age, - IRuntimeState runtime, IProfilingLogger logger) + IMainDom mainDom, IProfilingLogger logger) : base(runner, delayMilliseconds, periodMilliseconds) { //SystemDirectories.TempFileUploads _tempFolders = tempFolders.ToArray(); _age = age; - _runtime = runtime; + _mainDom = mainDom; _logger = logger; } public override bool PerformRun() { // ensure we do not run if not main domain - if (_runtime.IsMainDom == false) + if (_mainDom.IsMainDom == false) { _logger.Debug("Does not run if not MainDom."); return false; // do NOT repeat, going down diff --git a/src/Umbraco.Core/Services/IRuntime.cs b/src/Umbraco.Core/Services/IRuntime.cs index e846342dbc..4715068073 100644 --- a/src/Umbraco.Core/Services/IRuntime.cs +++ b/src/Umbraco.Core/Services/IRuntime.cs @@ -13,13 +13,15 @@ namespace Umbraco.Core /// /// The application register. /// The application factory. - IFactory Boot(IRegister register); + IFactory Configure(IRegister register); /// /// Gets the runtime state. /// IRuntimeState State { get; } + void Start(); + /// /// Terminates the runtime. /// diff --git a/src/Umbraco.Core/Services/IRuntimeState.cs b/src/Umbraco.Core/Services/IRuntimeState.cs index 565b2563e6..4b5e26651b 100644 --- a/src/Umbraco.Core/Services/IRuntimeState.cs +++ b/src/Umbraco.Core/Services/IRuntimeState.cs @@ -25,21 +25,6 @@ namespace Umbraco.Core /// SemVersion SemanticVersion { get; } - /// - /// Gets a value indicating whether the application is running in debug mode. - /// - bool Debug { get; } - - /// - /// Gets a value indicating whether the runtime is the current main domain. - /// - bool IsMainDom { get; } - - /// - /// Get the server's current role. - /// - ServerRole ServerRole { get; } - /// /// Gets the Umbraco application url. /// @@ -71,6 +56,5 @@ namespace Umbraco.Core /// BootFailedException BootFailedException { get; } - IMainDom MainDom { get; } } } diff --git a/src/Umbraco.Core/SimpleMainDom.cs b/src/Umbraco.Core/SimpleMainDom.cs index 87cc7bcff1..52ed6c1d91 100644 --- a/src/Umbraco.Core/SimpleMainDom.cs +++ b/src/Umbraco.Core/SimpleMainDom.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Hosting; namespace Umbraco.Core { @@ -16,6 +17,9 @@ namespace Umbraco.Core /// public bool IsMainDom { get; private set; } = true; + // always acquire + public bool Acquire(IHostingEnvironmentLifetime hostingEnvironment) => true; + /// public bool Register(Action release, int weight = 100) => Register(null, release, weight); diff --git a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs index 78b9589a2e..70b79fbeb0 100644 --- a/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/BatchedDatabaseServerMessenger.cs @@ -28,17 +28,18 @@ namespace Umbraco.Web private readonly IRequestAccessor _requestAccessor; public BatchedDatabaseServerMessenger( - IRuntimeState runtime, + IMainDom mainDom, IUmbracoDatabaseFactory databaseFactory, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, + IServerRegistrar serverRegistrar, DatabaseServerMessengerOptions options, IHostingEnvironment hostingEnvironment, CacheRefresherCollection cacheRefreshers, IRequestCache requestCache, IRequestAccessor requestAccessor) - : base(runtime, scopeProvider, sqlContext, proflog, true, options, hostingEnvironment, cacheRefreshers) + : base(mainDom, scopeProvider, sqlContext, proflog, serverRegistrar, true, options, hostingEnvironment, cacheRefreshers) { _databaseFactory = databaseFactory; _requestCache = requestCache; diff --git a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs index 2a24e6f318..4e183b9211 100644 --- a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs +++ b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs @@ -91,7 +91,6 @@ namespace Umbraco.Web.Compose private readonly BackgroundTaskRunner _processTaskRunner; private bool _started; private IBackgroundTask[] _tasks; - private IndexRebuilder _indexRebuilder; private readonly IRequestAccessor _requestAccessor; public DatabaseServerRegistrarAndMessengerComponent( @@ -100,14 +99,12 @@ namespace Umbraco.Web.Compose IServerMessenger serverMessenger, IServerRegistrationService registrationService, ILogger logger, - IHostingEnvironment hostingEnvironment, - IndexRebuilder indexRebuilder, + IHostingEnvironmentLifetime hostingEnvironment, IRequestAccessor requestAccessor) { _runtime = runtime; _logger = logger; _registrationService = registrationService; - _indexRebuilder = indexRebuilder; _requestAccessor = requestAccessor; // create task runner for DatabaseServerRegistrar diff --git a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs index d4e22bbfde..06b3cc0cc9 100644 --- a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs +++ b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs @@ -4,13 +4,13 @@ using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Manifest; -using Umbraco.Net; +using Umbraco.Core.Net; namespace Umbraco.Core.Compose { public sealed class ManifestWatcherComponent : IComponent { - private readonly IRuntimeState _runtimeState; + private readonly IHostingEnvironment _hosting; private readonly ILogger _logger; private readonly IIOHelper _ioHelper; private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime; @@ -19,9 +19,9 @@ namespace Umbraco.Core.Compose // package.manifest chances and restarts the application on any change private ManifestWatcher _mw; - public ManifestWatcherComponent(IRuntimeState runtimeState, ILogger logger, IIOHelper ioHelper, IUmbracoApplicationLifetime umbracoApplicationLifetime) + public ManifestWatcherComponent(IHostingEnvironment hosting, ILogger logger, IIOHelper ioHelper, IUmbracoApplicationLifetime umbracoApplicationLifetime) { - _runtimeState = runtimeState; + _hosting = hosting; _logger = logger; _ioHelper = ioHelper; _umbracoApplicationLifetime = umbracoApplicationLifetime; @@ -29,7 +29,7 @@ namespace Umbraco.Core.Compose public void Initialize() { - if (_runtimeState.Debug == false) return; + if (_hosting.IsDebugMode == false) return; //if (ApplicationContext.Current.IsConfigured == false || GlobalSettings.DebugMode == false) // return; diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs index 67cfcded92..1bf954e4c1 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs @@ -44,7 +44,7 @@ namespace Umbraco.Core.Runtime public override void Compose(Composition composition) { base.Compose(composition); - + // composers composition .ComposeRepositories() @@ -120,10 +120,11 @@ namespace Umbraco.Core.Runtime // project composition.RegisterUnique(factory => new DatabaseServerMessenger( - factory.GetInstance(), + factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), + factory.GetInstance(), true, new DatabaseServerMessengerOptions(), factory.GetInstance(), factory.GetInstance() diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs index 5cd51a174a..89ec036607 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Reflection; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; @@ -12,7 +11,6 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; -using Umbraco.Core.Sync; namespace Umbraco.Core.Runtime { @@ -25,12 +23,26 @@ namespace Umbraco.Core.Runtime { private ComponentCollection _components; private IFactory _factory; - private RuntimeState _state; + private readonly RuntimeState _state; private readonly IUmbracoBootPermissionChecker _umbracoBootPermissionChecker; private readonly IGlobalSettings _globalSettings; private readonly IConnectionStrings _connectionStrings; + /// + /// Constructor + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public CoreRuntime( Configs configs, IUmbracoVersion umbracoVersion, @@ -65,11 +77,7 @@ namespace Umbraco.Core.Runtime // runtime state // beware! must use '() => _factory.GetInstance()' and NOT '_factory.GetInstance' // as the second one captures the current value (null) and therefore fails - _state = new RuntimeState(Logger, - Configs.Global(), - new Lazy(() => mainDom), - new Lazy(() => _factory.GetInstance()), - UmbracoVersion, HostingEnvironment, BackOfficeInfo) + _state = new RuntimeState(Logger, Configs.Global(), UmbracoVersion, BackOfficeInfo) { Level = RuntimeLevel.Boot }; @@ -81,12 +89,13 @@ namespace Umbraco.Core.Runtime protected ILogger Logger { get; } protected IBackOfficeInfo BackOfficeInfo { get; } + public IDbProviderFactoryCreator DbProviderFactoryCreator { get; } /// /// Gets the profiler. /// - protected IProfiler Profiler { get; set; } + protected IProfiler Profiler { get; } /// /// Gets the profiling logger. @@ -109,10 +118,10 @@ namespace Umbraco.Core.Runtime /// public IRuntimeState State => _state; - public IMainDom MainDom { get; private set; } + public IMainDom MainDom { get; } /// - public virtual IFactory Boot(IRegister register) + public virtual IFactory Configure(IRegister register) { if (register is null) throw new ArgumentNullException(nameof(register)); @@ -140,28 +149,24 @@ namespace Umbraco.Core.Runtime // application environment ConfigureUnhandledException(); - ConfigureApplicationRootPath(); - - Boot(register, timer); + return _factory = Configure(register, timer); } - - return _factory; } /// - /// Boots the runtime within a timer. + /// Configure the runtime within a timer. /// - protected virtual IFactory Boot(IRegister register, DisposableTimer timer) + private IFactory Configure(IRegister register, DisposableTimer timer) { if (register is null) throw new ArgumentNullException(nameof(register)); if (timer is null) throw new ArgumentNullException(nameof(timer)); Composition composition = null; + IFactory factory = null; try { - // throws if not full-trust - _umbracoBootPermissionChecker.ThrowIfNotPermissions(); + // run handlers RuntimeOptions.DoRuntimeBoot(ProfilingLogger); @@ -179,15 +184,8 @@ namespace Umbraco.Core.Runtime composition = new Composition(register, typeLoader, ProfilingLogger, _state, Configs, IOHelper, appCaches); composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, MainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper, UmbracoVersion, DbProviderFactoryCreator, HostingEnvironment, BackOfficeInfo); - // run handlers - RuntimeOptions.DoRuntimeEssentials(composition, appCaches, typeLoader, databaseFactory); - - // register runtime-level services - // there should be none, really - this is here "just in case" - Compose(composition); - - // acquire the main domain - if this fails then anything that should be registered with MainDom will not operate - AcquireMainDom(MainDom); + // register ourselves (TODO: Should we put this in RegisterEssentials?) + composition.Register(_ => this, Lifetime.Singleton); // determine our runtime level DetermineRuntimeLevel(databaseFactory, ProfilingLogger); @@ -205,13 +203,7 @@ namespace Umbraco.Core.Runtime composers.Compose(); // create the factory - _factory = composition.CreateFactory(); - - // create & initialize the components - _components = _factory.GetInstance(); - _components.Initialize(); - - + factory = composition.CreateFactory(); } catch (Exception e) { @@ -228,11 +220,11 @@ namespace Umbraco.Core.Runtime // if something goes wrong above, we may end up with no factory // meaning nothing can get the runtime state, etc - so let's try // to make sure we have a factory - if (_factory == null) + if (factory == null) { try { - _factory = composition?.CreateFactory(); + factory = composition?.CreateFactory(); } catch { /* yea */ } } @@ -246,7 +238,29 @@ namespace Umbraco.Core.Runtime // throw a BootFailedException for every requests. } - return _factory; + return factory; + } + + public void Start() + { + // throws if not full-trust + _umbracoBootPermissionChecker.ThrowIfNotPermissions(); + + ConfigureApplicationRootPath(); + + // run handlers + RuntimeOptions.DoRuntimeEssentials(_factory); + + var hostingEnvironmentLifetime = _factory.TryGetInstance(); + if (hostingEnvironmentLifetime == null) + throw new InvalidOperationException($"An instance of {typeof(IHostingEnvironmentLifetime)} could not be resolved from the container, ensure that one if registered in your runtime before calling {nameof(IRuntime)}.{nameof(Start)}"); + + // acquire the main domain - if this fails then anything that should be registered with MainDom will not operate + AcquireMainDom(MainDom, _factory.GetInstance()); + + // create & initialize the components + _components = _factory.GetInstance(); + _components.Initialize(); } protected virtual void ConfigureUnhandledException() @@ -273,13 +287,13 @@ namespace Umbraco.Core.Runtime IOHelper.SetRootDirectory(path); } - private bool AcquireMainDom(IMainDom mainDom) + private bool AcquireMainDom(IMainDom mainDom, IHostingEnvironmentLifetime hostingEnvironmentLifetime) { using (var timer = ProfilingLogger.DebugDuration("Acquiring MainDom.", "Acquired.")) { try { - return mainDom.IsMainDom; + return mainDom.Acquire(hostingEnvironmentLifetime); } catch { @@ -338,12 +352,6 @@ namespace Umbraco.Core.Runtime _components?.Terminate(); } - /// - /// Composes the runtime. - /// - public virtual void Compose(Composition composition) - { - } #region Getters @@ -384,5 +392,6 @@ namespace Umbraco.Core.Runtime #endregion + } } diff --git a/src/Umbraco.Infrastructure/Runtime/WebRuntime.cs b/src/Umbraco.Infrastructure/Runtime/WebRuntime.cs index 2f45a3e437..fc2a019023 100644 --- a/src/Umbraco.Infrastructure/Runtime/WebRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/WebRuntime.cs @@ -40,7 +40,7 @@ namespace Umbraco.Web.Runtime } /// - public override IFactory Boot(IRegister register) + public override IFactory Configure(IRegister register) { var profilingLogger = new ProfilingLogger(Logger, Profiler); @@ -57,7 +57,7 @@ namespace Umbraco.Web.Runtime NetworkHelper.MachineName); Logger.Debug("Runtime: {Runtime}", GetType().FullName); - var factory = base.Boot(register); + var factory = base.Configure(register); // now (and only now) is the time to switch over to perWebRequest scopes. // up until that point we may not have a request, and scoped services would diff --git a/src/Umbraco.Infrastructure/RuntimeOptions.cs b/src/Umbraco.Infrastructure/RuntimeOptions.cs index 23abd474a4..562a7e3c5c 100644 --- a/src/Umbraco.Infrastructure/RuntimeOptions.cs +++ b/src/Umbraco.Infrastructure/RuntimeOptions.cs @@ -16,7 +16,7 @@ namespace Umbraco.Core public static class RuntimeOptions { private static List> _onBoot; - private static List> _onEssentials; + private static List> _onEssentials; /// /// Executes the RuntimeBoot handlers. @@ -33,13 +33,13 @@ namespace Umbraco.Core /// /// Executes the RuntimeEssentials handlers. /// - internal static void DoRuntimeEssentials(Composition composition, AppCaches appCaches, TypeLoader typeLoader, IUmbracoDatabaseFactory databaseFactory) + internal static void DoRuntimeEssentials(IFactory factory) { if (_onEssentials== null) return; foreach (var action in _onEssentials) - action(composition, appCaches, typeLoader, databaseFactory); + action(factory); } /// @@ -64,10 +64,10 @@ namespace Umbraco.Core /// essential things (AppCaches, a TypeLoader, and a database factory) but /// before anything else. /// - public static void OnRuntimeEssentials(Action action) + public static void OnRuntimeEssentials(Action action) { if (_onEssentials == null) - _onEssentials = new List>(); + _onEssentials = new List>(); _onEssentials.Add(action); } } diff --git a/src/Umbraco.Infrastructure/RuntimeState.cs b/src/Umbraco.Infrastructure/RuntimeState.cs index 420fba7ffc..e0099c5e7e 100644 --- a/src/Umbraco.Infrastructure/RuntimeState.cs +++ b/src/Umbraco.Infrastructure/RuntimeState.cs @@ -22,44 +22,22 @@ namespace Umbraco.Core private readonly ILogger _logger; private readonly IGlobalSettings _globalSettings; private readonly ConcurrentHashSet _applicationUrls = new ConcurrentHashSet(); - private readonly Lazy _mainDom; - private readonly Lazy _serverRegistrar; private readonly IUmbracoVersion _umbracoVersion; - private readonly IHostingEnvironment _hostingEnvironment; private readonly IBackOfficeInfo _backOfficeInfo; /// /// Initializes a new instance of the class. /// public RuntimeState(ILogger logger, IGlobalSettings globalSettings, - Lazy mainDom, Lazy serverRegistrar, IUmbracoVersion umbracoVersion, - IHostingEnvironment hostingEnvironment, + IUmbracoVersion umbracoVersion, IBackOfficeInfo backOfficeInfo) { _logger = logger; _globalSettings = globalSettings; - _mainDom = mainDom; - _serverRegistrar = serverRegistrar; _umbracoVersion = umbracoVersion; - _hostingEnvironment = hostingEnvironment; _backOfficeInfo = backOfficeInfo; } - /// - /// Gets the server registrar. - /// - /// - /// This is NOT exposed in the interface. - /// - private IServerRegistrar ServerRegistrar => _serverRegistrar.Value; - - /// - /// Gets the application MainDom. - /// - /// - /// This is NOT exposed in the interface as MainDom is internal. - /// - public IMainDom MainDom => _mainDom.Value; /// public Version Version => _umbracoVersion.Current; @@ -70,23 +48,14 @@ namespace Umbraco.Core /// public SemVersion SemanticVersion => _umbracoVersion.SemanticVersion; - /// - public bool Debug => _hostingEnvironment.IsDebugMode; - - /// - public bool IsMainDom => MainDom.IsMainDom; - - /// - public ServerRole ServerRole => ServerRegistrar.GetCurrentServerRole(); - /// public Uri ApplicationUrl { get; private set; } /// - public string CurrentMigrationState { get; internal set; } + public string CurrentMigrationState { get; private set; } /// - public string FinalMigrationState { get; internal set; } + public string FinalMigrationState { get; private set; } /// public RuntimeLevel Level { get; internal set; } = RuntimeLevel.Unknown; @@ -248,7 +217,7 @@ namespace Umbraco.Core Reason = RuntimeLevelReason.UpgradeMigrations; } - protected virtual bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger) + private bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory, ILogger logger) { var upgrader = new Upgrader(new UmbracoPlan(_umbracoVersion, _globalSettings)); var stateValueKey = upgrader.StateValueKey; diff --git a/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs b/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs index 0b5b81319f..31884992f7 100644 --- a/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs +++ b/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs @@ -81,7 +81,7 @@ namespace Umbraco.Web.Scheduling private readonly string _logPrefix; private readonly BackgroundTaskRunnerOptions _options; private readonly ILogger _logger; - private readonly IHostingEnvironment _hostingEnvironment; + private readonly IHostingEnvironmentLifetime _hostingEnvironment; private readonly object _locker = new object(); private readonly BufferBlock _tasks = new BufferBlock(new DataflowBlockOptions()); @@ -105,7 +105,7 @@ namespace Umbraco.Web.Scheduling /// A logger. /// The hosting environment /// An optional main domain hook. - public BackgroundTaskRunner(ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null) + public BackgroundTaskRunner(ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null) : this(typeof(T).FullName, new BackgroundTaskRunnerOptions(), logger, hostingEnvironment, hook) { } @@ -116,7 +116,7 @@ namespace Umbraco.Web.Scheduling /// A logger. /// The hosting environment /// An optional main domain hook. - public BackgroundTaskRunner(string name, ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null) + public BackgroundTaskRunner(string name, ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null) : this(name, new BackgroundTaskRunnerOptions(), logger, hostingEnvironment, hook) { } @@ -127,7 +127,7 @@ namespace Umbraco.Web.Scheduling /// A logger. /// The hosting environment /// An optional main domain hook. - public BackgroundTaskRunner(BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null) + public BackgroundTaskRunner(BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null) : this(typeof(T).FullName, options, logger, hostingEnvironment, hook) { } @@ -139,7 +139,7 @@ namespace Umbraco.Web.Scheduling /// A logger. /// The hosting environment /// An optional main domain hook. - public BackgroundTaskRunner(string name, BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironment hostingEnvironment, MainDomHook hook = null) + public BackgroundTaskRunner(string name, BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null) { _options = options ?? throw new ArgumentNullException(nameof(options)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); diff --git a/src/Umbraco.Infrastructure/Scheduling/HealthCheckNotifier.cs b/src/Umbraco.Infrastructure/Scheduling/HealthCheckNotifier.cs index 04c1571b3b..e7692b851a 100644 --- a/src/Umbraco.Infrastructure/Scheduling/HealthCheckNotifier.cs +++ b/src/Umbraco.Infrastructure/Scheduling/HealthCheckNotifier.cs @@ -11,22 +11,27 @@ namespace Umbraco.Web.Scheduling { public class HealthCheckNotifier : RecurringTaskBase { - private readonly IRuntimeState _runtimeState; + private readonly IMainDom _mainDom; private readonly HealthCheckCollection _healthChecks; private readonly HealthCheckNotificationMethodCollection _notifications; private readonly IProfilingLogger _logger; private readonly IHealthChecksSettings _healthChecksSettingsConfig; + private readonly IServerRegistrar _serverRegistrar; + private readonly IRuntimeState _runtimeState; public HealthCheckNotifier(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications, - IRuntimeState runtimeState, IProfilingLogger logger, IHealthChecksSettings healthChecksSettingsConfig) + IMainDom mainDom, IProfilingLogger logger, IHealthChecksSettings healthChecksSettingsConfig, IServerRegistrar serverRegistrar, + IRuntimeState runtimeState) : base(runner, delayMilliseconds, periodMilliseconds) { _healthChecks = healthChecks; _notifications = notifications; - _runtimeState = runtimeState; + _mainDom = mainDom; _logger = logger; _healthChecksSettingsConfig = healthChecksSettingsConfig; + _serverRegistrar = serverRegistrar; + _runtimeState = runtimeState; } public override async Task PerformRunAsync(CancellationToken token) @@ -34,7 +39,7 @@ namespace Umbraco.Web.Scheduling if (_runtimeState.Level != RuntimeLevel.Run) return true; // repeat... - switch (_runtimeState.ServerRole) + switch (_serverRegistrar.GetCurrentServerRole()) { case ServerRole.Replica: _logger.Debug("Does not run on replica servers."); @@ -45,7 +50,7 @@ namespace Umbraco.Web.Scheduling } // ensure we do not run if not main domain, but do NOT lock it - if (_runtimeState.IsMainDom == false) + if (_mainDom.IsMainDom == false) { _logger.Debug("Does not run if not MainDom."); return false; // do NOT repeat, going down diff --git a/src/Umbraco.Infrastructure/Scheduling/LogScrubber.cs b/src/Umbraco.Infrastructure/Scheduling/LogScrubber.cs index 563d79a193..aaf09dbe8f 100644 --- a/src/Umbraco.Infrastructure/Scheduling/LogScrubber.cs +++ b/src/Umbraco.Infrastructure/Scheduling/LogScrubber.cs @@ -11,17 +11,19 @@ namespace Umbraco.Web.Scheduling public class LogScrubber : RecurringTaskBase { - private readonly IRuntimeState _runtime; + private readonly IMainDom _mainDom; + private readonly IServerRegistrar _serverRegistrar; private readonly IAuditService _auditService; private readonly ILoggingSettings _settings; private readonly IProfilingLogger _logger; private readonly IScopeProvider _scopeProvider; public LogScrubber(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - IRuntimeState runtime, IAuditService auditService, ILoggingSettings settings, IScopeProvider scopeProvider, IProfilingLogger logger) + IMainDom mainDom, IServerRegistrar serverRegistrar, IAuditService auditService, ILoggingSettings settings, IScopeProvider scopeProvider, IProfilingLogger logger) : base(runner, delayMilliseconds, periodMilliseconds) { - _runtime = runtime; + _mainDom = mainDom; + _serverRegistrar = serverRegistrar; _auditService = auditService; _settings = settings; _scopeProvider = scopeProvider; @@ -53,7 +55,7 @@ namespace Umbraco.Web.Scheduling public override bool PerformRun() { - switch (_runtime.ServerRole) + switch (_serverRegistrar.GetCurrentServerRole()) { case ServerRole.Replica: _logger.Debug("Does not run on replica servers."); @@ -64,7 +66,7 @@ namespace Umbraco.Web.Scheduling } // ensure we do not run if not main domain, but do NOT lock it - if (_runtime.IsMainDom == false) + if (_mainDom.IsMainDom == false) { _logger.Debug("Does not run if not MainDom."); return false; // do NOT repeat, going down diff --git a/src/Umbraco.Infrastructure/Scheduling/ScheduledPublishing.cs b/src/Umbraco.Infrastructure/Scheduling/ScheduledPublishing.cs index b074704033..fea16999fd 100644 --- a/src/Umbraco.Infrastructure/Scheduling/ScheduledPublishing.cs +++ b/src/Umbraco.Infrastructure/Scheduling/ScheduledPublishing.cs @@ -10,16 +10,20 @@ namespace Umbraco.Web.Scheduling public class ScheduledPublishing : RecurringTaskBase { private readonly IRuntimeState _runtime; + private readonly IMainDom _mainDom; + private readonly IServerRegistrar _serverRegistrar; private readonly IContentService _contentService; private readonly IUmbracoContextFactory _umbracoContextFactory; private readonly ILogger _logger; private readonly IServerMessenger _serverMessenger; public ScheduledPublishing(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - IRuntimeState runtime, IContentService contentService, IUmbracoContextFactory umbracoContextFactory, ILogger logger, IServerMessenger serverMessenger) + IRuntimeState runtime, IMainDom mainDom, IServerRegistrar serverRegistrar, IContentService contentService, IUmbracoContextFactory umbracoContextFactory, ILogger logger, IServerMessenger serverMessenger) : base(runner, delayMilliseconds, periodMilliseconds) { _runtime = runtime; + _mainDom = mainDom; + _serverRegistrar = serverRegistrar; _contentService = contentService; _umbracoContextFactory = umbracoContextFactory; _logger = logger; @@ -31,7 +35,7 @@ namespace Umbraco.Web.Scheduling if (Suspendable.ScheduledPublishing.CanRun == false) return true; // repeat, later - switch (_runtime.ServerRole) + switch (_serverRegistrar.GetCurrentServerRole()) { case ServerRole.Replica: _logger.Debug("Does not run on replica servers."); @@ -42,7 +46,7 @@ namespace Umbraco.Web.Scheduling } // ensure we do not run if not main domain, but do NOT lock it - if (_runtime.IsMainDom == false) + if (_mainDom.IsMainDom == false) { _logger.Debug("Does not run if not MainDom."); return false; // do NOT repeat, going down diff --git a/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs b/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs index c8ff67579a..c867d81d69 100644 --- a/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs +++ b/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs @@ -26,10 +26,12 @@ namespace Umbraco.Web.Scheduling private const int OneHourMilliseconds = 3600000; private readonly IRuntimeState _runtime; + private readonly IMainDom _mainDom; + private readonly IServerRegistrar _serverRegistrar; private readonly IContentService _contentService; private readonly IAuditService _auditService; private readonly IProfilingLogger _logger; - private readonly IHostingEnvironment _hostingEnvironment; + private readonly IHostingEnvironmentLifetime _hostingEnvironment; private readonly IScopeProvider _scopeProvider; private readonly HealthCheckCollection _healthChecks; private readonly HealthCheckNotificationMethodCollection _notifications; @@ -43,7 +45,6 @@ namespace Umbraco.Web.Scheduling private BackgroundTaskRunner _keepAliveRunner; private BackgroundTaskRunner _publishingRunner; - private BackgroundTaskRunner _tasksRunner; private BackgroundTaskRunner _scrubberRunner; private BackgroundTaskRunner _fileCleanupRunner; private BackgroundTaskRunner _healthCheckRunner; @@ -52,15 +53,17 @@ namespace Umbraco.Web.Scheduling private object _locker = new object(); private IBackgroundTask[] _tasks; - public SchedulerComponent(IRuntimeState runtime, + public SchedulerComponent(IRuntimeState runtime, IMainDom mainDom, IServerRegistrar serverRegistrar, IContentService contentService, IAuditService auditService, HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications, IScopeProvider scopeProvider, IUmbracoContextFactory umbracoContextFactory, IProfilingLogger logger, - IHostingEnvironment hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig, + IHostingEnvironmentLifetime hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig, IIOHelper ioHelper, IServerMessenger serverMessenger, IRequestAccessor requestAccessor, ILoggingSettings loggingSettings, IKeepAliveSettings keepAliveSettings) { _runtime = runtime; + _mainDom = mainDom; + _serverRegistrar = serverRegistrar; _contentService = contentService; _auditService = auditService; _scopeProvider = scopeProvider; @@ -83,7 +86,6 @@ namespace Umbraco.Web.Scheduling // backgrounds runners are web aware, if the app domain dies, these tasks will wind down correctly _keepAliveRunner = new BackgroundTaskRunner("KeepAlive", _logger, _hostingEnvironment); _publishingRunner = new BackgroundTaskRunner("ScheduledPublishing", _logger, _hostingEnvironment); - _tasksRunner = new BackgroundTaskRunner("ScheduledTasks", _logger, _hostingEnvironment); _scrubberRunner = new BackgroundTaskRunner("LogScrubber", _logger, _hostingEnvironment); _fileCleanupRunner = new BackgroundTaskRunner("TempFileCleanup", _logger, _hostingEnvironment); _healthCheckRunner = new BackgroundTaskRunner("HealthCheckNotifier", _logger, _hostingEnvironment); @@ -138,7 +140,7 @@ namespace Umbraco.Web.Scheduling { // ping/keepalive // on all servers - var task = new KeepAlive(_keepAliveRunner, DefaultDelayMilliseconds, FiveMinuteMilliseconds, _runtime, keepAliveSettings, _logger); + var task = new KeepAlive(_keepAliveRunner, DefaultDelayMilliseconds, FiveMinuteMilliseconds, _runtime, _mainDom, keepAliveSettings, _logger, _serverRegistrar); _keepAliveRunner.TryAdd(task); return task; } @@ -147,7 +149,7 @@ namespace Umbraco.Web.Scheduling { // scheduled publishing/unpublishing // install on all, will only run on non-replica servers - var task = new ScheduledPublishing(_publishingRunner, DefaultDelayMilliseconds, OneMinuteMilliseconds, _runtime, _contentService, _umbracoContextFactory, _logger, _serverMessenger); + var task = new ScheduledPublishing(_publishingRunner, DefaultDelayMilliseconds, OneMinuteMilliseconds, _runtime, _mainDom, _serverRegistrar, _contentService, _umbracoContextFactory, _logger, _serverMessenger); _publishingRunner.TryAdd(task); return task; } @@ -173,7 +175,7 @@ namespace Umbraco.Web.Scheduling } var periodInMilliseconds = healthCheckSettingsConfig.NotificationSettings.PeriodInHours * 60 * 60 * 1000; - var task = new HealthCheckNotifier(_healthCheckRunner, delayInMilliseconds, periodInMilliseconds, healthChecks, notifications, _runtime, logger, _healthChecksSettingsConfig); + var task = new HealthCheckNotifier(_healthCheckRunner, delayInMilliseconds, periodInMilliseconds, healthChecks, notifications, _mainDom, logger, _healthChecksSettingsConfig, _serverRegistrar, _runtime); _healthCheckRunner.TryAdd(task); return task; } @@ -182,7 +184,7 @@ namespace Umbraco.Web.Scheduling { // log scrubbing // install on all, will only run on non-replica servers - var task = new LogScrubber(_scrubberRunner, DefaultDelayMilliseconds, LogScrubber.GetLogScrubbingInterval(), _runtime, _auditService, settings, _scopeProvider, _logger); + var task = new LogScrubber(_scrubberRunner, DefaultDelayMilliseconds, LogScrubber.GetLogScrubbingInterval(), _mainDom, _serverRegistrar, _auditService, settings, _scopeProvider, _logger); _scrubberRunner.TryAdd(task); return task; } @@ -194,7 +196,7 @@ namespace Umbraco.Web.Scheduling var task = new TempFileCleanup(_fileCleanupRunner, DefaultDelayMilliseconds, OneHourMilliseconds, new[] { new DirectoryInfo(_ioHelper.MapPath(Constants.SystemDirectories.TempFileUploads)) }, TimeSpan.FromDays(1), //files that are over a day old - _runtime, _logger); + _mainDom, _logger); _scrubberRunner.TryAdd(task); return task; } diff --git a/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs b/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs index 2c964a2723..fa697a4743 100644 --- a/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs +++ b/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs @@ -18,10 +18,10 @@ namespace Umbraco.Web.Search private readonly IndexRebuilder _indexRebuilder; private readonly IMainDom _mainDom; private readonly IProfilingLogger _logger; - private readonly IHostingEnvironment _hostingEnvironment; + private readonly IHostingEnvironmentLifetime _hostingEnvironment; private static BackgroundTaskRunner _rebuildOnStartupRunner; - public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IHostingEnvironment hostingEnvironment, IndexRebuilder indexRebuilder) + public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IHostingEnvironmentLifetime hostingEnvironment, IndexRebuilder indexRebuilder) { _mainDom = mainDom; _logger = logger; @@ -32,8 +32,6 @@ namespace Umbraco.Web.Search /// /// Called to rebuild empty indexes on startup /// - /// - /// /// /// public void RebuildIndexes(bool onlyEmptyIndexes, int waitMilliseconds = 0) diff --git a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs index 5a46a37d43..c915013162 100644 --- a/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs +++ b/src/Umbraco.Infrastructure/Sync/DatabaseServerMessenger.cs @@ -28,10 +28,11 @@ namespace Umbraco.Core.Sync // public class DatabaseServerMessenger : ServerMessengerBase, IDatabaseServerMessenger { - private readonly IRuntimeState _runtime; + private readonly IMainDom _mainDom; private readonly ManualResetEvent _syncIdle; private readonly object _locko = new object(); private readonly IProfilingLogger _profilingLogger; + private readonly IServerRegistrar _serverRegistrar; private readonly IHostingEnvironment _hostingEnvironment; private readonly CacheRefresherCollection _cacheRefreshers; private readonly ISqlContext _sqlContext; @@ -46,14 +47,15 @@ namespace Umbraco.Core.Sync public DatabaseServerMessengerOptions Options { get; } public DatabaseServerMessenger( - IRuntimeState runtime, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, + IMainDom mainDom, IScopeProvider scopeProvider, ISqlContext sqlContext, IProfilingLogger proflog, IServerRegistrar serverRegistrar, bool distributedEnabled, DatabaseServerMessengerOptions options, IHostingEnvironment hostingEnvironment, CacheRefresherCollection cacheRefreshers) : base(distributedEnabled) { ScopeProvider = scopeProvider ?? throw new ArgumentNullException(nameof(scopeProvider)); _sqlContext = sqlContext; - _runtime = runtime; + _mainDom = mainDom; _profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog)); + _serverRegistrar = serverRegistrar; _hostingEnvironment = hostingEnvironment; _cacheRefreshers = cacheRefreshers; Logger = proflog; @@ -126,7 +128,7 @@ namespace Umbraco.Core.Sync const int weight = 10; - var registered = _runtime.MainDom.Register( + var registered = _mainDom.Register( () => { lock (_locko) @@ -262,7 +264,7 @@ namespace Umbraco.Core.Sync _lastPruned = _lastSync; - switch (_runtime.ServerRole) + switch (_serverRegistrar.GetCurrentServerRole()) { case ServerRole.Single: case ServerRole.Master: diff --git a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs index 5db79de977..3c189cc045 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs @@ -42,7 +42,7 @@ namespace Umbraco.ModelsBuilder.Embedded private static readonly string[] OurFiles = { "models.hash", "models.generated.cs", "all.generated.cs", "all.dll.path", "models.err" }; private readonly IModelsBuilderConfig _config; - private readonly IHostingEnvironment _hostingEnvironment; + private readonly IHostingEnvironmentLifetime _hostingLifetime; private readonly IIOHelper _ioHelper; private readonly ModelsGenerationError _errors; @@ -51,12 +51,13 @@ namespace Umbraco.ModelsBuilder.Embedded IProfilingLogger logger, IModelsBuilderConfig config, IHostingEnvironment hostingEnvironment, + IHostingEnvironmentLifetime hostingLifetime, IIOHelper ioHelper) { _umbracoServices = umbracoServices; _logger = logger; _config = config; - _hostingEnvironment = hostingEnvironment; + _hostingLifetime = hostingLifetime; _ioHelper = ioHelper; _errors = new ModelsGenerationError(config, ioHelper); _ver = 1; // zero is for when we had no version @@ -64,7 +65,7 @@ namespace Umbraco.ModelsBuilder.Embedded RazorBuildProvider.CodeGenerationStarted += RazorBuildProvider_CodeGenerationStarted; - if (!_hostingEnvironment.IsHosted) return; + if (!hostingEnvironment.IsHosted) return; var modelsDirectory = _config.ModelsDirectoryAbsolute(_ioHelper); if (!Directory.Exists(modelsDirectory)) @@ -73,7 +74,7 @@ namespace Umbraco.ModelsBuilder.Embedded // BEWARE! if the watcher is not properly released then for some reason the // BuildManager will start confusing types - using a 'registered object' here // though we should probably plug into Umbraco's MainDom - which is internal - _hostingEnvironment.RegisterObject(this); + _hostingLifetime.RegisterObject(this); _watcher = new FileSystemWatcher(modelsDirectory); _watcher.Changed += WatcherOnChanged; _watcher.EnableRaisingEvents = true; @@ -677,7 +678,7 @@ namespace Umbraco.ModelsBuilder.Embedded { _watcher.EnableRaisingEvents = false; _watcher.Dispose(); - _hostingEnvironment.UnregisterObject(this); + _hostingLifetime.UnregisterObject(this); } #endregion diff --git a/src/Umbraco.Tests.Common/TestHelperBase.cs b/src/Umbraco.Tests.Common/TestHelperBase.cs index 536bebee56..76aa38e246 100644 --- a/src/Umbraco.Tests.Common/TestHelperBase.cs +++ b/src/Umbraco.Tests.Common/TestHelperBase.cs @@ -12,11 +12,11 @@ using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Net; using Umbraco.Core.Persistence; using Umbraco.Core.Serialization; using Umbraco.Core.Strings; using Umbraco.Core.Sync; -using Umbraco.Net; using Umbraco.Web; using Umbraco.Web.Routing; @@ -31,7 +31,7 @@ namespace Umbraco.Tests.Common private UriUtility _uriUtility; private IIOHelper _ioHelper; - public TestHelperBase(Assembly entryAssembly) + protected TestHelperBase(Assembly entryAssembly) { SettingsForTests = new SettingsForTests(); MainDom = new SimpleMainDom(); @@ -52,12 +52,8 @@ namespace Umbraco.Tests.Common return new RuntimeState( Mock.Of(), Mock.Of(), - new Lazy(), - new Lazy(), GetUmbracoVersion(), - GetHostingEnvironment(), - GetBackOfficeInfo() - ); + GetBackOfficeInfo()); } public abstract IBackOfficeInfo GetBackOfficeInfo(); @@ -132,6 +128,7 @@ namespace Umbraco.Tests.Common } public abstract IHostingEnvironment GetHostingEnvironment(); + public abstract IHostingEnvironmentLifetime GetHostingEnvironmentLifetime(); public abstract IIpResolver GetIpResolver(); diff --git a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs index 2d86122770..b0b664484b 100644 --- a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs @@ -1,31 +1,17 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using System; +using System; using System.Collections.Generic; using System.Data.Common; using System.Data.SqlClient; using System.IO; -using Umbraco.Core.Persistence; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using Umbraco.Tests.Integration.Testing; -namespace Umbraco.Tests.Integration +namespace Umbraco.Tests.Integration.Implementations { public static class HostBuilderExtensions { - - /// - /// Ensures the lifetime of the host ends as soon as code executes - /// - /// - /// - public static IHostBuilder UseTestLifetime(this IHostBuilder hostBuilder) - { - hostBuilder.ConfigureServices((context, collection) => collection.AddSingleton()); - return hostBuilder; - } - public static IHostBuilder UseLocalDb(this IHostBuilder hostBuilder, string dbFilePath) { // Need to register SqlClient manually diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index 4c37903b0c..f1aa53694c 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -8,10 +8,11 @@ using System.Net; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Diagnostics; +using Umbraco.Core.Hosting; using Umbraco.Core.Logging; +using Umbraco.Core.Net; using Umbraco.Core.Persistence; using Umbraco.Core.Runtime; -using Umbraco.Net; using Umbraco.Tests.Common; using Umbraco.Web.BackOffice; using Umbraco.Web.BackOffice.AspNetCore; @@ -19,11 +20,11 @@ using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment; namespace Umbraco.Tests.Integration.Implementations { - public class TestHelper : TestHelperBase { private IBackOfficeInfo _backOfficeInfo; private readonly IHostingEnvironment _hostingEnvironment; + private readonly IHostingEnvironmentLifetime _hostingLifetime; private readonly IIpResolver _ipResolver; private readonly IWebHostEnvironment _hostEnvironment; private readonly IHttpContextAccessor _httpContextAccessor; @@ -40,11 +41,12 @@ namespace Umbraco.Tests.Integration.Implementations && x.ContentRootPath == CurrentAssemblyDirectory && x.WebRootPath == CurrentAssemblyDirectory); // same folder for now? - _hostingEnvironment = new AspNetCoreHostingEnvironment( + _hostingEnvironment = new TestHostingEnvironment( SettingsForTests.GetDefaultHostingSettings(), _hostEnvironment, - _httpContextAccessor, - Mock.Of()); + _httpContextAccessor); + + _hostingLifetime = new AspNetCoreHostingEnvironmentLifetime(Mock.Of()); Logger = new ProfilingLogger(new ConsoleLogger(new MessageTemplates()), Profiler); } @@ -75,7 +77,9 @@ namespace Umbraco.Tests.Integration.Implementations } public override IHostingEnvironment GetHostingEnvironment() => _hostingEnvironment; + public override IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() => _hostingLifetime; public override IIpResolver GetIpResolver() => _ipResolver; + } } diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs b/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs new file mode 100644 index 0000000000..491b7e5480 --- /dev/null +++ b/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs @@ -0,0 +1,23 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Umbraco.Core.Configuration; +using Umbraco.Web.BackOffice.AspNetCore; + +namespace Umbraco.Tests.Integration.Implementations +{ + + public class TestHostingEnvironment : AspNetCoreHostingEnvironment, Umbraco.Core.Hosting.IHostingEnvironment + { + public TestHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContextAccessor) : base(hostingSettings, webHostEnvironment, httpContextAccessor) + { + } + + /// + /// Override for tests since we are not hosted + /// + /// + /// This is specifically used by IOHelper and we want this to return false so that the root path is manually calcualted which is what we want for tests. + /// + bool Umbraco.Core.Hosting.IHostingEnvironment.IsHosted { get; } = false; + } +} diff --git a/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs b/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs index 063644490b..a18360eff9 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestLifetime.cs @@ -1,8 +1,8 @@ -using Microsoft.Extensions.Hosting; -using System.Threading; +using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; -namespace Umbraco.Tests.Integration +namespace Umbraco.Tests.Integration.Implementations { /// /// Ensures the host lifetime ends as soon as code execution is done diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index dae4d0cbb8..c9e0e94481 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -10,6 +10,7 @@ using NUnit.Framework; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Composing.LightInject; @@ -46,27 +47,36 @@ namespace Umbraco.Tests.Integration /// Manually configure the containers/dependencies and call Boot on Core runtime /// [Test] - public void BootCoreRuntime() + public void Boot_Core_Runtime() { // LightInject / Umbraco var container = UmbracoServiceProviderFactory.CreateServiceContainer(); var serviceProviderFactory = new UmbracoServiceProviderFactory(container); var umbracoContainer = serviceProviderFactory.GetContainer(); - // Create the core runtime + // Special case since we are not using the Generic Host, we need to manually add an AspNetCore service to the container + umbracoContainer.Register(x => Mock.Of()); + var testHelper = new TestHelper(); + + // Create the core runtime var coreRuntime = new CoreRuntime(testHelper.GetConfigs(), testHelper.GetUmbracoVersion(), testHelper.IOHelper, testHelper.Logger, testHelper.Profiler, testHelper.UmbracoBootPermissionChecker, testHelper.GetHostingEnvironment(), testHelper.GetBackOfficeInfo(), testHelper.DbProviderFactoryCreator, testHelper.MainDom, testHelper.GetTypeFinder()); - // boot it! - var factory = coreRuntime.Boot(umbracoContainer); + // boot it! + var factory = coreRuntime.Configure(umbracoContainer); Assert.IsTrue(coreRuntime.MainDom.IsMainDom); Assert.IsNull(coreRuntime.State.BootFailedException); Assert.AreEqual(RuntimeLevel.Install, coreRuntime.State.Level); Assert.IsTrue(MyComposer.IsComposed); + Assert.IsFalse(MyComponent.IsInit); + Assert.IsFalse(MyComponent.IsTerminated); + + coreRuntime.Start(); + Assert.IsTrue(MyComponent.IsInit); Assert.IsFalse(MyComponent.IsTerminated); @@ -78,7 +88,7 @@ namespace Umbraco.Tests.Integration } /// - /// Calling AddUmbracoCore to configure the container and boot the core runtime within a generic host + /// Calling AddUmbracoCore to configure the container /// [Test] public async Task AddUmbracoCore() @@ -99,22 +109,106 @@ namespace Umbraco.Tests.Integration }); var host = await hostBuilder.StartAsync(); + var app = new ApplicationBuilder(host.Services); // assert results - var runtimeState = umbracoContainer.GetInstance(); - var mainDom = umbracoContainer.GetInstance(); + var runtimeState = app.ApplicationServices.GetRequiredService(); + var mainDom = app.ApplicationServices.GetRequiredService(); + + Assert.IsFalse(mainDom.IsMainDom); // We haven't "Started" the runtime yet + Assert.IsNull(runtimeState.BootFailedException); + Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); + Assert.IsFalse(MyComponent.IsInit); // We haven't "Started" the runtime yet + + await host.StopAsync(); + + Assert.IsFalse(MyComponent.IsTerminated); // we didn't "Start" the runtime so nothing was registered for shutdown + } + + /// + /// Calling AddUmbracoCore to configure the container and UseUmbracoCore to start the runtime + /// + /// + [Test] + public async Task UseUmbracoCore() + { + var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); + var testHelper = new TestHelper(); + + var hostBuilder = new HostBuilder() + .UseUmbraco(serviceProviderFactory) + .ConfigureServices((hostContext, services) => + { + AddRequiredNetCoreServices(services, testHelper); + + // Add it! + services.AddUmbracoConfiguration(); + services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + }); + + var host = await hostBuilder.StartAsync(); + var app = new ApplicationBuilder(host.Services); + + app.UseUmbracoCore(); + + + // assert results + var runtimeState = app.ApplicationServices.GetRequiredService(); + var mainDom = app.ApplicationServices.GetRequiredService(); Assert.IsTrue(mainDom.IsMainDom); Assert.IsNull(runtimeState.BootFailedException); Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); Assert.IsTrue(MyComponent.IsInit); - Assert.IsFalse(MyComponent.IsTerminated); await host.StopAsync(); Assert.IsTrue(MyComponent.IsTerminated); } + [Test] + public async Task Install_Database() + { + var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); + var testHelper = new TestHelper(); + + var hostBuilder = new HostBuilder() + //TODO: Need to have a configured umb version for the runtime state + .UseLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb")) + .UseUmbraco(serviceProviderFactory) + .ConfigureServices((hostContext, services) => + { + AddRequiredNetCoreServices(services, testHelper); + + // Add it! + services.AddUmbracoConfiguration(); + services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + }); + + var host = await hostBuilder.StartAsync(); + var app = new ApplicationBuilder(host.Services); + + app.UseUmbracoCore(); + + + var runtimeState = (RuntimeState)app.ApplicationServices.GetRequiredService(); + Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); + + var dbBuilder = app.ApplicationServices.GetRequiredService(); + Assert.IsNotNull(dbBuilder); + + var canConnect = dbBuilder.CanConnectToDatabase; + Assert.IsTrue(canConnect); + + var dbResult = dbBuilder.CreateSchemaAndData(); + Assert.IsTrue(dbResult.Success); + + // TODO: Get this to work ... but to do that we need to mock or pass in a current umbraco version + //var dbFactory = app.ApplicationServices.GetRequiredService(); + //var profilingLogger = app.ApplicationServices.GetRequiredService(); + //runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger); + //Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level); + } [Ignore("This test just shows that resolving services from the container before the host is done resolves 2 different instances")] [Test] @@ -128,6 +222,8 @@ namespace Umbraco.Tests.Integration .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => { + // TODO: Try to re-register the service as a callback and see if it resolves to the same instance + lifetime1 = services.BuildServiceProvider().GetRequiredService(); }); @@ -141,46 +237,6 @@ namespace Umbraco.Tests.Integration } - [Test] - public async Task UseUmbracoCore() - { - var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); - var testHelper = new TestHelper(); - - var hostBuilder = new HostBuilder() - //TODO: Need to have a configured umb version for the runtime state - .UseLocalDb(Path.Combine(testHelper.CurrentAssemblyDirectory, "LocalDb")) - //.UseTestLifetime() - .UseUmbraco(serviceProviderFactory) - .ConfigureServices((hostContext, services) => - { - AddRequiredNetCoreServices(services, testHelper); - - // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); - }); - - var host = await hostBuilder.StartAsync(); - - var runtimeState = (RuntimeState)umbracoContainer.GetInstance(); - Assert.AreEqual(RuntimeLevel.Install, runtimeState.Level); - - var dbBuilder = umbracoContainer.GetInstance(); - Assert.IsNotNull(dbBuilder); - - var canConnect = dbBuilder.CanConnectToDatabase; - Assert.IsTrue(canConnect); - - var dbResult = dbBuilder.CreateSchemaAndData(); - Assert.IsTrue(dbResult.Success); - - var dbFactory = umbracoContainer.GetInstance(); - var profilingLogger = umbracoContainer.GetInstance(); - runtimeState.DetermineRuntimeLevel(dbFactory, profilingLogger); - Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level); - } - private LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory) { var container = new ServiceContainer(ContainerOptions.Default.Clone().WithMicrosoftSettings().WithAspNetCoreSettings()); @@ -189,9 +245,15 @@ namespace Umbraco.Tests.Integration return umbracoContainer; } + /// + /// These services need to be manually added because they do not get added by the generic host + /// + /// + /// private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper) { services.AddSingleton(x => testHelper.GetHttpContextAccessor()); + // the generic host does add IHostEnvironment but not this one because we are not actually in a web context services.AddSingleton(x => testHelper.GetWebHostEnvironment()); } diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs index 609dcd98b8..5eb57b6ca6 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs @@ -41,6 +41,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache private readonly IEntityXmlSerializer _entitySerializer; private readonly IVariationContextAccessor _variationContextAccessor; private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly IHostingEnvironmentLifetime _hostingLifetime; private readonly IHostingEnvironment _hostingEnvironment; #region Constructors @@ -57,6 +58,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache ILogger logger, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, + IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper, ISiteDomainHelper siteDomainHelper, IEntityXmlSerializer entitySerializer, @@ -67,7 +69,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache publishedSnapshotAccessor, variationContextAccessor, umbracoContextAccessor, documentRepository, mediaRepository, memberRepository, defaultCultureAccessor, - logger, globalSettings, hostingEnvironment, shortStringHelper, siteDomainHelper, entitySerializer, null, mainDom, testing, enableRepositoryEvents) + logger, globalSettings, hostingEnvironment, hostingLifetime, shortStringHelper, siteDomainHelper, entitySerializer, null, mainDom, testing, enableRepositoryEvents) { _umbracoContextAccessor = umbracoContextAccessor; } @@ -84,6 +86,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache ILogger logger, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, + IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper, ISiteDomainHelper siteDomainHelper, IEntityXmlSerializer entitySerializer, @@ -99,7 +102,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache _xmlStore = new XmlStore(serviceContext.ContentTypeService, serviceContext.ContentService, scopeProvider, _routesCache, _contentTypeCache, publishedSnapshotAccessor, mainDom, testing, enableRepositoryEvents, - documentRepository, mediaRepository, memberRepository, globalSettings, entitySerializer, hostingEnvironment, shortStringHelper); + documentRepository, mediaRepository, memberRepository, entitySerializer, hostingEnvironment, hostingLifetime, shortStringHelper); _domainService = serviceContext.DomainService; _memberService = serviceContext.MemberService; @@ -113,6 +116,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache _siteDomainHelper = siteDomainHelper; _entitySerializer = entitySerializer; _hostingEnvironment = hostingEnvironment; + _hostingLifetime = hostingLifetime; } public override void Dispose() diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs index 238da68370..b051682ed7 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs @@ -45,9 +45,8 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache private readonly IDocumentRepository _documentRepository; private readonly IMediaRepository _mediaRepository; private readonly IMemberRepository _memberRepository; - private readonly IGlobalSettings _globalSettings; private readonly IEntityXmlSerializer _entitySerializer; - private readonly IHostingEnvironment _hostingEnvironment; + private readonly IHostingEnvironmentLifetime _hostingLifetime; private readonly IShortStringHelper _shortStringHelper; private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; private readonly PublishedContentTypeCache _contentTypeCache; @@ -58,7 +57,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache private XmlStoreFilePersister _persisterTask; private volatile bool _released; - private bool _withRepositoryEvents; #region Constructors @@ -67,8 +65,8 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache /// /// The default constructor will boot the cache, load data from file or database, /// wire events in order to manage changes, etc. public XmlStore(IContentTypeService contentTypeService, IContentService contentService, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, - IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IGlobalSettings globalSettings, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper) - : this(contentTypeService, contentService, scopeProvider, routesCache, contentTypeCache, publishedSnapshotAccessor, mainDom, false, false, documentRepository, mediaRepository, memberRepository, globalSettings, entitySerializer, hostingEnvironment, shortStringHelper) + IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper) + : this(contentTypeService, contentService, scopeProvider, routesCache, contentTypeCache, publishedSnapshotAccessor, mainDom, false, false, documentRepository, mediaRepository, memberRepository, entitySerializer, hostingEnvironment, hostingLifetime, shortStringHelper) { } // internal for unit tests @@ -76,7 +74,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache // TODO: er, we DO have a DB? internal XmlStore(IContentTypeService contentTypeService, IContentService contentService, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, - bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IGlobalSettings globalSettings, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper) + bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper) { if (testing == false) EnsureConfigurationIsValid(); @@ -90,12 +88,11 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache _documentRepository = documentRepository; _mediaRepository = mediaRepository; _memberRepository = memberRepository; - _globalSettings = globalSettings; _entitySerializer = entitySerializer; - _hostingEnvironment = hostingEnvironment; + _hostingLifetime = hostingLifetime; _shortStringHelper = shortStringHelper; - _xmlFileName = TestHelper.IOHelper.MapPath(SystemFiles.GetContentCacheXml(_hostingEnvironment)); + _xmlFileName = TestHelper.IOHelper.MapPath(SystemFiles.GetContentCacheXml(hostingEnvironment)); if (testing) { @@ -150,7 +147,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache LongRunning = true, KeepAlive = true, Hosted = false // main domain will take care of stopping the runner (see below) - }, logger, _hostingEnvironment); + }, logger, _hostingLifetime); // create (and add to runner) _persisterTask = new XmlStoreFilePersister(runner, this, logger); @@ -207,7 +204,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache MediaTypeService.ScopedRefreshedEntity += OnMediaTypeRefreshedEntity; MemberTypeService.ScopedRefreshedEntity += OnMemberTypeRefreshedEntity; - _withRepositoryEvents = true; } private void ClearEvents() @@ -226,7 +222,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache MediaTypeService.ScopedRefreshedEntity -= OnMediaTypeRefreshedEntity; MemberTypeService.ScopedRefreshedEntity -= OnMemberTypeRefreshedEntity; - _withRepositoryEvents = false; } private void LazyInitializeContent() diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index 561a6d945e..f9de3579c2 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -32,8 +32,7 @@ namespace Umbraco.Tests.Routing //create the module var logger = Mock.Of(); var globalSettings = TestObjects.GetGlobalSettings(); - var runtime = new RuntimeState(logger, globalSettings, - new Lazy(), new Lazy(), UmbracoVersion, HostingEnvironment, BackOfficeInfo); + var runtime = new RuntimeState(logger, globalSettings, UmbracoVersion, BackOfficeInfo); _module = new UmbracoInjectedModule ( diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 92ab825ee2..44481666bc 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -146,31 +146,31 @@ namespace Umbraco.Tests.Runtimes } */ - // because we don't even have the core runtime component, - // there are a few required stuff that we need to compose - public override void Compose(Composition composition) - { - base.Compose(composition); + //// because we don't even have the core runtime component, + //// there are a few required stuff that we need to compose + //public override void Compose(Composition composition) + //{ + // base.Compose(composition); - var scopeProvider = Mock.Of(); - Mock.Get(scopeProvider) - .Setup(x => x.CreateScope( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny())) - .Returns(Mock.Of()); + // var scopeProvider = Mock.Of(); + // Mock.Get(scopeProvider) + // .Setup(x => x.CreateScope( + // It.IsAny(), + // It.IsAny(), + // It.IsAny(), + // It.IsAny(), + // It.IsAny(), + // It.IsAny())) + // .Returns(Mock.Of()); - composition.RegisterUnique(scopeProvider); - } + // composition.RegisterUnique(scopeProvider); + //} private IMainDom _mainDom; - public override IFactory Boot(IRegister container) + public override IFactory Configure(IRegister container) { - var factory = base.Boot(container); + var factory = base.Configure(container); _mainDom = factory.GetInstance(); return factory; } diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index 99a5352a17..f167aafb89 100644 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs @@ -72,7 +72,7 @@ namespace Umbraco.Tests.Runtimes var mainDom = new SimpleMainDom(); var umbracoVersion = TestHelper.GetUmbracoVersion(); var backOfficeInfo = TestHelper.GetBackOfficeInfo(); - var runtimeState = new RuntimeState(logger, null, new Lazy(() => mainDom), new Lazy(() => factory.GetInstance()), umbracoVersion, hostingEnvironment, backOfficeInfo); + var runtimeState = new RuntimeState(logger, null, umbracoVersion, backOfficeInfo); var configs = TestHelper.GetConfigs(); var variationContextAccessor = TestHelper.VariationContextAccessor; @@ -84,7 +84,6 @@ namespace Umbraco.Tests.Runtimes // create the core runtime and have it compose itself var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder); - coreRuntime.Compose(composition); // determine actual runtime level runtimeState.DetermineRuntimeLevel(databaseFactory, logger); @@ -279,7 +278,6 @@ namespace Umbraco.Tests.Runtimes // create the core runtime and have it compose itself var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder); - coreRuntime.Compose(composition); // get the components // all of them? diff --git a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs index f10b141916..18eb3d19a4 100644 --- a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs +++ b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs @@ -19,13 +19,13 @@ namespace Umbraco.Tests.Scheduling public class BackgroundTaskRunnerTests { private ILogger _logger; - private IHostingEnvironment _hostingEnvironment; + private IHostingEnvironmentLifetime _hostingEnvironment; [OneTimeSetUp] public void InitializeFixture() { _logger = new ConsoleLogger(new MessageTemplates()); - _hostingEnvironment = TestHelper.GetHostingEnvironment(); + _hostingEnvironment = TestHelper.GetHostingEnvironmentLifetime(); } [Test] @@ -934,7 +934,7 @@ namespace Umbraco.Tests.Scheduling [Test] public void SourceTaskTest() { - var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, _logger, TestHelper.GetHostingEnvironment()); + var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, _logger, TestHelper.GetHostingEnvironmentLifetime()); var task = new SourceTask(); runner.Add(task); diff --git a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests2.cs b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests2.cs index c65c7e3efb..01169abce2 100644 --- a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests2.cs +++ b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests2.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.Scheduling public async Task ThreadResumeIssue() { var logger = new DebugDiagnosticsLogger(new MessageTemplates()); - var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironment()); + var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironmentLifetime()); var work = new ThreadResumeIssueWorkItem(); runner.Add(work); @@ -77,7 +77,7 @@ namespace Umbraco.Tests.Scheduling public async Task DebuggerInterferenceIssue() { var logger = new DebugDiagnosticsLogger(new MessageTemplates()); - var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironment()); + var runner = new BackgroundTaskRunner(new BackgroundTaskRunnerOptions { KeepAlive = true, LongRunning = true }, logger, TestHelper.GetHostingEnvironmentLifetime()); var taskCompleted = false; runner.TaskCompleted += (sender, args) => { diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index 05d4de6e23..54cbec46e9 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -21,12 +21,12 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Net; using Umbraco.Core.Persistence; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Strings; -using Umbraco.Net; using Umbraco.Tests.Common; using Umbraco.Web; using Umbraco.Web.Hosting; @@ -40,7 +40,7 @@ namespace Umbraco.Tests.TestHelpers /// public static class TestHelper { - private static TestHelperInternal _testHelperInternal = new TestHelperInternal(); + private static readonly TestHelperInternal _testHelperInternal = new TestHelperInternal(); private class TestHelperInternal : TestHelperBase { public TestHelperInternal() : base(typeof(TestHelperInternal).Assembly) @@ -62,6 +62,9 @@ namespace Umbraco.Tests.TestHelpers public override IHostingEnvironment GetHostingEnvironment() => new AspNetHostingEnvironment(SettingsForTests.GetDefaultHostingSettings()); + public override IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() + => new AspNetHostingLifetime(); + public override IIpResolver GetIpResolver() => new AspNetIpResolver(); } @@ -320,6 +323,8 @@ namespace Umbraco.Tests.TestHelpers public static IHostingEnvironment GetHostingEnvironment() => _testHelperInternal.GetHostingEnvironment(); + public static IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() => _testHelperInternal.GetHostingEnvironmentLifetime(); + public static IIpResolver GetIpResolver() => _testHelperInternal.GetIpResolver(); public static IRequestCache GetRequestCache() => _testHelperInternal.GetRequestCache(); diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 5cf2c7b6bd..fbfada118a 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -265,6 +265,7 @@ namespace Umbraco.Tests.TestHelpers Logger, Factory.GetInstance(), HostingEnvironment, + HostingLifetime, ShortStringHelper, new SiteDomainHelper(), Factory.GetInstance(), diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index ca36a6049e..9222f7e4ab 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -51,10 +51,10 @@ using Umbraco.Web.Templates; using Umbraco.Web.PropertyEditors; using Umbraco.Core.Dictionary; using Umbraco.Core.Models; +using Umbraco.Core.Net; using Umbraco.Core.Request; using Umbraco.Core.Security; using Umbraco.Core.Services; -using Umbraco.Net; using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Web.AspNet; using Umbraco.Web.Install; @@ -140,6 +140,7 @@ namespace Umbraco.Tests.Testing protected virtual IProfilingLogger ProfilingLogger => Factory.GetInstance(); protected IHostingEnvironment HostingEnvironment { get; } = new AspNetHostingEnvironment(TestHelpers.SettingsForTests.GetDefaultHostingSettings()); + protected IHostingEnvironmentLifetime HostingLifetime { get; } = new AspNetHostingLifetime(); protected IIpResolver IpResolver => Factory.GetInstance(); protected IBackOfficeInfo BackOfficeInfo => Factory.GetInstance(); protected AppCaches AppCaches => Factory.GetInstance(); diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index 5e5197a28a..c5e9556d05 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -423,6 +423,7 @@ namespace Umbraco.Tests.Web.Mvc new TestDefaultCultureAccessor(), Current.Logger, TestObjects.GetGlobalSettings(), TestHelper.GetHostingEnvironment(), + TestHelper.GetHostingEnvironmentLifetime(), ShortStringHelper, new SiteDomainHelper(), Factory.GetInstance(), diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs new file mode 100644 index 0000000000..e85f3cb3f9 --- /dev/null +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs @@ -0,0 +1,27 @@ +using Microsoft.AspNetCore.Http; +using Umbraco.Core; +using Umbraco.Core.Composing; +using Umbraco.Core.Hosting; +using Umbraco.Core.Net; +using Umbraco.Core.Runtime; + +namespace Umbraco.Web.BackOffice.AspNetCore +{ + /// + /// Adds/replaces AspNetCore specific services + /// + [ComposeBefore(typeof(ICoreComposer))] + [ComposeAfter(typeof(CoreInitialComposer))] + public class AspNetCoreComposer : IComposer + { + public void Compose(Composition composition) + { + // AspNetCore specific services + composition.RegisterUnique(); + + // Our own netcore implementations + composition.RegisterUnique(); + composition.RegisterUnique(); + } + } +} diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironment.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironment.cs index 00bc894b0d..6f1298918d 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironment.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironment.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Concurrent; -using System.Diagnostics; +using System.Globalization; using System.IO; -using System.Threading; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Hosting; using Umbraco.Core; using Umbraco.Core.Configuration; @@ -13,30 +10,29 @@ namespace Umbraco.Web.BackOffice.AspNetCore { public class AspNetCoreHostingEnvironment : Umbraco.Core.Hosting.IHostingEnvironment { - private readonly ConcurrentDictionary _registeredObjects = - new ConcurrentDictionary(); + private readonly IHostingSettings _hostingSettings; private readonly IWebHostEnvironment _webHostEnvironment; private readonly IHttpContextAccessor _httpContextAccessor; - private readonly IHostApplicationLifetime _hostApplicationLifetime; + private string _localTempPath; - public AspNetCoreHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContextAccessor, IHostApplicationLifetime hostHostApplicationLifetime) + public AspNetCoreHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, IHttpContextAccessor httpContextAccessor) { _hostingSettings = hostingSettings ?? throw new ArgumentNullException(nameof(hostingSettings)); _webHostEnvironment = webHostEnvironment; _httpContextAccessor = httpContextAccessor; - _hostApplicationLifetime = hostHostApplicationLifetime; SiteName = webHostEnvironment.ApplicationName; ApplicationId = AppDomain.CurrentDomain.Id.ToString(); ApplicationPhysicalPath = webHostEnvironment.ContentRootPath; ApplicationVirtualPath = "/"; //TODO how to find this, This is a server thing, not application thing. - IISVersion = new Version(0, 0); // TODO not necessary IIS + IISVersion = new Version(0, 0); // TODO not necessary IIS IsDebugMode = _hostingSettings.DebugMode; } + public bool IsHosted { get; } = true; public string SiteName { get; } public string ApplicationId { get; } @@ -56,7 +52,10 @@ namespace Umbraco.Web.BackOffice.AspNetCore switch (_hostingSettings.LocalTempStorageLocation) { case LocalTempStorage.AspNetTemp: - return _localTempPath = System.IO.Path.Combine(Path.GetTempPath(),ApplicationId, "UmbracoData"); + + // TODO: I don't think this is correct? but also we probably can remove AspNetTemp as an option entirely + // since this is legacy and we shouldn't use it + return _localTempPath = System.IO.Path.Combine(Path.GetTempPath(), ApplicationId, "UmbracoData"); case LocalTempStorage.EnvironmentTemp: @@ -84,8 +83,11 @@ namespace Umbraco.Web.BackOffice.AspNetCore } } - // TODO: This may need to take into account ~/ paths which means the ApplicationVirtualPath and is this the content root or web root? - public string MapPath(string path) => Path.Combine(_webHostEnvironment.WebRootPath, path); + public string MapPath(string path) + { + var newPath = path.TrimStart('~', '/').Replace('/', Path.DirectorySeparatorChar); + return Path.Combine(_webHostEnvironment.WebRootPath, newPath); + } // TODO: Need to take into account 'root' here public string ToAbsolute(string virtualPath, string root) @@ -101,43 +103,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore return applicationPath.Add(segment).Value; } - public void RegisterObject(IRegisteredObject registeredObject) - { - var wrapped = new RegisteredObjectWrapper(registeredObject); - if (!_registeredObjects.TryAdd(registeredObject, wrapped)) - { - throw new InvalidOperationException("Could not register object"); - } - - var cancellationTokenRegistration = _hostApplicationLifetime.ApplicationStopping.Register(() => wrapped.Stop(true)); - wrapped.CancellationTokenRegistration = cancellationTokenRegistration; - } - - public void UnregisterObject(IRegisteredObject registeredObject) - { - if (_registeredObjects.TryGetValue(registeredObject, out var wrapped)) - { - wrapped.CancellationTokenRegistration.Unregister(); - } - } - - - private class RegisteredObjectWrapper - { - private readonly IRegisteredObject _inner; - - public RegisteredObjectWrapper(IRegisteredObject inner) - { - _inner = inner; - } - - public CancellationTokenRegistration CancellationTokenRegistration { get; set; } - - public void Stop(bool immediate) - { - _inner.Stop(immediate); - } - } + } diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.cs new file mode 100644 index 0000000000..3726e50e3b --- /dev/null +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Concurrent; +using System.Threading; +using Microsoft.Extensions.Hosting; +using Umbraco.Core; +using Umbraco.Core.Hosting; + +namespace Umbraco.Web.BackOffice.AspNetCore +{ + public class AspNetCoreHostingEnvironmentLifetime : IHostingEnvironmentLifetime + { + private readonly IHostApplicationLifetime _hostApplicationLifetime; + private readonly ConcurrentDictionary _registeredObjects = + new ConcurrentDictionary(); + + public AspNetCoreHostingEnvironmentLifetime(IHostApplicationLifetime hostApplicationLifetime) + { + _hostApplicationLifetime = hostApplicationLifetime; + } + + public void RegisterObject(IRegisteredObject registeredObject) + { + var wrapped = new RegisteredObjectWrapper(registeredObject); + if (!_registeredObjects.TryAdd(registeredObject, wrapped)) + { + throw new InvalidOperationException("Could not register object"); + } + + var cancellationTokenRegistration = _hostApplicationLifetime.ApplicationStopping.Register(() => wrapped.Stop(true)); + wrapped.CancellationTokenRegistration = cancellationTokenRegistration; + } + + public void UnregisterObject(IRegisteredObject registeredObject) + { + if (_registeredObjects.TryGetValue(registeredObject, out var wrapped)) + { + wrapped.CancellationTokenRegistration.Unregister(); + } + } + + + private class RegisteredObjectWrapper + { + private readonly IRegisteredObject _inner; + + public RegisteredObjectWrapper(IRegisteredObject inner) + { + _inner = inner; + } + + public CancellationTokenRegistration CancellationTokenRegistration { get; set; } + + public void Stop(bool immediate) + { + _inner.Stop(immediate); + } + } + } +} diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs index a79838bd3e..feb122a48b 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs @@ -2,6 +2,9 @@ using System; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Umbraco.Core; +using Umbraco.Core.Composing; +using Umbraco.Core.Hosting; namespace Umbraco.Web.BackOffice.AspNetCore { @@ -14,5 +17,52 @@ namespace Umbraco.Web.BackOffice.AspNetCore return app; } + /// + /// Start Umbraco + /// + /// + /// + public static IApplicationBuilder UseUmbracoCore(this IApplicationBuilder app) + { + if (app == null) throw new ArgumentNullException(nameof(app)); + + // Register a listener for application shutdown in order to terminate the runtime + var hostLifetime = app.ApplicationServices.GetRequiredService(); + var runtime = app.ApplicationServices.GetRequiredService(); + var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime); + hostLifetime.RegisterObject(runtimeShutdown); + + // Start the runtime! + runtime.Start(); + + return app; + } + + /// + /// Ensures the runtime is shutdown when the application is shutting down + /// + private class CoreRuntimeShutdown : IRegisteredObject + { + public CoreRuntimeShutdown(IRuntime runtime, IHostingEnvironmentLifetime hostLifetime) + { + _runtime = runtime; + _hostLifetime = hostLifetime; + } + + private bool _completed = false; + private readonly IRuntime _runtime; + private readonly IHostingEnvironmentLifetime _hostLifetime; + + public void Stop(bool immediate) + { + if (!_completed) + { + _completed = true; + _runtime.Terminate(); + _hostLifetime.UnregisterObject(this); + } + + } + } } } diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs index 6c3cecad28..d283a7ffb1 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs @@ -19,8 +19,7 @@ using Umbraco.Core.Runtime; namespace Umbraco.Web.BackOffice.AspNetCore { - - + // TODO: Move to Umbraco.Web.Common public static class UmbracoCoreServiceCollectionExtensions { /// @@ -73,11 +72,12 @@ namespace Umbraco.Web.BackOffice.AspNetCore if (umbContainer is null) throw new ArgumentNullException(nameof(umbContainer)); if (entryAssembly is null) throw new ArgumentNullException(nameof(entryAssembly)); + // Special case! The generic host adds a few default services but we need to manually add this one here NOW because + // we resolve it before the host finishes configuring in the call to CreateCompositionRoot services.AddSingleton(); CreateCompositionRoot(services, out var logger, out var configs, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler); - // TODO: Get rid of this 'Current' requirement var globalSettings = configs.Global(); var umbracoVersion = new UmbracoVersion(globalSettings); @@ -95,9 +95,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore backOfficeInfo, typeFinder); - hostingEnvironment.RegisterObject(new CoreRuntimeShutdown(coreRuntime)); - - var factory = coreRuntime.Boot(umbContainer); + var factory = coreRuntime.Configure(umbContainer); return services; } @@ -119,7 +117,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore ? (IMainDomLock)new SqlMainDomLock(logger, globalSettings, connStrings, dbProviderFactoryCreator) : new MainDomSemaphoreLock(logger, hostingEnvironment); - var mainDom = new MainDom(logger, hostingEnvironment, mainDomLock); + var mainDom = new MainDom(logger, mainDomLock); var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetCoreBootPermissionsChecker(), hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom, typeFinder); @@ -137,10 +135,6 @@ namespace Umbraco.Web.BackOffice.AspNetCore var httpContextAccessor = serviceProvider.GetRequiredService(); var webHostEnvironment = serviceProvider.GetRequiredService(); - // TODO: I'm unsure about this, by doing this it means we are resolving a "Different" instance to the one - // that controls the whole app because the instances comes from a different service provider. This - // could cause some issues with shutdowns, etc... we need to investigate. - var hostApplicationLifetime = serviceProvider.GetRequiredService(); configs = serviceProvider.GetService(); if (configs == null) @@ -150,7 +144,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore var coreDebug = configs.CoreDebug(); var globalSettings = configs.Global(); - hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor, hostApplicationLifetime); + hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment, httpContextAccessor); ioHelper = new IOHelper(hostingEnvironment, globalSettings); logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, new AspNetCoreSessionIdResolver(httpContextAccessor), @@ -170,28 +164,6 @@ namespace Umbraco.Web.BackOffice.AspNetCore } } - /// - /// Ensures the runtime is shutdown when the application is shutting down - /// - private class CoreRuntimeShutdown : IRegisteredObject - { - public CoreRuntimeShutdown(IRuntime runtime) - { - _runtime = runtime; - } - - private bool _completed = false; - private readonly IRuntime _runtime; - - public void Stop(bool immediate) - { - if (!_completed) - { - _completed = true; - _runtime.Terminate(); - } - - } - } + } } diff --git a/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs b/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs index aa07894aa9..a61ad356d5 100644 --- a/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs +++ b/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs @@ -1,21 +1,15 @@ using System; -using System.Collections; -using System.Collections.Concurrent; -using System.Collections.Generic; using System.Web; using System.Web.Hosting; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; -using IRegisteredObject = Umbraco.Core.IRegisteredObject; namespace Umbraco.Web.Hosting { public class AspNetHostingEnvironment : IHostingEnvironment { - private readonly ConcurrentDictionary _registeredObjects = - new ConcurrentDictionary(); + private readonly IHostingSettings _hostingSettings; private string _localTempPath; @@ -46,23 +40,7 @@ namespace Umbraco.Web.Hosting } public string ToAbsolute(string virtualPath, string root) => VirtualPathUtility.ToAbsolute(virtualPath, root); - public void RegisterObject(IRegisteredObject registeredObject) - { - var wrapped = new RegisteredObjectWrapper(registeredObject); - if (!_registeredObjects.TryAdd(registeredObject, wrapped)) - { - throw new InvalidOperationException("Could not register object"); - } - HostingEnvironment.RegisterObject(wrapped); - } - - public void UnregisterObject(IRegisteredObject registeredObject) - { - if (_registeredObjects.TryGetValue(registeredObject, out var wrapped)) - { - HostingEnvironment.UnregisterObject(wrapped); - } - } + public string LocalTempPath { @@ -101,20 +79,7 @@ namespace Umbraco.Web.Hosting } } } - private class RegisteredObjectWrapper : System.Web.Hosting.IRegisteredObject - { - private readonly IRegisteredObject _inner; - - public RegisteredObjectWrapper(IRegisteredObject inner) - { - _inner = inner; - } - - public void Stop(bool immediate) - { - _inner.Stop(immediate); - } - } + } diff --git a/src/Umbraco.Web/AspNet/AspNetHostingLifetime.cs b/src/Umbraco.Web/AspNet/AspNetHostingLifetime.cs new file mode 100644 index 0000000000..316ecb8389 --- /dev/null +++ b/src/Umbraco.Web/AspNet/AspNetHostingLifetime.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Concurrent; +using System.Web.Hosting; +using Umbraco.Core.Hosting; +using IRegisteredObject = Umbraco.Core.IRegisteredObject; + +namespace Umbraco.Web.Hosting +{ + public class AspNetHostingLifetime : IHostingEnvironmentLifetime + { + private readonly ConcurrentDictionary _registeredObjects = + new ConcurrentDictionary(); + + public void RegisterObject(IRegisteredObject registeredObject) + { + var wrapped = new RegisteredObjectWrapper(registeredObject); + if (!_registeredObjects.TryAdd(registeredObject, wrapped)) + { + throw new InvalidOperationException("Could not register object"); + } + HostingEnvironment.RegisterObject(wrapped); + } + + public void UnregisterObject(IRegisteredObject registeredObject) + { + if (_registeredObjects.TryGetValue(registeredObject, out var wrapped)) + { + HostingEnvironment.UnregisterObject(wrapped); + } + } + + private class RegisteredObjectWrapper : System.Web.Hosting.IRegisteredObject + { + private readonly IRegisteredObject _inner; + + public RegisteredObjectWrapper(IRegisteredObject inner) + { + _inner = inner; + } + + public void Stop(bool immediate) + { + _inner.Stop(immediate); + } + } + } +} diff --git a/src/Umbraco.Web/Profiling/WebProfilingController.cs b/src/Umbraco.Web/Profiling/WebProfilingController.cs index b37a7eefb8..d8f71b5c85 100644 --- a/src/Umbraco.Web/Profiling/WebProfilingController.cs +++ b/src/Umbraco.Web/Profiling/WebProfilingController.cs @@ -1,6 +1,7 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Hosting; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Persistence; @@ -18,7 +19,7 @@ namespace Umbraco.Web.Profiling [UmbracoApplicationAuthorize(Core.Constants.Applications.Settings)] public class WebProfilingController : UmbracoAuthorizedJsonController { - private readonly IRuntimeState _runtimeState; + private readonly IHostingEnvironment _hosting; public WebProfilingController( IGlobalSettings globalSettings, @@ -30,17 +31,18 @@ namespace Umbraco.Web.Profiling IRuntimeState runtimeState, IShortStringHelper shortStringHelper, UmbracoMapper umbracoMapper, - IPublishedUrlProvider publishedUrlProvider) + IPublishedUrlProvider publishedUrlProvider, + IHostingEnvironment hosting) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, shortStringHelper, umbracoMapper, publishedUrlProvider) { - _runtimeState = runtimeState; + _hosting = hosting; } public object GetStatus() { return new { - Enabled = _runtimeState.Debug + Enabled = _hosting.IsDebugMode }; } }} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 5eb60cb629..ce08d5498d 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -134,6 +134,7 @@ + diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 9f24da95e3..30d3fe5041 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -32,7 +32,7 @@ namespace Umbraco.Web ? (IMainDomLock)new SqlMainDomLock(logger, globalSettings, connectionStrings, dbProviderFactoryCreator) : new MainDomSemaphoreLock(logger, hostingEnvironment); - var mainDom = new MainDom(logger, hostingEnvironment, mainDomLock); + var mainDom = new MainDom(logger, mainDomLock); var requestCache = new HttpRequestAppCache(() => HttpContext.Current?.Items); var umbracoBootPermissionChecker = new AspNetUmbracoBootPermissionChecker(); diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index ce5f1304cd..0963ad3c07 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -152,7 +152,9 @@ namespace Umbraco.Web Umbraco.Composing.Current.Profiler, Umbraco.Composing.Current.HostingEnvironment, Umbraco.Composing.Current.BackOfficeInfo); - _factory = Current.Factory = _runtime.Boot(register); + _factory = Current.Factory = _runtime.Configure(register); + + _runtime.Start(); } // called by ASP.NET (auto event wireup) once per app domain diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index 6f5fc26f90..9cc651f359 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -150,7 +150,7 @@ namespace Umbraco.Web { var request = GetRequestFromContext(); //NOTE: the request can be null during app startup! - return Current.RuntimeState.Debug + return Current.HostingEnvironment.IsDebugMode && request != null && (string.IsNullOrEmpty(request["umbdebugshowtrace"]) == false || string.IsNullOrEmpty(request["umbdebug"]) == false diff --git a/src/Umbraco.Web/UrlHelperExtensions.cs b/src/Umbraco.Web/UrlHelperExtensions.cs index a0bf5d3ded..f0ee309630 100644 --- a/src/Umbraco.Web/UrlHelperExtensions.cs +++ b/src/Umbraco.Web/UrlHelperExtensions.cs @@ -143,12 +143,12 @@ namespace Umbraco.Web //in case the user bypasses the installer and just bumps the web.config or client dependency config //if in debug mode, always burst the cache - if (Current.RuntimeState.Debug) + if (Current.HostingEnvironment.IsDebugMode) { return DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture).GenerateHash(); } - var version = Current.RuntimeState.SemanticVersion.ToSemanticString(); + var version = Current.UmbracoVersion.SemanticVersion.ToSemanticString(); return $"{version}.{ClientDependencySettings.Instance.Version}".GenerateHash(); } } From a0acc8126d20e370529d1da44b62d88fcdb502a9 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 16:52:42 +1100 Subject: [PATCH 17/28] oops change namespace back to Umbraco.net --- src/Umbraco.Core/Manifest/ManifestWatcher.cs | 2 +- src/Umbraco.Core/Net/IIpResolver.cs | 2 +- src/Umbraco.Core/Net/ISessionIdResolver.cs | 2 +- src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs | 2 +- src/Umbraco.Core/Net/IUserAgentProvider.cs | 2 +- src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs | 2 +- src/Umbraco.Infrastructure/Intall/InstallHelper.cs | 2 +- .../Intall/InstallSteps/StarterKitDownloadStep.cs | 2 +- .../Intall/InstallSteps/StarterKitInstallStep.cs | 2 +- .../Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs | 2 +- .../Logging/Serilog/LoggerConfigExtensions.cs | 2 +- src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs | 2 +- src/Umbraco.Tests.Common/TestHelperBase.cs | 2 +- src/Umbraco.Tests.Integration/Implementations/TestHelper.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestHelper.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs | 2 +- src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs | 2 +- .../AspNetCore/AspNetCoreSessionIdResolver.cs | 2 +- .../AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs | 2 +- .../AspNetCore/AspNetCoreUserAgentProvider.cs | 2 +- src/Umbraco.Web/AspNet/AspNetIpResolver.cs | 2 +- src/Umbraco.Web/AspNet/AspNetSessionManager.cs | 2 +- src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs | 2 +- src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs | 2 +- src/Umbraco.Web/Compose/AuditEventsComponent.cs | 2 +- src/Umbraco.Web/Composing/Current.cs | 2 +- src/Umbraco.Web/Editors/PackageInstallController.cs | 2 +- src/Umbraco.Web/Runtime/WebInitialComposer.cs | 2 +- src/Umbraco.Web/Security/AppBuilderExtensions.cs | 2 +- src/Umbraco.Web/Security/BackOfficeUserManager.cs | 2 +- src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs | 2 +- src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs | 2 +- src/Umbraco.Web/UmbracoDefaultOwinStartup.cs | 2 +- 34 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/Umbraco.Core/Manifest/ManifestWatcher.cs b/src/Umbraco.Core/Manifest/ManifestWatcher.cs index adf2be466b..23caac3a1b 100644 --- a/src/Umbraco.Core/Manifest/ManifestWatcher.cs +++ b/src/Umbraco.Core/Manifest/ManifestWatcher.cs @@ -4,7 +4,7 @@ using System.IO; using System.Linq; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Core.Manifest { diff --git a/src/Umbraco.Core/Net/IIpResolver.cs b/src/Umbraco.Core/Net/IIpResolver.cs index 8a7d670723..7fb6b8a793 100644 --- a/src/Umbraco.Core/Net/IIpResolver.cs +++ b/src/Umbraco.Core/Net/IIpResolver.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Net +namespace Umbraco.Net { public interface IIpResolver { diff --git a/src/Umbraco.Core/Net/ISessionIdResolver.cs b/src/Umbraco.Core/Net/ISessionIdResolver.cs index 94cdfb454a..745be5a435 100644 --- a/src/Umbraco.Core/Net/ISessionIdResolver.cs +++ b/src/Umbraco.Core/Net/ISessionIdResolver.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Net +namespace Umbraco.Net { public interface ISessionIdResolver { diff --git a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs index eb38c67e2e..10d5b10955 100644 --- a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Net +namespace Umbraco.Net { public interface IUmbracoApplicationLifetime { diff --git a/src/Umbraco.Core/Net/IUserAgentProvider.cs b/src/Umbraco.Core/Net/IUserAgentProvider.cs index d3f997c607..14246ea99e 100644 --- a/src/Umbraco.Core/Net/IUserAgentProvider.cs +++ b/src/Umbraco.Core/Net/IUserAgentProvider.cs @@ -1,4 +1,4 @@ -namespace Umbraco.Core.Net +namespace Umbraco.Net { public interface IUserAgentProvider { diff --git a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs index 06b3cc0cc9..a2ee650595 100644 --- a/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs +++ b/src/Umbraco.Infrastructure/Compose/ManifestWatcherComponent.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Manifest; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Core.Compose { diff --git a/src/Umbraco.Infrastructure/Intall/InstallHelper.cs b/src/Umbraco.Infrastructure/Intall/InstallHelper.cs index 7aca4af09f..cf4b174cde 100644 --- a/src/Umbraco.Infrastructure/Intall/InstallHelper.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallHelper.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Cookie; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Models; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Persistence; using Umbraco.Core.Serialization; using Umbraco.Core.Services; diff --git a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs index a20637584f..d8986cacb7 100644 --- a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitDownloadStep.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Umbraco.Core.Services; using Umbraco.Core.Configuration; using Umbraco.Core.Models.Packaging; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Web.Install.Models; namespace Umbraco.Web.Install.InstallSteps diff --git a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs index 0a6e67c829..4e14da30b7 100644 --- a/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs +++ b/src/Umbraco.Infrastructure/Intall/InstallSteps/StarterKitInstallStep.cs @@ -2,7 +2,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Services; using Umbraco.Web.Install.Models; diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs index 052775d918..1558cdcf21 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/HttpSessionIdEnricher.cs @@ -1,7 +1,7 @@ using Serilog.Core; using Serilog.Events; using System; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Core.Logging.Serilog.Enrichers { diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs index 59e0b8854f..f4e8f85281 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Hosting; using Umbraco.Core.Logging.Serilog.Enrichers; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Core.Logging.Serilog { diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs index 55b89d7996..bb77869e28 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Diagnostics; using Umbraco.Core.Hosting; using Umbraco.Core.IO; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Core.Logging.Serilog { diff --git a/src/Umbraco.Tests.Common/TestHelperBase.cs b/src/Umbraco.Tests.Common/TestHelperBase.cs index 76aa38e246..22177c1a50 100644 --- a/src/Umbraco.Tests.Common/TestHelperBase.cs +++ b/src/Umbraco.Tests.Common/TestHelperBase.cs @@ -12,7 +12,7 @@ using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Persistence; using Umbraco.Core.Serialization; using Umbraco.Core.Strings; diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index f1aa53694c..d218513ce3 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Diagnostics; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Persistence; using Umbraco.Core.Runtime; using Umbraco.Tests.Common; diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index 54cbec46e9..9cc9059499 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -21,7 +21,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Persistence; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Serialization; diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 9222f7e4ab..96576ac9a4 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -51,7 +51,7 @@ using Umbraco.Web.Templates; using Umbraco.Web.PropertyEditors; using Umbraco.Core.Dictionary; using Umbraco.Core.Models; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Request; using Umbraco.Core.Security; using Umbraco.Core.Services; diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs index e85f3cb3f9..3c65c24b1f 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Http; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Hosting; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Runtime; namespace Umbraco.Web.BackOffice.AspNetCore diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs index 520fe6b8aa..cee43757d8 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreIpResolver.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Http; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs index a27e378909..cafb02d367 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreSessionIdResolver.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs index e7aba5e2de..0dca3edec8 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUmbracoApplicationLifetime.cs @@ -1,7 +1,7 @@ using System.Threading; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs index a85970afaf..f9c9884704 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreUserAgentProvider.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Http; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.BackOffice.AspNetCore { diff --git a/src/Umbraco.Web/AspNet/AspNetIpResolver.cs b/src/Umbraco.Web/AspNet/AspNetIpResolver.cs index 026fb7ff12..7eaca54663 100644 --- a/src/Umbraco.Web/AspNet/AspNetIpResolver.cs +++ b/src/Umbraco.Web/AspNet/AspNetIpResolver.cs @@ -1,6 +1,6 @@ using System.Web; using Umbraco.Core; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web { diff --git a/src/Umbraco.Web/AspNet/AspNetSessionManager.cs b/src/Umbraco.Web/AspNet/AspNetSessionManager.cs index 9196cb137f..f81daadb0a 100644 --- a/src/Umbraco.Web/AspNet/AspNetSessionManager.cs +++ b/src/Umbraco.Web/AspNet/AspNetSessionManager.cs @@ -1,5 +1,5 @@ using System.Web; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Session; namespace Umbraco.Web.AspNet diff --git a/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs b/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs index 64988a20d9..245e8ea374 100644 --- a/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Web/AspNet/AspNetUmbracoApplicationLifetime.cs @@ -1,6 +1,6 @@ using System.Threading; using System.Web; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.AspNet { diff --git a/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs b/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs index 4ba73292bb..bd37b62531 100644 --- a/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs +++ b/src/Umbraco.Web/AspNet/AspNetUserAgentProvider.cs @@ -1,4 +1,4 @@ -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.AspNet { diff --git a/src/Umbraco.Web/Compose/AuditEventsComponent.cs b/src/Umbraco.Web/Compose/AuditEventsComponent.cs index d03f33d7ac..bd2520aa90 100644 --- a/src/Umbraco.Web/Compose/AuditEventsComponent.cs +++ b/src/Umbraco.Web/Compose/AuditEventsComponent.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index 4424de6771..70083d47dd 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -11,7 +11,7 @@ using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.Mapping; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.PackageActions; using Umbraco.Core.Packaging; using Umbraco.Core.PropertyEditors; diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 178a5c96d9..fe552650ea 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -14,7 +14,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Models.Editors; using Umbraco.Core.Models.Packaging; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Packaging; using Umbraco.Core.Persistence; using Umbraco.Core.Services; diff --git a/src/Umbraco.Web/Runtime/WebInitialComposer.cs b/src/Umbraco.Web/Runtime/WebInitialComposer.cs index 1d7fc8fd6e..2a746ffe4c 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComposer.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComposer.cs @@ -45,7 +45,7 @@ using Umbraco.Web.WebApi; using Umbraco.Web.PropertyEditors; using Umbraco.Examine; using Umbraco.Core.Models; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Request; using Umbraco.Core.Session; using Umbraco.Web.AspNet; diff --git a/src/Umbraco.Web/Security/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/AppBuilderExtensions.cs index 5416683eab..b3f950433c 100644 --- a/src/Umbraco.Web/Security/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/Security/AppBuilderExtensions.cs @@ -17,7 +17,7 @@ using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Mapping; using Umbraco.Core.Models.Identity; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Composing; diff --git a/src/Umbraco.Web/Security/BackOfficeUserManager.cs b/src/Umbraco.Web/Security/BackOfficeUserManager.cs index 64b7054723..7de7ba37e5 100644 --- a/src/Umbraco.Web/Security/BackOfficeUserManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeUserManager.cs @@ -9,7 +9,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Mapping; using Umbraco.Core.Models.Identity; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Web.Models.Identity; diff --git a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs index ffa9a1c967..d393078cc6 100644 --- a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Services; using Umbraco.Core.Models.Membership; using Umbraco.Web.Composing; using System; -using Umbraco.Core.Net; +using Umbraco.Net; namespace Umbraco.Web.Security.Providers { diff --git a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs index 9466dd6732..b099110911 100644 --- a/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs @@ -10,7 +10,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Security; using Umbraco.Core.Services; diff --git a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs index 8fcdc2c542..a0b7cdd225 100644 --- a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs +++ b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Mapping; -using Umbraco.Core.Net; +using Umbraco.Net; using Umbraco.Core.Services; using Umbraco.Web; using Umbraco.Web.Composing; From c988004762123e37a82fd2e8a2dfcfdefd1a5f3d Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 17:18:36 +1100 Subject: [PATCH 18/28] fixes test --- .../Runtimes/CoreRuntimeTests.cs | 42 ++----------------- 1 file changed, 3 insertions(+), 39 deletions(-) diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 44481666bc..08640f827a 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -136,48 +136,12 @@ namespace Umbraco.Tests.Runtimes return mock.Object; } - // FIXME: so how the f* should we do it now? - /* - // pretend we have the proper migration - // else BootFailedException because our mock IUmbracoDatabaseFactory does not provide databases - protected override bool EnsureUmbracoUpgradeState(IUmbracoDatabaseFactory databaseFactory) - { - return true; - } - */ - - //// because we don't even have the core runtime component, - //// there are a few required stuff that we need to compose - //public override void Compose(Composition composition) - //{ - // base.Compose(composition); - - // var scopeProvider = Mock.Of(); - // Mock.Get(scopeProvider) - // .Setup(x => x.CreateScope( - // It.IsAny(), - // It.IsAny(), - // It.IsAny(), - // It.IsAny(), - // It.IsAny(), - // It.IsAny())) - // .Returns(Mock.Of()); - - // composition.RegisterUnique(scopeProvider); - //} - - private IMainDom _mainDom; - public override IFactory Configure(IRegister container) { - var factory = base.Configure(container); - _mainDom = factory.GetInstance(); - return factory; - } + container.Register(Lifetime.Singleton); - public override void Terminate() - { - base.Terminate(); + var factory = base.Configure(container); + return factory; } // runs with only one single component From 07966b522597970c3e010c600075bed7438cf28c Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 17:19:12 +1100 Subject: [PATCH 19/28] more unused code --- src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 08640f827a..8443de7b09 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -104,11 +104,6 @@ namespace Umbraco.Tests.Runtimes return configs; } - private static IProfiler GetProfiler() - { - return new TestProfiler(); - } - public IRuntime Runtime { get; private set; } protected override IRuntime GetRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) From 2d506c1fd0290e51c253177c304030530fab0fd2 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 17:23:31 +1100 Subject: [PATCH 20/28] Adds container test showing how we can pre-resolve a service and ensures its the same on that gets used. --- .../ContainerTests.cs | 34 ++++++++++++++++++- src/Umbraco.Tests.Integration/RuntimeTests.cs | 31 ++--------------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/Umbraco.Tests.Integration/ContainerTests.cs b/src/Umbraco.Tests.Integration/ContainerTests.cs index f440944ab7..b439e32df1 100644 --- a/src/Umbraco.Tests.Integration/ContainerTests.cs +++ b/src/Umbraco.Tests.Integration/ContainerTests.cs @@ -1,4 +1,5 @@ -using LightInject; +using System.Threading.Tasks; +using LightInject; using LightInject.Microsoft.DependencyInjection; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -68,6 +69,37 @@ namespace Umbraco.Tests.Integration Assertions.AssertContainer(umbracoContainer.Container); } + [Explicit("This test just shows that resolving services from the container before the host is done resolves 2 different instances")] + [Test] + public async Task BuildServiceProvider_Before_Host_Is_Configured() + { + var umbracoContainer = RuntimeTests.GetUmbracoContainer(out var serviceProviderFactory); + + IHostApplicationLifetime lifetime1 = null; + + var hostBuilder = new HostBuilder() + .UseUmbraco(serviceProviderFactory) + .ConfigureServices((hostContext, services) => + { + // Resolve a service from the netcore container before the host has finished the ConfigureServices sequence + lifetime1 = services.BuildServiceProvider().GetRequiredService(); + + // Re-add as a callback, ensures its the same instance all the way through (hack) + services.AddSingleton(x => lifetime1); + }); + + var host = await hostBuilder.StartAsync(); + + var lifetime2 = host.Services.GetRequiredService(); + var lifetime3 = umbracoContainer.GetInstance(); + + lifetime1.StopApplication(); + Assert.IsTrue(lifetime1.ApplicationStopping.IsCancellationRequested); + Assert.AreEqual(lifetime1.ApplicationStopping.IsCancellationRequested, lifetime2.ApplicationStopping.IsCancellationRequested); + Assert.AreEqual(lifetime1.ApplicationStopping.IsCancellationRequested, lifetime3.ApplicationStopping.IsCancellationRequested); + + } + private class Foo { public Foo() diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index c9e0e94481..b12d02ca85 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -210,36 +210,9 @@ namespace Umbraco.Tests.Integration //Assert.AreEqual(RuntimeLevel.Run, runtimeState.Level); } - [Ignore("This test just shows that resolving services from the container before the host is done resolves 2 different instances")] - [Test] - public async Task BuildServiceProvider() + internal static LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory) { - var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); - - IHostApplicationLifetime lifetime1 = null; - - var hostBuilder = new HostBuilder() - .UseUmbraco(serviceProviderFactory) - .ConfigureServices((hostContext, services) => - { - // TODO: Try to re-register the service as a callback and see if it resolves to the same instance - - lifetime1 = services.BuildServiceProvider().GetRequiredService(); - }); - - var host = await hostBuilder.StartAsync(); - - var lifetime2 = host.Services.GetRequiredService(); - - lifetime1.StopApplication(); - Assert.IsTrue(lifetime1.ApplicationStopping.IsCancellationRequested); - Assert.AreEqual(lifetime1.ApplicationStopping.IsCancellationRequested, lifetime2.ApplicationStopping.IsCancellationRequested); - - } - - private LightInjectContainer GetUmbracoContainer(out UmbracoServiceProviderFactory serviceProviderFactory) - { - var container = new ServiceContainer(ContainerOptions.Default.Clone().WithMicrosoftSettings().WithAspNetCoreSettings()); + var container = UmbracoServiceProviderFactory.CreateServiceContainer(); serviceProviderFactory = new UmbracoServiceProviderFactory(container); var umbracoContainer = serviceProviderFactory.GetContainer(); return umbracoContainer; From 77ce21b0e32931cc99d9fbfa94a4d66d5f070bee Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 17:35:43 +1100 Subject: [PATCH 21/28] Adds notes/test about pre building the netcore container --- src/Umbraco.Tests.Integration/ContainerTests.cs | 8 ++++++++ .../AspNetCore/UmbracoCoreServiceCollectionExtensions.cs | 6 +++--- .../UmbracoWebsiteServiceCollectionExtensions.cs | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Tests.Integration/ContainerTests.cs b/src/Umbraco.Tests.Integration/ContainerTests.cs index b439e32df1..89cf2b5f7f 100644 --- a/src/Umbraco.Tests.Integration/ContainerTests.cs +++ b/src/Umbraco.Tests.Integration/ContainerTests.cs @@ -73,6 +73,14 @@ namespace Umbraco.Tests.Integration [Test] public async Task BuildServiceProvider_Before_Host_Is_Configured() { + // This is a test to show an anti-pattern used in netcore. This should be avoided in all cases if possible. + // There's a thread about this here: https://github.com/dotnet/aspnetcore/issues/14587 + // For some reason we are not being warned about this with our code analysis since we are using it + // in a couple of places but we should really try to see if we can avoid it. + // The test below shows how it could be possible to resolve an instance and then re-register it as a factory + // so that only one singleton instance is every created, but it's hacky and like Fowler says in that article + // it means the container won't be disposed, and maybe other services? not sure. + var umbracoContainer = RuntimeTests.GetUmbracoContainer(out var serviceProviderFactory); IHostApplicationLifetime lifetime1 = null; diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs index d283a7ffb1..20901822e3 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs @@ -29,6 +29,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore /// public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services) { + // TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured var serviceProvider = services.BuildServiceProvider(); var configuration = serviceProvider.GetService(); if (configuration == null) @@ -129,8 +130,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore out ILogger logger, out Configs configs, out IIOHelper ioHelper, out Core.Hosting.IHostingEnvironment hostingEnvironment, out IBackOfficeInfo backOfficeInfo, out IProfiler profiler) { - // TODO: Resolving services before the Host is done configuring this way means that the services resolved - // are not going to be the same instances that are going to be used within the application! + // TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured var serviceProvider = services.BuildServiceProvider(); var httpContextAccessor = serviceProvider.GetRequiredService(); @@ -148,7 +148,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore ioHelper = new IOHelper(hostingEnvironment, globalSettings); logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, new AspNetCoreSessionIdResolver(httpContextAccessor), - // need to build a new service provider since the one already resolved above doesn't have the IRequestCache yet + // TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured () => services.BuildServiceProvider().GetService(), coreDebug, ioHelper, new AspNetCoreMarchal()); diff --git a/src/Umbraco.Web.Website/AspNetCore/UmbracoWebsiteServiceCollectionExtensions.cs b/src/Umbraco.Web.Website/AspNetCore/UmbracoWebsiteServiceCollectionExtensions.cs index f7a198bc3b..6d2ce5e7e4 100644 --- a/src/Umbraco.Web.Website/AspNetCore/UmbracoWebsiteServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Website/AspNetCore/UmbracoWebsiteServiceCollectionExtensions.cs @@ -19,6 +19,7 @@ namespace Umbraco.Web.Website.AspNetCore { public static IServiceCollection AddUmbracoWebsite(this IServiceCollection services) { + // TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured var serviceProvider = services.BuildServiceProvider(); var configs = serviceProvider.GetService(); var imagingSettings = configs.Imaging(); From 926b0662e793bc32cb2f324ea7c8cdde8e6495c6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 17:39:36 +1100 Subject: [PATCH 22/28] another note --- src/Umbraco.Tests.Integration/ContainerTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Tests.Integration/ContainerTests.cs b/src/Umbraco.Tests.Integration/ContainerTests.cs index 89cf2b5f7f..945eeda2f0 100644 --- a/src/Umbraco.Tests.Integration/ContainerTests.cs +++ b/src/Umbraco.Tests.Integration/ContainerTests.cs @@ -80,6 +80,7 @@ namespace Umbraco.Tests.Integration // The test below shows how it could be possible to resolve an instance and then re-register it as a factory // so that only one singleton instance is every created, but it's hacky and like Fowler says in that article // it means the container won't be disposed, and maybe other services? not sure. + // In cases where we use it can we use IConfigureOptions? https://andrewlock.net/access-services-inside-options-and-startup-using-configureoptions/ var umbracoContainer = RuntimeTests.GetUmbracoContainer(out var serviceProviderFactory); From 1a8f422dce9442b1d725a97243169f488a894000 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 17:40:52 +1100 Subject: [PATCH 23/28] another note --- src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs index 10d5b10955..3e5361a1c1 100644 --- a/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs +++ b/src/Umbraco.Core/Net/IUmbracoApplicationLifetime.cs @@ -1,5 +1,6 @@ namespace Umbraco.Net { + // TODO: This shouldn't be in this namespace? public interface IUmbracoApplicationLifetime { /// From a5d728cc51f5c026dd62fc7c9a10a07c33e52d85 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Mar 2020 18:21:44 +1100 Subject: [PATCH 24/28] Reduce the usage of BuildServiceProvider --- src/Umbraco.Tests.Integration/RuntimeTests.cs | 31 ++++++++++--------- .../UmbracoCoreServiceCollectionExtensions.cs | 22 ++++++------- src/Umbraco.Web.UI.NetCore/Startup.cs | 20 ++++++++++-- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index b12d02ca85..0e11a29b95 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -94,18 +94,18 @@ namespace Umbraco.Tests.Integration public async Task AddUmbracoCore() { var umbracoContainer = GetUmbracoContainer(out var serviceProviderFactory); + var testHelper = new TestHelper(); var hostBuilder = new HostBuilder() .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => { - var testHelper = new TestHelper(); - - AddRequiredNetCoreServices(services, testHelper); + var webHostEnvironment = testHelper.GetWebHostEnvironment(); + AddRequiredNetCoreServices(services, testHelper, webHostEnvironment); // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + services.AddUmbracoConfiguration(hostContext.Configuration); + services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly); }); var host = await hostBuilder.StartAsync(); @@ -138,12 +138,13 @@ namespace Umbraco.Tests.Integration var hostBuilder = new HostBuilder() .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => - { - AddRequiredNetCoreServices(services, testHelper); + { + var webHostEnvironment = testHelper.GetWebHostEnvironment(); + AddRequiredNetCoreServices(services, testHelper, webHostEnvironment); // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + services.AddUmbracoConfiguration(hostContext.Configuration); + services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly); }); var host = await hostBuilder.StartAsync(); @@ -178,11 +179,12 @@ namespace Umbraco.Tests.Integration .UseUmbraco(serviceProviderFactory) .ConfigureServices((hostContext, services) => { - AddRequiredNetCoreServices(services, testHelper); + var webHostEnvironment = testHelper.GetWebHostEnvironment(); + AddRequiredNetCoreServices(services, testHelper, webHostEnvironment); // Add it! - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(umbracoContainer, GetType().Assembly); + services.AddUmbracoConfiguration(hostContext.Configuration); + services.AddUmbracoCore(webHostEnvironment, umbracoContainer, GetType().Assembly); }); var host = await hostBuilder.StartAsync(); @@ -223,11 +225,12 @@ namespace Umbraco.Tests.Integration /// /// /// - private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper) + /// + private void AddRequiredNetCoreServices(IServiceCollection services, TestHelper testHelper, IWebHostEnvironment webHostEnvironment) { services.AddSingleton(x => testHelper.GetHttpContextAccessor()); // the generic host does add IHostEnvironment but not this one because we are not actually in a web context - services.AddSingleton(x => testHelper.GetWebHostEnvironment()); + services.AddSingleton(x => webHostEnvironment); } [RuntimeLevel(MinLevel = RuntimeLevel.Install)] diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs index 20901822e3..d747cb349a 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoCoreServiceCollectionExtensions.cs @@ -26,14 +26,11 @@ namespace Umbraco.Web.BackOffice.AspNetCore /// Adds the Umbraco Configuration requirements /// /// + /// /// - public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services) + public static IServiceCollection AddUmbracoConfiguration(this IServiceCollection services, IConfiguration configuration) { - // TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured - var serviceProvider = services.BuildServiceProvider(); - var configuration = serviceProvider.GetService(); - if (configuration == null) - throw new InvalidOperationException($"Could not resolve {typeof(IConfiguration)} from the container"); + if (configuration == null) throw new ArgumentNullException(nameof(configuration)); var configsFactory = new AspNetCoreConfigsFactory(configuration); @@ -49,25 +46,27 @@ namespace Umbraco.Web.BackOffice.AspNetCore /// Adds the Umbraco Back Core requirements /// /// + /// /// - public static IServiceCollection AddUmbracoCore(this IServiceCollection services) + public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment) { if (!UmbracoServiceProviderFactory.IsActive) throw new InvalidOperationException("Ensure to add UseUmbraco() in your Program.cs after ConfigureWebHostDefaults to enable Umbraco's service provider factory"); var umbContainer = UmbracoServiceProviderFactory.UmbracoContainer; - return services.AddUmbracoCore(umbContainer, Assembly.GetEntryAssembly()); + return services.AddUmbracoCore(webHostEnvironment, umbContainer, Assembly.GetEntryAssembly()); } /// /// Adds the Umbraco Back Core requirements /// /// + /// /// /// /// - public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IRegister umbContainer, Assembly entryAssembly) + public static IServiceCollection AddUmbracoCore(this IServiceCollection services, IWebHostEnvironment webHostEnvironment, IRegister umbContainer, Assembly entryAssembly) { if (services is null) throw new ArgumentNullException(nameof(services)); if (umbContainer is null) throw new ArgumentNullException(nameof(umbContainer)); @@ -77,7 +76,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore // we resolve it before the host finishes configuring in the call to CreateCompositionRoot services.AddSingleton(); - CreateCompositionRoot(services, out var logger, out var configs, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler); + CreateCompositionRoot(services, webHostEnvironment, out var logger, out var configs, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler); var globalSettings = configs.Global(); var umbracoVersion = new UmbracoVersion(globalSettings); @@ -126,7 +125,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore return coreRuntime; } - private static void CreateCompositionRoot(IServiceCollection services, + private static void CreateCompositionRoot(IServiceCollection services, IWebHostEnvironment webHostEnvironment, out ILogger logger, out Configs configs, out IIOHelper ioHelper, out Core.Hosting.IHostingEnvironment hostingEnvironment, out IBackOfficeInfo backOfficeInfo, out IProfiler profiler) { @@ -134,7 +133,6 @@ namespace Umbraco.Web.BackOffice.AspNetCore var serviceProvider = services.BuildServiceProvider(); var httpContextAccessor = serviceProvider.GetRequiredService(); - var webHostEnvironment = serviceProvider.GetRequiredService(); configs = serviceProvider.GetService(); if (configs == null) diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs index ab8c6e021c..2753676452 100644 --- a/src/Umbraco.Web.UI.NetCore/Startup.cs +++ b/src/Umbraco.Web.UI.NetCore/Startup.cs @@ -16,13 +16,29 @@ namespace Umbraco.Web.UI.BackOffice { public class Startup { + private readonly IWebHostEnvironment _webHostEnvironment; + private readonly IConfiguration _config; + + /// + /// Constructor + /// + /// + /// + /// + /// Only a few services are possible to be injected here https://github.com/dotnet/aspnetcore/issues/9337 + /// + public Startup(IWebHostEnvironment webHostEnvironment, IConfiguration config) + { + _webHostEnvironment = webHostEnvironment ?? throw new ArgumentNullException(nameof(webHostEnvironment)); + _config = config ?? throw new ArgumentNullException(nameof(config)); + } // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { - services.AddUmbracoConfiguration(); - services.AddUmbracoCore(); + services.AddUmbracoConfiguration(_config); + services.AddUmbracoCore(_webHostEnvironment); services.AddUmbracoWebsite(); } From fee1f6f0ab5d56470e7387635bb7a63f9991b137 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Thu, 26 Mar 2020 15:30:25 +1100 Subject: [PATCH 25/28] Update src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs Co-Authored-By: Bjarke Berg --- .../Implementations/HostBuilderExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs index b0b664484b..9f1d0b21c4 100644 --- a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs @@ -16,7 +16,7 @@ namespace Umbraco.Tests.Integration.Implementations { // Need to register SqlClient manually // TODO: Move this to someplace central - DbProviderFactories.RegisterFactory("System.Data.SqlClient", SqlClientFactory.Instance); + DbProviderFactories.RegisterFactory(Constants.DbProviderNames.SqlServer, SqlClientFactory.Instance); hostBuilder.ConfigureAppConfiguration(x => { From 9bb999728867ab9cfc350dc89b1c2a7824c87e3b Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Thu, 26 Mar 2020 15:31:27 +1100 Subject: [PATCH 26/28] Update src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs Co-Authored-By: Bjarke Berg --- .../Implementations/HostBuilderExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs index 9f1d0b21c4..6be56a547b 100644 --- a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs @@ -28,7 +28,7 @@ namespace Umbraco.Tests.Integration.Implementations x.AddInMemoryCollection(new[] { - new KeyValuePair("ConnectionStrings:umbracoDbDSN", instance.GetConnectionString(dbName)) + new KeyValuePair($"ConnectionStrings:{Constants.System.UmbracoConnectionName}", instance.GetConnectionString(dbName)) }); }); return hostBuilder; From 29293bd25a67efeb0f8cca0cf6a7e41b0fe9cde9 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Thu, 26 Mar 2020 15:32:39 +1100 Subject: [PATCH 27/28] Update src/Umbraco.Tests.Integration/Implementations/TestHelper.cs Co-Authored-By: Bjarke Berg --- src/Umbraco.Tests.Integration/Implementations/TestHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index d218513ce3..ccbf7b03d4 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -63,7 +63,7 @@ namespace Umbraco.Tests.Integration.Implementations public IWebHostEnvironment GetWebHostEnvironment() => _hostEnvironment; - public override IDbProviderFactoryCreator DbProviderFactoryCreator => new SqlServerDbProviderFactoryCreator("System.Data.SqlClient", DbProviderFactories.GetFactory); + public override IDbProviderFactoryCreator DbProviderFactoryCreator => new SqlServerDbProviderFactoryCreator(Constants.DbProviderNames.SqlServer, DbProviderFactories.GetFactory); public override IBulkSqlInsertProvider BulkSqlInsertProvider => new SqlServerBulkSqlInsertProvider(); From f24cae51d885ed7e71e0f94be8334246224f1e50 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 26 Mar 2020 15:39:20 +1100 Subject: [PATCH 28/28] Renames IHostingEnvironmentLifetime to IApplicationShutdownRegistry --- ...ime.cs => IApplicationShutdownRegistry.cs} | 2 +- src/Umbraco.Core/Runtime/IMainDom.cs | 2 +- src/Umbraco.Core/Runtime/MainDom.cs | 9 ++++--- src/Umbraco.Core/SimpleMainDom.cs | 2 +- ...aseServerRegistrarAndMessengerComponent.cs | 2 +- .../Runtime/CoreRuntime.cs | 25 ++++--------------- .../Scheduling/BackgroundTaskRunner.cs | 10 ++++---- .../Scheduling/SchedulerComponent.cs | 4 +-- .../Search/BackgroundIndexRebuilder.cs | 4 +-- .../PureLiveModelFactory.cs | 4 +-- src/Umbraco.Tests.Common/TestHelperBase.cs | 2 +- .../Implementations/HostBuilderExtensions.cs | 1 + .../Implementations/TestHelper.cs | 6 ++--- .../XmlPublishedSnapshotService.cs | 6 ++--- .../LegacyXmlPublishedCache/XmlStore.cs | 6 ++--- .../Runtimes/CoreRuntimeTests.cs | 2 +- .../Scheduling/BackgroundTaskRunnerTests.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestHelper.cs | 6 ++--- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- ... AspNetCoreApplicationShutdownRegistry.cs} | 4 +-- .../AspNetCore/AspNetCoreComposer.cs | 2 +- ...oBackOfficeApplicationBuilderExtensions.cs | 6 ++--- ...s => AspNetApplicationShutdownRegistry.cs} | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 2 +- 24 files changed, 50 insertions(+), 63 deletions(-) rename src/Umbraco.Core/Hosting/{IHostingEnvironmentLifetime.cs => IApplicationShutdownRegistry.cs} (78%) rename src/Umbraco.Web.BackOffice/AspNetCore/{AspNetCoreHostingEnvironmentShutdown.cs => AspNetCoreApplicationShutdownRegistry.cs} (90%) rename src/Umbraco.Web/AspNet/{AspNetHostingLifetime.cs => AspNetApplicationShutdownRegistry.cs} (94%) diff --git a/src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs b/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs similarity index 78% rename from src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs rename to src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs index 891cedad20..93441f1a47 100644 --- a/src/Umbraco.Core/Hosting/IHostingEnvironmentLifetime.cs +++ b/src/Umbraco.Core/Hosting/IApplicationShutdownRegistry.cs @@ -1,6 +1,6 @@ namespace Umbraco.Core.Hosting { - public interface IHostingEnvironmentLifetime + public interface IApplicationShutdownRegistry { void RegisterObject(IRegisteredObject registeredObject); void UnregisterObject(IRegisteredObject registeredObject); diff --git a/src/Umbraco.Core/Runtime/IMainDom.cs b/src/Umbraco.Core/Runtime/IMainDom.cs index 1b7f09bc89..93a560ff7d 100644 --- a/src/Umbraco.Core/Runtime/IMainDom.cs +++ b/src/Umbraco.Core/Runtime/IMainDom.cs @@ -26,7 +26,7 @@ namespace Umbraco.Core /// /// /// - bool Acquire(IHostingEnvironmentLifetime hostingEnvironment); + bool Acquire(IApplicationShutdownRegistry hostingEnvironment); /// /// Registers a resource that requires the current AppDomain to be the main domain to function. diff --git a/src/Umbraco.Core/Runtime/MainDom.cs b/src/Umbraco.Core/Runtime/MainDom.cs index 0a4a250aa6..81db1b700d 100644 --- a/src/Umbraco.Core/Runtime/MainDom.cs +++ b/src/Umbraco.Core/Runtime/MainDom.cs @@ -21,7 +21,7 @@ namespace Umbraco.Core.Runtime #region Vars private readonly ILogger _logger; - private IHostingEnvironmentLifetime _hostingEnvironment; + private IApplicationShutdownRegistry _hostingEnvironment; private readonly IMainDomLock _mainDomLock; // our own lock for local consistency @@ -50,9 +50,10 @@ namespace Umbraco.Core.Runtime #endregion - public bool Acquire(IHostingEnvironmentLifetime hostingEnvironment) + public bool Acquire(IApplicationShutdownRegistry hostingEnvironment) { - _hostingEnvironment = hostingEnvironment; + _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); + return LazyInitializer.EnsureInitialized(ref _isMainDom, ref _isInitialized, ref _locko, () => { hostingEnvironment.RegisterObject(this); @@ -199,7 +200,7 @@ namespace Umbraco.Core.Runtime // The web app is stopping, need to wind down Dispose(true); - _hostingEnvironment.UnregisterObject(this); + _hostingEnvironment?.UnregisterObject(this); } #region IDisposable Support diff --git a/src/Umbraco.Core/SimpleMainDom.cs b/src/Umbraco.Core/SimpleMainDom.cs index 52ed6c1d91..e6bdda67d7 100644 --- a/src/Umbraco.Core/SimpleMainDom.cs +++ b/src/Umbraco.Core/SimpleMainDom.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core public bool IsMainDom { get; private set; } = true; // always acquire - public bool Acquire(IHostingEnvironmentLifetime hostingEnvironment) => true; + public bool Acquire(IApplicationShutdownRegistry hostingEnvironment) => true; /// public bool Register(Action release, int weight = 100) diff --git a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs index 4e183b9211..6c745f3877 100644 --- a/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs +++ b/src/Umbraco.Infrastructure/Compose/DatabaseServerRegistrarAndMessengerComponent.cs @@ -99,7 +99,7 @@ namespace Umbraco.Web.Compose IServerMessenger serverMessenger, IServerRegistrationService registrationService, ILogger logger, - IHostingEnvironmentLifetime hostingEnvironment, + IApplicationShutdownRegistry hostingEnvironment, IRequestAccessor requestAccessor) { _runtime = runtime; diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs index 89ec036607..139e9e9b67 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs @@ -28,21 +28,6 @@ namespace Umbraco.Core.Runtime private readonly IGlobalSettings _globalSettings; private readonly IConnectionStrings _connectionStrings; - - /// - /// Constructor - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// public CoreRuntime( Configs configs, IUmbracoVersion umbracoVersion, @@ -251,12 +236,12 @@ namespace Umbraco.Core.Runtime // run handlers RuntimeOptions.DoRuntimeEssentials(_factory); - var hostingEnvironmentLifetime = _factory.TryGetInstance(); + var hostingEnvironmentLifetime = _factory.TryGetInstance(); if (hostingEnvironmentLifetime == null) - throw new InvalidOperationException($"An instance of {typeof(IHostingEnvironmentLifetime)} could not be resolved from the container, ensure that one if registered in your runtime before calling {nameof(IRuntime)}.{nameof(Start)}"); + throw new InvalidOperationException($"An instance of {typeof(IApplicationShutdownRegistry)} could not be resolved from the container, ensure that one if registered in your runtime before calling {nameof(IRuntime)}.{nameof(Start)}"); // acquire the main domain - if this fails then anything that should be registered with MainDom will not operate - AcquireMainDom(MainDom, _factory.GetInstance()); + AcquireMainDom(MainDom, _factory.GetInstance()); // create & initialize the components _components = _factory.GetInstance(); @@ -287,13 +272,13 @@ namespace Umbraco.Core.Runtime IOHelper.SetRootDirectory(path); } - private bool AcquireMainDom(IMainDom mainDom, IHostingEnvironmentLifetime hostingEnvironmentLifetime) + private bool AcquireMainDom(IMainDom mainDom, IApplicationShutdownRegistry applicationShutdownRegistry) { using (var timer = ProfilingLogger.DebugDuration("Acquiring MainDom.", "Acquired.")) { try { - return mainDom.Acquire(hostingEnvironmentLifetime); + return mainDom.Acquire(applicationShutdownRegistry); } catch { diff --git a/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs b/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs index 31884992f7..2cda289591 100644 --- a/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs +++ b/src/Umbraco.Infrastructure/Scheduling/BackgroundTaskRunner.cs @@ -81,7 +81,7 @@ namespace Umbraco.Web.Scheduling private readonly string _logPrefix; private readonly BackgroundTaskRunnerOptions _options; private readonly ILogger _logger; - private readonly IHostingEnvironmentLifetime _hostingEnvironment; + private readonly IApplicationShutdownRegistry _hostingEnvironment; private readonly object _locker = new object(); private readonly BufferBlock _tasks = new BufferBlock(new DataflowBlockOptions()); @@ -105,7 +105,7 @@ namespace Umbraco.Web.Scheduling /// A logger. /// The hosting environment /// An optional main domain hook. - public BackgroundTaskRunner(ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null) + public BackgroundTaskRunner(ILogger logger, IApplicationShutdownRegistry hostingEnvironment, MainDomHook hook = null) : this(typeof(T).FullName, new BackgroundTaskRunnerOptions(), logger, hostingEnvironment, hook) { } @@ -116,7 +116,7 @@ namespace Umbraco.Web.Scheduling /// A logger. /// The hosting environment /// An optional main domain hook. - public BackgroundTaskRunner(string name, ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null) + public BackgroundTaskRunner(string name, ILogger logger, IApplicationShutdownRegistry hostingEnvironment, MainDomHook hook = null) : this(name, new BackgroundTaskRunnerOptions(), logger, hostingEnvironment, hook) { } @@ -127,7 +127,7 @@ namespace Umbraco.Web.Scheduling /// A logger. /// The hosting environment /// An optional main domain hook. - public BackgroundTaskRunner(BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null) + public BackgroundTaskRunner(BackgroundTaskRunnerOptions options, ILogger logger, IApplicationShutdownRegistry hostingEnvironment, MainDomHook hook = null) : this(typeof(T).FullName, options, logger, hostingEnvironment, hook) { } @@ -139,7 +139,7 @@ namespace Umbraco.Web.Scheduling /// A logger. /// The hosting environment /// An optional main domain hook. - public BackgroundTaskRunner(string name, BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null) + public BackgroundTaskRunner(string name, BackgroundTaskRunnerOptions options, ILogger logger, IApplicationShutdownRegistry hostingEnvironment, MainDomHook hook = null) { _options = options ?? throw new ArgumentNullException(nameof(options)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); diff --git a/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs b/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs index c867d81d69..30d0bc7e4a 100644 --- a/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs +++ b/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web.Scheduling private readonly IContentService _contentService; private readonly IAuditService _auditService; private readonly IProfilingLogger _logger; - private readonly IHostingEnvironmentLifetime _hostingEnvironment; + private readonly IApplicationShutdownRegistry _hostingEnvironment; private readonly IScopeProvider _scopeProvider; private readonly HealthCheckCollection _healthChecks; private readonly HealthCheckNotificationMethodCollection _notifications; @@ -57,7 +57,7 @@ namespace Umbraco.Web.Scheduling IContentService contentService, IAuditService auditService, HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications, IScopeProvider scopeProvider, IUmbracoContextFactory umbracoContextFactory, IProfilingLogger logger, - IHostingEnvironmentLifetime hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig, + IApplicationShutdownRegistry hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig, IIOHelper ioHelper, IServerMessenger serverMessenger, IRequestAccessor requestAccessor, ILoggingSettings loggingSettings, IKeepAliveSettings keepAliveSettings) { diff --git a/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs b/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs index fa697a4743..1946e2041b 100644 --- a/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs +++ b/src/Umbraco.Infrastructure/Search/BackgroundIndexRebuilder.cs @@ -18,10 +18,10 @@ namespace Umbraco.Web.Search private readonly IndexRebuilder _indexRebuilder; private readonly IMainDom _mainDom; private readonly IProfilingLogger _logger; - private readonly IHostingEnvironmentLifetime _hostingEnvironment; + private readonly IApplicationShutdownRegistry _hostingEnvironment; private static BackgroundTaskRunner _rebuildOnStartupRunner; - public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IHostingEnvironmentLifetime hostingEnvironment, IndexRebuilder indexRebuilder) + public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IApplicationShutdownRegistry hostingEnvironment, IndexRebuilder indexRebuilder) { _mainDom = mainDom; _logger = logger; diff --git a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs index 3c189cc045..3cfefa77ce 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs @@ -42,7 +42,7 @@ namespace Umbraco.ModelsBuilder.Embedded private static readonly string[] OurFiles = { "models.hash", "models.generated.cs", "all.generated.cs", "all.dll.path", "models.err" }; private readonly IModelsBuilderConfig _config; - private readonly IHostingEnvironmentLifetime _hostingLifetime; + private readonly IApplicationShutdownRegistry _hostingLifetime; private readonly IIOHelper _ioHelper; private readonly ModelsGenerationError _errors; @@ -51,7 +51,7 @@ namespace Umbraco.ModelsBuilder.Embedded IProfilingLogger logger, IModelsBuilderConfig config, IHostingEnvironment hostingEnvironment, - IHostingEnvironmentLifetime hostingLifetime, + IApplicationShutdownRegistry hostingLifetime, IIOHelper ioHelper) { _umbracoServices = umbracoServices; diff --git a/src/Umbraco.Tests.Common/TestHelperBase.cs b/src/Umbraco.Tests.Common/TestHelperBase.cs index 22177c1a50..67108833c3 100644 --- a/src/Umbraco.Tests.Common/TestHelperBase.cs +++ b/src/Umbraco.Tests.Common/TestHelperBase.cs @@ -128,7 +128,7 @@ namespace Umbraco.Tests.Common } public abstract IHostingEnvironment GetHostingEnvironment(); - public abstract IHostingEnvironmentLifetime GetHostingEnvironmentLifetime(); + public abstract IApplicationShutdownRegistry GetHostingEnvironmentLifetime(); public abstract IIpResolver GetIpResolver(); diff --git a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs index 6be56a547b..60cac26349 100644 --- a/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/Implementations/HostBuilderExtensions.cs @@ -5,6 +5,7 @@ using System.Data.SqlClient; using System.IO; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; +using Umbraco.Core; using Umbraco.Tests.Integration.Testing; namespace Umbraco.Tests.Integration.Implementations diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs index ccbf7b03d4..4a986fa35a 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHelper.cs @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Integration.Implementations { private IBackOfficeInfo _backOfficeInfo; private readonly IHostingEnvironment _hostingEnvironment; - private readonly IHostingEnvironmentLifetime _hostingLifetime; + private readonly IApplicationShutdownRegistry _hostingLifetime; private readonly IIpResolver _ipResolver; private readonly IWebHostEnvironment _hostEnvironment; private readonly IHttpContextAccessor _httpContextAccessor; @@ -46,7 +46,7 @@ namespace Umbraco.Tests.Integration.Implementations _hostEnvironment, _httpContextAccessor); - _hostingLifetime = new AspNetCoreHostingEnvironmentLifetime(Mock.Of()); + _hostingLifetime = new AspNetCoreApplicationShutdownRegistry(Mock.Of()); Logger = new ProfilingLogger(new ConsoleLogger(new MessageTemplates()), Profiler); } @@ -77,7 +77,7 @@ namespace Umbraco.Tests.Integration.Implementations } public override IHostingEnvironment GetHostingEnvironment() => _hostingEnvironment; - public override IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() => _hostingLifetime; + public override IApplicationShutdownRegistry GetHostingEnvironmentLifetime() => _hostingLifetime; public override IIpResolver GetIpResolver() => _ipResolver; diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs index 5eb57b6ca6..bf7cbe40c4 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs @@ -41,7 +41,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache private readonly IEntityXmlSerializer _entitySerializer; private readonly IVariationContextAccessor _variationContextAccessor; private readonly IUmbracoContextAccessor _umbracoContextAccessor; - private readonly IHostingEnvironmentLifetime _hostingLifetime; + private readonly IApplicationShutdownRegistry _hostingLifetime; private readonly IHostingEnvironment _hostingEnvironment; #region Constructors @@ -58,7 +58,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache ILogger logger, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, - IHostingEnvironmentLifetime hostingLifetime, + IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper, ISiteDomainHelper siteDomainHelper, IEntityXmlSerializer entitySerializer, @@ -86,7 +86,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache ILogger logger, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, - IHostingEnvironmentLifetime hostingLifetime, + IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper, ISiteDomainHelper siteDomainHelper, IEntityXmlSerializer entitySerializer, diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs index b051682ed7..dadf8b6824 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlStore.cs @@ -46,7 +46,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache private readonly IMediaRepository _mediaRepository; private readonly IMemberRepository _memberRepository; private readonly IEntityXmlSerializer _entitySerializer; - private readonly IHostingEnvironmentLifetime _hostingLifetime; + private readonly IApplicationShutdownRegistry _hostingLifetime; private readonly IShortStringHelper _shortStringHelper; private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; private readonly PublishedContentTypeCache _contentTypeCache; @@ -65,7 +65,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache /// /// The default constructor will boot the cache, load data from file or database, /// wire events in order to manage changes, etc. public XmlStore(IContentTypeService contentTypeService, IContentService contentService, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, - IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper) + IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper) : this(contentTypeService, contentService, scopeProvider, routesCache, contentTypeCache, publishedSnapshotAccessor, mainDom, false, false, documentRepository, mediaRepository, memberRepository, entitySerializer, hostingEnvironment, hostingLifetime, shortStringHelper) { } @@ -74,7 +74,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache // TODO: er, we DO have a DB? internal XmlStore(IContentTypeService contentTypeService, IContentService contentService, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache, IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, - bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper) + bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper) { if (testing == false) EnsureConfigurationIsValid(); diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 8443de7b09..6ccb2c3b35 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -133,7 +133,7 @@ namespace Umbraco.Tests.Runtimes public override IFactory Configure(IRegister container) { - container.Register(Lifetime.Singleton); + container.Register(Lifetime.Singleton); var factory = base.Configure(container); return factory; diff --git a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs index 18eb3d19a4..2291584f66 100644 --- a/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs +++ b/src/Umbraco.Tests/Scheduling/BackgroundTaskRunnerTests.cs @@ -19,7 +19,7 @@ namespace Umbraco.Tests.Scheduling public class BackgroundTaskRunnerTests { private ILogger _logger; - private IHostingEnvironmentLifetime _hostingEnvironment; + private IApplicationShutdownRegistry _hostingEnvironment; [OneTimeSetUp] public void InitializeFixture() diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index 9cc9059499..11393e3e6b 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -62,8 +62,8 @@ namespace Umbraco.Tests.TestHelpers public override IHostingEnvironment GetHostingEnvironment() => new AspNetHostingEnvironment(SettingsForTests.GetDefaultHostingSettings()); - public override IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() - => new AspNetHostingLifetime(); + public override IApplicationShutdownRegistry GetHostingEnvironmentLifetime() + => new AspNetApplicationShutdownRegistry(); public override IIpResolver GetIpResolver() => new AspNetIpResolver(); @@ -323,7 +323,7 @@ namespace Umbraco.Tests.TestHelpers public static IHostingEnvironment GetHostingEnvironment() => _testHelperInternal.GetHostingEnvironment(); - public static IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() => _testHelperInternal.GetHostingEnvironmentLifetime(); + public static IApplicationShutdownRegistry GetHostingEnvironmentLifetime() => _testHelperInternal.GetHostingEnvironmentLifetime(); public static IIpResolver GetIpResolver() => _testHelperInternal.GetIpResolver(); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 96576ac9a4..0345aab2da 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -140,7 +140,7 @@ namespace Umbraco.Tests.Testing protected virtual IProfilingLogger ProfilingLogger => Factory.GetInstance(); protected IHostingEnvironment HostingEnvironment { get; } = new AspNetHostingEnvironment(TestHelpers.SettingsForTests.GetDefaultHostingSettings()); - protected IHostingEnvironmentLifetime HostingLifetime { get; } = new AspNetHostingLifetime(); + protected IApplicationShutdownRegistry HostingLifetime { get; } = new AspNetApplicationShutdownRegistry(); protected IIpResolver IpResolver => Factory.GetInstance(); protected IBackOfficeInfo BackOfficeInfo => Factory.GetInstance(); protected AppCaches AppCaches => Factory.GetInstance(); diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs similarity index 90% rename from src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.cs rename to src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs index 3726e50e3b..92af822836 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreHostingEnvironmentShutdown.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreApplicationShutdownRegistry.cs @@ -7,13 +7,13 @@ using Umbraco.Core.Hosting; namespace Umbraco.Web.BackOffice.AspNetCore { - public class AspNetCoreHostingEnvironmentLifetime : IHostingEnvironmentLifetime + public class AspNetCoreApplicationShutdownRegistry : IApplicationShutdownRegistry { private readonly IHostApplicationLifetime _hostApplicationLifetime; private readonly ConcurrentDictionary _registeredObjects = new ConcurrentDictionary(); - public AspNetCoreHostingEnvironmentLifetime(IHostApplicationLifetime hostApplicationLifetime) + public AspNetCoreApplicationShutdownRegistry(IHostApplicationLifetime hostApplicationLifetime) { _hostApplicationLifetime = hostApplicationLifetime; } diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs index 3c65c24b1f..fc38e429a0 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/AspNetCoreComposer.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore // Our own netcore implementations composition.RegisterUnique(); - composition.RegisterUnique(); + composition.RegisterUnique(); } } } diff --git a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs index feb122a48b..770f4b883f 100644 --- a/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/AspNetCore/UmbracoBackOfficeApplicationBuilderExtensions.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore if (app == null) throw new ArgumentNullException(nameof(app)); // Register a listener for application shutdown in order to terminate the runtime - var hostLifetime = app.ApplicationServices.GetRequiredService(); + var hostLifetime = app.ApplicationServices.GetRequiredService(); var runtime = app.ApplicationServices.GetRequiredService(); var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime); hostLifetime.RegisterObject(runtimeShutdown); @@ -43,7 +43,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore /// private class CoreRuntimeShutdown : IRegisteredObject { - public CoreRuntimeShutdown(IRuntime runtime, IHostingEnvironmentLifetime hostLifetime) + public CoreRuntimeShutdown(IRuntime runtime, IApplicationShutdownRegistry hostLifetime) { _runtime = runtime; _hostLifetime = hostLifetime; @@ -51,7 +51,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore private bool _completed = false; private readonly IRuntime _runtime; - private readonly IHostingEnvironmentLifetime _hostLifetime; + private readonly IApplicationShutdownRegistry _hostLifetime; public void Stop(bool immediate) { diff --git a/src/Umbraco.Web/AspNet/AspNetHostingLifetime.cs b/src/Umbraco.Web/AspNet/AspNetApplicationShutdownRegistry.cs similarity index 94% rename from src/Umbraco.Web/AspNet/AspNetHostingLifetime.cs rename to src/Umbraco.Web/AspNet/AspNetApplicationShutdownRegistry.cs index 316ecb8389..dbd6e9e834 100644 --- a/src/Umbraco.Web/AspNet/AspNetHostingLifetime.cs +++ b/src/Umbraco.Web/AspNet/AspNetApplicationShutdownRegistry.cs @@ -6,7 +6,7 @@ using IRegisteredObject = Umbraco.Core.IRegisteredObject; namespace Umbraco.Web.Hosting { - public class AspNetHostingLifetime : IHostingEnvironmentLifetime + public class AspNetApplicationShutdownRegistry : IApplicationShutdownRegistry { private readonly ConcurrentDictionary _registeredObjects = new ConcurrentDictionary(); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index ce08d5498d..4b4f06ad2a 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -134,7 +134,7 @@ - +