diff --git a/src/core/IronPython.Modules/_ctypes/SimpleType.cs b/src/core/IronPython.Modules/_ctypes/SimpleType.cs index 14475cc33..6e21fb36e 100644 --- a/src/core/IronPython.Modules/_ctypes/SimpleType.cs +++ b/src/core/IronPython.Modules/_ctypes/SimpleType.cs @@ -58,8 +58,14 @@ public SimpleType(CodeContext/*!*/ context, string name, PythonTuple bases, Pyth case 'H': _type = SimpleTypeKind.UnsignedShort; break; case 'i': _type = SimpleTypeKind.SignedInt; break; case 'I': _type = SimpleTypeKind.UnsignedInt; break; - case 'l': _type = SimpleTypeKind.SignedLong; break; - case 'L': _type = SimpleTypeKind.UnsignedLong; break; + case 'l': + _type = SimpleTypeKind.SignedLong; + _charType = TypecodeOps.IsCLong32Bit ? _charType : 'q'; + break; + case 'L': + _type = SimpleTypeKind.UnsignedLong; + _charType = TypecodeOps.IsCLong32Bit ? _charType : 'Q'; + break; case 'f': _type = SimpleTypeKind.Single; break; case 'g': // long double, new in 2.6 case 'd': _type = SimpleTypeKind.Double; break; diff --git a/src/core/IronPython.Modules/_datetime.cs b/src/core/IronPython.Modules/_datetime.cs index 92387083d..5e461e0f2 100644 --- a/src/core/IronPython.Modules/_datetime.cs +++ b/src/core/IronPython.Modules/_datetime.cs @@ -54,13 +54,15 @@ internal timedelta(TimeSpan ts, double microsecond) } public timedelta(double days, double seconds, double microseconds, double milliseconds, double minutes, double hours, double weeks) { - double totalDays = weeks * 7 + days; - double totalSeconds = ((totalDays * 24 + hours) * 60 + minutes) * 60 + seconds; + double totalSeconds = (((weeks * 7 + days) * 24 + hours) * 60 + minutes) * 60 + seconds; + CheckDouble(totalSeconds); double totalSecondsSharp = Math.Floor(totalSeconds); double totalSecondsFloat = totalSeconds - totalSecondsSharp; double totalMicroseconds = Math.Round(totalSecondsFloat * 1e6 + milliseconds * 1000 + microseconds); + CheckDouble(totalMicroseconds); + double otherSecondsFromMicroseconds = Math.Floor(totalMicroseconds / 1e6); totalSecondsSharp += otherSecondsFromMicroseconds; @@ -71,28 +73,45 @@ public timedelta(double days, double seconds, double microseconds, double millis totalMicroseconds += 1e6; } - _days = (int)(totalSecondsSharp / SECONDSPERDAY); - _seconds = (int)(totalSecondsSharp - _days * SECONDSPERDAY); + _days = ToInt(totalSecondsSharp / SECONDSPERDAY); + _seconds = ToInt(totalSecondsSharp - _days * SECONDSPERDAY); if (_seconds < 0) { _days--; _seconds += (int)SECONDSPERDAY; } - _microseconds = (int)(totalMicroseconds); + _microseconds = ToInt(totalMicroseconds); if (Math.Abs(_days) > MAXDAYS) { throw PythonOps.OverflowError("days={0}; must have magnitude <= 999999999", _days); } + + static void CheckDouble(double d) { + if (double.IsInfinity(d)) { + throw PythonOps.OverflowError("cannot convert float infinity to integer"); + } else if (double.IsNaN(d)) { + throw PythonOps.ValueError("cannot convert float NaN to integer"); + } + } + + static int ToInt(double d) { + if (Int32.MinValue <= d && d <= Int32.MaxValue) { + return (int)d; + } else { + CheckDouble(d); + return checked((int)d); + } + } } public static timedelta __new__(CodeContext context, [NotNone] PythonType cls, - double days = 0D, - double seconds = 0D, - double microseconds = 0D, - double milliseconds = 0D, - double minutes = 0D, - double hours = 0D, - double weeks = 0D) { + double days = 0, + double seconds = 0, + double microseconds = 0, + double milliseconds = 0, + double minutes = 0, + double hours = 0, + double weeks = 0) { if (cls == DynamicHelpers.GetPythonTypeFromType(typeof(timedelta))) { return new timedelta(days, seconds, microseconds, milliseconds, minutes, hours, weeks); } else { diff --git a/src/core/IronPython.Modules/mmap.cs b/src/core/IronPython.Modules/mmap.cs index 94c31e3a5..a02f82ba2 100644 --- a/src/core/IronPython.Modules/mmap.cs +++ b/src/core/IronPython.Modules/mmap.cs @@ -338,6 +338,10 @@ public MmapDefault(CodeContext/*!*/ context, int fileno, long length, string? ta _offset = 0; // offset is ignored without an underlying file _sourceStream = null; + if (length == 0) { + throw PythonNT.GetOsError(PythonErrno.EINVAL); + } + // work around the .NET bug whereby CreateOrOpen throws on a null mapName if (_mapName is null) { _file = MemoryMappedFile.CreateNew(null, length, _fileAccess); @@ -859,7 +863,7 @@ public Bytes read(int len) { len = checked((int)(_view.Capacity - pos)); } - if (len == 0) { + if (len <= 0) { return Bytes.Empty; } @@ -960,11 +964,6 @@ public void resize(long newsize) { } } - if (_sourceStream == null) { - // resizing is not supported without an underlying file - throw WindowsError(PythonExceptions._OSError.ERROR_INVALID_PARAMETER); - } - if (_view.Capacity == newsize) { // resizing to the same size return; @@ -979,6 +978,33 @@ public void resize(long newsize) { ); } + if (_sourceStream is null) { + // resizing of anonymous map + // TODO: non-copying implementation? + + MemoryMappedFile file; + // work around the .NET bug whereby CreateOrOpen throws on a null mapName + if (_mapName is null) { + file = MemoryMappedFile.CreateNew(null, newsize, _fileAccess); + } else { + Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); + file = MemoryMappedFile.CreateOrOpen(_mapName, newsize, _fileAccess); + } + + using (var oldStream = _file.CreateViewStream(0, Math.Min(_view.Capacity, newsize))) { + using var newStream = file.CreateViewStream(); + oldStream.CopyTo(newStream); + } + + _view.Flush(); + _view.Dispose(); + _file.Dispose(); + + _file = file; + _view = _file.CreateViewAccessor(_offset, newsize, _fileAccess); + return; + } + _view.Flush(); _view.Dispose(); _file.Dispose(); diff --git a/src/core/IronPython.Modules/nt.cs b/src/core/IronPython.Modules/nt.cs index ea48bc5e1..7d6d9c20b 100644 --- a/src/core/IronPython.Modules/nt.cs +++ b/src/core/IronPython.Modules/nt.cs @@ -849,6 +849,8 @@ public static object open(CodeContext/*!*/ context, [NotNone] string path, int f } } + VerifyPath(path, functionName: nameof(open), argName: nameof(path)); + if ((RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) && !ClrModule.IsMono) { // Use PosixFileStream to operate on fd directly // On Mono, we must use FileStream due to limitations in MemoryMappedFile diff --git a/src/core/IronPython.StdLib/lib/test/support/__init__.py b/src/core/IronPython.StdLib/lib/test/support/__init__.py index 6a5a2a9f3..01657b5a1 100644 --- a/src/core/IronPython.StdLib/lib/test/support/__init__.py +++ b/src/core/IronPython.StdLib/lib/test/support/__init__.py @@ -2764,14 +2764,24 @@ def disable_faulthandler(): def fd_count(): """Count the number of open file descriptors. """ - if sys.platform.startswith(('linux', 'freebsd')): + # ironpython: backported from Python 3.12 + if sys.platform.startswith(('linux', 'freebsd', 'emscripten')): + fd_path = "/proc/self/fd" + elif sys.platform == "darwin": + fd_path = "/dev/fd" + else: + fd_path = None + + if fd_path is not None: try: - names = os.listdir("/proc/self/fd") - # Substract one because listdir() opens internally a file - # descriptor to list the content of the /proc/self/fd/ directory. + names = os.listdir(fd_path) + # Subtract one because listdir() internally opens a file + # descriptor to list the content of the directory. return len(names) - 1 except FileNotFoundError: pass + except PermissionError: # ironpython: bug in .NET 6 on macOS + pass MAXFD = 256 if hasattr(os, 'sysconf'): diff --git a/tests/IronPython.Tests/Cases/CPythonCasesManifest.ini b/tests/IronPython.Tests/Cases/CPythonCasesManifest.ini index a05843296..d84c327fc 100644 --- a/tests/IronPython.Tests/Cases/CPythonCasesManifest.ini +++ b/tests/IronPython.Tests/Cases/CPythonCasesManifest.ini @@ -7,9 +7,6 @@ Timeout=120000 # 2 minute timeout [CPython.ctypes.test_as_parameter] Ignore=true -[CPython.ctypes.test_bitfields] # IronPython.modules.type_related.test_bitfields_ctypes_stdlib -Ignore=true - [CPython.ctypes.test_cast] RunCondition=NOT $(IS_POSIX) # https://github.com/IronLanguages/ironpython3/issues/1455 @@ -186,6 +183,9 @@ Ignore=true Ignore=true Reason=ImportError: No module named audioop +[CPython.test_base64] +IsolationLevel=PROCESS # https://github.com/IronLanguages/ironpython3/issues/1440 + [CPython.test_bdb] # new in 3.6 Ignore=true diff --git a/tests/IronPython.Tests/Cases/IronPythonCasesManifest.ini b/tests/IronPython.Tests/Cases/IronPythonCasesManifest.ini index 64e16b3d8..1bb409f49 100644 --- a/tests/IronPython.Tests/Cases/IronPythonCasesManifest.ini +++ b/tests/IronPython.Tests/Cases/IronPythonCasesManifest.ini @@ -146,6 +146,7 @@ Reason=StackOverflowException - https://github.com/IronLanguages/ironpython2/iss [IronPython.test_threading_stdlib] IsolationLevel=PROCESS +RunCondition=NOT $(IS_MONO) # TODO: figure out [IronPython.test_threadsafety] Ignore=true diff --git a/tests/suite/modules/type_related/test_bitfields_ctypes_stdlib.py b/tests/suite/modules/type_related/test_bitfields_ctypes_stdlib.py deleted file mode 100644 index 0f9b89da4..000000000 --- a/tests/suite/modules/type_related/test_bitfields_ctypes_stdlib.py +++ /dev/null @@ -1,30 +0,0 @@ -# Licensed to the .NET Foundation under one or more agreements. -# The .NET Foundation licenses this file to you under the Apache 2.0 License. -# See the LICENSE file in the project root for more information. - -## -## Run selected tests from test_bitfields from StdLib -## - -from iptest import is_ironpython, generate_suite, run_test, is_windows - -import ctypes.test.test_bitfields - -def load_tests(loader, standard_tests, pattern): - tests = loader.loadTestsFromModule(ctypes.test.test_bitfields, pattern=pattern) - - if is_ironpython: - failing_tests = [] - if not is_windows: # https://github.com/IronLanguages/ironpython3/issues/1442 - failing_tests += [ - ctypes.test.test_bitfields.BitFieldTest('test_mixed_1'), - ctypes.test.test_bitfields.BitFieldTest('test_mixed_4'), - ctypes.test.test_bitfields.C_Test('test_shorts'), - ] - - return generate_suite(tests, failing_tests) - - else: - return tests - -run_test(__name__) diff --git a/tests/suite/test_array_stdlib.py b/tests/suite/test_array_stdlib.py index 8ea4a05b4..a2ffc0577 100644 --- a/tests/suite/test_array_stdlib.py +++ b/tests/suite/test_array_stdlib.py @@ -6,7 +6,7 @@ ## Run selected tests from test_array from StdLib ## -from iptest import is_ironpython, generate_suite, run_test +from iptest import is_ironpython, generate_suite, run_test, is_windows import test.test_array @@ -61,6 +61,11 @@ def load_tests(loader, standard_tests, pattern): test.test_array.UnsignedShortTest('test_type_error'), # https://github.com/IronLanguages/ironpython3/issues/767 ] + if not is_windows: + failing_tests += [ + test.test_array.LongTest('test_overflow'), # OverflowError: couldn't convert Intable to Int64 + ] + return generate_suite(tests, failing_tests) else: diff --git a/tests/suite/test_file.py b/tests/suite/test_file.py index f79c9fa98..1a21a3e09 100644 --- a/tests/suite/test_file.py +++ b/tests/suite/test_file.py @@ -688,7 +688,7 @@ def test_errors(self): with self.assertRaises(OSError) as cm: open('path_too_long' * 100) - self.assertEqual(cm.exception.errno, (errno.ENAMETOOLONG if is_posix else errno.EINVAL) if is_netcoreapp or sys.version_info >= (3,6) else errno.ENOENT) + self.assertEqual(cm.exception.errno, (errno.ENAMETOOLONG if is_posix else errno.EINVAL) if is_netcoreapp or is_cpython and sys.version_info >= (3,6) else errno.ENOENT) def test_write_bytes(self): fname = self.temp_file diff --git a/tests/suite/test_functools_stdlib.py b/tests/suite/test_functools_stdlib.py index a5843af39..db79bd2d0 100644 --- a/tests/suite/test_functools_stdlib.py +++ b/tests/suite/test_functools_stdlib.py @@ -58,6 +58,7 @@ def load_tests(loader, standard_tests, pattern): skip_tests += [ test.test_functools.TestPartialCSubclass('test_weakref'), test.test_functools.TestPartialPy('test_weakref'), + test.test_functools.TestPartialPySubclass('test_weakref'), ] return generate_suite(tests, failing_tests, skip_tests) diff --git a/tests/suite/test_io_stdlib.py b/tests/suite/test_io_stdlib.py index fc6c079d2..cbab4c2b2 100644 --- a/tests/suite/test_io_stdlib.py +++ b/tests/suite/test_io_stdlib.py @@ -118,11 +118,6 @@ def load_tests(loader, standard_tests, pattern): test.test_io.PyTextIOWrapperTest('test_read_byteslike'), ] - if is_mono: - failing_tests += [ - test.test_io.PyMiscIOTest('test_create_fail'), - ] - if is_mono or is_windows: failing_tests += [ test.test_io.PyTextIOWrapperTest('test_seek_append_bom'), # OSError: [Errno -2146232800] Unable seek backward to overwrite data that previously existed in a file opened in Append mode. diff --git a/tests/suite/test_structures_ctypes_stdlib.py b/tests/suite/test_structures_ctypes_stdlib.py index 8eb4dc2de..fd08ed8af 100644 --- a/tests/suite/test_structures_ctypes_stdlib.py +++ b/tests/suite/test_structures_ctypes_stdlib.py @@ -18,10 +18,6 @@ def load_tests(loader, standard_tests, pattern): ctypes.test.test_structures.StructureTestCase('test_conflicting_initializers'), # AssertionError ctypes.test.test_structures.StructureTestCase('test_pass_by_value_in_register'), # NotImplementedError: in dll ] - if is_osx: - failing_tests += [ - ctypes.test.test_structures.StructureTestCase('test_pass_by_value'), - ] return generate_suite(tests, failing_tests) diff --git a/tests/suite/test_threading_stdlib.py b/tests/suite/test_threading_stdlib.py index 459c219d1..87160c1f6 100644 --- a/tests/suite/test_threading_stdlib.py +++ b/tests/suite/test_threading_stdlib.py @@ -14,7 +14,16 @@ def load_tests(loader, standard_tests, pattern): tests = loader.loadTestsFromModule(test.test_threading) if is_ironpython: - failing_tests = [] + failing_tests = [ + test.test_threading.CRLockTests('test_weakref_deleted'), # TypeError: cannot create weak reference to 'RLock' object + test.test_threading.CRLockTests('test_weakref_exists'), # TypeError: cannot create weak reference to 'RLock' object + test.test_threading.LockTests('test_weakref_deleted'), # TypeError: cannot create weak reference to 'lock' object + test.test_threading.LockTests('test_weakref_exists'), # TypeError: cannot create weak reference to 'lock' object + test.test_threading.ConditionAsRLockTests('test_weakref_deleted'), # AssertionError + test.test_threading.PyRLockTests('test_weakref_deleted'), # AssertionError + test.test_threading.ThreadTests('test_main_thread_during_shutdown'), # AssertionError + test.test_threading.ThreadingExceptionTests('test_bare_raise_in_brand_new_thread'), # AssertionError: TypeError('exceptions must derive from BaseException',) is not an instance of + ] skip_tests = [ test.test_threading.SubinterpThreadingTests('test_threads_join'), # ImportError: No module named '_testcapi'