Files
Umbraco-CMS/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Components/ComponentTests.cs

643 lines
26 KiB
C#
Raw Normal View History

// Copyright (c) Umbraco.
// See LICENSE for more details.
using System;
2016-08-25 15:09:51 +02:00
using System.Collections.Generic;
2019-11-11 18:56:14 +11:00
using System.IO;
2016-12-15 08:57:23 +01:00
using System.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
2020-09-17 11:35:29 +02:00
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
2016-08-25 15:09:51 +02:00
using Moq;
using NUnit.Framework;
2021-04-26 21:09:06 +02:00
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Configuration;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Logging;
using Umbraco.Cms.Core.Scoping;
Netcore: File systems rework (#10181) * Allow IMediaFileSystem to be replace in the DI, or registered with inner filesystem * Remove GetFileSystem from Filesystems It was only used by tests. * Make MediaFileSystem inherit from PhysicalFileSystem directly * Remove FileSystemWrapper * Remove inner filesystem from MediaFileSystem * Add MediaFileManager and bare minimum to make it testable * Remove MediaFileSystem * Fix unit tests using MediaFileManager * Remove IFileSystem and rely only on FileSystem * Hide dangerous methods in FileSystems and do some cleaning * Apply stylecop warnings to MediaFileManager * Add FilesystemsCreator to Tests.Common This allows you to create an instance if FileSystems with your own specified IFileSystem for testing purposes outside our own test suite. * Allow the stylesheet filesystem to be replaced. * Fix tests * Don't save stylesheetWrapper in a temporary var * refactor(FileSystems): change how stylesheet filesystem is registered * fix(FileSystems): unable to overwrite media filesystem SetMediaFileSystem added the MediaManager as a Singleton instead of replacing the existing instance. * fix(FileSystems): calling AddFileSystems replaces MediaManager When calling AddFileSystems after SetMediaFileSystem the MediaManager gets replaced by the default PhysicalFileSystem, so instead of calling SetMediaFileSystem in AddFileSystems we now call TrySetMediaFileSystem instead. This method will not replace any existing instance of the MediaManager if there's already a MediaManager registered. * Use SetMediaFileSystem instead of TrySet, and rename AddFilesystems to ConfigureFileSystems Also don't call AddFileSystems again in ConfigureFilesystems * Don't wrap CSS filesystem twice * Add CreateShadowWrapperInternal to avoid casting * Throw UnauthorizedAccessException isntead of InvalidOperationException * Remove ResetShadowId Co-authored-by: Rasmus John Pedersen <mail@rjp.dk>
2021-04-27 09:52:17 +02:00
using Umbraco.Cms.Core.Strings;
using Umbraco.Cms.Infrastructure.Migrations.Install;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Cms.Infrastructure.Persistence.Mappers;
using Umbraco.Cms.Tests.UnitTests.TestHelpers;
2016-08-25 15:09:51 +02:00
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
2016-08-25 15:09:51 +02:00
{
[TestFixture]
2016-11-05 19:23:55 +01:00
public class ComponentTests
2016-08-25 15:09:51 +02:00
{
private static readonly List<Type> Composed = new List<Type>();
private static readonly IIOHelper IOHelper = TestHelper.IOHelper;
2019-01-07 09:30:47 +01:00
private static readonly List<Type> Initialized = new List<Type>();
private static readonly List<Type> Terminated = new List<Type>();
2016-08-25 15:09:51 +02:00
private static IServiceProvider MockFactory(Action<Mock<IServiceProvider>> setup = null)
2016-11-05 19:23:55 +01:00
{
// FIXME: use IUmbracoDatabaseFactory vs UmbracoDatabaseFactory, clean it all up!
var mock = new Mock<IServiceProvider>();
NullLoggerFactory loggerFactory = NullLoggerFactory.Instance;
ILogger logger = loggerFactory.CreateLogger("GenericLogger");
2020-09-21 21:06:24 +02:00
var globalSettings = new GlobalSettings();
var connectionStrings = new ConnectionStrings();
var mapperCollection = new NPocoMapperCollection(() => new[] { new NullableDateMapper() });
Merge commit '94d525d88f713b36419f28bfda4d82ee68637d83' into v9/dev # Conflicts: # build/NuSpecs/UmbracoCms.Web.nuspec # src/Umbraco.Core/Composing/Current.cs # src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs # src/Umbraco.Core/Runtime/CoreRuntime.cs # src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs # src/Umbraco.Infrastructure/Persistence/NPocoDatabaseExtensions.cs # src/Umbraco.Infrastructure/Persistence/UmbracoDatabase.cs # src/Umbraco.Persistence.SqlCe/SqlCeSyntaxProvider.cs # src/Umbraco.PublishedCache.NuCache/DataSource/BTree.cs # src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataModel.cs # src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataSerializationResult.cs # src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataSerializerEntityType.cs # src/Umbraco.PublishedCache.NuCache/DataSource/ContentData.cs # src/Umbraco.PublishedCache.NuCache/DataSource/ContentNestedData.cs # src/Umbraco.PublishedCache.NuCache/DataSource/CultureVariation.cs # src/Umbraco.PublishedCache.NuCache/DataSource/IContentCacheDataSerializer.cs # src/Umbraco.PublishedCache.NuCache/DataSource/IContentCacheDataSerializerFactory.cs # src/Umbraco.PublishedCache.NuCache/DataSource/IDictionaryOfPropertyDataSerializer.cs # src/Umbraco.PublishedCache.NuCache/DataSource/JsonContentNestedDataSerializer.cs # src/Umbraco.PublishedCache.NuCache/DataSource/JsonContentNestedDataSerializerFactory.cs # src/Umbraco.PublishedCache.NuCache/DataSource/LazyCompressedString.cs # src/Umbraco.PublishedCache.NuCache/DataSource/MsgPackContentNestedDataSerializer.cs # src/Umbraco.PublishedCache.NuCache/DataSource/MsgPackContentNestedDataSerializerFactory.cs # src/Umbraco.PublishedCache.NuCache/DataSource/PropertyData.cs # src/Umbraco.PublishedCache.NuCache/NuCacheSerializerComponent.cs # src/Umbraco.PublishedCache.NuCache/NuCacheSerializerComposer.cs # src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentTypeServiceVariantsTests.cs # src/Umbraco.Tests/App.config # src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs # src/Umbraco.Tests/PublishedContent/NuCacheTests.cs # src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs # src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml # src/Umbraco.Web.UI/web.Template.Debug.config # src/Umbraco.Web.UI/web.Template.config # src/Umbraco.Web/Composing/ModuleInjector.cs # src/Umbraco.Web/Editors/NuCacheStatusController.cs # src/Umbraco.Web/PublishedCache/NuCache/DataSource/ContentNestedData.cs # src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs # src/Umbraco.Web/PublishedCache/NuCache/NuCacheComposer.cs # src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs # src/Umbraco.Web/Runtime/WebRuntime.cs
2021-06-24 09:43:57 -06:00
var f = new UmbracoDatabaseFactory(
loggerFactory.CreateLogger<UmbracoDatabaseFactory>(),
loggerFactory,
Options.Create(globalSettings),
Mock.Of<IOptionsMonitor<ConnectionStrings>>(x => x.CurrentValue == connectionStrings),
new MapperCollection(() => Enumerable.Empty<BaseMapper>()),
Merge commit '94d525d88f713b36419f28bfda4d82ee68637d83' into v9/dev # Conflicts: # build/NuSpecs/UmbracoCms.Web.nuspec # src/Umbraco.Core/Composing/Current.cs # src/Umbraco.Core/Persistence/NPocoDatabaseExtensions-Bulk.cs # src/Umbraco.Core/Runtime/CoreRuntime.cs # src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs # src/Umbraco.Infrastructure/Persistence/NPocoDatabaseExtensions.cs # src/Umbraco.Infrastructure/Persistence/UmbracoDatabase.cs # src/Umbraco.Persistence.SqlCe/SqlCeSyntaxProvider.cs # src/Umbraco.PublishedCache.NuCache/DataSource/BTree.cs # src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataModel.cs # src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataSerializationResult.cs # src/Umbraco.PublishedCache.NuCache/DataSource/ContentCacheDataSerializerEntityType.cs # src/Umbraco.PublishedCache.NuCache/DataSource/ContentData.cs # src/Umbraco.PublishedCache.NuCache/DataSource/ContentNestedData.cs # src/Umbraco.PublishedCache.NuCache/DataSource/CultureVariation.cs # src/Umbraco.PublishedCache.NuCache/DataSource/IContentCacheDataSerializer.cs # src/Umbraco.PublishedCache.NuCache/DataSource/IContentCacheDataSerializerFactory.cs # src/Umbraco.PublishedCache.NuCache/DataSource/IDictionaryOfPropertyDataSerializer.cs # src/Umbraco.PublishedCache.NuCache/DataSource/JsonContentNestedDataSerializer.cs # src/Umbraco.PublishedCache.NuCache/DataSource/JsonContentNestedDataSerializerFactory.cs # src/Umbraco.PublishedCache.NuCache/DataSource/LazyCompressedString.cs # src/Umbraco.PublishedCache.NuCache/DataSource/MsgPackContentNestedDataSerializer.cs # src/Umbraco.PublishedCache.NuCache/DataSource/MsgPackContentNestedDataSerializerFactory.cs # src/Umbraco.PublishedCache.NuCache/DataSource/PropertyData.cs # src/Umbraco.PublishedCache.NuCache/NuCacheSerializerComponent.cs # src/Umbraco.PublishedCache.NuCache/NuCacheSerializerComposer.cs # src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentTypeServiceVariantsTests.cs # src/Umbraco.Tests/App.config # src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs # src/Umbraco.Tests/PublishedContent/NuCacheTests.cs # src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs # src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml # src/Umbraco.Web.UI/web.Template.Debug.config # src/Umbraco.Web.UI/web.Template.config # src/Umbraco.Web/Composing/ModuleInjector.cs # src/Umbraco.Web/Editors/NuCacheStatusController.cs # src/Umbraco.Web/PublishedCache/NuCache/DataSource/ContentNestedData.cs # src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs # src/Umbraco.Web/PublishedCache/NuCache/NuCacheComposer.cs # src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs # src/Umbraco.Web/Runtime/WebRuntime.cs
2021-06-24 09:43:57 -06:00
TestHelper.DbProviderFactoryCreator,
new DatabaseSchemaCreatorFactory(loggerFactory.CreateLogger<DatabaseSchemaCreator>(), loggerFactory, new UmbracoVersion(), Mock.Of<IEventAggregator>()),
mapperCollection);
Netcore: File systems rework (#10181) * Allow IMediaFileSystem to be replace in the DI, or registered with inner filesystem * Remove GetFileSystem from Filesystems It was only used by tests. * Make MediaFileSystem inherit from PhysicalFileSystem directly * Remove FileSystemWrapper * Remove inner filesystem from MediaFileSystem * Add MediaFileManager and bare minimum to make it testable * Remove MediaFileSystem * Fix unit tests using MediaFileManager * Remove IFileSystem and rely only on FileSystem * Hide dangerous methods in FileSystems and do some cleaning * Apply stylecop warnings to MediaFileManager * Add FilesystemsCreator to Tests.Common This allows you to create an instance if FileSystems with your own specified IFileSystem for testing purposes outside our own test suite. * Allow the stylesheet filesystem to be replaced. * Fix tests * Don't save stylesheetWrapper in a temporary var * refactor(FileSystems): change how stylesheet filesystem is registered * fix(FileSystems): unable to overwrite media filesystem SetMediaFileSystem added the MediaManager as a Singleton instead of replacing the existing instance. * fix(FileSystems): calling AddFileSystems replaces MediaManager When calling AddFileSystems after SetMediaFileSystem the MediaManager gets replaced by the default PhysicalFileSystem, so instead of calling SetMediaFileSystem in AddFileSystems we now call TrySetMediaFileSystem instead. This method will not replace any existing instance of the MediaManager if there's already a MediaManager registered. * Use SetMediaFileSystem instead of TrySet, and rename AddFilesystems to ConfigureFileSystems Also don't call AddFileSystems again in ConfigureFilesystems * Don't wrap CSS filesystem twice * Add CreateShadowWrapperInternal to avoid casting * Throw UnauthorizedAccessException isntead of InvalidOperationException * Remove ResetShadowId Co-authored-by: Rasmus John Pedersen <mail@rjp.dk>
2021-04-27 09:52:17 +02:00
var fs = new FileSystems(loggerFactory, IOHelper, Options.Create(globalSettings), Mock.Of<IHostingEnvironment>());
2020-09-21 21:06:24 +02:00
var coreDebug = new CoreDebugSettings();
var mediaFileManager = new MediaFileManager(
Mock.Of<IFileSystem>(),
Mock.Of<IMediaPathScheme>(),
Mock.Of<ILogger<MediaFileManager>>(),
Mock.Of<IShortStringHelper>(),
Mock.Of<IServiceProvider>(),
Options.Create(new ContentSettings()));
IEventAggregator eventAggregator = Mock.Of<IEventAggregator>();
var scopeProvider = new ScopeProvider(f, fs, Options.Create(coreDebug), mediaFileManager, loggerFactory.CreateLogger<ScopeProvider>(), loggerFactory, NoAppCache.Instance, eventAggregator);
2016-12-15 08:57:23 +01:00
mock.Setup(x => x.GetService(typeof(ILogger))).Returns(logger);
mock.Setup(x => x.GetService(typeof(ILogger<ComponentCollection>))).Returns(loggerFactory.CreateLogger<ComponentCollection>);
mock.Setup(x => x.GetService(typeof(ILoggerFactory))).Returns(loggerFactory);
mock.Setup(x => x.GetService(typeof(IProfilingLogger))).Returns(new ProfilingLogger(loggerFactory.CreateLogger<ProfilingLogger>(), Mock.Of<IProfiler>()));
mock.Setup(x => x.GetService(typeof(IUmbracoDatabaseFactory))).Returns(f);
mock.Setup(x => x.GetService(typeof(IScopeProvider))).Returns(scopeProvider);
2016-11-05 19:23:55 +01:00
setup?.Invoke(mock);
return mock.Object;
}
private static IServiceCollection MockRegister() => new ServiceCollection();
private static TypeLoader MockTypeLoader() => new TypeLoader(Mock.Of<ITypeFinder>(), new VaryingRuntimeHash(), Mock.Of<IAppPolicyCache>(), new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of<ILogger<TypeLoader>>(), Mock.Of<IProfiler>());
2016-08-25 15:09:51 +02:00
[Test]
2018-06-20 11:33:42 +02:00
public void Boot1A()
2016-08-25 15:09:51 +02:00
{
IServiceCollection register = MockRegister();
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
2016-08-25 15:09:51 +02:00
Type[] types = TypeArray<Composer1, Composer2, Composer4>();
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
2016-08-25 15:09:51 +02:00
Composed.Clear();
// 2 is Core and requires 4
// 3 is User
// => reorder components accordingly
2019-01-07 09:30:47 +01:00
composers.Compose();
2019-01-03 21:00:28 +01:00
AssertTypeArray(TypeArray<Composer1, Composer4, Composer2>(), Composed);
2019-01-07 09:30:47 +01:00
IServiceProvider factory = MockFactory(m =>
2019-01-07 09:30:47 +01:00
{
m.Setup(x => x.GetService(It.Is<Type>(t => t == typeof(ISomeResource)))).Returns(() => new SomeResource());
m.Setup(x => x.GetService(It.IsAny<Type>())).Returns<Type>((type) =>
2019-01-07 09:30:47 +01:00
{
if (type == typeof(Composer1))
{
return new Composer1();
}
if (type == typeof(Composer5))
{
return new Composer5();
}
if (type == typeof(Component5))
{
return new Component5(new SomeResource());
}
if (type == typeof(IProfilingLogger))
{
return new ProfilingLogger(Mock.Of<ILogger<ProfilingLogger>>(), Mock.Of<IProfiler>());
}
if (type == typeof(ILogger<ComponentCollection>))
{
return Mock.Of<ILogger<ComponentCollection>>();
}
2019-01-07 09:30:47 +01:00
throw new NotSupportedException(type.FullName);
});
});
ComponentCollectionBuilder builder = composition.WithCollectionBuilder<ComponentCollectionBuilder>();
builder.RegisterWith(register);
ComponentCollection components = builder.CreateCollection(factory);
2019-01-07 09:30:47 +01:00
Assert.IsEmpty(components);
components.Initialize();
Assert.IsEmpty(Initialized);
components.Terminate();
Assert.IsEmpty(Terminated);
2018-06-20 11:33:42 +02:00
}
[Test]
public void Boot1B()
{
IServiceCollection register = MockRegister();
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
2018-06-20 11:33:42 +02:00
Type[] types = TypeArray<Composer1, Composer2, Composer3, Composer4>();
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
2018-06-20 11:33:42 +02:00
Composed.Clear();
2018-06-20 11:33:42 +02:00
// 2 is Core and requires 4
// 3 is User - stays with RuntimeLevel.Run
// => reorder components accordingly
2019-02-14 10:39:27 +01:00
composers.Compose();
2019-01-03 21:00:28 +01:00
AssertTypeArray(TypeArray<Composer1, Composer4, Composer2, Composer3>(), Composed);
}
[Test]
public void Boot2()
{
IServiceCollection register = MockRegister();
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = TypeArray<Composer20, Composer21>();
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
// 21 is required by 20
// => reorder components accordingly
2019-02-14 10:39:27 +01:00
composers.Compose();
2019-01-03 21:00:28 +01:00
AssertTypeArray(TypeArray<Composer21, Composer20>(), Composed);
2016-08-25 15:09:51 +02:00
}
[Test]
public void Boot3()
{
IServiceCollection register = MockRegister();
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = TypeArray<Composer22, Composer24, Composer25>();
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
// i23 requires 22
// 24, 25 implement i23
// 25 required by i23
// => reorder components accordingly
2019-02-14 10:39:27 +01:00
composers.Compose();
2019-01-03 21:00:28 +01:00
AssertTypeArray(TypeArray<Composer22, Composer25, Composer24>(), Composed);
}
[Test]
public void BrokenRequire()
2016-08-25 15:09:51 +02:00
{
IServiceCollection register = MockRegister();
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
2016-08-25 15:09:51 +02:00
Type[] types = TypeArray<Composer1, Composer2, Composer3>();
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
2016-08-25 15:09:51 +02:00
Composed.Clear();
try
{
// 2 is Core and requires 4
// 4 is missing
// => throw
2019-02-14 10:39:27 +01:00
composers.Compose();
2016-08-25 15:09:51 +02:00
Assert.Fail("Expected exception.");
}
catch (Exception e)
{
Assert.AreEqual("Broken composer dependency: Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components.ComponentTests+Composer2 -> Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components.ComponentTests+Composer4.", e.Message);
2016-08-25 15:09:51 +02:00
}
}
[Test]
public void BrokenRequired()
{
IServiceCollection register = MockRegister();
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = TypeArray<Composer2, Composer4, Composer13>();
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
// 2 is Core and requires 4
// 13 is required by 1
// 1 is missing
// => reorder components accordingly
2019-02-14 10:39:27 +01:00
composers.Compose();
2019-01-03 21:00:28 +01:00
AssertTypeArray(TypeArray<Composer4, Composer2, Composer13>(), Composed);
}
2016-08-25 15:09:51 +02:00
[Test]
public void Initialize()
{
2019-01-07 09:30:47 +01:00
Composed.Clear();
Initialized.Clear();
Terminated.Clear();
IServiceCollection register = MockRegister();
TypeLoader typeLoader = MockTypeLoader();
IServiceProvider factory = MockFactory(m =>
2016-11-05 19:23:55 +01:00
{
m.Setup(x => x.GetService(It.Is<Type>(t => t == typeof(ISomeResource)))).Returns(() => new SomeResource());
m.Setup(x => x.GetService(It.IsAny<Type>())).Returns<Type>((type) =>
2019-01-03 21:00:28 +01:00
{
if (type == typeof(Composer1))
{
return new Composer1();
}
if (type == typeof(Composer5))
{
return new Composer5();
}
if (type == typeof(Composer5a))
{
return new Composer5a();
}
if (type == typeof(Component5))
{
return new Component5(new SomeResource());
}
if (type == typeof(Component5a))
{
return new Component5a();
}
if (type == typeof(IProfilingLogger))
{
return new ProfilingLogger(Mock.Of<ILogger<ProfilingLogger>>(), Mock.Of<IProfiler>());
}
if (type == typeof(ILogger<ComponentCollection>))
{
return Mock.Of<ILogger<ComponentCollection>>();
}
2019-01-03 21:00:28 +01:00
throw new NotSupportedException(type.FullName);
});
2016-11-05 19:23:55 +01:00
});
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
2016-08-25 15:09:51 +02:00
Type[] types = new[] { typeof(Composer1), typeof(Composer5), typeof(Composer5a) };
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
2019-01-07 09:30:47 +01:00
Assert.IsEmpty(Composed);
2019-01-03 21:00:28 +01:00
composers.Compose();
2019-02-14 10:39:27 +01:00
AssertTypeArray(TypeArray<Composer1, Composer5, Composer5a>(), Composed);
2019-01-07 09:30:47 +01:00
ComponentCollectionBuilder builder = composition.WithCollectionBuilder<ComponentCollectionBuilder>();
builder.RegisterWith(register);
ComponentCollection components = builder.CreateCollection(factory);
2019-01-07 09:30:47 +01:00
Assert.IsEmpty(Initialized);
components.Initialize();
2019-02-14 10:39:27 +01:00
AssertTypeArray(TypeArray<Component5, Component5a>(), Initialized);
2019-01-07 09:30:47 +01:00
Assert.IsEmpty(Terminated);
components.Terminate();
2019-02-14 10:39:27 +01:00
AssertTypeArray(TypeArray<Component5a, Component5>(), Terminated);
2016-08-25 15:09:51 +02:00
}
2016-08-31 18:25:18 +02:00
[Test]
public void Requires1()
2016-08-25 15:09:51 +02:00
{
IServiceCollection register = MockRegister();
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
2016-08-31 18:25:18 +02:00
Type[] types = new[] { typeof(Composer6), typeof(Composer7), typeof(Composer8) };
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
2016-08-31 18:25:18 +02:00
Composed.Clear();
2019-02-14 10:39:27 +01:00
composers.Compose();
2016-08-31 18:25:18 +02:00
Assert.AreEqual(2, Composed.Count);
2019-01-03 21:00:28 +01:00
Assert.AreEqual(typeof(Composer6), Composed[0]);
Assert.AreEqual(typeof(Composer8), Composed[1]);
2016-08-25 15:09:51 +02:00
}
2016-08-31 18:25:18 +02:00
[Test]
2018-06-20 11:33:42 +02:00
public void Requires2A()
2016-08-25 15:09:51 +02:00
{
IServiceCollection register = MockRegister();
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
2016-08-31 18:25:18 +02:00
Type[] types = new[] { typeof(Composer9), typeof(Composer2), typeof(Composer4) };
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
2016-08-31 18:25:18 +02:00
Composed.Clear();
2019-02-14 10:39:27 +01:00
composers.Compose();
Assert.AreEqual(3, Composed.Count);
2019-01-03 21:00:28 +01:00
Assert.AreEqual(typeof(Composer4), Composed[0]);
Assert.AreEqual(typeof(Composer2), Composed[1]);
2018-06-20 11:33:42 +02:00
}
[Test]
public void Requires2B()
{
IServiceCollection register = MockRegister();
TypeLoader typeLoader = MockTypeLoader();
IServiceProvider factory = MockFactory();
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
2018-06-20 11:33:42 +02:00
Type[] types = new[] { typeof(Composer9), typeof(Composer2), typeof(Composer4) };
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
2018-06-20 11:33:42 +02:00
Composed.Clear();
2019-01-03 21:00:28 +01:00
composers.Compose();
ComponentCollectionBuilder builder = composition.WithCollectionBuilder<ComponentCollectionBuilder>();
builder.RegisterWith(register);
ComponentCollection components = builder.CreateCollection(factory);
2016-08-31 18:25:18 +02:00
Assert.AreEqual(3, Composed.Count);
2019-01-03 21:00:28 +01:00
Assert.AreEqual(typeof(Composer4), Composed[0]);
Assert.AreEqual(typeof(Composer2), Composed[1]);
Assert.AreEqual(typeof(Composer9), Composed[2]);
2016-08-25 15:09:51 +02:00
}
[Test]
public void WeakDependencies()
{
IServiceCollection register = MockRegister();
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = new[] { typeof(Composer10) };
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
2019-02-14 10:39:27 +01:00
composers.Compose();
Assert.AreEqual(1, Composed.Count);
2019-01-03 21:00:28 +01:00
Assert.AreEqual(typeof(Composer10), Composed[0]);
2019-01-03 21:00:28 +01:00
types = new[] { typeof(Composer11) };
composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
2019-02-14 10:39:27 +01:00
Assert.Throws<Exception>(() => composers.Compose());
2019-04-05 19:00:34 +02:00
Console.WriteLine("throws:");
composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Dictionary<Type, List<Type>> requirements = composers.GetRequirements(false);
Console.WriteLine(ComposerGraph.GetComposersReport(requirements));
2019-01-03 21:00:28 +01:00
types = new[] { typeof(Composer2) };
composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
2019-02-14 10:39:27 +01:00
Assert.Throws<Exception>(() => composers.Compose());
2019-04-05 19:00:34 +02:00
Console.WriteLine("throws:");
composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
2019-04-05 19:00:34 +02:00
requirements = composers.GetRequirements(false);
Console.WriteLine(ComposerGraph.GetComposersReport(requirements));
2019-01-03 21:00:28 +01:00
types = new[] { typeof(Composer12) };
composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
2019-02-14 10:39:27 +01:00
composers.Compose();
Assert.AreEqual(1, Composed.Count);
2019-01-03 21:00:28 +01:00
Assert.AreEqual(typeof(Composer12), Composed[0]);
}
[Test]
public void DisableMissing()
{
IServiceCollection register = MockRegister();
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
Type[] types = new[] { typeof(Composer6), typeof(Composer8) }; // 8 disables 7 which is not in the list
var composers = new ComposerGraph(composition, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Composed.Clear();
2019-02-14 10:39:27 +01:00
composers.Compose();
Assert.AreEqual(2, Composed.Count);
2019-01-03 21:00:28 +01:00
Assert.AreEqual(typeof(Composer6), Composed[0]);
Assert.AreEqual(typeof(Composer8), Composed[1]);
}
2019-02-04 18:49:56 +01:00
[Test]
public void AttributesPriorities()
{
IServiceCollection register = MockRegister();
var composition = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
2019-02-04 18:49:56 +01:00
Type[] types = new[] { typeof(Composer26) };
DisableComposerAttribute[] enableDisableAttributes = new[] { new DisableComposerAttribute(typeof(Composer26)) };
var composers = new ComposerGraph(composition, types, enableDisableAttributes, Mock.Of<ILogger<ComposerGraph>>());
2019-02-04 18:49:56 +01:00
Composed.Clear();
2019-02-14 10:39:27 +01:00
composers.Compose();
2019-02-04 18:49:56 +01:00
Assert.AreEqual(0, Composed.Count); // 26 gone
types = new[] { typeof(Composer26), typeof(Composer27) }; // 26 disabled by assembly attribute, enabled by 27
composers = new ComposerGraph(composition, types, enableDisableAttributes, Mock.Of<ILogger<ComposerGraph>>());
2019-02-04 18:49:56 +01:00
Composed.Clear();
2019-02-14 10:39:27 +01:00
composers.Compose();
2019-02-04 18:49:56 +01:00
Assert.AreEqual(2, Composed.Count); // both
Assert.AreEqual(typeof(Composer26), Composed[0]);
Assert.AreEqual(typeof(Composer27), Composed[1]);
}
2019-04-05 19:00:34 +02:00
[Test]
public void AllComposers()
{
ITypeFinder typeFinder = TestHelper.GetTypeFinder();
var typeLoader = new TypeLoader(typeFinder, new VaryingRuntimeHash(), AppCaches.Disabled.RuntimeCache, new DirectoryInfo(TestHelper.GetHostingEnvironment().MapPathContentRoot(Constants.SystemDirectories.TempData)), Mock.Of<ILogger<TypeLoader>>(), Mock.Of<IProfiler>());
2019-04-05 19:00:34 +02:00
IServiceCollection register = MockRegister();
var builder = new UmbracoBuilder(register, Mock.Of<IConfiguration>(), TestHelper.GetMockedTypeLoader());
2020-03-09 21:23:38 +11:00
var allComposers = typeLoader.GetTypes<IComposer>().ToList();
var types = allComposers.Where(x => x.FullName.StartsWith("Umbraco.Core.") || x.FullName.StartsWith("Umbraco.Web")).ToList();
var composers = new ComposerGraph(builder, types, Enumerable.Empty<Attribute>(), Mock.Of<ILogger<ComposerGraph>>());
Dictionary<Type, List<Type>> requirements = composers.GetRequirements();
string report = ComposerGraph.GetComposersReport(requirements);
2019-04-05 19:00:34 +02:00
Console.WriteLine(report);
IEnumerable<Type> composerTypes = composers.SortComposers(requirements);
2019-04-05 19:00:34 +02:00
foreach (Type type in composerTypes)
{
2019-04-05 19:00:34 +02:00
Console.WriteLine(type);
}
2019-04-05 19:00:34 +02:00
}
2019-01-03 21:00:28 +01:00
public class TestComposerBase : IComposer
2016-08-25 15:09:51 +02:00
{
public virtual void Compose(IUmbracoBuilder builder) => Composed.Add(GetType());
2016-08-25 15:09:51 +02:00
}
2019-01-03 21:00:28 +01:00
public class Composer1 : TestComposerBase
{
}
2016-08-31 18:25:18 +02:00
2019-01-04 10:29:29 +01:00
[ComposeAfter(typeof(Composer4))]
2021-04-26 21:09:06 +02:00
public class Composer2 : TestComposerBase
{
}
2016-08-25 15:09:51 +02:00
2021-08-27 10:42:36 +01:00
public class Composer3 : TestComposerBase, IComposer
{
}
2016-08-31 18:25:18 +02:00
2019-01-03 21:00:28 +01:00
public class Composer4 : TestComposerBase
{
}
2019-01-03 21:00:28 +01:00
public class Composer5 : TestComposerBase
{
2020-11-21 15:43:01 +00:00
public override void Compose(IUmbracoBuilder builder)
2019-01-03 21:00:28 +01:00
{
2020-11-21 15:43:01 +00:00
base.Compose(builder);
builder.Components().Append<Component5>();
2019-01-03 21:00:28 +01:00
}
}
2019-02-14 10:39:27 +01:00
[ComposeAfter(typeof(Composer5))]
public class Composer5a : TestComposerBase
{
public override void Compose(IUmbracoBuilder builder)
2019-02-14 10:39:27 +01:00
{
base.Compose(builder);
builder.Components().Append<Component5a>();
2019-02-14 10:39:27 +01:00
}
}
2019-01-07 09:30:47 +01:00
public class TestComponentBase : IComponent
2016-08-31 18:25:18 +02:00
{
public virtual void Initialize() => Initialized.Add(GetType());
2019-01-07 09:30:47 +01:00
public virtual void Terminate() => Terminated.Add(GetType());
2019-01-07 09:30:47 +01:00
}
public class Component5 : TestComponentBase
{
private readonly ISomeResource _resource;
public Component5(ISomeResource resource) => _resource = resource;
2016-08-25 15:09:51 +02:00
}
2019-02-14 10:39:27 +01:00
public class Component5a : TestComponentBase
{
}
2019-02-14 10:39:27 +01:00
2019-01-03 21:00:28 +01:00
[Disable]
public class Composer6 : TestComposerBase
{
}
2016-08-31 18:25:18 +02:00
2019-01-03 21:00:28 +01:00
public class Composer7 : TestComposerBase
{
}
2016-08-31 18:25:18 +02:00
2019-01-03 21:00:28 +01:00
[Disable(typeof(Composer7))]
[Enable(typeof(Composer6))]
public class Composer8 : TestComposerBase
{
}
2016-08-31 18:25:18 +02:00
2021-08-27 10:42:36 +01:00
public interface ITestComposer : IComposer
{
}
2016-08-31 18:25:18 +02:00
[ComposeAfter(typeof(Composer2))]
[ComposeAfter(typeof(Composer4))]
2019-01-03 21:00:28 +01:00
public class Composer9 : TestComposerBase, ITestComposer
{
}
2016-08-31 18:25:18 +02:00
2019-01-04 10:29:29 +01:00
[ComposeAfter(typeof(ITestComposer))]
2019-01-03 21:00:28 +01:00
public class Composer10 : TestComposerBase
{
}
2019-01-04 10:29:29 +01:00
[ComposeAfter(typeof(ITestComposer), false)]
2019-01-03 21:00:28 +01:00
public class Composer11 : TestComposerBase
{
}
2019-01-04 10:29:29 +01:00
[ComposeAfter(typeof(Composer4), true)]
2021-04-26 21:09:06 +02:00
public class Composer12 : TestComposerBase
{
}
2019-01-04 10:29:29 +01:00
[ComposeBefore(typeof(Composer1))]
2019-01-03 21:00:28 +01:00
public class Composer13 : TestComposerBase
{
}
public interface ISomeResource
{
}
2016-08-25 15:09:51 +02:00
public class SomeResource : ISomeResource
{
}
2019-01-03 21:00:28 +01:00
public class Composer20 : TestComposerBase
{
}
2019-01-04 10:29:29 +01:00
[ComposeBefore(typeof(Composer20))]
2019-01-03 21:00:28 +01:00
public class Composer21 : TestComposerBase
{
}
2019-01-03 21:00:28 +01:00
public class Composer22 : TestComposerBase
{
}
2019-01-04 10:29:29 +01:00
[ComposeAfter(typeof(Composer22))]
2019-01-03 21:00:28 +01:00
public interface IComposer23 : IComposer
{
}
2019-01-03 21:00:28 +01:00
public class Composer24 : TestComposerBase, IComposer23
{
}
// should insert itself between 22 and anything i23
2019-01-04 10:29:29 +01:00
[ComposeBefore(typeof(IComposer23))]
////[RequireComponent(typeof(Component22))] - not needed, implement i23
2019-01-03 21:00:28 +01:00
public class Composer25 : TestComposerBase, IComposer23
{
}
2019-02-04 18:49:56 +01:00
public class Composer26 : TestComposerBase
{
}
2019-02-04 18:49:56 +01:00
[Enable(typeof(Composer26))]
public class Composer27 : TestComposerBase
{
}
// FIXME: move to Testing
private static Type[] TypeArray<T1>() => new[] { typeof(T1) };
private static Type[] TypeArray<T1, T2>() => new[] { typeof(T1), typeof(T2) };
private static Type[] TypeArray<T1, T2, T3>() => new[] { typeof(T1), typeof(T2), typeof(T3) };
private static Type[] TypeArray<T1, T2, T3, T4>() => new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) };
private static Type[] TypeArray<T1, T2, T3, T4, T5>() => new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5) };
private static Type[] TypeArray<T1, T2, T3, T4, T5, T6>() => new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6) };
private static Type[] TypeArray<T1, T2, T3, T4, T5, T6, T7>() => new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7) };
private static Type[] TypeArray<T1, T2, T3, T4, T5, T6, T7, T8>() => new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8) };
private static void AssertTypeArray(IReadOnlyList<Type> expected, IReadOnlyList<Type> test)
{
Assert.AreEqual(expected.Count, test.Count);
for (int i = 0; i < expected.Count; i++)
{
Assert.AreEqual(expected[i], test[i]);
}
}
2016-08-25 15:09:51 +02:00
}
}