summaryrefslogtreecommitdiff
path: root/tests/bindings
diff options
context:
space:
mode:
authorJosh Haberman <jhaberman@gmail.com>2014-06-26 20:24:32 -0700
committerJosh Haberman <jhaberman@gmail.com>2014-06-26 20:24:32 -0700
commit2d10fa33071d52d7a35ce3b13bc459cd16a0aa33 (patch)
treebf47d38e2e1cc8ddb4711b23b26e7fd10742e07d /tests/bindings
parent7d565f1e7a0f107506d3cf31ef2e33e22a504d2b (diff)
Sync from internal Google development.
Diffstat (limited to 'tests/bindings')
-rw-r--r--tests/bindings/lua/test.lua303
-rw-r--r--tests/bindings/lua/upb.lua757
-rw-r--r--tests/bindings/lua/upb.pb.lua70
3 files changed, 827 insertions, 303 deletions
diff --git a/tests/bindings/lua/test.lua b/tests/bindings/lua/test.lua
deleted file mode 100644
index 99f58f2..0000000
--- a/tests/bindings/lua/test.lua
+++ /dev/null
@@ -1,303 +0,0 @@
-
-local upb = require "upb"
-local lunit = require "lunit"
-
-if _VERSION >= 'Lua 5.2' then
- _ENV = lunit.module("testupb", "seeall")
-else
- module("testupb", lunit.testcase, package.seeall)
-end
-
-function test_fielddef()
- local f = upb.FieldDef()
- assert_false(f:is_frozen())
- assert_nil(f:number())
- assert_nil(f:name())
- assert_nil(f:type())
- assert_equal(upb.LABEL_OPTIONAL, f:label())
-
- f:set_name("foo_field")
- f:set_number(3)
- f:set_label(upb.LABEL_REPEATED)
- f:set_type(upb.TYPE_FLOAT)
-
- assert_equal("foo_field", f:name())
- assert_equal(3, f:number())
- assert_equal(upb.LABEL_REPEATED, f:label())
- assert_equal(upb.TYPE_FLOAT, f:type())
-
- local f2 = upb.FieldDef{
- name = "foo", number = 5, type = upb.TYPE_DOUBLE, label = upb.LABEL_REQUIRED
- }
-
- assert_equal("foo", f2:name())
- assert_equal(5, f2:number())
- assert_equal(upb.TYPE_DOUBLE, f2:type())
- assert_equal(upb.LABEL_REQUIRED, f2:label())
-end
-
-function test_enumdef()
- local e = upb.EnumDef()
- assert_equal(0, #e)
- assert_nil(e:value(5))
- assert_nil(e:value("NONEXISTENT_NAME"))
-
- for name, value in e:values() do
- fail()
- end
-
- e:add("VAL1", 1)
- e:add("VAL2", 2)
-
- local values = {}
- for name, value in e:values() do
- values[name] = value
- end
-
- assert_equal(1, values["VAL1"])
- assert_equal(2, values["VAL2"])
-
- local e2 = upb.EnumDef{
- values = {
- {"FOO", 1},
- {"BAR", 77},
- }
- }
-
- assert_equal(1, e2:value("FOO"))
- assert_equal(77, e2:value("BAR"))
- assert_equal("FOO", e2:value(1))
- assert_equal("BAR", e2:value(77))
-end
-
-function test_empty_msgdef()
- local md = upb.MessageDef()
- assert_nil(md:full_name()) -- Def without name is anonymous.
- assert_false(md:is_frozen())
- assert_equal(0, #md)
- assert_nil(md:field("nonexistent_field"))
- assert_nil(md:field(3))
- for field in md:fields() do
- fail()
- end
-
- upb.freeze(md)
- assert_true(md:is_frozen())
- assert_equal(0, #md)
- assert_nil(md:field("nonexistent_field"))
- assert_nil(md:field(3))
- for field in md:fields() do
- fail()
- end
-end
-
-function test_msgdef_constructor()
- local f1 = upb.FieldDef{name = "field1", number = 7, type = upb.TYPE_INT32}
- local f2 = upb.FieldDef{name = "field2", number = 8, type = upb.TYPE_INT32}
- local md = upb.MessageDef{
- full_name = "TestMessage",
- fields = {f1, f2}
- }
- assert_equal("TestMessage", md:full_name())
- assert_false(md:is_frozen())
- assert_equal(2, #md)
- assert_equal(f1, md:field("field1"))
- assert_equal(f2, md:field("field2"))
- assert_equal(f1, md:field(7))
- assert_equal(f2, md:field(8))
- local count = 0
- local found = {}
- for field in md:fields() do
- count = count + 1
- found[field] = true
- end
- assert_equal(2, count)
- assert_true(found[f1])
- assert_true(found[f2])
-
- upb.freeze(md)
-end
-
-function test_msgdef_setters()
- local md = upb.MessageDef()
- md:set_full_name("Message1")
- assert_equal("Message1", md:full_name())
- local f = upb.FieldDef{name = "field1", number = 3, type = upb.TYPE_DOUBLE}
- md:add{f}
- assert_equal(1, #md)
- assert_equal(f, md:field("field1"))
-end
-
-function test_msgdef_errors()
- assert_error(function() upb.MessageDef{bad_initializer_key = 5} end)
- local md = upb.MessageDef()
- assert_error(function()
- -- Duplicate field number.
- upb.MessageDef{
- fields = {
- upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32},
- upb.FieldDef{name = "field2", number = 1, type = upb.TYPE_INT32}
- }
- }
- end)
- assert_error(function()
- -- Duplicate field name.
- upb.MessageDef{
- fields = {
- upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32},
- upb.FieldDef{name = "field1", number = 2, type = upb.TYPE_INT32}
- }
- }
- end)
-
- -- attempt to set a name with embedded NULLs.
- assert_error_match("names cannot have embedded NULLs", function()
- md:set_full_name("abc\0def")
- end)
-
- upb.freeze(md)
- -- Attempt to mutate frozen MessageDef.
- -- TODO(haberman): better error message and test for message.
- assert_error(function()
- md:add{upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}}
- end)
- assert_error(function()
- md:set_full_name("abc")
- end)
-
- -- Attempt to freeze a msgdef without freezing its subdef.
- assert_error_match("is not frozen or being frozen", function()
- m1 = upb.MessageDef()
- upb.freeze(
- upb.MessageDef{
- fields = {
- upb.FieldDef{name = "f1", number = 1, type = upb.TYPE_MESSAGE,
- subdef = m1}
- }
- }
- )
- end)
-end
-
-function test_symtab()
- local empty = upb.SymbolTable()
- assert_equal(0, #empty:getdefs(upb.DEF_ANY))
-
- local symtab = upb.SymbolTable{
- upb.MessageDef{full_name = "TestMessage"},
- upb.MessageDef{full_name = "ContainingMessage", fields = {
- upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32},
- upb.FieldDef{name = "field2", number = 2, type = upb.TYPE_MESSAGE,
- subdef_name = ".TestMessage"}
- }
- }
- }
-
- local msgdef1 = symtab:lookup("TestMessage")
- local msgdef2 = symtab:lookup("ContainingMessage")
- assert_not_nil(msgdef1)
- assert_not_nil(msgdef2)
- assert_equal(msgdef1, msgdef2:field("field2"):subdef())
- assert_true(msgdef1:is_frozen())
- assert_true(msgdef2:is_frozen())
-
- symtab:add{
- upb.MessageDef{full_name = "ContainingMessage2", fields = {
- upb.FieldDef{name = "field5", number = 5, type = upb.TYPE_MESSAGE,
- subdef = msgdef2}
- }
- }
- }
-
- local msgdef3 = symtab:lookup("ContainingMessage2")
- assert_not_nil(msgdef3)
- assert_equal(msgdef3:field("field5"):subdef(), msgdef2)
-end
-
-function test_symtab_add_extension()
- -- Adding an extension at the same time as the extendee.
- local symtab = upb.SymbolTable{
- upb.MessageDef{full_name = "M1"},
- upb.FieldDef{name = "extension1", is_extension = true, number = 1,
- type = upb.TYPE_INT32, containing_type_name = "M1"}
- }
-
- local m1 = symtab:lookup("M1")
- assert_not_nil(m1)
- assert_equal(1, #m1)
-
- local f1 = m1:field("extension1")
- assert_not_nil(f1)
- assert_true(f1:is_extension())
- assert_true(f1:is_frozen())
- assert_equal(1, f1:number())
-
- -- Adding an extension to an existing extendee.
- symtab:add{
- upb.FieldDef{name = "extension2", is_extension = true, number = 2,
- type = upb.TYPE_INT32, containing_type_name = "M1"}
- }
-
- local m1_2 = symtab:lookup("M1")
- assert_not_nil(m1_2)
- assert_true(m1 ~= m1_2)
- assert_equal(2, #m1_2)
-
- local f2 = m1_2:field("extension2")
- assert_not_nil(f2)
- assert_true(f2:is_extension())
- assert_true(f2:is_frozen())
- assert_equal(2, f2:number())
-end
-
--- Lua 5.1 and 5.2 have slightly different semantics for how a finalizer
--- can be defined in Lua.
-if _VERSION >= 'Lua 5.2' then
- function defer(fn)
- setmetatable({}, { __gc = fn })
- end
-else
- function defer(fn)
- getmetatable(newproxy(true)).__gc = fn
- end
-end
-
-function test_finalizer()
- -- Tests that we correctly handle a call into an already-finalized object.
- -- Collectible objects are finalized in the opposite order of creation.
- do
- local t = {}
- defer(function()
- assert_error_match("called into dead def", function()
- -- Generic def call.
- t[1]:full_name()
- end)
- assert_error_match("called into dead msgdef", function()
- -- Specific msgdef call.
- t[1]:add()
- end)
- assert_error_match("called into dead enumdef", function()
- t[2]:values()
- end)
- assert_error_match("called into dead fielddef", function()
- t[3]:number()
- end)
- assert_error_match("called into dead symtab",
- function() t[4]:lookup()
- end)
- end)
- t = {
- upb.MessageDef(),
- upb.EnumDef(),
- upb.FieldDef(),
- upb.SymbolTable(),
- }
- end
- collectgarbage()
-end
-
-local stats = lunit.main()
-
-if stats.failed > 0 or stats.errors > 0 then
- error("One or more errors in test suite")
-end
diff --git a/tests/bindings/lua/upb.lua b/tests/bindings/lua/upb.lua
new file mode 100644
index 0000000..f32a690
--- /dev/null
+++ b/tests/bindings/lua/upb.lua
@@ -0,0 +1,757 @@
+
+local upb = require "upb"
+local lunit = require "lunit"
+
+if _VERSION >= 'Lua 5.2' then
+ _ENV = lunit.module("testupb", "seeall")
+else
+ module("testupb", lunit.testcase, package.seeall)
+end
+
+function iter_to_array(iter)
+ local arr = {}
+ for v in iter do
+ arr[#arr + 1] = v
+ end
+ return arr
+end
+
+function test_fielddef()
+ local f = upb.FieldDef()
+ assert_false(f:is_frozen())
+ assert_nil(f:number())
+ assert_nil(f:name())
+ assert_nil(f:type())
+ assert_equal(upb.LABEL_OPTIONAL, f:label())
+
+ f:set_name("foo_field")
+ f:set_number(3)
+ f:set_label(upb.LABEL_REPEATED)
+ f:set_type(upb.TYPE_FLOAT)
+
+ assert_equal("foo_field", f:name())
+ assert_equal(3, f:number())
+ assert_equal(upb.LABEL_REPEATED, f:label())
+ assert_equal(upb.TYPE_FLOAT, f:type())
+
+ local f2 = upb.FieldDef{
+ name = "foo", number = 5, type = upb.TYPE_DOUBLE, label = upb.LABEL_REQUIRED
+ }
+
+ assert_equal("foo", f2:name())
+ assert_equal(5, f2:number())
+ assert_equal(upb.TYPE_DOUBLE, f2:type())
+ assert_equal(upb.LABEL_REQUIRED, f2:label())
+end
+
+function test_enumdef()
+ local e = upb.EnumDef()
+ assert_equal(0, #e)
+ assert_nil(e:value(5))
+ assert_nil(e:value("NONEXISTENT_NAME"))
+
+ for name, value in e:values() do
+ fail()
+ end
+
+ e:add("VAL1", 1)
+ e:add("VAL2", 2)
+
+ local values = {}
+ for name, value in e:values() do
+ values[name] = value
+ end
+
+ assert_equal(1, values["VAL1"])
+ assert_equal(2, values["VAL2"])
+
+ local e2 = upb.EnumDef{
+ values = {
+ {"FOO", 1},
+ {"BAR", 77},
+ }
+ }
+
+ assert_equal(1, e2:value("FOO"))
+ assert_equal(77, e2:value("BAR"))
+ assert_equal("FOO", e2:value(1))
+ assert_equal("BAR", e2:value(77))
+
+ e2:freeze()
+
+ local f = upb.FieldDef{type = upb.TYPE_ENUM}
+
+ -- No default set and no EnumDef to get a default from.
+ assert_equal(f:default(), nil)
+
+ f:set_subdef(upb.EnumDef())
+ -- No default to pull in from the EnumDef.
+ assert_equal(f:default(), nil)
+
+ f:set_subdef(e2)
+ -- First member added to e2.
+ assert_equal(f:default(), "FOO")
+
+ f:set_subdef(nil)
+ assert_equal(f:default(), nil)
+
+ f:set_default(1)
+ assert_equal(f:default(), 1)
+
+ f:set_default("YOYOYO")
+ assert_equal(f:default(), "YOYOYO")
+
+ f:set_subdef(e2)
+ f:set_default(1)
+ -- It prefers to return a string, and could resolve the explicit "1" we set
+ -- it to to the string value.
+ assert_equal(f:default(), "FOO")
+
+ -- FieldDef can specify default value by name or number, but the value must
+ -- exist at freeze time.
+ local m1 = upb.build_defs{
+ upb.MessageDef{
+ full_name = "A",
+ fields = {
+ upb.FieldDef{
+ name = "f1",
+ number = 1,
+ type = upb.TYPE_ENUM,
+ subdef = e2,
+ default = "BAR"
+ },
+ upb.FieldDef{
+ name = "f2",
+ number = 2,
+ type = upb.TYPE_ENUM,
+ subdef = e2,
+ default = 77
+ }
+ }
+ }
+ }
+
+ assert_equal(m1:field("f1"):default(), "BAR")
+ assert_equal(m1:field("f1"):default(), "BAR")
+
+ assert_error_match(
+ "enum default for field A.f1 .DOESNT_EXIST. is not in the enum",
+ function()
+ local m1 = upb.build_defs{
+ upb.MessageDef{
+ full_name = "A",
+ fields = {
+ upb.FieldDef{
+ name = "f1",
+ number = 1,
+ type = upb.TYPE_ENUM,
+ subdef = e2,
+ default = "DOESNT_EXIST"
+ }
+ }
+ }
+ }
+ end
+ )
+
+ assert_error_match(
+ "enum default for field A.f1 .142. is not in the enum",
+ function()
+ local m1 = upb.build_defs{
+ upb.MessageDef{
+ full_name = "A",
+ fields = {
+ upb.FieldDef{
+ name = "f1",
+ number = 1,
+ type = upb.TYPE_ENUM,
+ subdef = e2,
+ default = 142
+ }
+ }
+ }
+ }
+ end
+ )
+end
+
+function test_empty_msgdef()
+ local md = upb.MessageDef()
+ assert_nil(md:full_name()) -- Def without name is anonymous.
+ assert_false(md:is_frozen())
+ assert_equal(0, #md)
+ assert_nil(md:field("nonexistent_field"))
+ assert_nil(md:field(3))
+ for field in md:fields() do
+ fail()
+ end
+
+ upb.freeze(md)
+ assert_true(md:is_frozen())
+ assert_equal(0, #md)
+ assert_nil(md:field("nonexistent_field"))
+ assert_nil(md:field(3))
+ for field in md:fields() do
+ fail()
+ end
+end
+
+function test_msgdef_constructor()
+ local f1 = upb.FieldDef{name = "field1", number = 7, type = upb.TYPE_INT32}
+ local f2 = upb.FieldDef{name = "field2", number = 8, type = upb.TYPE_INT32}
+ local md = upb.MessageDef{
+ full_name = "TestMessage",
+ fields = {f1, f2}
+ }
+ assert_equal("TestMessage", md:full_name())
+ assert_false(md:is_frozen())
+ assert_equal(2, #md)
+ assert_equal(f1, md:field("field1"))
+ assert_equal(f2, md:field("field2"))
+ assert_equal(f1, md:field(7))
+ assert_equal(f2, md:field(8))
+ local count = 0
+ local found = {}
+ for field in md:fields() do
+ count = count + 1
+ found[field] = true
+ end
+ assert_equal(2, count)
+ assert_true(found[f1])
+ assert_true(found[f2])
+
+ upb.freeze(md)
+end
+
+function test_iteration()
+ -- Test that we cannot crash the process even if we modify the set of fields
+ -- during iteration.
+ local md = upb.MessageDef{full_name = "TestMessage"}
+
+ for i=1,10 do
+ md:add(upb.FieldDef{
+ name = "field" .. tostring(i),
+ number = 1000 - i,
+ type = upb.TYPE_INT32
+ })
+ end
+
+ local add = #md
+ for f in md:fields() do
+ if add > 0 then
+ add = add - 1
+ for i=10000,11000 do
+ local field_name = "field" .. tostring(i)
+ -- We want to add fields to the table to trigger a table resize,
+ -- but we must skip it if the field name or number already exists
+ -- otherwise it will raise an error.
+ if md:field(field_name) == nil and
+ md:field(i) == nil then
+ md:add(upb.FieldDef{
+ name = field_name,
+ number = i,
+ type = upb.TYPE_INT32
+ })
+ end
+ end
+ end
+ end
+
+ -- Test that iterators don't crash the process even if the MessageDef goes
+ -- out of scope.
+ --
+ -- Note: have previously verified that this can indeed crash the process if
+ -- we do not explicitly add a reference from the iterator to the underlying
+ -- MessageDef.
+ local iter = md:fields()
+ md = nil
+ collectgarbage()
+ while iter() do
+ end
+
+ local ed = upb.EnumDef{
+ values = {
+ {"FOO", 1},
+ {"BAR", 77},
+ }
+ }
+ iter = ed:values()
+ ed = nil
+ collectgarbage()
+ while iter() do
+ end
+end
+
+function test_msgdef_setters()
+ local md = upb.MessageDef()
+ md:set_full_name("Message1")
+ assert_equal("Message1", md:full_name())
+ local f = upb.FieldDef{name = "field1", number = 3, type = upb.TYPE_DOUBLE}
+ md:add(f)
+ assert_equal(1, #md)
+ assert_equal(f, md:field("field1"))
+end
+
+function test_msgdef_errors()
+ assert_error(function() upb.MessageDef{bad_initializer_key = 5} end)
+ local md = upb.MessageDef()
+ assert_error(function()
+ -- Duplicate field number.
+ upb.MessageDef{
+ fields = {
+ upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32},
+ upb.FieldDef{name = "field2", number = 1, type = upb.TYPE_INT32}
+ }
+ }
+ end)
+ assert_error(function()
+ -- Duplicate field name.
+ upb.MessageDef{
+ fields = {
+ upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32},
+ upb.FieldDef{name = "field1", number = 2, type = upb.TYPE_INT32}
+ }
+ }
+ end)
+
+ -- attempt to set a name with embedded NULLs.
+ assert_error_match("names cannot have embedded NULLs", function()
+ md:set_full_name("abc\0def")
+ end)
+
+ upb.freeze(md)
+ -- Attempt to mutate frozen MessageDef.
+ assert_error_match("frozen", function()
+ md:add(upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32})
+ end)
+ assert_error_match("frozen", function()
+ md:set_full_name("abc")
+ end)
+
+ -- Attempt to freeze a msgdef without freezing its subdef.
+ assert_error_match("is not frozen or being frozen", function()
+ m1 = upb.MessageDef()
+ upb.freeze(
+ upb.MessageDef{
+ fields = {
+ upb.FieldDef{name = "f1", number = 1, type = upb.TYPE_MESSAGE,
+ subdef = m1}
+ }
+ }
+ )
+ end)
+end
+
+function test_symtab()
+ local empty = upb.SymbolTable()
+ assert_equal(0, #iter_to_array(empty:defs(upb.DEF_ANY)))
+ assert_equal(0, #iter_to_array(empty:defs(upb.DEF_MSG)))
+ assert_equal(0, #iter_to_array(empty:defs(upb.DEF_ENUM)))
+
+ local symtab = upb.SymbolTable{
+ upb.MessageDef{full_name = "TestMessage"},
+ upb.MessageDef{full_name = "ContainingMessage", fields = {
+ upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32},
+ upb.FieldDef{name = "field2", number = 2, type = upb.TYPE_MESSAGE,
+ subdef_name = ".TestMessage"}
+ }
+ }
+ }
+
+ local msgdef1 = symtab:lookup("TestMessage")
+ local msgdef2 = symtab:lookup("ContainingMessage")
+ assert_not_nil(msgdef1)
+ assert_not_nil(msgdef2)
+ assert_equal(msgdef1, msgdef2:field("field2"):subdef())
+ assert_true(msgdef1:is_frozen())
+ assert_true(msgdef2:is_frozen())
+
+ symtab:add{
+ upb.MessageDef{full_name = "ContainingMessage2", fields = {
+ upb.FieldDef{name = "field5", number = 5, type = upb.TYPE_MESSAGE,
+ subdef = msgdef2}
+ }
+ }
+ }
+
+ local msgdef3 = symtab:lookup("ContainingMessage2")
+ assert_not_nil(msgdef3)
+ assert_equal(msgdef3:field("field5"):subdef(), msgdef2)
+
+ -- Freeze the symtab and verify that mutating operations are not allowed.
+ assert_false(symtab:is_frozen())
+ symtab:freeze()
+ assert_true(symtab:is_frozen())
+ assert_error_match("frozen", function() symtab:freeze() end)
+ assert_error_match("frozen", function()
+ symtab:add{
+ upb.MessageDef{full_name = "Foo"}
+ }
+ end)
+end
+
+function test_symtab_add_extension()
+ -- Adding an extension at the same time as the extendee.
+ local symtab = upb.SymbolTable{
+ upb.MessageDef{full_name = "M1"},
+ upb.FieldDef{name = "extension1", is_extension = true, number = 1,
+ type = upb.TYPE_INT32, containing_type_name = "M1"}
+ }
+
+ local m1 = symtab:lookup("M1")
+ assert_not_nil(m1)
+ assert_equal(1, #m1)
+
+ local f1 = m1:field("extension1")
+ assert_not_nil(f1)
+ assert_true(f1:is_extension())
+ assert_true(f1:is_frozen())
+ assert_equal(1, f1:number())
+
+ -- Adding an extension to an existing extendee.
+ symtab:add{
+ upb.FieldDef{name = "extension2", is_extension = true, number = 2,
+ type = upb.TYPE_INT32, containing_type_name = "M1"}
+ }
+
+ local m1_2 = symtab:lookup("M1")
+ assert_not_nil(m1_2)
+ assert_true(m1 ~= m1_2)
+ assert_equal(2, #m1_2)
+
+ local f2 = m1_2:field("extension2")
+ assert_not_nil(f2)
+ assert_true(f2:is_extension())
+ assert_true(f2:is_frozen())
+ assert_equal(2, f2:number())
+end
+
+function test_numeric_array()
+ local function test_for_numeric_type(upb_type, val, too_big, too_small, bad3)
+ local array = upb.Array(upb_type)
+ assert_equal(0, #array)
+
+ -- 0 is never a valid index in Lua.
+ assert_error_match("array index", function() return array[0] end)
+ -- Past the end of the array.
+ assert_error_match("array index", function() return array[1] end)
+
+ array[1] = val
+ assert_equal(val, array[1])
+ assert_equal(1, #array)
+ -- Past the end of the array.
+ assert_error_match("array index", function() return array[2] end)
+
+ array[2] = 10
+ assert_equal(val, array[1])
+ assert_equal(10, array[2])
+ assert_equal(2, #array)
+ -- Past the end of the array.
+ assert_error_match("array index", function() return array[3] end)
+
+ local n = 1
+ for i, val in upb.ipairs(array) do
+ assert_equal(n, i)
+ n = n + 1
+ assert_equal(array[i], val)
+ end
+
+ -- Values that are out of range.
+ local errmsg = "not an integer or out of range"
+ if too_small then
+ assert_error_match(errmsg, function() array[3] = too_small end)
+ end
+ if too_big then
+ assert_error_match(errmsg, function() array[3] = too_big end)
+ end
+ if bad3 then
+ assert_error_match(errmsg, function() array[3] = bad3 end)
+ end
+
+ -- Can't assign other Lua types.
+ errmsg = "bad argument #3"
+ assert_error_match(errmsg, function() array[3] = "abc" end)
+ assert_error_match(errmsg, function() array[3] = true end)
+ assert_error_match(errmsg, function() array[3] = false end)
+ assert_error_match(errmsg, function() array[3] = nil end)
+ assert_error_match(errmsg, function() array[3] = {} end)
+ assert_error_match(errmsg, function() array[3] = print end)
+ assert_error_match(errmsg, function() array[3] = array end)
+ end
+
+ -- in-range of 64-bit types but not exactly representable as double
+ local bad64 = 2^68 - 1
+
+ test_for_numeric_type(upb.TYPE_UINT32, 2^32 - 1, 2^32, -1, 5.1)
+ test_for_numeric_type(upb.TYPE_UINT64, 2^63, 2^64, -1, bad64)
+ test_for_numeric_type(upb.TYPE_INT32, 2^31 - 1, 2^31, -2^31 - 1, 5.1)
+ -- Enums don't exist at a language level in Lua, so we just represent enum
+ -- values as int32s.
+ test_for_numeric_type(upb.TYPE_ENUM, 2^31 - 1, 2^31, -2^31 - 1, 5.1)
+ test_for_numeric_type(upb.TYPE_INT64, 2^62, 2^63, -2^64, bad64)
+ test_for_numeric_type(upb.TYPE_FLOAT, 10^38)
+ test_for_numeric_type(upb.TYPE_DOUBLE, 10^101)
+end
+
+function test_string_array()
+ local function test_for_string_type(upb_type)
+ local array = upb.Array(upb_type)
+ assert_equal(0, #array)
+
+ -- 0 is never a valid index in Lua.
+ assert_error_match("array index", function() return array[0] end)
+ -- Past the end of the array.
+ assert_error_match("array index", function() return array[1] end)
+
+ array[1] = "foo"
+ assert_equal("foo", array[1])
+ assert_equal(1, #array)
+ -- Past the end of the array.
+ assert_error_match("array index", function() return array[2] end)
+
+ local array2 = upb.Array(upb_type)
+ assert_equal(0, #array2)
+
+ array[2] = "bar"
+ assert_equal("foo", array[1])
+ assert_equal("bar", array[2])
+ assert_equal(2, #array)
+ -- Past the end of the array.
+ assert_error_match("array index", function() return array[3] end)
+
+ local n = 1
+ for i, val in upb.ipairs(array) do
+ assert_equal(n, i)
+ n = n + 1
+ assert_equal(array[i], val)
+ end
+ assert_equal(3, n)
+
+ -- Can't assign other Lua types.
+ assert_error_match("Expected string", function() array[3] = 123 end)
+ assert_error_match("Expected string", function() array[3] = true end)
+ assert_error_match("Expected string", function() array[3] = false end)
+ assert_error_match("Expected string", function() array[3] = nil end)
+ assert_error_match("Expected string", function() array[3] = {} end)
+ assert_error_match("Expected string", function() array[3] = print end)
+ assert_error_match("Expected string", function() array[3] = array end)
+ end
+
+ test_for_string_type(upb.TYPE_STRING)
+ test_for_string_type(upb.TYPE_BYTES)
+end
+
+function test_msg_primitives()
+ local function test_for_numeric_type(upb_type, val, too_big, too_small, bad3)
+
+ msg = upb.Message(
+ upb.build_defs{
+ upb.MessageDef{full_name = "TestMessage", fields = {
+ upb.FieldDef{name = "f", number = 1, type = upb_type},
+ }
+ }
+ }
+ )
+
+ -- Defaults to nil
+ assert_nil(msg.f)
+
+ msg.f = 0
+ assert_equal(0, msg.f)
+
+ msg.f = val
+ assert_equal(val, msg.f)
+
+ local errmsg = "not an integer or out of range"
+ if too_small then
+ assert_error_match(errmsg, function() msg.f = too_small end)
+ end
+ if too_big then
+ assert_error_match(errmsg, function() msg.f = too_big end)
+ end
+ if bad3 then
+ assert_error_match(errmsg, function() msg.f = bad3 end)
+ end
+
+ -- Can't assign other Lua types.
+ errmsg = "bad argument #3"
+ assert_error_match(errmsg, function() msg.f = "abc" end)
+ assert_error_match(errmsg, function() msg.f = true end)
+ assert_error_match(errmsg, function() msg.f = false end)
+ assert_error_match(errmsg, function() msg.f = nil end)
+ assert_error_match(errmsg, function() msg.f = {} end)
+ assert_error_match(errmsg, function() msg.f = print end)
+ assert_error_match(errmsg, function() msg.f = array end)
+ end
+
+ local msgdef = upb.build_defs{
+ upb.MessageDef{full_name = "TestMessage", fields = {
+ upb.FieldDef{name = "i32", number = 1, type = upb.TYPE_INT32},
+ upb.FieldDef{name = "u32", number = 2, type = upb.TYPE_UINT32},
+ upb.FieldDef{name = "i64", number = 3, type = upb.TYPE_INT64},
+ upb.FieldDef{name = "u64", number = 4, type = upb.TYPE_UINT64},
+ upb.FieldDef{name = "dbl", number = 5, type = upb.TYPE_DOUBLE},
+ upb.FieldDef{name = "flt", number = 6, type = upb.TYPE_FLOAT},
+ upb.FieldDef{name = "bool", number = 7, type = upb.TYPE_BOOL},
+ }
+ }
+ }
+
+ msg = upb.Message(msgdef)
+
+ -- Unset member returns nil. This is unlike C++/Java, but is more
+ -- Lua-like behavior.
+ assert_equal(nil, msg.i32)
+ assert_equal(nil, msg.u32)
+ assert_equal(nil, msg.i64)
+ assert_equal(nil, msg.u64)
+ assert_equal(nil, msg.dbl)
+ assert_equal(nil, msg.flt)
+ assert_equal(nil, msg.bool)
+
+ -- Attempts to access non-existent fields fail.
+ assert_error_match("no such field", function() msg.no_such = 1 end)
+
+ msg.i32 = 10
+ msg.u32 = 20
+ msg.i64 = 30
+ msg.u64 = 40
+ msg.dbl = 50
+ msg.flt = 60
+ msg.bool = true
+
+ assert_equal(10, msg.i32)
+ assert_equal(20, msg.u32)
+ assert_equal(30, msg.i64)
+ assert_equal(40, msg.u64)
+ assert_equal(50, msg.dbl)
+ assert_equal(60, msg.flt)
+ assert_equal(true, msg.bool)
+
+ test_for_numeric_type(upb.TYPE_UINT32, 2^32 - 1, 2^32, -1, 5.1)
+ test_for_numeric_type(upb.TYPE_UINT64, 2^62, 2^64, -1, bad64)
+ test_for_numeric_type(upb.TYPE_INT32, 2^31 - 1, 2^31, -2^31 - 1, 5.1)
+ test_for_numeric_type(upb.TYPE_INT64, 2^61, 2^63, -2^64, bad64)
+ test_for_numeric_type(upb.TYPE_FLOAT, 2^20)
+ test_for_numeric_type(upb.TYPE_DOUBLE, 10^101)
+end
+
+function test_msg_array()
+ local msgdef = upb.build_defs{
+ upb.MessageDef{full_name = "TestMessage", fields = {
+ upb.FieldDef{name = "i32_array", number = 1, type = upb.TYPE_INT32,
+ label = upb.LABEL_REPEATED},
+ }
+ }
+ }
+
+ msg = upb.Message(msgdef)
+
+ assert_nil(msg.i32_array)
+
+ -- Can't assign a scalar; array is expected.
+ assert_error_match("lupb.array expected", function() msg.i32_array = 5 end)
+
+ -- Can't assign array of the wrong type.
+ local function assign_int64()
+ msg.i32_array = upb.Array(upb.TYPE_INT64)
+ end
+ assert_error_match("Array type mismatch", assign_int64)
+
+ local arr = upb.Array(upb.TYPE_INT32)
+ msg.i32_array = arr
+ assert_equal(arr, msg.i32_array)
+
+ -- Can't assign other Lua types.
+ assert_error_match("array expected", function() msg.i32_array = "abc" end)
+ assert_error_match("array expected", function() msg.i32_array = true end)
+ assert_error_match("array expected", function() msg.i32_array = false end)
+ assert_error_match("array expected", function() msg.i32_array = nil end)
+ assert_error_match("array expected", function() msg.i32_array = {} end)
+ assert_error_match("array expected", function() msg.i32_array = print end)
+end
+
+function test_msg_submsg()
+ local test_msgdef, submsg_msgdef = upb.build_defs{
+ upb.MessageDef{full_name = "TestMessage", fields = {
+ upb.FieldDef{name = "submsg", number = 1, type = upb.TYPE_MESSAGE,
+ subdef_name = ".SubMessage"},
+ }
+ },
+ upb.MessageDef{full_name = "SubMessage"}
+ }
+
+ msg = upb.Message(test_msgdef)
+
+ assert_nil(msg.submsg)
+
+ -- Can't assign message of the wrong type.
+ local function assign_int64()
+ msg.submsg = upb.Message(test_msgdef)
+ end
+ assert_error_match("Message type mismatch", assign_int64)
+
+ local sub = upb.Message(submsg_msgdef)
+ msg.submsg = sub
+ assert_equal(sub, msg.submsg)
+
+ -- Can't assign other Lua types.
+ assert_error_match("msg expected", function() msg.submsg = "abc" end)
+ assert_error_match("msg expected", function() msg.submsg = true end)
+ assert_error_match("msg expected", function() msg.submsg = false end)
+ assert_error_match("msg expected", function() msg.submsg = nil end)
+ assert_error_match("msg expected", function() msg.submsg = {} end)
+ assert_error_match("msg expected", function() msg.submsg = print end)
+end
+
+-- Lua 5.1 and 5.2 have slightly different semantics for how a finalizer
+-- can be defined in Lua.
+if _VERSION >= 'Lua 5.2' then
+ function defer(fn)
+ setmetatable({}, { __gc = fn })
+ end
+else
+ function defer(fn)
+ getmetatable(newproxy(true)).__gc = fn
+ end
+end
+
+function test_finalizer()
+ -- Tests that we correctly handle a call into an already-finalized object.
+ -- Collectible objects are finalized in the opposite order of creation.
+ do
+ local t = {}
+ defer(function()
+ assert_error_match("called into dead object", function()
+ -- Generic def call.
+ t[1]:full_name()
+ end)
+ assert_error_match("called into dead object", function()
+ -- Specific msgdef call.
+ t[1]:add()
+ end)
+ assert_error_match("called into dead object", function()
+ t[2]:values()
+ end)
+ assert_error_match("called into dead object", function()
+ t[3]:number()
+ end)
+ assert_error_match("called into dead object",
+ function() t[4]:lookup()
+ end)
+ end)
+ t = {
+ upb.MessageDef(),
+ upb.EnumDef(),
+ upb.FieldDef(),
+ upb.SymbolTable(),
+ }
+ end
+ collectgarbage()
+end
+
+local stats = lunit.main()
+
+if stats.failed > 0 or stats.errors > 0 then
+ error("One or more errors in test suite")
+end
diff --git a/tests/bindings/lua/upb.pb.lua b/tests/bindings/lua/upb.pb.lua
new file mode 100644
index 0000000..02b443a
--- /dev/null
+++ b/tests/bindings/lua/upb.pb.lua
@@ -0,0 +1,70 @@
+
+local upb = require "upb"
+local pb = require "upb.pb"
+local lunit = require "lunit"
+
+if _VERSION >= 'Lua 5.2' then
+ _ENV = lunit.module("testupb_pb", "seeall")
+else
+ module("testupb_pb", lunit.testcase, package.seeall)
+end
+
+local primitive_types_msg = upb.build_defs{
+ upb.MessageDef{full_name = "TestMessage", fields = {
+ upb.FieldDef{name = "i32", number = 1, type = upb.TYPE_INT32},
+ upb.FieldDef{name = "u32", number = 2, type = upb.TYPE_UINT32},
+ upb.FieldDef{name = "i64", number = 3, type = upb.TYPE_INT64},
+ upb.FieldDef{name = "u64", number = 4, type = upb.TYPE_UINT64},
+ upb.FieldDef{name = "dbl", number = 5, type = upb.TYPE_DOUBLE},
+ upb.FieldDef{name = "flt", number = 6, type = upb.TYPE_FLOAT},
+ upb.FieldDef{name = "bool", number = 7, type = upb.TYPE_BOOL},
+ }
+ }
+}
+
+function test_decodermethod()
+ local dm = pb.DecoderMethod(primitive_types_msg)
+
+ assert_error(
+ function()
+ -- Needs at least one argument to construct.
+ pb.DecoderMethod()
+ end)
+end
+
+function test_parse_primitive()
+ local binary_pb =
+ "\008\128\128\128\128\002\016\128\128\128\128\004\024\128\128"
+ .. "\128\128\128\128\128\002\032\128\128\128\128\128\128\128\001\041\000"
+ .. "\000\000\000\000\000\248\063\053\000\000\096\064\056\001"
+ local dm = pb.DecoderMethod(primitive_types_msg)
+ msg = dm:parse(binary_pb)
+ assert_equal(536870912, msg.i32)
+ assert_equal(1073741824, msg.u32)
+ assert_equal(1125899906842624, msg.i64)
+ assert_equal(562949953421312, msg.u64)
+ assert_equal(1.5, msg.dbl)
+ assert_equal(3.5, msg.flt)
+ assert_equal(true, msg.bool)
+end
+
+function test_parse_string()
+ local msgdef = upb.build_defs{
+ upb.MessageDef{full_name = "TestMessage", fields = {
+ upb.FieldDef{name = "str", number = 1, type = upb.TYPE_STRING},
+ }
+ }
+ }
+
+ local binary_pb = "\010\005Hello"
+ local dm = pb.DecoderMethod(msgdef)
+ msg = dm:parse(binary_pb)
+ assert_equal("Hello", msg.str)
+end
+
+
+local stats = lunit.main()
+
+if stats.failed > 0 or stats.errors > 0 then
+ error("One or more errors in test suite")
+end
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback