Strengthen ordering of TraitsInConstructOrder.
All types that are dependencies of a trait must now occur before it in the construct ordering. Previously, only one type that was a dependency of a trait needed to occur before it.
This commit is contained in:
@@ -100,7 +100,7 @@ namespace OpenRA
|
|||||||
var unresolved = source.Except(resolved);
|
var unresolved = source.Except(resolved);
|
||||||
|
|
||||||
var testResolve = new Func<Type, Type, bool>((a, b) => a == b || a.IsAssignableFrom(b));
|
var testResolve = new Func<Type, Type, bool>((a, b) => a == b || a.IsAssignableFrom(b));
|
||||||
var more = unresolved.Where(u => u.Dependencies.All(d => resolved.Exists(r => testResolve(d, r.Type))));
|
var more = unresolved.Where(u => u.Dependencies.All(d => resolved.Exists(r => testResolve(d, r.Type)) && !unresolved.Any(u1 => testResolve(d, u1.Type))));
|
||||||
|
|
||||||
// Re-evaluate the vars above until sorted
|
// Re-evaluate the vars above until sorted
|
||||||
while (more.Any())
|
while (more.Any())
|
||||||
@@ -122,14 +122,14 @@ namespace OpenRA
|
|||||||
exceptionString += u.Type + ": { " + string.Join(", ", deps) + " }\r\n";
|
exceptionString += u.Type + ": { " + string.Join(", ", deps) + " }\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception(exceptionString);
|
throw new YamlException(exceptionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructOrderCache = resolved.Select(r => r.Trait).ToList();
|
constructOrderCache = resolved.Select(r => r.Trait).ToList();
|
||||||
return constructOrderCache;
|
return constructOrderCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IEnumerable<Type> PrerequisitesOf(ITraitInfo info)
|
public static IEnumerable<Type> PrerequisitesOf(ITraitInfo info)
|
||||||
{
|
{
|
||||||
return info
|
return info
|
||||||
.GetType()
|
.GetType()
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@@ -34,20 +33,26 @@ namespace OpenRA.Test
|
|||||||
[TestCase(TestName = "Trait ordering sorts in dependency order correctly")]
|
[TestCase(TestName = "Trait ordering sorts in dependency order correctly")]
|
||||||
public void TraitOrderingSortsCorrectly()
|
public void TraitOrderingSortsCorrectly()
|
||||||
{
|
{
|
||||||
var actorInfo = new ActorInfo("test", new MockCInfo(), new MockBInfo(), new MockAInfo());
|
var unorderedTraits = new ITraitInfo[] { new MockBInfo(), new MockCInfo(), new MockAInfo(), new MockBInfo() };
|
||||||
|
var actorInfo = new ActorInfo("test", unorderedTraits);
|
||||||
|
var orderedTraits = actorInfo.TraitsInConstructOrder().ToArray();
|
||||||
|
|
||||||
var i = new List<ITraitInfo>(actorInfo.TraitsInConstructOrder());
|
CollectionAssert.AreEquivalent(unorderedTraits, orderedTraits);
|
||||||
|
|
||||||
Assert.That(i[0], Is.InstanceOf<MockAInfo>());
|
for (var i = 0; i < orderedTraits.Length; i++)
|
||||||
Assert.That(i[1].GetType().Name, Is.EqualTo("MockBInfo"));
|
{
|
||||||
Assert.That(i[2].GetType().Name, Is.EqualTo("MockCInfo"));
|
var traitTypesThatMustOccurBeforeThisTrait = ActorInfo.PrerequisitesOf(orderedTraits[i]);
|
||||||
|
var traitTypesThatOccurAfterThisTrait = orderedTraits.Skip(i + 1).Select(ti => ti.GetType());
|
||||||
|
var traitTypesThatShouldOccurEarlier = traitTypesThatOccurAfterThisTrait.Intersect(traitTypesThatMustOccurBeforeThisTrait);
|
||||||
|
CollectionAssert.IsEmpty(traitTypesThatShouldOccurEarlier, "Dependency order has not been satisfied.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase(TestName = "Trait ordering exception reports missing dependencies")]
|
[TestCase(TestName = "Trait ordering exception reports missing dependencies")]
|
||||||
public void TraitOrderingReportsMissingDependencies()
|
public void TraitOrderingReportsMissingDependencies()
|
||||||
{
|
{
|
||||||
var actorInfo = new ActorInfo("test", new MockBInfo(), new MockCInfo());
|
var actorInfo = new ActorInfo("test", new MockBInfo(), new MockCInfo());
|
||||||
var ex = Assert.Throws<Exception>(() => actorInfo.TraitsInConstructOrder());
|
var ex = Assert.Throws<YamlException>(() => actorInfo.TraitsInConstructOrder());
|
||||||
|
|
||||||
StringAssert.Contains(typeof(MockAInfo).Name, ex.Message, "Exception message did not report a missing dependency.");
|
StringAssert.Contains(typeof(MockAInfo).Name, ex.Message, "Exception message did not report a missing dependency.");
|
||||||
StringAssert.Contains(typeof(MockBInfo).Name, ex.Message, "Exception message did not report a missing dependency.");
|
StringAssert.Contains(typeof(MockBInfo).Name, ex.Message, "Exception message did not report a missing dependency.");
|
||||||
@@ -60,7 +65,7 @@ namespace OpenRA.Test
|
|||||||
public void TraitOrderingReportsCyclicDependencies()
|
public void TraitOrderingReportsCyclicDependencies()
|
||||||
{
|
{
|
||||||
var actorInfo = new ActorInfo("test", new MockDInfo(), new MockEInfo(), new MockFInfo());
|
var actorInfo = new ActorInfo("test", new MockDInfo(), new MockEInfo(), new MockFInfo());
|
||||||
var ex = Assert.Throws<Exception>(() => actorInfo.TraitsInConstructOrder());
|
var ex = Assert.Throws<YamlException>(() => actorInfo.TraitsInConstructOrder());
|
||||||
|
|
||||||
StringAssert.Contains(typeof(MockDInfo).Name, ex.Message, "Exception message should report all cyclic dependencies.");
|
StringAssert.Contains(typeof(MockDInfo).Name, ex.Message, "Exception message should report all cyclic dependencies.");
|
||||||
StringAssert.Contains(typeof(MockEInfo).Name, ex.Message, "Exception message should report all cyclic dependencies.");
|
StringAssert.Contains(typeof(MockEInfo).Name, ex.Message, "Exception message should report all cyclic dependencies.");
|
||||||
|
|||||||
Reference in New Issue
Block a user