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; 6 using System.Collections.Generic; 7 using System.Linq; 8 using System.Text.Encodings.Web; 9 using System.Text.Unicode; 10 using Xunit; 11 12 namespace Microsoft.Framework.WebEncoders 13 { 14 public static class TextEncoderSettingsExtensions 15 { IsCharacterAllowed(this TextEncoderSettings settings, char character)16 public static bool IsCharacterAllowed(this TextEncoderSettings settings, char character) 17 { 18 var bitmap = settings.GetAllowedCharacters(); 19 return bitmap.IsCharacterAllowed(character); 20 } 21 } 22 23 public class TextEncoderSettingsTests 24 { 25 [Fact] Ctor_Parameterless_CreatesEmptyFilter()26 public void Ctor_Parameterless_CreatesEmptyFilter() 27 { 28 var filter = new TextEncoderSettings(); 29 Assert.Equal(0, filter.GetAllowedCodePoints().Count()); 30 } 31 32 [Fact] Ctor_OtherTextEncoderSettingsAsInterface()33 public void Ctor_OtherTextEncoderSettingsAsInterface() 34 { 35 // Arrange 36 var originalFilter = new OddTextEncoderSettings(); 37 38 // Act 39 var newFilter = new TextEncoderSettings(originalFilter); 40 41 // Assert 42 for (int i = 0; i <= Char.MaxValue; i++) 43 { 44 Assert.Equal((i % 2) == 1, newFilter.IsCharacterAllowed((char)i)); 45 } 46 } 47 48 [Fact] Ctor_OtherTextEncoderSettingsAsConcreteType_Clones()49 public void Ctor_OtherTextEncoderSettingsAsConcreteType_Clones() 50 { 51 // Arrange 52 var originalFilter = new TextEncoderSettings(); 53 originalFilter.AllowCharacter('x'); 54 55 // Act 56 var newFilter = new TextEncoderSettings(originalFilter); 57 newFilter.AllowCharacter('y'); 58 59 // Assert 60 Assert.True(originalFilter.IsCharacterAllowed('x')); 61 Assert.False(originalFilter.IsCharacterAllowed('y')); 62 Assert.True(newFilter.IsCharacterAllowed('x')); 63 Assert.True(newFilter.IsCharacterAllowed('y')); 64 } 65 66 [Fact] Ctor_UnicodeRanges()67 public void Ctor_UnicodeRanges() 68 { 69 // Act 70 var filter = new TextEncoderSettings(UnicodeRanges.LatinExtendedA, UnicodeRanges.LatinExtendedC); 71 72 // Assert 73 for (int i = 0; i < 0x0100; i++) 74 { 75 Assert.False(filter.IsCharacterAllowed((char)i)); 76 } 77 for (int i = 0x0100; i <= 0x017F; i++) 78 { 79 Assert.True(filter.IsCharacterAllowed((char)i)); 80 } 81 for (int i = 0x0180; i < 0x2C60; i++) 82 { 83 Assert.False(filter.IsCharacterAllowed((char)i)); 84 } 85 for (int i = 0x2C60; i <= 0x2C7F; i++) 86 { 87 Assert.True(filter.IsCharacterAllowed((char)i)); 88 } 89 for (int i = 0x2C80; i <= Char.MaxValue; i++) 90 { 91 Assert.False(filter.IsCharacterAllowed((char)i)); 92 } 93 } 94 95 [Fact] Ctor_Null_UnicodeRanges()96 public void Ctor_Null_UnicodeRanges() 97 { 98 Assert.Throws<ArgumentNullException>("allowedRanges", () => new TextEncoderSettings(default(UnicodeRange[]))); 99 } 100 101 102 [Fact] Ctor_Null_TextEncoderSettings()103 public void Ctor_Null_TextEncoderSettings() 104 { 105 Assert.Throws<ArgumentNullException>("other", () => new TextEncoderSettings(default(TextEncoderSettings))); 106 } 107 108 [Fact] AllowChar()109 public void AllowChar() 110 { 111 // Arrange 112 var filter = new TextEncoderSettings(); 113 filter.AllowCharacter('\u0100'); 114 115 // Assert 116 Assert.True(filter.IsCharacterAllowed('\u0100')); 117 Assert.False(filter.IsCharacterAllowed('\u0101')); 118 } 119 120 [Fact] AllowChars_Array()121 public void AllowChars_Array() 122 { 123 // Arrange 124 var filter = new TextEncoderSettings(); 125 filter.AllowCharacters('\u0100', '\u0102'); 126 127 // Assert 128 Assert.True(filter.IsCharacterAllowed('\u0100')); 129 Assert.False(filter.IsCharacterAllowed('\u0101')); 130 Assert.True(filter.IsCharacterAllowed('\u0102')); 131 Assert.False(filter.IsCharacterAllowed('\u0103')); 132 } 133 134 [Fact] AllowChars_String()135 public void AllowChars_String() 136 { 137 // Arrange 138 var filter = new TextEncoderSettings(); 139 filter.AllowCharacters('\u0100', '\u0102'); 140 141 // Assert 142 Assert.True(filter.IsCharacterAllowed('\u0100')); 143 Assert.False(filter.IsCharacterAllowed('\u0101')); 144 Assert.True(filter.IsCharacterAllowed('\u0102')); 145 Assert.False(filter.IsCharacterAllowed('\u0103')); 146 } 147 148 149 [Fact] AllowChars_Null()150 public void AllowChars_Null() 151 { 152 TextEncoderSettings filter = new TextEncoderSettings(); 153 Assert.Throws<ArgumentNullException>("characters", () => filter.AllowCharacters(null)); 154 } 155 156 [Fact] AllowFilter()157 public void AllowFilter() 158 { 159 // Arrange 160 var filter = new TextEncoderSettings(UnicodeRanges.BasicLatin); 161 filter.AllowCodePoints(new OddTextEncoderSettings().GetAllowedCodePoints()); 162 163 // Assert 164 for (int i = 0; i <= 0x007F; i++) 165 { 166 Assert.True(filter.IsCharacterAllowed((char)i)); 167 } 168 for (int i = 0x0080; i <= Char.MaxValue; i++) 169 { 170 Assert.Equal((i % 2) == 1, filter.IsCharacterAllowed((char)i)); 171 } 172 } 173 174 [Fact] AllowFilter_NullCodePoints()175 public void AllowFilter_NullCodePoints() 176 { 177 TextEncoderSettings filter = new TextEncoderSettings(UnicodeRanges.BasicLatin); 178 Assert.Throws<ArgumentNullException>("codePoints", () => filter.AllowCodePoints(null)); 179 } 180 181 [Fact] AllowFilter_NonBMP()182 public void AllowFilter_NonBMP() 183 { 184 TextEncoderSettings filter = new TextEncoderSettings(); 185 filter.AllowCodePoints(Enumerable.Range(0x10000, 20)); 186 Assert.Empty(filter.GetAllowedCodePoints()); 187 } 188 189 [Fact] AllowRange()190 public void AllowRange() 191 { 192 // Arrange 193 var filter = new TextEncoderSettings(); 194 filter.AllowRange(UnicodeRanges.LatinExtendedA); 195 196 // Assert 197 for (int i = 0; i < 0x0100; i++) 198 { 199 Assert.False(filter.IsCharacterAllowed((char)i)); 200 } 201 for (int i = 0x0100; i <= 0x017F; i++) 202 { 203 Assert.True(filter.IsCharacterAllowed((char)i)); 204 } 205 for (int i = 0x0180; i <= Char.MaxValue; i++) 206 { 207 Assert.False(filter.IsCharacterAllowed((char)i)); 208 } 209 } 210 211 [Fact] AllowRange_NullRange()212 public void AllowRange_NullRange() 213 { 214 TextEncoderSettings filter = new TextEncoderSettings(); 215 Assert.Throws<ArgumentNullException>("range", () => filter.AllowRange(null)); 216 } 217 218 [Fact] AllowRanges()219 public void AllowRanges() 220 { 221 // Arrange 222 var filter = new TextEncoderSettings(); 223 filter.AllowRanges(UnicodeRanges.LatinExtendedA, UnicodeRanges.LatinExtendedC); 224 225 // Assert 226 for (int i = 0; i < 0x0100; i++) 227 { 228 Assert.False(filter.IsCharacterAllowed((char)i)); 229 } 230 for (int i = 0x0100; i <= 0x017F; i++) 231 { 232 Assert.True(filter.IsCharacterAllowed((char)i)); 233 } 234 for (int i = 0x0180; i < 0x2C60; i++) 235 { 236 Assert.False(filter.IsCharacterAllowed((char)i)); 237 } 238 for (int i = 0x2C60; i <= 0x2C7F; i++) 239 { 240 Assert.True(filter.IsCharacterAllowed((char)i)); 241 } 242 for (int i = 0x2C80; i <= Char.MaxValue; i++) 243 { 244 Assert.False(filter.IsCharacterAllowed((char)i)); 245 } 246 } 247 248 [Fact] AllowRanges_NullRange()249 public void AllowRanges_NullRange() 250 { 251 TextEncoderSettings filter = new TextEncoderSettings(); 252 Assert.Throws<ArgumentNullException>("ranges", () => filter.AllowRanges(null)); 253 } 254 255 [Fact] Clear()256 public void Clear() 257 { 258 // Arrange 259 var filter = new TextEncoderSettings(); 260 for (int i = 1; i <= Char.MaxValue; i++) 261 { 262 filter.AllowCharacter((char)i); 263 } 264 265 // Act 266 filter.Clear(); 267 268 // Assert 269 for (int i = 0; i <= Char.MaxValue; i++) 270 { 271 Assert.False(filter.IsCharacterAllowed((char)i)); 272 } 273 } 274 275 [Fact] ForbidChar()276 public void ForbidChar() 277 { 278 // Arrange 279 var filter = new TextEncoderSettings(UnicodeRanges.BasicLatin); 280 filter.ForbidCharacter('x'); 281 282 // Assert 283 Assert.True(filter.IsCharacterAllowed('w')); 284 Assert.False(filter.IsCharacterAllowed('x')); 285 Assert.True(filter.IsCharacterAllowed('y')); 286 Assert.True(filter.IsCharacterAllowed('z')); 287 } 288 289 [Fact] ForbidChars_Array()290 public void ForbidChars_Array() 291 { 292 // Arrange 293 var filter = new TextEncoderSettings(UnicodeRanges.BasicLatin); 294 filter.ForbidCharacters('x', 'z'); 295 296 // Assert 297 Assert.True(filter.IsCharacterAllowed('w')); 298 Assert.False(filter.IsCharacterAllowed('x')); 299 Assert.True(filter.IsCharacterAllowed('y')); 300 Assert.False(filter.IsCharacterAllowed('z')); 301 } 302 303 [Fact] ForbidChars_String()304 public void ForbidChars_String() 305 { 306 // Arrange 307 var filter = new TextEncoderSettings(UnicodeRanges.BasicLatin); 308 filter.ForbidCharacters('x', 'z'); 309 310 // Assert 311 Assert.True(filter.IsCharacterAllowed('w')); 312 Assert.False(filter.IsCharacterAllowed('x')); 313 Assert.True(filter.IsCharacterAllowed('y')); 314 Assert.False(filter.IsCharacterAllowed('z')); 315 } 316 317 318 [Fact] ForbidChars_Null()319 public void ForbidChars_Null() 320 { 321 TextEncoderSettings filter = new TextEncoderSettings(UnicodeRanges.BasicLatin); 322 Assert.Throws<ArgumentNullException>("characters", () => filter.ForbidCharacters(null)); 323 } 324 325 [Fact] ForbidRange()326 public void ForbidRange() 327 { 328 // Arrange 329 var filter = new TextEncoderSettings(new OddTextEncoderSettings()); 330 filter.ForbidRange(UnicodeRanges.Specials); 331 332 // Assert 333 for (int i = 0; i <= 0xFFEF; i++) 334 { 335 Assert.Equal((i % 2) == 1, filter.IsCharacterAllowed((char)i)); 336 } 337 for (int i = 0xFFF0; i <= Char.MaxValue; i++) 338 { 339 Assert.False(filter.IsCharacterAllowed((char)i)); 340 } 341 } 342 343 [Fact] ForbidRange_Null()344 public void ForbidRange_Null() 345 { 346 TextEncoderSettings filter = new TextEncoderSettings(); 347 Assert.Throws<ArgumentNullException>("range", () => filter.ForbidRange(null)); 348 } 349 350 [Fact] ForbidRanges()351 public void ForbidRanges() 352 { 353 // Arrange 354 var filter = new TextEncoderSettings(new OddTextEncoderSettings()); 355 filter.ForbidRanges(UnicodeRanges.BasicLatin, UnicodeRanges.Specials); 356 357 // Assert 358 for (int i = 0; i <= 0x007F; i++) 359 { 360 Assert.False(filter.IsCharacterAllowed((char)i)); 361 } 362 for (int i = 0x0080; i <= 0xFFEF; i++) 363 { 364 Assert.Equal((i % 2) == 1, filter.IsCharacterAllowed((char)i)); 365 } 366 for (int i = 0xFFF0; i <= Char.MaxValue; i++) 367 { 368 Assert.False(filter.IsCharacterAllowed((char)i)); 369 } 370 } 371 372 [Fact] ForbidRanges_Null()373 public void ForbidRanges_Null() 374 { 375 TextEncoderSettings filter = new TextEncoderSettings(new OddTextEncoderSettings()); 376 Assert.Throws<ArgumentNullException>("ranges", () => filter.ForbidRanges(null)); 377 } 378 379 [Fact] GetAllowedCodePoints()380 public void GetAllowedCodePoints() 381 { 382 // Arrange 383 var expected = Enumerable.Range(UnicodeRanges.BasicLatin.FirstCodePoint, UnicodeRanges.BasicLatin.Length) 384 .Concat(Enumerable.Range(UnicodeRanges.Specials.FirstCodePoint, UnicodeRanges.Specials.Length)) 385 .Except(new int[] { 'x' }) 386 .OrderBy(i => i) 387 .ToArray(); 388 389 var filter = new TextEncoderSettings(UnicodeRanges.BasicLatin, UnicodeRanges.Specials); 390 filter.ForbidCharacter('x'); 391 392 // Act 393 var retVal = filter.GetAllowedCodePoints().OrderBy(i => i).ToArray(); 394 395 // Assert 396 Assert.Equal<int>(expected, retVal); 397 } 398 399 // a code point filter which allows only odd code points through 400 private sealed class OddTextEncoderSettings : TextEncoderSettings 401 { GetAllowedCodePoints()402 public override IEnumerable<int> GetAllowedCodePoints() 403 { 404 for (int i = 1; i <= Char.MaxValue; i += 2) 405 { 406 yield return i; 407 } 408 } 409 } 410 } 411 } 412