summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Kanis <kanis@comcard.de>2015-08-07 09:02:45 +0200
committerLars Kanis <lars@greiz-reinsdorf.de>2015-08-07 23:25:33 +0200
commit97e518404c2cdb20b3b3a13c64677da50215c519 (patch)
tree7f067a3d999c5f4f99f76275c0a866a640cb35cd
parentb035ca4e70dd696f4504622ea43eed0eb99fb5ba (diff)
downloadffi-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.c51
-rw-r--r--spec/ffi/fixtures/PipeHelper.h21
-rw-r--r--spec/ffi/fixtures/PipeHelperPosix.c41
-rw-r--r--spec/ffi/fixtures/PipeHelperWindows.c72
-rw-r--r--spec/ffi/function_spec.rb1
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) }