Skip to content

Commit

Permalink
Merge pull request #407 from adierking/testfile
Browse files Browse the repository at this point in the history
tests: read from a temporary file instead of vi on non-Apple platforms
  • Loading branch information
ktopley-apple committed Nov 6, 2018
2 parents 6a5c6d8 + 50b8af2 commit 64a12c6
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 18 deletions.
4 changes: 3 additions & 1 deletion tests/dispatch_io.c
Expand Up @@ -240,14 +240,16 @@ test_io_stop(void) // rdar://problem/8250057
static void
test_io_read_write(void)
{
const char *path_in = "/usr/bin/vi";
char *path_in = dispatch_test_get_large_file();
char path_out[] = "/tmp/dispatchtest_io.XXXXXX";

int in = open(path_in, O_RDONLY);
if (in == -1) {
test_errno("open", errno, 0);
test_stop();
}
dispatch_test_release_large_file(path_in);
free(path_in);
struct stat sb;
if (fstat(in, &sb)) {
test_errno("fstat", errno, 0);
Expand Down
45 changes: 31 additions & 14 deletions tests/dispatch_io_net.c
Expand Up @@ -58,16 +58,14 @@ int
main(int argc, char** argv)
{
struct hostent *he;
int sockfd, clientfd;
int sockfd = -1, clientfd = -1;
int read_fd = -1, fd = -1;
struct sockaddr_in addr1, addr2, server;
socklen_t addr2len;
socklen_t addr1len;
pid_t clientid;

const char *path = "/usr/bin/vi";
int read_fd, fd;

if (argc == 2) {
if (argc == 3) {
// Client
dispatch_test_start(NULL);

Expand All @@ -94,11 +92,19 @@ main(int argc, char** argv)

// Read from the socket and compare the contents are what we expect

const char *path = argv[2];
fd = open(path, O_RDONLY);
if (fd == -1) {
test_errno("client-open", errno, 0);
test_stop();
}

// The reference file path given to us by the server was produced by
// dispatch_test_get_large_file(). It may point to a temporary file, and
// we are responsible for cleaning it up because we are the last to
// access it.
dispatch_test_release_large_file(path);

#ifdef F_NOCACHE
if (fcntl(fd, F_NOCACHE, 1)) {
test_errno("client-fcntl F_NOCACHE", errno, 0);
Expand Down Expand Up @@ -213,17 +219,28 @@ main(int argc, char** argv)
char port_str[10] = {};
snprintf(port_str, 10, " %d", addr1.sin_port);

char *arguments [3] = {};
// The client must read from the same test file as the server. It will
// unlink the file as soon as it can, so the server must open it before
// starting the client process.
char *path = dispatch_test_get_large_file();
read_fd = open(path, O_RDONLY);
if (read_fd == -1) {
test_errno("open", errno, 0);
goto stop_test;
}

char *arguments [4] = {};
arguments[0] = exec_filename;
arguments[1] = port_str;
arguments[2] = NULL;
arguments[2] = path;
arguments[3] = NULL;

#ifdef HAVE_POSIX_SPAWNP
int error;
if ((error = posix_spawnp(&clientid, exec_filename, NULL, NULL,
arguments, environ)) != 0) {
test_errno("Server-posix_spawnp()", error, 0);
test_stop();
goto stop_test;
}
#elif defined(__unix__)
clientid = fork();
Expand All @@ -245,15 +262,10 @@ main(int argc, char** argv)
clientfd = accept(sockfd, (struct sockaddr *)&addr2, &addr2len);
if(clientfd == -1) {
test_errno("Server-accept()", errno, 0);
test_stop();
goto stop_test;
}

fprintf(stderr, "Server accepted connection. Server now writing\n");
read_fd = open(path, O_RDONLY);
if (read_fd == -1) {
test_errno("open", errno, 0);
goto stop_test;
}
#ifdef F_NOCACHE
if (fcntl(read_fd, F_NOCACHE, 1)) {
test_errno("fcntl F_NOCACHE", errno, 0);
Expand Down Expand Up @@ -311,9 +323,14 @@ main(int argc, char** argv)
dispatch_release(g);
fprintf(stderr, "Shutting down server\n");
close(sockfd);
free(path);
test_stop();

stop_test:
if (path != NULL) {
dispatch_test_release_large_file(path);
free(path);
}
close(read_fd);
close(clientfd);
close(sockfd);
Expand Down
4 changes: 3 additions & 1 deletion tests/dispatch_read.c
Expand Up @@ -47,7 +47,7 @@ test_fin(void *cxt)
int
main(void)
{
const char *path = "/usr/bin/vi";
char *path = dispatch_test_get_large_file();
struct stat sb;

dispatch_test_start("Dispatch Source Read");
Expand All @@ -57,6 +57,8 @@ main(void)
perror(path);
exit(EXIT_FAILURE);
}
dispatch_test_release_large_file(path);
free(path);
if (fstat(infd, &sb) == -1) {
perror(path);
exit(EXIT_FAILURE);
Expand Down
4 changes: 3 additions & 1 deletion tests/dispatch_read2.c
Expand Up @@ -122,12 +122,14 @@ dispatch_read2(dispatch_fd_t fd,
static void
test_read(void)
{
const char *path = "/usr/bin/vi";
char *path = dispatch_test_get_large_file();
int fd = open(path, O_RDONLY);
if (fd == -1) {
test_errno("open", errno, 0);
test_stop();
}
dispatch_test_release_large_file(path);
free(path);
#ifdef F_NOCACHE
if (fcntl(fd, F_NOCACHE, 1)) {
test_errno("fcntl F_NOCACHE", errno, 0);
Expand Down
4 changes: 3 additions & 1 deletion tests/dispatch_select.c
Expand Up @@ -86,7 +86,7 @@ stage1(int stage)
void
stage2(void)
{
const char *path = "/usr/bin/vi";
char *path = dispatch_test_get_large_file();
struct stat sb;

int fd = open(path, O_RDONLY);
Expand All @@ -95,6 +95,8 @@ stage2(void)
perror(path);
exit(EXIT_FAILURE);
}
dispatch_test_release_large_file(path);
free(path);

if (!dispatch_test_check_evfilt_read_for_fd(fd)) {
test_skip("EVFILT_READ kevent not firing for test file");
Expand Down
77 changes: 77 additions & 0 deletions tests/dispatch_test.c
Expand Up @@ -82,6 +82,83 @@ dispatch_test_check_evfilt_read_for_fd(int fd)
#endif
}

char *
dispatch_test_get_large_file(void)
{
#if defined(__APPLE__)
return strdup("/usr/bin/vi");
#elif defined(__unix__)
// Depending on /usr/bin/vi being present is unreliable (especially on
// Android), so fill up a large-enough temp file with random bytes

const char *temp_dir = getenv("TMPDIR");
if (temp_dir == NULL || temp_dir[0] == '\0') {
temp_dir = "/tmp";
}
const char *const suffix = "/dispatch_test.XXXXXX";
size_t temp_dir_len = strlen(temp_dir);
size_t suffix_len = strlen(suffix);
char *path = malloc(temp_dir_len + suffix_len + 1);
assert(path != NULL);
memcpy(path, temp_dir, temp_dir_len);
memcpy(&path[temp_dir_len], suffix, suffix_len + 1);
int temp_fd = mkstemp(path);
if (temp_fd == -1) {
perror("mkstemp");
exit(EXIT_FAILURE);
}

const size_t file_size = 2 * 1024 * 1024;
char *file_buf = malloc(file_size);
assert(file_buf != NULL);

int urandom_fd = open("/dev/urandom", O_RDONLY);
if (urandom_fd == -1) {
perror("/dev/urandom");
exit(EXIT_FAILURE);
}
ssize_t num;
size_t pos = 0;
while (pos < file_size) {
num = read(urandom_fd, &file_buf[pos], file_size - pos);
if (num > 0) {
pos += (size_t)num;
} else if (num == -1 && errno != EINTR) {
perror("read");
exit(EXIT_FAILURE);
}
}
close(urandom_fd);

do {
num = write(temp_fd, file_buf, file_size);
} while (num == -1 && errno == EINTR);
if (num == -1) {
perror("write");
exit(EXIT_FAILURE);
}
assert(num == file_size);
close(temp_fd);
free(file_buf);
return path;
#else
#error "dispatch_test_get_large_file not implemented on this platform"
#endif
}

void
dispatch_test_release_large_file(const char *path)
{
#if defined(__APPLE__)
// The path is fixed to a system file - do nothing
(void)path;
#elif defined(__unix__)
unlink(path);
#else
#error "dispatch_test_release_large_file not implemented on this platform"
#endif
}

void
_dispatch_test_current(const char* file, long line, const char* desc, dispatch_queue_t expected)
{
Expand Down
3 changes: 3 additions & 0 deletions tests/dispatch_test.h
Expand Up @@ -39,6 +39,9 @@ void dispatch_test_start(const char* desc);

bool dispatch_test_check_evfilt_read_for_fd(int fd);

char *dispatch_test_get_large_file(void);
void dispatch_test_release_large_file(const char *path);

void _dispatch_test_current(const char* file, long line, const char* desc, dispatch_queue_t expected);
#define dispatch_test_current(a,b) _dispatch_test_current(__SOURCE_FILE__, __LINE__, a, b)

Expand Down

0 comments on commit 64a12c6

Please sign in to comment.