• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--[[--------------------------------------------------------------------------
2
3Protocol Buffers - Google's data interchange format
4Copyright 2023 Google LLC.  All rights reserved.
5
6Use of this source code is governed by a BSD-style
7license that can be found in the LICENSE file or at
8https://developers.google.com/open-source/licenses/bsd
9
10--]]--------------------------------------------------------------------------
11
12local upb = require "lupb"
13local lunit = require "lunit"
14local upb_test = require "lua.test_pb"
15local test_messages_proto3 = require "google.protobuf.test_messages_proto3_pb"
16local test_messages_proto2 = require "google.protobuf.test_messages_proto2_pb"
17local descriptor = require "google.protobuf.descriptor_pb"
18local empty = require "google.protobuf.empty_pb"
19
20if _VERSION >= 'Lua 5.2' then
21  _ENV = lunit.module("testupb", "seeall")
22else
23  module("testupb", lunit.testcase, package.seeall)
24end
25
26function iter_to_array(iter)
27  local arr = {}
28  for v in iter do
29    arr[#arr + 1] = v
30  end
31  return arr
32end
33
34function test_def_readers()
35  local m = test_messages_proto3.TestAllTypesProto3
36  assert_equal("TestAllTypesProto3", m:name())
37  assert_equal("protobuf_test_messages.proto3.TestAllTypesProto3", m:full_name())
38
39  -- field
40  local f = m:field("optional_int32")
41  local f2 = m:field(1)
42  assert_equal(f, f2)
43  assert_equal(1, f:number())
44  assert_equal("optional_int32", f:name())
45  assert_equal(upb.LABEL_OPTIONAL, f:label())
46  assert_equal(upb.DESCRIPTOR_TYPE_INT32, f:descriptor_type())
47  assert_equal(upb.TYPE_INT32, f:type())
48  assert_nil(f:containing_oneof())
49  assert_equal(m, f:containing_type())
50  assert_equal(0, f:default())
51  local message_field_count = 0
52  for field in m:fields() do
53    message_field_count = message_field_count + 1
54  end
55  assert_equal(message_field_count, #m)
56
57  local message_oneof_count = 0
58  for oneof in m:oneofs() do
59    message_oneof_count = message_oneof_count + 1
60  end
61  assert_equal(message_oneof_count, m:oneof_count())
62
63  -- oneof
64  local o = m:lookup_name("oneof_field")
65  assert_equal("oneof_field", o:name())
66  assert_equal(m, o:containing_type())
67  local oneof_field_count = 0
68  for field in o:fields() do
69    oneof_field_count = oneof_field_count + 1
70  end
71  assert_equal(oneof_field_count, #o)
72
73  -- enum
74  local e = test_messages_proto3['TestAllTypesProto3.NestedEnum']
75  assert_true(#e > 3 and #e < 10)
76  assert_equal(2, e:value("BAZ"):number())
77end
78
79function test_msg_map()
80  msg = test_messages_proto3.TestAllTypesProto3()
81  msg.map_int32_int32[5] = 10
82  msg.map_int32_int32[6] = 12
83  assert_equal(10, msg.map_int32_int32[5])
84  assert_equal(12, msg.map_int32_int32[6])
85
86  -- Test overwrite.
87  msg.map_int32_int32[5] = 20
88  assert_equal(20, msg.map_int32_int32[5])
89  assert_equal(12, msg.map_int32_int32[6])
90  msg.map_int32_int32[5] = 10
91
92  -- Test delete.
93  msg.map_int32_int32[5] = nil
94  assert_nil(msg.map_int32_int32[5])
95  assert_equal(12, msg.map_int32_int32[6])
96  msg.map_int32_int32[5] = 10
97
98  local serialized = upb.encode(msg)
99  assert_true(#serialized > 0)
100  local msg2 = upb.decode(test_messages_proto3.TestAllTypesProto3, serialized)
101  assert_equal(10, msg2.map_int32_int32[5])
102  assert_equal(12, msg2.map_int32_int32[6])
103end
104
105function test_map_sorting()
106  function msg_with_int32_entries(start, expand)
107    local msg = test_messages_proto3.TestAllTypesProto3()
108    for i=start,start + 8 do
109      msg.map_int32_int32[i] = i * 2
110    end
111
112    if expand then
113      for i=start+20,200 do
114        msg.map_int32_int32[i] = i
115      end
116      for i=start+20,200 do
117        msg.map_int32_int32[i] = nil
118      end
119    end
120    return msg
121  end
122
123  function msg_with_msg_entries(expand)
124    local msg = test_messages_proto3.TestAllTypesProto3()
125    -- 8! = 40320 possible orderings makes it overwhelmingly likely that two
126    -- random orderings will be different.
127    for i=1,8 do
128      local submsg = test_messages_proto3.TestAllTypesProto3.NestedMessage()
129      submsg.corecursive = msg_with_int32_entries(i, expand)
130      msg.map_string_nested_message[tostring(i)] = submsg
131    end
132
133    expand = false
134    if expand then
135      for i=21,2000 do
136        local submsg = test_messages_proto3.TestAllTypesProto3.NestedMessage()
137        submsg.corecursive = msg_with_int32_entries(i, expand)
138        msg.map_string_nested_message[tostring(i)] = submsg
139      end
140      for i=21,2000 do
141        msg.map_string_nested_message[tostring(i)] = nil
142      end
143    end
144    return msg
145  end
146
147  -- Create two messages with the same contents but (hopefully) different
148  -- map table orderings.
149  local msg = msg_with_msg_entries(false)
150  local msg2 = msg_with_msg_entries(true)
151
152  local text1 = upb.text_encode(msg)
153  local text2 = upb.text_encode(msg2)
154  assert_equal(text1, text2)
155
156  local binary1 = upb.encode(msg, {upb.ENCODE_DETERMINISTIC})
157  local binary2 = upb.encode(msg2, {upb.ENCODE_DETERMINISTIC})
158  assert_equal(binary1, binary2)
159
160  -- Non-sorted map should compare different.
161  local text3 = upb.text_encode(msg, {upb.TXTENC_NOSORT})
162  assert_not_equal(text1, text3)
163
164  local binary3 = upb.encode(msg)
165  assert_not_equal(binary1, binary3)
166end
167
168function test_utf8()
169  local proto2_msg = test_messages_proto2.TestAllTypesProto2()
170  proto2_msg.optional_string = "\xff"
171  local serialized = upb.encode(proto2_msg)
172
173  -- Decoding invalid UTF-8 succeeds in proto2.
174  upb.decode(test_messages_proto2.TestAllTypesProto2, serialized)
175
176  -- Decoding invalid UTF-8 fails in proto2.
177  assert_error_match("Error decoding protobuf", function()
178    upb.decode(test_messages_proto3.TestAllTypesProto3, serialized)
179  end)
180
181  -- TODO: should proto3 accessors also check UTF-8 at set time?
182end
183
184function test_string_double_map()
185  msg = upb_test.MapTest()
186  msg.map_string_double["one"] = 1.0
187  msg.map_string_double["two point five"] = 2.5
188  assert_equal(1, msg.map_string_double["one"])
189  assert_equal(2.5, msg.map_string_double["two point five"])
190
191  -- Test overwrite.
192  msg.map_string_double["one"] = 2
193  assert_equal(2, msg.map_string_double["one"])
194  assert_equal(2.5, msg.map_string_double["two point five"])
195  msg.map_string_double["one"] = 1.0
196
197  -- Test delete.
198  msg.map_string_double["one"] = nil
199  assert_nil(msg.map_string_double["one"])
200  assert_equal(2.5, msg.map_string_double["two point five"])
201  msg.map_string_double["one"] = 1
202
203  local serialized = upb.encode(msg)
204  assert_true(#serialized > 0)
205  local msg2 = upb.decode(upb_test.MapTest, serialized)
206  assert_equal(1, msg2.map_string_double["one"])
207  assert_equal(2.5, msg2.map_string_double["two point five"])
208end
209
210function test_string_double_map()
211  local function fill_msg(msg)
212    msg.i32_packed[1] = 100
213    msg.i32_packed[2] = 200
214    msg.i32_packed[3] = 50000
215
216    msg.i64_packed[1] = 101
217    msg.i64_packed[2] = 201
218    msg.i64_packed[3] = 50001
219
220    msg.f32_packed[1] = 102
221    msg.f32_packed[2] = 202
222    msg.f32_packed[3] = 50002
223
224    msg.f64_packed[1] = 103
225    msg.f64_packed[2] = 203
226    msg.f64_packed[3] = 50003
227  end
228
229  local function check_msg(msg)
230    assert_equal(100, msg.i32_packed[1])
231    assert_equal(200, msg.i32_packed[2])
232    assert_equal(50000, msg.i32_packed[3])
233    assert_equal(3, #msg.i32_packed)
234
235    assert_equal(101, msg.i64_packed[1])
236    assert_equal(201, msg.i64_packed[2])
237    assert_equal(50001, msg.i64_packed[3])
238    assert_equal(3, #msg.i64_packed)
239
240    assert_equal(102, msg.f32_packed[1])
241    assert_equal(202, msg.f32_packed[2])
242    assert_equal(50002, msg.f32_packed[3])
243    assert_equal(3, #msg.f32_packed)
244
245    assert_equal(103, msg.f64_packed[1])
246    assert_equal(203, msg.f64_packed[2])
247    assert_equal(50003, msg.f64_packed[3])
248    assert_equal(3, #msg.f64_packed)
249  end
250
251  local msg = upb_test.PackedTest()
252  fill_msg(msg)
253  check_msg(msg)
254
255  local serialized_packed = upb.encode(msg)
256  local msg2 = upb.decode(upb_test.PackedTest, serialized_packed)
257  local msg3 = upb.decode(upb_test.UnpackedTest, serialized_packed)
258  check_msg(msg2)
259  check_msg(msg3)
260
261  serialized_unpacked = upb.encode(msg3)
262  local msg4 = upb.decode(upb_test.PackedTest, serialized_unpacked)
263  local msg5 = upb.decode(upb_test.PackedTest, serialized_unpacked)
264  check_msg(msg4)
265  check_msg(msg5)
266
267end
268
269function test_msg_string_map()
270  msg = test_messages_proto3.TestAllTypesProto3()
271  msg.map_string_string["foo"] = "bar"
272  msg.map_string_string["baz"] = "quux"
273  assert_nil(msg.map_string_string["abc"])
274  assert_equal("bar", msg.map_string_string["foo"])
275  assert_equal("quux", msg.map_string_string["baz"])
276
277  -- Test overwrite.
278  msg.map_string_string["foo"] = "123"
279  assert_equal("123", msg.map_string_string["foo"])
280  assert_equal("quux", msg.map_string_string["baz"])
281  msg.map_string_string["foo"] = "bar"
282
283  -- Test delete
284  msg.map_string_string["foo"] = nil
285  assert_nil(msg.map_string_string["foo"])
286  assert_equal("quux", msg.map_string_string["baz"])
287  msg.map_string_string["foo"] = "bar"
288
289  local serialized = upb.encode(msg)
290  assert_true(#serialized > 0)
291  local msg2 = upb.decode(test_messages_proto3.TestAllTypesProto3, serialized)
292  assert_equal("bar", msg2.map_string_string["foo"])
293  assert_equal("quux", msg2.map_string_string["baz"])
294end
295
296function test_msg_array()
297  msg = test_messages_proto3.TestAllTypesProto3()
298
299  assert_not_nil(msg.repeated_int32)
300  assert_equal(msg.repeated_int32, msg.repeated_int32)
301  assert_equal(0, #msg.repeated_int32)
302
303  msg.repeated_int32[1] = 2
304  assert_equal(1, #msg.repeated_int32);
305  assert_equal(2, msg.repeated_int32[1]);
306
307  -- Can't assign a scalar; array is expected.
308  assert_error_match("lupb.array expected", function() msg.repeated_int32 = 5 end)
309
310  -- Can't assign array of the wrong type.
311  local function assign_int64()
312    msg.repeated_int32 = upb.Array(upb.TYPE_INT64)
313  end
314  assert_error_match("array type mismatch", assign_int64)
315
316  local arr = upb.Array(upb.TYPE_INT32)
317  arr[1] = 6
318  assert_equal(1, #arr)
319  msg.repeated_int32 = arr
320  assert_equal(msg.repeated_int32, msg.repeated_int32)
321  assert_equal(arr, msg.repeated_int32)
322  assert_equal(1, #msg.repeated_int32)
323  assert_equal(6, msg.repeated_int32[1])
324
325  -- Can't assign other Lua types.
326  assert_error_match("array expected", function() msg.repeated_int32 = "abc" end)
327  assert_error_match("array expected", function() msg.repeated_int32 = true end)
328  assert_error_match("array expected", function() msg.repeated_int32 = false end)
329  assert_error_match("array expected", function() msg.repeated_int32 = nil end)
330  assert_error_match("array expected", function() msg.repeated_int32 = {} end)
331  assert_error_match("array expected", function() msg.repeated_int32 = print end)
332end
333
334function test_array_append()
335  local arr = upb.Array(upb.TYPE_INT32)
336  for i=1,200000 do
337    arr[i] = i
338  end
339  for i=1,200000 do
340    assert_equal(i, arr[i])
341  end
342end
343
344function test_msg_submsg()
345  --msg = test_messages_proto3.TestAllTypesProto3()
346  msg = test_messages_proto3['TestAllTypesProto3']()
347
348  assert_nil(msg.optional_nested_message)
349
350  -- Can't assign message of the wrong type.
351  local function assign_int64()
352    msg.optional_nested_message = test_messages_proto3.TestAllTypesProto3()
353  end
354  assert_error_match("message type mismatch", assign_int64)
355
356  local nested = test_messages_proto3['TestAllTypesProto3.NestedMessage']()
357  msg.optional_nested_message = nested
358  assert_equal(nested, msg.optional_nested_message)
359
360  -- Can't assign other Lua types.
361  assert_error_match("msg expected", function() msg.optional_nested_message = "abc" end)
362  assert_error_match("msg expected", function() msg.optional_nested_message = true end)
363  assert_error_match("msg expected", function() msg.optional_nested_message = false end)
364  assert_error_match("msg expected", function() msg.optional_nested_message = nil end)
365  assert_error_match("msg expected", function() msg.optional_nested_message = {} end)
366  assert_error_match("msg expected", function() msg.optional_nested_message = print end)
367end
368
369-- Lua 5.1 and 5.2 have slightly different semantics for how a finalizer
370-- can be defined in Lua.
371if _VERSION >= 'Lua 5.2' then
372  function defer(fn)
373    setmetatable({}, { __gc = fn })
374  end
375else
376  function defer(fn)
377    getmetatable(newproxy(true)).__gc = fn
378  end
379end
380
381function test_finalizer()
382  -- Tests that we correctly handle a call into an already-finalized object.
383  -- Collectible objects are finalized in the opposite order of creation.
384  do
385    local t = {}
386    defer(function()
387      assert_error_match("called into dead object", function()
388        -- Generic def call.
389        t[1]:lookup_msg("abc")
390      end)
391    end)
392    t = {
393      upb.DefPool(),
394    }
395  end
396  collectgarbage()
397end
398
399-- in-range of 64-bit types but not exactly representable as double
400local bad64 = 2^68 - 1
401
402local numeric_types = {
403  [upb.TYPE_UINT32] = {
404    valid_val = 2^32 - 1,
405    too_big = 2^32,
406    too_small = -1,
407    other_bad = 5.1
408  },
409  [upb.TYPE_UINT64] = {
410    valid_val = 2^63,
411    too_big = 2^64,
412    too_small = -1,
413    other_bad = bad64
414  },
415  [upb.TYPE_INT32] = {
416    valid_val = 2^31 - 1,
417    too_big = 2^31,
418    too_small = -2^31 - 1,
419    other_bad = 5.1
420  },
421  -- Enums don't exist at a language level in Lua, so we just represent enum
422  -- values as int32s.
423  [upb.TYPE_ENUM] = {
424    valid_val = 2^31 - 1,
425    too_big = 2^31,
426    too_small = -2^31 - 1,
427    other_bad = 5.1
428  },
429  [upb.TYPE_INT64] = {
430    valid_val = 2^62,
431    too_big = 2^63,
432    too_small = -2^64,
433    other_bad = bad64
434  },
435  [upb.TYPE_FLOAT] = {
436    valid_val = 340282306073709652508363335590014353408
437  },
438  [upb.TYPE_DOUBLE] = {
439    valid_val = 10^101
440  },
441}
442
443function test_utf8()
444  local invalid_utf8 = "\xff"
445  local proto2_msg = test_messages_proto2.TestAllTypesProto2{
446    optional_string = invalid_utf8,
447  }
448
449  -- As proto2, invalid UTF-8 parses and serializes fine.
450  local serialized = upb.encode(proto2_msg)
451  local proto2_msg2 = upb.decode(test_messages_proto2.TestAllTypesProto2, serialized)
452
453  -- Decoding as proto3 fails.
454  assert_error(function()
455    upb.decode(test_messages_proto3.TestAllTypesProto3, serialized)
456  end)
457end
458
459function test_msg_primitives()
460  local msg = test_messages_proto3.TestAllTypesProto3{
461    optional_int32 = 10,
462    optional_uint32 = 20,
463    optional_int64 = 30,
464    optional_uint64 = 40,
465    optional_double = 50,
466    optional_float = 60,
467    optional_sint32 = 70,
468    optional_sint64 = 80,
469    optional_fixed32 = 90,
470    optional_fixed64 = 100,
471    optional_sfixed32 = 110,
472    optional_sfixed64 = 120,
473    optional_bool = true,
474    optional_string = "abc",
475    optional_nested_message = test_messages_proto3['TestAllTypesProto3.NestedMessage']{a = 123},
476  }
477
478  -- Attempts to access non-existent fields fail.
479  assert_error_match("no such field", function() msg.no_such = 1 end)
480
481  assert_equal(10, msg.optional_int32)
482  assert_equal(20, msg.optional_uint32)
483  assert_equal(30, msg.optional_int64)
484  assert_equal(40, msg.optional_uint64)
485  assert_equal(50, msg.optional_double)
486  assert_equal(60, msg.optional_float)
487  assert_equal(70, msg.optional_sint32)
488  assert_equal(80, msg.optional_sint64)
489  assert_equal(90, msg.optional_fixed32)
490  assert_equal(100, msg.optional_fixed64)
491  assert_equal(110, msg.optional_sfixed32)
492  assert_equal(120, msg.optional_sfixed64)
493  assert_equal(true, msg.optional_bool)
494  assert_equal("abc", msg.optional_string)
495  assert_equal(123, msg.optional_nested_message.a)
496end
497
498
499function test_string_array()
500  local function test_for_string_type(upb_type)
501    local array = upb.Array(upb_type)
502    assert_equal(0, #array)
503
504    -- 0 is never a valid index in Lua.
505    assert_error_match("array index", function() return array[0] end)
506    -- Past the end of the array.
507    assert_error_match("array index", function() return array[1] end)
508
509    array[1] = "foo"
510    assert_equal("foo", array[1])
511    assert_equal(1, #array)
512    -- Past the end of the array.
513    assert_error_match("array index", function() return array[2] end)
514
515    local array2 = upb.Array(upb_type)
516    assert_equal(0, #array2)
517
518    array[2] = "bar"
519    assert_equal("foo", array[1])
520    assert_equal("bar", array[2])
521    assert_equal(2, #array)
522    -- Past the end of the array.
523    assert_error_match("array index", function() return array[3] end)
524
525    -- Can't assign other Lua types.
526    assert_error_match("Expected string", function() array[3] = 123 end)
527    assert_error_match("Expected string", function() array[3] = true end)
528    assert_error_match("Expected string", function() array[3] = false end)
529    assert_error_match("Expected string", function() array[3] = nil end)
530    assert_error_match("Expected string", function() array[3] = {} end)
531    assert_error_match("Expected string", function() array[3] = print end)
532    assert_error_match("Expected string", function() array[3] = array end)
533  end
534
535  test_for_string_type(upb.TYPE_STRING)
536  test_for_string_type(upb.TYPE_BYTES)
537end
538
539function test_numeric_array()
540  local function test_for_numeric_type(upb_type)
541    local array = upb.Array(upb_type)
542    local vals = numeric_types[upb_type]
543    assert_equal(0, #array)
544
545    -- 0 is never a valid index in Lua.
546    assert_error_match("array index", function() return array[0] end)
547    -- Past the end of the array.
548    assert_error_match("array index", function() return array[1] end)
549
550    array[1] = vals.valid_val
551    assert_equal(vals.valid_val, array[1])
552    assert_equal(1, #array)
553    assert_equal(vals.valid_val, array[1])
554    -- Past the end of the array.
555    assert_error_match("array index", function() return array[2] end)
556
557    array[2] = 10
558    assert_equal(vals.valid_val, array[1])
559    assert_equal(10, array[2])
560    assert_equal(2, #array)
561    -- Past the end of the array.
562    assert_error_match("array index", function() return array[3] end)
563
564    -- Values that are out of range.
565    local errmsg = "not an integer or out of range"
566    if vals.too_small then
567      assert_error_match(errmsg, function() array[3] = vals.too_small end)
568    end
569    if vals.too_big then
570      assert_error_match(errmsg, function() array[3] = vals.too_big end)
571    end
572    if vals.other_bad then
573      assert_error_match(errmsg, function() array[3] = vals.other_bad end)
574    end
575
576    -- Can't assign other Lua types.
577    errmsg = "bad argument #3"
578    assert_error_match(errmsg, function() array[3] = "abc" end)
579    assert_error_match(errmsg, function() array[3] = true end)
580    assert_error_match(errmsg, function() array[3] = false end)
581    assert_error_match(errmsg, function() array[3] = nil end)
582    assert_error_match(errmsg, function() array[3] = {} end)
583    assert_error_match(errmsg, function() array[3] = print end)
584    assert_error_match(errmsg, function() array[3] = array end)
585  end
586
587  for k in pairs(numeric_types) do
588    test_for_numeric_type(k)
589  end
590end
591
592function test_numeric_map()
593  local function test_for_numeric_types(key_type, val_type)
594    local map = upb.Map(key_type, val_type)
595    local key_vals = numeric_types[key_type]
596    local val_vals = numeric_types[val_type]
597
598    assert_equal(0, #map)
599
600    -- Unset keys return nil
601    assert_nil(map[key_vals.valid_val])
602
603    map[key_vals.valid_val] = val_vals.valid_val
604    assert_equal(1, #map)
605    assert_equal(val_vals.valid_val, map[key_vals.valid_val])
606
607    i = 0
608    for k, v in pairs(map) do
609      assert_equal(key_vals.valid_val, k)
610      assert_equal(val_vals.valid_val, v)
611    end
612
613    -- Out of range key/val
614    local errmsg = "not an integer or out of range"
615    if key_vals.too_small then
616      assert_error_match(errmsg, function() map[key_vals.too_small] = 1 end)
617    end
618    if key_vals.too_big then
619      assert_error_match(errmsg, function() map[key_vals.too_big] = 1 end)
620    end
621    if key_vals.other_bad then
622      assert_error_match(errmsg, function() map[key_vals.other_bad] = 1 end)
623    end
624
625    if val_vals.too_small then
626      assert_error_match(errmsg, function() map[1] = val_vals.too_small end)
627    end
628    if val_vals.too_big then
629      assert_error_match(errmsg, function() map[1] = val_vals.too_big end)
630    end
631    if val_vals.other_bad then
632      assert_error_match(errmsg, function() map[1] = val_vals.other_bad end)
633    end
634  end
635
636  for k in pairs(numeric_types) do
637    for v in pairs(numeric_types) do
638      test_for_numeric_types(k, v)
639    end
640  end
641end
642
643function test_unknown()
644  local bytes = string.rep("\x38\x00", 1000)
645  for i=1,1000 do
646    local msg = upb.decode(test_messages_proto3.TestAllTypesProto3, bytes)
647  end
648end
649
650function test_foo()
651  local defpool = upb.DefPool()
652  local filename = "external/com_google_protobuf/src/google/protobuf/descriptor_proto-descriptor-set.proto.bin"
653  local alternate_filename = "src/google/protobuf/descriptor_proto-descriptor-set.proto.bin"
654  local file = io.open(filename, "rb") or io.open("bazel-bin/" .. filename, "rb") or io.open(alternate_filename, "rb")
655  assert_not_nil(file)
656  local descriptor = file:read("*a")
657  assert_true(#descriptor > 0)
658  defpool:add_set(descriptor)
659  local FileDescriptorSet = defpool:lookup_msg("google.protobuf.FileDescriptorSet")
660  assert_not_nil(FileDescriptorSet)
661  set = FileDescriptorSet()
662  assert_equal(#set.file, 0)
663  assert_error_match("lupb.array expected", function () set.file = 1 end)
664
665  set = upb.decode(FileDescriptorSet, descriptor)
666
667  -- Test that we can at least call this without crashing.
668  set_textformat = tostring(set)
669
670  -- print(set_textformat)
671  assert_equal(#set.file, 1)
672  assert_equal(set.file[1].name, "google/protobuf/descriptor.proto")
673end
674
675function test_descriptor()
676  local defpool = upb.DefPool()
677  local file_proto = descriptor.FileDescriptorProto {
678    name = "test.proto",
679    message_type = upb.Array(descriptor.DescriptorProto, {
680      descriptor.DescriptorProto{
681        name = "ABC",
682      },
683    })
684  }
685  local file = defpool:add_file(upb.encode(file_proto))
686  assert_equal(file:defpool(), defpool)
687end
688
689function test_descriptor_error()
690  local defpool = upb.DefPool()
691  local file = descriptor.FileDescriptorProto()
692  file.name = "test.proto"
693  file.message_type[1] = descriptor.DescriptorProto{
694    name = "ABC"
695  }
696  file.message_type[2] = descriptor.DescriptorProto{
697    name = "BC."
698  }
699  assert_error(function () defpool:add_file(upb.encode(file)) end)
700  assert_nil(defpool:lookup_msg("ABC"))
701end
702
703function test_duplicate_enumval()
704  local defpool = upb.DefPool()
705  local file_proto = descriptor.FileDescriptorProto {
706    name = "test.proto",
707    message_type = upb.Array(descriptor.DescriptorProto, {
708      descriptor.DescriptorProto{
709        name = "ABC",
710      },
711    }),
712    enum_type = upb.Array(descriptor.EnumDescriptorProto, {
713      descriptor.EnumDescriptorProto{
714        name = "MyEnum",
715        value = upb.Array(descriptor.EnumValueDescriptorProto, {
716          descriptor.EnumValueDescriptorProto{
717            name = "ABC",
718            number = 1,
719          }
720        }),
721      },
722    })
723  }
724  assert_error(function () defpool:add_file(upb.encode(file_proto)) end)
725end
726
727function test_duplicate_filename_error()
728  local defpool = upb.DefPool()
729  local file = descriptor.FileDescriptorProto()
730  file.name = "test.proto"
731  defpool:add_file(upb.encode(file))
732  -- Second add with the same filename fails.
733  assert_error(function () defpool:add_file(upb.encode(file)) end)
734end
735
736function test_encode_skipunknown()
737  -- Test that upb.ENCODE_SKIPUNKNOWN does not encode unknown fields.
738  local msg = test_messages_proto3.TestAllTypesProto3{
739    optional_int32 = 10,
740    optional_uint32 = 20,
741    optional_int64 = 30,
742  }
743  -- SKIPUNKNOWN here tests that it does *not* affect regular fields.
744  local serialized = upb.encode(msg, {upb.ENCODE_SKIPUNKNOWN})
745  assert_true(#serialized > 0)
746  local empty_with_unknown = upb.decode(empty.Empty, serialized)
747  assert_true(#upb.encode(empty_with_unknown) > 0)
748  -- Verify that unknown fields are not serialized.
749  assert_true(#upb.encode(empty_with_unknown, {upb.ENCODE_SKIPUNKNOWN}) == 0)
750end
751
752function test_json_emit_defaults()
753  local msg = test_messages_proto3.TestAllTypesProto3()
754  local json = upb.json_encode(msg, {upb.JSONENC_EMITDEFAULTS})
755end
756
757function test_json_locale()
758  local msg = test_messages_proto3.TestAllTypesProto3()
759  msg.optional_double = 1.1
760  local original_locale = os.setlocale(nil)
761  os.setlocale("C")
762  local json = upb.json_encode(msg)
763  os.setlocale("de_DE.utf8")
764  assert_equal(json, upb.json_encode(msg))
765  os.setlocale(original_locale)  -- Restore.
766end
767
768function test_encode_depth_limit()
769  local msg = test_messages_proto3.TestAllTypesProto3()
770  msg.recursive_message = msg
771  assert_error(function() upb.encode(msg) end)
772end
773
774function test_large_field_number()
775  local msg = upb_test.TestLargeFieldNumber()
776  msg.i32 = 5
777  local serialized = upb.encode(msg)
778  local msg2 = upb.decode(upb_test.TestLargeFieldNumber, serialized)
779  assert_equal(msg.i32, msg2.i32)
780end
781
782function test_timestamp_minutes()
783  local msg = upb.json_decode(upb_test.TestTimestamp, '{"ts": "2000-01-01T00:00:00-06:59"}')
784  assert_equal(msg.ts.seconds, 946684800 + ((6 * 60) + 59) * 60)
785end
786
787function test_gc()
788  local top = test_messages_proto3.TestAllTypesProto3()
789  local n = 100
790  local m
791
792  for i=1,n do
793    local inner = test_messages_proto3.TestAllTypesProto3()
794    m = inner
795    for j=1,n do
796      local tmp = m
797      m = test_messages_proto3.TestAllTypesProto3()
798      -- This will cause the arenas to fuse. But we stop referring to the child,
799      -- so the Lua object is eligible for collection (and therefore its original
800      -- arena can be collected too). Only the fusing will keep the C mem alivd.
801      m.recursive_message = tmp
802
803    end
804    top.recursive_message = m
805  end
806
807  collectgarbage()
808
809  for i=1,n do
810    -- Verify we can touch all the messages again and without accessing freed
811    -- memory.
812    m = m.recursive_message
813    assert_not_nil(m)
814  end
815end
816
817function test_b9440()
818  local m = upb_test.HelloRequest()
819  m.id = 8
820  assert_equal(8, m.id)
821  m.version = "1"
822  assert_equal(8, m.id)
823end
824
825local stats = lunit.main()
826
827if stats.failed > 0 or stats.errors > 0 then
828  error("One or more errors in test suite")
829end
830