Skip to content

Commit cf27034

Browse files
committed
nuget preparation, generics tests, cloneextension lib tests (to compare correctness and performance)
1 parent db6886c commit cf27034

File tree

12 files changed

+256
-10
lines changed

12 files changed

+256
-10
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ bin
22
obj
33
*.user
44
*.suo
5-
packages
5+
packages
6+
.tools
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
using CloneExtensions;
2+
3+
using NUnit.Framework;
4+
5+
namespace Force.DeepCloner.Tests
6+
{
7+
[TestFixture]
8+
public class CloneExtensionsSpec
9+
{
10+
public class C1
11+
{
12+
public int X { get; set; }
13+
}
14+
15+
public class C2 : C1
16+
{
17+
public new int X { get; set; }
18+
}
19+
20+
public class C3 : C1
21+
{
22+
public int Y { get; set; }
23+
}
24+
25+
public class C4
26+
{
27+
public C1 A { get; set; }
28+
29+
public C1 B { get; set; }
30+
}
31+
32+
public struct S5
33+
{
34+
public C1 A { get; set; }
35+
36+
public C1 B { get; set; }
37+
}
38+
39+
public class C6
40+
{
41+
public C6 A { get; set; }
42+
}
43+
44+
[Test, Ignore("Not works")]
45+
public void Ensure_Parent_Prop_Clone()
46+
{
47+
var c2 = new C2();
48+
var c1 = c2 as C1;
49+
c2.X = 2;
50+
c1.X = 1;
51+
var c2Clone = c2.GetClone();
52+
Assert.That(c2Clone.X, Is.EqualTo(1));
53+
Assert.That((c2Clone as C1).X, Is.EqualTo(1));
54+
}
55+
56+
[Test]
57+
public void Ensure_Parent_Prop_Clone2()
58+
{
59+
var c3 = new C3();
60+
c3.Y = 2;
61+
c3.X = 1;
62+
var c3Clone = c3.GetClone();
63+
Assert.That(c3Clone.Y, Is.EqualTo(2));
64+
Assert.That(c3Clone.X, Is.EqualTo(1));
65+
}
66+
67+
[Test, Ignore("Not works")]
68+
public void Ensure_Cast_To_Parent_Clone()
69+
{
70+
var c3 = new C3();
71+
var c1 = c3 as C1;
72+
c1.X = 1;
73+
c3.Y = 2;
74+
var c1Clone = c1.GetClone();
75+
Assert.That(c1Clone.X, Is.EqualTo(1));
76+
Assert.That((c1Clone as C3).Y, Is.EqualTo(2));
77+
}
78+
79+
[Test]
80+
public void Class_Should_Be_Deep_Copied()
81+
{
82+
var c4 = new C4();
83+
var c1 = new C1 { X = 1 };
84+
c4.A = c1;
85+
c4.B = c1;
86+
var c4Clone = c4.GetClone();
87+
c1.X = 2;
88+
Assert.That(c4Clone.A.X, Is.EqualTo(1));
89+
Assert.That(c4Clone.B.X, Is.EqualTo(1));
90+
Assert.That(c4Clone.A, Is.EqualTo(c4Clone.B));
91+
}
92+
93+
[Test]
94+
public void Struct_Should_Be_Deep_Copied()
95+
{
96+
var s5 = new S5();
97+
var c1 = new C1 { X = 1 };
98+
s5.A = c1;
99+
s5.B = c1;
100+
var c4Clone = s5.GetClone();
101+
c1.X = 2;
102+
Assert.That(c4Clone.A.X, Is.EqualTo(1));
103+
Assert.That(c4Clone.B.X, Is.EqualTo(1));
104+
Assert.That(c4Clone.A, Is.EqualTo(c4Clone.B));
105+
}
106+
107+
[Test]
108+
public void Array_Should_Be_Deep_Copied()
109+
{
110+
var c1 = new C1 { X = 1 };
111+
var a = new[] { c1, c1 };
112+
113+
var aClone = a.GetClone();
114+
Assert.That(aClone[0].X, Is.EqualTo(1));
115+
Assert.That(aClone[1].X, Is.EqualTo(1));
116+
Assert.That(aClone[0], Is.EqualTo(aClone[1]));
117+
}
118+
119+
[Test]
120+
public void CrossRef_Should_be_Cloned()
121+
{
122+
var c = new C6();
123+
c.A = c;
124+
125+
var aClone = c.GetClone();
126+
Assert.That(aClone.A, Is.EqualTo(aClone));
127+
Assert.That(aClone.A, Is.Not.EqualTo(c));
128+
}
129+
130+
[Test, Ignore("Should manually declare constructor")]
131+
public void AnonymousType_Should_be_Cloned()
132+
{
133+
var c = new { X = 1 }.GetClone();
134+
Assert.That(c.X, Is.EqualTo(1));
135+
}
136+
}
137+
}

