All of lore.kernel.org
 help / color / mirror / Atom feed
From: Fabiano Rosas <farosas@suse.de>
To: Junjie Cao <junjie.cao@intel.com>, qemu-devel@nongnu.org
Cc: berrange@redhat.com, peterx@redhat.com, junjie.cao@intel.com
Subject: Re: [PATCH v3 4/4] tests/unit: add pread/pwrite _all tests for io channel file
Date: Tue, 14 Apr 2026 13:01:25 -0300	[thread overview]
Message-ID: <878qapzg2y.fsf@suse.de> (raw)
In-Reply-To: <20260413214549.926435-5-junjie.cao@intel.com>

Junjie Cao <junjie.cao@intel.com> writes:

> Add unit tests for the new qio_channel_pread{v,}_all{,_eof}() and
> qio_channel_pwrite{v,}_all() APIs.
>
> The basic tests write data to a file channel, then read it back at
> various offsets using both the single-buffer and iovec variants to
> make sure the round-trip produces identical content.  The _eof tests
> verify all three return cases -- full read (1), clean EOF (0), and
> partial-then-EOF (-1 with error set) -- and check that the strict
> wrappers (preadv_all / pread_all) treat a clean EOF as an error.
>
> All tests are guarded by CONFIG_PREADV since the underlying channel
> methods require preadv(2).
>
> Signed-off-by: Junjie Cao <junjie.cao@intel.com>
> ---
>  tests/unit/test-io-channel-file.c | 207 ++++++++++++++++++++++++++++++
>  1 file changed, 207 insertions(+)
>
> diff --git a/tests/unit/test-io-channel-file.c b/tests/unit/test-io-channel-file.c
> index 1977006ce9..b597350dca 100644
> --- a/tests/unit/test-io-channel-file.c
> +++ b/tests/unit/test-io-channel-file.c
> @@ -102,6 +102,203 @@ static void test_io_channel_fd(void)
>  }
>  
>  
> +#ifdef CONFIG_PREADV
> +static void test_io_channel_pread_all(void)
> +{
> +    QIOChannel *ioc;
> +    char write_buf[] = "Hello World, pread_all";
> +    char read_buf[sizeof(write_buf)] = {0};
> +    int ret;
> +
> +    unlink(TEST_FILE);
> +    ioc = QIO_CHANNEL(qio_channel_file_new_path(
> +                          TEST_FILE,
> +                          O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
> +                          TEST_MASK,
> +                          &error_abort));
> +
> +    ret = qio_channel_pwrite_all(ioc, write_buf, sizeof(write_buf),
> +                                 0, &error_abort);
> +    g_assert_cmpint(ret, ==, 0);
> +
> +    /* Read back at offset 0 */
> +    ret = qio_channel_pread_all(ioc, read_buf, sizeof(read_buf),
> +                                0, &error_abort);
> +    g_assert_cmpint(ret, ==, 0);
> +    g_assert_cmpmem(write_buf, sizeof(write_buf),
> +                    read_buf, sizeof(read_buf));
> +
> +    /* Read at a non-zero offset */
> +    memset(read_buf, 0, sizeof(read_buf));
> +    ret = qio_channel_pread_all(ioc, read_buf, sizeof(write_buf) - 7,
> +                                7, &error_abort);
> +    g_assert_cmpint(ret, ==, 0);
> +    g_assert_cmpmem(write_buf + 7, sizeof(write_buf) - 7,
> +                    read_buf, sizeof(write_buf) - 7);
> +
> +    unlink(TEST_FILE);
> +    object_unref(OBJECT(ioc));
> +}
> +
> +static void test_io_channel_preadv_all(void)
> +{
> +    QIOChannel *ioc;
> +    char write_buf[256];
> +    char read_buf[256] = {0};
> +    struct iovec write_iov[2];
> +    struct iovec read_iov[2];
> +    int ret;
> +    size_t i;
> +
> +    for (i = 0; i < sizeof(write_buf); i++) {
> +        write_buf[i] = i & 0xff;
> +    }
> +
> +    unlink(TEST_FILE);
> +    ioc = QIO_CHANNEL(qio_channel_file_new_path(
> +                          TEST_FILE,
> +                          O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
> +                          TEST_MASK,
> +                          &error_abort));
> +
> +    /* Write using pwritev_all with 2 iovecs */
> +    write_iov[0].iov_base = write_buf;
> +    write_iov[0].iov_len = 128;
> +    write_iov[1].iov_base = write_buf + 128;
> +    write_iov[1].iov_len = 128;
> +    ret = qio_channel_pwritev_all(ioc, write_iov, 2, 0, &error_abort);
> +    g_assert_cmpint(ret, ==, 0);
> +
> +    /* Read back using preadv_all with 2 iovecs */
> +    read_iov[0].iov_base = read_buf;
> +    read_iov[0].iov_len = 128;
> +    read_iov[1].iov_base = read_buf + 128;
> +    read_iov[1].iov_len = 128;
> +    ret = qio_channel_preadv_all(ioc, read_iov, 2, 0, &error_abort);
> +    g_assert_cmpint(ret, ==, 0);
> +
> +    g_assert_cmpmem(write_buf, sizeof(write_buf),
> +                    read_buf, sizeof(read_buf));
> +
> +    /* Read at non-zero offset with preadv_all */
> +    memset(read_buf, 0, sizeof(read_buf));
> +    read_iov[0].iov_base = read_buf;
> +    read_iov[0].iov_len = 64;
> +    read_iov[1].iov_base = read_buf + 64;
> +    read_iov[1].iov_len = 64;
> +    ret = qio_channel_preadv_all(ioc, read_iov, 2, 128, &error_abort);
> +    g_assert_cmpint(ret, ==, 0);
> +
> +    g_assert_cmpmem(write_buf + 128, 128,
> +                    read_buf, 128);
> +
> +    unlink(TEST_FILE);
> +    object_unref(OBJECT(ioc));
> +}
> +
> +static void test_io_channel_preadv_all_eof(void)
> +{
> +    QIOChannel *ioc;
> +    char write_buf[] = "Hello World, preadv_all_eof";
> +    char read_buf[sizeof(write_buf)] = {0};
> +    struct iovec iov;
> +    int ret;
> +    Error *err = NULL;
> +
> +    unlink(TEST_FILE);
> +    ioc = QIO_CHANNEL(qio_channel_file_new_path(
> +                          TEST_FILE,
> +                          O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
> +                          TEST_MASK,
> +                          &error_abort));
> +
> +    ret = qio_channel_pwrite_all(ioc, write_buf, sizeof(write_buf),
> +                                 0, &error_abort);
> +    g_assert_cmpint(ret, ==, 0);
> +
> +    /* Full read succeeds: should return 1 */
> +    iov.iov_base = read_buf;
> +    iov.iov_len = sizeof(read_buf);
> +    ret = qio_channel_preadv_all_eof(ioc, &iov, 1, 0, &error_abort);
> +    g_assert_cmpint(ret, ==, 1);
> +    g_assert_cmpmem(write_buf, sizeof(write_buf),
> +                    read_buf, sizeof(read_buf));
> +
> +    /* Clean EOF: offset at file end, should return 0 */
> +    iov.iov_base = read_buf;
> +    iov.iov_len = 1;
> +    ret = qio_channel_preadv_all_eof(ioc, &iov, 1,
> +                                     sizeof(write_buf), &err);
> +    g_assert_cmpint(ret, ==, 0);
> +    g_assert_null(err);
> +
> +    /* Partial EOF: start before end, request extends past */
> +    iov.iov_base = read_buf;
> +    iov.iov_len = 8;
> +    ret = qio_channel_preadv_all_eof(ioc, &iov, 1,
> +                                     sizeof(write_buf) - 4, &err);
> +    g_assert_cmpint(ret, ==, -1);
> +    g_assert_nonnull(err);
> +    error_free(err);
> +    err = NULL;
> +
> +    /* Strict wrapper (preadv_all) treats clean EOF as error */
> +    iov.iov_base = read_buf;
> +    iov.iov_len = 1;
> +    ret = qio_channel_preadv_all(ioc, &iov, 1,
> +                                 sizeof(write_buf), &err);
> +    g_assert_cmpint(ret, ==, -1);
> +    g_assert_nonnull(err);
> +    error_free(err);
> +
> +    unlink(TEST_FILE);
> +    object_unref(OBJECT(ioc));
> +}
> +
> +static void test_io_channel_pread_all_eof(void)
> +{
> +    QIOChannel *ioc;
> +    char write_buf[] = "Hello World, pread_all_eof";
> +    char read_buf[sizeof(write_buf)] = {0};
> +    int ret;
> +    Error *err = NULL;
> +
> +    unlink(TEST_FILE);
> +    ioc = QIO_CHANNEL(qio_channel_file_new_path(
> +                          TEST_FILE,
> +                          O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
> +                          TEST_MASK,
> +                          &error_abort));
> +
> +    ret = qio_channel_pwrite_all(ioc, write_buf, sizeof(write_buf),
> +                                 0, &error_abort);
> +    g_assert_cmpint(ret, ==, 0);
> +
> +    /* Full read succeeds: should return 1 */
> +    ret = qio_channel_pread_all_eof(ioc, read_buf, sizeof(read_buf),
> +                                    0, &error_abort);
> +    g_assert_cmpint(ret, ==, 1);
> +    g_assert_cmpmem(write_buf, sizeof(write_buf),
> +                    read_buf, sizeof(read_buf));
> +
> +    /* Clean EOF: should return 0 */
> +    ret = qio_channel_pread_all_eof(ioc, read_buf, 1,
> +                                    sizeof(write_buf), &err);
> +    g_assert_cmpint(ret, ==, 0);
> +    g_assert_null(err);
> +
> +    /* Partial EOF: should return -1 */
> +    ret = qio_channel_pread_all_eof(ioc, read_buf, 8,
> +                                    sizeof(write_buf) - 4, &err);
> +    g_assert_cmpint(ret, ==, -1);
> +    g_assert_nonnull(err);
> +    error_free(err);
> +
> +    unlink(TEST_FILE);
> +    object_unref(OBJECT(ioc));
> +}
> +#endif /* CONFIG_PREADV */
> +
>  #ifndef _WIN32
>  static void test_io_channel_pipe(bool async)
>  {
> @@ -147,6 +344,16 @@ int main(int argc, char **argv)
>      g_test_add_func("/io/channel/file", test_io_channel_file);
>      g_test_add_func("/io/channel/file/rdwr", test_io_channel_file_rdwr);
>      g_test_add_func("/io/channel/file/fd", test_io_channel_fd);
> +#ifdef CONFIG_PREADV
> +    g_test_add_func("/io/channel/file/pread-all",
> +                    test_io_channel_pread_all);
> +    g_test_add_func("/io/channel/file/preadv-all",
> +                    test_io_channel_preadv_all);
> +    g_test_add_func("/io/channel/file/preadv-all-eof",
> +                    test_io_channel_preadv_all_eof);
> +    g_test_add_func("/io/channel/file/pread-all-eof",
> +                    test_io_channel_pread_all_eof);
> +#endif
>  #ifndef _WIN32
>      g_test_add_func("/io/channel/pipe/sync", test_io_channel_pipe_sync);
>      g_test_add_func("/io/channel/pipe/async", test_io_channel_pipe_async);

Reviewed-by: Fabiano Rosas <farosas@suse.de>


  reply	other threads:[~2026-04-14 16:03 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-13 21:45 [PATCH v3 0/4] io/channel: complete pread/pwrite_all API and fix multifd_file_recv_data Junjie Cao
2026-04-13 21:45 ` [PATCH v3 1/4] io/channel: introduce qio_channel_pread{v, }_all{, _eof}() Junjie Cao
2026-04-14 15:49   ` Fabiano Rosas
2026-04-17  9:45   ` [PATCH v3 1/4] io/channel: introduce qio_channel_pread{v,}_all{,_eof}() Daniel P. Berrangé
2026-04-13 21:45 ` [PATCH v3 2/4] io/channel: introduce qio_channel_pwrite{v,}_all() Junjie Cao
2026-04-14 15:54   ` [PATCH v3 2/4] io/channel: introduce qio_channel_pwrite{v, }_all() Fabiano Rosas
2026-04-17  9:46   ` Daniel P. Berrangé via qemu development
2026-04-13 21:45 ` [PATCH v3 3/4] migration/file: fix type mismatch and NULL deref in multifd_file_recv_data Junjie Cao
2026-04-14 15:55   ` Fabiano Rosas
2026-04-13 21:45 ` [PATCH v3 4/4] tests/unit: add pread/pwrite _all tests for io channel file Junjie Cao
2026-04-14 16:01   ` Fabiano Rosas [this message]
2026-04-17  9:47   ` Daniel P. Berrangé
2026-04-17 16:51 ` [PATCH v3 0/4] io/channel: complete pread/pwrite_all API and fix multifd_file_recv_data Junjie Cao
2026-04-17  9:48   ` Daniel P. Berrangé
2026-04-17 14:04     ` Peter Xu
2026-04-26  8:15 ` Michael Tokarev
2026-04-26  8:21   ` Michael Tokarev
2026-04-29 14:24     ` Fabiano Rosas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=878qapzg2y.fsf@suse.de \
    --to=farosas@suse.de \
    --cc=berrange@redhat.com \
    --cc=junjie.cao@intel.com \
    --cc=peterx@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.