From 608966e4cb44172c983f0676796e09714ce5e014 Mon Sep 17 00:00:00 2001 From: Hugh Bellamy Date: Fri, 12 Apr 2019 23:19:34 +0100 Subject: [PATCH 1/2] Fix ToolboxItem bugs --- .../src/System/Drawing/Design/ToolboxItem.cs | 58 ++++++++----------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxItem.cs b/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxItem.cs index 7583e8f57ab..65fcde013dc 100644 --- a/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxItem.cs +++ b/src/System.Windows.Forms.Design/src/System/Drawing/Design/ToolboxItem.cs @@ -101,7 +101,7 @@ public AssemblyName[] DependentAssemblies } set { - Properties["DependentAssemblies"] = value.Clone(); + Properties["DependentAssemblies"] = value?.Clone(); } } @@ -277,23 +277,15 @@ public string TypeName } /// - /// Gets the version for this toolboxitem. It defaults to AssemblyName.Version unless - /// overridden in a derived toolboxitem. This can be overridden to return an empty string - /// to suppress its display in the toolbox tooltip. + /// Gets the version for this toolboxitem. It defaults to AssemblyName.Version unless + /// overridden in a derived toolboxitem. This can be overridden to + /// return an empty string to suppress its display in the toolbox tooltip. /// public virtual string Version { - get - { - if (AssemblyName != null) - { - return AssemblyName.Version.ToString(); - } - return string.Empty; - } + get => AssemblyName?.Version?.ToString() ?? string.Empty; } - /// /// Occurs when components are created. /// @@ -408,7 +400,7 @@ protected virtual IComponent[] CreateComponentsCore(IDesignerHost host, IDiction { IComponent[] components = CreateComponentsCore(host); - if (host != null) + if (host != null && components != null) { for (int i = 0; i < components.Length; i++) { @@ -527,10 +519,9 @@ private static bool AreAssemblyNamesEqual(AssemblyName name1, AssemblyName name2 public override int GetHashCode() { - string typeName = TypeName; - int hash = (typeName != null) ? typeName.GetHashCode() : 0; - - return unchecked(hash ^ DisplayName.GetHashCode()); + int typeHash = TypeName?.GetHashCode() ?? 0; + int displayHash = DisplayName?.GetHashCode() ?? 0; + return unchecked(typeHash ^ displayHash); } /// @@ -542,8 +533,8 @@ protected virtual object FilterPropertyValue(string propertyName, object value) switch (propertyName) { case "AssemblyName": - if (value != null) - value = ((AssemblyName)value).Clone(); + if (value is AssemblyName valueName) + value = valueName.Clone(); break; @@ -598,7 +589,7 @@ protected virtual Type GetType(IDesignerHost host, AssemblyName assemblyName, st if (host != null) { - ts = (ITypeResolutionService)host.GetService(typeof(ITypeResolutionService)); + ts = host.GetService(typeof(ITypeResolutionService)) as ITypeResolutionService; } if (ts != null) @@ -664,7 +655,7 @@ protected virtual Type GetType(IDesignerHost host, AssemblyName assemblyName, st { } - if (a == null && assemblyName.CodeBase != null && assemblyName.CodeBase.Length > 0) + if (a == null && !string.IsNullOrEmpty(assemblyName.CodeBase)) { try { @@ -804,7 +795,8 @@ public virtual void Initialize(Type type) private AssemblyName GetNonRetargetedAssemblyName(Type type, AssemblyName policiedAssemblyName) { - if (type == null || policiedAssemblyName == null) + Debug.Assert(type != null); + if (policiedAssemblyName == null) return null; //if looking for myself, just return it. (not a reference) @@ -833,17 +825,17 @@ private AssemblyName GetNonRetargetedAssemblyName(Type type, AssemblyName polici // in assemblyname. foreach (AssemblyName name in type.Assembly.GetReferencedAssemblies()) { - Assembly a = null; - try { - a = Assembly.Load(name); - if (a != null && a.FullName == policiedAssemblyName.FullName) + Assembly a = Assembly.Load(name); + if (a.FullName == policiedAssemblyName.FullName) + { return name; + } } catch { - //ignore all exceptions and just fall through if it fails (it shouldn't, but who knows). + // Ignore all exceptions and just fall through if it fails (it shouldn't, but who knows). } } @@ -900,10 +892,7 @@ protected virtual void OnComponentsCreating(ToolboxComponentsCreatingEventArgs a _componentsCreatingEvent?.Invoke(this, args); } - public override string ToString() - { - return DisplayName; - } + public override string ToString() => DisplayName ?? string.Empty; /// /// Called as a helper to ValidatePropertyValue to validate that an object @@ -992,6 +981,10 @@ protected virtual object ValidatePropertyValue(string propertyName, object value value = filter; break; + case "DependentAssemblies": + ValidatePropertyType(propertyName, value, typeof(AssemblyName[]), true); + break; + case "IsTransient": ValidatePropertyType(propertyName, value, typeof(bool), false); break; @@ -1002,7 +995,6 @@ protected virtual object ValidatePropertyValue(string propertyName, object value [SuppressMessage("Microsoft.Usage", "CA2240:ImplementISerializableCorrectly")] void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { - //IntSecurity.UnmanagedCode.Demand(); Serialize(info, context); } From 21be3a442aaee1cc2dcd3276f4bd1dcbcf876e44 Mon Sep 17 00:00:00 2001 From: Hugh Bellamy Date: Fri, 12 Apr 2019 23:19:39 +0100 Subject: [PATCH 2/2] Add ToolboxItem tests --- .../tests/UnitTests/Resources/16x16.bmp | Bin 0 -> 1078 bytes .../tests/UnitTests/Resources/16x24.bmp | Bin 0 -> 1590 bytes .../tests/UnitTests/Resources/24x16.bmp | Bin 0 -> 1590 bytes .../System.Windows.Forms.Design.Tests.csproj | 12 + .../Design/ToolboxItemCollectionTests.cs | 75 + .../System/Drawing/Design/ToolboxItemTests.cs | 1775 +++++++++++++++++ 6 files changed, 1862 insertions(+) create mode 100644 src/System.Windows.Forms.Design/tests/UnitTests/Resources/16x16.bmp create mode 100644 src/System.Windows.Forms.Design/tests/UnitTests/Resources/16x24.bmp create mode 100644 src/System.Windows.Forms.Design/tests/UnitTests/Resources/24x16.bmp create mode 100644 src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemCollectionTests.cs create mode 100644 src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemTests.cs diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/Resources/16x16.bmp b/src/System.Windows.Forms.Design/tests/UnitTests/Resources/16x16.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8bf3513637095395c071fdf0b616ae43334da166 GIT binary patch literal 1078 zcmZvbOGuPa6vrnhG;9&pW^|Dqr0jCqFtyK}W!=d`Mx&LdeR-m~VXd+Kd zz(XToB$btb$D<;2BGz8L=nFbK>1TU4PeJJ;z+45CmjSo36{M#tFh1DkntsW(IULGv z46)wcUZA7|NIC};762yZFDwLdbAaqDAoT(eb_hsITVafKh`ov!X0xgld38DxqhIKoB;yDVpJw|K(a|PU zRjn`w(Ac;rH3owi6YK89&`?m5V{%f&@0Vk$-bZ~A^`GJQ13f+OIp&5wVhXXRseKWU zT7UaTc>Rmgo|&0N;@NJ_>mX*Nq*QYK+pw`_0>c}~$Y`P84u`Ev&TsaKy*?)cysHuE zYweg|-$e3IP%tFV&tg%~*2dcDc}sseqK-B44hLx4q1QVR5$U1r!1c^-#Kbsh-((Fu zVa%WM{zM&!8t7zNcY`>;B9f2rqZWi5c!tnWGvkPycgSTVCzrr#UE8f6QO6>N#R7P} zKwZN!u4Q@3y$ zi5w31TZk)xBsh@56s5Qe)gRQ#g>ssV8OTL0jo+u|eGk|H{^;Glzu)`3&;5Cy_jzOI z)@Mz6ZIy4JV6EUG;AZlbopY`CG?^3@m(2#Q$jfumxw)_$i#%6(*S+Fjy5!U=C;(R| zUQW(ZU(0o~v!S8_s;eR63pjBcjva%vG^nbAl2Wi*SK3gv)p=zl)YQPCLl74udgtLx z3hax5@LkIP9L2>;Z7jxIUJiA2@a|4H8Ea5f1cil?kHmB;9(IKr1P08LnmR`5vN)9Q zrY7;T&meLSq<#*kEkf^Ae&s9@A|fCx41$9Gl6sGjpRejmHSqE)uqC9QP5yKE`ToP+1HBX$&FTA5HEV7*_~f90$pq(9f1#`0PH5g(HuR`R`+ zmPqksHQMhloV5}i-KuM(?&|8*zvcWMAtA8swNZwK21R3_|z7tOUCcGc<@$HfSU4l0k zOYI(U{krr;$)B2MHg^#4lCs|={W75S)aP>51I-T%=*G=W>9^tQdrsmT#%_nQvOziP zz{jVDjT`%9e@l9>{i(jaLDiuRzfHZYTGcE2TG3Aw{Sn=7RagFyv+oHAP`cfG99hbf zsSzfo;PJR2c4kOUt`%M<-rjfQZzDK3S>hklecjNY^3K8Cy_3*wSNQp-UhO;S^Z*G- zclF-kc)<4UWg=H0$RIr2D)lpT58S%_n77|4mGeBlDw78w>&8uW|H{`Lu3dB5xY5!t z^p^sQ+~0Tl{<1RV{%^{A%T%&ye0rpgzP@2z-EvvzDnT6^%oTKXKO`=`S?CmAG#})` zh5NdPb8=MgLVc4%c-ew{L8ZWk=W|xc$twFif%+#4qKS$s&~Ho47xn(KvcTRb|7>MH z5r6+Q)~?H4(6QpNCX)@`7On5)6(RDDr|-u(Lk#`??Txb>Ia(}oCj@6$y*fq1!y`rL zSgHMPES8>Sy3ToGwHg%2oBXIxQSf{1MZ-`CeI5@iM|nAvl?CB;gPK=V{2S$$g6CW= zP*~3KU-J-eX(`m#!{y6RTL)@>;XItr5r{l@4oXU7uNJ)Cpj3SSXGd|{?QrD^_i8Jqu|^Og{S1Bt6}vpkP6`pHf{7%3rtJe9j-I6IxnK&7GbO zd-p=}A;`9ZL+s{WFv-e-%uLAmM0k(FzI_n)4s6^A2?;ae+nD&|*W62OI2_Q{22D*6 z9c2<95Bm=+ko|cd)-#UBpYW8= zJ-ffD@7CN5w{AUV$BqX?N6Vdd!`YMF%-p{R<|A5L?~2Vn;T;o<^2WLjyj543o15U_ z>^P@R4$Jx!J9qYrY$rL{C-DvFSgCjF>5*JSOZr1{j~1kPKX8 zdU}GInjxIdPR4)xMb= z17v3_-+m@G_MXVwTGue{ifoj;Xd@7K@{C^zlP2E~k(*m(zgy5pSeQE3F8p4RdBR_z z`R#U-t}eMx!>_XLmiT|q3lV+nit8ZjR6PR&y_$D=)=!ar1Y7Y4e?FMiYm<}XT)f!K zuHDz-u}NxP4mgV9ZN(5NgunI{C!OGTyGyGa=YSa z6Lb>2xtZpsUhx9v=bvyUTlrB)^j5`xOx`zm_fYLS9OAF!=8v5-q@;Z#I$sLh97?)I zM#c>pJN0}^R3(vb*2=h2uN_HiAu*{@#zlf0!G4L0NBYUaKl!QZ`jYe#hs3E)dO};r zBZ_Q4uqCQM^gk6?S+~BFmtHQxvce%b;$ZDs2b(t8Wbd@#utscbhSc8;iAk__m)2Lv zMw!#pJ;c{2J*8oaoG)&2-~$(1-^#=io+&)X1;+%+ZYu94oFFmrYpmAWa&At?TX8Mt zR%;5X2YEcE^fObBtG!4LJjLOd7N5q+FC3AY9;UEx6q{{I^k#LR3guyt_xauv;t$D? g9hYlS*Px1@g6h$VOG!0XdWzHSUexyronI>d2B(rUe*gdg literal 0 HcmV?d00001 diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System.Windows.Forms.Design.Tests.csproj b/src/System.Windows.Forms.Design/tests/UnitTests/System.Windows.Forms.Design.Tests.csproj index 2db090483e3..3c66db51f45 100644 --- a/src/System.Windows.Forms.Design/tests/UnitTests/System.Windows.Forms.Design.Tests.csproj +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System.Windows.Forms.Design.Tests.csproj @@ -14,8 +14,20 @@ + + + + System.Drawing.Design.Tests.16x16.bmp + + + System.Drawing.Design.Tests.24x16.bmp + + + System.Drawing.Design.Tests.16x24.bmp + + diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemCollectionTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemCollectionTests.cs new file mode 100644 index 00000000000..0c65b8cc261 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemCollectionTests.cs @@ -0,0 +1,75 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; + +namespace System.Drawing.Design.Tests +{ + public class ToolboxItemCollectionTests + { + [Fact] + public void ToolboxItemCollection_Ctor_ToolboxItemArray() + { + var item = new ToolboxItem(); + var collection = new ToolboxItemCollection(new ToolboxItem[] { item }); + Assert.Same(item, Assert.Single(collection)); + Assert.Same(item, collection[0]); + Assert.True(collection.Contains(item)); + Assert.Equal(0, collection.IndexOf(item)); + } + + [Fact] + public void ToolboxItemCollection_Ctor_NullToolboxItemArray_ThrowsArgumentNullException() + { + Assert.Throws("c", () => new ToolboxItemCollection((ToolboxItem[])null)); + } + + [Fact] + public void ToolboxItemCollection_Ctor_ToolboxItemCollection() + { + var item = new ToolboxItem(); + var value = new ToolboxItemCollection(new ToolboxItem[] { item }); + var collection = new ToolboxItemCollection(value); + Assert.Same(item, Assert.Single(collection)); + Assert.Same(item, collection[0]); + Assert.True(collection.Contains(item)); + Assert.Equal(0, collection.IndexOf(item)); + } + + [Fact] + public void ToolboxItemCollection_Ctor_NullToolboxItemCollection_ThrowsArgumentNullException() + { + Assert.Throws("c", () => new ToolboxItemCollection((ToolboxItemCollection)null)); + } + + [Fact] + public void ToolboxItemCollection_Contains_NoSuchValue_ReturnsFalse() + { + var item = new ToolboxItem(); + var collection = new ToolboxItemCollection(new ToolboxItem[] { item }); + Assert.False(collection.Contains(new ToolboxItem { DisplayName = "Other" })); + Assert.False(collection.Contains(null)); + } + + [Fact] + public void ToolboxItemCollection_IndexOf_NoSuchValue_ReturnsNegativeOne() + { + var item = new ToolboxItem(); + var collection = new ToolboxItemCollection(new ToolboxItem[] { item }); + Assert.Equal(-1, collection.IndexOf(new ToolboxItem { DisplayName = "Other" })); + Assert.Equal(-1, collection.IndexOf(null)); + } + + [Fact] + public void ToolboxItemCollection_CopyTo_Invoke_Success() + { + var item = new ToolboxItem(); + var collection = new ToolboxItemCollection(new ToolboxItem[] { item }); + + var array = new ToolboxItem[3]; + collection.CopyTo(array, 1); + Assert.Equal(new ToolboxItem[] { null, item, null }, array); + } + } +} diff --git a/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemTests.cs b/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemTests.cs new file mode 100644 index 00000000000..56f0e181697 --- /dev/null +++ b/src/System.Windows.Forms.Design/tests/UnitTests/System/Drawing/Design/ToolboxItemTests.cs @@ -0,0 +1,1775 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using Moq; +using WinForms.Common.Tests; +using Xunit; + +namespace System.Drawing.Design.Tests +{ + public class ToolboxItemTests + { + [Fact] + public void ToolboxItem_Ctor_Default() + { + var item = new ToolboxItem(); + Assert.Null(item.AssemblyName); + Assert.Null(item.Bitmap); + Assert.Null(item.Company); + Assert.Equal(".NET Component", item.ComponentType); + Assert.Null(item.DependentAssemblies); + Assert.Null(item.Description); + Assert.Empty(item.DisplayName); + Assert.Empty(item.Filter); + Assert.Same(item.Filter, item.Filter); + Assert.False(item.IsTransient); + Assert.False(item.Locked); + Assert.Null(item.OriginalBitmap); + Assert.Empty(item.Properties); + Assert.Same(item.Properties, item.Properties); + Assert.False(item.Properties.IsFixedSize); + Assert.False(item.Properties.IsReadOnly); + Assert.Empty(item.TypeName); + Assert.Empty(item.Version); + } + + public static IEnumerable AssemblyName_Set_TestData() + { + yield return new object[] { null }; + yield return new object[] { new AssemblyName() }; + yield return new object[] { new AssemblyName(typeof(int).Assembly.FullName) }; + } + + [Theory] + [MemberData(nameof(AssemblyName_Set_TestData))] + public void ToolboxItem_AssemblyName_Set_GetReturnsExpected(AssemblyName value) + { + var item = new ToolboxItem + { + AssemblyName = value + }; + if (value == null) + { + Assert.Null(item.AssemblyName); + Assert.Null(item.Properties["AssemblyName"]); + Assert.Empty(item.Version); + } + else + { + Assert.Equal(value.FullName, item.AssemblyName.FullName); + Assert.NotSame(value, item.AssemblyName); + Assert.NotSame(item.AssemblyName, item.AssemblyName); + Assert.Equal(value.FullName, ((AssemblyName)item.Properties["AssemblyName"]).FullName); + Assert.NotSame(value, item.Properties["AssemblyName"]); + Assert.NotSame(item.Properties["AssemblyName"], item.Properties["AssemblyName"]); + Assert.Equal(value.Version?.ToString() ?? string.Empty, item.Version); + } + + // Set same. + item.AssemblyName = value; + if (value == null) + { + Assert.Null(item.AssemblyName); + Assert.Null(item.Properties["AssemblyName"]); + Assert.Empty(item.Version); + } + else + { + Assert.Equal(value.FullName, item.AssemblyName.FullName); + Assert.NotSame(value, item.AssemblyName); + Assert.NotSame(item.AssemblyName, item.AssemblyName); + Assert.Equal(value.FullName, ((AssemblyName)item.Properties["AssemblyName"]).FullName); + Assert.NotSame(value, item.Properties["AssemblyName"]); + Assert.NotSame(item.Properties["AssemblyName"], item.Properties["AssemblyName"]); + Assert.Equal(value.Version?.ToString() ?? string.Empty, item.Version); + } + } + + [Fact] + public void ToolboxItem_AssemblyName_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("AssemblyName", new object())); + } + + public static IEnumerable Bitmap_Set_TestData() + { + yield return new object[] { null }; + yield return new object[] { new Bitmap(10, 10) }; + } + + [Theory] + [MemberData(nameof(Bitmap_Set_TestData))] + public void ToolboxItem_Bitmap_Set_GetReturnsExpected(Bitmap value) + { + var item = new ToolboxItem + { + Bitmap = value + }; + Assert.Same(value, item.Bitmap); + Assert.Same(value, item.Properties["Bitmap"]); + + // Set same. + item.Bitmap = value; + Assert.Same(value, item.Bitmap); + Assert.Same(value, item.Properties["Bitmap"]); + } + + [Fact] + public void ToolboxItem_Bitmap_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("Bitmap", new object())); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void ToolboxItem_Company_Set_GetReturnsExpected(string value) + { + var item = new ToolboxItem + { + Company = value + }; + Assert.Same(value, item.Company); + Assert.Same(value, item.Properties["Company"]); + + // Set same. + item.Company = value; + Assert.Same(value, item.Company); + Assert.Same(value, item.Properties["Company"]); + } + + [Fact] + public void ToolboxItem_Company_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("Company", new object())); + } + + public static IEnumerable DependentAssemblies_Set_TestData() + { + yield return new object[] { null }; + yield return new object[] { new AssemblyName[0] }; + yield return new object[] { new AssemblyName[] { null } }; + yield return new object[] { new AssemblyName[] { new AssemblyName() } }; + } + + [Theory] + [MemberData(nameof(DependentAssemblies_Set_TestData))] + public void ToolboxItem_DependentAssemblies_Set_GetReturnsExpected(AssemblyName[] value) + { + var item = new ToolboxItem + { + DependentAssemblies = value + }; + if (value == null) + { + Assert.Null(item.DependentAssemblies); + Assert.Null(item.Properties["DependentAssemblies"]); + } + else + { + Assert.Equal(value, item.DependentAssemblies); + Assert.NotSame(value, item.DependentAssemblies); + Assert.Equal(value, item.Properties["DependentAssemblies"]); + Assert.NotSame(value, item.Properties["DependentAssemblies"]); + } + + // Set same. + item.DependentAssemblies = value; + if (value == null) + { + Assert.Null(item.DependentAssemblies); + Assert.Null(item.Properties["DependentAssemblies"]); + } + else + { + Assert.Equal(value, item.DependentAssemblies); + Assert.NotSame(value, item.DependentAssemblies); + Assert.Equal(value, item.Properties["DependentAssemblies"]); + Assert.NotSame(value, item.Properties["DependentAssemblies"]); + } + } + + [Fact] + public void ToolboxItem_DependentAssemblies_SetWithInvalidPropertyType_GetThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("DependentAssemblies", new object())); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void ToolboxItem_Description_Set_GetReturnsExpected(string value) + { + var item = new ToolboxItem + { + Description = value + }; + Assert.Same(value, item.Description); + Assert.Same(value, item.Properties["Description"]); + + // Set same. + item.Description = value; + Assert.Same(value, item.Description); + Assert.Same(value, item.Properties["Description"]); + } + + [Fact] + public void ToolboxItem_Description_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("Description", new object())); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void ToolboxItem_DisplayName_Set_GetReturnsExpected(string value) + { + var item = new ToolboxItem + { + DisplayName = value + }; + Assert.Same(value ?? string.Empty, item.DisplayName); + Assert.Same(value ?? string.Empty, item.Properties["DisplayName"]); + + // Set same. + item.DisplayName = value; + Assert.Same(value ?? string.Empty, item.DisplayName); + Assert.Same(value ?? string.Empty, item.Properties["DisplayName"]); + } + + [Fact] + public void ToolboxItem_DisplayName_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("DisplayName", new object())); + } + + public static IEnumerable Filter_Set_TestData() + { + yield return new object[] { null, new object[0] }; + yield return new object[] { new object[0], new object[0] }; + yield return new object[] { new object[] { null }, new object[0] }; + yield return new object[] { new object[] { new object(), new ToolboxItemFilterAttribute("filterString") }, new object[] { new ToolboxItemFilterAttribute("filterString") } }; + } + + [Theory] + [MemberData(nameof(Filter_Set_TestData))] + public void ToolboxItem_Filter_Set_GetReturnsExpected(ICollection value, ICollection expected) + { + var item = new ToolboxItem + { + Filter = value + }; + Assert.Equal(expected , item.Filter); + Assert.Equal(expected, item.Properties["Filter"]); + + // Set same. + item.Filter = value; + Assert.Equal(expected , item.Filter); + Assert.Equal(expected, item.Properties["Filter"]); + } + + [Fact] + public void ToolboxItem_Filter_SetWithInvalidPropertyType_GetThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("Filter", new object())); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetBoolTheoryData))] + public void ToolboxItem_IsTransient_Set_GetReturnsExpected(bool value) + { + var item = new ToolboxItem + { + IsTransient = value + }; + Assert.Equal(value , item.IsTransient); + Assert.Equal(value, item.Properties["IsTransient"]); + + // Set same. + item.IsTransient = value; + Assert.Equal(value , item.IsTransient); + Assert.Equal(value, item.Properties["IsTransient"]); + } + + [Fact] + public void ToolboxItem_IsTransient_SetWithNullPropertyType_GetThrowsArgumentNullException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("IsTransient", null)); + } + + [Fact] + public void ToolboxItem_IsTransient_SetWithInvalidPropertyType_GetThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("IsTransient", new object())); + } + + [Theory] + [MemberData(nameof(Bitmap_Set_TestData))] + public void ToolboxItem_OriginalBitmap_Set_GetReturnsExpected(Bitmap value) + { + var item = new ToolboxItem + { + OriginalBitmap = value + }; + Assert.Same(value, item.OriginalBitmap); + Assert.Same(value, item.Properties["OriginalBitmap"]); + + // Set same. + item.OriginalBitmap = value; + Assert.Same(value, item.OriginalBitmap); + Assert.Same(value, item.Properties["OriginalBitmap"]); + } + + [Fact] + public void ToolboxItem_OriginalBitmap_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("OriginalBitmap", new object())); + } + + [Theory] + [CommonMemberData(nameof(CommonTestHelper.GetStringTheoryData))] + public void ToolboxItem_TypeName_Set_GetReturnsExpected(string value) + { + var item = new ToolboxItem + { + TypeName = value + }; + Assert.Same(value ?? string.Empty, item.TypeName); + Assert.Same(value ?? string.Empty, item.Properties["TypeName"]); + + // Set same. + item.TypeName = value; + Assert.Same(value ?? string.Empty, item.TypeName); + Assert.Same(value ?? string.Empty, item.Properties["TypeName"]); + } + + [Fact] + public void ToolboxItem_TypeName_SetWithInvalidPropertyType_ThrowsArgumentException() + { + var item = new ToolboxItem(); + Assert.Throws("value", () => item.Properties.Add("TypeName", new object())); + } + + [Fact] + public void ToolboxItem_CreateComponents_InvokeWithoutHost_ReturnsExpected() + { + var item = new ToolboxItem + { + AssemblyName = typeof(Component).Assembly.GetName(true), + TypeName = "System.ComponentModel.Component" + }; + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.IsType(Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.IsType(Assert.Single(item.CreateComponents())); + Assert.Equal(1, creatingCallCount); + Assert.Equal(1, createdCallCount); + + Assert.IsType(Assert.Single(item.CreateComponents(null))); + Assert.Equal(2, creatingCallCount); + Assert.Equal(2, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.IsType(Assert.Single(item.CreateComponents(null))); + Assert.Equal(2, creatingCallCount); + Assert.Equal(2, createdCallCount); + } + + public static IEnumerable CreateComponents_InvokeWithHostWithNonIComponentInitializerDesigner_TestData() + { + var mockDesigner = new Mock(MockBehavior.Strict); + mockDesigner.Setup(d => d.Dispose()); + + yield return new object[] { new Component(), null }; + yield return new object[] { new Component(), mockDesigner.Object }; + + yield return new object[] { null, null }; + yield return new object[] { null, mockDesigner.Object }; + } + + [Theory] + [MemberData(nameof(CreateComponents_InvokeWithHostWithNonIComponentInitializerDesigner_TestData))] + public void ToolboxItem_CreateComponents_InvokeWithHostWithNonIComponentInitializerDesigner_ReturnsExpected(Component component, IDesigner designer) + { + var item = new ToolboxItem + { + TypeName = "typeName" + }; + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(component); + mockDesignerHost + .Setup(h => h.GetDesigner(component)) + .Returns(designer); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(component, Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object))); + Assert.Equal(1, creatingCallCount); + Assert.Equal(1, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object, null))); + Assert.Equal(2, creatingCallCount); + Assert.Equal(2, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object, new Hashtable()))); + Assert.Equal(3, creatingCallCount); + Assert.Equal(3, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object))); + Assert.Equal(3, creatingCallCount); + Assert.Equal(3, createdCallCount); + } + + [Fact] + public void ToolboxItem_CreateComponents_InvokeWithHostWithIComponentInitializerDesigner_ReturnsExpected() + { + var component = new Component(); + var item = new ToolboxItem + { + TypeName = "typeName" + }; + var mockDesigner = new Mock(MockBehavior.Strict); + mockDesigner.Setup(d => d.Dispose()); + var mockComponentInitializer = mockDesigner.As(); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(null)); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(new Hashtable())); + + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(component); + mockDesignerHost + .Setup(h => h.GetDesigner(component)) + .Returns(mockDesigner.Object); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(component, Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object))); + Assert.Equal(1, creatingCallCount); + Assert.Equal(1, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object, null))); + Assert.Equal(2, creatingCallCount); + Assert.Equal(2, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object, new Hashtable()))); + Assert.Equal(3, creatingCallCount); + Assert.Equal(3, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object))); + Assert.Equal(3, creatingCallCount); + Assert.Equal(3, createdCallCount); + } + + [Fact] + public void ToolboxItem_CreateComponents_InvokeWithHostWithThrowingIComponentInitializerDesigner_ReturnsExpected() + { + var component = new Component(); + var item = new ToolboxItem + { + TypeName = "typeName" + }; + var mockDesigner = new Mock(MockBehavior.Strict); + mockDesigner.Setup(d => d.Dispose()); + var mockComponentInitializer = mockDesigner.As(); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(null)) + .Throws(new Exception()); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(new Hashtable())) + .Throws(new Exception()); + + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(component); + mockDesignerHost + .Setup(h => h.GetDesigner(component)) + .Returns(mockDesigner.Object); + mockDesignerHost + .Setup(h => h.DestroyComponent(component)); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(component, Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Throws(() => item.CreateComponents(mockDesignerHost.Object)); + Assert.Equal(1, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Throws(() => item.CreateComponents(mockDesignerHost.Object, null)); + Assert.Equal(2, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Throws(() => item.CreateComponents(mockDesignerHost.Object, new Hashtable())); + Assert.Equal(3, creatingCallCount); + Assert.Equal(0, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Throws(() => item.CreateComponents(mockDesignerHost.Object)); + Assert.Equal(3, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Fact] + public void ToolboxItem_CreateComponents_InvokeWithNullComponentsCoreWithHost_ReturnsExpected() + { + var item = new NullComponentsToolboxItem + { + TypeName = "typeName" + }; + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(new Component()); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.Components); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Null(item.CreateComponents(mockDesignerHost.Object)); + Assert.Equal(1, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Null(item.CreateComponents(mockDesignerHost.Object, null)); + Assert.Equal(2, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Null(item.CreateComponents(mockDesignerHost.Object, new Hashtable())); + Assert.Equal(3, creatingCallCount); + Assert.Equal(0, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Null(item.CreateComponents(mockDesignerHost.Object)); + Assert.Equal(3, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Theory] + [InlineData("")] + [InlineData("NoSuchType")] + [InlineData("System.Int32")] + public void ToolboxItem_CreateComponents_InvokeInvalidType_ReturnsEmpty(string typeName) + { + var item = new ToolboxItem + { + TypeName = typeName + }; + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.Components); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + Assert.Empty(item.CreateComponents()); + Assert.Equal(1, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Fact] + public void ToolboxItem_CreateComponentsCore_InvokeWithoutHost_ReturnsExpected() + { + var item = new SubToolboxItem + { + AssemblyName = typeof(Component).Assembly.GetName(true), + TypeName = "System.ComponentModel.Component" + }; + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.IsType(Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.IsType(Assert.Single(item.CreateComponentsCore(null))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.IsType(Assert.Single(item.CreateComponentsCore(null))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Theory] + [MemberData(nameof(CreateComponents_InvokeWithHostWithNonIComponentInitializerDesigner_TestData))] + public void ToolboxItem_CreateComponentsCore_InvokeWithHostWithNonIComponentInitializerDesigner_ReturnsExpected(Component component, IDesigner designer) + { + var item = new SubToolboxItem + { + TypeName = "typeName" + }; + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(component); + mockDesignerHost + .Setup(h => h.GetDesigner(component)) + .Returns(designer); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(component, Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object, null))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object, new Hashtable()))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Fact] + public void ToolboxItem_CreateComponentsCore_InvokeWithHostWithIComponentInitializerDesigner_ReturnsExpected() + { + var component = new Component(); + var item = new SubToolboxItem + { + TypeName = "typeName" + }; + var mockDesigner = new Mock(MockBehavior.Strict); + mockDesigner.Setup(d => d.Dispose()); + var mockComponentInitializer = mockDesigner.As(); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(null)); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(new Hashtable())); + + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(component); + mockDesignerHost + .Setup(h => h.GetDesigner(component)) + .Returns(mockDesigner.Object); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(component, Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object, null))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object, new Hashtable()))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Same(component, Assert.Single(item.CreateComponents(mockDesignerHost.Object))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Fact] + public void ToolboxItem_CreateComponentsCore_InvokeWithHostWithThrowingIComponentInitializerDesigner_ReturnsExpected() + { + var component = new Component(); + var item = new SubToolboxItem + { + TypeName = "typeName" + }; + var mockDesigner = new Mock(MockBehavior.Strict); + mockDesigner.Setup(d => d.Dispose()); + var mockComponentInitializer = mockDesigner.As(); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(null)) + .Throws(new Exception()); + mockComponentInitializer + .Setup(i => i.InitializeNewComponent(new Hashtable())) + .Throws(new Exception()); + + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + mockDesignerHost + .Setup(h => h.CreateComponent(typeof(bool))) + .Returns(component); + mockDesignerHost + .Setup(h => h.GetDesigner(component)) + .Returns(mockDesigner.Object); + mockDesignerHost + .Setup(h => h.DestroyComponent(component)); + + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(mockDesignerHost.Object, e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Same(component, Assert.Single(e.Components)); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + // With handler. + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Throws(() => item.CreateComponentsCore(mockDesignerHost.Object, null)); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + Assert.Throws(() => item.CreateComponentsCore(mockDesignerHost.Object, new Hashtable())); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + + // Remove handler. + item.ComponentsCreating -= creatingHandler; + item.ComponentsCreated -= createdHandler; + + Assert.Same(component, Assert.Single(item.CreateComponentsCore(mockDesignerHost.Object))); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Theory] + [InlineData("")] + [InlineData("NoSuchType")] + [InlineData("System.Int32")] + public void ToolboxItem_CreateComponentsCore_InvokeInvalidType_ReturnsEmpty(string typeName) + { + var item = new SubToolboxItem + { + TypeName = typeName + }; + int creatingCallCount = 0; + int createdCallCount = 0; + ToolboxComponentsCreatingEventHandler creatingHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.DesignerHost); + creatingCallCount++; + }; + ToolboxComponentsCreatedEventHandler createdHandler = (sender, e) => + { + Assert.Same(item, sender); + Assert.Null(e.Components); + createdCallCount++; + }; + item.ComponentsCreating += creatingHandler; + item.ComponentsCreated += createdHandler; + + Assert.Empty(item.CreateComponentsCore(null)); + Assert.Equal(0, creatingCallCount); + Assert.Equal(0, createdCallCount); + } + + [Fact] + public void ToolboxItem_CheckUnlocked_NotLocked_Nop() + { + var item = new SubToolboxItem(); + item.CheckUnlocked(); + item.CheckUnlocked(); + } + + [Fact] + public void ToolboxItem_CheckUnlocked_Locked_ThrowsInvalidOperationException() + { + var item = new SubToolboxItem(); + item.Lock(); + Assert.Throws(() => item.CheckUnlocked()); + } + + public static IEnumerable Equals_TestData() + { + var item = new ToolboxItem(); + yield return new object[] { item, item, true }; + yield return new object[] { item, new ToolboxItem(), true }; + yield return new object[] { item, new SubToolboxItem(), false }; + + yield return new object[] + { + item, + new ToolboxItem + { + Company = "Company", + DependentAssemblies = new AssemblyName[] { null }, + Description = "Description", + Filter = new ToolboxItemFilterAttribute[] { new ToolboxItemFilterAttribute("Filter") }, + IsTransient = true + }, + true + }; + + yield return new object[] + { + new ToolboxItem { TypeName = "TypeName" }, + new ToolboxItem { TypeName = "TypeName" }, + true + }; + yield return new object[] + { + new ToolboxItem { TypeName = "TypeName" }, + new ToolboxItem { TypeName = "typename" }, + false + }; + yield return new object[] + { + new ToolboxItem { TypeName = "TypeName" }, + new ToolboxItem(), + false + }; + yield return new object[] + { + new ToolboxItem(), + new ToolboxItem { TypeName = "TypeName" }, + false + }; + yield return new object[] + { + new NoValidationToolboxItem { TypeName = null }, + new NoValidationToolboxItem { TypeName = null }, + true + }; + yield return new object[] + { + new NoValidationToolboxItem { TypeName = null }, + new NoValidationToolboxItem { TypeName = "TypeName" }, + false + }; + yield return new object[] + { + new NoValidationToolboxItem { TypeName = "TypeName" }, + new NoValidationToolboxItem { TypeName = null }, + false + }; + + yield return new object[] + { + new ToolboxItem { DisplayName = "DisplayName" }, + new ToolboxItem { DisplayName = "DisplayName" }, + true + }; + yield return new object[] + { + new ToolboxItem { DisplayName = "DisplayName" }, + new ToolboxItem { DisplayName = "displayname" }, + false + }; + yield return new object[] + { + new ToolboxItem { DisplayName = "DisplayName" }, + new ToolboxItem(), + false + }; + yield return new object[] + { + new ToolboxItem(), + new ToolboxItem { DisplayName = "DisplayName" }, + false + }; + yield return new object[] + { + new NoValidationToolboxItem { DisplayName = null }, + new NoValidationToolboxItem { DisplayName = null }, + true + }; + yield return new object[] + { + new NoValidationToolboxItem { DisplayName = null }, + new NoValidationToolboxItem { DisplayName = "TypeName" }, + false + }; + yield return new object[] + { + new NoValidationToolboxItem { DisplayName = "TypeName" }, + new NoValidationToolboxItem { DisplayName = null }, + false + }; + + yield return new object[] + { + new ToolboxItem { AssemblyName = new AssemblyName("Name") }, + new ToolboxItem { AssemblyName = new AssemblyName("Name") }, + true + }; + yield return new object[] + { + new ToolboxItem { AssemblyName = new AssemblyName("Name") }, + new ToolboxItem { AssemblyName = new AssemblyName("name") }, + false + }; + yield return new object[] + { + new ToolboxItem(), + new ToolboxItem { AssemblyName = new AssemblyName("Name") }, + false + }; + yield return new object[] + { + new ToolboxItem { AssemblyName = new AssemblyName("Name") }, + new ToolboxItem(), + false + }; + + yield return new object[] { new ToolboxItem(), new object(), false }; + yield return new object[] { new ToolboxItem(), null, false }; + } + + [Theory] + [MemberData(nameof(Equals_TestData))] + public void ToolboxItem_Equals_Invoke_ReturnsExpected(ToolboxItem item, object other, bool expected) + { + Assert.Equal(expected, item.Equals(other)); + + } + + public static IEnumerable FilterPropertyValue_TestData() + { + var o = new object(); + yield return new object[] { "AssemblyName", null, null, true }; + yield return new object[] { "AssemblyName", new AssemblyName("Name"), new AssemblyName("Name"), false }; + yield return new object[] { "AssemblyName", o, o, true }; + yield return new object[] { "assemblyName", new AssemblyName("Name"), new AssemblyName("Name"), true }; + + yield return new object[] { "DisplayName", null, string.Empty, false }; + yield return new object[] { "DisplayName", "value", "value", true }; + yield return new object[] { "DisplayName", o, o, true }; + yield return new object[] { "displayname", null, null, true }; + + yield return new object[] { "TypeName", null, string.Empty, false }; + yield return new object[] { "TypeName", "value", "value", true }; + yield return new object[] { "TypeName", o, o, true }; + yield return new object[] { "typename", null, null, true }; + + yield return new object[] { "Filter", null, Array.Empty(), false }; + yield return new object[] { "Filter", new ToolboxItemFilterAttribute[0], new ToolboxItemFilterAttribute[0], true }; + yield return new object[] { "Filter", o, o, true }; + yield return new object[] { "filter", null, null, true }; + + yield return new object[] { "IsTransient", null, false, false }; + yield return new object[] { "IsTransient", true, true, true }; + yield return new object[] { "IsTransient", o, o, true }; + yield return new object[] { "istransient", null, null, true }; + + yield return new object[] { "NoSuchProperty", null, null, true }; + yield return new object[] { "NoSuchProperty", "value", "value", true }; + yield return new object[] { "NoSuchProperty", o, o, true }; + } + + [Theory] + [MemberData(nameof(FilterPropertyValue_TestData))] + public void ToolboxItem_FilterPropertyValue_Invoke_ReturnsExpected(string propertyName, object value, object expected, bool same) + { + var item = new SubToolboxItem(); + object actual = item.FilterPropertyValue(propertyName, value); + if (expected is AssemblyName expectedName) + { + Assert.Equal(expectedName.FullName, Assert.IsType(actual).FullName); + } + else + { + Assert.Equal(expected, actual); + } + Assert.Equal(same, object.ReferenceEquals(value, actual)); + } + + public static IEnumerable GetHashCode_TestData() + { + yield return new object[] { new ToolboxItem() }; + yield return new object[] { new ToolboxItem { TypeName = "TypeName", DisplayName = "DisplayName" } }; + yield return new object[] { new NoValidationToolboxItem { TypeName = null, DisplayName = null } }; + } + + [Theory] + [MemberData(nameof(GetHashCode_TestData))] + public void ToolboxItem_GetHashCode_Invoke_ReturnsExpected(ToolboxItem item) + { + Assert.Equal(item.GetHashCode(), item.GetHashCode()); + } + + public static IEnumerable GetType_TestData() + { + var nullServiceDesignerHost = new Mock(MockBehavior.Strict); + nullServiceDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(null); + foreach (object host in new object[] { null, nullServiceDesignerHost.Object }) + { + yield return new object[] { null, null, "System.Int32", false, typeof(int) }; + yield return new object[] { null, new AssemblyName("NoSuchAssembly"), "System.Int32", false, typeof(int) }; + yield return new object[] { null, new AssemblyName(typeof(int).Assembly.FullName), "System.Int32", false, typeof(int) }; + yield return new object[] { null, new AssemblyName(typeof(ToolboxItem).Assembly.FullName), "System.Int32", false, typeof(int) }; + yield return new object[] { null, new AssemblyName(typeof(int).Assembly.FullName), "System.Drawing.Design.Tests.ToolboxItemTests", false, null }; + yield return new object[] { null, new AssemblyName(typeof(ToolboxItemTests).Assembly.FullName), "System.Drawing.Design.Tests.ToolboxItemTests", false, typeof(ToolboxItemTests) }; + yield return new object[] { null, new AssemblyName(typeof(ToolboxItemTests).Assembly.FullName), "System.Drawing.Design.Tests.toolboxitemtests", false, null }; + yield return new object[] { null, new AssemblyName(typeof(ToolboxItemTests).Assembly.FullName), "NoSuchType", false, null }; + yield return new object[] { null, null, string.Empty, false, null }; + + var validNameWithCodeBase = new AssemblyName(typeof(int).Assembly.FullName); + validNameWithCodeBase.CodeBase = "System.Windows.Forms.Design.Tests.dll"; + yield return new object[] { null, validNameWithCodeBase, "System.Drawing.Design.Tests.ToolboxItemTests", false, null }; + + var invalidNameWithCodeBase = new AssemblyName("NoSuchAssembly"); + invalidNameWithCodeBase.CodeBase = "System.Windows.Forms.Design.Tests.dll"; + yield return new object[] { null, invalidNameWithCodeBase, "System.Drawing.Design.Tests.ToolboxItemTests", false, typeof(ToolboxItemTests) }; + + var invalidNameWithInvalidCodeBase = new AssemblyName("NoSuchAssembly"); + invalidNameWithInvalidCodeBase.CodeBase = "AlsoNoSuchAssembly"; + yield return new object[] { null, invalidNameWithInvalidCodeBase, "System.Drawing.Design.Tests.ToolboxItemTests", false, null }; + + AssemblyLoadContext.Default.Resolving += (context, name) => + { + if (name.Name == "ThrowBadImageFormatException") + { + throw new BadImageFormatException(); + } + else if (name.Name == "ThrowIOException") + { + throw new IOException(); + } + + return null; + }; + yield return new object[] { null, new AssemblyName("ThrowBadImageFormatException"), "System.Int32", false, typeof(int) }; + yield return new object[] { null, new AssemblyName("ThrowIOException"), "System.Int32", false, typeof(int) }; + + var badImageFormatExceptionCodeBase = new AssemblyName("NoSuchAssembly"); + badImageFormatExceptionCodeBase.CodeBase = "ThrowBadImageFormatException"; + yield return new object[] { null, badImageFormatExceptionCodeBase, "System.Int32", false, typeof(int) }; + + var ioFormatExceptionCodeBase = new AssemblyName("NoSuchAssembly"); + ioFormatExceptionCodeBase.CodeBase = "ThrowIOException"; + yield return new object[] { null, ioFormatExceptionCodeBase, "System.Int32", false, typeof(int) }; + } + + var invalidServiceDesignerHost = new Mock(MockBehavior.Strict); + invalidServiceDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new object()); + yield return new object[] { invalidServiceDesignerHost.Object, new AssemblyName(typeof(int).Assembly.FullName), "System.Int32", false, typeof(int) }; + + foreach (bool reference in new bool[] { true, false }) + { + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(new CustomTypeResolutionService()); + yield return new object[] { mockDesignerHost.Object, null, "typeName", reference, typeof(bool) }; + yield return new object[] { mockDesignerHost.Object, null, string.Empty, false, null }; + yield return new object[] { mockDesignerHost.Object, new AssemblyName(), "typeName", reference, typeof(bool) }; + yield return new object[] { mockDesignerHost.Object, new AssemblyName(typeof(int).Assembly.FullName), "System.Int32", reference, typeof(int) }; + yield return new object[] { mockDesignerHost.Object, new AssemblyName(typeof(int).Assembly.FullName), "System.Drawing.Design.Tests.ToolboxItemTests", reference, typeof(ToolboxItemTests) }; + yield return new object[] { mockDesignerHost.Object, new AssemblyName(typeof(int).Assembly.FullName), "System.Drawing.Design.Tests.toolboxitemtests", reference, null }; + yield return new object[] { mockDesignerHost.Object, new AssemblyName(typeof(int).Assembly.FullName), "NoSuchType", reference, null }; + } + } + + [Theory] + [MemberData(nameof(GetType_TestData))] + public void ToolboxItem_GetType_InvokeWithoutTypeNameAssemblyName_ReturnsExpected(IDesignerHost host, AssemblyName assemblyName, string typeName, bool reference, Type expected) + { + if (reference) + { + return; + } + + var item = new ToolboxItem + { + AssemblyName = assemblyName, + TypeName = typeName + }; + Assert.Equal(expected, item.GetType(host)); + } + + [Theory] + [MemberData(nameof(GetType_TestData))] + public void ToolboxItem_GetType_InvokeWithTypeNameAssemblyName_ReturnsExpected(IDesignerHost host, AssemblyName assemblyName, string typeName, bool reference, Type expected) + { + var item = new SubToolboxItem(); + Assert.Equal(expected, item.GetType(host, assemblyName, typeName, reference)); + } + + [Fact] + public void ToolboxItem_GetType_NullTypeName_ThrowsArgumentNullException() + { + var item = new SubToolboxItem(); + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(null); + Assert.Throws("typeName", () => item.GetType(mockDesignerHost.Object, null, null, false)); + Assert.Throws("typeName", () => item.GetType(null, null, null, false)); + } + + [Fact] + public void ToolboxItem_GetType_EmptyAssemblyName_ThrowsArgumentException() + { + var item = new SubToolboxItem(); + var mockDesignerHost = new Mock(MockBehavior.Strict); + mockDesignerHost + .Setup(h => h.GetService(typeof(ITypeResolutionService))) + .Returns(null); + Assert.Throws(null, () => item.GetType(mockDesignerHost.Object, new AssemblyName(), "typeName", false)); + Assert.Throws(null, () => item.GetType(null, new AssemblyName(), "typeName", false)); + } + + public static IEnumerable Initialize_TypeWithAttributes_TestData() + { + yield return new object[] { typeof(ClassWithValidAttributes), new Size(16, 16) }; + yield return new object[] { typeof(ClassWithStretchedWidthImage), new Size(24, 16) }; + yield return new object[] { typeof(ClassWithStretchedHeightImage), new Size(16, 24) }; + yield return new object[] { typeof(ClassWithInvalidImage), new Size(16, 16) }; + } + + [Theory] + [MemberData(nameof(Initialize_TypeWithAttributes_TestData))] + public void ToolboxItem_Initialize_TypeWithAttributes_Success(Type type, Size expectedOriginalBitmapSize) + { + using (var bitmap = new Bitmap(10, 10)) + using (var originalBitmap = new Bitmap(10, 10)) + { + var filter = new ToolboxItemFilterAttribute[] { new ToolboxItemFilterAttribute("Filter") }; + var item = new ToolboxItem + { + AssemblyName = new AssemblyName("AssemblyName"), + Bitmap = bitmap, + Company = "Company", + Description = "Description", + DependentAssemblies = new AssemblyName[2], + DisplayName = "DisplayName", + Filter = filter, + OriginalBitmap = originalBitmap + }; + item.Initialize(type); + if (expectedOriginalBitmapSize == new Size(10, 10)) + { + Assert.NotEqual(bitmap, item.Bitmap); + Assert.Same(item.Bitmap, item.Bitmap); + } + else + { + Assert.Equal(new Size(16, 16), item.Bitmap.Size); + } + Assert.Equal("Microsoft Corporation", item.Company); + Assert.Equal("Description", item.Description); + Assert.Equal(type.Assembly.FullName, item.AssemblyName.FullName); + Assert.Equal(new string[] { type.Assembly.FullName }, item.DependentAssemblies.Select(a => a.FullName)); + Assert.Equal(type.Name, item.DisplayName); + Assert.Equal(new string[] { type.Name, "Filter", "System.Drawing.Design.Tests.ToolboxItemTests+" + type.Name }, item.Filter.Cast().Select(a => a.FilterString).OrderBy(f => f)); + Assert.Equal(expectedOriginalBitmapSize, item.OriginalBitmap.Size); + } + } + + [Fact] + public void ToolboxItem_Initialize_ObjectType_Success() + { + using (var bitmap = new Bitmap(10, 10)) + using (var originalBitmap = new Bitmap(10, 10)) + { + var filter = new ToolboxItemFilterAttribute[] { new ToolboxItemFilterAttribute("Filter") }; + var item = new ToolboxItem + { + AssemblyName = new AssemblyName("AssemblyName"), + Bitmap = bitmap, + Company = "Company", + Description = "Description", + DependentAssemblies = new AssemblyName[2], + DisplayName = "DisplayName", + Filter = filter, + OriginalBitmap = originalBitmap + }; + item.Initialize(typeof(object)); + Assert.NotEqual(bitmap, item.Bitmap); + Assert.Same(item.Bitmap, item.Bitmap); + Assert.Equal("Microsoft Corporation", item.Company); + Assert.Empty(item.Description); + Assert.Equal(typeof(object).Assembly.FullName, item.AssemblyName.FullName); + Assert.Equal(new string[] { typeof(object).Assembly.FullName }, item.DependentAssemblies.Select(a => a.FullName)); + Assert.Equal("Object", item.DisplayName); + Assert.Equal(new string[] { "System.Object" }, item.Filter.Cast().Select(a => a.FilterString)); + Assert.Same(item.OriginalBitmap, item.OriginalBitmap); + } + } + + [Fact] + public void ToolboxItem_Initialize_NullType_Nop() + { + using (var bitmap = new Bitmap(10, 10)) + using (var originalBitmap = new Bitmap(10, 10)) + { + var filter = new ToolboxItemFilterAttribute[] { new ToolboxItemFilterAttribute("Filter") }; + var item = new ToolboxItem + { + AssemblyName = new AssemblyName("AssemblyName"), + Bitmap = bitmap, + Company = "Company", + Description = "Description", + DependentAssemblies = new AssemblyName[2], + DisplayName = "DisplayName", + Filter = filter, + OriginalBitmap = originalBitmap + }; + item.Initialize(null); + Assert.Equal("AssemblyName", item.AssemblyName.FullName); + Assert.Same(bitmap, item.Bitmap); + Assert.Equal("Company", item.Company); + Assert.Equal("Description", item.Description); + Assert.Equal(new AssemblyName[2], item.DependentAssemblies); + Assert.Equal("DisplayName", item.DisplayName); + Assert.Equal(filter, item.Filter); + Assert.Same(originalBitmap, item.OriginalBitmap); + } + } + + [Theory] + [InlineData(null)] + [InlineData(typeof(int))] + public void ToolboxItem_Initialize_Locked_ThrowsInvalidOperationException(Type type) + { + var item = new ToolboxItem(); + item.Lock(); + Assert.Throws(() => item.Initialize(type)); + } + + [Fact] + public void ToolboxItem_Lock_Invoke_Success() + { + var item = new ToolboxItem(); + item.Lock(); + Assert.True(item.Locked); + Assert.True(item.Properties.IsFixedSize); + Assert.True(item.Properties.IsReadOnly); + + // Lock again. + item.Lock(); + Assert.True(item.Locked); + Assert.True(item.Properties.IsFixedSize); + Assert.True(item.Properties.IsReadOnly); + } + + [Fact] + public void ToolboxItem_OnComponentsCreated_Invoke_Success() + { + var item = new SubToolboxItem(); + + // No handler. + item.OnComponentsCreated(null); + + // Handler. + int callCount = 0; + ToolboxComponentsCreatedEventHandler handler = (sender, e) => + { + Assert.Equal(item, sender); + Assert.Null(e); + callCount++; + }; + + item.ComponentsCreated += handler; + item.OnComponentsCreated(null); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + item.ComponentsCreated -= handler; + item.OnComponentsCreated(null); + Assert.Equal(1, callCount); + } + [Fact] + public void ToolboxItem_OnComponentsCreating_Invoke_Success() + { + var item = new SubToolboxItem(); + + // No handler. + item.OnComponentsCreating(null); + + // Handler. + int callCount = 0; + ToolboxComponentsCreatingEventHandler handler = (sender, e) => + { + Assert.Equal(item, sender); + Assert.Null(e); + callCount++; + }; + + item.ComponentsCreating += handler; + item.OnComponentsCreating(null); + Assert.Equal(1, callCount); + + // Should not call if the handler is removed. + item.ComponentsCreating -= handler; + item.OnComponentsCreating(null); + Assert.Equal(1, callCount); + } + + public static IEnumerable ToString_TestData() + { + yield return new object[] { new ToolboxItem(), string.Empty }; + yield return new object[] { new ToolboxItem { DisplayName = "DisplayName" }, "DisplayName" }; + yield return new object[] { new NoValidationToolboxItem { DisplayName = null }, string.Empty }; + } + + [Theory] + [MemberData(nameof(ToString_TestData))] + public void ToolboxItem_ToString_Invoke_ReturnsExpected(ToolboxItem item, string expected) + { + Assert.Equal(expected, item.ToString()); + } + + public static IEnumerable ValidatePropertyValue_TestData() + { + var name = new AssemblyName(); + yield return new object[] { "AssemblyName", null, null }; + yield return new object[] { "AssemblyName", name, name }; + + var bitmap = new Bitmap(10, 10); + yield return new object[] { "Bitmap", null, null }; + yield return new object[] { "Bitmap", bitmap, bitmap }; + + var originalBitmap = new Bitmap(10, 10); + yield return new object[] { "OriginalBitmap", null, null }; + yield return new object[] { "OriginalBitmap", originalBitmap, originalBitmap }; + + yield return new object[] { "Company", null, string.Empty }; + yield return new object[] { "Company", "value", "value" }; + + yield return new object[] { "Description", null, string.Empty }; + yield return new object[] { "Description", "value", "value" }; + + yield return new object[] { "DisplayName", null, string.Empty }; + yield return new object[] { "DisplayName", "value", "value" }; + + yield return new object[] { "TypeName", null, string.Empty }; + yield return new object[] { "TypeName", "value", "value" }; + + var filter = new ToolboxItemFilterAttribute("filter"); + yield return new object[] { "Filter", null, new ToolboxItemFilterAttribute[0] }; + yield return new object[] { "Filter", new ToolboxItemFilterAttribute[0], new ToolboxItemFilterAttribute[0] }; + yield return new object[] { "Filter", new object[] { null, "value", filter, filter }, new ToolboxItemFilterAttribute[] { filter, filter } }; + + yield return new object[] { "NoSuchProperty", null, null }; + yield return new object[] { "NoSuchProperty", 1, 1 }; + + yield return new object[] { "istransient", null, null }; + yield return new object[] { "istransient", 1, 1 }; + } + + [Theory] + [MemberData(nameof(ValidatePropertyValue_TestData))] + public void ToolboxItem_ValidatePropertyValue_ValueAllowed_ReturnsExpected(string propertyName, object value, object expected) + { + var item = new SubToolboxItem(); + Assert.Equal(expected, item.ValidatePropertyValue(propertyName, value)); + } + + [Theory] + [InlineData("IsTransient")] + public void ToolboxItem_ValidatePropertyValue_NullValueDisallowed_ThrowsArgumentNullException(string propertyName) + { + var item = new SubToolboxItem(); + Assert.Throws("value", () => item.ValidatePropertyValue(propertyName, null)); + } + + [Theory] + [InlineData("AssemblyName")] + [InlineData("Bitmap")] + [InlineData("OriginalBitmap")] + [InlineData("Company")] + [InlineData("Description")] + [InlineData("DisplayName")] + [InlineData("TypeName")] + [InlineData("Filter")] + [InlineData("DependentAssemblies")] + public void ToolboxItem_ValidatePropertyValue_InvalidValue_ThrowsArgumentException(string propertyName) + { + var item = new SubToolboxItem(); + Assert.Throws("value", () => item.ValidatePropertyValue(propertyName, new object())); + } + + [Theory] + [InlineData(null, null)] + [InlineData("propertyName", typeof(int))] + public void ToolboxItem_ValidatePropertyType_NullDisallowed_ThrowsArgumentNullException(string propertyName, Type expectedType) + { + var item = new SubToolboxItem(); + Assert.Throws("value", () => item.ValidatePropertyType(propertyName, null, expectedType, allowNull: false)); + } + + [Theory] + [InlineData(null, null)] + [InlineData("propertyName", typeof(int))] + public void ToolboxItem_ValidatePropertyType_NullAllowed_Nop(string propertyName, Type expectedType) + { + var item = new SubToolboxItem(); + item.ValidatePropertyType(propertyName, null, expectedType, allowNull: true); + } + + [Theory] + [InlineData(null, false)] + [InlineData("propertyName", true)] + public void ToolboxItem_ValidatePropertyType_ValidType_Nop(string propertyName, bool allowNull) + { + var item = new SubToolboxItem(); + item.ValidatePropertyType(propertyName, 1, typeof(int), allowNull); + } + + [Theory] + [InlineData(null, false)] + [InlineData("propertyName", true)] + public void ToolboxItem_ValidatePropertyType_InvalidType_ThrowsArgumentException(string propertyName, bool allowNull) + { + var item = new SubToolboxItem(); + Assert.Throws("value", () => item.ValidatePropertyType(propertyName, new object(), typeof(int), allowNull)); + } + + private class SubToolboxItem : ToolboxItem + { + public new void CheckUnlocked() => base.CheckUnlocked(); + + public new IComponent[] CreateComponentsCore(IDesignerHost host) + { + return base.CreateComponentsCore(host); + } + + public new IComponent[] CreateComponentsCore(IDesignerHost host, IDictionary defaultValues) + { + return base.CreateComponentsCore(host, defaultValues); + } + + public new object FilterPropertyValue(string propertyName, object value) + { + return base.FilterPropertyValue(propertyName, value); + } + + public new Type GetType(IDesignerHost host, AssemblyName assemblyName, string typeName, bool reference) + { + return base.GetType(host, assemblyName, typeName, reference); + } + + public new void OnComponentsCreated(ToolboxComponentsCreatedEventArgs args) + { + base.OnComponentsCreated(args); + } + + public new void OnComponentsCreating(ToolboxComponentsCreatingEventArgs args) + { + base.OnComponentsCreating(args); + } + + public new object ValidatePropertyValue(string propertyName, object value) + { + return base.ValidatePropertyValue(propertyName, value); + } + + public new void ValidatePropertyType(string propertyName, object value, Type expectedType, bool allowNull) + { + base.ValidatePropertyType(propertyName, value, expectedType, allowNull); + } + } + + private class CustomTypeResolutionService : ITypeResolutionService + { + public Assembly GetAssemblyResult { get; set; } + + public Assembly GetAssembly(AssemblyName name) => GetAssemblyResult; + + public Assembly GetAssembly(AssemblyName name, bool throwOnError) + { + throw new NotImplementedException(); + } + + public string GetPathOfAssembly(AssemblyName name) + { + throw new NotImplementedException(); + } + + public Type GetType(string name) + { + if (name == "typeName") + { + return typeof(bool); + } + + return Type.GetType(name); + } + + public Type GetType(string name, bool throwOnError) + { + throw new NotImplementedException(); + } + + public Type GetType(string name, bool throwOnError, bool ignoreCase) + { + throw new NotImplementedException(); + } + + public List ReferenceAssemblies { get; } = new List(); + + public void ReferenceAssembly(AssemblyName name) + { + ReferenceAssemblies.Add(name); + } + } + + private class NoValidationToolboxItem : ToolboxItem + { + protected override object FilterPropertyValue(string propertyName, object value) + { + // Don't normalize. + return value; + } + + protected override object ValidatePropertyValue(string propertyName, object value) + { + // Don't normalize. + return value; + } + } + + private class NullComponentsToolboxItem : ToolboxItem + { + protected override IComponent[] CreateComponentsCore(IDesignerHost host) + { + return null; + } + } + + [Description("Description")] + [ToolboxBitmap(typeof(ToolboxItemTests), "16x16.bmp")] + [ToolboxItemFilter("System.Drawing.Design.Tests.ToolboxItemTests+ClassWithValidAttributes")] + [ToolboxItemFilter("ClassWithValidAttributes")] + [ToolboxItemFilter("Filter")] + private class ClassWithValidAttributes + { + } + + [Description("Description")] + [ToolboxBitmap(typeof(ToolboxItemTests), "24x16.bmp")] + [ToolboxItemFilter("System.Drawing.Design.Tests.ToolboxItemTests+ClassWithStretchedWidthImage")] + [ToolboxItemFilter("ClassWithStretchedWidthImage")] + [ToolboxItemFilter("Filter")] + private class ClassWithStretchedWidthImage + { + } + + [Description("Description")] + [ToolboxBitmap(typeof(ToolboxItemTests), "16x24.bmp")] + [ToolboxItemFilter("System.Drawing.Design.Tests.ToolboxItemTests+ClassWithStretchedHeightImage")] + [ToolboxItemFilter("ClassWithStretchedHeightImage")] + [ToolboxItemFilter("Filter")] + private class ClassWithStretchedHeightImage + { + } + + [Description("Description")] + [ToolboxBitmap("NoSuchImage")] + [ToolboxItemFilter("System.Drawing.Design.Tests.ToolboxItemTests+ClassWithInvalidImage")] + [ToolboxItemFilter("ClassWithInvalidImage")] + [ToolboxItemFilter("Filter")] + private class ClassWithInvalidImage + { + } + } +}