# Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import sys import random def test_bare_msg_type(): import genmsg.msgs tests = [(None, None), ('String', 'String'), ('std_msgs/String', 'std_msgs/String'), ('String[10]', 'String'), ('string[10]', 'string'), ('std_msgs/String[10]', 'std_msgs/String'), ] for val, res in tests: assert res == genmsg.msgs.bare_msg_type(val) PKG = 'genmsg' def test_resolve_type(): from genmsg.msgs import resolve_type, bare_msg_type for t in ['string', 'string[]', 'string[14]', 'int32', 'int32[]']: bt = bare_msg_type(t) t == resolve_type(t, PKG) assert 'foo/string' == resolve_type('foo/string', PKG) assert 'std_msgs/Header' == resolve_type('Header', 'roslib') assert 'std_msgs/Header' == resolve_type('std_msgs/Header', 'roslib') assert 'std_msgs/Header' == resolve_type('Header', 'stereo_msgs') assert 'std_msgs/String' == resolve_type('String', 'std_msgs') assert 'std_msgs/String' == resolve_type('std_msgs/String', 'std_msgs') assert 'std_msgs/String' == resolve_type('std_msgs/String', PKG) assert 'std_msgs/String[]' == resolve_type('std_msgs/String[]', PKG) def test_parse_type(): import genmsg.msgs tests = [ ('a', ('a', False, None)), ('int8', ('int8', False, None)), ('std_msgs/String', ('std_msgs/String', False, None)), ('a[]', ('a', True, None)), ('int8[]', ('int8', True, None)), ('std_msgs/String[]', ('std_msgs/String', True, None)), ('a[1]', ('a', True, 1)), ('int8[1]', ('int8', True, 1)), ('std_msgs/String[1]', ('std_msgs/String', True, 1)), ('a[11]', ('a', True, 11)), ('int8[11]', ('int8', True, 11)), ('std_msgs/String[11]', ('std_msgs/String', True, 11)), ] for val, res in tests: assert res == genmsg.msgs.parse_type(val) fail = ['a[1][2]', 'a[][]', '', None, 'a[', 'a[[1]', 'a[1]]'] for f in fail: try: genmsg.msgs.parse_type(f) assert False, "should have failed on %s"%f except ValueError as e: pass def test_Constant(): import genmsg.msgs vals = [random.randint(0, 1000) for i in range(0, 3)] type_, name, val = [str(x) for x in vals] x = genmsg.msgs.Constant(type_, name, val, str(val)) assert type_ == x.type assert name == x.name assert val == x.val assert x == genmsg.msgs.Constant(type_, name, val, str(val)) assert x != 1 assert not x == 1 assert x != genmsg.msgs.Constant('baz', name, val, str(val)) assert x != genmsg.msgs.Constant(type_, 'foo', val, str(val)) assert x != genmsg.msgs.Constant(type_, name, 'foo', 'foo') # tripwire assert repr(x) assert str(x) try: genmsg.msgs.Constant(None, name, val, str(val)) assert False, "should have raised" except: pass try: genmsg.msgs.Constant(type_, None, val, str(val)) assert False, "should have raised" except: pass try: genmsg.msgs.Constant(type_, name, None, 'None') assert False, "should have raised" except: pass try: genmsg.msgs.Constant(type_, name, val, None) assert False, "should have raised" except: pass try: x.foo = 'bar' assert False, 'Constant should not allow arbitrary attr assignment' except: pass def test_MsgSpec(): def sub_test_MsgSpec(types, names, constants, text, full_name, has_header): m = MsgSpec(types, names, constants, text, full_name) assert m.types == types assert m.names == names assert m.text == text assert has_header == m.has_header() assert m.constants == constants assert list(zip(types, names)) == m.fields() assert m == MsgSpec(types, names, constants, text, full_name) return m from genmsg import MsgSpec, InvalidMsgSpec from genmsg.msgs import Field # don't allow duplicate fields try: MsgSpec(['int32', 'int64'], ['x', 'x'], [], 'int32 x\nint64 x', 'x/DupFields') assert False, "should have raised" except InvalidMsgSpec: pass # don't allow invalid fields try: MsgSpec(['string['], ['x'], [], 'int32 x\nint64 x', 'x/InvalidFields') assert False, "should have raised" except InvalidMsgSpec: pass # allow empty msg empty = sub_test_MsgSpec([], [], [], '', 'x/Nothing', False) assert [] == empty.fields() assert [] == empty.parsed_fields() assert 'x/Nothing' == empty.full_name assert 'x' == empty.package assert 'Nothing' == empty.short_name # one-field one_field = sub_test_MsgSpec(['int32'], ['x'], [], 'int32 x', 'x/OneInt', False) # make sure that equals tests every declared field assert one_field == MsgSpec(['int32'], ['x'], [], 'int32 x', 'x/OneInt') assert one_field != MsgSpec(['uint32'], ['x'], [], 'int32 x', 'x/OneInt') assert one_field != MsgSpec(['int32'], ['y'], [], 'int32 x', 'x/OneInt') assert one_field != MsgSpec(['int32'], ['x'], [], 'uint32 x', 'x/OneInt') assert one_field != MsgSpec(['int32'], ['x'], [], 'int32 x', 'x/OneIntBad') # test against __ne__ as well assert one_field != MsgSpec(['int32'], ['x'], [], 'uint32 x', 'x/OneInt') assert [Field('x', 'int32')] == one_field.parsed_fields(), "%s vs %s"%([Field('x', 'int32')], one_field.parsed_fields()) #test str assert "int32 x" == str(one_field).strip() # test variations of multiple fields and headers two_fields = sub_test_MsgSpec(['int32', 'string'], ['x', 'str'], [], 'int32 x\nstring str', 'x/TwoFields', False) assert [Field('x', 'int32'), Field('str', 'string')] == two_fields.parsed_fields() one_header = sub_test_MsgSpec(['std_msgs/Header'], ['header'], [], 'Header header', 'x/OneHeader', True) header_and_fields = sub_test_MsgSpec(['std_msgs/Header', 'int32', 'string'], ['header', 'x', 'str'], [], 'Header header\nint32 x\nstring str', 'x/HeaderAndFields', True) embed_types = sub_test_MsgSpec(['std_msgs/Header', 'std_msgs/Int32', 'string'], ['header', 'x', 'str'], [], 'Header header\nstd_msgs/Int32 x\nstring str', 'x/EmbedTypes', True) #test strify assert "int32 x\nstring str" == str(two_fields).strip() # types and names mismatch try: MsgSpec(['int32', 'int32'], ['intval'], [], 'int32 intval\int32 y') assert False, "types and names must align" except: pass # test (not) equals against non msgspec assert not (one_field == 1) assert one_field != 1 # test constants from genmsg.msgs import Constant msgspec = MsgSpec(['int32'], ['x'], [Constant('int8', 'c', 1, '1')], 'int8 c=1\nuint32 x', 'x/Constants') assert msgspec.constants == [Constant('int8', 'c', 1, '1')] # tripwire str(msgspec) repr(msgspec) # test that repr doesn't throw an error [repr(x) for x in [empty, one_field, one_header, two_fields, embed_types]] def test_Field(): from genmsg.msgs import Field field = Field('foo', 'string') assert field == Field('foo', 'string') assert field != Field('bar', 'string') assert field != Field('foo', 'int32') assert field != 1 assert not field == 1 assert field.name == 'foo' assert field.type == 'string' assert field.base_type == 'string' assert field.is_array == False assert field.array_len == None assert field.is_header == False assert field.is_builtin == True field = Field('foo', 'std_msgs/String') assert field.type == 'std_msgs/String' assert field.base_type == 'std_msgs/String' assert field.is_array == False assert field.array_len == None assert field.is_header == False assert field.is_builtin == False field = Field('foo', 'std_msgs/String[5]') assert field.type == 'std_msgs/String[5]' assert field.base_type == 'std_msgs/String' assert field.is_array == True assert field.array_len == 5 assert field.is_header == False assert field.is_builtin == False field = Field('foo', 'std_msgs/String[]') assert field.type == 'std_msgs/String[]' assert field.base_type == 'std_msgs/String' assert field.is_array == True assert field.array_len == None assert field.is_header == False assert field.is_builtin == False field = Field('foo', 'std_msgs/Header') assert field.type == 'std_msgs/Header' assert field.is_header == True assert field.is_builtin == False field = Field('foo', 'std_msgs/Header[]') assert field.type == 'std_msgs/Header[]' assert field.is_header == False #tripwire repr(field) def test_is_valid_msg_type(): import genmsg.msgs vals = [ #basic 'F', 'f', 'Foo', 'Foo1', 'std_msgs/String', # arrays 'Foo[]', 'Foo[1]', 'Foo[10]', ] for v in vals: assert genmsg.msgs.is_valid_msg_type(v), "genmsg.msgs.is_valid_msg_type should have returned True for '%s'"%v # bad cases vals = [None, '', '#', '%', 'Foo%', 'Woo Woo', '/', '/String', 'Foo[f]', 'Foo[1d]', 'Foo[-1]', 'Foo[1:10]', 'Foo[', 'Foo]', 'Foo[]Bar'] for v in vals: assert not genmsg.msgs.is_valid_msg_type(v), "genmsg.msgs.is_valid_msg_type should have returned False for '%s'"%v def test_is_valid_constant_type(): import genmsg.msgs valid = ['int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', \ 'uint64', 'float32', 'float64', 'char', 'byte', 'string'] invalid = [ 'std_msgs/String', '/', 'String', 'time', 'duration','header', ] for v in valid: assert genmsg.msgs.is_valid_constant_type(v), "genmsg.msgs.is_valid_constant_type should have returned True for '%s'"%v for v in invalid: assert not genmsg.msgs.is_valid_constant_type(v), "genmsg.msgs.is_valid_constant_type should have returned False for '%s'"%v