Merge remote-tracking branch 'origin/netcore/netcore' into netcore/feature/migrate-remaining-trees
This commit is contained in:
23
src/Umbraco.Tests.UnitTests/Umbraco.Core/AttemptTests.cs
Normal file
23
src/Umbraco.Tests.UnitTests/Umbraco.Core/AttemptTests.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core
|
||||
{
|
||||
[TestFixture]
|
||||
public class AttemptTests
|
||||
{
|
||||
[Test]
|
||||
public void AttemptIf()
|
||||
{
|
||||
// just making sure that it is ok to use TryParse as a condition
|
||||
|
||||
int value;
|
||||
var attempt = Attempt.If(int.TryParse("1234", out value), value);
|
||||
Assert.IsTrue(attempt.Success);
|
||||
Assert.AreEqual(1234, attempt.Result);
|
||||
|
||||
attempt = Attempt.If(int.TryParse("12xxx34", out value), value);
|
||||
Assert.IsFalse(attempt.Success);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
|
||||
}
|
||||
|
||||
[TestCase(ClaimTypes.NameIdentifier, _testUserId)]
|
||||
[TestCase(ClaimTypes.Name, _testUserName)]
|
||||
[TestCase(ClaimTypes.Name, _testUserName)]
|
||||
public async Task CreateAsync_Should_Include_Claim(string expectedClaimType, object expectedClaimValue)
|
||||
{
|
||||
var sut = CreateSut();
|
||||
@@ -79,7 +79,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
|
||||
var claimsPrincipal = await sut.CreateAsync(_testUser);
|
||||
|
||||
Assert.True(claimsPrincipal.HasClaim(expectedClaimType, expectedClaimValue.ToString()));
|
||||
Assert.True(claimsPrincipal.GetUmbracoIdentity().Actor.HasClaim(expectedClaimType, expectedClaimValue.ToString()));
|
||||
Assert.True(claimsPrincipal.GetUmbracoIdentity().HasClaim(expectedClaimType, expectedClaimValue.ToString()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -94,9 +94,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
|
||||
var sut = CreateSut();
|
||||
|
||||
var claimsPrincipal = await sut.CreateAsync(_testUser);
|
||||
|
||||
|
||||
Assert.True(claimsPrincipal.HasClaim(expectedClaimType, expectedClaimValue));
|
||||
Assert.True(claimsPrincipal.GetUmbracoIdentity().Actor.HasClaim(expectedClaimType, expectedClaimValue));
|
||||
Assert.True(claimsPrincipal.GetUmbracoIdentity().HasClaim(expectedClaimType, expectedClaimValue));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -112,7 +112,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
|
||||
var sut = CreateSut();
|
||||
|
||||
var claimsPrincipal = await sut.CreateAsync(_testUser);
|
||||
|
||||
|
||||
Assert.True(claimsPrincipal.HasClaim(expectedClaimType, expectedClaimValue));
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
|
||||
|
||||
var claimsPrincipal = await sut.CreateAsync(_testUser);
|
||||
|
||||
Assert.True(claimsPrincipal.GetUmbracoIdentity().Actor.HasClaim(expectedClaimType, expectedClaimValue));
|
||||
Assert.True(claimsPrincipal.GetUmbracoIdentity().HasClaim(expectedClaimType, expectedClaimValue));
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
|
||||
if (!UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity, out var backofficeIdentity))
|
||||
Assert.Fail();
|
||||
|
||||
Assert.IsNull(backofficeIdentity.Actor);
|
||||
Assert.AreEqual(1234, backofficeIdentity.Id);
|
||||
//Assert.AreEqual(sessionId, backofficeIdentity.SessionId);
|
||||
Assert.AreEqual(securityStamp, backofficeIdentity.SecurityStamp);
|
||||
@@ -60,7 +61,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
|
||||
new Claim(ClaimTypes.Name, "testing", ClaimValueTypes.String, TestIssuer, TestIssuer),
|
||||
});
|
||||
|
||||
if (UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity, out var backofficeIdentity))
|
||||
if (UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity, out _))
|
||||
Assert.Fail();
|
||||
|
||||
Assert.Pass();
|
||||
@@ -83,7 +84,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
|
||||
new Claim(ClaimsIdentity.DefaultRoleClaimType, "admin", ClaimValueTypes.String, TestIssuer, TestIssuer),
|
||||
});
|
||||
|
||||
if (UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity, out var backofficeIdentity))
|
||||
if (UmbracoBackOfficeIdentity.FromClaimsIdentity(claimsIdentity, out _))
|
||||
Assert.Fail();
|
||||
|
||||
Assert.Pass();
|
||||
@@ -105,6 +106,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
|
||||
1234, "testing", "hello world", new[] { 654 }, new[] { 654 }, "en-us", securityStamp, new[] { "content", "media" }, new[] { "admin" });
|
||||
|
||||
Assert.AreEqual(12, identity.Claims.Count());
|
||||
Assert.IsNull(identity.Actor);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +118,11 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.BackOffice
|
||||
var identity = new UmbracoBackOfficeIdentity(
|
||||
1234, "testing", "hello world", new[] { 654 }, new[] { 654 }, "en-us", securityStamp, new[] { "content", "media" }, new[] { "admin" });
|
||||
|
||||
// this will be filtered out during cloning
|
||||
identity.AddClaim(new Claim(Constants.Security.TicketExpiresClaimType, "test"));
|
||||
|
||||
var cloned = identity.Clone();
|
||||
Assert.IsNull(cloned.Actor);
|
||||
|
||||
Assert.AreEqual(10, cloned.Claims.Count());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core
|
||||
{
|
||||
public class ClaimsIdentityExtensionsTests
|
||||
{
|
||||
[Test]
|
||||
public void FindFirstValue_WhenIdentityIsNull_ExpectArgumentNullException()
|
||||
{
|
||||
ClaimsIdentity identity = null;
|
||||
Assert.Throws<ArgumentNullException>(() => identity.FindFirstValue("test"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FindFirstValue_WhenClaimNotPresent_ExpectNull()
|
||||
{
|
||||
var identity = new ClaimsIdentity(new List<Claim>());
|
||||
var value = identity.FindFirstValue("test");
|
||||
Assert.IsNull(value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FindFirstValue_WhenMatchingClaimPresent_ExpectCorrectValue()
|
||||
{
|
||||
var expectedClaim = new Claim("test", "123", "string", "Umbraco");
|
||||
var identity = new ClaimsIdentity(new List<Claim> {expectedClaim});
|
||||
|
||||
var value = identity.FindFirstValue("test");
|
||||
|
||||
Assert.AreEqual(expectedClaim.Value, value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void FindFirstValue_WhenMultipleMatchingClaimsPresent_ExpectFirstValue()
|
||||
{
|
||||
var expectedClaim = new Claim("test", "123", "string", "Umbraco");
|
||||
var dupeClaim = new Claim(expectedClaim.Type, Guid.NewGuid().ToString());
|
||||
var identity = new ClaimsIdentity(new List<Claim> {expectedClaim, dupeClaim});
|
||||
|
||||
var value = identity.FindFirstValue("test");
|
||||
|
||||
Assert.AreEqual(expectedClaim.Value, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Collections;
|
||||
using Umbraco.Tests.Common;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core.Collections
|
||||
{
|
||||
[TestFixture]
|
||||
public class DeepCloneableListTests
|
||||
{
|
||||
[Test]
|
||||
public void Deep_Clones_Each_Item_Once()
|
||||
{
|
||||
var list = new DeepCloneableList<TestClone>(ListCloneBehavior.CloneOnce);
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
|
||||
var cloned = list.DeepClone() as DeepCloneableList<TestClone>;
|
||||
|
||||
//Test that each item in the sequence is equal - based on the equality comparer of TestClone (i.e. it's ID)
|
||||
Assert.IsTrue(list.SequenceEqual(cloned));
|
||||
|
||||
//Test that each instance in the list is not the same one
|
||||
foreach (var item in list)
|
||||
{
|
||||
var clone = cloned.Single(x => x.Id == item.Id);
|
||||
Assert.AreNotSame(item, clone);
|
||||
}
|
||||
|
||||
//clone again from the clone - since it's clone once the items should be the same
|
||||
var cloned2 = cloned.DeepClone() as DeepCloneableList<TestClone>;
|
||||
|
||||
//Test that each item in the sequence is equal - based on the equality comparer of TestClone (i.e. it's ID)
|
||||
Assert.IsTrue(cloned.SequenceEqual(cloned2));
|
||||
|
||||
//Test that each instance in the list is the same one
|
||||
foreach (var item in cloned)
|
||||
{
|
||||
var clone = cloned2.Single(x => x.Id == item.Id);
|
||||
Assert.AreSame(item, clone);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Deep_Clones_All_Elements()
|
||||
{
|
||||
var list = new DeepCloneableList<TestClone>(ListCloneBehavior.Always);
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
|
||||
var cloned = list.DeepClone() as DeepCloneableList<TestClone>;
|
||||
|
||||
Assert.IsNotNull(cloned);
|
||||
Assert.AreNotSame(list, cloned);
|
||||
Assert.AreEqual(list.Count, cloned.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Clones_Each_Item()
|
||||
{
|
||||
var list = new DeepCloneableList<TestClone>(ListCloneBehavior.Always);
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
|
||||
var cloned = (DeepCloneableList<TestClone>) list.DeepClone();
|
||||
|
||||
foreach (var item in cloned)
|
||||
{
|
||||
Assert.IsTrue(item.IsClone);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Cloned_Sequence_Equals()
|
||||
{
|
||||
var list = new DeepCloneableList<TestClone>(ListCloneBehavior.Always);
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
list.Add(new TestClone());
|
||||
|
||||
var cloned = (DeepCloneableList<TestClone>) list.DeepClone();
|
||||
|
||||
//Test that each item in the sequence is equal - based on the equality comparer of TestClone (i.e. it's ID)
|
||||
Assert.IsTrue(list.SequenceEqual(cloned));
|
||||
|
||||
//Test that each instance in the list is not the same one
|
||||
foreach (var item in list)
|
||||
{
|
||||
var clone = cloned.Single(x => x.Id == item.Id);
|
||||
Assert.AreNotSame(item, clone);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core.Collections;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core.Collections
|
||||
{
|
||||
[TestFixture]
|
||||
public class OrderedHashSetTests
|
||||
{
|
||||
[Test]
|
||||
public void Keeps_Last()
|
||||
{
|
||||
var list = new OrderedHashSet<MyClass>(keepOldest: false);
|
||||
var items = new[] {new MyClass("test"), new MyClass("test"), new MyClass("test")};
|
||||
foreach (var item in items)
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
|
||||
Assert.AreEqual(1, list.Count);
|
||||
Assert.AreEqual(items[2].Id, list[0].Id);
|
||||
Assert.AreNotEqual(items[0].Id, list[0].Id);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Keeps_First()
|
||||
{
|
||||
var list = new OrderedHashSet<MyClass>(keepOldest: true);
|
||||
var items = new[] {new MyClass("test"), new MyClass("test"), new MyClass("test")};
|
||||
foreach (var item in items)
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
|
||||
Assert.AreEqual(1, list.Count);
|
||||
Assert.AreEqual(items[0].Id, list[0].Id);
|
||||
}
|
||||
|
||||
private class MyClass : IEquatable<MyClass>
|
||||
{
|
||||
public MyClass(string name)
|
||||
{
|
||||
Name = name;
|
||||
Id = Guid.NewGuid();
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public Guid Id { get; }
|
||||
|
||||
public bool Equals(MyClass other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return string.Equals(Name, other.Name);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((MyClass) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Name.GetHashCode();
|
||||
}
|
||||
|
||||
public static bool operator ==(MyClass left, MyClass right)
|
||||
{
|
||||
return Equals(left, right);
|
||||
}
|
||||
|
||||
public static bool operator !=(MyClass left, MyClass right)
|
||||
{
|
||||
return Equals(left, right) == false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using Lucene.Net.Index;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core
|
||||
{
|
||||
[TestFixture]
|
||||
public class DelegateExtensionsTests
|
||||
{
|
||||
[Test]
|
||||
public void Only_Executes_Specific_Count()
|
||||
{
|
||||
const int maxTries = 5;
|
||||
var totalTries = 0;
|
||||
DelegateExtensions.RetryUntilSuccessOrMaxAttempts((currentTry) =>
|
||||
{
|
||||
totalTries = currentTry;
|
||||
return Attempt<IndexWriter>.Fail();
|
||||
}, 5, TimeSpan.FromMilliseconds(10));
|
||||
|
||||
Assert.AreEqual(maxTries, totalTries);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Quits_On_Success_Count()
|
||||
{
|
||||
var totalTries = 0;
|
||||
DelegateExtensions.RetryUntilSuccessOrMaxAttempts((currentTry) =>
|
||||
{
|
||||
totalTries = currentTry;
|
||||
return totalTries == 2 ? Attempt<string>.Succeed() : Attempt<string>.Fail();
|
||||
}, 5, TimeSpan.FromMilliseconds(10));
|
||||
|
||||
Assert.AreEqual(2, totalTries);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Web.Trees;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core
|
||||
{
|
||||
[TestFixture]
|
||||
public class EnumExtensionsTests
|
||||
{
|
||||
[TestCase(TreeUse.Dialog, TreeUse.Dialog, true)]
|
||||
[TestCase(TreeUse.Dialog, TreeUse.Main, false)]
|
||||
[TestCase(TreeUse.Dialog | TreeUse.Main, TreeUse.Dialog, true)]
|
||||
[TestCase(TreeUse.Dialog, TreeUse.Dialog | TreeUse.Main, false)]
|
||||
public void HasFlagTest(TreeUse value, TreeUse test, bool expected)
|
||||
{
|
||||
// the built-in Enum.HasFlag() method determines whether
|
||||
// all bits from <test> are set (other bits can be set too)
|
||||
|
||||
if (expected)
|
||||
Assert.IsTrue(value.HasFlag(test));
|
||||
else
|
||||
Assert.IsFalse(value.HasFlag(test));
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
[TestCase(TreeUse.Dialog, TreeUse.Dialog, true)]
|
||||
[TestCase(TreeUse.Dialog, TreeUse.Main, false)]
|
||||
[TestCase(TreeUse.Dialog | TreeUse.Main, TreeUse.Dialog, true)]
|
||||
[TestCase(TreeUse.Dialog, TreeUse.Dialog | TreeUse.Main, false)]
|
||||
public void HasFlagAllTest(TreeUse value, TreeUse test, bool expected)
|
||||
{
|
||||
// the HasFlagAll() extension method determines whether
|
||||
// all bits from <test> are set (other bits can be set too)
|
||||
|
||||
if (expected)
|
||||
Assert.IsTrue(value.HasFlagAll(test));
|
||||
else
|
||||
Assert.IsFalse(value.HasFlagAll(test));
|
||||
}
|
||||
|
||||
[TestCase(TreeUse.Dialog, TreeUse.Dialog, true)]
|
||||
[TestCase(TreeUse.Dialog, TreeUse.Main, false)]
|
||||
[TestCase(TreeUse.Dialog | TreeUse.Main, TreeUse.Dialog, true)]
|
||||
[TestCase(TreeUse.Dialog, TreeUse.Dialog | TreeUse.Main, true)]
|
||||
public void HasFlagAnyTest(TreeUse value, TreeUse test, bool expected)
|
||||
{
|
||||
// the HasFlagAny() extension method determines whether
|
||||
// at least one bit from <test> is set
|
||||
|
||||
if (expected)
|
||||
Assert.IsTrue(value.HasFlagAny(test));
|
||||
else
|
||||
Assert.IsFalse(value.HasFlagAny(test));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core
|
||||
{
|
||||
[TestFixture]
|
||||
public class EnumerableExtensionsTests
|
||||
{
|
||||
[Test]
|
||||
public void Unsorted_Sequence_Equal()
|
||||
{
|
||||
var list1 = new[] { 1, 2, 3, 4, 5, 6 };
|
||||
var list2 = new[] { 6, 5, 3, 2, 1, 4 };
|
||||
var list3 = new[] { 6, 5, 4, 3, 2, 2 };
|
||||
|
||||
Assert.IsTrue(list1.UnsortedSequenceEqual(list2));
|
||||
Assert.IsTrue(list2.UnsortedSequenceEqual(list1));
|
||||
Assert.IsFalse(list1.UnsortedSequenceEqual(list3));
|
||||
|
||||
Assert.IsTrue(((IEnumerable<object>)null).UnsortedSequenceEqual(null));
|
||||
Assert.IsFalse(((IEnumerable<int>)null).UnsortedSequenceEqual(list1));
|
||||
Assert.IsFalse(list1.UnsortedSequenceEqual(null));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Contains_All()
|
||||
{
|
||||
var list1 = new[] {1, 2, 3, 4, 5, 6};
|
||||
var list2 = new[] {6, 5, 3, 2, 1, 4};
|
||||
var list3 = new[] {6, 5, 4, 3};
|
||||
|
||||
Assert.IsTrue(list1.ContainsAll(list2));
|
||||
Assert.IsTrue(list2.ContainsAll(list1));
|
||||
Assert.IsTrue(list1.ContainsAll(list3));
|
||||
Assert.IsFalse(list3.ContainsAll(list1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SelectRecursive_2()
|
||||
{
|
||||
var hierarchy = new TestItem("1")
|
||||
{
|
||||
Children = new List<TestItem>
|
||||
{
|
||||
new TestItem("1.1"),
|
||||
new TestItem("1.2"),
|
||||
new TestItem("1.3")
|
||||
}
|
||||
};
|
||||
|
||||
var selectRecursive = hierarchy.Children.SelectRecursive(x => x.Children);
|
||||
|
||||
Assert.AreEqual(3, selectRecursive.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SelectRecursive()
|
||||
{
|
||||
var hierarchy = new TestItem("1")
|
||||
{
|
||||
Children = new List<TestItem>
|
||||
{
|
||||
new TestItem("1.1")
|
||||
{
|
||||
Children = new List<TestItem>
|
||||
{
|
||||
new TestItem("1.1.1")
|
||||
{
|
||||
Children = new List<TestItem>
|
||||
{
|
||||
new TestItem("1.1.1.1")
|
||||
{
|
||||
Children = new List<TestItem>
|
||||
{
|
||||
new TestItem("1.1.1.1.1"),
|
||||
new TestItem("1.1.1.1.2")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new TestItem("1.2")
|
||||
{
|
||||
Children = new List<TestItem>
|
||||
{
|
||||
new TestItem("1.2.1")
|
||||
{
|
||||
Children = new List<TestItem>
|
||||
{
|
||||
new TestItem("1.2.1.1")
|
||||
{
|
||||
Children = new List<TestItem>()
|
||||
}
|
||||
}
|
||||
},
|
||||
new TestItem("1.2.2")
|
||||
{
|
||||
Children = new List<TestItem>
|
||||
{
|
||||
new TestItem("1.2.2.1")
|
||||
{
|
||||
Children = new List<TestItem>()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var selectRecursive = hierarchy.Children.SelectRecursive(x => x.Children);
|
||||
Assert.AreEqual(10, selectRecursive.Count());
|
||||
}
|
||||
|
||||
private class TestItem
|
||||
{
|
||||
public TestItem(string name)
|
||||
{
|
||||
Children = Enumerable.Empty<TestItem>();
|
||||
Name = name;
|
||||
}
|
||||
public string Name { get; }
|
||||
public IEnumerable<TestItem> Children { get; set; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InGroupsOf_ReturnsAllElements()
|
||||
{
|
||||
var integers = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
|
||||
var groupsOfTwo = integers.InGroupsOf(2).ToArray();
|
||||
|
||||
var flattened = groupsOfTwo.SelectMany(x => x).ToArray();
|
||||
|
||||
Assert.That(groupsOfTwo.Length, Is.EqualTo(5));
|
||||
Assert.That(flattened.Length, Is.EqualTo(integers.Length));
|
||||
CollectionAssert.AreEquivalent(integers, flattened);
|
||||
|
||||
var groupsOfMassive = integers.InGroupsOf(100).ToArray();
|
||||
Assert.That(groupsOfMassive.Length, Is.EqualTo(1));
|
||||
flattened = groupsOfMassive.SelectMany(x => x).ToArray();
|
||||
Assert.That(flattened.Length, Is.EqualTo(integers.Length));
|
||||
CollectionAssert.AreEquivalent(integers, flattened);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InGroupsOf_CanRepeat()
|
||||
{
|
||||
var integers = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
var inGroupsOf = integers.InGroupsOf(2);
|
||||
Assert.AreEqual(5, inGroupsOf.Count());
|
||||
Assert.AreEqual(5, inGroupsOf.Count()); // again
|
||||
}
|
||||
|
||||
[TestCase]
|
||||
public void DistinctBy_ReturnsDistinctElements_AndResetsIteratorCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var tuple1 = new System.Tuple<string, string>("fruit", "apple");
|
||||
var tuple2 = new System.Tuple<string, string>("fruit", "orange");
|
||||
var tuple3 = new System.Tuple<string, string>("fruit", "banana");
|
||||
var tuple4 = new System.Tuple<string, string>("fruit", "banana"); // Should be filtered out
|
||||
var list = new List<System.Tuple<string, string>>()
|
||||
{
|
||||
tuple1,
|
||||
tuple2,
|
||||
tuple3,
|
||||
tuple4
|
||||
};
|
||||
|
||||
// Act
|
||||
var iteratorSource = list.DistinctBy(x => x.Item2);
|
||||
|
||||
// Assert
|
||||
// First check distinction
|
||||
Assert.AreEqual(3, iteratorSource.Count());
|
||||
|
||||
// Check for iterator block mistakes - reset to original query first
|
||||
iteratorSource = list.DistinctBy(x => x.Item2);
|
||||
Assert.AreEqual(iteratorSource.Count(), iteratorSource.ToList().Count());
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/Umbraco.Tests.UnitTests/Umbraco.Core/GuidUtilsTests.cs
Normal file
40
src/Umbraco.Tests.UnitTests/Umbraco.Core/GuidUtilsTests.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core
|
||||
{
|
||||
public class GuidUtilsTests
|
||||
{
|
||||
[Test]
|
||||
public void GuidCombineMethodsAreEqual()
|
||||
{
|
||||
var a = Guid.NewGuid();
|
||||
var b = Guid.NewGuid();
|
||||
|
||||
Assert.AreEqual(GuidUtils.Combine(a, b).ToByteArray(), Combine(a, b));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GuidThingTest()
|
||||
{
|
||||
var guid = new Guid("f918382f-2bba-453f-a3e2-1f594016ed3b");
|
||||
Assert.AreEqual("f22br4n0fm5fli5c", GuidUtils.ToBase32String(guid, 16));
|
||||
Assert.AreEqual("f22br4n0f", GuidUtils.ToBase32String(guid, 9));
|
||||
}
|
||||
|
||||
// Reference implementation taken from original code.
|
||||
private static byte[] Combine(Guid guid1, Guid guid2)
|
||||
{
|
||||
var bytes1 = guid1.ToByteArray();
|
||||
var bytes2 = guid2.ToByteArray();
|
||||
var bytes = new byte[bytes1.Length];
|
||||
for (var i = 0; i < bytes1.Length; i++)
|
||||
{
|
||||
bytes[i] = (byte)(bytes1[i] ^ bytes2[i]);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
71
src/Umbraco.Tests.UnitTests/Umbraco.Core/HexEncoderTests.cs
Normal file
71
src/Umbraco.Tests.UnitTests/Umbraco.Core/HexEncoderTests.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core
|
||||
{
|
||||
public class HexEncoderTests
|
||||
{
|
||||
[Test]
|
||||
public void ToHexStringCreatesCorrectValue()
|
||||
{
|
||||
var buffer = new byte[255];
|
||||
var random = new Random();
|
||||
random.NextBytes(buffer);
|
||||
|
||||
var sb = new StringBuilder(buffer.Length * 2);
|
||||
for (var i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
sb.Append(buffer[i].ToString("X2"));
|
||||
}
|
||||
|
||||
var expected = sb.ToString();
|
||||
|
||||
var actual = HexEncoder.Encode(buffer);
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToHexStringWithSeparatorCreatesCorrectValue()
|
||||
{
|
||||
var buffer = new byte[255];
|
||||
var random = new Random();
|
||||
random.NextBytes(buffer);
|
||||
|
||||
var expected = ToHexString(buffer, '/', 2, 4);
|
||||
var actual = HexEncoder.Encode(buffer, '/', 2, 4);
|
||||
|
||||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
private static readonly char[] _bytesToHexStringLookup = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
// Reference implementation taken from original extension method.
|
||||
private static string ToHexString(byte[] bytes, char separator, int blockSize, int blockCount)
|
||||
{
|
||||
int p = 0, bytesLength = bytes.Length, count = 0, size = 0;
|
||||
var chars = new char[(bytesLength * 2) + blockCount];
|
||||
for (var i = 0; i < bytesLength; i++)
|
||||
{
|
||||
var b = bytes[i];
|
||||
chars[p++] = _bytesToHexStringLookup[b / 0x10];
|
||||
chars[p++] = _bytesToHexStringLookup[b % 0x10];
|
||||
if (count == blockCount)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (++size < blockSize)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
chars[p++] = separator;
|
||||
size = 0;
|
||||
count++;
|
||||
}
|
||||
return new string(chars, 0, chars.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/Umbraco.Tests.UnitTests/Umbraco.Core/ReflectionTests.cs
Normal file
40
src/Umbraco.Tests.UnitTests/Umbraco.Core/ReflectionTests.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core
|
||||
{
|
||||
[TestFixture]
|
||||
public class ReflectionTests
|
||||
{
|
||||
[Test]
|
||||
public void GetBaseTypesIsOk()
|
||||
{
|
||||
// tests that the GetBaseTypes extension method works.
|
||||
|
||||
var type = typeof(Class2);
|
||||
var types = type.GetBaseTypes(true).ToArray();
|
||||
Assert.AreEqual(3, types.Length);
|
||||
Assert.Contains(typeof(Class2), types);
|
||||
Assert.Contains(typeof(Class1), types);
|
||||
Assert.Contains(typeof(object), types);
|
||||
|
||||
types = type.GetBaseTypes(false).ToArray();
|
||||
Assert.AreEqual(2, types.Length);
|
||||
Assert.Contains(typeof(Class1), types);
|
||||
Assert.Contains(typeof(object), types);
|
||||
}
|
||||
|
||||
#region Test Objects
|
||||
|
||||
private class Class1
|
||||
{
|
||||
}
|
||||
|
||||
private class Class2 : Class1
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,677 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core
|
||||
{
|
||||
[TestFixture]
|
||||
public class ReflectionUtilitiesTests
|
||||
{
|
||||
[Test]
|
||||
public void EmitCtorEmits()
|
||||
{
|
||||
var ctor1 = ReflectionUtilities.EmitConstructor<Func<Class1>>();
|
||||
Assert.IsInstanceOf<Class1>(ctor1());
|
||||
|
||||
var ctor2 = ReflectionUtilities.EmitConstructor<Func<object>>(declaring: typeof(Class1));
|
||||
Assert.IsInstanceOf<Class1>(ctor2());
|
||||
|
||||
var ctor3 = ReflectionUtilities.EmitConstructor<Func<int, Class3>>();
|
||||
Assert.IsInstanceOf<Class3>(ctor3(42));
|
||||
|
||||
var ctor4 = ReflectionUtilities.EmitConstructor<Func<int, object>>(declaring: typeof(Class3));
|
||||
Assert.IsInstanceOf<Class3>(ctor4(42));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitCtorEmitsFromInfo()
|
||||
{
|
||||
var ctorInfo = typeof(Class1).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Any, Array.Empty<Type>(), null);
|
||||
var ctor1 = ReflectionUtilities.EmitConstructor<Func<Class1>>(ctorInfo);
|
||||
Assert.IsInstanceOf<Class1>(ctor1());
|
||||
|
||||
ctorInfo = typeof(Class1).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Any, new[] { typeof(int) }, null);
|
||||
var ctor3 = ReflectionUtilities.EmitConstructor<Func<int, object>>(ctorInfo);
|
||||
Assert.IsInstanceOf<Class1>(ctor3(42));
|
||||
|
||||
Assert.Throws<ArgumentException>(() => ReflectionUtilities.EmitConstructor<Func<string, object>>(ctorInfo));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitCtorEmitsPrivateCtor()
|
||||
{
|
||||
var ctor = ReflectionUtilities.EmitConstructor<Func<string, Class3>>();
|
||||
Assert.IsInstanceOf<Class3>(ctor("foo"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitCtorThrowsIfNotFound()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() => ReflectionUtilities.EmitConstructor<Func<bool, Class3>>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitCtorThrowsIfInvalid()
|
||||
{
|
||||
var ctorInfo = typeof(Class1).GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, CallingConventions.Any, Array.Empty<Type>(), null);
|
||||
Assert.Throws<ArgumentException>(() => ReflectionUtilities.EmitConstructor<Func<Class2>>(ctorInfo));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitCtorReturnsNull()
|
||||
{
|
||||
Assert.IsNull(ReflectionUtilities.EmitConstructor<Func<bool, Class3>>(false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitMethodEmitsInstance()
|
||||
{
|
||||
var class1 = new Class1();
|
||||
|
||||
var method1 = ReflectionUtilities.EmitMethod<Action<Class1>>("Method1");
|
||||
method1(class1);
|
||||
|
||||
var method2 = ReflectionUtilities.EmitMethod<Action<Class1, int>>("Method2");
|
||||
method2(class1, 42);
|
||||
|
||||
var method3 = ReflectionUtilities.EmitMethod<Func<Class1, int>>("Method3");
|
||||
Assert.AreEqual(42, method3(class1));
|
||||
|
||||
var method4 = ReflectionUtilities.EmitMethod<Func<Class1, string, int>>("Method4");
|
||||
Assert.AreEqual(42, method4(class1, "42"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitMethodEmitsStatic()
|
||||
{
|
||||
var method1 = ReflectionUtilities.EmitMethod<Class1, Action>("SMethod1");
|
||||
method1();
|
||||
|
||||
var method2 = ReflectionUtilities.EmitMethod<Class1, Action<int>>("SMethod2");
|
||||
method2(42);
|
||||
|
||||
var method3 = ReflectionUtilities.EmitMethod<Class1, Func<int>>("SMethod3");
|
||||
Assert.AreEqual(42, method3());
|
||||
|
||||
var method4 = ReflectionUtilities.EmitMethod<Class1, Func<string, int>>("SMethod4");
|
||||
Assert.AreEqual(42, method4("42"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitMethodEmitsStaticStatic()
|
||||
{
|
||||
var method = ReflectionUtilities.EmitMethod<Action>(typeof (StaticClass1), "Method");
|
||||
method();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitMethodEmitsFromInfo()
|
||||
{
|
||||
var class1 = new Class1();
|
||||
|
||||
var methodInfo = typeof (Class1).GetMethod("Method1", BindingFlags.Instance | BindingFlags.Public);
|
||||
var method1 = ReflectionUtilities.EmitMethod<Action<Class1>>(methodInfo);
|
||||
method1(class1);
|
||||
|
||||
methodInfo = typeof(Class1).GetMethod("Method2", BindingFlags.Instance | BindingFlags.Public, null, new [] { typeof(int) }, null);
|
||||
var method2 = ReflectionUtilities.EmitMethod<Action<Class1, int>>(methodInfo);
|
||||
method2(class1, 42);
|
||||
|
||||
methodInfo = typeof(Class1).GetMethod("Method3", BindingFlags.Instance | BindingFlags.Public);
|
||||
var method3 = ReflectionUtilities.EmitMethod<Func<Class1, int>>(methodInfo);
|
||||
Assert.AreEqual(42, method3(class1));
|
||||
|
||||
methodInfo = typeof(Class1).GetMethod("Method4", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(string) }, null);
|
||||
var method4 = ReflectionUtilities.EmitMethod<Func<Class1, string, int>>(methodInfo);
|
||||
Assert.AreEqual(42, method4(class1, "42"));
|
||||
|
||||
methodInfo = typeof(Class1).GetMethod("SMethod1", BindingFlags.Static | BindingFlags.Public);
|
||||
var smethod1 = ReflectionUtilities.EmitMethod<Action>(methodInfo);
|
||||
smethod1();
|
||||
|
||||
methodInfo = typeof(Class1).GetMethod("SMethod2", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(int) }, null);
|
||||
var smethod2 = ReflectionUtilities.EmitMethod<Action<int>>(methodInfo);
|
||||
smethod2(42);
|
||||
|
||||
methodInfo = typeof(Class1).GetMethod("SMethod3", BindingFlags.Static | BindingFlags.Public);
|
||||
var smethod3 = ReflectionUtilities.EmitMethod<Func<int>>(methodInfo);
|
||||
Assert.AreEqual(42, smethod3());
|
||||
|
||||
methodInfo = typeof(Class1).GetMethod("SMethod4", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(string) }, null);
|
||||
var smethod4 = ReflectionUtilities.EmitMethod<Func<string, int>>(methodInfo);
|
||||
Assert.AreEqual(42, smethod4("42"));
|
||||
|
||||
methodInfo = typeof(StaticClass1).GetMethod("Method", BindingFlags.Static | BindingFlags.Public);
|
||||
var method = ReflectionUtilities.EmitMethod<Action>(methodInfo);
|
||||
method();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitMethodEmitsPrivateMethod()
|
||||
{
|
||||
var class1 = new Class1();
|
||||
|
||||
var method1 = ReflectionUtilities.EmitMethod<Action<Class1>>("MethodP1");
|
||||
method1(class1);
|
||||
|
||||
var method2 = ReflectionUtilities.EmitMethod<Class1, Action>("SMethodP1");
|
||||
method2();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitMethodThrowsIfNotFound()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() => ReflectionUtilities.EmitMethod<Action<Class1>>("ZZZ"));
|
||||
Assert.Throws<InvalidOperationException>(() => ReflectionUtilities.EmitMethod<Action<Class1, int, int>>("Method1"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitMethodThrowsIfInvalid()
|
||||
{
|
||||
var methodInfo = typeof(Class1).GetMethod("Method1", BindingFlags.Instance | BindingFlags.Public);
|
||||
Assert.Throws<ArgumentException>(() => ReflectionUtilities.EmitMethod<Action<Class1, int, int>>(methodInfo));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitMethodReturnsNull()
|
||||
{
|
||||
Assert.IsNull(ReflectionUtilities.EmitMethod<Action<Class1>>("ZZZ", false));
|
||||
Assert.IsNull(ReflectionUtilities.EmitMethod<Action<Class1, int, int>>("Method1", false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitPropertyEmits()
|
||||
{
|
||||
var class1 = new Class1();
|
||||
|
||||
var getter1 = ReflectionUtilities.EmitPropertyGetter<Class1, int>("Value1");
|
||||
Assert.AreEqual(42, getter1(class1));
|
||||
|
||||
var getter2 = ReflectionUtilities.EmitPropertyGetter<Class1, int>("Value3");
|
||||
Assert.AreEqual(42, getter2(class1));
|
||||
|
||||
var setter1 = ReflectionUtilities.EmitPropertySetter<Class1, int>("Value2");
|
||||
setter1(class1, 42);
|
||||
|
||||
var setter2 = ReflectionUtilities.EmitPropertySetter<Class1, int>("Value3");
|
||||
setter2(class1, 42);
|
||||
|
||||
(var getter3, var setter3) = ReflectionUtilities.EmitPropertyGetterAndSetter<Class1, int>("Value3");
|
||||
Assert.AreEqual(42, getter3(class1));
|
||||
setter3(class1, 42);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitPropertyEmitsFromInfo()
|
||||
{
|
||||
var class1 = new Class1();
|
||||
|
||||
var propertyInfo = typeof (Class1).GetProperty("Value1");
|
||||
var getter1 = ReflectionUtilities.EmitPropertyGetter<Class1, int>(propertyInfo);
|
||||
Assert.AreEqual(42, getter1(class1));
|
||||
|
||||
propertyInfo = typeof(Class1).GetProperty("Value3");
|
||||
var getter2 = ReflectionUtilities.EmitPropertyGetter<Class1, int>(propertyInfo);
|
||||
Assert.AreEqual(42, getter2(class1));
|
||||
|
||||
propertyInfo = typeof(Class1).GetProperty("Value2");
|
||||
var setter1 = ReflectionUtilities.EmitPropertySetter<Class1, int>(propertyInfo);
|
||||
setter1(class1, 42);
|
||||
|
||||
propertyInfo = typeof(Class1).GetProperty("Value3");
|
||||
var setter2 = ReflectionUtilities.EmitPropertySetter<Class1, int>(propertyInfo);
|
||||
setter2(class1, 42);
|
||||
|
||||
(var getter3, var setter3) = ReflectionUtilities.EmitPropertyGetterAndSetter<Class1, int>(propertyInfo);
|
||||
Assert.AreEqual(42, getter3(class1));
|
||||
setter3(class1, 42);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitPropertyEmitsPrivateProperty()
|
||||
{
|
||||
var class1 = new Class1();
|
||||
|
||||
var getter1 = ReflectionUtilities.EmitPropertyGetter<Class1, int>("ValueP1");
|
||||
Assert.AreEqual(42, getter1(class1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitPropertyThrowsIfNotFound()
|
||||
{
|
||||
Assert.Throws<InvalidOperationException>(() => ReflectionUtilities.EmitPropertyGetter<Class1, int>("Zalue1"));
|
||||
Assert.Throws<InvalidOperationException>(() => ReflectionUtilities.EmitPropertyGetter<Class1, int>("Value2"));
|
||||
|
||||
var propertyInfo = typeof(Class1).GetProperty("Value1");
|
||||
Assert.Throws<ArgumentException>(() => ReflectionUtilities.EmitPropertySetter<Class1, int>(propertyInfo));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitPropertyThrowsIfInvalid()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => ReflectionUtilities.EmitPropertyGetter<Class1, string>("Value1"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitPropertyReturnsNull()
|
||||
{
|
||||
Assert.IsNull(ReflectionUtilities.EmitPropertyGetter<Class1, int>("Zalue1", false));
|
||||
Assert.IsNull(ReflectionUtilities.EmitPropertyGetter<Class1, int>("Value2", false));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PropertySetterCanCastUnsafeValue()
|
||||
{
|
||||
// test that we can emit property setters that cast from eg 'object'
|
||||
|
||||
var type4 = typeof(Class4);
|
||||
var propInt4 = type4.GetProperty("IntValue");
|
||||
var propString4 = type4.GetProperty("StringValue");
|
||||
var propClassA4 = type4.GetProperty("ClassAValue");
|
||||
|
||||
var object4 = new Class4();
|
||||
var object2A = new Class2A();
|
||||
|
||||
// works with a string property
|
||||
Assert.IsNotNull(propString4);
|
||||
var setterString4 = ReflectionUtilities.EmitPropertySetterUnsafe<Class4, object>(propString4);
|
||||
Assert.IsNotNull(setterString4);
|
||||
setterString4(object4, "foo");
|
||||
Assert.IsNotNull(object4.StringValue);
|
||||
Assert.AreEqual("foo", object4.StringValue);
|
||||
|
||||
// unsafe is... unsafe
|
||||
Assert.Throws<InvalidCastException>(() => setterString4(object4, new Class2()));
|
||||
|
||||
// works with a reference property
|
||||
Assert.IsNotNull(propClassA4);
|
||||
var setterClassA4 = ReflectionUtilities.EmitPropertySetterUnsafe<Class4, object>(propClassA4);
|
||||
Assert.IsNotNull(setterClassA4);
|
||||
setterClassA4(object4, object2A);
|
||||
Assert.IsNotNull(object4.ClassAValue);
|
||||
Assert.AreEqual(object2A, object4.ClassAValue);
|
||||
|
||||
// works with a boxed value type
|
||||
Assert.IsNotNull(propInt4);
|
||||
var setterInt4 = ReflectionUtilities.EmitPropertySetterUnsafe<Class4, object>(propInt4);
|
||||
Assert.IsNotNull(setterInt4);
|
||||
|
||||
setterInt4(object4, 42);
|
||||
Assert.AreEqual(42, object4.IntValue);
|
||||
|
||||
// FIXME: the code below runs fine with ReSharper test running within VisualStudio
|
||||
// but it crashes when running via vstest.console.exe - unless some settings are required?
|
||||
|
||||
// converting works
|
||||
setterInt4(object4, 42.0);
|
||||
Assert.AreEqual(42, object4.IntValue);
|
||||
|
||||
// unsafe is... unsafe
|
||||
Assert.Throws<FormatException>(() => setterInt4(object4, "foo"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PropertySetterCanCastObject()
|
||||
{
|
||||
// Class5 inherits from Class4 and ClassValue is defined on Class4
|
||||
|
||||
var type5 = typeof(Class5);
|
||||
var propClass4 = type5.GetProperty("ClassValue");
|
||||
|
||||
var object2 = new Class2();
|
||||
|
||||
// can cast the object type from Class5 to Class4
|
||||
var setterClass4 = ReflectionUtilities.EmitPropertySetter<Class5, Class2>(propClass4);
|
||||
|
||||
var object4 = new Class5();
|
||||
setterClass4(object4, object2);
|
||||
Assert.IsNotNull(object4.ClassValue);
|
||||
Assert.AreSame(object2, object4.ClassValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PropertySetterCanCastUnsafeObject()
|
||||
{
|
||||
var type5 = typeof(Class5);
|
||||
var propClass4 = type5.GetProperty("ClassValue");
|
||||
|
||||
var object2 = new Class2();
|
||||
|
||||
// can cast the object type from object to Class4
|
||||
var setterClass4 = ReflectionUtilities.EmitPropertySetterUnsafe<object, Class2>(propClass4);
|
||||
|
||||
var object4 = new Class5();
|
||||
setterClass4(object4, object2);
|
||||
Assert.IsNotNull(object4.ClassValue);
|
||||
Assert.AreSame(object2, object4.ClassValue);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PropertyGetterCanCastValue()
|
||||
{
|
||||
var type4 = typeof(Class4);
|
||||
var propClassA4 = type4.GetProperty("ClassAValue");
|
||||
var propInt4 = type4.GetProperty("IntValue");
|
||||
|
||||
var object2A = new Class2A();
|
||||
var object4 = new Class4 { ClassAValue = object2A, IntValue = 159 };
|
||||
|
||||
// can cast the return type from Class2A to Class2
|
||||
var getterClassA4 = ReflectionUtilities.EmitPropertyGetter<Class4, Class2>(propClassA4);
|
||||
|
||||
var valueClass4A = getterClassA4(object4);
|
||||
Assert.IsNotNull(valueClass4A);
|
||||
Assert.AreSame(object2A, valueClass4A);
|
||||
|
||||
// cannot cast the return type from Class2A to Class3!
|
||||
Assert.Throws<ArgumentException>(()
|
||||
=> ReflectionUtilities.EmitPropertyGetter<Class4, Class3>(propClassA4));
|
||||
|
||||
// can cast and box the return type from int to object
|
||||
var getterInt4 = ReflectionUtilities.EmitPropertyGetter<Class4, object>(propInt4);
|
||||
|
||||
var valueInt4 = getterInt4(object4);
|
||||
Assert.IsTrue(valueInt4 is int);
|
||||
Assert.AreEqual(159, valueInt4);
|
||||
|
||||
// cannot cast the return type from int to Class3!
|
||||
Assert.Throws<ArgumentException>(()
|
||||
=> ReflectionUtilities.EmitPropertyGetter<Class4, Class3>(propInt4));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void PropertyGetterCanCastObject()
|
||||
{
|
||||
var type5 = typeof(Class5);
|
||||
var propClass4 = type5.GetProperty("ClassValue");
|
||||
|
||||
var object2 = new Class2();
|
||||
var object4 = new Class5 { ClassValue = object2 };
|
||||
|
||||
// can cast the object type from Class5 to Class4
|
||||
var getterClass4 = ReflectionUtilities.EmitPropertyGetter<Class5, Class2>(propClass4);
|
||||
|
||||
var valueClass4 = getterClass4(object4);
|
||||
Assert.IsNotNull(valueClass4);
|
||||
Assert.AreSame(object2, valueClass4);
|
||||
|
||||
// cannot cast the object type from Class3 to Class4!
|
||||
Assert.Throws<ArgumentException>(()
|
||||
=> ReflectionUtilities.EmitPropertyGetter<Class3, Class2>(propClass4));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitPropertyCastGetterEmits()
|
||||
{
|
||||
// test that we can emit property getters that cast the returned value to 'object'
|
||||
|
||||
// test simple class
|
||||
|
||||
var type4 = typeof(Class4);
|
||||
|
||||
var object4 = new Class4
|
||||
{
|
||||
IntValue = 1,
|
||||
StringValue = "foo",
|
||||
ClassValue = new Class2(),
|
||||
};
|
||||
|
||||
// works with a string property
|
||||
var propString4 = type4.GetProperty("StringValue");
|
||||
Assert.IsNotNull(propString4);
|
||||
var getterString4 = ReflectionUtilities.EmitPropertyGetter<Class4, object>(propString4);
|
||||
Assert.IsNotNull(getterString4);
|
||||
var valueString4 = getterString4(object4);
|
||||
Assert.IsNotNull(valueString4);
|
||||
Assert.AreEqual("foo", valueString4);
|
||||
|
||||
// works with a reference property
|
||||
var propClass4 = type4.GetProperty("ClassValue");
|
||||
Assert.IsNotNull(propClass4);
|
||||
var getterClass4 = ReflectionUtilities.EmitPropertyGetter<Class4, object>(propClass4);
|
||||
Assert.IsNotNull(getterClass4);
|
||||
var valueClass4 = getterClass4(object4);
|
||||
Assert.IsNotNull(valueClass4);
|
||||
Assert.IsInstanceOf<Class2>(valueClass4);
|
||||
|
||||
// works with a value type property
|
||||
var propInt4 = type4.GetProperty("IntValue");
|
||||
Assert.IsNotNull(propInt4);
|
||||
|
||||
// ... if explicitly getting a value type
|
||||
var getterInt4T = ReflectionUtilities.EmitPropertyGetter<Class4, int>(propInt4);
|
||||
Assert.IsNotNull(getterInt4T);
|
||||
var valueInt4T = getterInt4T(object4);
|
||||
Assert.AreEqual(1, valueInt4T);
|
||||
|
||||
// ... if using a compiled getter
|
||||
var valueInt4D = GetIntValue(object4);
|
||||
Assert.IsNotNull(valueInt4D);
|
||||
Assert.IsTrue(valueInt4D is int);
|
||||
Assert.AreEqual(1, valueInt4D);
|
||||
|
||||
// ... if getting a non-value type (emit adds a box)
|
||||
var getterInt4 = ReflectionUtilities.EmitPropertyGetter<Class4, object>(propInt4);
|
||||
Assert.IsNotNull(getterInt4);
|
||||
var valueInt4 = getterInt4(object4);
|
||||
Assert.IsNotNull(valueInt4);
|
||||
Assert.IsTrue(valueInt4 is int);
|
||||
Assert.AreEqual(1, valueInt4);
|
||||
|
||||
var getters4 = type4
|
||||
.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
|
||||
.ToDictionary(x => x.Name, x => (object) ReflectionUtilities.EmitPropertyGetter<Class4, object>(x));
|
||||
|
||||
Console.WriteLine("Getting object4 values...");
|
||||
var values4 = getters4.ToDictionary(kvp => kvp.Key, kvp => ((Func<Class4, object>) kvp.Value)(object4));
|
||||
|
||||
Console.WriteLine("Writing object4 values...");
|
||||
foreach ((var name, var value) in values4)
|
||||
Console.WriteLine($"{name}: {value}");
|
||||
Assert.AreEqual(4, values4.Count);
|
||||
Assert.AreEqual("foo", values4["StringValue"]);
|
||||
Assert.IsInstanceOf<Class2>(values4["ClassValue"]);
|
||||
Assert.AreEqual(1, values4["IntValue"]);
|
||||
|
||||
// test hierarchy
|
||||
|
||||
var type5 = typeof(Class5);
|
||||
|
||||
var getters5 = type5
|
||||
.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
|
||||
.ToDictionary(x => x.Name, x => (object) ReflectionUtilities.EmitPropertyGetter<Class5, object>(x));
|
||||
|
||||
var object5 = new Class5
|
||||
{
|
||||
IntValue = 1,
|
||||
IntValue2 = 1,
|
||||
StringValue = "foo",
|
||||
StringValue2 = "foo",
|
||||
ClassValue = new Class2(),
|
||||
ClassValue2 = new Class2()
|
||||
};
|
||||
|
||||
Console.WriteLine("Getting object5 values...");
|
||||
var values5 = getters5.ToDictionary(kvp => kvp.Key, kvp => ((Func<Class5, object>) kvp.Value)(object5));
|
||||
|
||||
Console.WriteLine("Writing object5 values...");
|
||||
foreach ((var name, var value) in values5)
|
||||
Console.WriteLine($"{name}: {value}");
|
||||
Assert.AreEqual(7, values5.Count);
|
||||
Assert.AreEqual("foo", values5["StringValue"]);
|
||||
Assert.IsInstanceOf<Class2>(values5["ClassValue"]);
|
||||
Assert.AreEqual(1, values5["IntValue"]);
|
||||
Assert.AreEqual("foo", values5["StringValue2"]);
|
||||
Assert.IsInstanceOf<Class2>(values5["ClassValue2"]);
|
||||
Assert.AreEqual(1, values5["IntValue2"]);
|
||||
|
||||
// test object extensions
|
||||
|
||||
Console.WriteLine("Getting object5D values...");
|
||||
var values5D = ObjectJsonExtensions.ToObjectDictionary(object5);
|
||||
|
||||
Console.WriteLine("Writing object5D values...");
|
||||
foreach ((var name, var value) in values5)
|
||||
Console.WriteLine($"{name}: {value}");
|
||||
Assert.AreEqual(7, values5.Count);
|
||||
Assert.AreEqual("foo", values5D["StringValue"]);
|
||||
Assert.IsInstanceOf<Class2>(values5D["ClassValue"]);
|
||||
Assert.AreEqual(1, values5D["IntValue"]);
|
||||
Assert.AreEqual("foo", values5D["StringValue2"]);
|
||||
Assert.IsInstanceOf<Class2>(values5D["ClassValue2"]);
|
||||
Assert.AreEqual(1, values5D["intValue2"]); // JsonProperty changes property name
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmitFieldGetterSetterEmits()
|
||||
{
|
||||
var getter1 = ReflectionUtilities.EmitFieldGetter<Class1, int>("Field1");
|
||||
var getter2 = ReflectionUtilities.EmitFieldGetter<Class1, int>("Field2");
|
||||
var c = new Class1();
|
||||
Assert.AreEqual(33, getter1(c));
|
||||
Assert.AreEqual(66, getter2(c));
|
||||
|
||||
var setter2 = ReflectionUtilities.EmitFieldSetter<Class1, int>("Field2");
|
||||
setter2(c, 99);
|
||||
Assert.AreEqual(99, getter2(c));
|
||||
|
||||
// works on readonly fields!
|
||||
var (getter3, setter3) = ReflectionUtilities.EmitFieldGetterAndSetter<Class1, int>("Field3");
|
||||
Assert.AreEqual(22, getter3(c));
|
||||
setter3(c, 44);
|
||||
Assert.AreEqual(44, getter3(c));
|
||||
}
|
||||
|
||||
// FIXME: missing tests specifying 'returned' on method, property
|
||||
|
||||
[Test]
|
||||
public void DeconstructAnonymousType()
|
||||
{
|
||||
var o = new { a = 1, b = "hello" };
|
||||
|
||||
var getters = new Dictionary<string, Func<object, object>>();
|
||||
foreach (var prop in o.GetType().GetProperties())
|
||||
getters[prop.Name] = ReflectionUtilities.EmitMethodUnsafe<Func<object, object>>(prop.GetMethod);
|
||||
|
||||
Assert.AreEqual(2, getters.Count);
|
||||
Assert.IsTrue(getters.ContainsKey("a"));
|
||||
Assert.IsTrue(getters.ContainsKey("b"));
|
||||
Assert.AreEqual(1, getters["a"](o));
|
||||
Assert.AreEqual("hello", getters["b"](o));
|
||||
}
|
||||
|
||||
#region IL Code
|
||||
|
||||
// these functions can be examined in eg DotPeek to understand IL works
|
||||
|
||||
// box [mscorlib]System.Int32
|
||||
public object GetIntValue(Class4 object4) => object4.IntValue;
|
||||
|
||||
// unbox.any [mscorlib]System.Int32
|
||||
public void SetIntValue(Class4 object4, object i) => object4.IntValue = (int) i;
|
||||
|
||||
// castclass [mscorlib]System.String
|
||||
public void SetStringValue(Class4 object4, object s) => object4.StringValue = (string) s;
|
||||
|
||||
// conv.i4
|
||||
public void SetIntValue(Class4 object4, double d) => object4.IntValue = (int) d;
|
||||
|
||||
// unbox.any [mscorlib]System.Double
|
||||
// conv.i4
|
||||
public void SetIntValue2(Class4 object4, object d) => object4.IntValue = (int) (double) d;
|
||||
|
||||
public void SetIntValue3(Class4 object4, object v)
|
||||
{
|
||||
if (v is int i)
|
||||
object4.IntValue = i;
|
||||
else
|
||||
object4.IntValue = Convert.ToInt32(v);
|
||||
}
|
||||
|
||||
public void SetIntValue4(Class4 object4, object v)
|
||||
{
|
||||
if (v is int i)
|
||||
object4.IntValue = i;
|
||||
else
|
||||
object4.IntValue = (int) Convert.ChangeType(v, typeof(int));
|
||||
}
|
||||
|
||||
// get field
|
||||
public int GetIntField(Class1 object1) => object1.Field1;
|
||||
|
||||
// set field
|
||||
public void SetIntField(Class1 object1, int i) => object1.Field1 = i;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Test Objects
|
||||
|
||||
public static class StaticClass1
|
||||
{
|
||||
public static void Method() { }
|
||||
}
|
||||
|
||||
public class Class1
|
||||
{
|
||||
public Class1() { }
|
||||
public Class1(int i) { }
|
||||
|
||||
public void Method1() { }
|
||||
public void Method2(int i) { }
|
||||
public int Method3() => 42;
|
||||
public int Method4(string s) => int.Parse(s);
|
||||
|
||||
public string Method5() => "foo";
|
||||
|
||||
public static void SMethod1() { }
|
||||
public static void SMethod2(int i) { }
|
||||
public static int SMethod3() => 42;
|
||||
public static int SMethod4(string s) => int.Parse(s);
|
||||
|
||||
private void MethodP1() { }
|
||||
private static void SMethodP1() { }
|
||||
|
||||
public int Value1 => 42;
|
||||
public int Value2 { set { } }
|
||||
public int Value3 { get { return 42; } set { } }
|
||||
private int ValueP1 => 42;
|
||||
|
||||
public int Field1 = 33;
|
||||
private int Field2 = 66;
|
||||
public readonly int Field3 = 22;
|
||||
}
|
||||
|
||||
public class Class2 { }
|
||||
|
||||
public class Class2A : Class2 { }
|
||||
|
||||
public class Class3
|
||||
{
|
||||
public Class3(int i) { }
|
||||
|
||||
private Class3(string s) { }
|
||||
}
|
||||
|
||||
public class Class4
|
||||
{
|
||||
public int IntValue { get; set; }
|
||||
public string StringValue { get; set; }
|
||||
public Class2 ClassValue { get;set; }
|
||||
public Class2A ClassAValue { get; set; }
|
||||
}
|
||||
|
||||
public class Class5 : Class4
|
||||
{
|
||||
[JsonProperty("intValue2")]
|
||||
public int IntValue2 { get; set; }
|
||||
public string StringValue2 { get; set; }
|
||||
public Class2 ClassValue2 { get;set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core
|
||||
{
|
||||
[TestFixture]
|
||||
public class VersionExtensionTests
|
||||
{
|
||||
[TestCase(1, 0, 0, 0, "0.2147483647.2147483647.2147483647")]
|
||||
[TestCase(1, 1, 0, 0, "1.0.2147483647.2147483647")]
|
||||
[TestCase(1, 1, 1, 0, "1.1.0.2147483647")]
|
||||
[TestCase(1, 1, 1, 1, "1.1.1.0")]
|
||||
[TestCase(0, 1, 0, 0, "0.0.2147483647.2147483647")]
|
||||
[TestCase(0, 1, 1, 0, "0.1.0.2147483647")]
|
||||
[TestCase(0, 1, 1, 1, "0.1.1.0")]
|
||||
[TestCase(0, 0, 1, 0, "0.0.0.2147483647")]
|
||||
[TestCase(0, 0, 1, 1, "0.0.1.0")]
|
||||
[TestCase(0, 0, 0, 1, "0.0.0.0")]
|
||||
[TestCase(7, 3, 0, 0, "7.2.2147483647.2147483647")]
|
||||
public void Subtract_Revision(int major, int minor, int build, int rev, string outcome)
|
||||
{
|
||||
var version = new Version(major, minor, build, rev);
|
||||
|
||||
var result = version.SubtractRevision();
|
||||
|
||||
Assert.AreEqual(new Version(outcome), result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Core
|
||||
{
|
||||
[TestFixture]
|
||||
public class XmlExtensionsTests
|
||||
{
|
||||
[Test]
|
||||
public void XCDataToXmlNode()
|
||||
{
|
||||
var cdata = new XElement("test", new XCData("hello world"));
|
||||
var xdoc = new XmlDocument();
|
||||
|
||||
var xmlNode = cdata.GetXmlNode(xdoc);
|
||||
|
||||
Assert.AreEqual("hello world", xmlNode.InnerText);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void XTextToXmlNode()
|
||||
{
|
||||
var cdata = new XElement("test", new XText("hello world"));
|
||||
var xdoc = new XmlDocument();
|
||||
|
||||
var xmlNode = cdata.GetXmlNode(xdoc);
|
||||
|
||||
Assert.AreEqual("hello world", xmlNode.InnerText);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToXmlNodeIsNonDestructive()
|
||||
{
|
||||
const string xml = "<root><foo attr=\"123\">hello</foo><bar>world</bar></root>";
|
||||
|
||||
var cdata = new XElement("test", new XText("hello world"));
|
||||
var xdoc = new XmlDocument();
|
||||
xdoc.LoadXml(xml);
|
||||
|
||||
var xmlNode = cdata.GetXmlNode(xdoc);
|
||||
|
||||
Assert.AreEqual("hello world", xmlNode.InnerText);
|
||||
Assert.AreEqual(xml, xdoc.OuterXml);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Lucene.Net.Contrib" Version="3.0.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1" />
|
||||
|
||||
Reference in New Issue
Block a user