[igt-dev] [PATCH 2/2] tests/fbdev: Add tests for read/write ops on framebuffer
Daniel Vetter
daniel.vetter at ffwll.ch
Tue Nov 3 12:08:35 UTC 2020
On Tue, Nov 3, 2020 at 11:48 AM Thomas Zimmermann <tzimmermann at suse.de> wrote:
>
> Read and write tests check the read and written buffer against the
> content of the mapped framebuffer. Fbdev has some specific behavior
> when reading/writing near the EOF, which the eof test checks.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann at suse.de>
> ---
> tests/fbdev.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 80 insertions(+)
>
> diff --git a/tests/fbdev.c b/tests/fbdev.c
> index 11df954d..045b0874 100644
> --- a/tests/fbdev.c
> +++ b/tests/fbdev.c
> @@ -25,6 +25,7 @@
>
> #include "igt.h"
>
> +#include <errno.h>
> #include <fcntl.h>
> #include <string.h>
> #include <sys/ioctl.h>
> @@ -43,6 +44,7 @@ igt_main
> struct fb_fix_screeninfo fix_info;
> int fd = -1;
> void *map = NULL;
> + void *buf = NULL;
Same thing here as with the shared map, this blows up if you only run
specific subtests.
Also I think this is getting unwieldy, and we should extract subtests
into functions that get called for local scoping and everything.
>
> /*
> * Should this test focus on the fbdev independent of any drm driver,
> @@ -82,7 +84,85 @@ igt_main
> memset(map, 0, fix_info.smem_len);
> }
>
> + igt_subtest("read") {
> + ssize_t ret;
> + int cmp;
> +
> + /* allocate two additional byte for eof test */
> + buf = malloc(fix_info.smem_len + 2);
> + igt_assert(buf);
> +
> + /* framebuffer should be 0 from mmap test */
> + ret = pread(fd, buf, fix_info.smem_len, 0);
> + igt_require_f(ret == (ssize_t)fix_info.smem_len, "pread failed\n");
> + cmp = memcmp(map, buf, fix_info.smem_len);
> + igt_require_f(!cmp, "read buffer differs from mapped framebuffer for 0\n");
> +
> + /* fill framebuffer with 0x55 and compare again */
> + memset(map, 0x55, fix_info.smem_len);
> + ret = pread(fd, buf, fix_info.smem_len, 0);
> + igt_require_f(ret == (ssize_t)fix_info.smem_len, "pread failed\n");
> + cmp = memcmp(map, buf, fix_info.smem_len);
> + igt_require_f(!cmp, "read buffer differs from mapped framebuffer for 0x55\n");
> + }
> +
> + igt_subtest("write") {
> + ssize_t ret;
> + int cmp;
> +
> + /* clear framebuffer and compare again */
> + memset(buf, 0, fix_info.smem_len);
> + ret = pwrite(fd, buf, fix_info.smem_len, 0);
> + igt_require_f(ret == (ssize_t)fix_info.smem_len, "pwrite failed\n");
> + cmp = memcmp(map, buf, fix_info.smem_len);
> + igt_require_f(!cmp, "write buffer differs from mapped framebuffer for 0\n");
> + }
> +
> + igt_subtest("eof") {
> + unsigned long lastindex = fix_info.smem_len - 1;
> + unsigned char *maplast = &((unsigned char *)map)[lastindex];
> + unsigned char *buflast = &((unsigned char *)buf)[lastindex];
> + long long ret;
> +
> + *buflast = 0x55;
> +
> + /* write across EOF; set remaining bytes */
> + ret = (long long)pwrite(fd, buflast, 2, lastindex);
> + igt_require_f(ret == 1, "write crossed EOF, ret=%lld\n", ret);
> + igt_require_f(*maplast == *buflast, "write buffer differs from mapped framebuffer at final byte, "
> + "maplast=%u buflast=%u\n", *maplast, *buflast);
> +
> + /* write at EOF; get ENOSPC */
> + ret = (long long)pwrite(fd, &buflast[1], 1, lastindex + 1);
> + igt_require_f((ret == -1) && (errno == ENOSPC), "write at EOF, ret=%lld\n", ret);
> +
> + *maplast = 0;
> +
> + /* write final byte */
> + ret = (long long)pwrite(fd, buflast, 1, lastindex);
> + igt_require_f(ret == 1, "write before EOF, ret=%lld\n", ret);
> + igt_require_f(*maplast == *buflast, "write buffer differs from mapped framebuffer at final byte, "
> + "maplast=%u buflast=%u\n", *maplast, *buflast);
> +
> + /* write after EOF; get EFBIG */
> + ret = (long long)pwrite(fd, &buflast[2], 1, lastindex + 2);
> + igt_require_f((ret == -1) && (errno == EFBIG), "write after EOF, ret=%lld\n", ret);
> +
> + *maplast = 0;
> +
> + /* read across the EOF; get remaining bytes */
> + ret = (long long)pread(fd, buflast, 2, lastindex);
> + igt_require_f(ret == 1, "read before EOF\n");
> + igt_require_f(*maplast == *buflast, "read buffer differs from mapped framebuffer at final byte, "
> + "maplast=%u buflast=%u\n", *maplast, *buflast);
> +
> + /* read after EOF; get 0 */
> + ret = (long long)pread(fd, &buflast[1], 1, lastindex + 1);
> + igt_require_f(ret == 0, "read at EOF, ret=%lld\n", ret);
Maybe also a NULL pointer tests which checks we get an EFAULT?
Another corner case is a read/write that's not PAGE aligned, e.g. from
PAGE_SIZE/2 to PAGE_SIZE + PAGE_SIZE/2 (assuming the buffer is at
least 2 pages ofc).
Otherwise test logic looks complete to me. Thanks for creating these.
-Daniel
> + }
> +
> igt_fixture {
> + free(buf);
> if (map && map != MAP_FAILED)
> munmap(map, fix_info.smem_len);
> close(fd);
> --
> 2.29.0
>
> _______________________________________________
> igt-dev mailing list
> igt-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/igt-dev
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the igt-dev
mailing list