$search
00001 #! /usr/bin/env python 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: # Attribute values aren't numeric 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)