github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/testdata/lua-5.3.3-tests/utf8.lua (about) 1 -- $Id: utf8.lua,v 1.11 2014/12/26 17:20:53 roberto Exp $ 2 3 print "testing UTF-8 library" 4 5 local utf8 = require'utf8' 6 7 8 local function checkerror (msg, f, ...) 9 local s, err = pcall(f, ...) 10 assert(not s and string.find(err, msg)) 11 end 12 13 14 local function len (s) 15 return #string.gsub(s, "[\x80-\xBF]", "") 16 end 17 18 19 local justone = "^" .. utf8.charpattern .. "$" 20 21 -- 't' is the list of codepoints of 's' 22 local function checksyntax (s, t) 23 local ts = {"return '"} 24 for i = 1, #t do ts[i + 1] = string.format("\\u{%x}", t[i]) end 25 ts[#t + 2] = "'" 26 ts = table.concat(ts) 27 assert(assert(load(ts))() == s) 28 end 29 30 assert(utf8.offset("alo", 5) == nil) 31 assert(utf8.offset("alo", -4) == nil) 32 33 -- 't' is the list of codepoints of 's' 34 local function check (s, t) 35 local l = utf8.len(s) 36 assert(#t == l and len(s) == l) 37 assert(utf8.char(table.unpack(t)) == s) 38 39 assert(utf8.offset(s, 0) == 1) 40 41 checksyntax(s, t) 42 43 local t1 = {utf8.codepoint(s, 1, -1)} 44 assert(#t == #t1) 45 for i = 1, #t do assert(t[i] == t1[i]) end 46 47 for i = 1, l do 48 local pi = utf8.offset(s, i) -- position of i-th char 49 local pi1 = utf8.offset(s, 2, pi) -- position of next char 50 assert(string.find(string.sub(s, pi, pi1 - 1), justone)) 51 assert(utf8.offset(s, -1, pi1) == pi) 52 assert(utf8.offset(s, i - l - 1) == pi) 53 assert(pi1 - pi == #utf8.char(utf8.codepoint(s, pi))) 54 for j = pi, pi1 - 1 do 55 assert(utf8.offset(s, 0, j) == pi) 56 end 57 for j = pi + 1, pi1 - 1 do 58 assert(not utf8.len(s, j)) 59 end 60 assert(utf8.len(s, pi, pi) == 1) 61 assert(utf8.len(s, pi, pi1 - 1) == 1) 62 assert(utf8.len(s, pi) == l - i + 1) 63 assert(utf8.len(s, pi1) == l - i) 64 assert(utf8.len(s, 1, pi) == i) 65 end 66 67 local i = 0 68 for p, c in utf8.codes(s) do 69 i = i + 1 70 assert(c == t[i] and p == utf8.offset(s, i)) 71 assert(utf8.codepoint(s, p) == c) 72 end 73 assert(i == #t) 74 75 i = 0 76 for p, c in utf8.codes(s) do 77 i = i + 1 78 assert(c == t[i] and p == utf8.offset(s, i)) 79 end 80 assert(i == #t) 81 82 i = 0 83 for c in string.gmatch(s, utf8.charpattern) do 84 i = i + 1 85 assert(c == utf8.char(t[i])) 86 end 87 assert(i == #t) 88 89 for i = 1, l do 90 assert(utf8.offset(s, i) == utf8.offset(s, i - l - 1, #s + 1)) 91 end 92 93 end 94 95 96 do -- error indication in utf8.len 97 local function check (s, p) 98 local a, b = utf8.len(s) 99 assert(not a and b == p) 100 end 101 check("abc\xE3def", 4) 102 check("汉字\x80", #("汉字") + 1) 103 check("\xF4\x9F\xBF", 1) 104 check("\xF4\x9F\xBF\xBF", 1) 105 end 106 107 -- error in utf8.codes 108 checkerror("invalid UTF%-8 code", 109 function () 110 local s = "ab\xff" 111 for c in utf8.codes(s) do assert(c) end 112 end) 113 114 115 -- error in initial position for offset 116 checkerror("position out of range", utf8.offset, "abc", 1, 5) 117 checkerror("position out of range", utf8.offset, "abc", 1, -4) 118 checkerror("position out of range", utf8.offset, "", 1, 2) 119 checkerror("position out of range", utf8.offset, "", 1, -1) 120 checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) 121 checkerror("continuation byte", utf8.offset, "𦧺", 1, 2) 122 checkerror("continuation byte", utf8.offset, "\x80", 1) 123 124 125 126 local s = "hello World" 127 local t = {string.byte(s, 1, -1)} 128 for i = 1, utf8.len(s) do assert(t[i] == string.byte(s, i)) end 129 check(s, t) 130 131 check("汉字/漢字", {27721, 23383, 47, 28450, 23383,}) 132 133 do 134 local s = "áéí\128" 135 local t = {utf8.codepoint(s,1,#s - 1)} 136 assert(#t == 3 and t[1] == 225 and t[2] == 233 and t[3] == 237) 137 checkerror("invalid UTF%-8 code", utf8.codepoint, s, 1, #s) 138 checkerror("out of range", utf8.codepoint, s, #s + 1) 139 t = {utf8.codepoint(s, 4, 3)} 140 assert(#t == 0) 141 checkerror("out of range", utf8.codepoint, s, -(#s + 1), 1) 142 checkerror("out of range", utf8.codepoint, s, 1, #s + 1) 143 end 144 145 assert(utf8.char() == "") 146 assert(utf8.char(97, 98, 99) == "abc") 147 148 assert(utf8.codepoint(utf8.char(0x10FFFF)) == 0x10FFFF) 149 150 checkerror("value out of range", utf8.char, 0x10FFFF + 1) 151 152 local function invalid (s) 153 checkerror("invalid UTF%-8 code", utf8.codepoint, s) 154 assert(not utf8.len(s)) 155 end 156 157 -- UTF-8 representation for 0x11ffff (value out of valid range) 158 invalid("\xF4\x9F\xBF\xBF") 159 160 -- overlong sequences 161 invalid("\xC0\x80") -- zero 162 invalid("\xC1\xBF") -- 0x7F (should be coded in 1 byte) 163 invalid("\xE0\x9F\xBF") -- 0x7FF (should be coded in 2 bytes) 164 invalid("\xF0\x8F\xBF\xBF") -- 0xFFFF (should be coded in 3 bytes) 165 166 167 -- invalid bytes 168 invalid("\x80") -- continuation byte 169 invalid("\xBF") -- continuation byte 170 invalid("\xFE") -- invalid byte 171 invalid("\xFF") -- invalid byte 172 173 174 -- empty string 175 check("", {}) 176 177 -- minimum and maximum values for each sequence size 178 s = "\0 \x7F\z 179 \xC2\x80 \xDF\xBF\z 180 \xE0\xA0\x80 \xEF\xBF\xBF\z 181 \xF0\x90\x80\x80 \xF4\x8F\xBF\xBF" 182 s = string.gsub(s, " ", "") 183 check(s, {0,0x7F, 0x80,0x7FF, 0x800,0xFFFF, 0x10000,0x10FFFF}) 184 185 x = "日本語a-4\0éó" 186 check(x, {26085, 26412, 35486, 97, 45, 52, 0, 233, 243}) 187 188 189 -- Supplementary Characters 190 check("𣲷𠜎𠱓𡁻𠵼ab𠺢", 191 {0x23CB7, 0x2070E, 0x20C53, 0x2107B, 0x20D7C, 0x61, 0x62, 0x20EA2,}) 192 193 check("𨳊𩶘𦧺𨳒𥄫𤓓\xF4\x8F\xBF\xBF", 194 {0x28CCA, 0x29D98, 0x269FA, 0x28CD2, 0x2512B, 0x244D3, 0x10ffff}) 195 196 197 local i = 0 198 for p, c in string.gmatch(x, "()(" .. utf8.charpattern .. ")") do 199 i = i + 1 200 assert(utf8.offset(x, i) == p) 201 assert(utf8.len(x, p) == utf8.len(x) - i + 1) 202 assert(utf8.len(c) == 1) 203 for j = 1, #c - 1 do 204 assert(utf8.offset(x, 0, p + j - 1) == p) 205 end 206 end 207 208 print'ok' 209