cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

test-iov.c (17650B)


      1#include "qemu/osdep.h"
      2#include "qemu-common.h"
      3#include "qemu/iov.h"
      4#include "qemu/sockets.h"
      5
      6/* create a randomly-sized iovec with random vectors */
      7static void iov_random(struct iovec **iovp, unsigned *iov_cntp)
      8{
      9     unsigned niov = g_test_rand_int_range(3,8);
     10     struct iovec *iov = g_malloc(niov * sizeof(*iov));
     11     unsigned i;
     12     for (i = 0; i < niov; ++i) {
     13         iov[i].iov_len = g_test_rand_int_range(5,20);
     14         iov[i].iov_base = g_malloc(iov[i].iov_len);
     15     }
     16     *iovp = iov;
     17     *iov_cntp = niov;
     18}
     19
     20static void iov_free(struct iovec *iov, unsigned niov)
     21{
     22    unsigned i;
     23    for (i = 0; i < niov; ++i) {
     24        g_free(iov[i].iov_base);
     25    }
     26    g_free(iov);
     27}
     28
     29static bool iov_equals(const struct iovec *a, const struct iovec *b,
     30                       unsigned niov)
     31{
     32    return memcmp(a, b, sizeof(a[0]) * niov) == 0;
     33}
     34
     35static void test_iov_bytes(struct iovec *iov, unsigned niov,
     36                           size_t offset, size_t bytes)
     37{
     38    unsigned i;
     39    size_t j, o;
     40    unsigned char *b;
     41    o = 0;
     42
     43    /* we walk over all elements, */
     44    for (i = 0; i < niov; ++i) {
     45        b = iov[i].iov_base;
     46        /* over each char of each element, */
     47        for (j = 0; j < iov[i].iov_len; ++j) {
     48            /* counting each of them and
     49             * verifying that the ones within [offset,offset+bytes)
     50             * range are equal to the position number (o) */
     51            if (o >= offset && o < offset + bytes) {
     52                g_assert(b[j] == (o & 255));
     53            } else {
     54                g_assert(b[j] == 0xff);
     55            }
     56            ++o;
     57        }
     58    }
     59}
     60
     61static void test_to_from_buf_1(void)
     62{
     63     unsigned niov;
     64     struct iovec *iov;
     65     size_t sz;
     66     unsigned char *ibuf, *obuf;
     67     unsigned i, j, n;
     68
     69     iov_random(&iov, &niov);
     70
     71     sz = iov_size(iov, niov);
     72
     73     ibuf = g_malloc(sz + 8) + 4;
     74     memcpy(ibuf-4, "aaaa", 4); memcpy(ibuf + sz, "bbbb", 4);
     75     obuf = g_malloc(sz + 8) + 4;
     76     memcpy(obuf-4, "xxxx", 4); memcpy(obuf + sz, "yyyy", 4);
     77
     78     /* fill in ibuf with 0123456... */
     79     for (i = 0; i < sz; ++i) {
     80         ibuf[i] = i & 255;
     81     }
     82
     83     for (i = 0; i <= sz; ++i) {
     84
     85         /* Test from/to buf for offset(i) in [0..sz] up to the end of buffer.
     86          * For last iteration with offset == sz, the procedure should
     87          * skip whole vector and process exactly 0 bytes */
     88
     89         /* first set bytes [i..sz) to some "random" value */
     90         n = iov_memset(iov, niov, 0, 0xff, sz);
     91         g_assert(n == sz);
     92
     93         /* next copy bytes [i..sz) from ibuf to iovec */
     94         n = iov_from_buf(iov, niov, i, ibuf + i, sz - i);
     95         g_assert(n == sz - i);
     96
     97         /* clear part of obuf */
     98         memset(obuf + i, 0, sz - i);
     99         /* and set this part of obuf to values from iovec */
    100         n = iov_to_buf(iov, niov, i, obuf + i, sz - i);
    101         g_assert(n == sz - i);
    102
    103         /* now compare resulting buffers */
    104         g_assert(memcmp(ibuf, obuf, sz) == 0);
    105
    106         /* test just one char */
    107         n = iov_to_buf(iov, niov, i, obuf + i, 1);
    108         g_assert(n == (i < sz));
    109         if (n) {
    110             g_assert(obuf[i] == (i & 255));
    111         }
    112
    113         for (j = i; j <= sz; ++j) {
    114             /* now test num of bytes cap up to byte no. j,
    115              * with j in [i..sz]. */
    116
    117             /* clear iovec */
    118             n = iov_memset(iov, niov, 0, 0xff, sz);
    119             g_assert(n == sz);
    120
    121             /* copy bytes [i..j) from ibuf to iovec */
    122             n = iov_from_buf(iov, niov, i, ibuf + i, j - i);
    123             g_assert(n == j - i);
    124
    125             /* clear part of obuf */
    126             memset(obuf + i, 0, j - i);
    127
    128             /* copy bytes [i..j) from iovec to obuf */
    129             n = iov_to_buf(iov, niov, i, obuf + i, j - i);
    130             g_assert(n == j - i);
    131
    132             /* verify result */
    133             g_assert(memcmp(ibuf, obuf, sz) == 0);
    134
    135             /* now actually check if the iovec contains the right data */
    136             test_iov_bytes(iov, niov, i, j - i);
    137         }
    138    }
    139    g_assert(!memcmp(ibuf-4, "aaaa", 4) && !memcmp(ibuf+sz, "bbbb", 4));
    140    g_free(ibuf-4);
    141    g_assert(!memcmp(obuf-4, "xxxx", 4) && !memcmp(obuf+sz, "yyyy", 4));
    142    g_free(obuf-4);
    143    iov_free(iov, niov);
    144}
    145
    146static void test_to_from_buf(void)
    147{
    148    int x;
    149    for (x = 0; x < 4; ++x) {
    150        test_to_from_buf_1();
    151    }
    152}
    153
    154static void test_io(void)
    155{
    156#ifndef _WIN32
    157/* socketpair(PF_UNIX) which does not exist on windows */
    158
    159    int sv[2];
    160    int r;
    161    unsigned i, j, k, s;
    162    fd_set fds;
    163    unsigned niov;
    164    struct iovec *iov, *siov;
    165    unsigned char *buf;
    166    size_t sz;
    167
    168    iov_random(&iov, &niov);
    169    sz = iov_size(iov, niov);
    170    buf = g_malloc(sz);
    171    for (i = 0; i < sz; ++i) {
    172        buf[i] = i & 255;
    173    }
    174    iov_from_buf(iov, niov, 0, buf, sz);
    175
    176    siov = g_memdup(iov, sizeof(*iov) * niov);
    177
    178    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
    179       perror("socketpair");
    180       exit(1);
    181    }
    182
    183    FD_ZERO(&fds);
    184
    185    if (fork() == 0) {
    186       /* writer */
    187
    188       close(sv[0]);
    189       FD_SET(sv[1], &fds);
    190       fcntl(sv[1], F_SETFL, O_RDWR|O_NONBLOCK);
    191       r = g_test_rand_int_range(sz / 2, sz);
    192       setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &r, sizeof(r));
    193
    194       for (i = 0; i <= sz; ++i) {
    195           for (j = i; j <= sz; ++j) {
    196               k = i;
    197               do {
    198                   s = g_test_rand_int_range(0, j - k + 1);
    199                   r = iov_send(sv[1], iov, niov, k, s);
    200                   g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
    201                   if (r >= 0) {
    202                       k += r;
    203                       usleep(g_test_rand_int_range(0, 30));
    204                   } else if (errno == EAGAIN) {
    205                       select(sv[1]+1, NULL, &fds, NULL, NULL);
    206                       continue;
    207                   } else {
    208                       perror("send");
    209                       exit(1);
    210                   }
    211               } while(k < j);
    212           }
    213       }
    214       iov_free(iov, niov);
    215       g_free(buf);
    216       g_free(siov);
    217       exit(0);
    218
    219    } else {
    220       /* reader & verifier */
    221
    222       close(sv[1]);
    223       FD_SET(sv[0], &fds);
    224       fcntl(sv[0], F_SETFL, O_RDWR|O_NONBLOCK);
    225       r = g_test_rand_int_range(sz / 2, sz);
    226       setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &r, sizeof(r));
    227       usleep(500000);
    228
    229       for (i = 0; i <= sz; ++i) {
    230           for (j = i; j <= sz; ++j) {
    231               k = i;
    232               iov_memset(iov, niov, 0, 0xff, sz);
    233               do {
    234                   s = g_test_rand_int_range(0, j - k + 1);
    235                   r = iov_recv(sv[0], iov, niov, k, s);
    236                   g_assert(memcmp(iov, siov, sizeof(*iov)*niov) == 0);
    237                   if (r > 0) {
    238                       k += r;
    239                   } else if (!r) {
    240                       if (s) {
    241                           break;
    242                       }
    243                   } else if (errno == EAGAIN) {
    244                       select(sv[0]+1, &fds, NULL, NULL, NULL);
    245                       continue;
    246                   } else {
    247                       perror("recv");
    248                       exit(1);
    249                   }
    250               } while(k < j);
    251               test_iov_bytes(iov, niov, i, j - i);
    252           }
    253        }
    254
    255       iov_free(iov, niov);
    256       g_free(buf);
    257       g_free(siov);
    258     }
    259#endif
    260}
    261
    262static void test_discard_front(void)
    263{
    264    struct iovec *iov;
    265    struct iovec *iov_tmp;
    266    unsigned int iov_cnt;
    267    unsigned int iov_cnt_tmp;
    268    void *old_base;
    269    size_t size;
    270    size_t ret;
    271
    272    /* Discard zero bytes */
    273    iov_random(&iov, &iov_cnt);
    274    iov_tmp = iov;
    275    iov_cnt_tmp = iov_cnt;
    276    ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, 0);
    277    g_assert(ret == 0);
    278    g_assert(iov_tmp == iov);
    279    g_assert(iov_cnt_tmp == iov_cnt);
    280    iov_free(iov, iov_cnt);
    281
    282    /* Discard more bytes than vector size */
    283    iov_random(&iov, &iov_cnt);
    284    iov_tmp = iov;
    285    iov_cnt_tmp = iov_cnt;
    286    size = iov_size(iov, iov_cnt);
    287    ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size + 1);
    288    g_assert(ret == size);
    289    g_assert(iov_cnt_tmp == 0);
    290    iov_free(iov, iov_cnt);
    291
    292    /* Discard entire vector */
    293    iov_random(&iov, &iov_cnt);
    294    iov_tmp = iov;
    295    iov_cnt_tmp = iov_cnt;
    296    size = iov_size(iov, iov_cnt);
    297    ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
    298    g_assert(ret == size);
    299    g_assert(iov_cnt_tmp == 0);
    300    iov_free(iov, iov_cnt);
    301
    302    /* Discard within first element */
    303    iov_random(&iov, &iov_cnt);
    304    iov_tmp = iov;
    305    iov_cnt_tmp = iov_cnt;
    306    old_base = iov->iov_base;
    307    size = g_test_rand_int_range(1, iov->iov_len);
    308    ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
    309    g_assert(ret == size);
    310    g_assert(iov_tmp == iov);
    311    g_assert(iov_cnt_tmp == iov_cnt);
    312    g_assert(iov_tmp->iov_base == old_base + size);
    313    iov_tmp->iov_base = old_base; /* undo before g_free() */
    314    iov_free(iov, iov_cnt);
    315
    316    /* Discard entire first element */
    317    iov_random(&iov, &iov_cnt);
    318    iov_tmp = iov;
    319    iov_cnt_tmp = iov_cnt;
    320    ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, iov->iov_len);
    321    g_assert(ret == iov->iov_len);
    322    g_assert(iov_tmp == iov + 1);
    323    g_assert(iov_cnt_tmp == iov_cnt - 1);
    324    iov_free(iov, iov_cnt);
    325
    326    /* Discard within second element */
    327    iov_random(&iov, &iov_cnt);
    328    iov_tmp = iov;
    329    iov_cnt_tmp = iov_cnt;
    330    old_base = iov[1].iov_base;
    331    size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
    332    ret = iov_discard_front(&iov_tmp, &iov_cnt_tmp, size);
    333    g_assert(ret == size);
    334    g_assert(iov_tmp == iov + 1);
    335    g_assert(iov_cnt_tmp == iov_cnt - 1);
    336    g_assert(iov_tmp->iov_base == old_base + (size - iov->iov_len));
    337    iov_tmp->iov_base = old_base; /* undo before g_free() */
    338    iov_free(iov, iov_cnt);
    339}
    340
    341static void test_discard_front_undo(void)
    342{
    343    IOVDiscardUndo undo;
    344    struct iovec *iov;
    345    struct iovec *iov_tmp;
    346    struct iovec *iov_orig;
    347    unsigned int iov_cnt;
    348    unsigned int iov_cnt_tmp;
    349    size_t size;
    350
    351    /* Discard zero bytes */
    352    iov_random(&iov, &iov_cnt);
    353    iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
    354    iov_tmp = iov;
    355    iov_cnt_tmp = iov_cnt;
    356    iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, 0, &undo);
    357    iov_discard_undo(&undo);
    358    assert(iov_equals(iov, iov_orig, iov_cnt));
    359    g_free(iov_orig);
    360    iov_free(iov, iov_cnt);
    361
    362    /* Discard more bytes than vector size */
    363    iov_random(&iov, &iov_cnt);
    364    iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
    365    iov_tmp = iov;
    366    iov_cnt_tmp = iov_cnt;
    367    size = iov_size(iov, iov_cnt);
    368    iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size + 1, &undo);
    369    iov_discard_undo(&undo);
    370    assert(iov_equals(iov, iov_orig, iov_cnt));
    371    g_free(iov_orig);
    372    iov_free(iov, iov_cnt);
    373
    374    /* Discard entire vector */
    375    iov_random(&iov, &iov_cnt);
    376    iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
    377    iov_tmp = iov;
    378    iov_cnt_tmp = iov_cnt;
    379    size = iov_size(iov, iov_cnt);
    380    iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
    381    iov_discard_undo(&undo);
    382    assert(iov_equals(iov, iov_orig, iov_cnt));
    383    g_free(iov_orig);
    384    iov_free(iov, iov_cnt);
    385
    386    /* Discard within first element */
    387    iov_random(&iov, &iov_cnt);
    388    iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
    389    iov_tmp = iov;
    390    iov_cnt_tmp = iov_cnt;
    391    size = g_test_rand_int_range(1, iov->iov_len);
    392    iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
    393    iov_discard_undo(&undo);
    394    assert(iov_equals(iov, iov_orig, iov_cnt));
    395    g_free(iov_orig);
    396    iov_free(iov, iov_cnt);
    397
    398    /* Discard entire first element */
    399    iov_random(&iov, &iov_cnt);
    400    iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
    401    iov_tmp = iov;
    402    iov_cnt_tmp = iov_cnt;
    403    iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, iov->iov_len, &undo);
    404    iov_discard_undo(&undo);
    405    assert(iov_equals(iov, iov_orig, iov_cnt));
    406    g_free(iov_orig);
    407    iov_free(iov, iov_cnt);
    408
    409    /* Discard within second element */
    410    iov_random(&iov, &iov_cnt);
    411    iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
    412    iov_tmp = iov;
    413    iov_cnt_tmp = iov_cnt;
    414    size = iov->iov_len + g_test_rand_int_range(1, iov[1].iov_len);
    415    iov_discard_front_undoable(&iov_tmp, &iov_cnt_tmp, size, &undo);
    416    iov_discard_undo(&undo);
    417    assert(iov_equals(iov, iov_orig, iov_cnt));
    418    g_free(iov_orig);
    419    iov_free(iov, iov_cnt);
    420}
    421
    422static void test_discard_back(void)
    423{
    424    struct iovec *iov;
    425    unsigned int iov_cnt;
    426    unsigned int iov_cnt_tmp;
    427    void *old_base;
    428    size_t size;
    429    size_t ret;
    430
    431    /* Discard zero bytes */
    432    iov_random(&iov, &iov_cnt);
    433    iov_cnt_tmp = iov_cnt;
    434    ret = iov_discard_back(iov, &iov_cnt_tmp, 0);
    435    g_assert(ret == 0);
    436    g_assert(iov_cnt_tmp == iov_cnt);
    437    iov_free(iov, iov_cnt);
    438
    439    /* Discard more bytes than vector size */
    440    iov_random(&iov, &iov_cnt);
    441    iov_cnt_tmp = iov_cnt;
    442    size = iov_size(iov, iov_cnt);
    443    ret = iov_discard_back(iov, &iov_cnt_tmp, size + 1);
    444    g_assert(ret == size);
    445    g_assert(iov_cnt_tmp == 0);
    446    iov_free(iov, iov_cnt);
    447
    448    /* Discard entire vector */
    449    iov_random(&iov, &iov_cnt);
    450    iov_cnt_tmp = iov_cnt;
    451    size = iov_size(iov, iov_cnt);
    452    ret = iov_discard_back(iov, &iov_cnt_tmp, size);
    453    g_assert(ret == size);
    454    g_assert(iov_cnt_tmp == 0);
    455    iov_free(iov, iov_cnt);
    456
    457    /* Discard within last element */
    458    iov_random(&iov, &iov_cnt);
    459    iov_cnt_tmp = iov_cnt;
    460    old_base = iov[iov_cnt - 1].iov_base;
    461    size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
    462    ret = iov_discard_back(iov, &iov_cnt_tmp, size);
    463    g_assert(ret == size);
    464    g_assert(iov_cnt_tmp == iov_cnt);
    465    g_assert(iov[iov_cnt - 1].iov_base == old_base);
    466    iov_free(iov, iov_cnt);
    467
    468    /* Discard entire last element */
    469    iov_random(&iov, &iov_cnt);
    470    iov_cnt_tmp = iov_cnt;
    471    old_base = iov[iov_cnt - 1].iov_base;
    472    size = iov[iov_cnt - 1].iov_len;
    473    ret = iov_discard_back(iov, &iov_cnt_tmp, size);
    474    g_assert(ret == size);
    475    g_assert(iov_cnt_tmp == iov_cnt - 1);
    476    iov_free(iov, iov_cnt);
    477
    478    /* Discard within second-to-last element */
    479    iov_random(&iov, &iov_cnt);
    480    iov_cnt_tmp = iov_cnt;
    481    old_base = iov[iov_cnt - 2].iov_base;
    482    size = iov[iov_cnt - 1].iov_len +
    483           g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
    484    ret = iov_discard_back(iov, &iov_cnt_tmp, size);
    485    g_assert(ret == size);
    486    g_assert(iov_cnt_tmp == iov_cnt - 1);
    487    g_assert(iov[iov_cnt - 2].iov_base == old_base);
    488    iov_free(iov, iov_cnt);
    489}
    490
    491static void test_discard_back_undo(void)
    492{
    493    IOVDiscardUndo undo;
    494    struct iovec *iov;
    495    struct iovec *iov_orig;
    496    unsigned int iov_cnt;
    497    unsigned int iov_cnt_tmp;
    498    size_t size;
    499
    500    /* Discard zero bytes */
    501    iov_random(&iov, &iov_cnt);
    502    iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
    503    iov_cnt_tmp = iov_cnt;
    504    iov_discard_back_undoable(iov, &iov_cnt_tmp, 0, &undo);
    505    iov_discard_undo(&undo);
    506    assert(iov_equals(iov, iov_orig, iov_cnt));
    507    g_free(iov_orig);
    508    iov_free(iov, iov_cnt);
    509
    510    /* Discard more bytes than vector size */
    511    iov_random(&iov, &iov_cnt);
    512    iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
    513    iov_cnt_tmp = iov_cnt;
    514    size = iov_size(iov, iov_cnt);
    515    iov_discard_back_undoable(iov, &iov_cnt_tmp, size + 1, &undo);
    516    iov_discard_undo(&undo);
    517    assert(iov_equals(iov, iov_orig, iov_cnt));
    518    g_free(iov_orig);
    519    iov_free(iov, iov_cnt);
    520
    521    /* Discard entire vector */
    522    iov_random(&iov, &iov_cnt);
    523    iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
    524    iov_cnt_tmp = iov_cnt;
    525    size = iov_size(iov, iov_cnt);
    526    iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
    527    iov_discard_undo(&undo);
    528    assert(iov_equals(iov, iov_orig, iov_cnt));
    529    g_free(iov_orig);
    530    iov_free(iov, iov_cnt);
    531
    532    /* Discard within last element */
    533    iov_random(&iov, &iov_cnt);
    534    iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
    535    iov_cnt_tmp = iov_cnt;
    536    size = g_test_rand_int_range(1, iov[iov_cnt - 1].iov_len);
    537    iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
    538    iov_discard_undo(&undo);
    539    assert(iov_equals(iov, iov_orig, iov_cnt));
    540    g_free(iov_orig);
    541    iov_free(iov, iov_cnt);
    542
    543    /* Discard entire last element */
    544    iov_random(&iov, &iov_cnt);
    545    iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
    546    iov_cnt_tmp = iov_cnt;
    547    size = iov[iov_cnt - 1].iov_len;
    548    iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
    549    iov_discard_undo(&undo);
    550    assert(iov_equals(iov, iov_orig, iov_cnt));
    551    g_free(iov_orig);
    552    iov_free(iov, iov_cnt);
    553
    554    /* Discard within second-to-last element */
    555    iov_random(&iov, &iov_cnt);
    556    iov_orig = g_memdup(iov, sizeof(iov[0]) * iov_cnt);
    557    iov_cnt_tmp = iov_cnt;
    558    size = iov[iov_cnt - 1].iov_len +
    559           g_test_rand_int_range(1, iov[iov_cnt - 2].iov_len);
    560    iov_discard_back_undoable(iov, &iov_cnt_tmp, size, &undo);
    561    iov_discard_undo(&undo);
    562    assert(iov_equals(iov, iov_orig, iov_cnt));
    563    g_free(iov_orig);
    564    iov_free(iov, iov_cnt);
    565}
    566
    567int main(int argc, char **argv)
    568{
    569    g_test_init(&argc, &argv, NULL);
    570    g_test_rand_int();
    571    g_test_add_func("/basic/iov/from-to-buf", test_to_from_buf);
    572    g_test_add_func("/basic/iov/io", test_io);
    573    g_test_add_func("/basic/iov/discard-front", test_discard_front);
    574    g_test_add_func("/basic/iov/discard-back", test_discard_back);
    575    g_test_add_func("/basic/iov/discard-front-undo", test_discard_front_undo);
    576    g_test_add_func("/basic/iov/discard-back-undo", test_discard_back_undo);
    577    return g_test_run();
    578}