DeepCloner.Tests/DeepCloner.Tests.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
3434
</PropertyGroup>
3535
<ItemGroup>
36+
<Reference Include="CloneExtensions">
37+
<HintPath>..\packages\CloneExtensions.1.2\lib\portable-net40+sl50+win+wp80\CloneExtensions.dll</HintPath>
38+
</Reference>
3639
<Reference Include="nunit.framework">
3740
<HintPath>..\packages\NUnit.3.0.1\lib\net40\nunit.framework.dll</HintPath>
3841
</Reference>
@@ -46,7 +49,9 @@
4649
</ItemGroup>
4750
<ItemGroup>
4851
<Compile Include="ArraysSpec.cs" />
52+
<Compile Include="CloneExtensionsSpec.cs" />
4953
<Compile Include="ConstructorsSpec.cs" />
54+
<Compile Include="GenericsSpec.cs" />
5055
<Compile Include="InheritanceSpec.cs" />
5156
<Compile Include="LoopCheckSpec.cs" />
5257
<Compile Include="Objects\DoableStruct1.cs" />

DeepCloner.Tests/GenericsSpec.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
3+
using NUnit.Framework;
4+
5+
namespace Force.DeepCloner.Tests
6+
{
7+
[TestFixture]
8+
public class GenericsSpec
9+
{
10+
[Test]
11+
public void Tuple_Should_Be_Cloned()
12+
{
13+
var c = new Tuple<int, int>(1, 2).DeepClone();
14+
Assert.That(c.Item1, Is.EqualTo(1));
15+
Assert.That(c.Item2, Is.EqualTo(2));
16+
17+
c = new Tuple<int, int>(1, 2).ShallowClone();
18+
Assert.That(c.Item1, Is.EqualTo(1));
19+
Assert.That(c.Item2, Is.EqualTo(2));
20+
}
21+
22+
public class C1
23+
{
24+
public int X { get; set; }
25+
}
26+
27+
public class C2 : C1
28+
{
29+
public int Y { get; set; }
30+
}
31+
32+
[Test]
33+
public void Tuple_Should_Be_Cloned_With_Inheritance_And_Same_Object()
34+
{
35+
var c2 = new C2 { X = 1, Y = 2 };
36+
var c = new Tuple<C1, C2>(c2, c2).DeepClone();
37+
var cs = new Tuple<C1, C2>(c2, c2).ShallowClone();
38+
c2.X = 42;
39+
c2.Y = 42;
40+
Assert.That(c.Item1.X, Is.EqualTo(1));
41+
Assert.That(c.Item2.Y, Is.EqualTo(2));
42+
Assert.That(c.Item2, Is.EqualTo(c.Item1));
43+
44+
Assert.That(cs.Item1.X, Is.EqualTo(42));
45+
Assert.That(cs.Item2.Y, Is.EqualTo(42));
46+
Assert.That(cs.Item2, Is.EqualTo(cs.Item1));
47+
}
48+
}
49+
}

DeepCloner.Tests/PerformanceSpec.cs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using System.IO;
44
using System.Runtime.Serialization.Formatters.Binary;
55

6+
using CloneExtensions;
7+
68
using NUnit.Framework;
79

810
namespace Force.DeepCloner.Tests
@@ -29,7 +31,16 @@ private class C2 : C1
2931
{
3032
}
3133

32-
private C1 ManualClone(C1 x)
34+
private C1 ManualDeepClone(C1 x)
35+
{
36+
var y = new C1();
37+
y.V1 = x.V1;
38+
y.V2 = x.V2;
39+
y.O = new object();
40+
return y;
41+
}
42+
43+
private C1 ManualShallowClone(C1 x)
3344
{
3445
var y = new C1();
3546
y.V1 = x.V1;
@@ -52,22 +63,27 @@ public void Test_Construct_Variants()
5263
{
5364
var c1 = new C1 { V1 = 1 };
5465
// warm up
55-
for (var i = 0; i < 1000; i++) ManualClone(c1);
66+
for (var i = 0; i < 1000; i++) ManualDeepClone(c1);
67+
for (var i = 0; i < 1000; i++) c1.GetClone();
5668
for (var i = 0; i < 1000; i++) c1.DeepClone();
5769
for (var i = 0; i < 1000; i++) CloneViaFormatter(c1);
5870

5971
// test
6072
var sw = new Stopwatch();
6173
sw.Start();
6274

63-
for (var i = 0; i < 1000000; i++) ManualClone(c1);
75+
for (var i = 0; i < 1000000; i++) ManualDeepClone(c1);
6476
Console.WriteLine("Manual: " + sw.ElapsedMilliseconds);
6577
sw.Restart();
6678

6779
for (var i = 0; i < 1000000; i++) c1.DeepClone();
6880
Console.WriteLine("Deep: " + sw.ElapsedMilliseconds);
6981
sw.Restart();
7082

83+
for (var i = 0; i < 1000000; i++) c1.GetClone();
84+
Console.WriteLine("Clone Extensions: " + sw.ElapsedMilliseconds);
85+
sw.Restart();
86+
7187
// inaccurate variant, but test should complete in reasonable time
7288
for (var i = 0; i < 100000; i++) CloneViaFormatter(c1);
7389
Console.WriteLine("Binary Formatter: " + (sw.ElapsedMilliseconds * 10));
@@ -119,15 +135,16 @@ public void Test_Shallow_Variants()
119135
{
120136
var c1 = new C1();
121137
// warm up
122-
for (var i = 0; i < 1000; i++) ManualClone(c1);
138+
for (var i = 0; i < 1000; i++) ManualShallowClone(c1);
123139
for (var i = 0; i < 1000; i++) c1.Clone();
124140
for (var i = 0; i < 1000; i++) c1.ShallowClone();
141+
for (var i = 0; i < 1000; i++) c1.GetClone();
125142

126143
// test
127144
var sw = new Stopwatch();
128145
sw.Start();
129146

130-
for (var i = 0; i < 1000000; i++) ManualClone(c1);
147+
for (var i = 0; i < 1000000; i++) ManualShallowClone(c1);
131148
Console.WriteLine("Manual External: " + sw.ElapsedMilliseconds);
132149
sw.Restart();
133150

@@ -137,6 +154,11 @@ public void Test_Shallow_Variants()
137154

138155
for (var i = 0; i < 1000000; i++) c1.ShallowClone();
139156
Console.WriteLine("Shallow: " + sw.ElapsedMilliseconds);
157+
sw.Restart();
158+
159+
for (var i = 0; i < 1000000; i++) c1.GetClone(CloningFlags.Shallow);
160+
Console.WriteLine("Clone Extensions: " + sw.ElapsedMilliseconds);
161+
sw.Restart();
140162
}
141163
}
142164
}

