blob: bddab8eec15cee09a1adfe678d6f6642734d7677 [file]
/*
* Copyright (c) Meta Platforms, Inc. and affiliates
*
* Authors: Mattias Nissler <mnissler@meta.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Nutanix nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*/
#undef NDEBUG /* so assert() works in release builds */
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/eventfd.h>
#include <unistd.h>
#include "fd_cache.h"
/* See fd_cache.c */
extern bool kcmp_checked;
extern bool kcmp_available;
static int
make_tmpfile()
{
char template[] = "libvfio_user_fd_cache_tests_tmp_XXXXXX";
int fd;
fd = mkstemp(template);
assert(fd != -1);
assert(unlink(template) == 0);
return fd;
}
static void
test_tmpfile()
{
int fd1, fd2, fd3;
fd1 = make_tmpfile();
fd2 = dup(fd1);
assert(fd2 != -1);
assert(fd2 != fd1);
assert(fd_cache_is_same_file(fd1, fd2) == 0);
/* Confirm that the cache recognizes duplicated file descriptors. */
fd1 = fd_cache_get(fd1);
assert(fd1 != -1);
fd2 = fd_cache_get(fd2);
assert(fd2 != -1);
assert(fd1 == fd2);
/* Make sure an unrelated file descriptor doesn't get de-duplicated. */
fd3 = make_tmpfile();
assert(fd3 != -1);
fd3 = fd_cache_get(fd3);
assert(fd3 != -1);
assert(fd1 != fd3);
assert(fd_cache_put(&fd1) == 0);
assert(fd_cache_put(&fd2) == 0);
assert(fd_cache_put(&fd3) == 0);
}
static void
test_eventfd()
{
int fd1, fd2;
fd1 = eventfd(0, 0);
assert(fd1 != -1);
fd2 = dup(fd1);
assert(fd2 != -1);
assert(fd_cache_is_same_file(fd1, fd2) == 0);
fd1 = fd_cache_get(fd1);
assert(fd1 != -1);
fd2 = fd_cache_get(fd2);
assert(fd2 != -1);
/*
* If we don't have kcmp, file descriptors for non-regular files can't be
* de-duplicated reliably, so make sure the cache ignores them.
*/
if (kcmp_available) {
assert(fd1 == fd2);
} else {
assert(fd1 != fd2);
}
assert(fd_cache_put(&fd1) == 0);
assert(fd_cache_put(&fd2) == 0);
}
int
main(void)
{
test_tmpfile();
test_eventfd();
/* Enable fallback mode for the remaining test cases. */
kcmp_checked = true;
kcmp_available = false;
/* Run tests again, with the fallback force-enabled. */
test_tmpfile();
test_eventfd();
return 0;
}
/* ex: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab: */