Go to the documentation of this file.00001
00002 import roslib
00003 roslib.load_manifest('xacro')
00004
00005 import sys
00006 import unittest
00007 import xacro
00008 from xml.dom.minidom import parse, parseString
00009 import xml.dom
00010
00011 def all_attributes_match(a, b):
00012 if len(a.attributes) != len(b.attributes):
00013 print "Different number of attributes"
00014 return False
00015 a_atts = [(a.attributes.item(i).name, a.attributes.item(i).value) for i in range(len(a.attributes))]
00016 b_atts = [(b.attributes.item(i).name, b.attributes.item(i).value) for i in range(len(b.attributes))]
00017 a_atts.sort()
00018 b_atts.sort()
00019
00020 for i in range(len(a_atts)):
00021 if a_atts[i][0] != b_atts[i][0]:
00022 print "Different attribute names: %s and %s" % (a_atts[i][0], b_atts[i][0])
00023 return False
00024 try:
00025 if abs(float(a_atts[i][1]) - float(b_atts[i][1])) > 1.0e-9:
00026 print "Different attribute values: %s and %s" % (a_atts[i][1], b_atts[i][1])
00027 return False
00028 except ValueError:
00029 if a_atts[i][1] != b_atts[i][1]:
00030 print "Different attribute values: %s and %s" % (a_atts[i][1], b_atts[i][1])
00031 return False
00032
00033 return True
00034
00035 def elements_match(a, b):
00036 if not a and not b:
00037 return True
00038 if not a or not b:
00039 return False
00040
00041 if a.nodeType != b.nodeType:
00042 print "Different node types: %d and %d" % (a.nodeType, b.nodeType)
00043 return False
00044 if a.nodeName != b.nodeName:
00045 print "Different element names: %s and %s" % (a.nodeName, b.nodeName)
00046 return False
00047
00048 if not all_attributes_match(a, b):
00049 return False
00050
00051 if not elements_match(xacro.first_child_element(a), xacro.first_child_element(b)):
00052 return False
00053 if not elements_match(xacro.next_sibling_element(a), xacro.next_sibling_element(b)):
00054 return False
00055 return True
00056
00057 def xml_matches(a, b):
00058 if isinstance(a, str):
00059 return xml_matches(parseString(a).documentElement, b)
00060 if isinstance(b, str):
00061 return xml_matches(a, parseString(b).documentElement)
00062 if a.nodeType == xml.dom.Node.DOCUMENT_NODE:
00063 return xml_matches(a.documentElement, b)
00064 if b.nodeType == xml.dom.Node.DOCUMENT_NODE:
00065 return xml_matches(a, b.documentElement)
00066
00067 if not elements_match(a, b):
00068 print "Match failed:"
00069 a.writexml(sys.stdout)
00070 print
00071 print '='*78
00072 b.writexml(sys.stdout)
00073 return False
00074 return True
00075
00076 def quick_xacro(xml):
00077 if isinstance(xml, str):
00078 doc = parseString(xml)
00079 return quick_xacro(doc)
00080 xacro.eval_self_contained(xml)
00081 return xml
00082
00083
00084 class TestXacro(unittest.TestCase):
00085
00086 def test_DEPRECATED_should_replace_before_macroexpand(self):
00087 self.assertTrue(
00088 xml_matches(
00089 quick_xacro('''<a>
00090 <macro name="inner" params="*the_block">
00091 <in_the_inner><insert_block name="the_block" /></in_the_inner>
00092 </macro>
00093 <macro name="outer" params="*the_block">
00094 <in_the_outer><inner><insert_block name="the_block" /></inner></in_the_outer>
00095 </macro>
00096 <outer><woot /></outer></a>'''),
00097 '''<a>
00098 <in_the_outer><in_the_inner><woot /></in_the_inner></in_the_outer></a>'''))
00099
00100 def test_should_replace_before_macroexpand(self):
00101 self.assertTrue(
00102 xml_matches(
00103 quick_xacro('''<a xmlns:xacro="http://www.ros.org/wiki/xacro">
00104 <xacro:macro name="inner" params="*the_block">
00105 <in_the_inner><xacro:insert_block name="the_block" /></in_the_inner>
00106 </xacro:macro>
00107 <xacro:macro name="outer" params="*the_block">
00108 <in_the_outer><xacro:inner><insert_block name="the_block" /></xacro:inner></in_the_outer>
00109 </xacro:macro>
00110 <xacro:outer><woot /></xacro:outer></a>'''),
00111 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro">
00112 <in_the_outer><in_the_inner><woot /></in_the_inner></in_the_outer></a>'''))
00113
00114 def test_property_replacement(self):
00115 self.assertTrue(
00116 xml_matches(
00117 quick_xacro('''<a xmlns:xacro="http://www.ros.org/wiki/xacro">
00118 <xacro:property name="foo" value="42" />
00119 <the_foo result="${foo}" />
00120 </a>'''),
00121 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro">
00122 <the_foo result="42" />
00123 </a>'''))
00124
00125 def test_math_ignores_spaces(self):
00126 self.assertTrue(
00127 xml_matches(
00128 quick_xacro('''<a><f v="${0.9 / 2 - 0.2}" /></a>'''),
00129 '''<a><f v="0.25" /></a>'''))
00130
00131 def test_escaping_dollar_braces(self):
00132 self.assertTrue(
00133 xml_matches(
00134 quick_xacro('''<a b="$${foo}" c="$$${foo}" />'''),
00135 '''<a b="${foo}" c="$${foo}" />'''))
00136
00137 def test_just_a_dollar_sign(self):
00138 self.assertTrue(
00139 xml_matches(
00140 quick_xacro('''<a b="$" />'''),
00141 '''<a b="$" />'''))
00142
00143 def test_multiple_insert_blocks(self):
00144 self.assertTrue(
00145 xml_matches(
00146 quick_xacro('''<a xmlns:xacro="http://www.ros.org/wiki/xacro">
00147 <xacro:macro name="foo" params="*block">
00148 <xacro:insert_block name="block" />
00149 <xacro:insert_block name="block" />
00150 </xacro:macro>
00151 <xacro:foo>
00152 <a_block />
00153 </xacro:foo>
00154 </a>'''),
00155 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro">
00156 <a_block />
00157 <a_block />
00158 </a>'''))
00159
00160 def test_multiple_blocks(self):
00161 self.assertTrue(
00162 xml_matches(
00163 quick_xacro('''<a xmlns:xacro="http://www.ros.org/wiki/xacro">
00164 <xacro:macro name="foo" params="*block1 *block2">
00165 <xacro:insert_block name="block2" />
00166 <first>
00167 <xacro:insert_block name="block1" />
00168 </first>
00169 </xacro:macro>
00170 <xacro:foo>
00171 <first_block />
00172 <second_block />
00173 </xacro:foo>
00174 </a>'''),
00175 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro">
00176 <second_block />
00177 <first>
00178 <first_block />
00179 </first>
00180 </a>'''))
00181
00182 def test_integer_stays_integer(self):
00183 self.assertTrue(
00184 xml_matches(
00185 quick_xacro('''<a xmlns:xacro="http://www.ros.org/wiki/xacro">
00186 <xacro:macro name="m" params="num">
00187 <test number="${num}" />
00188 </xacro:macro>
00189 <xacro:m num="100" />
00190 </a>'''),
00191 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro">
00192 <test number="100" />
00193 </a>'''))
00194
00195
00196 def test_insert_block_property(self):
00197 self.assertTrue(
00198 xml_matches(
00199 quick_xacro('''<a xmlns:xacro="http://www.ros.org/wiki/xacro">
00200 <xacro:property name="some_block">
00201 <some_block />
00202 </xacro:property>
00203 <foo>
00204 <xacro:insert_block name="some_block" />
00205 </foo>
00206 </a>'''),
00207 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro">
00208 <foo><some_block /></foo>
00209 </a>'''))
00210
00211
00212
00213 if __name__ == '__main__':
00214 import rostest
00215 rostest.unitrun('xacro', 'test_xacro', TestXacro)