1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Collections.Generic; 6 using System.Drawing; 7 using System.Globalization; 8 using System.Linq; 9 using Xunit; 10 11 namespace System.ComponentModel.TypeConverterTests 12 { 13 public class RectangleConverterTests : StringTypeConverterTestBase<Rectangle> 14 { 15 protected override TypeConverter Converter { get; } = new RectangleConverter(); 16 protected override bool StandardValuesSupported { get; } = false; 17 protected override bool StandardValuesExclusive { get; } = false; 18 protected override Rectangle Default => new Rectangle(0, 0, 100, 100); 19 protected override bool CreateInstanceSupported { get; } = true; 20 protected override bool IsGetPropertiesSupported { get; } = true; 21 22 protected override IEnumerable<Tuple<Rectangle, Dictionary<string, object>>> CreateInstancePairs { 23 get 24 { 25 yield return Tuple.Create(new Rectangle(10, 10, 20, 30), new Dictionary<string, object> 26 { 27 ["X"] = 10, 28 ["Y"] = 10, 29 ["Width"] = 20, 30 ["Height"] = 30, 31 }); 32 yield return Tuple.Create(new Rectangle(-10, -10, 20, 30), new Dictionary<string, object> 33 { 34 ["X"] = -10, 35 ["Y"] = -10, 36 ["Width"] = 20, 37 ["Height"] = 30, 38 }); 39 } 40 } 41 42 [Theory] 43 [InlineData(typeof(string))] CanConvertFromTrue(Type type)44 public void CanConvertFromTrue(Type type) 45 { 46 CanConvertFrom(type); 47 } 48 49 [Theory] 50 [InlineData(typeof(Rectangle))] 51 [InlineData(typeof(RectangleF))] 52 [InlineData(typeof(Point))] 53 [InlineData(typeof(PointF))] 54 [InlineData(typeof(Color))] 55 [InlineData(typeof(Size))] 56 [InlineData(typeof(SizeF))] 57 [InlineData(typeof(object))] 58 [InlineData(typeof(int))] CanConvertFromFalse(Type type)59 public void CanConvertFromFalse(Type type) 60 { 61 CannotConvertFrom(type); 62 } 63 64 [Theory] 65 [InlineData(typeof(string))] CanConvertToTrue(Type type)66 public void CanConvertToTrue(Type type) 67 { 68 CanConvertTo(type); 69 } 70 71 [Theory] 72 [InlineData(typeof(Rectangle))] 73 [InlineData(typeof(RectangleF))] 74 [InlineData(typeof(Point))] 75 [InlineData(typeof(PointF))] 76 [InlineData(typeof(Color))] 77 [InlineData(typeof(Size))] 78 [InlineData(typeof(SizeF))] 79 [InlineData(typeof(object))] 80 [InlineData(typeof(int))] CanConvertToFalse(Type type)81 public void CanConvertToFalse(Type type) 82 { 83 CannotConvertTo(type); 84 } 85 86 public static IEnumerable<object[]> RectangleData => 87 new[] 88 { 89 new object[] {0, 0, 0, 0}, 90 new object[] {1, 1, 1, 1}, 91 new object[] {-1, 1, 1, 1}, 92 new object[] {1, -1, 1, 1}, 93 new object[] {-1, -1, 1, 1}, 94 new object[] {int.MaxValue, int.MaxValue, int.MaxValue, int.MaxValue}, 95 new object[] {int.MinValue, int.MaxValue, int.MaxValue, int.MaxValue}, 96 new object[] {int.MaxValue, int.MinValue, int.MaxValue, int.MaxValue}, 97 new object[] {int.MinValue, int.MinValue, int.MaxValue, int.MaxValue}, 98 }; 99 100 [Theory] 101 [MemberData(nameof(RectangleData))] ConvertFrom(int x, int y, int width, int height)102 public void ConvertFrom(int x, int y, int width, int height) 103 { 104 TestConvertFromString(new Rectangle(x, y, width, height), $"{x}, {y}, {width}, {height}"); 105 } 106 107 [Theory] 108 [InlineData("10, 10")] 109 [InlineData("1, 1, 1, 1, 1")] ConvertFrom_ArgumentException(string value)110 public void ConvertFrom_ArgumentException(string value) 111 { 112 ConvertFromThrowsArgumentExceptionForString(value); 113 } 114 115 [Fact] ConvertFrom_Invalid()116 public void ConvertFrom_Invalid() 117 { 118 ConvertFromThrowsFormatInnerExceptionForString("*1, 1, 1, 1"); 119 } 120 121 public static IEnumerable<object[]> ConvertFrom_NotSupportedData => 122 new[] 123 { 124 new object[] {new Point(10, 10)}, 125 new object[] {new PointF(10, 10)}, 126 new object[] {new Size(10, 10)}, 127 new object[] {new SizeF(10, 10)}, 128 new object[] {new object()}, 129 new object[] {1001}, 130 }; 131 132 [Theory] 133 [MemberData(nameof(ConvertFrom_NotSupportedData))] ConvertFrom_NotSupported(object value)134 public void ConvertFrom_NotSupported(object value) 135 { 136 ConvertFromThrowsNotSupportedFor(value); 137 } 138 139 [Theory] 140 [MemberData(nameof(RectangleData))] ConvertTo(int x, int y, int width, int height)141 public void ConvertTo(int x, int y, int width, int height) 142 { 143 TestConvertToString(new Rectangle(x, y, width, height), $"{x}, {y}, {width}, {height}"); 144 } 145 146 [Theory] 147 [InlineData(typeof(Size))] 148 [InlineData(typeof(SizeF))] 149 [InlineData(typeof(Point))] 150 [InlineData(typeof(PointF))] 151 [InlineData(typeof(object))] 152 [InlineData(typeof(int))] ConvertTo_NotSupportedException(Type type)153 public void ConvertTo_NotSupportedException(Type type) 154 { 155 ConvertToThrowsNotSupportedForType(type); 156 } 157 158 [Fact] CreateInstance_CaseSensitive()159 public void CreateInstance_CaseSensitive() 160 { 161 AssertExtensions.Throws<ArgumentException>(null, () => 162 { 163 Converter.CreateInstance(null, new Dictionary<string, object> 164 { 165 ["x"] = -10, 166 ["Y"] = -10, 167 ["Width"] = 20, 168 ["Height"] = 30, 169 }); 170 }); 171 } 172 173 [Fact] TestGetProperties()174 public void TestGetProperties() 175 { 176 var rect = new Rectangle(10, 10, 20, 30); 177 var propsColl = Converter.GetProperties(rect); 178 Assert.Equal(4, propsColl.Count); 179 Assert.Equal(rect.X, propsColl["X"].GetValue(rect)); 180 Assert.Equal(rect.Y, propsColl["Y"].GetValue(rect)); 181 Assert.Equal(rect.Width, propsColl["Width"].GetValue(rect)); 182 Assert.Equal(rect.Height, propsColl["Height"].GetValue(rect)); 183 184 rect = new Rectangle(-10, -10, 20, 30); 185 propsColl = Converter.GetProperties(null, rect); 186 Assert.Equal(4, propsColl.Count); 187 Assert.Equal(rect.X, propsColl["X"].GetValue(rect)); 188 Assert.Equal(rect.Y, propsColl["Y"].GetValue(rect)); 189 Assert.Equal(rect.Width, propsColl["Width"].GetValue(rect)); 190 Assert.Equal(rect.Height, propsColl["Height"].GetValue(rect)); 191 192 rect = new Rectangle(10, 10, 20, 30); 193 propsColl = Converter.GetProperties(null, rect, null); 194 Assert.Equal(11, propsColl.Count); 195 Assert.Equal(rect.X, propsColl["X"].GetValue(rect)); 196 Assert.Equal(rect.Y, propsColl["Y"].GetValue(rect)); 197 Assert.Equal(rect.Width, propsColl["Width"].GetValue(rect)); 198 Assert.Equal(rect.Height, propsColl["Height"].GetValue(rect)); 199 Assert.Equal(rect.IsEmpty, propsColl["IsEmpty"].GetValue(rect)); 200 201 Assert.Equal(rect.Top, propsColl["Top"].GetValue(rect)); 202 Assert.Equal(rect.Bottom, propsColl["Bottom"].GetValue(rect)); 203 Assert.Equal(rect.Left, propsColl["Left"].GetValue(rect)); 204 Assert.Equal(rect.Right, propsColl["Right"].GetValue(rect)); 205 Assert.Equal(rect.Location, propsColl["Location"].GetValue(rect)); 206 Assert.Equal(rect.Size, propsColl["Size"].GetValue(rect)); 207 Assert.Equal(rect.IsEmpty, propsColl["IsEmpty"].GetValue(rect)); 208 209 // Pick an attibute that cannot be applied to properties to make sure everything gets filtered 210 propsColl = Converter.GetProperties(null, new Rectangle(10, 10, 20, 30), new Attribute[] { new System.Reflection.AssemblyCopyrightAttribute("")}); 211 Assert.Equal(0, propsColl.Count); 212 } 213 214 [Theory] 215 [MemberData(nameof(RectangleData))] ConvertFromInvariantString(int x, int y, int width, int height)216 public void ConvertFromInvariantString(int x, int y, int width, int height) 217 { 218 var rect = (Rectangle)Converter.ConvertFromInvariantString($"{x}, {y}, {width}, {height}"); 219 Assert.Equal(x, rect.X); 220 Assert.Equal(y, rect.Y); 221 Assert.Equal(width, rect.Width); 222 Assert.Equal(height, rect.Height); 223 } 224 225 [Fact] ConvertFromInvariantString_ArgumentException()226 public void ConvertFromInvariantString_ArgumentException() 227 { 228 ConvertFromInvariantStringThrowsArgumentException("1, 2, 3"); 229 } 230 231 [Fact] ConvertFromInvariantString_FormatException()232 public void ConvertFromInvariantString_FormatException() 233 { 234 ConvertFromInvariantStringThrowsFormatInnerException("hello"); 235 } 236 237 [Theory] 238 [MemberData(nameof(RectangleData))] ConvertFromString(int x, int y, int width, int height)239 public void ConvertFromString(int x, int y, int width, int height) 240 { 241 var rect = 242 (Rectangle)Converter.ConvertFromString(string.Format("{0}{4} {1}{4} {2}{4} {3}", x, y, width, height, 243 CultureInfo.CurrentCulture.TextInfo.ListSeparator)); 244 Assert.Equal(x, rect.X); 245 Assert.Equal(y, rect.Y); 246 Assert.Equal(width, rect.Width); 247 Assert.Equal(height, rect.Height); 248 } 249 250 [Fact] ConvertFromString_ArgumentException()251 public void ConvertFromString_ArgumentException() 252 { 253 ConvertFromStringThrowsArgumentException(string.Format("1{0} 1{0} 1{0} 1{0} 1", 254 CultureInfo.CurrentCulture.TextInfo.ListSeparator)); 255 } 256 257 [Fact] ConvertFromString_FormatException()258 public void ConvertFromString_FormatException() 259 { 260 ConvertFromStringThrowsFormatInnerException("hello"); 261 } 262 263 [Theory] 264 [MemberData(nameof(RectangleData))] ConvertToInvariantString(int x, int y, int width, int height)265 public void ConvertToInvariantString(int x, int y, int width, int height) 266 { 267 var str = Converter.ConvertToInvariantString(new Rectangle(x, y, width, height)); 268 Assert.Equal($"{x}, {y}, {width}, {height}", str); 269 } 270 271 [Theory] 272 [MemberData(nameof(RectangleData))] ConvertToString(int x, int y, int width, int height)273 public void ConvertToString(int x, int y, int width, int height) 274 { 275 var str = Converter.ConvertToString(new Rectangle(x, y, width, height)); 276 Assert.Equal( 277 string.Format("{0}{4} {1}{4} {2}{4} {3}", x, y, width, height, 278 CultureInfo.CurrentCulture.TextInfo.ListSeparator), str); 279 } 280 } 281 } 282