mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			212 lines
		
	
	
	
		
			8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
	
		
			8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
 | |
| import unittest, struct
 | |
| import os
 | |
| from test import test_support
 | |
| 
 | |
| def isinf(x):
 | |
|     return x * 0.5 == x
 | |
| 
 | |
| def isnan(x):
 | |
|     return x != x
 | |
| 
 | |
| class FormatFunctionsTestCase(unittest.TestCase):
 | |
| 
 | |
|     def setUp(self):
 | |
|         self.save_formats = {'double':float.__getformat__('double'),
 | |
|                              'float':float.__getformat__('float')}
 | |
| 
 | |
|     def tearDown(self):
 | |
|         float.__setformat__('double', self.save_formats['double'])
 | |
|         float.__setformat__('float', self.save_formats['float'])
 | |
| 
 | |
|     def test_getformat(self):
 | |
|         self.assert_(float.__getformat__('double') in
 | |
|                      ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
 | |
|         self.assert_(float.__getformat__('float') in
 | |
|                      ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
 | |
|         self.assertRaises(ValueError, float.__getformat__, 'chicken')
 | |
|         self.assertRaises(TypeError, float.__getformat__, 1)
 | |
| 
 | |
|     def test_setformat(self):
 | |
|         for t in 'double', 'float':
 | |
|             float.__setformat__(t, 'unknown')
 | |
|             if self.save_formats[t] == 'IEEE, big-endian':
 | |
|                 self.assertRaises(ValueError, float.__setformat__,
 | |
|                                   t, 'IEEE, little-endian')
 | |
|             elif self.save_formats[t] == 'IEEE, little-endian':
 | |
|                 self.assertRaises(ValueError, float.__setformat__,
 | |
|                                   t, 'IEEE, big-endian')
 | |
|             else:
 | |
|                 self.assertRaises(ValueError, float.__setformat__,
 | |
|                                   t, 'IEEE, big-endian')
 | |
|                 self.assertRaises(ValueError, float.__setformat__,
 | |
|                                   t, 'IEEE, little-endian')
 | |
|             self.assertRaises(ValueError, float.__setformat__,
 | |
|                               t, 'chicken')
 | |
|         self.assertRaises(ValueError, float.__setformat__,
 | |
|                           'chicken', 'unknown')
 | |
| 
 | |
| BE_DOUBLE_INF = '\x7f\xf0\x00\x00\x00\x00\x00\x00'
 | |
| LE_DOUBLE_INF = ''.join(reversed(BE_DOUBLE_INF))
 | |
| BE_DOUBLE_NAN = '\x7f\xf8\x00\x00\x00\x00\x00\x00'
 | |
| LE_DOUBLE_NAN = ''.join(reversed(BE_DOUBLE_NAN))
 | |
| 
 | |
| BE_FLOAT_INF = '\x7f\x80\x00\x00'
 | |
| LE_FLOAT_INF = ''.join(reversed(BE_FLOAT_INF))
 | |
| BE_FLOAT_NAN = '\x7f\xc0\x00\x00'
 | |
| LE_FLOAT_NAN = ''.join(reversed(BE_FLOAT_NAN))
 | |
| 
 | |
| # on non-IEEE platforms, attempting to unpack a bit pattern
 | |
| # representing an infinity or a NaN should raise an exception.
 | |
| 
 | |
| class UnknownFormatTestCase(unittest.TestCase):
 | |
|     def setUp(self):
 | |
|         self.save_formats = {'double':float.__getformat__('double'),
 | |
|                              'float':float.__getformat__('float')}
 | |
|         float.__setformat__('double', 'unknown')
 | |
|         float.__setformat__('float', 'unknown')
 | |
| 
 | |
|     def tearDown(self):
 | |
|         float.__setformat__('double', self.save_formats['double'])
 | |
|         float.__setformat__('float', self.save_formats['float'])
 | |
| 
 | |
|     def test_double_specials_dont_unpack(self):
 | |
|         for fmt, data in [('>d', BE_DOUBLE_INF),
 | |
|                           ('>d', BE_DOUBLE_NAN),
 | |
|                           ('<d', LE_DOUBLE_INF),
 | |
|                           ('<d', LE_DOUBLE_NAN)]:
 | |
|             self.assertRaises(ValueError, struct.unpack, fmt, data)
 | |
| 
 | |
|     def test_float_specials_dont_unpack(self):
 | |
|         for fmt, data in [('>f', BE_FLOAT_INF),
 | |
|                           ('>f', BE_FLOAT_NAN),
 | |
|                           ('<f', LE_FLOAT_INF),
 | |
|                           ('<f', LE_FLOAT_NAN)]:
 | |
|             self.assertRaises(ValueError, struct.unpack, fmt, data)
 | |
| 
 | |
| 
 | |
| # on an IEEE platform, all we guarantee is that bit patterns
 | |
| # representing infinities or NaNs do not raise an exception; all else
 | |
| # is accident (today).
 | |
| # let's also try to guarantee that -0.0 and 0.0 don't get confused.
 | |
| 
 | |
| class IEEEFormatTestCase(unittest.TestCase):
 | |
|     if float.__getformat__("double").startswith("IEEE"):
 | |
|         def test_double_specials_do_unpack(self):
 | |
|             for fmt, data in [('>d', BE_DOUBLE_INF),
 | |
|                               ('>d', BE_DOUBLE_NAN),
 | |
|                               ('<d', LE_DOUBLE_INF),
 | |
|                               ('<d', LE_DOUBLE_NAN)]:
 | |
|                 struct.unpack(fmt, data)
 | |
| 
 | |
|     if float.__getformat__("float").startswith("IEEE"):
 | |
|         def test_float_specials_do_unpack(self):
 | |
|             for fmt, data in [('>f', BE_FLOAT_INF),
 | |
|                               ('>f', BE_FLOAT_NAN),
 | |
|                               ('<f', LE_FLOAT_INF),
 | |
|                               ('<f', LE_FLOAT_NAN)]:
 | |
|                 struct.unpack(fmt, data)
 | |
| 
 | |
|     if float.__getformat__("double").startswith("IEEE"):
 | |
|         def test_negative_zero(self):
 | |
|             import math
 | |
|             def pos_pos():
 | |
|                 return 0.0, math.atan2(0.0, -1)
 | |
|             def pos_neg():
 | |
|                 return 0.0, math.atan2(-0.0, -1)
 | |
|             def neg_pos():
 | |
|                 return -0.0, math.atan2(0.0, -1)
 | |
|             def neg_neg():
 | |
|                 return -0.0, math.atan2(-0.0, -1)
 | |
|             self.assertEquals(pos_pos(), neg_pos())
 | |
|             self.assertEquals(pos_neg(), neg_neg())
 | |
| 
 | |
| 
 | |
| class ReprTestCase(unittest.TestCase):
 | |
|     def test_repr(self):
 | |
|         floats_file = open(os.path.join(os.path.split(__file__)[0],
 | |
|                            'floating_points.txt'))
 | |
|         for line in floats_file:
 | |
|             line = line.strip()
 | |
|             if not line or line.startswith('#'):
 | |
|                 continue
 | |
|             v = eval(line)
 | |
|             self.assertEqual(v, eval(repr(v)))
 | |
|         floats_file.close()
 | |
| 
 | |
| # Beginning with Python 2.6 float has cross platform compatible
 | |
| # ways to create and representate inf and nan
 | |
| class InfNanTest(unittest.TestCase):
 | |
|     def test_inf_from_str(self):
 | |
|         self.assert_(isinf(float("inf")))
 | |
|         self.assert_(isinf(float("+inf")))
 | |
|         self.assert_(isinf(float("-inf")))
 | |
| 
 | |
|         self.assertEqual(repr(float("inf")), "inf")
 | |
|         self.assertEqual(repr(float("+inf")), "inf")
 | |
|         self.assertEqual(repr(float("-inf")), "-inf")
 | |
| 
 | |
|         self.assertEqual(repr(float("INF")), "inf")
 | |
|         self.assertEqual(repr(float("+Inf")), "inf")
 | |
|         self.assertEqual(repr(float("-iNF")), "-inf")
 | |
| 
 | |
|         self.assertEqual(str(float("inf")), "inf")
 | |
|         self.assertEqual(str(float("+inf")), "inf")
 | |
|         self.assertEqual(str(float("-inf")), "-inf")
 | |
| 
 | |
|         self.assertRaises(ValueError, float, "info")
 | |
|         self.assertRaises(ValueError, float, "+info")
 | |
|         self.assertRaises(ValueError, float, "-info")
 | |
|         self.assertRaises(ValueError, float, "in")
 | |
|         self.assertRaises(ValueError, float, "+in")
 | |
|         self.assertRaises(ValueError, float, "-in")
 | |
| 
 | |
|     def test_inf_as_str(self):
 | |
|         self.assertEqual(repr(1e300 * 1e300), "inf")
 | |
|         self.assertEqual(repr(-1e300 * 1e300), "-inf")
 | |
| 
 | |
|         self.assertEqual(str(1e300 * 1e300), "inf")
 | |
|         self.assertEqual(str(-1e300 * 1e300), "-inf")
 | |
| 
 | |
|     def test_nan_from_str(self):
 | |
|         self.assert_(isnan(float("nan")))
 | |
|         self.assert_(isnan(float("+nan")))
 | |
|         self.assert_(isnan(float("-nan")))
 | |
| 
 | |
|         self.assertEqual(repr(float("nan")), "nan")
 | |
|         self.assertEqual(repr(float("+nan")), "nan")
 | |
|         self.assertEqual(repr(float("-nan")), "nan")
 | |
| 
 | |
|         self.assertEqual(repr(float("NAN")), "nan")
 | |
|         self.assertEqual(repr(float("+NAn")), "nan")
 | |
|         self.assertEqual(repr(float("-NaN")), "nan")
 | |
| 
 | |
|         self.assertEqual(str(float("nan")), "nan")
 | |
|         self.assertEqual(str(float("+nan")), "nan")
 | |
|         self.assertEqual(str(float("-nan")), "nan")
 | |
| 
 | |
|         self.assertRaises(ValueError, float, "nana")
 | |
|         self.assertRaises(ValueError, float, "+nana")
 | |
|         self.assertRaises(ValueError, float, "-nana")
 | |
|         self.assertRaises(ValueError, float, "na")
 | |
|         self.assertRaises(ValueError, float, "+na")
 | |
|         self.assertRaises(ValueError, float, "-na")
 | |
| 
 | |
|     def test_nan_as_str(self):
 | |
|         self.assertEqual(repr(1e300 * 1e300 * 0), "nan")
 | |
|         self.assertEqual(repr(-1e300 * 1e300 * 0), "nan")
 | |
| 
 | |
|         self.assertEqual(str(1e300 * 1e300 * 0), "nan")
 | |
|         self.assertEqual(str(-1e300 * 1e300 * 0), "nan")
 | |
| 
 | |
| def test_main():
 | |
|     test_support.run_unittest(
 | |
|         FormatFunctionsTestCase,
 | |
|         UnknownFormatTestCase,
 | |
|         IEEEFormatTestCase,
 | |
|         ReprTestCase,
 | |
|         InfNanTest,
 | |
|         )
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     test_main()
 | 
