More code and tests written for deep cloning.

This commit is contained in:
Shannon
2014-04-15 19:12:42 +10:00
parent 9118701669
commit 0e4e12d0ba
24 changed files with 1048 additions and 366 deletions

View File

@@ -42,5 +42,27 @@ namespace Umbraco.Core.Models
clone.Id = new Lazy<int>(() => id);
return clone;
}
protected bool Equals(ContentTypeSort other)
{
return Id.Value.Equals(other.Id.Value) && string.Equals(Alias, other.Alias);
}
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((ContentTypeSort) obj);
}
public override int GetHashCode()
{
unchecked
{
return (Id.GetHashCode()*397) ^ Alias.GetHashCode();
}
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
@@ -96,5 +97,12 @@ namespace Umbraco.Core.Models
if(ParentId == Guid.Empty)
_parentId = new Guid("41c7638d-f529-4bff-853e-59a0c2fb1bde");
}
public override object DeepClone()
{
var clone = (DictionaryItem)base.DeepClone();
clone.Translations = Translations.Select(x => (IDictionaryTranslation) x.DeepClone()).ToList();
return clone;
}
}
}

View File

@@ -65,5 +65,12 @@ namespace Umbraco.Core.Models
}, _value, ValueSelector);
}
}
public override object DeepClone()
{
var clone = (DictionaryTranslation)base.DeepClone();
clone.Language = (ILanguage)Language.DeepClone();
return clone;
}
}
}

View File

@@ -107,5 +107,12 @@ namespace Umbraco.Core.Models
{
get { return _relationType.Id; }
}
public override object DeepClone()
{
var clone = (Relation)base.DeepClone();
clone.RelationType = (RelationType)RelationType.DeepClone();
return clone;
}
}
}

View File

@@ -118,5 +118,6 @@ namespace Umbraco.Core.Models
}, _childObjectType, ChildObjectTypeSelector);
}
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Globalization;
using System.Reflection;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence.Mappers;
@@ -34,7 +35,7 @@ namespace Umbraco.Core.Models
{
UpdateDate = updateDate;
CreateDate = createDate;
Key = Id.ToString().EncodeAsGuid();
Key = Id.ToString(CultureInfo.InvariantCulture).EncodeAsGuid();
Id = id;
ServerAddress = serverAddress;
ComputerName = computerName;
@@ -51,7 +52,7 @@ namespace Umbraco.Core.Models
{
CreateDate = createDate;
UpdateDate = createDate;
Key = 0.ToString().EncodeAsGuid();
Key = 0.ToString(CultureInfo.InvariantCulture).EncodeAsGuid();
ServerAddress = serverAddress;
ComputerName = computerName;
}

View File

@@ -132,5 +132,12 @@ namespace Umbraco.Core.Models
}, _comment, CommentSelector);
}
}
public override object DeepClone()
{
var clone = (Task) base.DeepClone();
clone.TaskType = (TaskType)TaskType.DeepClone();
return clone;
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Umbraco.Core.Models.EntityBase;
@@ -46,17 +47,20 @@ namespace Umbraco.Core.Models
public UmbracoEntity()
{
AdditionalData = new Dictionary<string, object>();
UmbracoProperties = new List<UmbracoProperty>();
}
public UmbracoEntity(bool trashed)
{
AdditionalData = new Dictionary<string, object>();
UmbracoProperties = new List<UmbracoProperty>();
Trashed = trashed;
}
public UmbracoEntity(int trashed)
{
AdditionalData = new Dictionary<string, object>();
UmbracoProperties = new List<UmbracoProperty>();
Trashed = trashed == 1;
}
@@ -287,10 +291,45 @@ namespace Umbraco.Core.Models
/// </summary>
public IList<UmbracoProperty> UmbracoProperties { get; set; }
internal class UmbracoProperty
public override object DeepClone()
{
var clone = (UmbracoEntity)base.DeepClone();
clone.UmbracoProperties = UmbracoProperties.Select(x => (UmbracoProperty) x.DeepClone()).ToList();
return clone;
}
internal class UmbracoProperty : IDeepCloneable
{
public Guid DataTypeControlId { get; set; }
public string Value { get; set; }
public object DeepClone()
{
//Memberwise clone on Entity will work since it doesn't have any deep elements
// for any sub class this will work for standard properties as well that aren't complex object's themselves.
var clone = MemberwiseClone();
return clone;
}
protected bool Equals(UmbracoProperty other)
{
return DataTypeControlId.Equals(other.DataTypeControlId) && string.Equals(Value, other.Value);
}
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((UmbracoProperty) obj);
}
public override int GetHashCode()
{
unchecked
{
return (DataTypeControlId.GetHashCode()*397) ^ (Value != null ? Value.GetHashCode() : 0);
}
}
}
}
}

