Bug 1212023

Summary: python-smmap: fails to build on ALP
Product: [SUSE ALP - SUSE Adaptable Linux Platform] Granite Reporter: Héctor Orón Martínez <hector.oron>
Component: BasesystemAssignee: Python maintainers (group account) <python-maintainers>
Status: RESOLVED FIXED QA Contact:
Severity: Major    
Priority: P1 - Urgent CC: daniel.garcia, ihno, jsrain, kstreitova, python-maintainers, saweber
Version: unspecified   
Target Milestone: ---   
Hardware: PowerPC-64   
OS: Other   
Whiteboard:
Found By: --- Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---

Description Héctor Orón Martínez 2023-06-05 12:43:02 UTC
ALP June Milestone 1 expects to have packages fixed to build images to take under test by Friday 9th.

In that context the following package has been found to fail to build from source:

  python-smmap

Note package seems to build fine on Factory:

  https://build.opensuse.org/package/show/openSUSE:Factory:PowerPC/python-smmap

With the following error:

[   32s] + pytest-3.11 --ignore=_build. --ignore=_build.python311 --ignore=_build.python310 -v
[   32s] ============================= test session starts ==============================
[   32s] platform linux -- Python 3.11.2, pytest-7.3.1, pluggy-1.0.0 -- /usr/bin/python3.11
[   32s] cachedir: .pytest_cache
[   32s] rootdir: /home/abuild/rpmbuild/BUILD/smmap-5.0.0
[   32s] collecting ... collected 9 items
[   32s] 
[   44s] smmap/test/test_buf.py::TestBuf::test_basics PASSED                      [ 11%]
[   44s] smmap/test/test_mman.py::TestMMan::test_cursor PASSED                    [ 22%]
[   49s] smmap/test/test_mman.py::TestMMan::test_memman_operation FAILED          [ 33%]
[   49s] smmap/test/test_mman.py::TestMMan::test_memory_manager PASSED            [ 44%]
[   49s] smmap/test/test_tutorial.py::TestTutorial::test_example PASSED           [ 55%]
[   49s] smmap/test/test_util.py::TestMMan::test_region PASSED                    [ 66%]
[   49s] smmap/test/test_util.py::TestMMan::test_region_list PASSED               [ 77%]
[   49s] smmap/test/test_util.py::TestMMan::test_util PASSED                      [ 88%]
[   49s] smmap/test/test_util.py::TestMMan::test_window PASSED                    [100%]
[   49s] 
[   49s] =================================== FAILURES ===================================
[   49s] ________________________ TestMMan.test_memman_operation ________________________
[   49s] 
[   49s] self = <smmap.test.test_mman.TestMMan testMethod=test_memman_operation>
[   49s] 
[   49s]     def test_memman_operation(self):
[   49s]         # test more access, force it to actually unmap regions
[   49s]         with FileCreator(self.k_window_test_size, "manager_operation_test") as fc:
[   49s]             with open(fc.path, 'rb') as fp:
[   49s]                 data = fp.read()
[   49s]             fd = os.open(fc.path, os.O_RDONLY)
[   49s]             try:
[   49s]                 max_num_handles = 15
[   49s]                 # small_size =
[   49s]                 for mtype, args in ((StaticWindowMapManager, (0, fc.size // 3, max_num_handles)),
[   49s]                                     (SlidingWindowMapManager, (fc.size // 100, fc.size // 3, max_num_handles)),):
[   49s]                     for item in (fc.path, fd):
[   49s]                         assert len(data) == fc.size
[   49s]     
[   49s]                         # small windows, a reasonable max memory. Not too many regions at once
[   49s]                         man = mtype(window_size=args[0], max_memory_size=args[1], max_open_handles=args[2])
[   49s]                         c = man.make_cursor(item)
[   49s]     
[   49s]                         # still empty (more about that is tested in test_memory_manager()
[   49s]                         assert man.num_open_files() == 0
[   49s]                         assert man.mapped_memory_size() == 0
[   49s]     
[   49s]                         base_offset = 5000
[   49s]                         # window size is 0 for static managers, hence size will be 0. We take that into consideration
[   49s]                         size = man.window_size() // 2
[   49s]                         assert c.use_region(base_offset, size).is_valid()
[   49s]                         rr = c.region()
[   49s]                         assert rr.client_count() == 2  # the manager and the cursor and us
[   49s]     
[   49s]                         assert man.num_open_files() == 1
[   49s]                         assert man.num_file_handles() == 1
[   49s]                         assert man.mapped_memory_size() == rr.size()
[   49s]     
[   49s]                         # assert c.size() == size        # the cursor may overallocate in its static version
[   49s]                         assert c.ofs_begin() == base_offset
[   49s]                         assert rr.ofs_begin() == 0        # it was aligned and expanded
[   49s]                         if man.window_size():
[   49s]                             # but isn't larger than the max window (aligned)
[   49s]                             assert rr.size() == align_to_mmap(man.window_size(), True)
[   49s]                         else:
[   49s]                             assert rr.size() == fc.size
[   49s]                         # END ignore static managers which dont use windows and are aligned to file boundaries
[   49s]     
[   49s]                         assert c.buffer()[:] == data[base_offset:base_offset + (size or c.size())]
[   49s]     
[   49s]                         # obtain second window, which spans the first part of the file - it is a still the same window
[   49s]                         nsize = (size or fc.size) - 10
[   49s]                         assert c.use_region(0, nsize).is_valid()
[   49s]                         assert c.region() == rr
[   49s]                         assert man.num_file_handles() == 1
[   49s]                         assert c.size() == nsize
[   49s]                         assert c.ofs_begin() == 0
[   49s]                         assert c.buffer()[:] == data[:nsize]
[   49s]     
[   49s]                         # map some part at the end, our requested size cannot be kept
[   49s]                         overshoot = 4000
[   49s]                         base_offset = fc.size - (size or c.size()) + overshoot
[   49s]                         assert c.use_region(base_offset, size).is_valid()
[   49s]                         if man.window_size():
[   49s]                             assert man.num_file_handles() == 2
[   49s]                             assert c.size() < size
[   49s]                             assert c.region() is not rr  # old region is still available, but has not curser ref anymore
[   49s]                             assert rr.client_count() == 1  # only held by manager
[   49s]                         else:
[   49s]                             assert c.size() < fc.size
[   49s]                         # END ignore static managers which only have one handle per file
[   49s]                         rr = c.region()
[   49s]                         assert rr.client_count() == 2  # manager + cursor
[   49s]                         assert rr.ofs_begin() < c.ofs_begin()  # it should have extended itself to the left
[   49s]                         assert rr.ofs_end() <= fc.size  # it cannot be larger than the file
[   49s]                         assert c.buffer()[:] == data[base_offset:base_offset + (size or c.size())]
[   49s]     
[   49s]                         # unising a region makes the cursor invalid
[   49s]                         c.unuse_region()
[   49s]                         assert not c.is_valid()
[   49s]                         if man.window_size():
[   49s]                             # but doesn't change anything regarding the handle count - we cache it and only
[   49s]                             # remove mapped regions if we have to
[   49s]                             assert man.num_file_handles() == 2
[   49s]                         # END ignore this for static managers
[   49s]     
[   49s]                         # iterate through the windows, verify data contents
[   49s]                         # this will trigger map collection after a while
[   49s]                         max_random_accesses = 5000
[   49s]                         num_random_accesses = max_random_accesses
[   49s]                         memory_read = 0
[   49s]                         st = time()
[   49s]     
[   49s]                         # cache everything to get some more performance
[   49s]                         includes_ofs = c.includes_ofs
[   49s]                         max_mapped_memory_size = man.max_mapped_memory_size()
[   49s]                         max_file_handles = man.max_file_handles()
[   49s]                         mapped_memory_size = man.mapped_memory_size
[   49s]                         num_file_handles = man.num_file_handles
[   49s]                         while num_random_accesses:
[   49s]                             num_random_accesses -= 1
[   49s]                             base_offset = randint(0, fc.size - 1)
[   49s]     
[   49s]                             # precondition
[   49s]                             if man.window_size():
[   49s] >                               assert max_mapped_memory_size >= mapped_memory_size()
[   49s] E                               assert 2668398 >= 2686976
[   49s] E                                +  where 2686976 = <bound method StaticWindowMapManager.mapped_memory_size of <smmap.mman.SlidingWindowMapManager object at 0x7fff7d3f3830>>()
[   49s] 
[   49s] smmap/test/test_mman.py:196: AssertionError
[   49s] ----------------------------- Captured stderr call -----------------------------
[   49s] <class 'smmap.mman.StaticWindowMapManager'>: Read 79 mb of memory with 5000 random on cursor initialized with <class 'str'> accesses in 1.134274s (70.331620 mb/s)
[   49s] 
[   49s] <class 'smmap.mman.StaticWindowMapManager'>: Read 123 mb of memory with 5000 random on cursor initialized with <class 'int'> accesses in 1.704334s (72.237248 mb/s)
[   49s] 
[   49s] =========================== short test summary info ============================
[   49s] FAILED smmap/test/test_mman.py::TestMMan::test_memman_operation - assert 2668...
[   49s] ========================= 1 failed, 8 passed in 16.96s =========================
[   49s] error: Bad exit status from /var/tmp/rpm-tmp.P7H1T1 (%check)

Full log: https://build.suse.de/package/live_build_log/SUSE:ALP:Source:Standard:Core:1.0:Build/python-smmap/standard/ppc64le
Comment 1 Daniel Garcia 2023-06-06 06:39:47 UTC
In this case, the factory package is equal to the one in ALP, and I was unable to replicate the error locally, so maybe it's a flaky test that fail some times in the OBS run.