public void ForbidUndefinedCharacters_RemovesUndefinedChars() { // Arrange // We only allow odd-numbered characters in this test so that // we can validate that we properly merged the two bitmaps together // rather than simply overwriting the target. var bitmap = AllowedCharsBitmap.CreateNew(); for (int i = 1; i <= Char.MaxValue; i += 2) { bitmap.AllowCharacter((char)i); } // Act bitmap.ForbidUndefinedCharacters(); // Assert for (int i = 0; i <= Char.MaxValue; i++) { if (i % 2 == 0) { Assert.False(bitmap.IsCharacterAllowed((char)i)); // these chars were never allowed in the original description } else { Assert.Equal(UnicodeHelpers.IsCharacterDefined((char)i), bitmap.IsCharacterAllowed((char)i)); } } }
public void IsCharacterDefined() { // Arrange bool[] definedChars = ReadListOfDefinedCharacters(); List <string> errors = new List <string>(); // Act & assert for (int i = 0; i <= Char.MaxValue; i++) { bool expected = definedChars[i]; bool actual = UnicodeHelpers.IsCharacterDefined((char)i); if (expected != actual) { errors.Add($"Character U+{i:X4}: expected = {expected}, actual = {actual}"); } } if (errors.Count > 0) { Assert.True(false, String.Join(Environment.NewLine, errors)); } }
public void UrlEncode_AllRangesAllowed_StillEncodesForbiddenChars() { // Arrange UrlEncoder encoder = new UrlEncoder(UnicodeRanges.All); // Act & assert - BMP chars for (int i = 0; i <= 0xFFFF; i++) { string input = new String((char)i, 1); string expected; if (IsSurrogateCodePoint(i)) { expected = "%EF%BF%BD"; // unpaired surrogate -> Unicode replacement char } else { bool mustEncode = true; // RFC 3987, Sec. 2.2 gives the list of allowed chars // (We allow 'ipchar' except for "'", "&", "+", "%", and "=" if (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z') || ('0' <= i && i <= '9')) { mustEncode = false; // ALPHA / DIGIT } else if ((0x00A0 <= i && i <= 0xD7FF) | (0xF900 <= i && i <= 0xFDCF) | (0xFDF0 <= i && i <= 0xFFEF)) { mustEncode = !UnicodeHelpers.IsCharacterDefined((char)i); // 'ucschar' } else { switch (i) { // iunreserved case '-': case '.': case '_': case '~': // isegment-nz-nc case '@': // sub-delims case '!': case '$': case '(': case ')': case '*': case ',': case ';': mustEncode = false; break; } } if (mustEncode) { expected = GetKnownGoodPercentEncodedValue(i); } else { expected = input; // no encoding } } string retVal = encoder.UrlEncode(input); Assert.Equal(expected, retVal); } // Act & assert - astral chars for (int i = 0x10000; i <= 0x10FFFF; i++) { string input = Char.ConvertFromUtf32(i); string expected = GetKnownGoodPercentEncodedValue(i); string retVal = encoder.UrlEncode(input); Assert.Equal(expected, retVal); } }
public void JavaScriptStringEncode_AllRangesAllowed_StillEncodesForbiddenChars_Extended() { // Arrange JavaScriptStringEncoder encoder = new JavaScriptStringEncoder(UnicodeRanges.All); // Act & assert - BMP chars for (int i = 0; i <= 0xFFFF; i++) { string input = new String((char)i, 1); string expected; if (IsSurrogateCodePoint(i)) { expected = "\uFFFD"; // unpaired surrogate -> Unicode replacement char } else { if (input == "\b") { expected = @"\b"; } else if (input == "\t") { expected = @"\t"; } else if (input == "\n") { expected = @"\n"; } else if (input == "\f") { expected = @"\f"; } else if (input == "\r") { expected = @"\r"; } else if (input == "\\") { expected = @"\\"; } else if (input == "/") { expected = @"\/"; } else { bool mustEncode = false; switch (i) { case '<': case '>': case '&': case '\"': case '\'': case '+': mustEncode = true; break; } if (i <= 0x001F || (0x007F <= i && i <= 0x9F)) { mustEncode = true; // control char } else if (!UnicodeHelpers.IsCharacterDefined((char)i)) { mustEncode = true; // undefined (or otherwise disallowed) char } if (mustEncode) { expected = String.Format(CultureInfo.InvariantCulture, @"\u{0:X4}", i); } else { expected = input; // no encoding } } } string retVal = encoder.JavaScriptStringEncode(input); Assert.Equal(expected, retVal); } // Act & assert - astral chars for (int i = 0x10000; i <= 0x10FFFF; i++) { string input = Char.ConvertFromUtf32(i); string expected = String.Format(CultureInfo.InvariantCulture, @"\u{0:X4}\u{1:X4}", (uint)input[0], (uint)input[1]); string retVal = encoder.JavaScriptStringEncode(input); Assert.Equal(expected, retVal); } }
public void HtmlEncode_AllRangesAllowed_StillEncodesForbiddenChars_Extended() { // Arrange HtmlEncoder encoder = new HtmlEncoder(UnicodeRanges.All); // Act & assert - BMP chars for (int i = 0; i <= 0xFFFF; i++) { string input = new String((char)i, 1); string expected; if (IsSurrogateCodePoint(i)) { expected = "\uFFFD"; // unpaired surrogate -> Unicode replacement char } else { if (input == "<") { expected = "<"; } else if (input == ">") { expected = ">"; } else if (input == "&") { expected = "&"; } else if (input == "\"") { expected = """; } else { bool mustEncode = false; if (i == '\'' || i == '+') { mustEncode = true; // apostrophe, plus } else if (i <= 0x001F || (0x007F <= i && i <= 0x9F)) { mustEncode = true; // control char } else if (!UnicodeHelpers.IsCharacterDefined((char)i)) { mustEncode = true; // undefined (or otherwise disallowed) char } if (mustEncode) { expected = String.Format(CultureInfo.InvariantCulture, "&#x{0:X};", i); } else { expected = input; // no encoding } } } string retVal = encoder.HtmlEncode(input); Assert.Equal(expected, retVal); } // Act & assert - astral chars for (int i = 0x10000; i <= 0x10FFFF; i++) { string input = Char.ConvertFromUtf32(i); string expected = String.Format(CultureInfo.InvariantCulture, "&#x{0:X};", i); string retVal = encoder.HtmlEncode(input); Assert.Equal(expected, retVal); } }