View File

@@ -0,0 +1,253 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Tests.Models.Collections
{
public abstract class Item : IEntity, ICanBeDirty
{
private bool _hasIdentity;
private int? _hash;
private int _id;
private Guid _key;
protected Item()
{
_propertyChangedInfo = new Dictionary<string, bool>();
}
/// <summary>
/// Integer Id
/// </summary>
[DataMember]
public int Id
{
get
{
return _id;
}
set
{
_id = value;
HasIdentity = true;
}
}
/// <summary>
/// Guid based Id
/// </summary>
/// <remarks>The key is currectly used to store the Unique Id from the
/// umbracoNode table, which many of the entities are based on.</remarks>
[DataMember]
public Guid Key
{
get
{
if (_key == Guid.Empty)
return _id.ToGuid();
return _key;
}
set { _key = value; }
}
/// <summary>
/// Gets or sets the Created Date
/// </summary>
[DataMember]
public DateTime CreateDate { get; set; }
/// <summary>
/// Gets or sets the Modified Date
/// </summary>
[DataMember]
public DateTime UpdateDate { get; set; }
/// <summary>
/// Gets or sets the WasCancelled flag, which is used to track
/// whether some action against an entity was cancelled through some event.
/// This only exists so we have a way to check if an event was cancelled through
/// the new api, which also needs to take effect in the legacy api.
/// </summary>
[IgnoreDataMember]
internal bool WasCancelled { get; set; }
/// <summary>
/// Property changed event
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Method to call on a property setter.
/// </summary>
/// <param name="propertyInfo">The property info.</param>
protected virtual void OnPropertyChanged(PropertyInfo propertyInfo)
{
_propertyChangedInfo[propertyInfo.Name] = true;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyInfo.Name));
}
}
internal virtual void ResetIdentity()
{
_hasIdentity = false;
_id = default(int);
}
/// <summary>
/// Method to call on entity saved when first added
/// </summary>
internal virtual void AddingEntity()
{
CreateDate = DateTime.Now;
UpdateDate = DateTime.Now;
}
/// <summary>
/// Method to call on entity saved/updated
/// </summary>
internal virtual void UpdatingEntity()
{
UpdateDate = DateTime.Now;
}
/// <summary>
/// Tracks the properties that have changed
/// </summary>
//private readonly IDictionary<string, bool> _propertyChangedInfo = new Dictionary<string, bool>();
private IDictionary<string, bool> _propertyChangedInfo;
/// <summary>
/// Indicates whether a specific property on the current entity is dirty.
/// </summary>
/// <param name="propertyName">Name of the property to check</param>
/// <returns>True if Property is dirty, otherwise False</returns>
public virtual bool IsPropertyDirty(string propertyName)
{
return _propertyChangedInfo.Any(x => x.Key == propertyName);
}
/// <summary>
/// Indicates whether the current entity is dirty.
/// </summary>
/// <returns>True if entity is dirty, otherwise False</returns>
public virtual bool IsDirty()
{
return _propertyChangedInfo.Any();
}
/// <summary>
/// Resets dirty properties by clearing the dictionary used to track changes.
/// </summary>
/// <remarks>
/// Please note that resetting the dirty properties could potentially
/// obstruct the saving of a new or updated entity.
/// </remarks>
public virtual void ResetDirtyProperties()
{
_propertyChangedInfo.Clear();
}
/// <summary>
/// Indicates whether the current entity has an identity, eg. Id.
/// </summary>
public virtual bool HasIdentity
{
get
{
return _hasIdentity;
}
protected set
{
_hasIdentity = value;
}
}
public static bool operator ==(Item left, Item right)
{
/*if (ReferenceEquals(null, left))
return false;
if(ReferenceEquals(null, right))
return false;*/
return ReferenceEquals(left, right);
return left.Equals(right);
}
public static bool operator !=(Item left, Item right)
{
return !(left == right);
}
/*public virtual bool SameIdentityAs(IEntity other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return SameIdentityAs(other as Entity);
}
public virtual bool Equals(Entity other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return SameIdentityAs(other);
}
public virtual Type GetRealType()
{
return GetType();
}
public virtual bool SameIdentityAs(Entity other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
if (GetType() == other.GetRealType() && HasIdentity && other.HasIdentity)
return other.Id.Equals(Id);
return false;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
return false;
if (ReferenceEquals(this, obj))
return true;
return SameIdentityAs(obj as IEntity);
}
public override int GetHashCode()
{
if (!_hash.HasValue)
_hash = !HasIdentity ? new int?(base.GetHashCode()) : new int?(Id.GetHashCode() * 397 ^ GetType().GetHashCode());
return _hash.Value;
}*/
public object DeepClone()
{
return this.MemberwiseClone();
}
}
}

