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