Skip to content

Commit 0a411a9

Browse files
committed
Update test_mmap.py from Cpython v3.11.2
1 parent 6c6290d commit 0a411a9

File tree

1 file changed

+99
-9
lines changed

1 file changed

+99
-9
lines changed

Lib/test/test_mmap.py

+99-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
from test.support import (requires, _2G, _4G, gc_collect, cpython_only)
1+
from test.support import (
2+
requires, _2G, _4G, gc_collect, cpython_only, is_emscripten
3+
)
24
from test.support.import_helper import import_module
35
from test.support.os_helper import TESTFN, unlink
46
import unittest
57
import os
68
import re
79
import itertools
10+
import random
811
import socket
12+
import string
913
import sys
1014
import weakref
1115

@@ -14,6 +18,16 @@
1418

1519
PAGESIZE = mmap.PAGESIZE
1620

21+
tagname_prefix = f'python_{os.getpid()}_test_mmap'
22+
def random_tagname(length=10):
23+
suffix = ''.join(random.choices(string.ascii_uppercase, k=length))
24+
return f'{tagname_prefix}_{suffix}'
25+
26+
# Python's mmap module dup()s the file descriptor. Emscripten's FS layer
27+
# does not materialize file changes through a dupped fd to a new mmap.
28+
if is_emscripten:
29+
raise unittest.SkipTest("incompatible with Emscripten's mmap emulation.")
30+
1731

1832
class MmapTests(unittest.TestCase):
1933

@@ -609,21 +623,23 @@ def test_tagname(self):
609623
data1 = b"0123456789"
610624
data2 = b"abcdefghij"
611625
assert len(data1) == len(data2)
626+
tagname1 = random_tagname()
627+
tagname2 = random_tagname()
612628

613629
# Test same tag
614-
m1 = mmap.mmap(-1, len(data1), tagname="foo")
630+
m1 = mmap.mmap(-1, len(data1), tagname=tagname1)
615631
m1[:] = data1
616-
m2 = mmap.mmap(-1, len(data2), tagname="foo")
632+
m2 = mmap.mmap(-1, len(data2), tagname=tagname1)
617633
m2[:] = data2
618634
self.assertEqual(m1[:], data2)
619635
self.assertEqual(m2[:], data2)
620636
m2.close()
621637
m1.close()
622638

623639
# Test different tag
624-
m1 = mmap.mmap(-1, len(data1), tagname="foo")
640+
m1 = mmap.mmap(-1, len(data1), tagname=tagname1)
625641
m1[:] = data1
626-
m2 = mmap.mmap(-1, len(data2), tagname="boo")
642+
m2 = mmap.mmap(-1, len(data2), tagname=tagname2)
627643
m2[:] = data2
628644
self.assertEqual(m1[:], data1)
629645
self.assertEqual(m2[:], data2)
@@ -634,17 +650,18 @@ def test_tagname(self):
634650
@unittest.skipUnless(os.name == 'nt', 'requires Windows')
635651
def test_sizeof(self):
636652
m1 = mmap.mmap(-1, 100)
637-
tagname = "foo"
653+
tagname = random_tagname()
638654
m2 = mmap.mmap(-1, 100, tagname=tagname)
639655
self.assertEqual(sys.getsizeof(m2),
640656
sys.getsizeof(m1) + len(tagname) + 1)
641657

642658
@unittest.skipUnless(os.name == 'nt', 'requires Windows')
643659
def test_crasher_on_windows(self):
644660
# Should not crash (Issue 1733986)
645-
m = mmap.mmap(-1, 1000, tagname="foo")
661+
tagname = random_tagname()
662+
m = mmap.mmap(-1, 1000, tagname=tagname)
646663
try:
647-
mmap.mmap(-1, 5000, tagname="foo")[:] # same tagname, but larger size
664+
mmap.mmap(-1, 5000, tagname=tagname)[:] # same tagname, but larger size
648665
except:
649666
pass
650667
m.close()
@@ -707,7 +724,6 @@ def test_write_returning_the_number_of_bytes_written(self):
707724
self.assertEqual(mm.write(b"yz"), 2)
708725
self.assertEqual(mm.write(b"python"), 6)
709726