View File

@@ -0,0 +1,42 @@
using System;
namespace Umbraco.Tests.Models.Collections
{
public class OrderItem : Item
{
public readonly int PartNumber;
public readonly string Description;
public readonly double UnitPrice;
private int _quantity = 0;
public OrderItem(int partNumber, string description,
int quantity, double unitPrice)
{
this.PartNumber = partNumber;
this.Description = description;
this.Quantity = quantity;
this.UnitPrice = unitPrice;
}
public int Quantity
{
get { return _quantity; }
set
{
if (value < 0)
throw new ArgumentException("Quantity cannot be negative.");
_quantity = value;
}
}
public override string ToString()
{
return String.Format(
"{0,9} {1,6} {2,-12} at {3,8:#,###.00} = {4,10:###,###.00}",
PartNumber, _quantity, Description, UnitPrice,
UnitPrice * _quantity);
}
}
}

View File

@@ -1,15 +1,8 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Tests.TestHelpers.Entities;
namespace Umbraco.Tests.Models.Collections
@@ -71,358 +64,4 @@ namespace Umbraco.Tests.Models.Collections
Assert.That(contentType.PropertyGroups.Any(x => x.Name.InvariantEquals("Test")), Is.False);
}
}
public class SimpleOrder : KeyedCollection<int, OrderItem>, INotifyCollectionChanged
{
// The parameterless constructor of the base class creates a
// KeyedCollection with an internal dictionary. For this code
// example, no other constructors are exposed.
//
public SimpleOrder() : base() { }
public SimpleOrder(IEnumerable<OrderItem> properties)
{
Reset(properties);
}
// This is the only method that absolutely must be overridden,
// because without it the KeyedCollection cannot extract the
// keys from the items. The input parameter type is the
// second generic type argument, in this case OrderItem, and
// the return value type is the first generic type argument,
// in this case int.
//
protected override int GetKeyForItem(OrderItem item)
{
// In this example, the key is the part number.
return item.PartNumber;
}
internal void Reset(IEnumerable<OrderItem> properties)
{
Clear();
properties.ForEach(Add);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
protected override void SetItem(int index, OrderItem item)
{
base.SetItem(index, item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
}
protected override void RemoveItem(int index)
{
var removed = this[index];
base.RemoveItem(index);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removed));
}
protected override void InsertItem(int index, OrderItem item)
{
base.InsertItem(index, item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
protected override void ClearItems()
{
base.ClearItems();
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public new bool Contains(int partNumber)
{
return this.Any(x => x.PartNumber == partNumber);
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
{
if (CollectionChanged != null)
{
CollectionChanged(this, args);
}
}
}
public class OrderItem : Item
{
public readonly int PartNumber;
public readonly string Description;
public readonly double UnitPrice;
private int _quantity = 0;
public OrderItem(int partNumber, string description,
int quantity, double unitPrice)
{
this.PartNumber = partNumber;
this.Description = description;
this.Quantity = quantity;
this.UnitPrice = unitPrice;
}
public int Quantity
{
get { return _quantity; }
set
{
if (value < 0)
throw new ArgumentException("Quantity cannot be negative.");
_quantity = value;
}
}
public override string ToString()
{
return String.Format(
"{0,9} {1,6} {2,-12} at {3,8:#,###.00} = {4,10:###,###.00}",
PartNumber, _quantity, Description, UnitPrice,
UnitPrice * _quantity);
}
}
public abstract class Item : IEntity, ICanBeDirty
{
private bool _hasIdentity;
private int? _hash;
private int _id;
private Guid _key;
protected Item()
{
_propertyChangedInfo = new Dictionary<string, bool>();
}
/// <summary>
/// Integer Id
/// </summary>
[DataMember]
public int Id
{
get
{
return _id;
}
set
{
_id = value;
HasIdentity = true;
}
}
/// <summary>
/// Guid based Id
/// </summary>
/// <remarks>The key is currectly used to store the Unique Id from the
/// umbracoNode table, which many of the entities are based on.</remarks>
[DataMember]
public Guid Key
{
get
{
if (_key == Guid.Empty)
return _id.ToGuid();
return _key;
}
set { _key = value; }
}
/// <summary>
/// Gets or sets the Created Date
/// </summary>
[DataMember]
public DateTime CreateDate { get; set; }
/// <summary>
/// Gets or sets the Modified Date
/// </summary>
[DataMember]
public DateTime UpdateDate { get; set; }
/// <summary>
/// Gets or sets the WasCancelled flag, which is used to track
/// whether some action against an entity was cancelled through some event.
/// This only exists so we have a way to check if an event was cancelled through
/// the new api, which also needs to take effect in the legacy api.
/// </summary>
[IgnoreDataMember]
internal bool WasCancelled { get; set; }
/// <summary>
/// Property changed event
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Method to call on a property setter.
/// </summary>
/// <param name="propertyInfo">The property info.</param>
protected virtual void OnPropertyChanged(PropertyInfo propertyInfo)
{
_propertyChangedInfo[propertyInfo.Name] = true;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyInfo.Name));
}
}
internal virtual void ResetIdentity()
{
_hasIdentity = false;
_id = default(int);
}
/// <summary>
/// Method to call on entity saved when first added
/// </summary>
internal virtual void AddingEntity()
{
CreateDate = DateTime.Now;
UpdateDate = DateTime.Now;
}
/// <summary>
/// Method to call on entity saved/updated
/// </summary>
internal virtual void UpdatingEntity()
{
UpdateDate = DateTime.Now;
}
/// <summary>
/// Tracks the properties that have changed
/// </summary>
//private readonly IDictionary<string, bool> _propertyChangedInfo = new Dictionary<string, bool>();
private IDictionary<string, bool> _propertyChangedInfo;
/// <summary>
/// Indicates whether a specific property on the current entity is dirty.
/// </summary>
/// <param name="propertyName">Name of the property to check</param>
/// <returns>True if Property is dirty, otherwise False</returns>
public virtual bool IsPropertyDirty(string propertyName)
{
return _propertyChangedInfo.Any(x => x.Key == propertyName);
}
/// <summary>
/// Indicates whether the current entity is dirty.
/// </summary>
/// <returns>True if entity is dirty, otherwise False</returns>
public virtual bool IsDirty()
{
return _propertyChangedInfo.Any();
}
/// <summary>
/// Resets dirty properties by clearing the dictionary used to track changes.
/// </summary>
/// <remarks>
/// Please note that resetting the dirty properties could potentially
/// obstruct the saving of a new or updated entity.
/// </remarks>
public virtual void ResetDirtyProperties()
{
_propertyChangedInfo.Clear();
}
/// <summary>
/// Indicates whether the current entity has an identity, eg. Id.
/// </summary>
public virtual bool HasIdentity
{
get
{
return _hasIdentity;
}
protected set
{
_hasIdentity = value;
}
}
public static bool operator ==(Item left, Item right)
{
/*if (ReferenceEquals(null, left))
return false;
if(ReferenceEquals(null, right))
return false;*/
return ReferenceEquals(left, right);
return left.Equals(right);
}
public static bool operator !=(Item left, Item right)
{
return !(left == right);
}
/*public virtual bool SameIdentityAs(IEntity other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return SameIdentityAs(other as Entity);
}
public virtual bool Equals(Entity other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return SameIdentityAs(other);
}
public virtual Type GetRealType()
{
return GetType();
}
public virtual bool SameIdentityAs(Entity other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
if (GetType() == other.GetRealType() && HasIdentity && other.HasIdentity)
return other.Id.Equals(Id);
return false;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
return false;
if (ReferenceEquals(this, obj))
return true;
return SameIdentityAs(obj as IEntity);
}
public override int GetHashCode()
{
if (!_hash.HasValue)
_hash = !HasIdentity ? new int?(base.GetHashCode()) : new int?(Id.GetHashCode() * 397 ^ GetType().GetHashCode());
return _hash.Value;
}*/
public object DeepClone()
{
return this.MemberwiseClone();
}
}
}

