mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-04-05 21:01:35 +08:00
Fixed missing feature states exception.
- Fixed an issue with Orchard failing to initialize when the Settings_ShellFeatureRecord contains orphaned features (which happens when a module has been removed). - Added unit tests.
This commit is contained in:
parent
40f1e39622
commit
40071a6050
src
Orchard.Tests/Environment/ShellBuilders
Orchard/Environment/ShellBuilders
@ -9,6 +9,7 @@ using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Environment.ShellBuilders;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Tests.Environment.TestDependencies;
|
||||
using Orchard.Utility.Extensions;
|
||||
|
||||
@ -17,16 +18,22 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
public class CompositionStrategyTests : ContainerTestBase {
|
||||
private CompositionStrategy _compositionStrategy;
|
||||
private Mock<IExtensionManager> _extensionManager;
|
||||
private IEnumerable<ExtensionDescriptor> _availableExtensions;
|
||||
private IEnumerable<Feature> _installedFeatures;
|
||||
private Mock<ILogger> _loggerMock;
|
||||
|
||||
protected override void Register(ContainerBuilder builder) {
|
||||
_extensionManager = new Mock<IExtensionManager>(MockBehavior.Loose);
|
||||
_extensionManager = new Mock<IExtensionManager>();
|
||||
_loggerMock = new Mock<ILogger>();
|
||||
|
||||
builder.RegisterType<CompositionStrategy>().AsSelf();
|
||||
builder.RegisterInstance(_extensionManager.Object);
|
||||
builder.RegisterInstance(_loggerMock.Object);
|
||||
}
|
||||
|
||||
protected override void Resolve(ILifetimeScope container) {
|
||||
_compositionStrategy = container.Resolve<CompositionStrategy>();
|
||||
_compositionStrategy.Logger = container.Resolve<ILogger>();
|
||||
|
||||
var alphaExtension = new ExtensionDescriptor {
|
||||
Id = "Alpha",
|
||||
@ -54,7 +61,11 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
betaFeatureDescriptor
|
||||
};
|
||||
|
||||
var features = new List<Feature> {
|
||||
_availableExtensions = new[] {
|
||||
alphaExtension
|
||||
};
|
||||
|
||||
_installedFeatures = new List<Feature> {
|
||||
new Feature {
|
||||
Descriptor = alphaFeatureDescriptor,
|
||||
ExportedTypes = new List<Type> {
|
||||
@ -69,16 +80,16 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
}
|
||||
};
|
||||
|
||||
_extensionManager.Setup(x => x.AvailableExtensions()).Returns(new List<ExtensionDescriptor> {
|
||||
alphaExtension
|
||||
});
|
||||
_loggerMock.Setup(x => x.IsEnabled(It.IsAny<LogLevel>())).Returns(true);
|
||||
|
||||
_extensionManager.Setup(x => x.AvailableFeatures()).Returns(
|
||||
_extensionManager.Setup(x => x.AvailableExtensions()).Returns(() => _availableExtensions);
|
||||
|
||||
_extensionManager.Setup(x => x.AvailableFeatures()).Returns(() =>
|
||||
_extensionManager.Object.AvailableExtensions()
|
||||
.SelectMany(ext => ext.Features)
|
||||
.ToReadOnlyCollection());
|
||||
|
||||
_extensionManager.Setup(x => x.LoadFeatures(It.IsAny<IEnumerable<FeatureDescriptor>>())).Returns(features);
|
||||
_extensionManager.Setup(x => x.LoadFeatures(It.IsAny<IEnumerable<FeatureDescriptor>>())).Returns(() => _installedFeatures);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -87,7 +98,7 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
var shellDescriptor = CreateShellDescriptor("Alpha", "Beta");
|
||||
var shellBlueprint = _compositionStrategy.Compose(shellSettings, shellDescriptor);
|
||||
|
||||
Assert.That(shellBlueprint.Dependencies.Count(x => x.Type == typeof (AlphaDependency)), Is.EqualTo(1));
|
||||
Assert.That(shellBlueprint.Dependencies.Count(x => x.Type == typeof(AlphaDependency)), Is.EqualTo(1));
|
||||
Assert.That(shellBlueprint.Dependencies.Count(x => x.Type == typeof(BetaDependency)), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
@ -101,6 +112,34 @@ namespace Orchard.Tests.Environment.ShellBuilders {
|
||||
Assert.That(shellDescriptor.Features.Count(x => x.Name == "Alpha"), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ComposeDoesNotThrowWhenFeatureStateRecordDoesNotExist() {
|
||||
var shellSettings = CreateShell();
|
||||
var shellDescriptor = CreateShellDescriptor("MyFeature");
|
||||
|
||||
Assert.DoesNotThrow(() => _compositionStrategy.Compose(shellSettings, shellDescriptor));
|
||||
_loggerMock.Verify(x => x.Log(LogLevel.Warning, null, It.IsAny<string>(), It.IsAny<object[]>()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ComposeThrowsWhenAutoEnabledDependencyDoesNotExist() {
|
||||
var myModule = _availableExtensions.First();
|
||||
|
||||
myModule.Features = myModule.Features.Concat(new[] {
|
||||
new FeatureDescriptor {
|
||||
Extension = myModule,
|
||||
Name = "MyFeature",
|
||||
Id = "MyFeature",
|
||||
Dependencies = new[] { "NonExistingFeature" }
|
||||
}
|
||||
});
|
||||
|
||||
var shellSettings = CreateShell();
|
||||
var shellDescriptor = CreateShellDescriptor("MyFeature");
|
||||
|
||||
Assert.Throws<OrchardException>(() => _compositionStrategy.Compose(shellSettings, shellDescriptor));
|
||||
}
|
||||
|
||||
private ShellSettings CreateShell() {
|
||||
return new ShellSettings();
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ using Orchard.ContentManagement.Records;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Descriptor.Models;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Environment.Extensions.Helpers;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Environment.ShellBuilders.Models;
|
||||
using Orchard.Localization;
|
||||
@ -76,19 +75,29 @@ namespace Orchard.Environment.ShellBuilders {
|
||||
}
|
||||
|
||||
private IEnumerable<string> ExpandDependencies(IDictionary<string, FeatureDescriptor> availableFeatures, IEnumerable<string> features) {
|
||||
return ExpandDependenciesInternal(availableFeatures, features).Distinct();
|
||||
return ExpandDependenciesInternal(availableFeatures, features, dependentFeatureDescriptor: null).Distinct();
|
||||
}
|
||||
|
||||
private IEnumerable<string> ExpandDependenciesInternal(IDictionary<string, FeatureDescriptor> availableFeatures, IEnumerable<string> features) {
|
||||
private IEnumerable<string> ExpandDependenciesInternal(IDictionary<string, FeatureDescriptor> availableFeatures, IEnumerable<string> features, FeatureDescriptor dependentFeatureDescriptor = null) {
|
||||
foreach (var shellFeature in features) {
|
||||
|
||||
if (!availableFeatures.ContainsKey(shellFeature)) {
|
||||
throw new OrchardException(T("The feature {0} is not available", shellFeature));
|
||||
// If the feature comes from a list of feature dependencies it indicates a bug, so throw an exception.
|
||||
if(dependentFeatureDescriptor != null)
|
||||
throw new OrchardException(
|
||||
T("The feature '{0}' was listed as a dependency of '{1}' of extension '{2}', but this feature could not be found. Please update your manifest file or install the module providing the missing feature.",
|
||||
shellFeature,
|
||||
dependentFeatureDescriptor.Name,
|
||||
dependentFeatureDescriptor.Extension.Name));
|
||||
|
||||
// If the feature comes from the shell descriptor it means the feature is simply orphaned, so don't throw an exception.
|
||||
Logger.Warning("Identified '{0}' as an orphaned feature state record in Settings_ShellFeatureRecord.", shellFeature);
|
||||
continue;
|
||||
}
|
||||
|
||||
var feature = availableFeatures[shellFeature];
|
||||
|
||||
foreach (var childDependency in ExpandDependenciesInternal(availableFeatures, feature.Dependencies))
|
||||
foreach (var childDependency in ExpandDependenciesInternal(availableFeatures, feature.Dependencies, dependentFeatureDescriptor: feature))
|
||||
yield return childDependency;
|
||||
|
||||
foreach (var dependency in feature.Dependencies)
|
||||
|
Loading…
Reference in New Issue
Block a user