14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Test case for property 24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# more tests are in test_descr 34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport sys 54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport unittest 64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom test.test_support import run_unittest 74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PropertyBase(Exception): 94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PropertyGet(PropertyBase): 124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PropertySet(PropertyBase): 154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PropertyDel(PropertyBase): 184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass BaseClass(object): 214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __init__(self): 224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._spam = 5 234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @property 254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """BaseClass.getter""" 274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self._spam 284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @spam.setter 304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self, value): 314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._spam = value 324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @spam.deleter 344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm del self._spam 364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass SubClass(BaseClass): 384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @BaseClass.spam.getter 404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """SubClass.getter""" 424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise PropertyGet(self._spam) 434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @spam.setter 454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self, value): 464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise PropertySet(self._spam) 474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @spam.deleter 494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise PropertyDel(self._spam) 514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PropertyDocBase(object): 534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _spam = 1 544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def _get_spam(self): 554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self._spam 564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm spam = property(_get_spam, doc="spam spam spam") 574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PropertyDocSub(PropertyDocBase): 594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @PropertyDocBase.spam.getter 604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """The decorator does not use this doc string""" 624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self._spam 634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PropertySubNewGetter(BaseClass): 654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @BaseClass.spam.getter 664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """new docstring""" 684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 5 694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PropertyNewGetter(object): 714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @property 724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """original docstring""" 744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 1 754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @spam.getter 764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """new docstring""" 784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 8 794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PropertyTests(unittest.TestCase): 814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_property_decorator_baseclass(self): 824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # see #1620 834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm base = BaseClass() 844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(base.spam, 5) 854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(base._spam, 5) 864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm base.spam = 10 874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(base.spam, 10) 884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(base._spam, 10) 894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm delattr(base, "spam") 904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(not hasattr(base, "spam")) 914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertTrue(not hasattr(base, "_spam")) 924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm base.spam = 20 934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(base.spam, 20) 944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(base._spam, 20) 954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_property_decorator_subclass(self): 974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # see #1620 984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sub = SubClass() 994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(PropertyGet, getattr, sub, "spam") 1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(PropertySet, setattr, sub, "spam", None) 1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertRaises(PropertyDel, delattr, sub, "spam") 1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @unittest.skipIf(sys.flags.optimize >= 2, 1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Docstrings are omitted with -O2 and above") 1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_property_decorator_subclass_doc(self): 1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sub = SubClass() 1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(sub.__class__.spam.__doc__, "SubClass.getter") 1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @unittest.skipIf(sys.flags.optimize >= 2, 1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Docstrings are omitted with -O2 and above") 1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_property_decorator_baseclass_doc(self): 1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm base = BaseClass() 1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(base.__class__.spam.__doc__, "BaseClass.getter") 1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_property_decorator_doc(self): 1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm base = PropertyDocBase() 1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sub = PropertyDocSub() 1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(base.__class__.spam.__doc__, "spam spam spam") 1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(sub.__class__.spam.__doc__, "spam spam spam") 1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @unittest.skipIf(sys.flags.optimize >= 2, 1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Docstrings are omitted with -O2 and above") 1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_property_getter_doc_override(self): 1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm newgettersub = PropertySubNewGetter() 1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(newgettersub.spam, 5) 1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(newgettersub.__class__.spam.__doc__, "new docstring") 1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm newgetter = PropertyNewGetter() 1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(newgetter.spam, 8) 1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(newgetter.__class__.spam.__doc__, "new docstring") 1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# Issue 5890: subclasses of property do not preserve method __doc__ strings 1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PropertySub(property): 1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """This is a subclass of property""" 1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PropertySubSlots(property): 1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """This is a subclass of property that defines __slots__""" 1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm __slots__ = () 1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass PropertySubclassTests(unittest.TestCase): 1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_slots_docstring_copy_exception(self): 1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm try: 1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class Foo(object): 1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @PropertySubSlots 1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Trying to copy this docstring will raise an exception""" 1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 1 1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm except AttributeError: 1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pass 1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise Exception("AttributeError not raised") 1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @unittest.skipIf(sys.flags.optimize >= 2, 1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Docstrings are omitted with -O2 and above") 1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_docstring_copy(self): 1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class Foo(object): 1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @PropertySub 1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """spam wrapped in property subclass""" 1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 1 1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Foo.spam.__doc__, 1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "spam wrapped in property subclass") 1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @unittest.skipIf(sys.flags.optimize <= 2, 1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Docstrings are omitted with -O2 and above") 1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_property_setter_copies_getter_docstring(self): 1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class Foo(object): 1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __init__(self): self._spam = 1 1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @PropertySub 1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """spam wrapped in property subclass""" 1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self._spam 1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @spam.setter 1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self, value): 1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """this docstring is ignored""" 1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._spam = value 1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm foo = Foo() 1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(foo.spam, 1) 1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm foo.spam = 2 1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(foo.spam, 2) 1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Foo.spam.__doc__, 1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "spam wrapped in property subclass") 1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class FooSub(Foo): 1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @Foo.spam.setter 1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self, value): 1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """another ignored docstring""" 1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self._spam = 'eggs' 1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm foosub = FooSub() 1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(foosub.spam, 1) 1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm foosub.spam = 7 1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(foosub.spam, 'eggs') 1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual( 1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm FooSub.spam.__doc__, 1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "spam wrapped in property subclass") 1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @unittest.skipIf(sys.flags.optimize <= 2, 2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm "Docstrings are omitted with -O2 and above") 2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def test_property_new_getter_new_docstring(self): 2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class Foo(object): 2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @PropertySub 2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """a docstring""" 2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 1 2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @spam.getter 2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """a new docstring""" 2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 2 2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Foo.spam.__doc__, "a new docstring") 2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class FooBase(object): 2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @PropertySub 2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """a docstring""" 2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 1 2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm class Foo2(FooBase): 2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm @FooBase.spam.getter 2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def spam(self): 2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """a new docstring""" 2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 2 2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.assertEqual(Foo.spam.__doc__, "a new docstring") 2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef test_main(): 2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm run_unittest(PropertyTests, PropertySubclassTests) 2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == '__main__': 2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm test_main() 232