View File

@@ -0,0 +1,82 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using Umbraco.Core;
namespace Umbraco.Tests.Models.Collections
{
public class SimpleOrder : KeyedCollection<int, OrderItem>, INotifyCollectionChanged
{
// The parameterless constructor of the base class creates a
// KeyedCollection with an internal dictionary. For this code
// example, no other constructors are exposed.
//
public SimpleOrder() : base() { }
public SimpleOrder(IEnumerable<OrderItem> properties)
{
Reset(properties);
}
// This is the only method that absolutely must be overridden,
// because without it the KeyedCollection cannot extract the
// keys from the items. The input parameter type is the
// second generic type argument, in this case OrderItem, and
// the return value type is the first generic type argument,
// in this case int.
//
protected override int GetKeyForItem(OrderItem item)
{
// In this example, the key is the part number.
return item.PartNumber;
}
internal void Reset(IEnumerable<OrderItem> properties)
{
Clear();
properties.ForEach(Add);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
protected override void SetItem(int index, OrderItem item)
{
base.SetItem(index, item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
}
protected override void RemoveItem(int index)
{
var removed = this[index];
base.RemoveItem(index);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, removed));
}
protected override void InsertItem(int index, OrderItem item)
{
base.InsertItem(index, item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
}
protected override void ClearItems()
{
base.ClearItems();
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public new bool Contains(int partNumber)
{
return this.Any(x => x.PartNumber == partNumber);
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
{
if (CollectionChanged != null)
{
CollectionChanged(this, args);
}
}
}
}

View File

@@ -10,6 +10,25 @@ namespace Umbraco.Tests.Models
[TestFixture]
public class ContentTypeTests
{
[Test]
public void Can_Deep_Clone_Content_Type_Sort()
{
var contentType = new ContentTypeSort(new Lazy<int>(() => 3), 4, "test");
var clone = (ContentTypeSort) contentType.DeepClone();
Assert.AreNotSame(clone, contentType);
Assert.AreEqual(clone, contentType);
Assert.AreEqual(clone.Id.Value, contentType.Id.Value);
Assert.AreEqual(clone.SortOrder, contentType.SortOrder);
Assert.AreEqual(clone.Alias, contentType.Alias);
//This double verifies by reflection
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(contentType, null));
}
}
[Test]
public void Can_Deep_Clone_Content_Type()
{

View File

@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Umbraco.Core.Models;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class DataTypeDefinitionTests
{
[Test]
public void Can_Deep_Clone()
{
var dtd = new DataTypeDefinition(9, Guid.NewGuid())
{
CreateDate = DateTime.Now,
CreatorId = 5,
DatabaseType = DataTypeDatabaseType.Nvarchar,
Id = 4,
Key = Guid.NewGuid(),
Level = 7,
Name = "Test",
ParentId = 9,
Path = "-1,2",
SortOrder = 8,
Trashed = true,
UpdateDate = DateTime.Now
};
var clone = (DataTypeDefinition) dtd.DeepClone();
Assert.AreNotSame(clone, dtd);
Assert.AreEqual(clone, dtd);
Assert.AreEqual(clone.CreateDate, dtd.CreateDate);
Assert.AreEqual(clone.CreatorId, dtd.CreatorId);
Assert.AreEqual(clone.DatabaseType, dtd.DatabaseType);
Assert.AreEqual(clone.Id, dtd.Id);
Assert.AreEqual(clone.Key, dtd.Key);
Assert.AreEqual(clone.Level, dtd.Level);
Assert.AreEqual(clone.Name, dtd.Name);
Assert.AreEqual(clone.ParentId, dtd.ParentId);
Assert.AreEqual(clone.Path, dtd.Path);
Assert.AreEqual(clone.SortOrder, dtd.SortOrder);
Assert.AreEqual(clone.Trashed, dtd.Trashed);
Assert.AreEqual(clone.UpdateDate, dtd.UpdateDate);
//This double verifies by reflection
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(dtd, null));
}
}
}
}

