test_urdf_error.py
Go to the documentation of this file.
1 
2 import unittest
3 from urdf_parser_py import urdf
5 
6 ParseError = xmlr.core.ParseError
7 
8 class TestURDFParserError(unittest.TestCase):
9  def setUp(self):
10  # Manually patch "on_error" to capture errors
11  self.errors = []
12  def add_error(message):
13  self.errors.append(message)
14  xmlr.core.on_error = add_error
15 
16  def tearDown(self):
17  xmlr.core.on_error = xmlr.core.on_error_stderr
18 
19  def assertLoggedErrors(self, errors, func, *args, **kwds):
20  func(*args, **kwds)
21  self.assertEqual(self.errors, errors)
22 
23  def assertParseErrorPath(self, path, func, *args, **kwds):
24  with self.assertRaises(ParseError) as cm:
25  func(*args, **kwds)
26  e = cm.exception
27  self.assertEqual(str(e.path), str(path))
28 
29  def getParseFuncs(self, cls, xml_string):
30  """ Check XML parsing of a given string, using both "from_xml_string" and "parse" """
31  # Static method for parsing an object
32  # TODO: Use parameterized tests to decide which method to use
33  def preclean(func):
34  def op():
35  # Dirty hack to clean external state
36  self.tearDown()
37  self.setUp()
38  func()
39  return op
40  use_static = lambda: cls.from_xml_string(xml_string)
41  # Bound method for parsing an object (backwards compatibility)
42  use_bound = lambda: cls().parse(xml_string)
43  return [use_static, preclean(use_bound)]
44 
45  def test_unknown_tag(self):
46  xml_string = '''<?xml version="1.0"?>
47 <link name="b">
48  <unknown_element/>
49 </link>'''
50  funcs = self.getParseFuncs(urdf.Link, xml_string)
51  errors_expected = ['Unknown tag "unknown_element" in /link[@name=\'b\']']
52  for func in funcs:
53  self.assertLoggedErrors(errors_expected, func)
54 
56  xml_string = '''<?xml version="1.0"?>
57 <link name="b" unknown_attribute="nothing useful"/>'''
58  funcs = self.getParseFuncs(urdf.Link, xml_string)
59  errors_expected = ['Unknown attribute "unknown_attribute" in /link[@name=\'b\']']
60  for func in funcs:
61  self.assertLoggedErrors(errors_expected, func)
62 
64  xml_string = '''<?xml version="1.0"?>
65 <link/>'''
66  funcs = self.getParseFuncs(urdf.Link, xml_string)
67  for func in funcs:
68  self.assertParseErrorPath('/link', func)
69 
71  xml_string = '''<?xml version="1.0"?>
72 <joint name="bad_joint" type="badtype">
73  <parent link="parent"/>
74  <child link="child"/>
75 </joint>'''
76  funcs = self.getParseFuncs(urdf.Joint, xml_string)
77  for func in funcs:
78  self.assertParseErrorPath("/joint[@name='bad_joint']", func)
79 
81  xml_string = '''<?xml version="1.0"?>
82 <robot name="test">
83  <joint name="bad_joint" type="badtype">
84  <parent link="parent"/>
85  <child link="child"/>
86  </joint>
87 </robot>'''
88  funcs = self.getParseFuncs(urdf.Robot, xml_string)
89  for func in funcs:
90  self.assertParseErrorPath("/robot[@name='test']/joint[@name='bad_joint']", func)
91 
93  """ Show that an aggregate with an unset name still has its index specified """
94  xml_string = '''<?xml version="1.0"?>
95 <robot name="test">
96  <link name="good"/>
97  <link name_BAD="bad"/>
98 </robot>'''
99  funcs = self.getParseFuncs(urdf.Robot, xml_string)
100  for func in funcs:
101  self.assertParseErrorPath("/robot[@name='test']/link[2]", func)
102 
104  """ If an aggregate duck-typed element does not have a required attribute, ensure it is reported with the index """
105  xml_string = '''<?xml version="1.0"?>
106 <robot name="test">
107  <transmission name_BAD="bad_trans"/>
108 </robot>'''
109  funcs = self.getParseFuncs(urdf.Robot, xml_string)
110  for func in funcs:
111  self.assertParseErrorPath("/robot[@name='test']/transmission[1]", func)
112 
114  xml_string = '''<?xml version="1.0"?>
115 <robot name="test">
116  <link name="b">
117  <inertial>
118  <origin xyz="0.1 0.2 BAD_NUMBER"/>
119  </inertial>
120  </link>
121 </robot>'''
122  funcs = self.getParseFuncs(urdf.Robot, xml_string)
123  for func in funcs:
124  self.assertParseErrorPath("/robot[@name='test']/link[@name='b']/inertial/origin[@xyz]", func)
125 
126  def test_bad_ducktype(self):
127  xml_string = '''<?xml version="1.0"?>
128 <robot name="test">
129  <transmission name="simple_trans">
130  <type>transmission_interface/SimpleTransmission</type>
131  <joint name="foo_joint">
132  <hardwareInterface>EffortJointInterface</hardwareInterface>
133  </joint>
134  <actuator name="foo_motor"/>
135  </transmission>
136  <transmission name="simple_trans_bad">
137  <type>transmission_interface/SimpleTransmission</type>
138  <actuator name="foo_motor"/>
139  <joint name_BAD="foo_joint">
140  <hardwareInterface>EffortJointInterface</hardwareInterface>
141  </joint>
142  </transmission>
143 </robot>'''
144  funcs = self.getParseFuncs(urdf.Robot, xml_string)
145  for func in funcs:
146  self.assertParseErrorPath("/robot[@name='test']/transmission[@name='simple_trans_bad']", func)
147 
148 if __name__ == '__main__':
149  unittest.main()
def getParseFuncs(self, cls, xml_string)
def assertParseErrorPath(self, path, func, args, kwds)
def assertLoggedErrors(self, errors, func, args, kwds)


urdfdom_py
Author(s): Thomas Moulard, David Lu, Kelsey Hawkins, Antonio El Khoury, Eric Cousineau, Ioan Sucan , Jackie Kay
autogenerated on Mon Feb 28 2022 23:58:25