Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 471dbac

Browse filesBrowse files
authored
Merge pull request #4841 from Masorubka1/test_mmap.py
Update test_mmap.py from Cpython v3.11.2
2 parents 507e103 + ffea61b commit 471dbac
Copy full SHA for 471dbac

File tree

1 file changed

+99
-9
lines changed
Filter options

1 file changed

+99
-9
lines changed

‎Lib/test/test_mmap.py

Copy file name to clipboardExpand all lines: Lib/test/test_mmap.py
+99-9Lines changed: 99 additions & 9 deletions
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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.