View File

@@ -0,0 +1,82 @@
using System;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core.Models;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class DictionaryItemTests
{
[Test]
public void Can_Deep_Clone()
{
var item = new DictionaryItem("blah")
{
CreateDate = DateTime.Now,
Id = 8,
ItemKey = "blah",
Key = Guid.NewGuid(),
ParentId = Guid.NewGuid(),
UpdateDate = DateTime.Now,
Translations = new[]
{
new DictionaryTranslation(new Language("en-AU")
{
CreateDate = DateTime.Now,
CultureName = "en",
Id = 11,
IsoCode = "AU",
Key = Guid.NewGuid(),
UpdateDate = DateTime.Now
}, "colour")
{
CreateDate = DateTime.Now,
Id = 88,
Key = Guid.NewGuid(),
UpdateDate = DateTime.Now
},
new DictionaryTranslation(new Language("en-US")
{
CreateDate = DateTime.Now,
CultureName = "en",
Id = 12,
IsoCode = "US",
Key = Guid.NewGuid(),
UpdateDate = DateTime.Now
}, "color")
{
CreateDate = DateTime.Now,
Id = 89,
Key = Guid.NewGuid(),
UpdateDate = DateTime.Now
},
}
};
var clone = (DictionaryItem)item.DeepClone();
Assert.AreNotSame(clone, item);
Assert.AreEqual(clone, item);
Assert.AreEqual(clone.CreateDate, item.CreateDate);
Assert.AreEqual(clone.Id, item.Id);
Assert.AreEqual(clone.ItemKey, item.ItemKey);
Assert.AreEqual(clone.Key, item.Key);
Assert.AreEqual(clone.ParentId, item.ParentId);
Assert.AreEqual(clone.UpdateDate, item.UpdateDate);
Assert.AreEqual(clone.Translations.Count(), item.Translations.Count());
for (var i = 0; i < item.Translations.Count(); i++)
{
Assert.AreNotSame(clone.Translations.ElementAt(i), item.Translations.ElementAt(i));
Assert.AreEqual(clone.Translations.ElementAt(i), item.Translations.ElementAt(i));
}
//This double verifies by reflection
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null));
}
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using NUnit.Framework;
using Umbraco.Core.Models;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class DictionaryTranslationTests
{
[Test]
public void Can_Deep_Clone()
{
var item = new DictionaryTranslation(new Language("en-AU")
{
CreateDate = DateTime.Now,
CultureName = "en",
Id = 11,
IsoCode = "AU",
Key = Guid.NewGuid(),
UpdateDate = DateTime.Now
}, "colour")
{
CreateDate = DateTime.Now,
Id = 88,
Key = Guid.NewGuid(),
UpdateDate = DateTime.Now
};
var clone = (DictionaryTranslation) item.DeepClone();
Assert.AreNotSame(clone, item);
Assert.AreEqual(clone, item);
Assert.AreEqual(clone.CreateDate, item.CreateDate);
Assert.AreEqual(clone.Id, item.Id);
Assert.AreEqual(clone.Key, item.Key);
Assert.AreEqual(clone.UpdateDate, item.UpdateDate);
Assert.AreNotSame(clone.Language, item.Language);
Assert.AreEqual(clone.Language, item.Language);
Assert.AreEqual(clone.Value, item.Value);
//This double verifies by reflection
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null));
}
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using NUnit.Framework;
using Umbraco.Core.Models;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class LanguageTests
{
[Test]
public void Can_Deep_Clone()
{
var item = new Language("en-AU")
{
CreateDate = DateTime.Now,
CultureName = "en",
Id = 11,
IsoCode = "AU",
Key = Guid.NewGuid(),
UpdateDate = DateTime.Now
};
var clone = (Language) item.DeepClone();
Assert.AreNotSame(clone, item);
Assert.AreEqual(clone, item);
Assert.AreEqual(clone.CreateDate, item.CreateDate);
Assert.AreEqual(clone.CultureName, item.CultureName);
Assert.AreEqual(clone.Id, item.Id);
Assert.AreEqual(clone.IsoCode, item.IsoCode);
Assert.AreEqual(clone.Key, item.Key);
Assert.AreEqual(clone.UpdateDate, item.UpdateDate);
//This double verifies by reflection
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null));
}
}
}
}

