aboutsummaryrefslogtreecommitdiff
path: root/testes/tpack.lua
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-07-09 12:33:01 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-07-09 12:33:01 -0300
commit7c519dfbd0c68b952f0849e01deaa3750e1f8153 (patch)
treedde3ddbba310877db725df37a0d9f2cbe4e2a8f9 /testes/tpack.lua
parentf59e6a93c0ad38a27a420e51abf8f13d962446b5 (diff)
downloadlua-7c519dfbd0c68b952f0849e01deaa3750e1f8153.tar.gz
lua-7c519dfbd0c68b952f0849e01deaa3750e1f8153.tar.bz2
lua-7c519dfbd0c68b952f0849e01deaa3750e1f8153.zip
Added manual and tests for version 5.4-w2
Diffstat (limited to 'testes/tpack.lua')
-rw-r--r--testes/tpack.lua324
1 files changed, 324 insertions, 0 deletions
diff --git a/testes/tpack.lua b/testes/tpack.lua
new file mode 100644
index 00000000..0e639cc5
--- /dev/null
+++ b/testes/tpack.lua
@@ -0,0 +1,324 @@
1-- $Id: tpack.lua,v 1.14 2018/06/04 14:26:32 roberto Exp $
2-- See Copyright Notice in file all.lua
3
4local pack = string.pack
5local packsize = string.packsize
6local unpack = string.unpack
7
8print "testing pack/unpack"
9
10-- maximum size for integers
11local NB = 16
12
13local sizeshort = packsize("h")
14local sizeint = packsize("i")
15local sizelong = packsize("l")
16local sizesize_t = packsize("T")
17local sizeLI = packsize("j")
18local sizefloat = packsize("f")
19local sizedouble = packsize("d")
20local sizenumber = packsize("n")
21local little = (pack("i2", 1) == "\1\0")
22local align = packsize("!xXi16")
23
24assert(1 <= sizeshort and sizeshort <= sizeint and sizeint <= sizelong and
25 sizefloat <= sizedouble)
26
27print("platform:")
28print(string.format(
29 "\tshort %d, int %d, long %d, size_t %d, float %d, double %d,\n\z
30 \tlua Integer %d, lua Number %d",
31 sizeshort, sizeint, sizelong, sizesize_t, sizefloat, sizedouble,
32 sizeLI, sizenumber))
33print("\t" .. (little and "little" or "big") .. " endian")
34print("\talignment: " .. align)
35
36
37-- check errors in arguments
38function checkerror (msg, f, ...)
39 local status, err = pcall(f, ...)
40 -- print(status, err, msg)
41 assert(not status and string.find(err, msg))
42end
43
44-- minimum behavior for integer formats
45assert(unpack("B", pack("B", 0xff)) == 0xff)
46assert(unpack("b", pack("b", 0x7f)) == 0x7f)
47assert(unpack("b", pack("b", -0x80)) == -0x80)
48
49assert(unpack("H", pack("H", 0xffff)) == 0xffff)
50assert(unpack("h", pack("h", 0x7fff)) == 0x7fff)
51assert(unpack("h", pack("h", -0x8000)) == -0x8000)
52
53assert(unpack("L", pack("L", 0xffffffff)) == 0xffffffff)
54assert(unpack("l", pack("l", 0x7fffffff)) == 0x7fffffff)
55assert(unpack("l", pack("l", -0x80000000)) == -0x80000000)
56
57
58for i = 1, NB do
59 -- small numbers with signal extension ("\xFF...")
60 local s = string.rep("\xff", i)
61 assert(pack("i" .. i, -1) == s)
62 assert(packsize("i" .. i) == #s)
63 assert(unpack("i" .. i, s) == -1)
64
65 -- small unsigned number ("\0...\xAA")
66 s = "\xAA" .. string.rep("\0", i - 1)
67 assert(pack("<I" .. i, 0xAA) == s)
68 assert(unpack("<I" .. i, s) == 0xAA)
69 assert(pack(">I" .. i, 0xAA) == s:reverse())
70 assert(unpack(">I" .. i, s:reverse()) == 0xAA)
71end
72
73do
74 local lnum = 0x13121110090807060504030201
75 local s = pack("<j", lnum)
76 assert(unpack("<j", s) == lnum)
77 assert(unpack("<i" .. sizeLI + 1, s .. "\0") == lnum)
78 assert(unpack("<i" .. sizeLI + 1, s .. "\0") == lnum)
79
80 for i = sizeLI + 1, NB do
81 local s = pack("<j", -lnum)
82 assert(unpack("<j", s) == -lnum)
83 -- strings with (correct) extra bytes
84 assert(unpack("<i" .. i, s .. ("\xFF"):rep(i - sizeLI)) == -lnum)
85 assert(unpack(">i" .. i, ("\xFF"):rep(i - sizeLI) .. s:reverse()) == -lnum)
86 assert(unpack("<I" .. i, s .. ("\0"):rep(i - sizeLI)) == -lnum)
87
88 -- overflows
89 checkerror("does not fit", unpack, "<I" .. i, ("\x00"):rep(i - 1) .. "\1")
90 checkerror("does not fit", unpack, ">i" .. i, "\1" .. ("\x00"):rep(i - 1))
91 end
92end
93
94for i = 1, sizeLI do
95 local lstr = "\1\2\3\4\5\6\7\8\9\10\11\12\13"
96 local lnum = 0x13121110090807060504030201
97 local n = lnum & (~(-1 << (i * 8)))
98 local s = string.sub(lstr, 1, i)
99 assert(pack("<i" .. i, n) == s)
100 assert(pack(">i" .. i, n) == s:reverse())
101 assert(unpack(">i" .. i, s:reverse()) == n)
102end
103
104-- sign extension
105do
106 local u = 0xf0
107 for i = 1, sizeLI - 1 do
108 assert(unpack("<i"..i, "\xf0"..("\xff"):rep(i - 1)) == -16)
109 assert(unpack(">I"..i, "\xf0"..("\xff"):rep(i - 1)) == u)
110 u = u * 256 + 0xff
111 end
112end
113
114-- mixed endianness
115do
116 assert(pack(">i2 <i2", 10, 20) == "\0\10\20\0")
117 local a, b = unpack("<i2 >i2", "\10\0\0\20")
118 assert(a == 10 and b == 20)
119 assert(pack("=i4", 2001) == pack("i4", 2001))
120end
121
122print("testing invalid formats")
123
124checkerror("out of limits", pack, "i0", 0)
125checkerror("out of limits", pack, "i" .. NB + 1, 0)
126checkerror("out of limits", pack, "!" .. NB + 1, 0)
127checkerror("%(17%) out of limits %[1,16%]", pack, "Xi" .. NB + 1)
128checkerror("invalid format option 'r'", pack, "i3r", 0)
129checkerror("16%-byte integer", unpack, "i16", string.rep('\3', 16))
130checkerror("not power of 2", pack, "!4i3", 0);
131checkerror("missing size", pack, "c", "")
132checkerror("variable%-length format", packsize, "s")
133checkerror("variable%-length format", packsize, "z")
134
135-- overflow in option size (error will be in digit after limit)
136checkerror("invalid format", packsize, "c1" .. string.rep("0", 40))
137
138if packsize("i") == 4 then
139 -- result would be 2^31 (2^3 repetitions of 2^28 strings)
140 local s = string.rep("c268435456", 2^3)
141 checkerror("too large", packsize, s)
142 -- one less is OK
143 s = string.rep("c268435456", 2^3 - 1) .. "c268435455"
144 assert(packsize(s) == 0x7fffffff)
145end
146
147-- overflow in packing
148for i = 1, sizeLI - 1 do
149 local umax = (1 << (i * 8)) - 1
150 local max = umax >> 1
151 local min = ~max
152 checkerror("overflow", pack, "<I" .. i, -1)
153 checkerror("overflow", pack, "<I" .. i, min)
154 checkerror("overflow", pack, ">I" .. i, umax + 1)
155
156 checkerror("overflow", pack, ">i" .. i, umax)
157 checkerror("overflow", pack, ">i" .. i, max + 1)
158 checkerror("overflow", pack, "<i" .. i, min - 1)
159
160 assert(unpack(">i" .. i, pack(">i" .. i, max)) == max)
161 assert(unpack("<i" .. i, pack("<i" .. i, min)) == min)
162 assert(unpack(">I" .. i, pack(">I" .. i, umax)) == umax)
163end
164
165-- Lua integer size
166assert(unpack(">j", pack(">j", math.maxinteger)) == math.maxinteger)
167assert(unpack("<j", pack("<j", math.mininteger)) == math.mininteger)
168assert(unpack("<J", pack("<j", -1)) == -1) -- maximum unsigned integer
169
170if little then
171 assert(pack("f", 24) == pack("<f", 24))
172else
173 assert(pack("f", 24) == pack(">f", 24))
174end
175
176print "testing pack/unpack of floating-point numbers"
177
178for _, n in ipairs{0, -1.1, 1.9, 1/0, -1/0, 1e20, -1e20, 0.1, 2000.7} do
179 assert(unpack("n", pack("n", n)) == n)
180 assert(unpack("<n", pack("<n", n)) == n)
181 assert(unpack(">n", pack(">n", n)) == n)
182 assert(pack("<f", n) == pack(">f", n):reverse())
183 assert(pack(">d", n) == pack("<d", n):reverse())
184end
185
186-- for non-native precisions, test only with "round" numbers
187for _, n in ipairs{0, -1.5, 1/0, -1/0, 1e10, -1e9, 0.5, 2000.25} do
188 assert(unpack("<f", pack("<f", n)) == n)
189 assert(unpack(">f", pack(">f", n)) == n)
190 assert(unpack("<d", pack("<d", n)) == n)
191 assert(unpack(">d", pack(">d", n)) == n)
192end
193
194print "testing pack/unpack of strings"
195do
196 local s = string.rep("abc", 1000)
197 assert(pack("zB", s, 247) == s .. "\0\xF7")
198 local s1, b = unpack("zB", s .. "\0\xF9")
199 assert(b == 249 and s1 == s)
200 s1 = pack("s", s)
201 assert(unpack("s", s1) == s)
202
203 checkerror("does not fit", pack, "s1", s)
204
205 checkerror("contains zeros", pack, "z", "alo\0");
206
207 checkerror("unfinished string", unpack, "zc10000000", "alo")
208
209 for i = 2, NB do
210 local s1 = pack("s" .. i, s)
211 assert(unpack("s" .. i, s1) == s and #s1 == #s + i)
212 end
213end
214
215do
216 local x = pack("s", "alo")
217 checkerror("too short", unpack, "s", x:sub(1, -2))
218 checkerror("too short", unpack, "c5", "abcd")
219 checkerror("out of limits", pack, "s100", "alo")
220end
221
222do
223 assert(pack("c0", "") == "")
224 assert(packsize("c0") == 0)
225 assert(unpack("c0", "") == "")
226 assert(pack("<! c3", "abc") == "abc")
227 assert(packsize("<! c3") == 3)
228 assert(pack(">!4 c6", "abcdef") == "abcdef")
229 assert(pack("c3", "123") == "123")
230 assert(pack("c0", "") == "")
231 assert(pack("c8", "123456") == "123456\0\0")
232 assert(pack("c88", "") == string.rep("\0", 88))
233 assert(pack("c188", "ab") == "ab" .. string.rep("\0", 188 - 2))
234 local a, b, c = unpack("!4 z c3", "abcdefghi\0xyz")
235 assert(a == "abcdefghi" and b == "xyz" and c == 14)
236 checkerror("longer than", pack, "c3", "1234")
237end
238
239
240-- testing multiple types and sequence
241do
242 local x = pack("<b h b f d f n i", 1, 2, 3, 4, 5, 6, 7, 8)
243 assert(#x == packsize("<b h b f d f n i"))
244 local a, b, c, d, e, f, g, h = unpack("<b h b f d f n i", x)
245 assert(a == 1 and b == 2 and c == 3 and d == 4 and e == 5 and f == 6 and
246 g == 7 and h == 8)
247end
248
249print "testing alignment"
250do
251 assert(pack(" < i1 i2 ", 2, 3) == "\2\3\0") -- no alignment by default
252 local x = pack(">!8 b Xh i4 i8 c1 Xi8", -12, 100, 200, "\xEC")
253 assert(#x == packsize(">!8 b Xh i4 i8 c1 Xi8"))
254 assert(x == "\xf4" .. "\0\0\0" ..
255 "\0\0\0\100" ..
256 "\0\0\0\0\0\0\0\xC8" ..
257 "\xEC" .. "\0\0\0\0\0\0\0")
258 local a, b, c, d, pos = unpack(">!8 c1 Xh i4 i8 b Xi8 XI XH", x)
259 assert(a == "\xF4" and b == 100 and c == 200 and d == -20 and (pos - 1) == #x)
260
261 x = pack(">!4 c3 c4 c2 z i4 c5 c2 Xi4",
262 "abc", "abcd", "xz", "hello", 5, "world", "xy")
263 assert(x == "abcabcdxzhello\0\0\0\0\0\5worldxy\0")
264 local a, b, c, d, e, f, g, pos = unpack(">!4 c3 c4 c2 z i4 c5 c2 Xh Xi4", x)
265 assert(a == "abc" and b == "abcd" and c == "xz" and d == "hello" and
266 e == 5 and f == "world" and g == "xy" and (pos - 1) % 4 == 0)
267
268 x = pack(" b b Xd b Xb x", 1, 2, 3)
269 assert(packsize(" b b Xd b Xb x") == 4)
270 assert(x == "\1\2\3\0")
271 a, b, c, pos = unpack("bbXdb", x)
272 assert(a == 1 and b == 2 and c == 3 and pos == #x)
273
274 -- only alignment
275 assert(packsize("!8 xXi8") == 8)
276 local pos = unpack("!8 xXi8", "0123456701234567"); assert(pos == 9)
277 assert(packsize("!8 xXi2") == 2)
278 local pos = unpack("!8 xXi2", "0123456701234567"); assert(pos == 3)
279 assert(packsize("!2 xXi2") == 2)
280 local pos = unpack("!2 xXi2", "0123456701234567"); assert(pos == 3)
281 assert(packsize("!2 xXi8") == 2)
282 local pos = unpack("!2 xXi8", "0123456701234567"); assert(pos == 3)
283 assert(packsize("!16 xXi16") == 16)
284 local pos = unpack("!16 xXi16", "0123456701234567"); assert(pos == 17)
285
286 checkerror("invalid next option", pack, "X")
287 checkerror("invalid next option", unpack, "XXi", "")
288 checkerror("invalid next option", unpack, "X i", "")
289 checkerror("invalid next option", pack, "Xc1")
290end
291
292do -- testing initial position
293 local x = pack("i4i4i4i4", 1, 2, 3, 4)
294 for pos = 1, 16, 4 do
295 local i, p = unpack("i4", x, pos)
296 assert(i == pos//4 + 1 and p == pos + 4)
297 end
298
299 -- with alignment
300 for pos = 0, 12 do -- will always round position to power of 2
301 local i, p = unpack("!4 i4", x, pos + 1)
302 assert(i == (pos + 3)//4 + 1 and p == i*4 + 1)
303 end
304
305 -- negative indices
306 local i, p = unpack("!4 i4", x, -4)
307 assert(i == 4 and p == 17)
308 local i, p = unpack("!4 i4", x, -7)
309 assert(i == 4 and p == 17)
310 local i, p = unpack("!4 i4", x, -#x)
311 assert(i == 1 and p == 5)
312
313 -- limits
314 for i = 1, #x + 1 do
315 assert(unpack("c0", x, i) == "")
316 end
317 checkerror("out of string", unpack, "c0", x, 0)
318 checkerror("out of string", unpack, "c0", x, #x + 2)
319 checkerror("out of string", unpack, "c0", x, -(#x + 1))
320
321end
322
323print "OK"
324