diff options
author | Lars Kanis <kanis@comcard.de> | 2015-08-07 09:02:45 +0200 |
---|---|---|
committer | Lars Kanis <lars@greiz-reinsdorf.de> | 2015-08-07 23:25:33 +0200 |
commit | 97e518404c2cdb20b3b3a13c64677da50215c519 (patch) | |
tree | 7f067a3d999c5f4f99f76275c0a866a640cb35cd | |
parent | b035ca4e70dd696f4504622ea43eed0eb99fb5ba (diff) | |
download | ffi-97e518404c2cdb20b3b3a13c64677da50215c519.tar.gz |
Add Windows port to blocking function test.
This separates pipe functions from test code as a
POSIX and a Windows implementation.
-rw-r--r-- | spec/ffi/fixtures/FunctionTest.c | 51 | ||||
-rw-r--r-- | spec/ffi/fixtures/PipeHelper.h | 21 | ||||
-rw-r--r-- | spec/ffi/fixtures/PipeHelperPosix.c | 41 | ||||
-rw-r--r-- | spec/ffi/fixtures/PipeHelperWindows.c | 72 | ||||
-rw-r--r-- | spec/ffi/function_spec.rb | 1 |
5 files changed, 151 insertions, 35 deletions
diff --git a/spec/ffi/fixtures/FunctionTest.c b/spec/ffi/fixtures/FunctionTest.c index 1c9a247..a37373a 100644 --- a/spec/ffi/fixtures/FunctionTest.c +++ b/spec/ffi/fixtures/FunctionTest.c @@ -11,10 +11,10 @@ #ifndef _WIN32 #include <unistd.h> #include <pthread.h> +#include <stdlib.h> #endif -#include <stdio.h> -#include <stdlib.h> +#include "PipeHelper.h" int testAdd(int a, int b) { @@ -27,56 +27,37 @@ int testFunctionAdd(int a, int b, int (*f)(int, int)) }; struct testBlockingData { - int pipe1[2]; - int pipe2[2]; + FD_TYPE pipe1[2]; + FD_TYPE pipe2[2]; }; struct testBlockingData *testBlockingOpen() { struct testBlockingData *self = malloc(sizeof(struct testBlockingData)); - if( pipe(self->pipe1) == -1 ) return NULL; - if( pipe(self->pipe2) == -1 ) return NULL; + if( pipeHelperCreatePipe(self->pipe1) == -1 ) return NULL; + if( pipeHelperCreatePipe(self->pipe2) == -1 ) return NULL; return self; } -char testBlockingReadChar(int fd) -{ - char d; - struct timeval timeout; - fd_set read_fds; - FD_ZERO(&read_fds); - FD_SET(fd, &read_fds); - - timeout.tv_sec = 10; // timeout after x seconds - timeout.tv_usec = 0; - - if(select(fd + 1, &read_fds, NULL, NULL, &timeout) <= 0) - return 0; - - if( read(fd, &d, 1) != 1) - return 0; - return d; -} - char testBlockingWR(struct testBlockingData *self, char c) { - if( write(self->pipe1[1], &c, 1) != 1) - return 0; - return testBlockingReadChar(self->pipe2[0]); + if( pipeHelperWriteChar(self->pipe1[1], c) != 1) + return 0; + return pipeHelperReadChar(self->pipe2[0], 10); } char testBlockingRW(struct testBlockingData *self, char c) { - char d = testBlockingReadChar(self->pipe1[0]); - if( write(self->pipe2[1], &c, 1) != 1) - return 0; + char d = pipeHelperReadChar(self->pipe1[0], 10); + if( pipeHelperWriteChar(self->pipe2[1], c) != 1) + return 0; return d; } void testBlockingClose(struct testBlockingData *self) { - close(self->pipe1[0]); - close(self->pipe1[1]); - close(self->pipe2[0]); - close(self->pipe2[1]); + pipeHelperClosePipe(self->pipe1[0]); + pipeHelperClosePipe(self->pipe1[1]); + pipeHelperClosePipe(self->pipe2[0]); + pipeHelperClosePipe(self->pipe2[1]); free(self); } diff --git a/spec/ffi/fixtures/PipeHelper.h b/spec/ffi/fixtures/PipeHelper.h new file mode 100644 index 0000000..4a02111 --- /dev/null +++ b/spec/ffi/fixtures/PipeHelper.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 Lars Kanis. All rights reserved. + * + * For licensing, see LICENSE.SPECS + */ + +#ifndef PIPEHELPER_H +#define PIPEHELPER_H + +#ifdef _WIN32 +#define FD_TYPE HANDLE +#else +#define FD_TYPE int +#endif + +int pipeHelperCreatePipe(FD_TYPE pipefd[2]); +char pipeHelperReadChar(FD_TYPE fd, int timeout); +int pipeHelperWriteChar(FD_TYPE fd, char c); +void pipeHelperClosePipe(FD_TYPE fd); + +#endif diff --git a/spec/ffi/fixtures/PipeHelperPosix.c b/spec/ffi/fixtures/PipeHelperPosix.c new file mode 100644 index 0000000..c1252b4 --- /dev/null +++ b/spec/ffi/fixtures/PipeHelperPosix.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015 Lars Kanis. All rights reserved. + * + * For licensing, see LICENSE.SPECS + */ + +#ifndef _WIN32 +#include <unistd.h> +#include <sys/time.h> +#include "PipeHelper.h" + +int pipeHelperCreatePipe(FD_TYPE pipefd[2]) +{ + return pipe(pipefd); +} + +char pipeHelperReadChar(FD_TYPE fd, int timeout) +{ + char d; + struct timeval time = {timeout, 0}; // timeout after x seconds + fd_set read_fds; + FD_ZERO(&read_fds); + FD_SET(fd, &read_fds); + + if(select(fd + 1, &read_fds, NULL, NULL, &time) <= 0) + return 0; + + if( read(fd, &d, 1) != 1) + return 0; + return d; +} + +int pipeHelperWriteChar(FD_TYPE fd, char c) +{ + return write(fd, &c, 1); +} + +void pipeHelperClosePipe(FD_TYPE fd) { + close(fd); +} +#endif diff --git a/spec/ffi/fixtures/PipeHelperWindows.c b/spec/ffi/fixtures/PipeHelperWindows.c new file mode 100644 index 0000000..470bacc --- /dev/null +++ b/spec/ffi/fixtures/PipeHelperWindows.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2007 Wayne Meissner. All rights reserved. + * + * For licensing, see LICENSE.SPECS + */ + +#ifdef _WIN32 +#include <windows.h> +#include "PipeHelper.h" + +int pipeHelperCreatePipe(FD_TYPE pipefd[2]) +{ + char name[ MAX_PATH ]; + static int pipe_idx = 0; + sprintf( name, "\\\\.\\Pipe\\pipeHelper-%u-%i", + (unsigned int)GetCurrentProcessId(), pipe_idx++ ); + + pipefd[0] = CreateNamedPipe( name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_BYTE | PIPE_WAIT, + 1, // Number of pipes + 5, // Out buffer size + 5, // In buffer size + 60 * 1000, // Timeout in ms + NULL ); + if(pipefd[0] == INVALID_HANDLE_VALUE) + return -1; + + pipefd[1] = CreateFile( name, GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(pipefd[1] == INVALID_HANDLE_VALUE) { + CloseHandle( pipefd[0] ); + return -1; + } + return 0; +} + +char pipeHelperReadChar(FD_TYPE fd, int timeout) +{ + char d; + OVERLAPPED ovl; + ZeroMemory(&ovl, sizeof(ovl)); + ovl.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if( ReadFile(fd, &d, 1, NULL, &ovl) == 0) { + DWORD recvd = 0;; + DWORD res = WaitForSingleObject(ovl.hEvent, timeout * 1000); + if( res != WAIT_OBJECT_0 ) { + CloseHandle(ovl.hEvent); + return 0; + } + if( GetOverlappedResult(fd, &ovl, &recvd, FALSE) == 0 ) { + CloseHandle(ovl.hEvent); + return 0; + } + } + CloseHandle(ovl.hEvent); + return d; +} + +int pipeHelperWriteChar(FD_TYPE fd, char c) +{ + DWORD written; + return WriteFile(fd, &c, 1, &written, NULL) == 0 ? 0 : 1; +} + +void pipeHelperClosePipe(FD_TYPE fd) { + CloseHandle(fd); +} + +#endif diff --git a/spec/ffi/function_spec.rb b/spec/ffi/function_spec.rb index 8dbbc72..dd4d2ea 100644 --- a/spec/ffi/function_spec.rb +++ b/spec/ffi/function_spec.rb @@ -68,6 +68,7 @@ describe FFI::Function do fpWR = FFI::Function.new(:char, [ :pointer, :char ], @libtest.find_function('testBlockingWR'), :blocking => true) fpClose = FFI::Function.new(:void, [ :pointer ], @libtest.find_function('testBlockingClose')) handle = fpOpen.call + expect(handle).not_to be_null begin thWR = Thread.new { fpWR.call(handle, 63) } thRW = Thread.new { fpRW.call(handle, 64) } |