aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThanos Makatos <thanos.makatos@nutanix.com>2021-02-17 13:15:35 +0000
committerGitHub <noreply@github.com>2021-02-17 13:15:35 +0000
commit47a6fdbb8b3e459ba4f7815269bae0abf95d29a6 (patch)
treefadcb3199e69d75a29b707915612c1ba43d8fe4f
parente4e0ebde2c25f3011d20b6a2f1b1b8f510b09d9e (diff)
downloadlibvfio-user-47a6fdbb8b3e459ba4f7815269bae0abf95d29a6.zip
libvfio-user-47a6fdbb8b3e459ba4f7815269bae0abf95d29a6.tar.gz
libvfio-user-47a6fdbb8b3e459ba4f7815269bae0abf95d29a6.tar.bz2
add unit tests for handle dirty pages w/o DMA (#348)
Signed-off-by: Thanos Makatos <thanos.makatos@nutanix.com> Reviewed-by: Swapnil Ingle <swapnil.ingle@nutanix.com>
-rw-r--r--lib/libvfio-user.c4
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/mocks.c28
-rw-r--r--test/mocks.h6
-rw-r--r--test/unit-tests.c41
5 files changed, 78 insertions, 2 deletions
diff --git a/lib/libvfio-user.c b/lib/libvfio-user.c
index 053a2d4..ab6f4a3 100644
--- a/lib/libvfio-user.c
+++ b/lib/libvfio-user.c
@@ -621,7 +621,7 @@ out:
return ret;
}
-static int
+int
handle_dirty_pages(vfu_ctx_t *vfu_ctx, uint32_t size,
struct iovec **iovecs, size_t *nr_iovecs,
struct vfio_iommu_type1_dirty_bitmap *dirty_bitmap)
@@ -654,6 +654,8 @@ handle_dirty_pages(vfu_ctx_t *vfu_ctx, uint32_t size,
return ret;
}
+UNIT_TEST_SYMBOL(handle_dirty_pages);
+#define handle_dirty_pages __wrap_handle_dirty_pages
/*
* FIXME return value is messed up, sometimes we return -1 and set errno while
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a4f49ad..11e243d 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -55,6 +55,7 @@ target_link_libraries(unit-tests PUBLIC "-Wl,--wrap=free")
target_link_libraries(unit-tests PUBLIC "-Wl,--wrap=process_request")
target_link_libraries(unit-tests PUBLIC "-Wl,--wrap=bind")
target_link_libraries(unit-tests PUBLIC "-Wl,--wrap=listen")
+target_link_libraries(unit-tests PUBLIC "-Wl,--wrap=handle_dirty_pages")
enable_testing()
add_test(NAME unit-tests COMMAND unit-tests)
diff --git a/test/mocks.c b/test/mocks.c
index 303a6c2..80545e6 100644
--- a/test/mocks.c
+++ b/test/mocks.c
@@ -88,6 +88,9 @@ __wrap__dma_controller_do_remove_region(dma_controller_t *dma,
bool
__wrap_device_is_stopped(struct migration *migr)
{
+ if (!is_patched(device_is_stopped)) {
+ return __real_device_is_stopped(migr);
+ }
check_expected(migr);
return mock();
}
@@ -109,6 +112,11 @@ __wrap_exec_command(vfu_ctx_t *vfu_ctx, struct vfio_user_header *hdr,
int *nr_fds_out, struct iovec *_iovecs, struct iovec **iovecs,
size_t *nr_iovecs, bool *free_iovec_data)
{
+ if (!is_patched(exec_command)) {
+ return __real_exec_command(vfu_ctx, hdr, size, fds, nr_fds, fds_out,
+ nr_fds_out, _iovecs, iovecs, nr_iovecs,
+ free_iovec_data);
+ }
check_expected(vfu_ctx);
check_expected(hdr);
check_expected(size);
@@ -187,6 +195,23 @@ int __wrap_listen(int sockfd __attribute__((unused)),
return 0;
}
+int
+__wrap_handle_dirty_pages(vfu_ctx_t *vfu_ctx, uint32_t size,
+ struct iovec **iovecs, size_t *nr_iovecs,
+ struct vfio_iommu_type1_dirty_bitmap *dirty_bitmap)
+{
+ if (!is_patched(handle_dirty_pages)) {
+ return __real_handle_dirty_pages(vfu_ctx, size, iovecs, nr_iovecs,
+ dirty_bitmap);
+ }
+ check_expected(vfu_ctx);
+ check_expected(size);
+ check_expected(iovecs);
+ check_expected(nr_iovecs);
+ check_expected(dirty_bitmap);
+ return mock();
+}
+
/* FIXME should be something faster than unsorted array, look at tsearch(3). */
static struct function funcs[] = {
{.addr = &__wrap_dma_controller_add_region},
@@ -200,7 +225,8 @@ static struct function funcs[] = {
{.addr = &__wrap_free},
{.addr = &__wrap_process_request},
{.addr = &__wrap_bind},
- {.addr = &__wrap_listen}
+ {.addr = &__wrap_listen},
+ {.addr = &__wrap_handle_dirty_pages},
};
static struct function*
diff --git a/test/mocks.h b/test/mocks.h
index 97a23b7..67a67b5 100644
--- a/test/mocks.h
+++ b/test/mocks.h
@@ -29,6 +29,7 @@
*/
#include <stdbool.h>
+#include "private.h"
void unpatch_all(void);
@@ -36,4 +37,9 @@ void patch(void *fn);
bool is_patched(void *fn);
+int
+handle_dirty_pages(vfu_ctx_t *vfu_ctx, uint32_t size,
+ struct iovec **iovecs, size_t *nr_iovecs,
+ struct vfio_iommu_type1_dirty_bitmap *dirty_bitmap);
+
/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/test/unit-tests.c b/test/unit-tests.c
index eda8c49..4ab51e4 100644
--- a/test/unit-tests.c
+++ b/test/unit-tests.c
@@ -46,6 +46,7 @@
#include "pci.h"
#include "private.h"
#include "migration.h"
+#include "mocks.h"
#include "tran_sock.h"
static void
@@ -1390,6 +1391,45 @@ test_setup_migration_callbacks(void **state)
/* FIXME can't validate p->v->migration because it's a private strcut, need to move it out of lib/migration.c */
}
+static void
+test_dirty_pages_without_dma(UNUSED void **state)
+{
+ vfu_ctx_t vfu_ctx = { .migration = NULL };
+ struct vfio_user_header hdr = {
+ .cmd = VFIO_USER_DIRTY_PAGES,
+ .flags = {
+ .type = VFIO_USER_F_TYPE_COMMAND
+ },
+ .msg_size = sizeof hdr
+ };
+ size_t size = sizeof hdr;
+ int fds = 0;
+ struct iovec _iovecs = { 0 };
+ struct iovec *iovecs = NULL;
+ size_t nr_iovecs = 0;
+ bool free_iovec_data = false;
+ int r;
+
+ patch(handle_dirty_pages);
+
+ /* XXX w/o DMA controller */
+ r = exec_command(&vfu_ctx, &hdr, size, &fds, 0, NULL, NULL,
+ &_iovecs, &iovecs, &nr_iovecs, &free_iovec_data);
+ assert_int_equal(0, r);
+
+ /* XXX w/ DMA controller */
+ vfu_ctx.dma = (void*)0xdeadbeef;
+ expect_value(__wrap_handle_dirty_pages, vfu_ctx, &vfu_ctx);
+ expect_value(__wrap_handle_dirty_pages, size, 0);
+ expect_value(__wrap_handle_dirty_pages, iovecs, &iovecs);
+ expect_value(__wrap_handle_dirty_pages, nr_iovecs, &nr_iovecs);
+ expect_value(__wrap_handle_dirty_pages, dirty_bitmap, NULL);
+ will_return(__wrap_handle_dirty_pages, 0xabcd);
+ r = exec_command(&vfu_ctx, &hdr, size, &fds, 0, NULL, NULL,
+ &_iovecs, &iovecs, &nr_iovecs, &free_iovec_data);
+ assert_int_equal(0xabcd, r);
+}
+
int main(void)
{
const struct CMUnitTest tests[] = {
@@ -1440,6 +1480,7 @@ int main(void)
cmocka_unit_test_setup_teardown(test_setup_migration_callbacks,
setup_test_setup_migration_region,
teardown_test_setup_migration_region),
+ cmocka_unit_test_setup(test_dirty_pages_without_dma, setup),
};
return cmocka_run_group_tests(tests, NULL, NULL);