Merge pull request #469 from compnerd/size
event: create a typedef for the unote ident type
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f530f04..ba0d7af 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -43,7 +43,11 @@
target_compile_definitions(bsdtests
PUBLIC
_CRT_NONSTDC_NO_WARNINGS
- _CRT_SECURE_NO_WARNINGS)
+ _CRT_SECURE_NO_WARNINGS
+ _USE_MATH_DEFINES)
+ target_link_libraries(bsdtests
+ PUBLIC
+ bcrypt)
endif ()
add_executable(bsdtestharness
@@ -165,8 +169,11 @@
pingpong
drift
readsync
- cascade
- io)
+ cascade)
+ if(NOT WIN32)
+ # Not ported to Windows yet
+ list(APPEND DISPATCH_C_TESTS io)
+ endif()
# an oddball; dispatch_priority.c compiled with -DUSE_SET_TARGET_QUEUE=1
add_unit_test(dispatch_priority2 SOURCES dispatch_priority.c)
target_compile_options(dispatch_priority2 PRIVATE -DUSE_SET_TARGET_QUEUE=1)
@@ -192,7 +199,9 @@
add_unit_test(dispatch_plusplus SOURCES dispatch_plusplus.cpp)
# test-specific link options
-if(NOT WIN32)
+if(WIN32)
+ target_link_libraries(dispatch_io_net PRIVATE WS2_32)
+else()
target_link_libraries(dispatch_group PRIVATE m)
target_link_libraries(dispatch_timer_short PRIVATE m)
endif()
diff --git a/tests/dispatch_apply.c b/tests/dispatch_apply.c
index d77d8bb..93c03b9 100644
--- a/tests/dispatch_apply.c
+++ b/tests/dispatch_apply.c
@@ -22,6 +22,11 @@
#include <stdio.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
+#ifdef __ANDROID__
+#include <linux/sysctl.h>
+#else
+#include <sys/sysctl.h>
+#endif /* __ANDROID__ */
#endif
#include <stdlib.h>
#include <assert.h>
@@ -29,11 +34,6 @@
#include <libkern/OSAtomic.h>
#endif
#include <sys/types.h>
-#ifdef __ANDROID__
-#include <linux/sysctl.h>
-#else
-#include <sys/sysctl.h>
-#endif /* __ANDROID__ */
#include <bsdtests.h>
#include "dispatch_test.h"
@@ -80,6 +80,10 @@
uint32_t activecpu;
#ifdef __linux__
activecpu = (uint32_t)sysconf(_SC_NPROCESSORS_ONLN);
+#elif defined(_WIN32)
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ activecpu = si.dwNumberOfProcessors;
#else
size_t s = sizeof(activecpu);
sysctlbyname("hw.activecpu", &activecpu, &s, NULL, 0);
diff --git a/tests/dispatch_concur.c b/tests/dispatch_concur.c
index 960f565..74b6c0c 100644
--- a/tests/dispatch_concur.c
+++ b/tests/dispatch_concur.c
@@ -20,17 +20,17 @@
#include <dispatch/dispatch.h>
#include <dispatch/private.h>
-#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
-#include <unistd.h>
-#endif
#include <stdlib.h>
#include <stdio.h>
+#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <sys/types.h>
+#include <unistd.h>
#ifdef __ANDROID__
#include <linux/sysctl.h>
#else
#include <sys/sysctl.h>
#endif /* __ANDROID__ */
+#endif
#include <bsdtests.h>
#include "dispatch_test.h"
@@ -234,6 +234,10 @@
#ifdef __linux__
activecpu = (uint32_t)sysconf(_SC_NPROCESSORS_ONLN);
+#elif defined(_WIN32)
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ activecpu = si.dwNumberOfProcessors;
#else
size_t s = sizeof(activecpu);
sysctlbyname("hw.activecpu", &activecpu, &s, NULL, 0);
diff --git a/tests/dispatch_io_net.c b/tests/dispatch_io_net.c
index 83b375e..1e722a8 100644
--- a/tests/dispatch_io_net.c
+++ b/tests/dispatch_io_net.c
@@ -21,17 +21,21 @@
#include <stdio.h>
#include <stdlib.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+#include <netdb.h>
+#include <netinet/in.h>
+#include <spawn.h>
+#include <sys/socket.h>
+#include <sys/param.h>
#include <unistd.h>
+#elif defined(_WIN32)
+#include <WinSock2.h>
+#include <WS2tcpip.h>
+#include <Windows.h>
#endif
#include <errno.h>
-#include <netdb.h>
#include <sys/types.h>
-#include <sys/param.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
#include <fcntl.h>
#include <sys/stat.h>
-#include <spawn.h>
#ifdef __APPLE__
#include <crt_externs.h>
#include <mach-o/dyld.h>
@@ -41,7 +45,9 @@
#include "dispatch_test.h"
#include <dispatch/dispatch.h>
+#if !defined(_WIN32)
extern char **environ;
+#endif
#ifndef DISPATCHTEST_IO
#if DISPATCH_API_VERSION >= 20100226 && DISPATCH_API_VERSION != 20101110
@@ -49,22 +55,39 @@
#endif
#endif
-#if defined(__linux__) || defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__) || defined(_WIN32)
#define _NSGetExecutablePath(ef,bs) (*(bs)=(size_t)snprintf(ef,*(bs),"%s",argv[0]),0)
#endif
+#if defined(_WIN32)
+typedef USHORT in_port_t;
+#endif
+
+#if !defined(_WIN32)
+#define closesocket(x) close(x)
+#endif
+
#if DISPATCHTEST_IO
int
main(int argc, char** argv)
{
struct hostent *he;
int sockfd = -1, clientfd = -1;
- int read_fd = -1, fd = -1;
+ dispatch_fd_t read_fd = -1, fd = -1;
struct sockaddr_in addr1, addr2, server;
socklen_t addr2len;
socklen_t addr1len;
pid_t clientid;
+#if defined(_WIN32)
+ WSADATA wsa;
+ int err = WSAStartup(MAKEWORD(2, 2), &wsa);
+ if (err != 0) {
+ fprintf(stderr, "WSAStartup failed with %d\n", err);
+ test_stop();
+ }
+#endif
+
if (argc == 3) {
// Client
dispatch_test_start(NULL);
@@ -93,7 +116,7 @@
// Read from the socket and compare the contents are what we expect
const char *path = argv[2];
- fd = open(path, O_RDONLY);
+ fd = dispatch_test_fd_open(path, O_RDONLY);
if (fd == -1) {
test_errno("client-open", errno, 0);
test_stop();
@@ -114,12 +137,8 @@
// investigate what the impact of lack of file cache disabling has
// for this test
#endif
- struct stat sb;
- if (fstat(fd, &sb)) {
- test_errno("client-fstat", errno, 0);
- test_stop();
- }
- size_t size = (size_t)sb.st_size;
+ size_t size = (size_t)dispatch_test_fd_lseek(fd, 0, SEEK_END);
+ dispatch_test_fd_lseek(fd, 0, SEEK_SET);
__block dispatch_data_t g_d1 = dispatch_data_empty;
__block dispatch_data_t g_d2 = dispatch_data_empty;
@@ -167,8 +186,8 @@
memcmp(dict_contig_buf, socket_contig_buf,
MIN(dict_contig_size, socket_contig_size)), 0);
- close(fd);
- close(sockfd);
+ dispatch_test_fd_close(fd);
+ closesocket(sockfd);
dispatch_release(g_d1);
dispatch_release(g_d2);
dispatch_release(dict_data);
@@ -223,7 +242,7 @@
// 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);
+ read_fd = dispatch_test_fd_open(path, O_RDONLY);
if (read_fd == -1) {
test_errno("open", errno, 0);
goto stop_test;
@@ -242,6 +261,23 @@
test_errno("Server-posix_spawnp()", error, 0);
goto stop_test;
}
+#elif defined(_WIN32)
+ WCHAR *cmdline = argv_to_command_line(arguments);
+ if (!cmdline) {
+ fprintf(stderr, "argv_to_command_line() failed\n");
+ test_stop();
+ }
+ STARTUPINFOW si = {.cb = sizeof(si)};
+ PROCESS_INFORMATION pi;
+ BOOL created = CreateProcessW(NULL, cmdline, NULL, NULL, FALSE, 0, NULL,
+ NULL, &si, &pi);
+ DWORD error = GetLastError();
+ free(cmdline);
+ if (!created) {
+ print_winapi_error("CreateProcessW", error);
+ test_stop();
+ }
+ clientid = (pid_t)pi.dwProcessId;
#elif defined(__unix__)
clientid = fork();
if (clientid == -1) {
@@ -275,12 +311,8 @@
// investigate what the impact of lack of file cache disabling has
// for this test
#endif
- struct stat sb;
- if (fstat(read_fd, &sb)) {
- test_errno("fstat", errno, 0);
- goto stop_test;
- }
- size_t size = (size_t)sb.st_size;
+ size_t size = (size_t)dispatch_test_fd_lseek(read_fd, 0, SEEK_END);
+ dispatch_test_fd_lseek(read_fd, 0, SEEK_SET);
dispatch_group_t g = dispatch_group_create();
dispatch_group_enter(g);
@@ -294,9 +326,9 @@
// convenience method handlers should only be called once
if (dispatch_data_get_size(d)!= size) {
fprintf(stderr, "Reading of data didn't complete\n");
- close(read_fd);
- close(clientfd);
- close(sockfd);
+ dispatch_test_fd_close(read_fd);
+ closesocket(clientfd);
+ closesocket(sockfd);
test_stop();
}
dispatch_group_enter(g);
@@ -308,21 +340,21 @@
if (remaining) {
fprintf(stderr, "Server-dispatch_write() incomplete .. "
"%zu bytes\n", dispatch_data_get_size(remaining));
- close(read_fd);
- close(clientfd);
- close(sockfd);
+ dispatch_test_fd_close(read_fd);
+ closesocket(clientfd);
+ closesocket(sockfd);
test_stop();
}
- close(clientfd); // Sending the client EOF
+ closesocket(clientfd); // Sending the client EOF
dispatch_group_leave(g);
});
- close(read_fd);
+ dispatch_test_fd_close(read_fd);
dispatch_group_leave(g);
});
test_group_wait(g);
dispatch_release(g);
fprintf(stderr, "Shutting down server\n");
- close(sockfd);
+ closesocket(sockfd);
free(path);
test_stop();
@@ -331,9 +363,9 @@
dispatch_test_release_large_file(path);
free(path);
}
- close(read_fd);
- close(clientfd);
- close(sockfd);
+ dispatch_test_fd_close(read_fd);
+ closesocket(clientfd);
+ closesocket(sockfd);
test_stop();
}
}
diff --git a/tests/dispatch_priority.c b/tests/dispatch_priority.c
index c500e87..d1a9e18 100644
--- a/tests/dispatch_priority.c
+++ b/tests/dispatch_priority.c
@@ -23,6 +23,11 @@
#include <dispatch/private.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
+#ifdef __ANDROID__
+#include <linux/sysctl.h>
+#else
+#include <sys/sysctl.h>
+#endif /* __ANDROID__ */
#endif
#include <stdlib.h>
#include <assert.h>
@@ -30,11 +35,6 @@
#include <TargetConditionals.h>
#endif
#include <sys/types.h>
-#ifdef __ANDROID__
-#include <linux/sysctl.h>
-#else
-#include <sys/sysctl.h>
-#endif /* __ANDROID__ */
#include <bsdtests.h>
#include "dispatch_test.h"
@@ -85,6 +85,10 @@
dispatch_once(&pred, ^{
#ifdef __linux__
n = (int)sysconf(_SC_NPROCESSORS_CONF);
+#elif defined(_WIN32)
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ n = (int)si.dwNumberOfProcessors;
#else
size_t l = sizeof(n);
int rc = sysctlbyname("hw.ncpu", &n, &l, NULL, 0);
diff --git a/tests/dispatch_read.c b/tests/dispatch_read.c
index b891d2e..23545b5 100644
--- a/tests/dispatch_read.c
+++ b/tests/dispatch_read.c
@@ -18,7 +18,6 @@
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
-#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
#include <fcntl.h>
@@ -48,27 +47,26 @@
main(void)
{
char *path = dispatch_test_get_large_file();
- struct stat sb;
dispatch_test_start("Dispatch Source Read");
- int infd = open(path, O_RDONLY);
+ dispatch_fd_t infd = dispatch_test_fd_open(path, O_RDONLY);
if (infd == -1) {
perror(path);
exit(EXIT_FAILURE);
}
dispatch_test_release_large_file(path);
free(path);
- if (fstat(infd, &sb) == -1) {
- perror(path);
- exit(EXIT_FAILURE);
- }
- bytes_total = (size_t)sb.st_size;
+ bytes_total = (size_t)dispatch_test_fd_lseek(infd, 0, SEEK_END);
+ dispatch_test_fd_lseek(infd, 0, SEEK_SET);
+
+#if !defined(_WIN32)
if (fcntl(infd, F_SETFL, O_NONBLOCK) != 0) {
perror(path);
exit(EXIT_FAILURE);
}
+#endif
if (!dispatch_test_check_evfilt_read_for_fd(infd)) {
test_skip("EVFILT_READ kevent not firing for test file");
@@ -88,11 +86,11 @@
test_double_less_than_or_equal("estimated", estimated, bytes_total - bytes_read);
const ssize_t bufsiz = 1024*500; // 500 KB buffer
static char buffer[1024*500]; // 500 KB buffer
- ssize_t actual = read(infd, buffer, sizeof(buffer));
+ ssize_t actual = dispatch_test_fd_read(infd, buffer, sizeof(buffer));
bytes_read += (size_t)actual;
printf("bytes read: %zd\n", actual);
if (actual < bufsiz) {
- actual = read(infd, buffer, sizeof(buffer));
+ actual = dispatch_test_fd_read(infd, buffer, sizeof(buffer));
bytes_read += (size_t)actual;
// confirm EOF condition
test_long("EOF", actual, 0);
@@ -102,7 +100,7 @@
dispatch_source_set_cancel_handler(reader, ^{
test_sizet("Bytes read", bytes_read, bytes_total);
- int res = close(infd);
+ int res = dispatch_test_fd_close(infd);
test_errno("close", res == -1 ? errno : 0, 0);
dispatch_release(reader);
});
diff --git a/tests/dispatch_read2.c b/tests/dispatch_read2.c
index d20c758..0e45359 100644
--- a/tests/dispatch_read2.c
+++ b/tests/dispatch_read2.c
@@ -20,16 +20,16 @@
#include <sys/stat.h>
#include <sys/types.h>
-#include <sys/param.h>
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
+#include <fts.h>
+#include <sys/param.h>
#include <unistd.h>
#endif
#include <errno.h>
-#include <fts.h>
#ifdef __APPLE__
#include <mach/mach.h>
#include <mach/mach_time.h>
@@ -68,10 +68,12 @@
dispatch_queue_t queue,
void (^handler)(dispatch_data_t d, int error))
{
+#if !defined(_WIN32)
if (fcntl(fd, F_SETFL, O_NONBLOCK) != 0) {
test_errno("fcntl O_NONBLOCK", errno, 0);
test_stop();
}
+#endif
dispatch_source_t reader = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ,
(uintptr_t)fd, 0, queue);
test_ptr_notnull("reader", reader);
@@ -82,16 +84,28 @@
dispatch_source_set_event_handler(reader, ^{
const ssize_t bufsiz = 1024*512; // 512KB buffer
char *buffer = NULL;
+#if defined(_WIN32)
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ size_t pagesize = (size_t)si.dwPageSize;
+ buffer = _aligned_malloc(bufsiz, pagesize);
+#else
size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
posix_memalign((void **)&buffer, pagesize, bufsiz);
- ssize_t actual = read(fd, buffer, bufsiz);
+#endif
+ ssize_t actual = dispatch_test_fd_read(fd, buffer, bufsiz);
if (actual == -1) {
err = errno;
}
if (actual > 0) {
bytes_read += (size_t)actual;
+#if defined(_WIN32)
+ dispatch_data_t tmp_data = dispatch_data_create(buffer, (size_t)actual,
+ NULL, ^{ _aligned_free(buffer); });
+#else
dispatch_data_t tmp_data = dispatch_data_create(buffer, (size_t)actual,
NULL, DISPATCH_DATA_DESTRUCTOR_FREE);
+#endif
dispatch_data_t concat = dispatch_data_create_concat(data,tmp_data);
dispatch_release(tmp_data);
dispatch_release(data);
@@ -100,7 +114,7 @@
// If we reached EOF or we read as much we were asked to.
if (actual < bufsiz || bytes_read >= length) {
char foo[2];
- actual = read(fd, foo, 2);
+ actual = dispatch_test_fd_read(fd, foo, 2);
bytes_read += (size_t)actual;
// confirm EOF condition
test_long("EOF", actual, 0);
@@ -123,7 +137,7 @@
test_read(void)
{
char *path = dispatch_test_get_large_file();
- int fd = open(path, O_RDONLY);
+ dispatch_fd_t fd = dispatch_test_fd_open(path, O_RDONLY);
if (fd == -1) {
test_errno("open", errno, 0);
test_stop();
@@ -139,12 +153,8 @@
// investigate what the impact of lack of file cache disabling has
// for this test
#endif
- struct stat sb;
- if (fstat(fd, &sb)) {
- test_errno("fstat", errno, 0);
- test_stop();
- }
- size_t size = (size_t)sb.st_size;
+ size_t size = (size_t)dispatch_test_fd_lseek(fd, 0, SEEK_END);
+ dispatch_test_fd_lseek(fd, 0, SEEK_SET);
dispatch_group_t g = dispatch_group_create();
void (^b)(dispatch_data_t, int) = ^(dispatch_data_t d, int error) {
test_errno("read error", error, 0);
@@ -158,7 +168,7 @@
if (contig_size) {
// Validate the copied buffer is similar to what we expect
char *buf = (char*)malloc(size);
- pread(fd, buf, size, 0);
+ dispatch_test_fd_pread(fd, buf, size, 0);
test_long("dispatch data contents", memcmp(buf, contig_buf,
size), 0);
free(buf);
@@ -170,7 +180,7 @@
dispatch_group_enter(g);
dispatch_read(fd, SIZE_MAX, dispatch_get_global_queue(0, 0), b); // rdar://problem/7795794
test_group_wait(g);
- lseek(fd, 0, SEEK_SET);
+ dispatch_test_fd_lseek(fd, 0, SEEK_SET);
if (dispatch_test_check_evfilt_read_for_fd(fd)) {
dispatch_group_enter(g);
dispatch_read2(fd, size, dispatch_get_global_queue(0,0), b);
@@ -179,22 +189,39 @@
test_skip("EVFILT_READ kevent not firing for test file");
}
dispatch_release(g);
- close(fd);
+ dispatch_test_fd_close(fd);
}
static void
test_read_write(void)
{
- const char *path_in = "/dev/urandom";
- char path_out[] = "/tmp/dispatchtest_io.XXXXXX";
- const size_t siz_in = 10240;
+#if defined(_WIN32)
+ char *path_in = dispatch_test_get_large_file();
+ char path_out[] = "dispatchtest_io.XXXXXX";
- int in = open(path_in, O_RDONLY);
+ dispatch_fd_t in = dispatch_test_fd_open(path_in, O_RDONLY);
if (in == -1) {
test_errno("open", errno, 0);
test_stop();
}
- int out = mkstemp(path_out);
+ dispatch_test_release_large_file(path_in);
+ free(path_in);
+
+ size_t siz_in = (size_t)dispatch_test_fd_lseek(in, 0, SEEK_END);
+ dispatch_test_fd_lseek(in, 0, SEEK_SET);
+#else
+ const char *path_in = "/dev/urandom";
+ char path_out[] = "/tmp/dispatchtest_io.XXXXXX";
+ const size_t siz_in = 10240;
+
+ dispatch_fd_t in = dispatch_test_fd_open(path_in, O_RDONLY);
+ if (in == -1) {
+ test_errno("open", errno, 0);
+ test_stop();
+ }
+#endif
+
+ dispatch_fd_t out = mkstemp(path_out);
if (out == -1) {
test_errno("mkstemp", errno, 0);
test_stop();
@@ -203,6 +230,7 @@
test_errno("unlink", errno, 0);
test_stop();
}
+
dispatch_queue_t q = dispatch_get_global_queue(0,0);
dispatch_group_t g = dispatch_group_create();
dispatch_group_enter(g);
@@ -212,7 +240,7 @@
test_errno("dispatch_read", err_in, 0);
test_stop();
}
- close(in);
+ dispatch_test_fd_close(in);
size_t siz_out = dispatch_data_get_size(data_in);
test_sizet("read size", siz_out, siz_in);
dispatch_retain(data_in);
@@ -222,14 +250,14 @@
test_errno("dispatch_write", err_out, 0);
test_stop();
}
- lseek(out, 0, SEEK_SET);
+ dispatch_test_fd_lseek(out, 0, SEEK_SET);
dispatch_read(out, siz_out, q,
^(dispatch_data_t cmp, int err_cmp) {
if (err_cmp) {
test_errno("dispatch_read", err_cmp, 0);
test_stop();
}
- close(out);
+ dispatch_test_fd_close(out);
size_t siz_cmp = dispatch_data_get_size(cmp);
test_sizet("readback size", siz_cmp, siz_out);
const void *data_buf, *cmp_buf;
@@ -252,17 +280,32 @@
static void
test_read_writes(void) // <rdar://problem/7785143>
{
- const char *path_in = "/dev/urandom";
- char path_out[] = "/tmp/dispatchtest_io.XXXXXX";
const size_t chunks_out = 320;
const size_t siz_chunk = 32, siz_in = siz_chunk * chunks_out;
- int in = open(path_in, O_RDONLY);
+#if defined(_WIN32)
+ char *path_in = dispatch_test_get_large_file();
+ char path_out[] = "dispatchtest_io.XXXXXX";
+
+ dispatch_fd_t in = dispatch_test_fd_open(path_in, O_RDONLY);
if (in == -1) {
test_errno("open", errno, 0);
test_stop();
}
- int out = mkstemp(path_out);
+ dispatch_test_release_large_file(path_in);
+ free(path_in);
+#else
+ const char *path_in = "/dev/urandom";
+ char path_out[] = "/tmp/dispatchtest_io.XXXXXX";
+
+ dispatch_fd_t in = dispatch_test_fd_open(path_in, O_RDONLY);
+ if (in == -1) {
+ test_errno("open", errno, 0);
+ test_stop();
+ }
+#endif
+
+ dispatch_fd_t out = mkstemp(path_out);
if (out == -1) {
test_errno("mkstemp", errno, 0);
test_stop();
@@ -271,6 +314,7 @@
test_errno("unlink", errno, 0);
test_stop();
}
+
dispatch_queue_t q = dispatch_get_global_queue(0,0);
dispatch_group_t g = dispatch_group_create();
dispatch_group_enter(g);
@@ -281,7 +325,7 @@
test_errno("dispatch_read", err_in, 0);
test_stop();
}
- close(in);
+ dispatch_test_fd_close(in);
siz_out = dispatch_data_get_size(data_in);
test_sizet("read size", siz_out, siz_in);
dispatch_retain(data_in);
@@ -311,14 +355,14 @@
});
test_group_wait(g);
dispatch_group_enter(g);
- lseek(out, 0, SEEK_SET);
+ dispatch_test_fd_lseek(out, 0, SEEK_SET);
dispatch_read(out, siz_in, q,
^(dispatch_data_t cmp, int err_cmp) {
if (err_cmp) {
test_errno("dispatch_read", err_cmp, 0);
test_stop();
}
- close(out);
+ dispatch_test_fd_close(out);
size_t siz_cmp = dispatch_data_get_size(cmp);
test_sizet("readback size", siz_cmp, siz_out);
const void *data_buf, *cmp_buf;
@@ -336,6 +380,7 @@
dispatch_release(g);
}
+#if !defined(_WIN32)
static void
test_writes_reads_eagain(void) // rdar://problem/8333366
{
@@ -395,6 +440,7 @@
Block_release(b);
dispatch_release(g);
}
+#endif
#endif // DISPATCHTEST_IO
@@ -408,8 +454,10 @@
test_read();
test_read_write();
test_read_writes();
+#if !defined(_WIN32)
test_writes_reads_eagain();
#endif
+#endif
test_fin(NULL);
});
dispatch_main();
diff --git a/tests/dispatch_readsync.c b/tests/dispatch_readsync.c
index 293387a..c543875 100644
--- a/tests/dispatch_readsync.c
+++ b/tests/dispatch_readsync.c
@@ -23,12 +23,12 @@
#include <stdlib.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
-#endif
#ifdef __ANDROID__
#include <linux/sysctl.h>
#else
#include <sys/sysctl.h>
#endif /* __ANDROID__ */
+#endif
#include <assert.h>
#include <bsdtests.h>
@@ -143,6 +143,11 @@
activecpu = (uint32_t)sysconf(_SC_NPROCESSORS_ONLN);
// don't want to parse /proc/sys/kernel/threads-max
wq_max_threads = activecpu * NTHREADS + 2;
+#elif defined(_WIN32)
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ activecpu = si.dwNumberOfProcessors;
+ wq_max_threads = activecpu * NTHREADS + 2;
#else
size_t s = sizeof(uint32_t);
sysctlbyname("hw.activecpu", &activecpu, &s, NULL, 0);
diff --git a/tests/dispatch_select.c b/tests/dispatch_select.c
index f7d4f55..66601ae 100644
--- a/tests/dispatch_select.c
+++ b/tests/dispatch_select.c
@@ -39,14 +39,25 @@
void
stage1(int stage)
{
+#if defined(_WIN32)
+ char *path = dispatch_test_get_large_file();
+ dispatch_fd_t fd = dispatch_test_fd_open(path, O_RDONLY);
+ if (fd == -1)
+ {
+ perror(path);
+ exit(EXIT_FAILURE);
+ }
+ dispatch_test_release_large_file(path);
+ free(path);
+#else
const char *path = "/dev/random";
-
int fd = open(path, O_RDONLY);
if (fd == -1)
{
perror(path);
exit(EXIT_FAILURE);
}
+#endif
dispatch_queue_t main_q = dispatch_get_main_queue();
test_ptr_notnull("main_q", main_q);
@@ -57,13 +68,13 @@
dispatch_source_set_event_handler(source, ^{
size_t buffer_size = 500*1024;
char buffer[500*1024];
- ssize_t sz = read(fd, buffer, buffer_size);
+ ssize_t sz = dispatch_test_fd_read(fd, buffer, buffer_size);
test_double_less_than_or_equal("kevent read 1", sz, buffer_size+1);
dispatch_source_cancel(source);
});
dispatch_source_set_cancel_handler(source, ^{
- int res = close(fd);
+ int res = dispatch_test_fd_close(fd);
test_errno("close", res == -1 ? errno : 0, 0);
dispatch_release(source);
if (stage == 1)
@@ -87,9 +98,7 @@
stage2(void)
{
char *path = dispatch_test_get_large_file();
- struct stat sb;
-
- int fd = open(path, O_RDONLY);
+ dispatch_fd_t fd = dispatch_test_fd_open(path, O_RDONLY);
if (fd == -1)
{
perror(path);
@@ -100,20 +109,15 @@
if (!dispatch_test_check_evfilt_read_for_fd(fd)) {
test_skip("EVFILT_READ kevent not firing for test file");
- close(fd);
+ dispatch_test_fd_close(fd);
dispatch_async(dispatch_get_main_queue(), ^{
stage1(3);
});
return;
}
- if (fstat(fd, &sb) == -1)
- {
- perror(path);
- exit(EXIT_FAILURE);
- }
-
- ssize_t expected = sb.st_size;
+ ssize_t expected = dispatch_test_fd_lseek(fd, 0, SEEK_END);
+ dispatch_test_fd_lseek(fd, 0, SEEK_SET);
actual = 0;
dispatch_queue_t main_q = dispatch_get_main_queue();
@@ -126,11 +130,11 @@
size_t est = dispatch_source_get_data(source);
test_double_less_than_or_equal("estimated", est, expected - actual);
char buffer[500*1024];
- ssize_t sz = read(fd, buffer, sizeof(buffer));
+ ssize_t sz = dispatch_test_fd_read(fd, buffer, sizeof(buffer));
actual += sz;
if (sz < (ssize_t)sizeof(buffer))
{
- sz = read(fd, buffer, sizeof(buffer));
+ sz = dispatch_test_fd_read(fd, buffer, sizeof(buffer));
actual += sz;
test_long("EOF", sz, 0);
dispatch_source_cancel(source);
@@ -139,7 +143,7 @@
dispatch_source_set_cancel_handler(source, ^{
test_long("bytes read", actual, expected);
- int res = close(fd);
+ int res = dispatch_test_fd_close(fd);
test_errno("close", res == -1 ? errno : 0, 0);
dispatch_release(source);
dispatch_async(dispatch_get_main_queue(), ^{
diff --git a/tests/dispatch_test.c b/tests/dispatch_test.c
index 9809543..b0d028d 100644
--- a/tests/dispatch_test.c
+++ b/tests/dispatch_test.c
@@ -25,6 +25,7 @@
#include <objc/objc-auto.h>
#endif
+#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
@@ -36,8 +37,8 @@
#include <sys/poll.h>
#endif
#elif defined(_WIN32)
-#include <io.h>
#include <Windows.h>
+#include <bcrypt.h>
#endif
#include <assert.h>
@@ -55,7 +56,7 @@
}
bool
-dispatch_test_check_evfilt_read_for_fd(int fd)
+dispatch_test_check_evfilt_read_for_fd(dispatch_fd_t fd)
{
#if HAS_SYS_EVENT_H
int kq = kqueue();
@@ -72,7 +73,7 @@
close(kq);
return r > 0;
#elif defined(_WIN32)
- HANDLE handle = (HANDLE)_get_osfhandle(fd);
+ HANDLE handle = (HANDLE)fd;
// A zero-distance move retrieves the file pointer
LARGE_INTEGER currentPosition;
LARGE_INTEGER distance = {.QuadPart = 0};
@@ -104,14 +105,28 @@
{
#if defined(__APPLE__)
return strdup("/usr/bin/vi");
-#elif defined(__unix__)
+#elif defined(__unix__) || defined(_WIN32)
// Depending on /usr/bin/vi being present is unreliable (especially on
// Android), so fill up a large-enough temp file with random bytes
+#if defined(_WIN32)
+ char temp_dir_buf[MAX_PATH];
+ const char *temp_dir = getenv("TEMP") ?: getenv("TMP");
+ if (!temp_dir) {
+ DWORD len = GetTempPathA(sizeof(temp_dir_buf), temp_dir_buf);
+ if (len > 0 && len < sizeof(temp_dir_buf)) {
+ temp_dir = temp_dir_buf;
+ } else {
+ temp_dir = ".";
+ }
+ }
+#else
const char *temp_dir = getenv("TMPDIR");
if (temp_dir == NULL || temp_dir[0] == '\0') {
temp_dir = "/tmp";
}
+#endif
+
const char *const suffix = "/dispatch_test.XXXXXX";
size_t temp_dir_len = strlen(temp_dir);
size_t suffix_len = strlen(suffix);
@@ -119,7 +134,7 @@
assert(path != NULL);
memcpy(path, temp_dir, temp_dir_len);
memcpy(&path[temp_dir_len], suffix, suffix_len + 1);
- int temp_fd = mkstemp(path);
+ dispatch_fd_t temp_fd = mkstemp(path);
if (temp_fd == -1) {
perror("mkstemp");
exit(EXIT_FAILURE);
@@ -129,12 +144,22 @@
char *file_buf = malloc(file_size);
assert(file_buf != NULL);
+ ssize_t num;
+#if defined(_WIN32)
+ NTSTATUS status = BCryptGenRandom(NULL, (PUCHAR)file_buf, file_size,
+ BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+ if (status < 0) {
+ fprintf(stderr, "BCryptGenRandom failed with %ld\n", status);
+ dispatch_test_release_large_file(path);
+ exit(EXIT_FAILURE);
+ }
+#else
int urandom_fd = open("/dev/urandom", O_RDONLY);
if (urandom_fd == -1) {
perror("/dev/urandom");
+ dispatch_test_release_large_file(path);
exit(EXIT_FAILURE);
}
- ssize_t num;
size_t pos = 0;
while (pos < file_size) {
num = read(urandom_fd, &file_buf[pos], file_size - pos);
@@ -142,26 +167,25 @@
pos += (size_t)num;
} else if (num == -1 && errno != EINTR) {
perror("read");
+ dispatch_test_release_large_file(path);
exit(EXIT_FAILURE);
}
}
close(urandom_fd);
+#endif
do {
- num = write(temp_fd, file_buf, file_size);
+ num = dispatch_test_fd_write(temp_fd, file_buf, file_size);
} while (num == -1 && errno == EINTR);
if (num == -1) {
perror("write");
+ dispatch_test_release_large_file(path);
exit(EXIT_FAILURE);
}
assert(num == file_size);
- close(temp_fd);
+ dispatch_test_fd_close(temp_fd);
free(file_buf);
return path;
-#elif defined(_WIN32)
- // TODO
- fprintf(stderr, "dispatch_test_get_large_file() not implemented on Windows\n");
- abort();
#else
#error "dispatch_test_get_large_file not implemented on this platform"
#endif
@@ -173,10 +197,10 @@
#if defined(__APPLE__)
// The path is fixed to a system file - do nothing
(void)path;
-#elif defined(__unix__)
- unlink(path);
-#elif defined(_WIN32)
- // TODO
+#elif defined(__unix__) || defined(_WIN32)
+ if (unlink(path) < 0) {
+ perror("unlink");
+ }
#else
#error "dispatch_test_release_large_file not implemented on this platform"
#endif
@@ -188,3 +212,155 @@
dispatch_queue_t actual = dispatch_get_current_queue();
_test_ptr(file, line, desc, actual, expected);
}
+
+dispatch_fd_t
+dispatch_test_fd_open(const char *path, int flags)
+{
+#if defined(_WIN32)
+ DWORD desired_access = 0;
+ DWORD creation_disposition = OPEN_EXISTING;
+ switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) {
+ case O_RDONLY:
+ desired_access = GENERIC_READ;
+ break;
+ case O_WRONLY:
+ desired_access = GENERIC_WRITE;
+ break;
+ case O_RDWR:
+ desired_access = GENERIC_READ | GENERIC_WRITE;
+ break;
+ }
+ if (flags & O_CREAT) {
+ creation_disposition = OPEN_ALWAYS;
+ if (flags & O_EXCL) {
+ creation_disposition = CREATE_NEW;
+ }
+ }
+ // FILE_SHARE_DELETE is important here because tests must be able to delete
+ // temporary files after opening them
+ HANDLE handle = CreateFileA(path, desired_access,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ /* lpSecurityAttributes */ NULL, creation_disposition,
+ /* dwFlagsAndAttributes */ 0, /* hTemplateFile */ NULL);
+ if (handle == INVALID_HANDLE_VALUE) {
+ DWORD error = GetLastError();
+ switch (error) {
+ case ERROR_ACCESS_DENIED:
+ errno = EACCES;
+ break;
+ case ERROR_FILE_EXISTS:
+ errno = EEXIST;
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_PATH_NOT_FOUND:
+ errno = ENOENT;
+ break;
+ default:
+ print_winapi_error("CreateFileA", GetLastError());
+ errno = EIO;
+ break;
+ }
+ return -1;
+ }
+ return (dispatch_fd_t)handle;
+#else
+ return open(path, flags);
+#endif
+}
+
+int
+dispatch_test_fd_close(dispatch_fd_t fd)
+{
+#if defined(_WIN32)
+ if (!CloseHandle((HANDLE)fd)) {
+ errno = EBADF;
+ return -1;
+ }
+ return 0;
+#else
+ return close(fd);
+#endif
+}
+
+off_t
+dispatch_test_fd_lseek(dispatch_fd_t fd, off_t offset, int whence)
+{
+#if defined(_WIN32)
+ DWORD method;
+ switch (whence) {
+ case SEEK_CUR:
+ method = FILE_CURRENT;
+ break;
+ case SEEK_END:
+ method = FILE_END;
+ break;
+ case SEEK_SET:
+ default:
+ method = FILE_BEGIN;
+ break;
+ }
+ LARGE_INTEGER distance = {.QuadPart = offset};
+ LARGE_INTEGER new_pos;
+ if (!SetFilePointerEx((HANDLE)fd, distance, &new_pos, method)) {
+ print_winapi_error("SetFilePointerEx", GetLastError());
+ errno = EINVAL;
+ return -1;
+ }
+ return (off_t)new_pos.QuadPart;
+#else
+ return lseek(fd, offset, whence);
+#endif
+}
+
+ssize_t
+dispatch_test_fd_pread(dispatch_fd_t fd, void *buf, size_t count, off_t offset)
+{
+#if defined(_WIN32)
+ OVERLAPPED overlapped;
+ memset(&overlapped, 0, sizeof(overlapped));
+ LARGE_INTEGER lioffset = {.QuadPart = offset};
+ overlapped.Offset = lioffset.LowPart;
+ overlapped.OffsetHigh = lioffset.HighPart;
+ DWORD num_read;
+ if (!ReadFile((HANDLE)fd, buf, count, &num_read, &overlapped)) {
+ print_winapi_error("ReadFile", GetLastError());
+ errno = EIO;
+ return -1;
+ }
+ return (ssize_t)num_read;
+#else
+ return pread(fd, buf, count, offset);
+#endif
+}
+
+ssize_t
+dispatch_test_fd_read(dispatch_fd_t fd, void *buf, size_t count)
+{
+#if defined(_WIN32)
+ DWORD num_read;
+ if (!ReadFile((HANDLE)fd, buf, count, &num_read, NULL)) {
+ print_winapi_error("ReadFile", GetLastError());
+ errno = EIO;
+ return -1;
+ }
+ return (ssize_t)num_read;
+#else
+ return read(fd, buf, count);
+#endif
+}
+
+ssize_t
+dispatch_test_fd_write(dispatch_fd_t fd, const void *buf, size_t count)
+{
+#if defined(_WIN32)
+ DWORD num_written;
+ if (!WriteFile((HANDLE)fd, buf, count, &num_written, NULL)) {
+ print_winapi_error("WriteFile", GetLastError());
+ errno = EIO;
+ return -1;
+ }
+ return (ssize_t)num_written;
+#else
+ return write(fd, buf, count);
+#endif
+}
diff --git a/tests/dispatch_test.h b/tests/dispatch_test.h
index 415e419..9de95b3 100644
--- a/tests/dispatch_test.h
+++ b/tests/dispatch_test.h
@@ -40,7 +40,7 @@
void dispatch_test_start(const char* desc);
-bool dispatch_test_check_evfilt_read_for_fd(int fd);
+bool dispatch_test_check_evfilt_read_for_fd(dispatch_fd_t fd);
char *dispatch_test_get_large_file(void);
void dispatch_test_release_large_file(const char *path);
@@ -53,6 +53,13 @@
size_t *newpl);
#endif
+dispatch_fd_t dispatch_test_fd_open(const char *path, int flags);
+int dispatch_test_fd_close(dispatch_fd_t fd);
+off_t dispatch_test_fd_lseek(dispatch_fd_t fd, off_t offset, int whence);
+ssize_t dispatch_test_fd_pread(dispatch_fd_t fd, void *buf, size_t count, off_t offset);
+ssize_t dispatch_test_fd_read(dispatch_fd_t fd, void *buf, size_t count);
+ssize_t dispatch_test_fd_write(dispatch_fd_t fd, const void *buf, size_t count);
+
#if defined(__cplusplus)
} /* extern "C" */
#endif
diff --git a/tests/generic_win_port.c b/tests/generic_win_port.c
index f84f9f9..ba685a1 100644
--- a/tests/generic_win_port.c
+++ b/tests/generic_win_port.c
@@ -1,4 +1,6 @@
+#define _CRT_RAND_S
#include <generic_win_port.h>
+#include <dispatch_test.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
@@ -220,6 +222,42 @@
return result * 100; // Convert from 100ns units
}
+static void
+randomize_name(char *out)
+{
+ static const char chars[] =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._-";
+ const size_t num_chars = sizeof(chars) - 1;
+ unsigned int lo, hi;
+ rand_s(&lo);
+ rand_s(&hi);
+ uint64_t val = ((uint64_t)hi << 32) | lo;
+ for (int j = 0; j < 6; j++) {
+ out[j] = chars[val % num_chars];
+ val /= num_chars;
+ }
+}
+
+dispatch_fd_t
+mkstemp(char *tmpl)
+{
+ size_t len = strlen(tmpl);
+ if (len < 6) {
+ errno = EINVAL;
+ return -1;
+ }
+ char *replace = &tmpl[len - 6];
+ for (int i = 0; i < 100; i++) {
+ randomize_name(replace);
+ dispatch_fd_t fd = dispatch_test_fd_open(tmpl, O_RDWR | O_CREAT | O_EXCL);
+ if (fd != -1) {
+ return fd;
+ }
+ }
+ errno = EEXIST;
+ return -1;
+}
+
void
print_winapi_error(const char *function_name, DWORD error)
{
@@ -236,6 +274,14 @@
}
}
+intptr_t
+random(void)
+{
+ unsigned int x;
+ rand_s(&x);
+ return x & INT_MAX;
+}
+
unsigned int
sleep(unsigned int seconds)
{
diff --git a/tests/generic_win_port.h b/tests/generic_win_port.h
index 41c076c..d693c74 100644
--- a/tests/generic_win_port.h
+++ b/tests/generic_win_port.h
@@ -1,6 +1,9 @@
#pragma once
+#include <dispatch/dispatch.h>
+#include <fcntl.h>
#include <stdint.h>
+#include <sys/types.h>
#include <Windows.h>
typedef int kern_return_t;
@@ -65,9 +68,15 @@
return 0;
}
+dispatch_fd_t
+mkstemp(char *tmpl);
+
void
print_winapi_error(const char *function_name, DWORD error);
+intptr_t
+random(void);
+
unsigned int
sleep(unsigned int seconds);