2 GTSAM Copyright 2010-2020, Georgia Tech Research Corporation,
3 Atlanta, Georgia 30332-0415
6 See LICENSE for the license information
8 Tests for interface_parser.
19 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
22 DunderMethod, Enum, Enumerator,
23 ForwardDeclaration, GlobalFunction,
24 Include, Method, Module, Namespace,
25 Operator, ReturnType, StaticMethod,
27 TypedefTemplateInstantiation, Typename,
33 """Test driver for all classes in interface_parser.py."""
36 """Test parsing of Typename."""
37 typename = Typename.rule.parseString(
"size_t")[0]
38 self.assertEqual(
"size_t", typename.name)
41 """Tests for BasicType."""
43 t = Type.rule.parseString(
"int x")[0]
44 self.assertEqual(
"int", t.typename.name)
45 self.assertTrue(t.is_basic)
48 t = Type.rule.parseString(
"const int x")[0]
49 self.assertEqual(
"int", t.typename.name)
50 self.assertTrue(t.is_basic)
51 self.assertTrue(t.is_const)
54 t = Type.rule.parseString(
"int* x")[0]
55 self.assertEqual(
"int", t.typename.name)
56 self.assertTrue(t.is_shared_ptr)
59 t = Type.rule.parseString(
"int@ x")[0]
60 self.assertEqual(
"int", t.typename.name)
61 self.assertTrue(t.is_ptr)
64 t = Type.rule.parseString(
"int& x")[0]
65 self.assertEqual(
"int", t.typename.name)
66 self.assertTrue(t.is_ref)
69 t = Type.rule.parseString(
"const int& x")[0]
70 self.assertEqual(
"int", t.typename.name)
71 self.assertTrue(t.is_const)
72 self.assertTrue(t.is_ref)
75 """Tests for CustomType."""
77 t = Type.rule.parseString(
"gtsam::Pose3 x")[0]
78 self.assertEqual(
"Pose3", t.typename.name)
79 self.assertEqual([
"gtsam"], t.typename.namespaces)
80 self.assertTrue(
not t.is_basic)
83 t = Type.rule.parseString(
"const gtsam::Pose3 x")[0]
84 self.assertEqual(
"Pose3", t.typename.name)
85 self.assertEqual([
"gtsam"], t.typename.namespaces)
86 self.assertTrue(t.is_const)
89 t = Type.rule.parseString(
"gtsam::Pose3* x")[0]
90 self.assertEqual(
"Pose3", t.typename.name)
91 self.assertEqual([
"gtsam"], t.typename.namespaces)
92 self.assertTrue(t.is_shared_ptr)
93 self.assertEqual(
"std::shared_ptr<gtsam::Pose3>", t.to_cpp())
96 t = Type.rule.parseString(
"gtsam::Pose3@ x")[0]
97 self.assertEqual(
"Pose3", t.typename.name)
98 self.assertEqual([
"gtsam"], t.typename.namespaces)
99 self.assertTrue(t.is_ptr)
102 t = Type.rule.parseString(
"gtsam::Pose3& x")[0]
103 self.assertEqual(
"Pose3", t.typename.name)
104 self.assertEqual([
"gtsam"], t.typename.namespaces)
105 self.assertTrue(t.is_ref)
108 t = Type.rule.parseString(
"const gtsam::Pose3& x")[0]
109 self.assertEqual(
"Pose3", t.typename.name)
110 self.assertEqual([
"gtsam"], t.typename.namespaces)
111 self.assertTrue(t.is_const)
112 self.assertTrue(t.is_ref)
115 """Test a templated type."""
116 t = TemplatedType.rule.parseString(
"Eigen::Matrix<double, 3, 4>")[0]
117 self.assertEqual(
"Matrix", t.typename.name)
118 self.assertEqual([
"Eigen"], t.typename.namespaces)
119 self.assertEqual(
"double", t.typename.instantiations[0].name)
120 self.assertEqual(
"3", t.typename.instantiations[1].name)
121 self.assertEqual(
"4", t.typename.instantiations[2].name)
123 t = TemplatedType.rule.parseString(
124 "gtsam::PinholeCamera<gtsam::Cal3S2>")[0]
125 self.assertEqual(
"PinholeCamera", t.typename.name)
126 self.assertEqual([
"gtsam"], t.typename.namespaces)
127 self.assertEqual(
"Cal3S2", t.typename.instantiations[0].name)
128 self.assertEqual([
"gtsam"], t.typename.instantiations[0].namespaces)
130 t = TemplatedType.rule.parseString(
"PinholeCamera<Cal3S2*>")[0]
131 self.assertEqual(
"PinholeCamera", t.typename.name)
132 self.assertEqual(
"Cal3S2", t.typename.instantiations[0].name)
133 self.assertTrue(t.template_params[0].is_shared_ptr)
136 """Test no arguments."""
137 empty_args = ArgumentList.rule.parseString(
"")[0]
138 self.assertEqual(0,
len(empty_args))
141 """Test arguments list for a method/function."""
142 arg_string =
"int a, C1 c1, C2& c2, C3* c3, "\
143 "const C4 c4, const C5& c5,"\
145 args = ArgumentList.rule.parseString(arg_string)[0]
147 self.assertEqual(7,
len(args.list()))
148 self.assertEqual([
'a',
'c1',
'c2',
'c3',
'c4',
'c5',
'c6'],
153 Test arguments list where the arguments are qualified with `const`
154 and can be either raw pointers, shared pointers or references.
156 arg_string =
"double x1, double* x2, double& x3, double@ x4, " \
157 "const double x5, const double* x6, const double& x7, const double@ x8"
158 args = ArgumentList.rule.parseString(arg_string)[0].
list()
159 self.assertEqual(8,
len(args))
160 self.assertFalse(args[1].ctype.is_ptr
and args[1].ctype.is_shared_ptr
161 and args[1].ctype.is_ref)
162 self.assertTrue(args[1].ctype.is_shared_ptr)
163 self.assertTrue(args[2].ctype.is_ref)
164 self.assertTrue(args[3].ctype.is_ptr)
165 self.assertTrue(args[4].ctype.is_const)
166 self.assertTrue(args[5].ctype.is_shared_ptr
and args[5].ctype.is_const)
167 self.assertTrue(args[6].ctype.is_ref
and args[6].ctype.is_const)
168 self.assertTrue(args[7].ctype.is_ptr
and args[7].ctype.is_const)
171 """Test arguments list where the arguments can be templated."""
172 arg_string =
"std::pair<string, double> steps, vector<T*> vector_of_pointers"
173 args = ArgumentList.rule.parseString(arg_string)[0]
174 args_list = args.list()
175 self.assertEqual(2,
len(args_list))
176 self.assertEqual(
"std::pair<string, double>",
177 args_list[0].ctype.to_cpp())
178 self.assertEqual(
"vector<std::shared_ptr<T>>",
179 args_list[1].ctype.to_cpp())
182 """Tests any expression that is a valid default argument"""
183 args = ArgumentList.rule.parseString(
"""
184 string c = "", int z = 0, double z2 = 0.0, bool f = false,
185 string s="hello"+"goodbye", char c='a', int a=3,
186 int b, double pi = 3.1415""")[0].
list()
189 self.assertEqual(args[0].default,
'""')
190 self.assertEqual(args[1].default,
'0')
191 self.assertEqual(args[2].default,
'0.0')
192 self.assertEqual(args[3].default,
"false")
193 self.assertEqual(args[4].default,
'"hello"+"goodbye"')
194 self.assertEqual(args[5].default,
"'a'")
195 self.assertEqual(args[6].default,
'3')
197 self.assertIsNone(args[7].default)
198 self.assertEqual(args[8].default,
'3.1415')
200 arg0 =
'gtsam::DefaultKeyFormatter'
201 arg1 =
'std::vector<size_t>()'
203 arg3 =
'[&c1, &c2](string s=5, int a){return s+"hello"+a+c1+c2;}'
204 arg4 =
'gtsam::Pose3()'
205 arg5 =
'Factor<gtsam::Pose3, gtsam::Point3>()'
206 arg6 =
'gtsam::Point3(1, 2, 3)'
207 arg7 =
'ns::Class<T, U>(3, 2, 1, "name")'
210 gtsam::KeyFormatter kf = {arg0},
211 std::vector<size_t> v = {arg1},
212 std::vector<size_t> l = {arg2},
213 gtsam::KeyFormatter lambda = {arg3},
214 gtsam::Pose3 p = {arg4},
215 Factor<gtsam::Pose3, gtsam::Point3> x = {arg5},
216 gtsam::Point3 x = {arg6},
217 ns::Class<T, U> obj = {arg7}
226 args = ArgumentList.rule.parseString(argument_list)[0].
list()
229 self.assertEqual(args[0].default, arg0)
231 self.assertEqual(args[1].default, arg1)
232 self.assertEqual(args[2].default, arg2)
233 self.assertEqual(args[3].default, arg3)
234 self.assertEqual(args[4].default, arg4)
235 self.assertEqual(args[5].default, arg5)
236 self.assertEqual(args[6].default, arg6)
238 self.assertEqual(args[7].default, arg7)
241 """Test ReturnType"""
243 return_type = ReturnType.rule.parseString(
"void")[0]
244 self.assertEqual(
"void", return_type.type1.typename.name)
245 self.assertTrue(return_type.type1.is_basic)
248 return_type = ReturnType.rule.parseString(
"size_t")[0]
249 self.assertEqual(
"size_t", return_type.type1.typename.name)
250 self.assertTrue(
not return_type.type2)
251 self.assertTrue(return_type.type1.is_basic)
254 return_type = ReturnType.rule.parseString(
"int&")[0]
255 self.assertEqual(
"int", return_type.type1.typename.name)
256 self.assertTrue(return_type.type1.is_basic
257 and return_type.type1.is_ref)
259 return_type = ReturnType.rule.parseString(
"const int")[0]
260 self.assertEqual(
"int", return_type.type1.typename.name)
261 self.assertTrue(return_type.type1.is_basic
262 and return_type.type1.is_const)
265 return_type = ReturnType.rule.parseString(
"pair<char, int>")[0]
266 self.assertEqual(
"char", return_type.type1.typename.name)
267 self.assertEqual(
"int", return_type.type2.typename.name)
269 return_type = ReturnType.rule.parseString(
"pair<Test ,Test*>")[0]
270 self.assertEqual(
"Test", return_type.type1.typename.name)
271 self.assertEqual(
"Test", return_type.type2.typename.name)
272 self.assertTrue(return_type.type2.is_shared_ptr)
275 """Test for a class method."""
276 ret = Method.rule.parseString(
"int f();")[0]
277 self.assertEqual(
"f", ret.name)
278 self.assertEqual(0,
len(ret.args))
279 self.assertTrue(
not ret.is_const)
281 ret = Method.rule.parseString(
"int f() const;")[0]
282 self.assertEqual(
"f", ret.name)
283 self.assertEqual(0,
len(ret.args))
284 self.assertTrue(ret.is_const)
286 ret = Method.rule.parseString(
287 "int f(const int x, const Class& c, Class* t) const;")[0]
288 self.assertEqual(
"f", ret.name)
289 self.assertEqual(3,
len(ret.args))
291 ret = Method.rule.parseString(
292 "pair<First ,Second*> create_MixedPtrs();")[0]
293 self.assertEqual(
"create_MixedPtrs", ret.name)
294 self.assertEqual(0,
len(ret.args))
295 self.assertEqual(
"First", ret.return_type.type1.typename.name)
296 self.assertEqual(
"Second", ret.return_type.type2.typename.name)
299 """Test for static methods."""
300 ret = StaticMethod.rule.parseString(
"static int f();")[0]
301 self.assertEqual(
"f", ret.name)
302 self.assertEqual(0,
len(ret.args))
304 ret = StaticMethod.rule.parseString(
305 "static int f(const int x, const Class& c, Class* t);")[0]
306 self.assertEqual(
"f", ret.name)
307 self.assertEqual(3,
len(ret.args))
310 """Test for class constructor."""
311 ret = Constructor.rule.parseString(
"f();")[0]
312 self.assertEqual(
"f", ret.name)
313 self.assertEqual(0,
len(ret.args))
315 ret = Constructor.rule.parseString(
316 "f(const int x, const Class& c, Class* t);")[0]
317 self.assertEqual(
"f", ret.name)
318 self.assertEqual(3,
len(ret.args))
320 ret = Constructor.rule.parseString(
321 """ForwardKinematics(const gtdynamics::Robot& robot,
322 const string& start_link_name, const string& end_link_name,
323 const gtsam::Values& joint_angles,
324 const gtsam::Pose3& l2Tp = gtsam::Pose3());""")[0]
325 self.assertEqual(
"ForwardKinematics", ret.name)
326 self.assertEqual(5,
len(ret.args))
327 self.assertEqual(
"gtsam::Pose3()", ret.args.list()[4].default)
330 """Test for templated class constructor."""
332 template<T = {double, int}>
335 ret = Constructor.rule.parseString(f)[0]
336 self.assertEqual(
"Class", ret.name)
337 self.assertEqual(0,
len(ret.args))
340 template<T = {double, int}>
341 Class(const T& name);
343 ret = Constructor.rule.parseString(f)[0]
344 self.assertEqual(
"Class", ret.name)
345 self.assertEqual(1,
len(ret.args))
346 self.assertEqual(
"const T & name", ret.args.args_list[0].
to_cpp())
349 """Test for special python dunder methods."""
350 iter_string =
"__iter__();"
351 ret = DunderMethod.rule.parse_string(iter_string)[0]
352 self.assertEqual(
"iter", ret.name)
354 contains_string =
"__contains__(size_t key);"
355 ret = DunderMethod.rule.parse_string(contains_string)[0]
356 self.assertEqual(
"contains", ret.name)
357 self.assertTrue(
len(ret.args) == 1)
360 """Test for operator overloading."""
362 wrap_string =
"gtsam::Vector2 operator-() const;"
363 ret = Operator.rule.parseString(wrap_string)[0]
364 self.assertEqual(
"operator", ret.name)
365 self.assertEqual(
"-", ret.operator)
366 self.assertEqual(
"Vector2", ret.return_type.type1.typename.name)
367 self.assertEqual(
"gtsam::Vector2",
368 ret.return_type.type1.typename.to_cpp())
369 self.assertTrue(
len(ret.args) == 0)
370 self.assertTrue(ret.is_unary)
373 wrap_string =
"gtsam::Vector2 operator*(const gtsam::Vector2 &v) const;"
374 ret = Operator.rule.parseString(wrap_string)[0]
375 self.assertEqual(
"operator", ret.name)
376 self.assertEqual(
"*", ret.operator)
377 self.assertEqual(
"Vector2", ret.return_type.type1.typename.name)
378 self.assertEqual(
"gtsam::Vector2",
379 ret.return_type.type1.typename.to_cpp())
380 self.assertTrue(
len(ret.args) == 1)
381 self.assertEqual(
"const gtsam::Vector2 &",
382 repr(ret.args.list()[0].ctype))
383 self.assertTrue(
not ret.is_unary)
386 """Test for typedef'd instantiation of a template."""
387 typedef = TypedefTemplateInstantiation.rule.parseString(
"""
388 typedef gtsam::BearingFactor<gtsam::Pose2, gtsam::Point2, gtsam::Rot2>
391 self.assertEqual(
"BearingFactor2D", typedef.new_name)
392 self.assertEqual(
"BearingFactor", typedef.typename.name)
393 self.assertEqual([
"gtsam"], typedef.typename.namespaces)
394 self.assertEqual(3,
len(typedef.typename.instantiations))
397 """Test a base class."""
398 ret = Class.rule.parseString(
"""
402 self.assertEqual(
"Base", ret.name)
403 self.assertEqual(0,
len(ret.ctors))
404 self.assertEqual(0,
len(ret.methods))
405 self.assertEqual(0,
len(ret.static_methods))
406 self.assertEqual(0,
len(ret.properties))
407 self.assertTrue(ret.is_virtual)
410 """Test an empty class declaration."""
411 ret = Class.rule.parseString(
"""
412 class FactorIndices {};
414 self.assertEqual(
"FactorIndices", ret.name)
415 self.assertEqual(0,
len(ret.ctors))
416 self.assertEqual(0,
len(ret.methods))
417 self.assertEqual(0,
len(ret.static_methods))
418 self.assertEqual(0,
len(ret.properties))
419 self.assertTrue(
not ret.is_virtual)
422 """Test a non-trivial class."""
423 ret = Class.rule.parseString(
"""
424 class SymbolicFactorGraph {
425 SymbolicFactorGraph();
426 SymbolicFactorGraph(const gtsam::SymbolicBayesNet& bayesNet);
427 SymbolicFactorGraph(const gtsam::SymbolicBayesTree& bayesTree);
429 // Dummy static method
430 static gtsam::SymbolidFactorGraph CreateGraph();
432 void push_back(gtsam::SymbolicFactor* factor);
433 void print(string s) const;
434 bool equals(const gtsam::SymbolicFactorGraph& rhs, double tol) const;
436 bool exists(size_t idx) const;
438 // Standard interface
439 gtsam::KeySet keys() const;
440 void push_back(const gtsam::SymbolicFactorGraph& graph);
441 void push_back(const gtsam::SymbolicBayesNet& bayesNet);
442 void push_back(const gtsam::SymbolicBayesTree& bayesTree);
444 /* Advanced interface */
445 void push_factor(size_t key);
446 void push_factor(size_t key1, size_t key2);
447 void push_factor(size_t key1, size_t key2, size_t key3);
448 void push_factor(size_t key1, size_t key2, size_t key3, size_t key4);
450 gtsam::SymbolicBayesNet* eliminateSequential();
451 gtsam::SymbolicBayesNet* eliminateSequential(
452 const gtsam::Ordering& ordering);
453 gtsam::SymbolicBayesTree* eliminateMultifrontal();
454 gtsam::SymbolicBayesTree* eliminateMultifrontal(
455 const gtsam::Ordering& ordering);
456 pair<gtsam::SymbolicBayesNet*, gtsam::SymbolicFactorGraph*>
457 eliminatePartialSequential(const gtsam::Ordering& ordering);
458 pair<gtsam::SymbolicBayesNet*, gtsam::SymbolicFactorGraph*>
459 eliminatePartialSequential(const gtsam::KeyVector& keys);
460 pair<gtsam::SymbolicBayesTree*, gtsam::SymbolicFactorGraph*>
461 eliminatePartialMultifrontal(const gtsam::Ordering& ordering);
462 gtsam::SymbolicBayesNet* marginalMultifrontalBayesNet(
463 const gtsam::Ordering& ordering);
464 gtsam::SymbolicBayesNet* marginalMultifrontalBayesNet(
465 const gtsam::KeyVector& key_vector,
466 const gtsam::Ordering& marginalizedVariableOrdering);
467 gtsam::SymbolicFactorGraph* marginal(const gtsam::KeyVector& key_vector);
471 self.assertEqual(
"SymbolicFactorGraph", ret.name)
472 self.assertEqual(3,
len(ret.ctors))
473 self.assertEqual(23,
len(ret.methods))
474 self.assertEqual(1,
len(ret.static_methods))
475 self.assertEqual(0,
len(ret.properties))
476 self.assertTrue(
not ret.is_virtual)
479 """Test a templated class."""
480 ret = Class.rule.parseString(
"""
481 template<POSE, POINT>
485 self.assertEqual(
"MyFactor", ret.name)
486 self.assertEqual(
"<POSE, POINT>",
repr(ret.template))
489 """Test for class inheritance."""
490 ret = Class.rule.parseString(
"""
491 virtual class Null: gtsam::noiseModel::mEstimator::Base {
493 void print(string s) const;
494 static gtsam::noiseModel::mEstimator::Null* Create();
496 // enabling serialization functionality
497 void serializable() const;
500 self.assertEqual(
"Null", ret.name)
501 self.assertEqual(1,
len(ret.ctors))
502 self.assertEqual(2,
len(ret.methods))
503 self.assertEqual(1,
len(ret.static_methods))
504 self.assertEqual(0,
len(ret.properties))
505 self.assertEqual(
"Base", ret.parent_class.name)
506 self.assertEqual([
"gtsam",
"noiseModel",
"mEstimator"],
507 ret.parent_class.namespaces)
508 self.assertTrue(ret.is_virtual)
510 ret = Class.rule.parseString(
511 "class ForwardKinematicsFactor : gtsam::BetweenFactor<gtsam::Pose3> {};"
515 self.assertEqual(
"ForwardKinematicsFactor", ret.name)
516 self.assertEqual(
"BetweenFactor", ret.parent_class.name)
517 self.assertEqual([
"gtsam"], ret.parent_class.namespaces)
518 self.assertEqual(
"Pose3", ret.parent_class.instantiations[0].name)
519 self.assertEqual([
"gtsam"],
520 ret.parent_class.instantiations[0].namespaces)
523 """Test for class with nested enum."""
524 ret = Class.rule.parseString(
"""
526 Pet(const string &name, Kind type);
527 enum Kind { Dog, Cat };
530 self.assertEqual(ret.name,
"Pet")
531 self.assertEqual(ret.enums[0].name,
"Kind")
534 """Test for include statements."""
535 include = Include.rule.parseString(
536 "#include <gtsam/slam/PriorFactor.h>")[0]
537 self.assertEqual(
"gtsam/slam/PriorFactor.h", include.header)
540 """Test for forward declarations."""
541 fwd = ForwardDeclaration.rule.parseString(
542 "virtual class Test:gtsam::Point3;")[0]
544 self.assertEqual(
"Test", fwd.name)
545 self.assertTrue(fwd.is_virtual)
548 """Test for global/free function."""
549 func = GlobalFunction.rule.parseString(
"""
550 gtsam::Values localToWorld(const gtsam::Values& local,
551 const gtsam::Pose2& base, const gtsam::KeyVector& keys);
553 self.assertEqual(
"localToWorld", func.name)
554 self.assertEqual(
"Values", func.return_type.type1.typename.name)
555 self.assertEqual(3,
len(func.args))
558 """Test for global variable."""
559 variable = Variable.rule.parseString(
"string kGravity;")[0]
560 self.assertEqual(variable.name,
"kGravity")
561 self.assertEqual(variable.ctype.typename.name,
"string")
563 variable = Variable.rule.parseString(
"string kGravity = 9.81;")[0]
564 self.assertEqual(variable.name,
"kGravity")
565 self.assertEqual(variable.ctype.typename.name,
"string")
566 self.assertEqual(variable.default,
"9.81")
568 variable = Variable.rule.parseString(
569 "const string kGravity = 9.81;")[0]
570 self.assertEqual(variable.name,
"kGravity")
571 self.assertEqual(variable.ctype.typename.name,
"string")
572 self.assertTrue(variable.ctype.is_const)
573 self.assertEqual(variable.default,
"9.81")
575 variable = Variable.rule.parseString(
576 "gtsam::Pose3 wTc = gtsam::Pose3();")[0]
577 self.assertEqual(variable.name,
"wTc")
578 self.assertEqual(variable.ctype.typename.name,
"Pose3")
579 self.assertEqual(variable.default,
"gtsam::Pose3()")
581 variable = Variable.rule.parseString(
582 "gtsam::Pose3 wTc = gtsam::Pose3(1, 2, 0);")[0]
583 self.assertEqual(variable.name,
"wTc")
584 self.assertEqual(variable.ctype.typename.name,
"Pose3")
585 self.assertEqual(variable.default,
"gtsam::Pose3(1, 2, 0)")
588 """Test for enumerator."""
589 enumerator = Enumerator.rule.parseString(
"Dog")[0]
590 self.assertEqual(enumerator.name,
"Dog")
592 enumerator = Enumerator.rule.parseString(
"Cat")[0]
593 self.assertEqual(enumerator.name,
"Cat")
596 """Test for enums."""
597 enum = Enum.rule.parseString(
"""
603 self.assertEqual(enum.name,
"Kind")
604 self.assertEqual(enum.enumerators[0].name,
"Dog")
605 self.assertEqual(enum.enumerators[1].name,
"Cat")
608 """Test for namespace parsing."""
609 namespace = Namespace.rule.parseString(
"""
611 #include <gtsam/geometry/Point2.h>
614 Point2(double x, double y);
618 char returnChar() const;
619 void argChar(char a) const;
620 void argUChar(unsigned char a) const;
623 #include <gtsam/geometry/Point3.h>
625 Point3(double x, double y, double z);
628 // static functions - use static keyword and uppercase
629 static double staticFunction();
630 static gtsam::Point3 StaticFunctionRet(double z);
632 // enabling serialization functionality
633 void serialize() const; // Just triggers a flag internally
636 self.assertEqual(
"gtsam", namespace.name)
639 """Test module parsing."""
640 module = Module.parseString(
"""
650 namespace two_dummy {
651 namespace three_dummy{
654 namespace fourth_dummy{
671 self.assertEqual([
"one",
"Global",
"globalVar"],
672 [x.name
for x
in module.content])
673 self.assertEqual([
"two",
"two_dummy",
"two",
"oneVar"],
674 [x.name
for x
in module.content[0].content])
677 if __name__ ==
'__main__':