View File

@@ -0,0 +1,48 @@
using System;
using NUnit.Framework;
using Umbraco.Core.Models;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class RelationTests
{
[Test]
public void Can_Deep_Clone()
{
var item = new Relation(9, 8, new RelationType(Guid.NewGuid(), Guid.NewGuid(), "test")
{
Id = 66
})
{
Comment = "test comment",
CreateDate = DateTime.Now,
Id = 4,
Key = Guid.NewGuid(),
UpdateDate = DateTime.Now
};
var clone = (Relation) item.DeepClone();
Assert.AreNotSame(clone, item);
Assert.AreEqual(clone, item);
Assert.AreEqual(clone.ChildId, item.ChildId);
Assert.AreEqual(clone.Comment, item.Comment);
Assert.AreEqual(clone.CreateDate, item.CreateDate);
Assert.AreEqual(clone.Id, item.Id);
Assert.AreEqual(clone.Key, item.Key);
Assert.AreEqual(clone.ParentId, item.ParentId);
Assert.AreNotSame(clone.RelationType, item.RelationType);
Assert.AreEqual(clone.RelationType, item.RelationType);
Assert.AreEqual(clone.RelationTypeId, item.RelationTypeId);
Assert.AreEqual(clone.UpdateDate, item.UpdateDate);
//This double verifies by reflection
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null));
}
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using NUnit.Framework;
using Umbraco.Core.Models;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class RelationTypeTests
{
[Test]
public void Can_Deep_Clone()
{
var item = new RelationType(Guid.NewGuid(), Guid.NewGuid(), "test")
{
Id = 66,
CreateDate = DateTime.Now,
IsBidirectional = true,
Key = Guid.NewGuid(),
Name = "Test",
UpdateDate = DateTime.Now
};
var clone = (RelationType)item.DeepClone();
Assert.AreNotSame(clone, item);
Assert.AreEqual(clone, item);
Assert.AreEqual(clone.Alias, item.Alias);
Assert.AreEqual(clone.ChildObjectType, item.ChildObjectType);
Assert.AreEqual(clone.IsBidirectional, item.IsBidirectional);
Assert.AreEqual(clone.Id, item.Id);
Assert.AreEqual(clone.Key, item.Key);
Assert.AreEqual(clone.Name, item.Name);
Assert.AreNotSame(clone.ParentObjectType, item.ParentObjectType);
Assert.AreEqual(clone.UpdateDate, item.UpdateDate);
//This double verifies by reflection
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null));
}
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using NUnit.Framework;
using Umbraco.Core.Models;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class TaskTests
{
[Test]
public void Can_Deep_Clone()
{
var item = new Task(new TaskType("test") {Id = 3})
{
AssigneeUserId = 4,
Closed = true,
Comment = "blah",
CreateDate = DateTime.Now,
EntityId = 99,
Id = 2,
Key = Guid.NewGuid(),
OwnerUserId = 89,
TaskType = new TaskType("asdf") {Id = 99},
UpdateDate = DateTime.Now
};
var clone = (Task) item.DeepClone();
Assert.AreNotSame(clone, item);
Assert.AreEqual(clone, item);
Assert.AreEqual(clone.CreateDate, item.CreateDate);
Assert.AreEqual(clone.UpdateDate, item.UpdateDate);
Assert.AreEqual(clone.AssigneeUserId, item.AssigneeUserId);
Assert.AreEqual(clone.Closed, item.Closed);
Assert.AreEqual(clone.Comment, item.Comment);
Assert.AreEqual(clone.EntityId, item.EntityId);
Assert.AreEqual(clone.Id, item.Id);
Assert.AreEqual(clone.Key, item.Key);
Assert.AreEqual(clone.OwnerUserId, item.OwnerUserId);
Assert.AreNotSame(clone.TaskType, item.TaskType);
Assert.AreEqual(clone.TaskType, item.TaskType);
//This double verifies by reflection
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null));
}
}
}
}

