diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index 30d27072fb..f65eb55ca5 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -25,7 +25,7 @@ #locate file with float format test values test_dir = os.path.dirname(__file__) or os.curdir -format_testfile = os.path.join(test_dir, 'formatfloat_testcases.txt') +format_testfile = os.path.join(test_dir, 'mathdata', 'formatfloat_testcases.txt') class FloatSubclass(float): pass @@ -131,7 +131,7 @@ def check(s): with self.assertRaises(ValueError, msg='float(%r)' % (s,)) as cm: float(s) self.assertEqual(str(cm.exception), - 'could not convert string to float: %r' % (s,)) + 'could not convert string to float: %r' % (s,)) check('\xbd') check('123\xbd') @@ -290,11 +290,11 @@ def test_is_integer(self): def test_floatasratio(self): for f, ratio in [ - (0.875, (7, 8)), - (-0.875, (-7, 8)), - (0.0, (0, 1)), - (11.5, (23, 2)), - ]: + (0.875, (7, 8)), + (-0.875, (-7, 8)), + (0.0, (0, 1)), + (11.5, (23, 2)), + ]: self.assertEqual(f.as_integer_ratio(), ratio) for i in range(10000): @@ -337,7 +337,7 @@ def test_float_containment(self): self.assertTrue((f,) == (f,), "(%r,) != (%r,)" % (f, f)) self.assertTrue({f} == {f}, "{%r} != {%r}" % (f, f)) self.assertTrue({f : None} == {f: None}, "{%r : None} != " - "{%r : None}" % (f, f)) + "{%r : None}" % (f, f)) # identical containers l, t, s, d = [f], (f,), {f}, {f: None} @@ -400,9 +400,9 @@ def test_float_mod(self): self.assertEqualAndEqualSign(mod(1e-100, -1.0), -1.0) self.assertEqualAndEqualSign(mod(1.0, -1.0), -0.0) + @support.requires_IEEE_754 # TODO: RUSTPYTHON @unittest.expectedFailure - @support.requires_IEEE_754 def test_float_pow(self): # test builtin pow and ** operator for IEEE 754 special cases. # Special cases taken from section F.9.4.4 of the C99 specification @@ -728,6 +728,8 @@ def test_format(self): self.assertEqual(format(INF, 'F'), 'INF') @support.requires_IEEE_754 + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_format_testfile(self): with open(format_testfile, encoding="utf-8") as testfile: for line in testfile: @@ -772,9 +774,12 @@ def test_issue35560(self): self.assertEqual(format(-123.34, '00.10g'), '-123.34') class ReprTestCase(unittest.TestCase): + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_repr(self): with open(os.path.join(os.path.split(__file__)[0], - 'floating_points.txt'), encoding="utf-8") as floats_file: + 'mathdata', + 'floating_points.txt'), encoding="utf-8") as floats_file: for line in floats_file: line = line.strip() if not line or line.startswith('#'): @@ -824,7 +829,7 @@ def test_short_repr(self): '2.86438000439698e+28', '8.89142905246179e+28', '3.08578087079232e+35', - ] + ] for s in test_strings: negs = '-'+s @@ -874,14 +879,14 @@ def test_overflow(self): self.assertRaises(OverflowError, round, 1.6e308, -308) self.assertRaises(OverflowError, round, -1.7e308, -308) - # TODO: RUSTPYTHON - @unittest.expectedFailure @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short', "applies only when using short float repr style") + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_previous_round_bugs(self): # particular cases that have occurred in bug reports self.assertEqual(round(562949953421312.5, 1), - 562949953421312.5) + 562949953421312.5) self.assertEqual(round(56294995342131.5, 3), 56294995342131.5) # round-half-even @@ -894,10 +899,10 @@ def test_previous_round_bugs(self): self.assertEqual(round(85.0, -1), 80.0) self.assertEqual(round(95.0, -1), 100.0) - # TODO: RUSTPYTHON - @unittest.expectedFailure @unittest.skipUnless(getattr(sys, 'float_repr_style', '') == 'short', "applies only when using short float repr style") + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_matches_float_format(self): # round should give the same results as float formatting for i in range(500): @@ -1131,7 +1136,7 @@ def test_invalid_inputs(self): '0x1.\uff10p0', '0x1p0 \n 0x2p0', '0x1p0\0 0x1p0', # embedded null byte is not end of string - ] + ] for x in invalid_inputs: try: result = fromHex(x) @@ -1150,7 +1155,7 @@ def test_whitespace(self): ('1.0', 1.0), ('-0x.2', -0.125), ('-0.0', -0.0) - ] + ] whitespace = [ '', ' ', @@ -1160,7 +1165,7 @@ def test_whitespace(self): '\f', '\v', '\r' - ] + ] for inp, expected in value_pairs: for lead in whitespace: for trail in whitespace: @@ -1510,4 +1515,4 @@ def __init__(self, value): if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file diff --git a/Lib/test/test_winapi.py b/Lib/test/test_winapi.py new file mode 100644 index 0000000000..7a33f90698 --- /dev/null +++ b/Lib/test/test_winapi.py @@ -0,0 +1,179 @@ +# Test the Windows-only _winapi module + +import os +import pathlib +import random +import re +import threading +import time +import unittest +from test.support import import_helper, os_helper + +_winapi = import_helper.import_module('_winapi', required_on=['win']) + +MAXIMUM_WAIT_OBJECTS = 64 +MAXIMUM_BATCHED_WAIT_OBJECTS = (MAXIMUM_WAIT_OBJECTS - 1) ** 2 + +class WinAPIBatchedWaitForMultipleObjectsTests(unittest.TestCase): + def _events_waitall_test(self, n): + evts = [_winapi.CreateEventW(0, False, False, None) for _ in range(n)] + + with self.assertRaises(TimeoutError): + _winapi.BatchedWaitForMultipleObjects(evts, True, 100) + + # Ensure no errors raised when all are triggered + for e in evts: + _winapi.SetEvent(e) + try: + _winapi.BatchedWaitForMultipleObjects(evts, True, 100) + except TimeoutError: + self.fail("expected wait to complete immediately") + + # Choose 8 events to set, distributed throughout the list, to make sure + # we don't always have them in the first chunk + chosen = [i * (len(evts) // 8) for i in range(8)] + + # Replace events with invalid handles to make sure we fail + for i in chosen: + old_evt = evts[i] + evts[i] = -1 + with self.assertRaises(OSError): + _winapi.BatchedWaitForMultipleObjects(evts, True, 100) + evts[i] = old_evt + + + def _events_waitany_test(self, n): + evts = [_winapi.CreateEventW(0, False, False, None) for _ in range(n)] + + with self.assertRaises(TimeoutError): + _winapi.BatchedWaitForMultipleObjects(evts, False, 100) + + # Choose 8 events to set, distributed throughout the list, to make sure + # we don't always have them in the first chunk + chosen = [i * (len(evts) // 8) for i in range(8)] + + # Trigger one by one. They are auto-reset events, so will only trigger once + for i in chosen: + with self.subTest(f"trigger event {i} of {len(evts)}"): + _winapi.SetEvent(evts[i]) + triggered = _winapi.BatchedWaitForMultipleObjects(evts, False, 10000) + self.assertSetEqual(set(triggered), {i}) + + # Trigger all at once. This may require multiple calls + for i in chosen: + _winapi.SetEvent(evts[i]) + triggered = set() + while len(triggered) < len(chosen): + triggered.update(_winapi.BatchedWaitForMultipleObjects(evts, False, 10000)) + self.assertSetEqual(triggered, set(chosen)) + + # Replace events with invalid handles to make sure we fail + for i in chosen: + with self.subTest(f"corrupt event {i} of {len(evts)}"): + old_evt = evts[i] + evts[i] = -1 + with self.assertRaises(OSError): + _winapi.BatchedWaitForMultipleObjects(evts, False, 100) + evts[i] = old_evt + + + # TODO: RUSTPYTHON + @unittest.expectedFailure + def test_few_events_waitall(self): + self._events_waitall_test(16) + + # TODO: RUSTPYTHON + @unittest.expectedFailure + def test_many_events_waitall(self): + self._events_waitall_test(256) + + # TODO: RUSTPYTHON + @unittest.expectedFailure + def test_max_events_waitall(self): + self._events_waitall_test(MAXIMUM_BATCHED_WAIT_OBJECTS) + + + # TODO: RUSTPYTHON + @unittest.expectedFailure + def test_few_events_waitany(self): + self._events_waitany_test(16) + + # TODO: RUSTPYTHON + @unittest.expectedFailure + def test_many_events_waitany(self): + self._events_waitany_test(256) + + # TODO: RUSTPYTHON + @unittest.expectedFailure + def test_max_events_waitany(self): + self._events_waitany_test(MAXIMUM_BATCHED_WAIT_OBJECTS) + + +class WinAPITests(unittest.TestCase): + # TODO: RUSTPYTHON + @unittest.expectedFailure + def test_getlongpathname(self): + testfn = pathlib.Path(os.getenv("ProgramFiles")).parents[-1] / "PROGRA~1" + if not os.path.isdir(testfn): + raise unittest.SkipTest("require x:\\PROGRA~1 to test") + + # pathlib.Path will be rejected - only str is accepted + with self.assertRaises(TypeError): + _winapi.GetLongPathName(testfn) + + actual = _winapi.GetLongPathName(os.fsdecode(testfn)) + + # Can't assume that PROGRA~1 expands to any particular variation, so + # ensure it matches any one of them. + candidates = set(testfn.parent.glob("Progra*")) + self.assertIn(pathlib.Path(actual), candidates) + + # TODO: RUSTPYTHON + @unittest.expectedFailure + def test_getshortpathname(self): + testfn = pathlib.Path(os.getenv("ProgramFiles")) + if not os.path.isdir(testfn): + raise unittest.SkipTest("require '%ProgramFiles%' to test") + + # pathlib.Path will be rejected - only str is accepted + with self.assertRaises(TypeError): + _winapi.GetShortPathName(testfn) + + actual = _winapi.GetShortPathName(os.fsdecode(testfn)) + + # Should contain "PROGRA~" but we can't predict the number + self.assertIsNotNone(re.match(r".\:\\PROGRA~\d", actual.upper()), actual) + + # TODO: RUSTPYTHON + @unittest.expectedFailure + def test_namedpipe(self): + pipe_name = rf"\\.\pipe\LOCAL\{os_helper.TESTFN}" + + # Pipe does not exist, so this raises + with self.assertRaises(FileNotFoundError): + _winapi.WaitNamedPipe(pipe_name, 0) + + pipe = _winapi.CreateNamedPipe( + pipe_name, + _winapi.PIPE_ACCESS_DUPLEX, + 8, # 8=PIPE_REJECT_REMOTE_CLIENTS + 2, # two instances available + 32, 32, 0, 0) + self.addCleanup(_winapi.CloseHandle, pipe) + + # Pipe instance is available, so this passes + _winapi.WaitNamedPipe(pipe_name, 0) + + with open(pipe_name, 'w+b') as pipe2: + # No instances available, so this times out + # (WinError 121 does not get mapped to TimeoutError) + with self.assertRaises(OSError): + _winapi.WaitNamedPipe(pipe_name, 0) + + _winapi.WriteFile(pipe, b'testdata') + self.assertEqual(b'testdata', pipe2.read(8)) + + self.assertEqual((b'', 0), _winapi.PeekNamedPipe(pipe, 8)[:2]) + pipe2.write(b'testdata') + pipe2.flush() + self.assertEqual((b'testdata', 8), _winapi.PeekNamedPipe(pipe, 8)[:2]) \ No newline at end of file