710-
@unittest.skipIf(os.name == 'nt', 'cannot resize anonymous mmaps on Windows')
711727
def test_resize_past_pos(self):
712728
m = mmap.mmap(-1, 8192)
713729
self.addCleanup(m.close)
@@ -797,6 +813,80 @@ def test_madvise(self):
797813
self.assertEqual(m.madvise(mmap.MADV_NORMAL, 0, 2), None)
798814
self.assertEqual(m.madvise(mmap.MADV_NORMAL, 0, size), None)
799815

816+
@unittest.skipUnless(os.name == 'nt', 'requires Windows')
817+
def test_resize_up_when_mapped_to_pagefile(self):
818+
"""If the mmap is backed by the pagefile ensure a resize up can happen
819+
and that the original data is still in place
820+
"""
821+
start_size = PAGESIZE
822+
new_size = 2 * start_size
823+
data = bytes(random.getrandbits(8) for _ in range(start_size))
824+
825+
m = mmap.mmap(-1, start_size)
826+
m[:] = data
827+
m.resize(new_size)
828+
self.assertEqual(len(m), new_size)
829+
self.assertEqual(m[:start_size], data[:start_size])
830+
831+
@unittest.skipUnless(os.name == 'nt', 'requires Windows')
832+
def test_resize_down_when_mapped_to_pagefile(self):
833+
"""If the mmap is backed by the pagefile ensure a resize down up can happen
834+
and that a truncated form of the original data is still in place
835+
"""
836+
start_size = PAGESIZE
837+
new_size = start_size // 2
838+
data = bytes(random.getrandbits(8) for _ in range(start_size))
839+
840+
m = mmap.mmap(-1, start_size)
841+
m[:] = data
842+
m.resize(new_size)
843+
self.assertEqual(len(m), new_size)
844+
self.assertEqual(m[:new_size], data[:new_size])
845+
846+
@unittest.skipUnless(os.name == 'nt', 'requires Windows')
847+
def test_resize_fails_if_mapping_held_elsewhere(self):
848+
"""If more than one mapping is held against a named file on Windows, neither
849+
mapping can be resized
850+
"""
851+
start_size = 2 * PAGESIZE
852+
reduced_size = PAGESIZE
853+
854+
f = open(TESTFN, 'wb+')
855+
f.truncate(start_size)
856+
try:
857+
m1 = mmap.mmap(f.fileno(), start_size)
858+
m2 = mmap.mmap(f.fileno(), start_size)
859+
with self.assertRaises(OSError):
860+
m1.resize(reduced_size)
861+
with self.assertRaises(OSError):
862+
m2.resize(reduced_size)
863+
m2.close()
864+
m1.resize(reduced_size)
865+
self.assertEqual(m1.size(), reduced_size)
866+
self.assertEqual(os.stat(f.fileno()).st_size, reduced_size)
867+
finally:
868+
f.close()
869+
870+
@unittest.skipUnless(os.name == 'nt', 'requires Windows')
871+
def test_resize_succeeds_with_error_for_second_named_mapping(self):
872+
"""If a more than one mapping exists of the same name, none of them can
873+
be resized: they'll raise an Exception and leave the original mapping intact
874+
"""
875+
start_size = 2 * PAGESIZE
876+
reduced_size = PAGESIZE
877+
tagname = random_tagname()
878+
data_length = 8
879+
data = bytes(random.getrandbits(8) for _ in range(data_length))
880+
881+
m1 = mmap.mmap(-1, start_size, tagname=tagname)
882+
m2 = mmap.mmap(-1, start_size, tagname=tagname)
883+
m1[:data_length] = data
884+
self.assertEqual(m2[:data_length], data)
885+
with self.assertRaises(OSError):
886+
m1.resize(reduced_size)
887+
self.assertEqual(m1.size(), start_size)
888+
self.assertEqual(m1[:data_length], data)
889+
self.assertEqual(m2[:data_length], data)
800890

801891
class LargeMmapTests(unittest.TestCase):
802892

0 commit comments

Comments
 (0)