View File

@@ -0,0 +1,42 @@
using System;
using NUnit.Framework;
using Umbraco.Core.Models;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class TaskTypeTests
{
[Test]
public void Can_Deep_Clone()
{
var item = new TaskType("test")
{
Id = 3,
Alias = "test",
CreateDate = DateTime.Now,
Key = Guid.NewGuid(),
UpdateDate = DateTime.Now
};
var clone = (TaskType)item.DeepClone();
Assert.AreNotSame(clone, item);
Assert.AreEqual(clone, item);
Assert.AreEqual(clone.CreateDate, item.CreateDate);
Assert.AreEqual(clone.Id, item.Id);
Assert.AreEqual(clone.Key, item.Key);
Assert.AreEqual(clone.Alias, item.Alias);
Assert.AreEqual(clone.UpdateDate, item.UpdateDate);
//This double verifies by reflection
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null));
}
}
}
}

View File

@@ -0,0 +1,54 @@
using System;
using NUnit.Framework;
using Umbraco.Core.Models;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class TemplateTests
{
[Test]
public void Can_Deep_Clone()
{
var item = new Template("-1,2,3", "Test", "test")
{
Id = 3,
CreateDate = DateTime.Now,
Key = Guid.NewGuid(),
UpdateDate = DateTime.Now,
Content = "blah",
CreatorId = 66,
Level = 55,
ParentId = 2,
SortOrder = 99,
MasterTemplateAlias = "master",
MasterTemplateId = new Lazy<int>(() => 88)
};
var clone = (Template)item.DeepClone();
Assert.AreNotSame(clone, item);
Assert.AreEqual(clone, item);
Assert.AreEqual(clone.CreateDate, item.CreateDate);
Assert.AreEqual(clone.Alias, item.Alias);
Assert.AreEqual(clone.CreatorId, item.CreatorId);
Assert.AreEqual(clone.Id, item.Id);
Assert.AreEqual(clone.Key, item.Key);
Assert.AreEqual(clone.Level, item.Level);
Assert.AreEqual(clone.MasterTemplateAlias, item.MasterTemplateAlias);
Assert.AreEqual(clone.MasterTemplateId.Value, item.MasterTemplateId.Value);
Assert.AreEqual(clone.Name, item.Name);
Assert.AreEqual(clone.ParentId, item.ParentId);
Assert.AreEqual(clone.SortOrder, item.SortOrder);
Assert.AreEqual(clone.UpdateDate, item.UpdateDate);
//This double verifies by reflection
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null));
}
}
}
}

View File

