From 295951348c8bed9173c4b9196960f885dba26453 Mon Sep 17 00:00:00 2001 From: Wukuyon Date: Sat, 18 Oct 2025 17:11:58 -0600 Subject: [PATCH] Add boundary case tests for test_utf8_simd_decode These tests were generated from Node.js and match the WHATWG Encoding Specification's behavior (substitution of maximal subparts). --- kitty_tests/parser.py | 299 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 298 insertions(+), 1 deletion(-) diff --git a/kitty_tests/parser.py b/kitty_tests/parser.py index 468df32ff..b65e02b80 100644 --- a/kitty_tests/parser.py +++ b/kitty_tests/parser.py @@ -288,6 +288,7 @@ class TestParser(BaseTest): pb(b'"\xe0\xa0"', '"\ufffd"') pb(b'"\xf0\x9f\x98"', '"\ufffd"') pb(b'"\xef\x93\x94\x95"', '"\uf4d4\ufffd"') + # Lone continuation bytes with no leading starts pb(b'"\xbf"', '"\ufffd"') pb(b'"\x80"', '"\ufffd"') @@ -340,9 +341,305 @@ class TestParser(BaseTest): # Low surrogate code point pb(b'"\xed\xb0\x80"', '"\ufffd\ufffd\ufffd"') - # Too large first codepoint + # Too large starter byte pb(b'"\xff\x80\x80\x80"', '"\ufffd\ufffd\ufffd\ufffd"') + # The following boundary cases come from the table of well-formed UTF-8 byte sequences + # `_. + # For continuation bytes, both 0xC0 and 0xC2 are tested as values that exceed the valid maximum. + # This is because 0xC0 is an invalid starter byte, but 0xC2 is also a starter byte for 2-byte sequences. + # simd-string-impl.h prefers classifying bytes as starter bytes when possible (e.g., in "\xf0\x90\xc2\x80"). + # The tests need to check that simd-string-impl.h correctly detects + # starter bytes that are actually invalid continution bytes, like 0xC2. + + # Boundary cases: 2-byte sequences + pb(b'"\xc1\x7f"', '"\ufffd\x7f"') + pb(b'"\xc1\x80"', '"\ufffd\ufffd"') + pb(b'"\xc1\xbf"', '"\ufffd\ufffd"') + pb(b'"\xc1\xc0"', '"\ufffd\ufffd"') + pb(b'"\xc1\xc2"', '"\ufffd\ufffd"') + pb(b'"\xc2\x7f"', '"\ufffd\x7f"') + pb(b'"\xc2\x80"', '"\x80"') + pb(b'"\xc2\xbf"', '"\xbf"') + pb(b'"\xc2\xc0"', '"\ufffd\ufffd"') + pb(b'"\xc2\xc2"', '"\ufffd\ufffd"') + pb(b'"\xdf\x7f"', '"\ufffd\x7f"') + pb(b'"\xdf\x80"', '"\u07c0"') + pb(b'"\xdf\xbf"', '"\u07ff"') + pb(b'"\xdf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xdf\xc2"', '"\ufffd\ufffd"') + + # Boundary cases: 3-byte sequences starting with 0xE0 + pb(b'"\xe0\x9f\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xe0\xa0\x7f"', '"\ufffd\x7f"') + pb(b'"\xe0\xa0\x80"', '"\u0800"') + pb(b'"\xe0\xa0\xbf"', '"\u083f"') + pb(b'"\xe0\xa0\xc0"', '"\ufffd\ufffd"') + pb(b'"\xe0\xa0\xc2"', '"\ufffd\ufffd"') + pb(b'"\xe0\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xe0\xbf\x80"', '"\u0fc0"') + pb(b'"\xe0\xbf\xbf"', '"\u0fff"') + pb(b'"\xe0\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xe0\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xe0\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xe0\xc2\x80"', '"\ufffd\x80"') + + # Boundary cases: 3-byte sequences starting with 0xE1..0xEC + pb(b'"\xe1\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xe1\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xe1\x80\x80"', '"\u1000"') + pb(b'"\xe1\x80\xbf"', '"\u103f"') + pb(b'"\xe1\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xe1\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xe1\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xe1\xbf\x80"', '"\u1fc0"') + pb(b'"\xe1\xbf\xbf"', '"\u1fff"') + pb(b'"\xe1\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xe1\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xe1\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xe1\xc2\x80"', '"\ufffd\x80"') + pb(b'"\xec\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xec\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xec\x80\x80"', '"\uc000"') + pb(b'"\xec\x80\xbf"', '"\uc03f"') + pb(b'"\xec\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xec\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xec\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xec\xbf\x80"', '"\ucfc0"') + pb(b'"\xec\xbf\xbf"', '"\ucfff"') + pb(b'"\xec\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xec\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xec\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xec\xc2\x80"', '"\ufffd\x80"') + + # Boundary cases: 3-byte sequences starting with 0xED + pb(b'"\xed\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xed\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xed\x80\x80"', '"\ud000"') + pb(b'"\xed\x80\xbf"', '"\ud03f"') + pb(b'"\xed\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xed\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xed\x9f\x7f"', '"\ufffd\x7f"') + pb(b'"\xed\x9f\x80"', '"\ud7c0"') + pb(b'"\xed\x9f\xbf"', '"\ud7ff"') + pb(b'"\xed\x9f\xc0"', '"\ufffd\ufffd"') + pb(b'"\xed\x9f\xc2"', '"\ufffd\ufffd"') + + # Boundary cases: 3-byte sequences starting with 0xEE..0xEF + pb(b'"\xed\xa0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xee\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xee\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xee\x80\x80"', '"\ue000"') + pb(b'"\xee\x80\xbf"', '"\ue03f"') + pb(b'"\xee\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xee\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xee\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xee\xbf\x80"', '"\uefc0"') + pb(b'"\xee\xbf\xbf"', '"\uefff"') + pb(b'"\xee\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xee\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xee\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xee\xc2\x80"', '"\ufffd\x80"') + pb(b'"\xef\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xef\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xef\x80\x80"', '"\uf000"') + pb(b'"\xef\x80\xbf"', '"\uf03f"') + pb(b'"\xef\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xef\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xef\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xef\xbf\x80"', '"\uffc0"') + pb(b'"\xef\xbf\xbf"', '"\uffff"') + pb(b'"\xef\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xef\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xef\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xef\xc2\x80"', '"\ufffd\x80"') + + # Boundary cases: 4-byte sequences starting with 0xF0 + pb(b'"\xf0\x8f\x80\x80"', '"\ufffd\ufffd\ufffd\ufffd"') + pb(b'"\xf0\x90\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xf0\x90\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xf0\x90\x80\x80"', '"\U00010000"') + pb(b'"\xf0\x90\x80\xbf"', '"\U0001003f"') + pb(b'"\xf0\x90\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf0\x90\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf0\x90\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xf0\x90\xbf\x80"', '"\U00010fc0"') + pb(b'"\xf0\x90\xbf\xbf"', '"\U00010fff"') + pb(b'"\xf0\x90\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf0\x90\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf0\x90\xc0\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf0\x90\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf0\x90\xc0\xbf"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf0\x90\xc0\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf0\x90\xc0\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf0\x90\xc2\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf0\x90\xc2\x80"', '"\ufffd\x80"') + pb(b'"\xf0\x90\xc2\xbf"', '"\ufffd\xbf"') + pb(b'"\xf0\x90\xc2\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf0\x90\xc2\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf0\xbf\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xf0\xbf\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xf0\xbf\x80\x80"', '"\U0003f000"') + pb(b'"\xf0\xbf\x80\xbf"', '"\U0003f03f"') + pb(b'"\xf0\xbf\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf0\xbf\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf0\xbf\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xf0\xbf\xbf\x80"', '"\U0003ffc0"') + pb(b'"\xf0\xbf\xbf\xbf"', '"\U0003ffff"') + pb(b'"\xf0\xbf\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf0\xbf\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf0\xbf\xc0\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf0\xbf\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf0\xbf\xc0\xbf"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf0\xbf\xc0\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf0\xbf\xc0\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf0\xbf\xc2\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf0\xbf\xc2\x80"', '"\ufffd\x80"') + pb(b'"\xf0\xbf\xc2\xbf"', '"\ufffd\xbf"') + pb(b'"\xf0\xbf\xc2\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf0\xbf\xc2\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf0\xc0\x80\x80"', '"\ufffd\ufffd\ufffd\ufffd"') + + # Boundary cases: 4-byte sequences starting with 0xF1..0xF3 + pb(b'"\xf1\x7f\x80\x80"', '"\ufffd\x7f\ufffd\ufffd"') + pb(b'"\xf1\x80\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xf1\x80\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xf1\x80\x80\x80"', '"\U00040000"') + pb(b'"\xf1\x80\x80\xbf"', '"\U0004003f"') + pb(b'"\xf1\x80\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf1\x80\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf1\x80\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xf1\x80\xbf\x80"', '"\U00040fc0"') + pb(b'"\xf1\x80\xbf\xbf"', '"\U00040fff"') + pb(b'"\xf1\x80\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf1\x80\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf1\x80\xc0\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf1\x80\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf1\x80\xc0\xbf"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf1\x80\xc0\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf1\x80\xc2\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf1\x80\xc2\x80"', '"\ufffd\x80"') + pb(b'"\xf1\x80\xc2\xbf"', '"\ufffd\xbf"') + pb(b'"\xf1\x80\xc2\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf1\xbf\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xf1\xbf\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xf1\xbf\x80\x80"', '"\U0007f000"') + pb(b'"\xf1\xbf\x80\xbf"', '"\U0007f03f"') + pb(b'"\xf1\xbf\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf1\xbf\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf1\xbf\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xf1\xbf\xbf\x80"', '"\U0007ffc0"') + pb(b'"\xf1\xbf\xbf\xbf"', '"\U0007ffff"') + pb(b'"\xf1\xbf\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf1\xbf\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf1\xbf\xc0\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf1\xbf\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf1\xbf\xc0\xbf"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf1\xbf\xc0\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf1\xbf\xc0\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf1\xbf\xc2\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf1\xbf\xc2\x80"', '"\ufffd\x80"') + pb(b'"\xf1\xbf\xc2\xbf"', '"\ufffd\xbf"') + pb(b'"\xf1\xbf\xc2\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf1\xbf\xc2\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf1\xc0\x80\x80"', '"\ufffd\ufffd\ufffd\ufffd"') + pb(b'"\xf1\xc2\x80\x80"', '"\ufffd\x80\ufffd"') + pb(b'"\xf3\x7f\x80\x80"', '"\ufffd\x7f\ufffd\ufffd"') + pb(b'"\xf3\x80\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xf3\x80\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xf3\x80\x80\x80"', '"\U000c0000"') + pb(b'"\xf3\x80\x80\xbf"', '"\U000c003f"') + pb(b'"\xf3\x80\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf3\x80\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf3\x80\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xf3\x80\xbf\x80"', '"\U000c0fc0"') + pb(b'"\xf3\x80\xbf\xbf"', '"\U000c0fff"') + pb(b'"\xf3\x80\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf3\x80\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf3\x80\xc0\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf3\x80\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf3\x80\xc0\xbf"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf3\x80\xc0\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf3\x80\xc0\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf3\x80\xc2\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf3\x80\xc2\x80"', '"\ufffd\x80"') + pb(b'"\xf3\x80\xc2\xbf"', '"\ufffd\xbf"') + pb(b'"\xf3\x80\xc2\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf3\x80\xc2\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf3\xbf\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xf3\xbf\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xf3\xbf\x80\x80"', '"\U000ff000"') + pb(b'"\xf3\xbf\x80\xbf"', '"\U000ff03f"') + pb(b'"\xf3\xbf\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf3\xbf\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf3\xbf\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xf3\xbf\xbf\x80"', '"\U000fffc0"') + pb(b'"\xf3\xbf\xbf\xbf"', '"\U000fffff"') + pb(b'"\xf3\xbf\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf3\xbf\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf3\xbf\xc0\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf3\xbf\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf3\xbf\xc0\xbf"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf3\xbf\xc0\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf3\xbf\xc0\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf3\xbf\xc2\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf3\xbf\xc2\x80"', '"\ufffd\x80"') + pb(b'"\xf3\xbf\xc2\xbf"', '"\ufffd\xbf"') + pb(b'"\xf3\xbf\xc2\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf3\xbf\xc2\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf3\xc0\x80\x80"', '"\ufffd\ufffd\ufffd\ufffd"') + pb(b'"\xf3\xc2\x80\x80"', '"\ufffd\x80\ufffd"') + + # Boundary cases: 4-byte sequences starting with 0xF4 + pb(b'"\xf4\x7f\x80\x80"', '"\ufffd\x7f\ufffd\ufffd"') + pb(b'"\xf4\x80\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xf4\x80\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xf4\x80\x80\x80"', '"\U00100000"') + pb(b'"\xf4\x80\x80\xbf"', '"\U0010003f"') + pb(b'"\xf4\x80\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf4\x80\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf4\x80\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xf4\x80\xbf\x80"', '"\U00100fc0"') + pb(b'"\xf4\x80\xbf\xbf"', '"\U00100fff"') + pb(b'"\xf4\x80\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf4\x80\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf4\x80\xc0\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf4\x80\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf4\x80\xc0\xbf"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf4\x80\xc0\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf4\x80\xc0\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf4\x80\xc2\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf4\x80\xc2\x80"', '"\ufffd\x80"') + pb(b'"\xf4\x80\xc2\xbf"', '"\ufffd\xbf"') + pb(b'"\xf4\x80\xc2\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf4\x80\xc2\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf4\x8f\x7f\x80"', '"\ufffd\x7f\ufffd"') + pb(b'"\xf4\x8f\x80\x7f"', '"\ufffd\x7f"') + pb(b'"\xf4\x8f\x80\x80"', '"\U0010f000"') + pb(b'"\xf4\x8f\x80\xbf"', '"\U0010f03f"') + pb(b'"\xf4\x8f\x80\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf4\x8f\x80\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf4\x8f\xbf\x7f"', '"\ufffd\x7f"') + pb(b'"\xf4\x8f\xbf\x80"', '"\U0010ffc0"') + pb(b'"\xf4\x8f\xbf\xbf"', '"\U0010ffff"') + pb(b'"\xf4\x8f\xbf\xc0"', '"\ufffd\ufffd"') + pb(b'"\xf4\x8f\xbf\xc2"', '"\ufffd\ufffd"') + pb(b'"\xf4\x8f\xc0\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf4\x8f\xc0\x80"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf4\x8f\xc0\xbf"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf4\x8f\xc0\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf4\x8f\xc0\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf4\x8f\xc2\x7f"', '"\ufffd\ufffd\x7f"') + pb(b'"\xf4\x8f\xc2\x80"', '"\ufffd\x80"') + pb(b'"\xf4\x8f\xc2\xbf"', '"\ufffd\xbf"') + pb(b'"\xf4\x8f\xc2\xc0"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf4\x8f\xc2\xc2"', '"\ufffd\ufffd\ufffd"') + pb(b'"\xf4\x90\x80\x80"', '"\ufffd\ufffd\ufffd\ufffd"') + pb(b'"\xf5\x80\x80\x80"', '"\ufffd\ufffd\ufffd\ufffd"') + + # Boundary case: too large codepoint (> U+10FFFF) + pb(b'"\xf5\x80\x80\x80"', '"\ufffd\ufffd\ufffd\ufffd"') + def test_find_either_of_two_bytes(self): sizes = []