[libcamera-devel] [PATCH v4 11/15] py: unittests.py: Add test for refs & keep-alives

Laurent Pinchart laurent.pinchart at ideasonboard.com
Sun Mar 12 16:04:02 CET 2023


Hi Tomi,

Thank you for the patch.

On Thu, Mar 09, 2023 at 04:25:57PM +0200, Tomi Valkeinen via libcamera-devel wrote:
> Add a test for references and keep-alives by doing a capture, reusing
> the Requests once and testing that the objects are freed as soon as all
> the refs and keep-alives are gone.
> 
> Signed-off-by: Tomi Valkeinen <tomi.valkeinen at ideasonboard.com>

Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

> ---
>  test/py/unittests.py | 128 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 128 insertions(+)
> 
> diff --git a/test/py/unittests.py b/test/py/unittests.py
> index 3bd2d7fd..b52b3391 100755
> --- a/test/py/unittests.py
> +++ b/test/py/unittests.py
> @@ -31,6 +31,134 @@ class BaseTestCase(unittest.TestCase):
>          self.assertTrue(all([not wr() for wr in wr_list]), msg)
>  
>  
> +# Test references and keep-alives by doing a capture, reusing the Requests once
> +# and testing that the objects are freed as soon as all the refs and keep-alives
> +# are gone.
> +class CaptureRefTestMethods(BaseTestCase):
> +    def test_ref(self):
> +        cm = libcam.CameraManager.singleton()
> +        wr_cm = weakref.ref(cm)
> +
> +        cam = cm.get('platform/vimc.0 Sensor B')
> +        self.assertIsNotNone(cam)
> +        wr_cam = weakref.ref(cam)
> +
> +        cam.acquire()
> +
> +        camconfig = cam.generate_configuration([libcam.StreamRole.StillCapture])
> +        self.assertTrue(camconfig.size == 1)
> +        wr_camconfig = weakref.ref(camconfig)
> +
> +        streamconfig = camconfig.at(0)
> +        wr_streamconfig = weakref.ref(streamconfig)
> +
> +        cam.configure(camconfig)
> +
> +        stream = streamconfig.stream
> +        wr_stream = weakref.ref(stream)
> +
> +        # stream keeps streamconfig and camconfig alive
> +        del streamconfig
> +        del camconfig
> +        gc.collect()
> +        self.assertIsAlive(wr_camconfig)
> +        self.assertIsAlive(wr_streamconfig)
> +
> +        allocator = libcam.FrameBufferAllocator(cam)
> +        num_bufs = allocator.allocate(stream)
> +        self.assertTrue(num_bufs > 0)
> +        wr_allocator = weakref.ref(allocator)
> +
> +        buffers = allocator.buffers(stream)
> +        self.assertIsNotNone(buffers)
> +
> +        wr_buffers = [weakref.ref(b) for b in buffers]
> +
> +        del allocator
> +        self.assertIsAlive(wr_allocator)
> +
> +        reqs = []
> +        wr_reqs = []
> +        for i in range(num_bufs):
> +            req = cam.create_request(i)
> +            self.assertIsNotNone(req)
> +
> +            wr_reqs.append(weakref.ref(req))
> +
> +            req.add_buffer(stream, buffers[i])
> +
> +            reqs.append(req)
> +
> +        del buffers
> +        del stream
> +
> +        self.assertIsDead(wr_stream)
> +
> +        cam.start()
> +
> +        reqs_target = num_bufs * 2
> +        reqs_queued = 0
> +        reqs_captured = 0
> +
> +        for req in reqs:
> +            cam.queue_request(req)
> +            reqs_queued += 1
> +
> +        del req
> +        del reqs
> +
> +        # All buffers and reqs should be alive
> +        self.assertIsAllAlive(wr_buffers)
> +        self.assertIsAllAlive(wr_reqs)
> +
> +        sel = selectors.DefaultSelector()
> +        sel.register(cm.event_fd, selectors.EVENT_READ)
> +
> +        while True:
> +            events = sel.select()
> +            if not events:
> +                continue
> +            del events
> +
> +            for ev in cm.get_events():
> +                self.assertEqual(ev.type, libcam.Event.Type.RequestCompleted)
> +
> +                reqs_captured += 1
> +                self.assertLessEqual(reqs_captured, reqs_target)
> +
> +                if reqs_queued < reqs_target:
> +                    req: libcam.Request = typing.cast(libcam.Request, ev.request)
> +                    req.reuse()
> +                    cam.queue_request(req)
> +                    reqs_queued += 1
> +                    del req
> +
> +            del ev
> +
> +            if reqs_captured == reqs_target:
> +                break
> +
> +        del sel
> +
> +        # The allocator and all buffers and reqs should be dead
> +        self.assertIsAllDead(wr_buffers)
> +        self.assertIsAllDead(wr_reqs)
> +        self.assertIsDead(wr_allocator)
> +
> +        events = cam.stop()
> +        self.assertZero(len(events))
> +        del events
> +        cam.release()
> +
> +        del cm
> +        self.assertIsAlive(wr_cm)
> +        self.assertIsAlive(wr_cam)
> +
> +        del cam
> +        self.assertIsDead(wr_cam)
> +        self.assertIsDead(wr_cm)
> +
> +
>  class SimpleTestMethods(BaseTestCase):
>      def test_get_ref(self):
>          cm = libcam.CameraManager.singleton()

-- 
Regards,

Laurent Pinchart


More information about the libcamera-devel mailing list