|
1 | | -from test.support import TESTFN, run_unittest, import_module, unlink, requires |
| 1 | +from test.support import (TESTFN, run_unittest, import_module, unlink, |
| 2 | + requires, _2G, _4G) |
2 | 3 | import unittest |
3 | 4 | import os |
4 | 5 | import re |
@@ -662,45 +663,49 @@ def setUp(self): |
662 | 663 | def tearDown(self): |
663 | 664 | unlink(TESTFN) |
664 | 665 |
|
665 | | - def _working_largefile(self): |
666 | | - # Only run if the current filesystem supports large files. |
667 | | - f = open(TESTFN, 'wb', buffering=0) |
668 | | - try: |
669 | | - f.seek(0x80000001) |
670 | | - f.write(b'x') |
671 | | - f.flush() |
672 | | - except (IOError, OverflowError): |
673 | | - raise unittest.SkipTest("filesystem does not have largefile support") |
674 | | - finally: |
675 | | - f.close() |
676 | | - unlink(TESTFN) |
677 | | - |
678 | | - def test_large_offset(self): |
| 666 | + def _create_test_file(self, num_zeroes, tail): |
679 | 667 | if sys.platform[:3] == 'win' or sys.platform == 'darwin': |
680 | 668 | requires('largefile', |
681 | 669 | 'test requires %s bytes and a long time to run' % str(0x180000000)) |
682 | | - self._working_largefile() |
683 | 670 | with open(TESTFN, 'wb') as f: |
684 | | - f.seek(0x14FFFFFFF) |
685 | | - f.write(b" ") |
| 671 | + try: |
| 672 | + f.seek(num_zeroes) |
| 673 | + f.write(tail) |
| 674 | + f.flush() |
| 675 | + except (IOError, OverflowError): |
| 676 | + raise unittest.SkipTest("filesystem does not have largefile support") |
686 | 677 |
|
| 678 | + def test_large_offset(self): |
| 679 | + self._create_test_file(0x14FFFFFFF, b" ") |
687 | 680 | with open(TESTFN, 'rb') as f: |
688 | 681 | with mmap.mmap(f.fileno(), 0, offset=0x140000000, access=mmap.ACCESS_READ) as m: |
689 | 682 | self.assertEqual(m[0xFFFFFFF], 32) |
690 | 683 |
|
691 | 684 | def test_large_filesize(self): |
692 | | - if sys.platform[:3] == 'win' or sys.platform == 'darwin': |
693 | | - requires('largefile', |
694 | | - 'test requires %s bytes and a long time to run' % str(0x180000000)) |
695 | | - self._working_largefile() |
696 | | - with open(TESTFN, 'wb') as f: |
697 | | - f.seek(0x17FFFFFFF) |
698 | | - f.write(b" ") |
699 | | - |
| 685 | + self._create_test_file(0x17FFFFFFF, b" ") |
700 | 686 | with open(TESTFN, 'rb') as f: |
701 | 687 | with mmap.mmap(f.fileno(), 0x10000, access=mmap.ACCESS_READ) as m: |
702 | 688 | self.assertEqual(m.size(), 0x180000000) |
703 | 689 |
|
| 690 | + # Issue 11277: mmap() with large (~4GB) sparse files crashes on OS X. |
| 691 | + |
| 692 | + def _test_around_boundary(self, boundary): |
| 693 | + tail = b' DEARdear ' |
| 694 | + start = boundary - len(tail) // 2 |
| 695 | + end = start + len(tail) |
| 696 | + self._create_test_file(start, tail) |
| 697 | + with open(TESTFN, 'rb') as f: |
| 698 | + with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as m: |
| 699 | + self.assertEqual(m[start:end], tail) |
| 700 | + |
| 701 | + @unittest.skipUnless(sys.maxsize > _4G, "test cannot run on 32-bit systems") |
| 702 | + def test_around_2GB(self): |
| 703 | + self._test_around_boundary(_2G) |
| 704 | + |
| 705 | + @unittest.skipUnless(sys.maxsize > _4G, "test cannot run on 32-bit systems") |
| 706 | + def test_around_4GB(self): |
| 707 | + self._test_around_boundary(_4G) |
| 708 | + |
704 | 709 |
|
705 | 710 | def test_main(): |
706 | 711 | run_unittest(MmapTests, LargeMmapTests) |
|
0 commit comments