1
2-- This is a test script for tshark/wireshark.
3-- This script runs inside tshark/wireshark, so to run it do:
4-- wireshark -X lua_script:<path_to_testdir>/lua/int64.lua
5-- tshark -r bogus.cap -X lua_script:<path_to_testdir>/lua/int64.lua
6
7-- Tests Int64/UInt64 functions
8
9local function testing(...)
10    print("---- Testing "..tostring(...).." ----")
11end
12
13local function test(name, ...)
14    io.stdout:write("test "..name.."...")
15    if (...) == true then
16        io.stdout:write("passed\n")
17    else
18        io.stdout:write("failed!\n")
19        error(name.." test failed!")
20    end
21end
22
23-- you can't compare (use the '==') userdata objects with numbers, so this function does it instead.
24function checkeq(arg1,arg2)
25    if arg1 == arg2 then
26        return true
27    elseif type(arg1) == 'userdata' and arg1.tonumber then
28        if type(arg2) == 'userdata' and arg2.tonumber then
29            return arg1:tonumber() == arg2:tonumber()
30        else
31            return arg1:tonumber() == arg2
32        end
33    elseif type(arg2) == 'userdata' and arg2.tonumber then
34        return arg1 == arg2:tonumber()
35    else
36        return false
37    end
38end
39
40-----------------------------
41
42testing("Int64/UInt64 library")
43
44local testtbl = { { ["type"]=Int64, ["name"]="Int64" } , { ["type"]=UInt64, ["name"]="UInt64" } }
45
46for i,t in ipairs(testtbl) do
47
48    local function testing(...)
49        print("---- Testing "..t.name..": "..tostring(...).." ----")
50    end
51
52    local function test(name, ...)
53        io.stdout:write("test "..t.name.."-"..name.."...")
54        if (...) == true then
55            io.stdout:write("passed\n")
56        else
57            io.stdout:write("failed!\n")
58            error(name.." test failed!")
59        end
60    end
61
62    testing("class")
63    local obj = t.type
64
65    for name, val in pairs(obj) do
66        print("\t"..name.." = "..type(val))
67    end
68
69    test("class1",type(obj) == 'table')
70    test("class2",type(obj.new) == 'function')
71    test("class3",type(obj.max) == 'function')
72    test("class4",type(obj.min) == 'function')
73    test("class5",type(obj.tonumber) == 'function')
74    test("class6",type(obj.fromhex) == 'function')
75    test("class7",type(obj.tohex) == 'function')
76    test("class8",type(obj.higher) == 'function')
77    test("class9",type(obj.lower) == 'function')
78
79
80    testing("new, tonumber, tostring")
81    local val = 12345
82    local my64a = obj.new(val)
83    local my64b = obj.new(tostring(val))
84    local zero = obj.new(0)
85    -- remember in Lua it's a double, so only precise up to 9,007,199,254,740,992
86    local my64c = obj.new(val,100)
87    local valc = (100 * 4294967296) + val
88    print(tostring(my64c))
89    local my64z = obj.new(0,0)
90    local my64d = obj.new(0,100)
91    local vald = (100 * 4294967296)
92
93    test("new1",checkeq(my64a,val))
94    test("new2",checkeq(my64b,val))
95    test("new3",checkeq(my64a,obj.new(my64b)))
96    test("new3b",checkeq(my64a,obj(my64b)))
97    test("new4",checkeq(valc,my64c))
98    test("new5",checkeq(0,my64z))
99    test("new6",obj.new(0,1):tonumber() == (2^32))
100    if t.name == "Int64" then
101        test("new7",obj(-1):tonumber() == -1)
102        test("new8",obj.new(0,-1):tonumber() == -4294967296)
103        test("new9",obj(obj.new(-1)):tonumber() == -1)
104    end
105
106    test("tonumber1",val == my64a:tonumber())
107    test("tonumber2",valc == my64c:tonumber())
108    test("tonumber3",vald == my64d:tonumber())
109    test("tonumber4",0 == my64z:tonumber())
110
111    test("tostring1", tostring(my64a)==tostring(val))
112    test("tostring2",tostring(my64b)==tostring(val))
113    test("tostring3",tostring(my64c)==tostring(valc))
114    test("tostring4",tostring(my64d)==tostring(vald))
115
116
117    testing("compare ops")
118
119    test("eq", my64a == my64b)
120
121    test("le1", my64a <= my64b)
122    test("le2", my64a <= my64c)
123    test("le3", my64z <= my64c)
124
125    test("ge1", my64a >= my64b)
126    test("ge2", my64c >= my64b)
127    test("ge2", my64c >= my64z)
128
129    test("neq1",not(my64a ~= my64b))
130    test("neq2",my64a ~= obj(0))
131    test("neq2",my64a ~= my64c)
132
133    test("gt1",my64a > my64z)
134    test("gt2",my64c > my64a)
135
136    test("lt1",not(my64a < my64b))
137    test("lt2",my64a < my64c)
138
139
140    testing("math ops")
141
142    test("add1",checkeq(my64a + my64b, val + val))
143    test("add2",my64a + my64z == my64b)
144    test("add3",my64a + my64b == my64b + my64a)
145    test("add4",my64d + my64a == my64c)
146    test("add5",checkeq(my64a + vald, valc))
147    test("add6",checkeq(vald + my64a, valc))
148
149    test("sub1",checkeq(my64a - my64b, 0))
150    test("sub2",my64a - my64b == my64z)
151    test("sub3",my64a - my64b == my64b - my64a)
152    test("sub4",my64c - my64a == my64d)
153    test("sub5",checkeq(my64a - val, 0))
154
155    test("mod1",checkeq(my64a % my64b, 0))
156    test("mod2",checkeq(my64c % my64b, valc % val))
157    test("mod3",checkeq(my64c % val, valc % val))
158    test("mod4",checkeq(val % my64c, val % valc))
159
160    test("div1",checkeq(my64a / my64b, 1))
161    test("div2",checkeq(my64a / val, 1))
162    test("div3",checkeq(val / my64a, 1))
163    test("div4",my64c / my64d == obj.new(1))
164
165    test("pow1",checkeq(my64a ^ 1, val))
166    test("pow2",checkeq(my64a ^ obj.new(2), val ^ 2))
167    test("pow3",checkeq(my64a ^ obj.new(3), val ^ 3))
168    test("pow4",checkeq(my64c ^ 1, valc ^ 1))
169
170    test("mul1",checkeq(my64a * obj(1), my64b))
171    test("mul2",checkeq(my64a * my64b, my64b * my64a))
172    test("mul3",checkeq(my64a * 1, my64b))
173    test("mul4",checkeq(2 * my64c, 2 * valc))
174
175    if t.name == "Int64" then
176        -- unary minus on UInt64 is illogical, but oh well
177        test("unm1",checkeq(-my64a,-val))
178        test("unm2",checkeq(string.sub(tostring(-my64a),1,1), "-"))
179        test("unm3",checkeq(-my64c,-valc))
180    else
181        test("unm1",checkeq(-my64a,val))
182        test("unm2",checkeq(string.sub(tostring(-my64a),1,1), "1"))
183        test("unm3",checkeq(-my64c,valc))
184    end
185    test("unm4",checkeq(-my64z,0))
186
187    testing("methods")
188
189    test("higher1",my64a:higher() == 0)
190    test("higher2",my64c:higher() == 100)
191
192    test("lower1",my64a:lower() == val)
193    test("lower2",my64c:lower() == val)
194    test("lower3",my64d:lower() == 0)
195
196    local vale1 = 3735928559  -- yields hex of deadbeef
197    local vale2 = 5045997  -- yields 4cfeed
198    local my64e = obj.new(vale1, vale2)
199    test("fromhex1",obj.fromhex("0000000000003039") == my64a);
200    test("fromhex2",obj.fromhex("3039") == my64a);
201    test("fromhex3",obj.fromhex("0000006400003039") == my64c);
202    test("fromhex4",obj.fromhex("0000000000000000") == my64z);
203    test("fromhex5",obj.fromhex("004cfeeddeadbeef") == my64e);
204    test("fromhex6",obj.fromhex("4cFEEDDEADBEEF") == my64e);
205
206    test("tohex1",my64a:tohex() == "0000000000003039")
207    test("tohex2",my64c:tohex(16) == "0000006400003039")
208    test("tohex3",my64z:tohex() == "0000000000000000")
209    test("tohex4",my64e:tohex() == "004cfeeddeadbeef")
210    test("tohex5",my64e:tohex(8) == "deadbeef")
211    test("tohex6",my64e:tohex(-8) == "DEADBEEF")
212
213    test("encode1",my64a:encode(true) ==  "\57\48\00\00\00\00\00\00")
214    test("encode2",my64a:encode(false) == "\00\00\00\00\00\00\48\57")
215    test("encode3",my64c:encode(false) == "\00\00\00\100\00\00\48\57")
216
217    test("decode1",obj.decode("\57\48\00\00\00\00\00\00", true) ==  my64a)
218    test("decode2",obj.decode("\00\00\00\00\00\00\48\57", false) == my64a)
219    test("decode3",obj.decode("\00\00\00\100\00\00\48\57", false) == my64c)
220
221
222    local function testpower(b)
223        testing("powers of "..b)
224        b=obj.new(b)
225        local z=obj.new(1)
226        for i=0,100 do
227            print(i,z,b^i)
228            assert(z==b^i)
229            z=b*z
230        end
231    end
232
233    testpower(2)
234    testpower(3)
235
236    testing"factorials"
237
238    F={
239    [1]="1",
240    [2]="2",
241    [3]="6",
242    [4]="24",
243    [5]="120",
244    [6]="720",
245    [7]="5040",
246    [8]="40320",
247    [9]="362880",
248    [10]="3628800",
249    [11]="39916800",
250    [12]="479001600",
251    [13]="6227020800",
252    [14]="87178291200",
253    [15]="1307674368000",
254    [16]="20922789888000",
255    [17]="355687428096000",
256    [18]="6402373705728000",
257    [19]="121645100408832000",
258    [20]="2432902008176640000",
259    }
260    z=obj.new(1)
261    f=1
262    for i=1,20 do
263        z=z*i
264        f=f*i
265        s=obj.tonumber(z)
266        print(i,z,f,f==obj.tonumber(z),tostring(z)==F[i])
267        --print(i,int64.new(F[i]))
268    end
269
270    testing("bit operations")
271
272    test("band1",checkeq(obj(1):band(1), 1))
273    test("band2",checkeq(obj(1):band(0), 0))
274    test("band3",checkeq(obj(4294967295,100):band(4294967295), 4294967295))
275    test("band4",obj.new(4294967295,100):band(obj(0,100),obj(0,100),obj(0,100)) == obj(0,100))
276    test("band5",checkeq(obj.new(4294967295,100):band(obj.new(0,100),obj(0)), 0))
277
278    test("bor1",checkeq(obj(1):bor(1), 1))
279    test("bor2",checkeq(obj(1):bor(0), 1))
280    test("bor3",checkeq(obj(0):bor(0), 0))
281    test("bor4",obj.new(0,100):bor(4294967295) == obj.new(4294967295,100))
282    test("bor5",obj.new(1):bor(obj(2),obj.new(4),obj(8),16,32,64,128) == obj(255))
283
284    test("bxor1",checkeq(obj.new(1):bxor(1), 0))
285    test("bxor2",checkeq(obj.new(1):bxor(0), 1))
286    test("bxor3",checkeq(obj.new(0):bxor(0), 0))
287    test("bxor4",obj.new(4294967295,100):bxor(obj(0,100)) == obj.new(4294967295))
288    test("bxor5",obj.new(1):bxor(obj(2),obj(4),obj(8),16,32,64,128) == obj(255))
289
290    test("bnot1",checkeq(obj.new(4294967295,4294967295):bnot(), 0))
291    test("bnot2",obj.new(0):bnot() == obj.new(4294967295,4294967295))
292    test("bnot3",obj.new(0xaaaaaaaa,0xaaaaaaaa):bnot() == obj.new( 0x55555555, 0x55555555))
293
294    test("bsawp1",obj.new( 0x01020304, 0x05060708 ):bswap() == obj.new( 0x08070605, 0x04030201 ))
295    test("bsawp2",obj.new( 0xFF020304, 0xFF060708 ):bswap() == obj.new( 0x080706FF, 0x040302FF ))
296
297    test("lshift1",obj.new( 0x01020304, 0x0506070F ):lshift(4) == obj.new( 0x10203040, 0x506070f0 ))
298    test("lshift2",obj.new( 0x0102030F, 0x05060708 ):lshift(63) == obj.new( 0, 0x80000000 ))
299    if t.name == "Int64" then
300        test("lshift3",checkeq(obj.new( 0x0102030F, 0x05060708 ):lshift(63), -9223372036854775808))
301    else
302        test("lshift3",obj.new( 0x0102030F, 0x05060708 ):lshift(63) == obj.new( 0, 0x80000000 ))
303    end
304
305    test("rshift1",obj.new( 0x01020304, 0xF5060708 ):rshift(4) == obj.new( 0x80102030, 0x0F506070 ))
306    test("rshift2",checkeq(obj.new( 0x01020304, 0xF5060708 ):rshift(63), 1))
307
308    if t.name == "Int64" then
309        test("arshift1",obj.new( 0x01020304, 0xF5060708 ):arshift(4) == obj.new( 0x80102030, 0xFF506070 ))
310        test("arshift2",obj.new( 0x01020304, 0xF5060708 ):arshift(63) == obj.new( 0xFFFFFFFF, 0xFFFFFFFF ))
311    else
312        test("arshift1",obj.new( 0x01020304, 0xF5060708 ):arshift(4) == obj.new( 0x80102030, 0x0F506070 ))
313        test("arshift2",checkeq(obj.new( 0x01020304, 0xF5060708 ):arshift(63),1))
314    end
315    test("arshift3",obj.new( 0x01020304, 0x05060708 ):arshift(4) == obj.new( 0x80102030, 0x00506070 ))
316    test("arshift4",checkeq(obj.new( 0x01020304, 0x05060708 ):arshift(63), 0))
317
318    test("rol1",obj.new( 0x01020304, 0xF5060708 ):rol(4) == obj.new( 0x1020304F, 0x50607080 ))
319    test("rol2",obj.new( 0x01020304, 0xF5060708 ):rol(32):rol(32) == obj.new( 0x01020304, 0xF5060708 ))
320
321    test("ror1",obj.new( 0x01020304, 0xF5060708 ):ror(4) == obj.new( 0x80102030, 0x4F506070 ))
322    test("ror2",obj.new( 0x01020304, 0xF5060708 ):ror(32):ror(32) == obj.new( 0x01020304, 0xF5060708 ))
323
324end
325
326testing("min and max values")
327z=Int64.new(2)
328z=z^63-1
329test("max1",tostring(Int64.max()) == "9223372036854775807")
330test("max2",Int64.max() == Int64.new(4294967295, 2147483647))
331test("max3",z==Int64.max())
332test("min1",tostring(Int64.min()) == "-9223372036854775808")
333test("min2",Int64.min() == Int64.new(0,2147483648))
334z=-z
335z=z-1
336test("min3",z==Int64.min())
337
338test("minmax",Int64.min()== - Int64.max() - 1)
339
340testing("error conditions")
341
342local function divtest(f,s)
343    local r = (f / s)
344    if r == 5 then
345        io.stdout:write("ok...")
346    else
347        error("test failed!")
348    end
349end
350
351local function modtest(f,s)
352    local r = (f % s)
353    if r == 5 then
354        io.stdout:write("ok...")
355    else
356        error("test failed!")
357    end
358end
359
360test("error1", pcall(divtest, 10, 2)) -- not an error, but checking the div function works above
361test("error2", not pcall(divtest, Int64(10), 0))
362test("error3", not pcall(divtest, Int64(10), Int64(0)))
363test("error4", not pcall(divtest, Int64(10), UInt64(0)))
364test("error5", not pcall(divtest, UInt64(10), 0))
365test("error6", not pcall(divtest, UInt64(10), Int64(0)))
366test("error7", not pcall(divtest, UInt64(10), UInt64(0)))
367test("error8", pcall(modtest, 17, 6)) -- not an error, but checking the mod function works above
368test("error9", not pcall(modtest, Int64(10), 0))
369test("error10", not pcall(modtest, Int64(10), Int64(0)))
370test("error11", not pcall(modtest, Int64(10), UInt64(0)))
371test("error12", not pcall(modtest, UInt64(10), 0))
372test("error13", not pcall(modtest, UInt64(10), Int64(0)))
373test("error14", not pcall(modtest, UInt64(10), UInt64(0)))
374
375print("\n-----------------------------\n")
376
377print("All tests passed!\n\n")
378