DeepCloner.Tests/packages.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
3+
<package id="CloneExtensions" version="1.2" targetFramework="net40" />
34
<package id="NUnit" version="3.0.1" targetFramework="net40" />
45
</packages>

DeepCloner.nuspec

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0"?>
2+
<package >
3+
<metadata>
4+
<id>DeepCloner</id>
5+
<title>DeepCloner</title>
6+
<version>0.8.0</version>
7+
<authors>force</authors>
8+
<owners>force</owners>
9+
<licenseUrl>https://github.com/force-net/DeepCloner/blob/develop/LICENSE</licenseUrl>
10+
<projectUrl>https://github.com/force-net/DeepCloner</projectUrl>
11+
<!--iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl-->
12+
<requireLicenseAcceptance>false</requireLicenseAcceptance>
13+
<description>Small Library for deep cloning .NET objects</description>
14+
<releaseNotes>Initial Public Release.</releaseNotes>
15+
<copyright>Copyright by Force 2016</copyright>
16+
<tags>.NET shallow deep clone</tags>
17+
</metadata>
18+
<files><file src="DeepCloner\bin\Release\DeepCloner.*" target="lib\net40" /></files>
19+
</package>

DeepCloner/DeepCloner.csproj

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,23 @@
2222
<WarningLevel>4</WarningLevel>
2323
</PropertyGroup>
2424
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
25-
<DebugType>pdbonly</DebugType>
25+
<DebugType>none</DebugType>
2626
<Optimize>true</Optimize>
2727
<OutputPath>bin\Release\</OutputPath>
2828
<DefineConstants>TRACE</DefineConstants>
2929
<ErrorReport>prompt</ErrorReport>
3030
<WarningLevel>4</WarningLevel>
31+
<DocumentationFile>bin\Release\DeepCloner.xml</DocumentationFile>
3132
</PropertyGroup>
3233
<PropertyGroup>
3334
<SignAssembly>true</SignAssembly>
3435
</PropertyGroup>
3536
<PropertyGroup>
3637
<DelaySign>true</DelaySign>
3738
</PropertyGroup>
39+
<PropertyGroup>
40+
<AssemblyOriginatorKeyFile>..\public.snk</AssemblyOriginatorKeyFile>
41+
</PropertyGroup>
3842
<ItemGroup>
3943
<Reference Include="System" />
4044
<Reference Include="System.Core" />
@@ -56,6 +60,11 @@
5660
<Compile Include="Helpers\TypeCreationHelper.cs" />
5761
<Compile Include="Properties\AssemblyInfo.cs" />
5862
</ItemGroup>
63+
<ItemGroup>
64+
<None Include="..\public.snk">
65+
<Link>public.snk</Link>
66+
</None>
67+
</ItemGroup>
5968
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
6069
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
6170
Other similar extension points exist, see Microsoft.Common.targets.

DeepCloner/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@
3131
// You can specify all the values or you can default the Build and Revision Numbers
3232
// by using the '*' as shown below:
3333
// [assembly: AssemblyVersion("1.0.*")]
34-
[assembly: AssemblyVersion("0.0.1.0")]
35-
[assembly: AssemblyFileVersion("0.0.1.0")]
34+
[assembly: AssemblyVersion("0.8.0.0")]
35+
[assembly: AssemblyFileVersion("0.8.0.0")]

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
# DeepCloner
1+
# DeepCloner
2+
3+
In progress...

0 commit comments

Comments
 (0)