@@ -1,4 +1,5 @@
using NUnit.Framework;
using System;
using NUnit.Framework;
using Umbraco.Core.Models;
namespace Umbraco.Tests.Models
@@ -18,5 +19,81 @@ namespace Umbraco.Tests.Models
Assert.IsTrue(trashedWithBool.Trashed);
Assert.IsTrue(trashedWithInt.Trashed);
}
[Test]
public void Can_Deep_Clone()
{
var item = new UmbracoEntity()
{
Id = 3,
ContentTypeAlias = "test1",
CreatorId = 4,
Key = Guid.NewGuid(),
UpdateDate = DateTime.Now,
CreateDate = DateTime.Now,
Name = "Test",
ParentId = 5,
SortOrder = 6,
Path = "-1,23",
Level = 7,
ContentTypeIcon = "icon",
ContentTypeThumbnail = "thumb",
HasChildren = true,
HasPendingChanges = true,
IsDraft = true,
IsPublished = true,
NodeObjectTypeId = Guid.NewGuid()
};
item.AdditionalData.Add("test1", 3);
item.AdditionalData.Add("test2", "valuie");
item.UmbracoProperties.Add(new UmbracoEntity.UmbracoProperty()
{
Value = "test",
DataTypeControlId = Guid.NewGuid()
});
item.UmbracoProperties.Add(new UmbracoEntity.UmbracoProperty()
{
Value = "test2",
DataTypeControlId = Guid.NewGuid()
});
var clone = (UmbracoEntity)item.DeepClone();
Assert.AreNotSame(clone, item);
Assert.AreEqual(clone, item);
Assert.AreEqual(clone.CreateDate, item.CreateDate);
Assert.AreEqual(clone.ContentTypeAlias, item.ContentTypeAlias);
Assert.AreEqual(clone.CreatorId, item.CreatorId);
Assert.AreEqual(clone.Id, item.Id);
Assert.AreEqual(clone.Key, item.Key);
Assert.AreEqual(clone.Level, item.Level);
Assert.AreEqual(clone.Name, item.Name);
Assert.AreEqual(clone.ParentId, item.ParentId);
Assert.AreEqual(clone.SortOrder, item.SortOrder);
Assert.AreEqual(clone.Path, item.Path);
Assert.AreEqual(clone.ContentTypeIcon, item.ContentTypeIcon);
Assert.AreEqual(clone.ContentTypeThumbnail, item.ContentTypeThumbnail);
Assert.AreEqual(clone.HasChildren, item.HasChildren);
Assert.AreEqual(clone.HasPendingChanges, item.HasPendingChanges);
Assert.AreEqual(clone.IsDraft, item.IsDraft);
Assert.AreEqual(clone.IsPublished, item.IsPublished);
Assert.AreEqual(clone.NodeObjectTypeId, item.NodeObjectTypeId);
Assert.AreEqual(clone.UpdateDate, item.UpdateDate);
Assert.AreEqual(clone.AdditionalData.Count, item.AdditionalData.Count);
Assert.AreEqual(clone.AdditionalData, item.AdditionalData);
Assert.AreEqual(clone.UmbracoProperties.Count, item.UmbracoProperties.Count);
for (var i = 0; i < clone.UmbracoProperties.Count; i++)
{
Assert.AreNotSame(clone.UmbracoProperties[i], item.UmbracoProperties[i]);
Assert.AreEqual(clone.UmbracoProperties[i], item.UmbracoProperties[i]);
}
//This double verifies by reflection
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null));
}
}
}
}

View File

@@ -157,9 +157,21 @@
<Compile Include="Membership\MembershipProviderBaseTests.cs" />
<Compile Include="Membership\UmbracoServiceMembershipProviderTests.cs" />
<Compile Include="MockTests.cs" />
<Compile Include="Models\Collections\Item.cs" />
<Compile Include="Models\Collections\OrderItem.cs" />
<Compile Include="Models\Collections\SimpleOrder.cs" />
<Compile Include="Models\ContentTypeTests.cs" />
<Compile Include="Models\DataTypeDefinitionTests.cs" />
<Compile Include="Models\DictionaryItemTests.cs" />
<Compile Include="Models\DictionaryTranslationTests.cs" />
<Compile Include="Models\LanguageTests.cs" />
<Compile Include="Models\PropertyGroupTests.cs" />
<Compile Include="Models\PropertyTypeTests.cs" />
<Compile Include="Models\RelationTests.cs" />
<Compile Include="Models\RelationTypeTests.cs" />
<Compile Include="Models\TaskTests.cs" />
<Compile Include="Models\TaskTypeTests.cs" />
<Compile Include="Models\TemplateTests.cs" />
<Compile Include="Models\UmbracoEntityTests.cs" />
<Compile Include="Mvc\UmbracoViewPageTests.cs" />
<Compile Include="Persistence\Auditing\AuditTests.cs" />