xref: /aosp_15_r20/external/flatbuffers/tests/luatest.lua (revision 890232f25432b36107d06881e0a25aaa6b473652)
1*890232f2SAndroid Build Coastguard Workerpackage.path = string.format("../lua/?.lua;./?.lua;%s",package.path)
2*890232f2SAndroid Build Coastguard Workerlocal compat = require("flatbuffers.compat")
3*890232f2SAndroid Build Coastguard Worker
4*890232f2SAndroid Build Coastguard Workerlocal performBenchmarkTests = false
5*890232f2SAndroid Build Coastguard Worker
6*890232f2SAndroid Build Coastguard Workerif #arg > 1 then
7*890232f2SAndroid Build Coastguard Worker    print("usage: lua luatests [benchmark]");
8*890232f2SAndroid Build Coastguard Worker    return
9*890232f2SAndroid Build Coastguard Workerelseif #arg > 0 then
10*890232f2SAndroid Build Coastguard Worker    if(arg[1] == "benchmark") then
11*890232f2SAndroid Build Coastguard Worker        performBenchmarkTests = true
12*890232f2SAndroid Build Coastguard Worker    end
13*890232f2SAndroid Build Coastguard Workerend
14*890232f2SAndroid Build Coastguard Worker
15*890232f2SAndroid Build Coastguard Workerlocal function checkReadBuffer(buf, offset, sizePrefix)
16*890232f2SAndroid Build Coastguard Worker    offset = offset or 0
17*890232f2SAndroid Build Coastguard Worker
18*890232f2SAndroid Build Coastguard Worker    if type(buf) == "string" then
19*890232f2SAndroid Build Coastguard Worker        buf = flatbuffers.binaryArray.New(buf)
20*890232f2SAndroid Build Coastguard Worker    end
21*890232f2SAndroid Build Coastguard Worker
22*890232f2SAndroid Build Coastguard Worker    if sizePrefix then
23*890232f2SAndroid Build Coastguard Worker        local size = flatbuffers.N.Int32:Unpack(buf, offset)
24*890232f2SAndroid Build Coastguard Worker        assert(size == buf.size - offset - 4)
25*890232f2SAndroid Build Coastguard Worker        offset = offset + flatbuffers.N.Int32.bytewidth
26*890232f2SAndroid Build Coastguard Worker    end
27*890232f2SAndroid Build Coastguard Worker
28*890232f2SAndroid Build Coastguard Worker    local mon = monster.GetRootAsMonster(buf, offset)
29*890232f2SAndroid Build Coastguard Worker    assert(mon:Hp() == 80, "Monster Hp is not 80")
30*890232f2SAndroid Build Coastguard Worker    assert(mon:Mana() == 150, "Monster Mana is not 150")
31*890232f2SAndroid Build Coastguard Worker    assert(mon:Name() == "MyMonster", "Monster Name is not MyMonster")
32*890232f2SAndroid Build Coastguard Worker    assert(mon:Testbool() == true)
33*890232f2SAndroid Build Coastguard Worker
34*890232f2SAndroid Build Coastguard Worker    local vec = assert(mon:Pos(), "Monster Position is nil")
35*890232f2SAndroid Build Coastguard Worker    assert(vec:X() == 1.0)
36*890232f2SAndroid Build Coastguard Worker    assert(vec:Y() == 2.0)
37*890232f2SAndroid Build Coastguard Worker    assert(vec:Z() == 3.0)
38*890232f2SAndroid Build Coastguard Worker    assert(vec:Test1() == 3.0)
39*890232f2SAndroid Build Coastguard Worker    assert(vec:Test2() == 2)
40*890232f2SAndroid Build Coastguard Worker
41*890232f2SAndroid Build Coastguard Worker    local t = require("MyGame.Example.Test").New()
42*890232f2SAndroid Build Coastguard Worker    t = assert(vec:Test3(t))
43*890232f2SAndroid Build Coastguard Worker
44*890232f2SAndroid Build Coastguard Worker    assert(t:A() == 5)
45*890232f2SAndroid Build Coastguard Worker    assert(t:B() == 6)
46*890232f2SAndroid Build Coastguard Worker
47*890232f2SAndroid Build Coastguard Worker    local ut = require("MyGame.Example.Any")
48*890232f2SAndroid Build Coastguard Worker    assert(mon:TestType() == ut.Monster)
49*890232f2SAndroid Build Coastguard Worker
50*890232f2SAndroid Build Coastguard Worker    local table2 = mon:Test()
51*890232f2SAndroid Build Coastguard Worker    assert(getmetatable(table2) == "flatbuffers.view.mt")
52*890232f2SAndroid Build Coastguard Worker
53*890232f2SAndroid Build Coastguard Worker    local mon2 = monster.New()
54*890232f2SAndroid Build Coastguard Worker    mon2:Init(table2.bytes, table2.pos)
55*890232f2SAndroid Build Coastguard Worker
56*890232f2SAndroid Build Coastguard Worker    assert(mon2:Name() == "Fred")
57*890232f2SAndroid Build Coastguard Worker
58*890232f2SAndroid Build Coastguard Worker    assert(mon:InventoryLength() == 5)
59*890232f2SAndroid Build Coastguard Worker    local invsum = 0
60*890232f2SAndroid Build Coastguard Worker    for i=1,mon:InventoryLength() do
61*890232f2SAndroid Build Coastguard Worker        local v = mon:Inventory(i)
62*890232f2SAndroid Build Coastguard Worker        invsum = invsum + v
63*890232f2SAndroid Build Coastguard Worker    end
64*890232f2SAndroid Build Coastguard Worker    assert(invsum == 10)
65*890232f2SAndroid Build Coastguard Worker
66*890232f2SAndroid Build Coastguard Worker    for i=1,5 do
67*890232f2SAndroid Build Coastguard Worker        assert(mon:VectorOfLongs(i) == 10^((i-1)*2))
68*890232f2SAndroid Build Coastguard Worker    end
69*890232f2SAndroid Build Coastguard Worker
70*890232f2SAndroid Build Coastguard Worker    local dbls = { -1.7976931348623157e+308, 0, 1.7976931348623157e+308}
71*890232f2SAndroid Build Coastguard Worker    for i=1,mon:VectorOfDoublesLength() do
72*890232f2SAndroid Build Coastguard Worker        assert(mon:VectorOfDoubles(i) == dbls[i])
73*890232f2SAndroid Build Coastguard Worker    end
74*890232f2SAndroid Build Coastguard Worker
75*890232f2SAndroid Build Coastguard Worker    assert(mon:Test4Length() == 2)
76*890232f2SAndroid Build Coastguard Worker
77*890232f2SAndroid Build Coastguard Worker    local test0 = mon:Test4(1)
78*890232f2SAndroid Build Coastguard Worker    local test1 = mon:Test4(2)
79*890232f2SAndroid Build Coastguard Worker
80*890232f2SAndroid Build Coastguard Worker    local v0 = test0:A()
81*890232f2SAndroid Build Coastguard Worker    local v1 = test0:B()
82*890232f2SAndroid Build Coastguard Worker    local v2 = test1:A()
83*890232f2SAndroid Build Coastguard Worker    local v3 = test1:B()
84*890232f2SAndroid Build Coastguard Worker
85*890232f2SAndroid Build Coastguard Worker    local sumtest12 = v0 + v1 + v2 + v3
86*890232f2SAndroid Build Coastguard Worker    assert(sumtest12 == 100)
87*890232f2SAndroid Build Coastguard Worker
88*890232f2SAndroid Build Coastguard Worker    assert(mon:TestarrayofstringLength() == 2)
89*890232f2SAndroid Build Coastguard Worker    assert(mon:Testarrayofstring(1) == "test1")
90*890232f2SAndroid Build Coastguard Worker    assert(mon:Testarrayofstring(2) == "test2")
91*890232f2SAndroid Build Coastguard Worker
92*890232f2SAndroid Build Coastguard Worker    assert(mon:TestarrayoftablesLength() == 0)
93*890232f2SAndroid Build Coastguard Worker    assert(mon:TestnestedflatbufferLength() == 0)
94*890232f2SAndroid Build Coastguard Worker    assert(mon:Testempty() == nil)
95*890232f2SAndroid Build Coastguard Workerend
96*890232f2SAndroid Build Coastguard Worker
97*890232f2SAndroid Build Coastguard Workerlocal function generateMonster(sizePrefix, b)
98*890232f2SAndroid Build Coastguard Worker    if b then b:Clear() end
99*890232f2SAndroid Build Coastguard Worker    b = b or flatbuffers.Builder(0)
100*890232f2SAndroid Build Coastguard Worker    local str = b:CreateString("MyMonster")
101*890232f2SAndroid Build Coastguard Worker    local test1 = b:CreateString("test1")
102*890232f2SAndroid Build Coastguard Worker    local test2 = b:CreateString("test2")
103*890232f2SAndroid Build Coastguard Worker    local fred = b:CreateString("Fred")
104*890232f2SAndroid Build Coastguard Worker
105*890232f2SAndroid Build Coastguard Worker    monster.StartInventoryVector(b, 5)
106*890232f2SAndroid Build Coastguard Worker    b:PrependByte(4)
107*890232f2SAndroid Build Coastguard Worker    b:PrependByte(3)
108*890232f2SAndroid Build Coastguard Worker    b:PrependByte(2)
109*890232f2SAndroid Build Coastguard Worker    b:PrependByte(1)
110*890232f2SAndroid Build Coastguard Worker    b:PrependByte(0)
111*890232f2SAndroid Build Coastguard Worker    local inv = b:EndVector(5)
112*890232f2SAndroid Build Coastguard Worker
113*890232f2SAndroid Build Coastguard Worker    monster.Start(b)
114*890232f2SAndroid Build Coastguard Worker    monster.AddName(b, fred)
115*890232f2SAndroid Build Coastguard Worker    local mon2 = monster.End(b)
116*890232f2SAndroid Build Coastguard Worker
117*890232f2SAndroid Build Coastguard Worker    monster.StartTest4Vector(b, 2)
118*890232f2SAndroid Build Coastguard Worker    test.CreateTest(b, 10, 20)
119*890232f2SAndroid Build Coastguard Worker    test.CreateTest(b, 30, 40)
120*890232f2SAndroid Build Coastguard Worker    local test4 = b:EndVector(2)
121*890232f2SAndroid Build Coastguard Worker
122*890232f2SAndroid Build Coastguard Worker    monster.StartTestarrayofstringVector(b, 2)
123*890232f2SAndroid Build Coastguard Worker    b:PrependUOffsetTRelative(test2)
124*890232f2SAndroid Build Coastguard Worker    b:PrependUOffsetTRelative(test1)
125*890232f2SAndroid Build Coastguard Worker    local testArrayOfString = b:EndVector(2)
126*890232f2SAndroid Build Coastguard Worker
127*890232f2SAndroid Build Coastguard Worker    monster.StartVectorOfLongsVector(b, 5)
128*890232f2SAndroid Build Coastguard Worker    b:PrependInt64(100000000)
129*890232f2SAndroid Build Coastguard Worker    b:PrependInt64(1000000)
130*890232f2SAndroid Build Coastguard Worker    b:PrependInt64(10000)
131*890232f2SAndroid Build Coastguard Worker    b:PrependInt64(100)
132*890232f2SAndroid Build Coastguard Worker    b:PrependInt64(1)
133*890232f2SAndroid Build Coastguard Worker    local vectorOfLongs = b:EndVector(5)
134*890232f2SAndroid Build Coastguard Worker
135*890232f2SAndroid Build Coastguard Worker    monster.StartVectorOfDoublesVector(b, 3)
136*890232f2SAndroid Build Coastguard Worker    b:PrependFloat64(1.7976931348623157e+308)
137*890232f2SAndroid Build Coastguard Worker    b:PrependFloat64(0)
138*890232f2SAndroid Build Coastguard Worker    b:PrependFloat64(-1.7976931348623157e+308)
139*890232f2SAndroid Build Coastguard Worker    local vectorOfDoubles = b:EndVector(3)
140*890232f2SAndroid Build Coastguard Worker
141*890232f2SAndroid Build Coastguard Worker    monster.Start(b)
142*890232f2SAndroid Build Coastguard Worker    local pos = vec3.CreateVec3(b, 1.0, 2.0, 3.0, 3.0, 2, 5, 6)
143*890232f2SAndroid Build Coastguard Worker    monster.AddPos(b, pos)
144*890232f2SAndroid Build Coastguard Worker
145*890232f2SAndroid Build Coastguard Worker    monster.AddHp(b, 80)
146*890232f2SAndroid Build Coastguard Worker    monster.AddName(b, str)
147*890232f2SAndroid Build Coastguard Worker    monster.AddInventory(b, inv)
148*890232f2SAndroid Build Coastguard Worker    monster.AddTestType(b, 1)
149*890232f2SAndroid Build Coastguard Worker    monster.AddTest(b, mon2)
150*890232f2SAndroid Build Coastguard Worker    monster.AddTest4(b, test4)
151*890232f2SAndroid Build Coastguard Worker    monster.AddTestbool(b, true)
152*890232f2SAndroid Build Coastguard Worker    monster.AddTestbool(b, false)
153*890232f2SAndroid Build Coastguard Worker    monster.AddTestbool(b, null)
154*890232f2SAndroid Build Coastguard Worker    monster.AddTestbool(b,"true")
155*890232f2SAndroid Build Coastguard Worker    monster.AddTestarrayofstring(b, testArrayOfString)
156*890232f2SAndroid Build Coastguard Worker    monster.AddVectorOfLongs(b, vectorOfLongs)
157*890232f2SAndroid Build Coastguard Worker    monster.AddVectorOfDoubles(b, vectorOfDoubles)
158*890232f2SAndroid Build Coastguard Worker    local mon = monster.End(b)
159*890232f2SAndroid Build Coastguard Worker
160*890232f2SAndroid Build Coastguard Worker    if sizePrefix then
161*890232f2SAndroid Build Coastguard Worker        b:FinishSizePrefixed(mon)
162*890232f2SAndroid Build Coastguard Worker    else
163*890232f2SAndroid Build Coastguard Worker        b:Finish(mon)
164*890232f2SAndroid Build Coastguard Worker    end
165*890232f2SAndroid Build Coastguard Worker    return b:Output(true), b:Head()
166*890232f2SAndroid Build Coastguard Workerend
167*890232f2SAndroid Build Coastguard Worker
168*890232f2SAndroid Build Coastguard Workerlocal function sizePrefix(sizePrefix)
169*890232f2SAndroid Build Coastguard Worker    local buf,offset = generateMonster(sizePrefix)
170*890232f2SAndroid Build Coastguard Worker    checkReadBuffer(buf, offset, sizePrefix)
171*890232f2SAndroid Build Coastguard Workerend
172*890232f2SAndroid Build Coastguard Worker
173*890232f2SAndroid Build Coastguard Workerlocal function fbbClear()
174*890232f2SAndroid Build Coastguard Worker    -- Generate a builder that will be 'cleared' and reused to create two different objects.
175*890232f2SAndroid Build Coastguard Worker    local fbb = flatbuffers.Builder(0)
176*890232f2SAndroid Build Coastguard Worker
177*890232f2SAndroid Build Coastguard Worker    -- First use the builder to read the normal monster data and verify it works
178*890232f2SAndroid Build Coastguard Worker    local buf, offset = generateMonster(false, fbb)
179*890232f2SAndroid Build Coastguard Worker    checkReadBuffer(buf, offset, false)
180*890232f2SAndroid Build Coastguard Worker
181*890232f2SAndroid Build Coastguard Worker    -- Then clear the builder to be used again
182*890232f2SAndroid Build Coastguard Worker    fbb:Clear()
183*890232f2SAndroid Build Coastguard Worker
184*890232f2SAndroid Build Coastguard Worker    -- Storage for the built monsters
185*890232f2SAndroid Build Coastguard Worker    local monsters = {}
186*890232f2SAndroid Build Coastguard Worker    local lastBuf
187*890232f2SAndroid Build Coastguard Worker
188*890232f2SAndroid Build Coastguard Worker    -- Make another builder that will be use identically to the 'cleared' one so outputs can be compared. Build both the
189*890232f2SAndroid Build Coastguard Worker    -- Cleared builder and new builder in the exact same way, so we can compare their results
190*890232f2SAndroid Build Coastguard Worker    for i, builder in ipairs({fbb, flatbuffers.Builder(0)}) do
191*890232f2SAndroid Build Coastguard Worker        local strOffset = builder:CreateString("Hi there")
192*890232f2SAndroid Build Coastguard Worker        monster.Start(builder)
193*890232f2SAndroid Build Coastguard Worker        monster.AddPos(builder, vec3.CreateVec3(builder, 3.0, 2.0, 1.0, 17.0, 3, 100, 123))
194*890232f2SAndroid Build Coastguard Worker        monster.AddName(builder, strOffset)
195*890232f2SAndroid Build Coastguard Worker        monster.AddMana(builder, 123)
196*890232f2SAndroid Build Coastguard Worker        builder:Finish(monster.End(builder))
197*890232f2SAndroid Build Coastguard Worker        local buf = builder:Output(false)
198*890232f2SAndroid Build Coastguard Worker        if not lastBuf then
199*890232f2SAndroid Build Coastguard Worker            lastBuf = buf
200*890232f2SAndroid Build Coastguard Worker        else
201*890232f2SAndroid Build Coastguard Worker            -- the output, sized-buffer should be identical
202*890232f2SAndroid Build Coastguard Worker            assert(lastBuf == buf, "Monster output buffers are not identical")
203*890232f2SAndroid Build Coastguard Worker        end
204*890232f2SAndroid Build Coastguard Worker        monsters[i] = monster.GetRootAsMonster(flatbuffers.binaryArray.New(buf), 0)
205*890232f2SAndroid Build Coastguard Worker    end
206*890232f2SAndroid Build Coastguard Worker
207*890232f2SAndroid Build Coastguard Worker    -- Check that all the fields for the generated monsters are as we expect
208*890232f2SAndroid Build Coastguard Worker    for i, monster in ipairs(monsters) do
209*890232f2SAndroid Build Coastguard Worker        assert(monster:Name() == "Hi there", "Monster Name is not 'Hi There' for monster "..i)
210*890232f2SAndroid Build Coastguard Worker        -- HP is default to 100 in the schema, but we change it in generateMonster to 80, so this is a good test to
211*890232f2SAndroid Build Coastguard Worker        -- see if the cleared builder really clears the data.
212*890232f2SAndroid Build Coastguard Worker        assert(monster:Hp() == 100, "HP doesn't equal the default value for monster "..i)
213*890232f2SAndroid Build Coastguard Worker        assert(monster:Mana() == 123, "Monster Mana is not '123' for monster "..i)
214*890232f2SAndroid Build Coastguard Worker        assert(monster:Pos():X() == 3.0, "Monster vec3.X is not '3' for monster "..i)
215*890232f2SAndroid Build Coastguard Worker    end
216*890232f2SAndroid Build Coastguard Workerend
217*890232f2SAndroid Build Coastguard Worker
218*890232f2SAndroid Build Coastguard Workerlocal function testCanonicalData()
219*890232f2SAndroid Build Coastguard Worker    local f = assert(io.open('monsterdata_test.mon', 'rb'))
220*890232f2SAndroid Build Coastguard Worker    local wireData = f:read("*a")
221*890232f2SAndroid Build Coastguard Worker    f:close()
222*890232f2SAndroid Build Coastguard Worker    checkReadBuffer(wireData)
223*890232f2SAndroid Build Coastguard Workerend
224*890232f2SAndroid Build Coastguard Worker
225*890232f2SAndroid Build Coastguard Workerlocal function testCreateEmptyString()
226*890232f2SAndroid Build Coastguard Worker    local b = flatbuffers.Builder(0)
227*890232f2SAndroid Build Coastguard Worker    local str = b:CreateString("")
228*890232f2SAndroid Build Coastguard Worker    monster.Start(b)
229*890232f2SAndroid Build Coastguard Worker    monster.AddName(b, str)
230*890232f2SAndroid Build Coastguard Worker    b:Finish(monster.End(b))
231*890232f2SAndroid Build Coastguard Worker    local s = b:Output()
232*890232f2SAndroid Build Coastguard Worker    local data = flatbuffers.binaryArray.New(s)
233*890232f2SAndroid Build Coastguard Worker    local mon = monster.GetRootAsMonster(data, 0)
234*890232f2SAndroid Build Coastguard Worker    assert(mon:Name() == "")
235*890232f2SAndroid Build Coastguard Workerend
236*890232f2SAndroid Build Coastguard Worker
237*890232f2SAndroid Build Coastguard Workerlocal function benchmarkMakeMonster(count, reuseBuilder)
238*890232f2SAndroid Build Coastguard Worker    local fbb = reuseBuilder and flatbuffers.Builder(0)
239*890232f2SAndroid Build Coastguard Worker    local length = #(generateMonster(false, fbb))
240*890232f2SAndroid Build Coastguard Worker
241*890232f2SAndroid Build Coastguard Worker    local s = os.clock()
242*890232f2SAndroid Build Coastguard Worker    for i=1,count do
243*890232f2SAndroid Build Coastguard Worker        generateMonster(false, fbb)
244*890232f2SAndroid Build Coastguard Worker    end
245*890232f2SAndroid Build Coastguard Worker    local e = os.clock()
246*890232f2SAndroid Build Coastguard Worker
247*890232f2SAndroid Build Coastguard Worker    local dur = (e - s)
248*890232f2SAndroid Build Coastguard Worker    local rate = count / (dur * 1000)
249*890232f2SAndroid Build Coastguard Worker    local data = (length * count) / (1024 * 1024)
250*890232f2SAndroid Build Coastguard Worker    local dataRate = data / dur
251*890232f2SAndroid Build Coastguard Worker
252*890232f2SAndroid Build Coastguard Worker    print(string.format('built %d %d-byte flatbuffers in %.2fsec: %.2f/msec, %.2fMB/sec',
253*890232f2SAndroid Build Coastguard Worker        count, length, dur, rate, dataRate))
254*890232f2SAndroid Build Coastguard Workerend
255*890232f2SAndroid Build Coastguard Worker
256*890232f2SAndroid Build Coastguard Workerlocal function benchmarkReadBuffer(count)
257*890232f2SAndroid Build Coastguard Worker    local f = assert(io.open('monsterdata_test.mon', 'rb'))
258*890232f2SAndroid Build Coastguard Worker    local buf = f:read("*a")
259*890232f2SAndroid Build Coastguard Worker    f:close()
260*890232f2SAndroid Build Coastguard Worker
261*890232f2SAndroid Build Coastguard Worker    local s = os.clock()
262*890232f2SAndroid Build Coastguard Worker    for i=1,count do
263*890232f2SAndroid Build Coastguard Worker        checkReadBuffer(buf)
264*890232f2SAndroid Build Coastguard Worker    end
265*890232f2SAndroid Build Coastguard Worker    local e = os.clock()
266*890232f2SAndroid Build Coastguard Worker
267*890232f2SAndroid Build Coastguard Worker    local dur = (e - s)
268*890232f2SAndroid Build Coastguard Worker    local rate = count / (dur * 1000)
269*890232f2SAndroid Build Coastguard Worker    local data = (#buf * count) / (1024 * 1024)
270*890232f2SAndroid Build Coastguard Worker    local dataRate = data / dur
271*890232f2SAndroid Build Coastguard Worker
272*890232f2SAndroid Build Coastguard Worker    print(string.format('traversed %d %d-byte flatbuffers in %.2fsec: %.2f/msec, %.2fMB/sec',
273*890232f2SAndroid Build Coastguard Worker        count, #buf, dur, rate, dataRate))
274*890232f2SAndroid Build Coastguard Workerend
275*890232f2SAndroid Build Coastguard Worker
276*890232f2SAndroid Build Coastguard Workerlocal function getRootAs_canAcceptString()
277*890232f2SAndroid Build Coastguard Worker    local f = assert(io.open('monsterdata_test.mon', 'rb'))
278*890232f2SAndroid Build Coastguard Worker    local wireData = f:read("*a")
279*890232f2SAndroid Build Coastguard Worker    f:close()
280*890232f2SAndroid Build Coastguard Worker    assert(type(wireData) == "string", "Data is not a string");
281*890232f2SAndroid Build Coastguard Worker    local mon = monster.GetRootAsMonster(wireData, 0)
282*890232f2SAndroid Build Coastguard Worker    assert(mon:Hp() == 80, "Monster Hp is not 80")
283*890232f2SAndroid Build Coastguard Workerend
284*890232f2SAndroid Build Coastguard Worker
285*890232f2SAndroid Build Coastguard Workerlocal function testAccessByteVectorAsString()
286*890232f2SAndroid Build Coastguard Worker    local f = assert(io.open('monsterdata_test.mon', 'rb'))
287*890232f2SAndroid Build Coastguard Worker    local wireData = f:read("*a")
288*890232f2SAndroid Build Coastguard Worker    f:close()
289*890232f2SAndroid Build Coastguard Worker    local mon = monster.GetRootAsMonster(wireData, 0)
290*890232f2SAndroid Build Coastguard Worker    -- the data of byte array Inventory is [0, 1, 2, 3, 4]
291*890232f2SAndroid Build Coastguard Worker    local s = mon:InventoryAsString(1, 3)
292*890232f2SAndroid Build Coastguard Worker    assert(#s == 3)
293*890232f2SAndroid Build Coastguard Worker    for i = 1, #s do
294*890232f2SAndroid Build Coastguard Worker        assert(string.byte(s, i) == i - 1)
295*890232f2SAndroid Build Coastguard Worker    end
296*890232f2SAndroid Build Coastguard Worker
297*890232f2SAndroid Build Coastguard Worker    local s = mon:InventoryAsString(2, 5)
298*890232f2SAndroid Build Coastguard Worker    assert(#s == 4)
299*890232f2SAndroid Build Coastguard Worker    for i = 1, #s do
300*890232f2SAndroid Build Coastguard Worker        assert(string.byte(s, i) == i)
301*890232f2SAndroid Build Coastguard Worker    end
302*890232f2SAndroid Build Coastguard Worker
303*890232f2SAndroid Build Coastguard Worker    local s = mon:InventoryAsString(5, 5)
304*890232f2SAndroid Build Coastguard Worker    assert(#s == 1)
305*890232f2SAndroid Build Coastguard Worker    assert(string.byte(s, 1) == 4)
306*890232f2SAndroid Build Coastguard Worker
307*890232f2SAndroid Build Coastguard Worker    local s = mon:InventoryAsString(2)
308*890232f2SAndroid Build Coastguard Worker    assert(#s == 4)
309*890232f2SAndroid Build Coastguard Worker    for i = 1, #s do
310*890232f2SAndroid Build Coastguard Worker        assert(string.byte(s, i) == i)
311*890232f2SAndroid Build Coastguard Worker    end
312*890232f2SAndroid Build Coastguard Worker
313*890232f2SAndroid Build Coastguard Worker    local s = mon:InventoryAsString()
314*890232f2SAndroid Build Coastguard Worker    assert(#s == 5)
315*890232f2SAndroid Build Coastguard Worker    for i = 1, #s do
316*890232f2SAndroid Build Coastguard Worker        assert(string.byte(s, i) == i - 1)
317*890232f2SAndroid Build Coastguard Worker    end
318*890232f2SAndroid Build Coastguard Workerend
319*890232f2SAndroid Build Coastguard Worker
320*890232f2SAndroid Build Coastguard Workerlocal tests =
321*890232f2SAndroid Build Coastguard Worker{
322*890232f2SAndroid Build Coastguard Worker    {
323*890232f2SAndroid Build Coastguard Worker        f = sizePrefix,
324*890232f2SAndroid Build Coastguard Worker        d = "Test size prefix",
325*890232f2SAndroid Build Coastguard Worker        args = {{true}, {false}}
326*890232f2SAndroid Build Coastguard Worker    },
327*890232f2SAndroid Build Coastguard Worker    {
328*890232f2SAndroid Build Coastguard Worker        f = fbbClear,
329*890232f2SAndroid Build Coastguard Worker        d = "FlatBufferBuilder Clear",
330*890232f2SAndroid Build Coastguard Worker    },
331*890232f2SAndroid Build Coastguard Worker    {
332*890232f2SAndroid Build Coastguard Worker        f = testCanonicalData,
333*890232f2SAndroid Build Coastguard Worker        d = "Tests Canonical flatbuffer file included in repo"
334*890232f2SAndroid Build Coastguard Worker    },
335*890232f2SAndroid Build Coastguard Worker    {
336*890232f2SAndroid Build Coastguard Worker        f = testCreateEmptyString,
337*890232f2SAndroid Build Coastguard Worker        d = "Avoid infinite loop when creating empty string"
338*890232f2SAndroid Build Coastguard Worker    },
339*890232f2SAndroid Build Coastguard Worker    {
340*890232f2SAndroid Build Coastguard Worker        f = getRootAs_canAcceptString,
341*890232f2SAndroid Build Coastguard Worker        d = "Tests that GetRootAs<type>() generated methods accept strings"
342*890232f2SAndroid Build Coastguard Worker    },
343*890232f2SAndroid Build Coastguard Worker    {
344*890232f2SAndroid Build Coastguard Worker        f = testAccessByteVectorAsString,
345*890232f2SAndroid Build Coastguard Worker        d = "Access byte vector as string"
346*890232f2SAndroid Build Coastguard Worker    },
347*890232f2SAndroid Build Coastguard Worker}
348*890232f2SAndroid Build Coastguard Worker
349*890232f2SAndroid Build Coastguard Workerlocal benchmarks =
350*890232f2SAndroid Build Coastguard Worker{
351*890232f2SAndroid Build Coastguard Worker    {
352*890232f2SAndroid Build Coastguard Worker        f = benchmarkMakeMonster,
353*890232f2SAndroid Build Coastguard Worker        d = "Benchmark making monsters",
354*890232f2SAndroid Build Coastguard Worker        args = {
355*890232f2SAndroid Build Coastguard Worker            {100},
356*890232f2SAndroid Build Coastguard Worker            {1000},
357*890232f2SAndroid Build Coastguard Worker            {10000},
358*890232f2SAndroid Build Coastguard Worker            {10000, true}
359*890232f2SAndroid Build Coastguard Worker        }
360*890232f2SAndroid Build Coastguard Worker    },
361*890232f2SAndroid Build Coastguard Worker    {
362*890232f2SAndroid Build Coastguard Worker        f = benchmarkReadBuffer,
363*890232f2SAndroid Build Coastguard Worker        d = "Benchmark reading monsters",
364*890232f2SAndroid Build Coastguard Worker        args = {
365*890232f2SAndroid Build Coastguard Worker            {100},
366*890232f2SAndroid Build Coastguard Worker            {1000},
367*890232f2SAndroid Build Coastguard Worker            {10000},
368*890232f2SAndroid Build Coastguard Worker            -- uncomment following to run 1 million to compare.
369*890232f2SAndroid Build Coastguard Worker            -- Took ~141 seconds on my machine
370*890232f2SAndroid Build Coastguard Worker            --{1000000},
371*890232f2SAndroid Build Coastguard Worker        }
372*890232f2SAndroid Build Coastguard Worker    },
373*890232f2SAndroid Build Coastguard Worker}
374*890232f2SAndroid Build Coastguard Worker
375*890232f2SAndroid Build Coastguard Workerlocal result, err = xpcall(function()
376*890232f2SAndroid Build Coastguard Worker    flatbuffers = assert(require("flatbuffers"))
377*890232f2SAndroid Build Coastguard Worker    monster = assert(require("MyGame.Example.Monster"))
378*890232f2SAndroid Build Coastguard Worker    test = assert(require("MyGame.Example.Test"))
379*890232f2SAndroid Build Coastguard Worker    vec3 = assert(require("MyGame.Example.Vec3"))
380*890232f2SAndroid Build Coastguard Worker
381*890232f2SAndroid Build Coastguard Worker    local function buildArgList(tbl)
382*890232f2SAndroid Build Coastguard Worker        local s = ""
383*890232f2SAndroid Build Coastguard Worker        for _,item in ipairs(tbl) do
384*890232f2SAndroid Build Coastguard Worker            s = s .. tostring(item) .. ","
385*890232f2SAndroid Build Coastguard Worker        end
386*890232f2SAndroid Build Coastguard Worker        return s:sub(1,-2)
387*890232f2SAndroid Build Coastguard Worker    end
388*890232f2SAndroid Build Coastguard Worker
389*890232f2SAndroid Build Coastguard Worker    if performBenchmarkTests then
390*890232f2SAndroid Build Coastguard Worker        for _,benchmark in ipairs(benchmarks) do
391*890232f2SAndroid Build Coastguard Worker            table.insert(tests, benchmark)
392*890232f2SAndroid Build Coastguard Worker        end
393*890232f2SAndroid Build Coastguard Worker    end
394*890232f2SAndroid Build Coastguard Worker
395*890232f2SAndroid Build Coastguard Worker    local testsPassed, testsFailed = 0,0
396*890232f2SAndroid Build Coastguard Worker    for _,test in ipairs(tests) do
397*890232f2SAndroid Build Coastguard Worker        local allargs = test.args or {{}}
398*890232f2SAndroid Build Coastguard Worker        for _,args in ipairs(allargs) do
399*890232f2SAndroid Build Coastguard Worker            local results, err = xpcall(test.f,debug.traceback, table.unpack(args))
400*890232f2SAndroid Build Coastguard Worker            if results then
401*890232f2SAndroid Build Coastguard Worker                testsPassed = testsPassed + 1
402*890232f2SAndroid Build Coastguard Worker            else
403*890232f2SAndroid Build Coastguard Worker                testsFailed = testsFailed + 1
404*890232f2SAndroid Build Coastguard Worker                print(string.format(" Test [%s](%s) failed: \n\t%s",
405*890232f2SAndroid Build Coastguard Worker                        test.d or "",
406*890232f2SAndroid Build Coastguard Worker                        buildArgList(args),
407*890232f2SAndroid Build Coastguard Worker                        err))
408*890232f2SAndroid Build Coastguard Worker            end
409*890232f2SAndroid Build Coastguard Worker        end
410*890232f2SAndroid Build Coastguard Worker    end
411*890232f2SAndroid Build Coastguard Worker
412*890232f2SAndroid Build Coastguard Worker    local totalTests = testsPassed + testsFailed
413*890232f2SAndroid Build Coastguard Worker    print(string.format("# of test passed: %d / %d (%.2f%%)",
414*890232f2SAndroid Build Coastguard Worker        testsPassed,
415*890232f2SAndroid Build Coastguard Worker        totalTests,
416*890232f2SAndroid Build Coastguard Worker        totalTests ~= 0
417*890232f2SAndroid Build Coastguard Worker            and 100 * (testsPassed / totalTests)
418*890232f2SAndroid Build Coastguard Worker            or 0)
419*890232f2SAndroid Build Coastguard Worker        )
420*890232f2SAndroid Build Coastguard Worker
421*890232f2SAndroid Build Coastguard Worker    return 0
422*890232f2SAndroid Build Coastguard Workerend, debug.traceback)
423*890232f2SAndroid Build Coastguard Worker
424*890232f2SAndroid Build Coastguard Workerif not result then
425*890232f2SAndroid Build Coastguard Worker    print("Unable to run tests due to test framework error: ",err)
426*890232f2SAndroid Build Coastguard Workerend
427*890232f2SAndroid Build Coastguard Worker
428*890232f2SAndroid Build Coastguard Workeros.exit(result and 0 or -1)
429