blob: 922de7aa04fab5ddfb65d9c685917aed5f004238 [file] [log] [blame]
Michael W. Hudsonba283e22005-05-27 15:23:20 +00001
2import unittest, struct
Christian Heimes827b35c2007-12-10 22:19:17 +00003import os
Michael W. Hudsonba283e22005-05-27 15:23:20 +00004from test import test_support
5
6class FormatFunctionsTestCase(unittest.TestCase):
7
8 def setUp(self):
9 self.save_formats = {'double':float.__getformat__('double'),
10 'float':float.__getformat__('float')}
11
12 def tearDown(self):
13 float.__setformat__('double', self.save_formats['double'])
14 float.__setformat__('float', self.save_formats['float'])
15
16 def test_getformat(self):
17 self.assert_(float.__getformat__('double') in
18 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
19 self.assert_(float.__getformat__('float') in
20 ['unknown', 'IEEE, big-endian', 'IEEE, little-endian'])
21 self.assertRaises(ValueError, float.__getformat__, 'chicken')
22 self.assertRaises(TypeError, float.__getformat__, 1)
23
24 def test_setformat(self):
25 for t in 'double', 'float':
26 float.__setformat__(t, 'unknown')
27 if self.save_formats[t] == 'IEEE, big-endian':
28 self.assertRaises(ValueError, float.__setformat__,
29 t, 'IEEE, little-endian')
30 elif self.save_formats[t] == 'IEEE, little-endian':
31 self.assertRaises(ValueError, float.__setformat__,
32 t, 'IEEE, big-endian')
33 else:
34 self.assertRaises(ValueError, float.__setformat__,
35 t, 'IEEE, big-endian')
36 self.assertRaises(ValueError, float.__setformat__,
37 t, 'IEEE, little-endian')
38 self.assertRaises(ValueError, float.__setformat__,
39 t, 'chicken')
40 self.assertRaises(ValueError, float.__setformat__,
41 'chicken', 'unknown')
42
Guido van Rossum2be161d2007-05-15 20:43:51 +000043BE_DOUBLE_INF = b'\x7f\xf0\x00\x00\x00\x00\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +000044LE_DOUBLE_INF = bytes(reversed(BE_DOUBLE_INF))
Guido van Rossum2be161d2007-05-15 20:43:51 +000045BE_DOUBLE_NAN = b'\x7f\xf8\x00\x00\x00\x00\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +000046LE_DOUBLE_NAN = bytes(reversed(BE_DOUBLE_NAN))
Michael W. Hudsonba283e22005-05-27 15:23:20 +000047
Guido van Rossum2be161d2007-05-15 20:43:51 +000048BE_FLOAT_INF = b'\x7f\x80\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +000049LE_FLOAT_INF = bytes(reversed(BE_FLOAT_INF))
Guido van Rossum2be161d2007-05-15 20:43:51 +000050BE_FLOAT_NAN = b'\x7f\xc0\x00\x00'
Guido van Rossum254348e2007-11-21 19:29:53 +000051LE_FLOAT_NAN = bytes(reversed(BE_FLOAT_NAN))
Michael W. Hudsonba283e22005-05-27 15:23:20 +000052
53# on non-IEEE platforms, attempting to unpack a bit pattern
54# representing an infinity or a NaN should raise an exception.
55
56class UnknownFormatTestCase(unittest.TestCase):
57 def setUp(self):
58 self.save_formats = {'double':float.__getformat__('double'),
59 'float':float.__getformat__('float')}
60 float.__setformat__('double', 'unknown')
61 float.__setformat__('float', 'unknown')
Tim Peters5d36a552005-06-03 22:40:27 +000062
Michael W. Hudsonba283e22005-05-27 15:23:20 +000063 def tearDown(self):
64 float.__setformat__('double', self.save_formats['double'])
65 float.__setformat__('float', self.save_formats['float'])
66
67 def test_double_specials_dont_unpack(self):
68 for fmt, data in [('>d', BE_DOUBLE_INF),
69 ('>d', BE_DOUBLE_NAN),
70 ('<d', LE_DOUBLE_INF),
71 ('<d', LE_DOUBLE_NAN)]:
72 self.assertRaises(ValueError, struct.unpack, fmt, data)
73
74 def test_float_specials_dont_unpack(self):
75 for fmt, data in [('>f', BE_FLOAT_INF),
76 ('>f', BE_FLOAT_NAN),
77 ('<f', LE_FLOAT_INF),
78 ('<f', LE_FLOAT_NAN)]:
79 self.assertRaises(ValueError, struct.unpack, fmt, data)
80
81
82# on an IEEE platform, all we guarantee is that bit patterns
83# representing infinities or NaNs do not raise an exception; all else
84# is accident (today).
Guido van Rossum04110fb2007-08-24 16:32:05 +000085# let's also try to guarantee that -0.0 and 0.0 don't get confused.
Michael W. Hudsonba283e22005-05-27 15:23:20 +000086
87class IEEEFormatTestCase(unittest.TestCase):
88 if float.__getformat__("double").startswith("IEEE"):
89 def test_double_specials_do_unpack(self):
90 for fmt, data in [('>d', BE_DOUBLE_INF),
91 ('>d', BE_DOUBLE_NAN),
92 ('<d', LE_DOUBLE_INF),
93 ('<d', LE_DOUBLE_NAN)]:
94 struct.unpack(fmt, data)
95
96 if float.__getformat__("float").startswith("IEEE"):
97 def test_float_specials_do_unpack(self):
98 for fmt, data in [('>f', BE_FLOAT_INF),
99 ('>f', BE_FLOAT_NAN),
100 ('<f', LE_FLOAT_INF),
101 ('<f', LE_FLOAT_NAN)]:
102 struct.unpack(fmt, data)
103
Guido van Rossum04110fb2007-08-24 16:32:05 +0000104 if float.__getformat__("double").startswith("IEEE"):
105 def test_negative_zero(self):
106 import math
107 def pos_pos():
108 return 0.0, math.atan2(0.0, -1)
109 def pos_neg():
110 return 0.0, math.atan2(-0.0, -1)
111 def neg_pos():
112 return -0.0, math.atan2(0.0, -1)
113 def neg_neg():
114 return -0.0, math.atan2(-0.0, -1)
115 self.assertEquals(pos_pos(), neg_pos())
116 self.assertEquals(pos_neg(), neg_neg())
117
Eric Smith8c663262007-08-25 02:26:07 +0000118class FormatTestCase(unittest.TestCase):
Eric Smith11fe3e02007-08-31 01:33:06 +0000119 def test_format(self):
Eric Smith8c663262007-08-25 02:26:07 +0000120 # these should be rewritten to use both format(x, spec) and
121 # x.__format__(spec)
122
123 self.assertEqual(format(0.0, 'f'), '0.000000')
124
125 # the default is 'g', except for empty format spec
126 self.assertEqual(format(0.0, ''), '0.0')
127 self.assertEqual(format(0.01, ''), '0.01')
128 self.assertEqual(format(0.01, 'g'), '0.01')
129
130 self.assertEqual(format(0, 'f'), '0.000000')
131
132 self.assertEqual(format(1.0, 'f'), '1.000000')
133 self.assertEqual(format(1, 'f'), '1.000000')
134
135 self.assertEqual(format(-1.0, 'f'), '-1.000000')
136 self.assertEqual(format(-1, 'f'), '-1.000000')
137
138 self.assertEqual(format( 1.0, ' f'), ' 1.000000')
139 self.assertEqual(format(-1.0, ' f'), '-1.000000')
140 self.assertEqual(format( 1.0, '+f'), '+1.000000')
141 self.assertEqual(format(-1.0, '+f'), '-1.000000')
142
143 # % formatting
144 self.assertEqual(format(-1.0, '%'), '-100.000000%')
145
146 # conversion to string should fail
147 self.assertRaises(ValueError, format, 3.0, "s")
148
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000149
Christian Heimes827b35c2007-12-10 22:19:17 +0000150class ReprTestCase(unittest.TestCase):
151 def test_repr(self):
152 floats_file = open(os.path.join(os.path.split(__file__)[0],
153 'floating_points.txt'))
154 for line in floats_file:
155 line = line.strip()
156 if not line or line.startswith('#'):
157 continue
158 v = eval(line)
159 self.assertEqual(v, eval(repr(v)))
160 floats_file.close()
161
162
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000163def test_main():
164 test_support.run_unittest(
165 FormatFunctionsTestCase,
166 UnknownFormatTestCase,
Eric Smith8c663262007-08-25 02:26:07 +0000167 IEEEFormatTestCase,
Christian Heimes827b35c2007-12-10 22:19:17 +0000168 FormatTestCase,
Christian Heimesb76922a2007-12-11 01:06:40 +0000169 #ReprTestCase
170 )
Michael W. Hudsonba283e22005-05-27 15:23:20 +0000171
172if __name__ == '__main__':
173 test_main()