[libdispatch-changes] [215] trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed Aug 8 22:09:03 PDT 2012
Revision: 215
http://trac.macosforge.org/projects/libdispatch/changeset/215
Author: dsteffen at apple.com
Date: 2012-08-08 22:09:03 -0700 (Wed, 08 Aug 2012)
Log Message:
-----------
MountainLion macosforge testsuite
Modified Paths:
--------------
trunk/Makefile.am
trunk/configure.ac
trunk/testing/Makefile.am
trunk/testing/bench.mm
trunk/testing/bsdtestharness.c
trunk/testing/bsdtests.c
trunk/testing/bsdtests.h
trunk/testing/dispatch_after.c
trunk/testing/dispatch_api.c
trunk/testing/dispatch_apply.c
trunk/testing/dispatch_concur.c
trunk/testing/dispatch_deadname.c
trunk/testing/dispatch_drift.c
trunk/testing/dispatch_group.c
trunk/testing/dispatch_io.c
trunk/testing/dispatch_priority.c
trunk/testing/dispatch_queue_finalizer.c
trunk/testing/dispatch_suspend_timer.c
trunk/testing/dispatch_test.c
trunk/testing/dispatch_test.h
trunk/testing/dispatch_timer.c
trunk/testing/dispatch_timer_bit31.c
trunk/testing/dispatch_timer_set_time.c
trunk/testing/dispatch_vm.c
Added Paths:
-----------
trunk/testing/dispatch_transform.c
Modified: trunk/Makefile.am
===================================================================
--- trunk/Makefile.am 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/Makefile.am 2012-08-09 05:09:03 UTC (rev 215)
@@ -9,7 +9,8 @@
man \
os \
private \
- src
+ src \
+ testing
EXTRA_DIST= \
LICENSE \
Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/configure.ac 2012-08-09 05:09:03 UTC (rev 215)
@@ -295,5 +295,11 @@
#
# Generate Makefiles.
#
-AC_CONFIG_FILES([Makefile dispatch/Makefile man/Makefile os/Makefile private/Makefile src/Makefile])
+AC_CONFIG_FILES([Makefile dispatch/Makefile man/Makefile os/Makefile private/Makefile src/Makefile testing/Makefile])
+
+#
+# Generate testsuite links
+#
+AC_CONFIG_LINKS([testing/dispatch:${x:+}private testing/bench.cc:testing/bench.mm testing/leaks-wrapper:testing/leaks-wrapper.sh])
+
AC_OUTPUT
Modified: trunk/testing/Makefile.am
===================================================================
--- trunk/testing/Makefile.am 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/Makefile.am 2012-08-09 05:09:03 UTC (rev 215)
@@ -62,17 +62,16 @@
dispatch_vnode \
dispatch_select
-dispatch_c99_CFLAGS=-std=c99
+dispatch_c99_CFLAGS=$(AM_CFLAGS) -std=c99
dispatch_plusplus_SOURCES=dispatch_plusplus.cpp
dispatch_priority2_SOURCES=dispatch_priority.c
-dispatch_priority2_CFLAGS=-DUSE_SET_TARGET_QUEUE=1
+dispatch_priority2_CPPFLAGS=$(AM_CPPFLAGS) -DUSE_SET_TARGET_QUEUE=1
-INCLUDES=-I$(top_builddir) -I$(top_srcdir)
+AM_CPPFLAGS=-I$(top_builddir) -I$(top_srcdir)
-CPPFLAGS=
-CFLAGS=-Wall -g $(MARCH_FLAGS) $(CBLOCKS_FLAGS)
-OBJCFLAGS=-Wall -g $(MARCH_FLAGS) $(CBLOCKS_FLAGS)
-CXXFLAGS=-Wall -g $(MARCH_FLAGS) $(CXXBLOCKS_FLAGS)
+AM_CFLAGS=-Wall $(MARCH_FLAGS) $(CBLOCKS_FLAGS)
+AM_OBJCFLAGS=-Wall $(MARCH_FLAGS) $(CBLOCKS_FLAGS) -fobjc-gc
+AM_CXXFLAGS=-Wall $(MARCH_FLAGS) $(CXXBLOCKS_FLAGS)
LDADD=libbsdtests.la ../src/libdispatch.la
libbsdtests_la_LDFLAGS=-avoid-version
@@ -83,10 +82,12 @@
if HAVE_COREFOUNDATION
TESTS+= \
dispatch_cf_main \
+ dispatch_transform \
dispatch_sync_on_main \
cffd
dispatch_cf_main_LDFLAGS=-framework CoreFoundation
+dispatch_transform_LDFLAGS=-framework CoreFoundation -framework Security
dispatch_sync_on_main_LDFLAGS=-framework CoreFoundation
cffd_LDFLAGS=-framework CoreFoundation
endif
@@ -99,14 +100,13 @@
bench
dispatch_sync_gc_SOURCES=dispatch_sync_gc.m
-dispatch_sync_gc_OBJCFLAGS=-fobjc-gc
dispatch_sync_gc_LDFLAGS=-framework Foundation
dispatch_apply_gc_SOURCES=dispatch_apply_gc.m
-dispatch_apply_gc_OBJCFLAGS=-fobjc-gc
dispatch_apply_gc_LDFLAGS=-framework Foundation
nsoperation_SOURCES=nsoperation.m
nsoperation_LDFLAGS=-framework Foundation
-bench_SOURCES=bench.cc func.c
+nodist_bench_SOURCES=bench.cc
+bench_SOURCES=func.c
bench_LDFLAGS=-framework Foundation
# Workaround missing objcxx support in older autotools
bench.o: bench.cc
Modified: trunk/testing/bench.mm
===================================================================
--- trunk/testing/bench.mm 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/bench.mm 2012-08-09 05:09:03 UTC (rev 215)
@@ -416,6 +416,13 @@
s = mach_absolute_time();
for (i = cnt; i; i--) {
+ global = 0;
+ asm volatile("mfence" ::: "memory");
+ }
+ print_result(s, "Store + mfence:");
+
+ s = mach_absolute_time();
+ for (i = cnt; i; i--) {
unsigned long _clbr;
#ifdef __LP64__
asm volatile("cpuid" : "=a" (_clbr)
@@ -466,9 +473,36 @@
print_result(s, "'dmb ishst' instruction:");
#endif
+#ifdef _ARM_ARCH_7
s = mach_absolute_time();
for (i = cnt; i; i--) {
+ asm volatile("str %[_r], [%[_p], %[_o]]" :
+ : [_p] "p" (&global), [_o] "M" (0), [_r] "r" (0) : "memory");
+ asm volatile("dmb ishst" : : : "memory");
+ }
+ print_result(s, "'str + dmb ishst' instructions:");
+#endif
+
#ifdef _ARM_ARCH_7
+ s = mach_absolute_time();
+ for (i = cnt; i; i--) {
+ uintptr_t prev;
+ uint32_t t;
+ do {
+ asm volatile("ldrex %[_r], [%[_p], %[_o]]"
+ : [_r] "=&r" (prev) \
+ : [_p] "p" (&global), [_o] "M" (0) : "memory");
+ asm volatile("strex %[_t], %[_r], [%[_p], %[_o]]"
+ : [_t] "=&r" (t) \
+ : [_p] "p" (&global), [_o] "M" (0), [_r] "r" (0) : "memory");
+ } while (t);
+ }
+ print_result(s, "'ldrex + strex' instructions:");
+#endif
+
+ s = mach_absolute_time();
+ for (i = cnt; i; i--) {
+#ifdef _ARM_ARCH_7
asm volatile("dsb ish" : : : "memory");
#else
asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory");
@@ -528,6 +562,37 @@
}
print_result(s, "Atomic increment:");
+ {
+ global = 0;
+ volatile int32_t *g = &global;
+
+ s = mach_absolute_time();
+ for (i = cnt; i; i--) {
+ uint32_t result;
+ __sync_and_and_fetch(g, 1);
+ result = *g;
+ if (result) {
+ abort();
+ }
+ }
+ print_result(s, "Atomic and-and-fetch, reloading result:");
+ }
+
+ {
+ global = 0;
+ volatile int32_t *g = &global;
+
+ s = mach_absolute_time();
+ for (i = cnt; i; i--) {
+ uint32_t result;
+ result = __sync_and_and_fetch(g, 1);
+ if (result) {
+ abort();
+ }
+ }
+ print_result(s, "Atomic and-and-fetch, using result:");
+ }
+
global = 0;
s = mach_absolute_time();
Modified: trunk/testing/bsdtestharness.c
===================================================================
--- trunk/testing/bsdtestharness.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/bsdtestharness.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -18,7 +18,6 @@
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
-#include <mach/clock_types.h>
#include <dispatch/dispatch.h>
#include <assert.h>
#include <spawn.h>
@@ -26,7 +25,10 @@
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
+#include <mach/clock_types.h>
#include <mach-o/arch.h>
+#include <sys/resource.h>
+#include <sys/time.h>
#include <bsdtests.h>
@@ -37,19 +39,31 @@
{
dispatch_source_t tmp_ds;
int res;
- pid_t pid;
+ pid_t pid = 0;
if (argc < 2) {
fprintf(stderr, "usage: %s [...]\n", argv[0]);
exit(1);
}
+ short spawnflags = POSIX_SPAWN_START_SUSPENDED;
+#if TARGET_OS_EMBEDDED
+ spawnflags |= POSIX_SPAWN_SETEXEC;
+#endif
+
posix_spawnattr_t attr;
res = posix_spawnattr_init(&attr);
assert(res == 0);
- res = posix_spawnattr_setflags(&attr, POSIX_SPAWN_START_SUSPENDED);
+ res = posix_spawnattr_setflags(&attr, spawnflags);
assert(res == 0);
+ uint64_t to = 0;
+ char *tos = getenv("BSDTEST_TIMEOUT");
+ if (tos) {
+ to = strtoul(tos, NULL, 0);
+ to *= NSEC_PER_SEC;
+ }
+
char *arch = getenv("BSDTEST_ARCH");
if (arch) {
const NXArchInfo *ai = NXGetArchInfoFromName(arch);
@@ -66,12 +80,21 @@
}
newargv[i-1] = NULL;
- res = posix_spawnp(&pid, newargv[0], NULL, &attr, newargv, environ);
- if (res) {
- errno = res;
- perror(newargv[0]);
- exit(EXIT_FAILURE);
+ struct timeval tv_start;
+ gettimeofday(&tv_start, NULL);
+
+ if (spawnflags & POSIX_SPAWN_SETEXEC) {
+ pid = fork();
}
+ if (!pid) {
+ res = posix_spawnp(&pid, newargv[0], NULL, &attr, newargv, environ);
+ if (res) {
+ errno = res;
+ perror(newargv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
//fprintf(stderr, "pid = %d\n", pid);
assert(pid > 0);
@@ -81,23 +104,40 @@
assert(tmp_ds);
dispatch_source_set_event_handler(tmp_ds, ^{
int status;
- int res2 = waitpid(pid, &status, 0);
+ struct rusage usage;
+ struct timeval tv_stop, tv_wall;
+
+ gettimeofday(&tv_stop, NULL);
+ tv_wall.tv_sec = tv_stop.tv_sec - tv_start.tv_sec;
+ tv_wall.tv_sec -= (tv_stop.tv_usec < tv_start.tv_usec);
+ tv_wall.tv_usec = abs(tv_stop.tv_usec - tv_start.tv_usec);
+
+ int res2 = wait4(pid, &status, 0, &usage);
assert(res2 != -1);
test_long("Process exited", (WIFEXITED(status) && WEXITSTATUS(status) && WEXITSTATUS(status) != 0xff) || WIFSIGNALED(status), 0);
+ printf("[PERF]\twall time: %ld.%06d\n", tv_wall.tv_sec, tv_wall.tv_usec);
+ printf("[PERF]\tuser time: %ld.%06d\n", usage.ru_utime.tv_sec, usage.ru_utime.tv_usec);
+ printf("[PERF]\tsystem time: %ld.%06d\n", usage.ru_stime.tv_sec, usage.ru_stime.tv_usec);
+ printf("[PERF]\tmax resident set size: %ld\n", usage.ru_maxrss);
+ printf("[PERF]\tpage faults: %ld\n", usage.ru_majflt);
+ printf("[PERF]\tswaps: %ld\n", usage.ru_nswap);
+ printf("[PERF]\tvoluntary context switches: %ld\n", usage.ru_nvcsw);
+ printf("[PERF]\tinvoluntary context switches: %ld\n", usage.ru_nivcsw);
exit((WIFEXITED(status) && WEXITSTATUS(status)) || WIFSIGNALED(status));
});
dispatch_resume(tmp_ds);
+ if (!to) {
#if TARGET_OS_EMBEDDED
- // Give embedded platforms a little more time.
- uint64_t timeout = 300LL * NSEC_PER_SEC;
+ to = 180LL * NSEC_PER_SEC;
#else
- uint64_t timeout = 150LL * NSEC_PER_SEC;
+ to = 90LL * NSEC_PER_SEC;
#endif
+ }
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeout), main_q, ^{
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, to), main_q, ^{
kill(pid, SIGKILL);
- fprintf(stderr, "Terminating unresponsive process (%0.1lfs)\n", (double)timeout/NSEC_PER_SEC);
+ fprintf(stderr, "Terminating unresponsive process (%0.1lfs)\n", (double)to / NSEC_PER_SEC);
});
signal(SIGINT, SIG_IGN);
@@ -109,6 +149,9 @@
});
dispatch_resume(tmp_ds);
+ if (spawnflags & POSIX_SPAWN_SETEXEC) {
+ usleep(USEC_PER_SEC/10);
+ }
kill(pid, SIGCONT);
dispatch_main();
Modified: trunk/testing/bsdtests.c
===================================================================
--- trunk/testing/bsdtests.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/bsdtests.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -127,6 +127,18 @@
_test_ptr(NULL, 0, desc, actual, expected);
}
+void _test_ptr_not(const char* file, long line, const char* desc, const void* actual, const void* expected)
+{
+ _test_print(file, line, desc,
+ (actual != expected), "%p", actual, "!%p", expected);
+}
+
+void test_ptr_not_format(const void *actual, const void* expected, const char *format, ...)
+{
+ GENERATE_DESC
+ _test_ptr_not(NULL, 0, desc, actual, expected);
+}
+
void
_test_uint32(const char* file, long line, const char* desc, uint32_t actual, uint32_t expected)
{
@@ -211,6 +223,19 @@
}
void
+_test_long_less_than_or_equal(const char* file, long line, const char* desc, long actual, long expected_max)
+{
+ _test_print(file, line, desc, (actual <= expected_max), "%ld", actual, "<=%ld", expected_max);
+}
+
+void
+test_long_less_than_or_equal_format(long actual, long expected_max, const char* format, ...)
+{
+ GENERATE_DESC
+ _test_long_less_than_or_equal(NULL, 0, desc, actual, expected_max);
+}
+
+void
_test_long_greater_than_or_equal(const char* file, long line, const char* desc, long actual, long expected_min)
{
_test_print(file, line, desc, (actual >= expected_min), "%ld", actual, ">=%ld", expected_min);
@@ -250,6 +275,20 @@
}
void
+_test_double_equal(const char* file, long line, const char* desc, double val, double expected)
+{
+ _test_print(file, line, desc, (val == expected), "%f", val, "%f", expected);
+}
+
+
+void
+test_double_equal_format(double val, double expected, const char *format, ...)
+{
+ GENERATE_DESC
+ _test_double_equal(NULL, 0, desc, val, expected);
+}
+
+void
_test_errno(const char* file, long line, const char* desc, long actual, long expected)
{
char* actual_str;
@@ -386,6 +425,10 @@
return;
}
+ unsetenv("DYLD_IMAGE_SUFFIX");
+ unsetenv("DYLD_INSERT_LIBRARIES");
+ unsetenv("DYLD_LIBRARY_PATH");
+
unsetenv("MallocStackLogging");
unsetenv("MallocStackLoggingNoCompact");
Modified: trunk/testing/bsdtests.h
===================================================================
--- trunk/testing/bsdtests.h 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/bsdtests.h 2012-08-09 05:09:03 UTC (rev 215)
@@ -18,10 +18,21 @@
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
+#ifndef __BSD_TEST_H__
+#define __BSD_TEST_H__
+
#include <errno.h>
#include <mach/error.h>
#include <CoreFoundation/CoreFoundation.h>
+static inline const char*
+__BASENAME__(const char *_str_)
+{
+ const char *_s_ = strrchr(_str_, '/');
+ return (_s_ ? _s_ : _str_ - 1) + 1;
+}
+#define __SOURCE_FILE__ __BASENAME__(__FILE__)
+
__BEGIN_DECLS
/**
@@ -47,67 +58,81 @@
* that is printed after the token.
*/
void _test_ptr_null(const char* file, long line, const char* desc, const void* ptr);
-#define test_ptr_null(a,b) _test_ptr_null(__FILE__, __LINE__, a, b)
+#define test_ptr_null(a,b) _test_ptr_null(__SOURCE_FILE__, __LINE__, a, b)
void test_ptr_null_format(void *ptr, const char *format, ...);
void _test_ptr_notnull(const char* file, long line, const char* desc, const void* ptr);
-#define test_ptr_notnull(a,b) _test_ptr_notnull(__FILE__, __LINE__, a, b)
+#define test_ptr_notnull(a,b) _test_ptr_notnull(__SOURCE_FILE__, __LINE__, a, b)
void test_ptr_notnull_format(const void *ptr, const char *format, ...) __printflike(2, 3);
+void _test_ptr_not(const char* file, long line, const char* desc, const void* actual, const void* expected);
+#define test_ptr_not(a, b, c) _test_ptr_not(__SOURCE_FILE__, __LINE__, a, b, c)
+void test_ptr_not_format(const void* actual, const void* expected, const char *format, ...);
+
void _test_ptr(const char* file, long line, const char* desc, const void* actual, const void* expected);
-#define test_ptr(a,b,c) _test_ptr(__FILE__, __LINE__, a, b, c)
+#define test_ptr(a,b,c) _test_ptr(__SOURCE_FILE__, __LINE__, a, b, c)
void test_ptr_format(const void* actual, const void* expected, const char *format, ...) __printflike(3,4);
void _test_uint32(const char* file, long line, const char* desc, uint32_t actual, uint32_t expected);
-#define test_uint32(a,b,c) _test_uint32(__FILE__, __LINE__, a, b, c)
+#define test_uint32(a,b,c) _test_uint32(__SOURCE_FILE__, __LINE__, a, b, c)
void test_uint32_format(long actual, long expected, const char *format, ...) __printflike(3,4);
void _test_int32(const char* file, long line, const char* desc, int32_t actual, int32_t expected);
-#define test_int32(a,b,c) _test_int32(__FILE__, __LINE__, a, b, c)
+#define test_int32(a,b,c) _test_int32(__SOURCE_FILE__, __LINE__, a, b, c)
void test_sint32_format(int32_t actual, int32_t expected, const char* format, ...) __printflike(3,4);
void _test_long(const char* file, long line, const char* desc, long actual, long expected);
-#define test_long(a,b,c) _test_long(__FILE__, __LINE__, a, b, c)
+#define test_long(a,b,c) _test_long(__SOURCE_FILE__, __LINE__, a, b, c)
void test_long_format(long actual, long expected, const char *format, ...) __printflike(3,4);
void _test_uint64(const char* file, long line, const char* desc, uint64_t actual, uint64_t expected);
-#define test_uint64(a,b,c) _test_uint64(__FILE__, __LINE__, a, b, c)
+#define test_uint64(a,b,c) _test_uint64(__SOURCE_FILE__, __LINE__, a, b, c)
void test_uint64_format(uint64_t actual, uint64_t expected, const char* desc, ...);
void _test_int64(const char* file, long line, const char* desc, int64_t actual, int64_t expected);
-#define test_int64(a,b,c) _test_uint64(__FILE__, __LINE__, a, b, c)
+#define test_int64(a,b,c) _test_uint64(__SOURCE_FILE__, __LINE__, a, b, c)
void test_int64_format(int64_t actual, int64_t expected, const char* desc, ...);
void _test_long_less_than(const char* file, long line, const char* desc, long actual, long max_expected);
-#define test_long_less_than(a,b,c) _test_long_less_than(__FILE__, __LINE__, a, b, c)
+#define test_long_less_than(a,b,c) _test_long_less_than(__SOURCE_FILE__, __LINE__, a, b, c)
void test_long_less_than_format(long actual, long max_expected, const char *format, ...) __printflike(3,4);
+void _test_long_less_than_or_equal(const char* file, long line, const char* desc, long actual, long max_expected);
+#define test_long_less_than_or_equal(a,b,c) _test_long_less_than_or_equal(__SOURCE_FILE__, __LINE__, a, b, c)
+void test_long_less_than_or_equal_format(long actual, long max_expected, const char *format, ...) __printflike(3,4);
+
void _test_long_greater_than_or_equal(const char* file, long line, const char* desc, long actual, long expected_min);
-#define test_long_greater_than_or_equal(a,b,c) _test_long_greater_than_or_equal(__FILE__, __LINE__, a, b, c)
+#define test_long_greater_than_or_equal(a,b,c) _test_long_greater_than_or_equal(__SOURCE_FILE__, __LINE__, a, b, c)
void test_long_greater_than_or_equal_format(long actual, long expected_min, const char *format, ...) __printflike(3,4);
void _test_double_less_than_or_equal(const char* file, long line, const char* desc, double val, double max_expected);
-#define test_double_less_than_or_equal(d, v, m) _test_double_less_than_or_equal(__FILE__, __LINE__, d, v, m)
+#define test_double_less_than_or_equal(d, v, m) _test_double_less_than_or_equal(__SOURCE_FILE__, __LINE__, d, v, m)
void test_double_less_than_or_equal_format(double val, double max_expected, const char *format, ...) __printflike(3,4);
void _test_double_less_than(const char* file, long line, const char* desc, double val, double max_expected);
-#define test_double_less_than(d, v, m) _test_double_less_than(__FILE__, __LINE__, d, v, m)
+#define test_double_less_than(d, v, m) _test_double_less_than(__SOURCE_FILE__, __LINE__, d, v, m)
void test_double_less_than_format(double val, double max_expected, const char *format, ...) __printflike(3,4);
+void _test_double_equal(const char* file, long line, const char* desc, double val, double expected);
+#define test_double_equal(d, v, m) _test_double_equal(__SOURCE_FILE__, __LINE__, d, v, m)
+void test_double_equal_format(double val, double expected, const char *format, ...) __printflike(3,4);
+
void _test_errno(const char* file, long line, const char* desc, long actual, long expected);
-#define test_errno(a,b,c) _test_errno(__FILE__, __LINE__, a, b, c)
+#define test_errno(a,b,c) _test_errno(__SOURCE_FILE__, __LINE__, a, b, c)
void test_errno_format(long actual, long expected, const char *format, ...) __printflike(3,4);
void _test_mach_error(const char* file, long line, const char* desc, mach_error_t actual, mach_error_t expected);
-#define test_mach_error(a,b,c) _test_mach_error(__FILE__, __LINE__, a, b, c)
+#define test_mach_error(a,b,c) _test_mach_error(__SOURCE_FILE__, __LINE__, a, b, c)
void test_mach_error_format(mach_error_t actual, mach_error_t expected, const char *format, ...) __printflike(3,4);
void test_cferror(const char* desc, CFErrorRef actual, CFIndex expectedCode);
void test_cferror_format(CFErrorRef actual, CFIndex expectedCode, const char *format, ...) __printflike(3,4);
void _test_skip(const char* file, long line, const char* desc);
-#define test_skip(m) _test_skip(__FILE__, __LINE__, m)
+#define test_skip(m) _test_skip(__SOURCE_FILE__, __LINE__, m)
#define test_skip2(m) _test_skip("", 0, m)
void test_skip_format(const char *format, ...) __printflike(1,2);
__END_DECLS
+
+#endif /* __BSD_TEST_H__ */
Modified: trunk/testing/dispatch_after.c
===================================================================
--- trunk/testing/dispatch_after.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_after.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -50,7 +50,7 @@
time_a_min = dispatch_time(0, 5.5*NSEC_PER_SEC);
time_a = dispatch_time(0, 6*NSEC_PER_SEC);
time_a_max = dispatch_time(0, 6.5*NSEC_PER_SEC);
- dispatch_after(time_a, dispatch_get_current_queue(), ^{
+ dispatch_after(time_a, dispatch_get_main_queue(), ^{
dispatch_time_t now_a = dispatch_time(0, 0);
test_long_less_than("can't finish faster than 5.5s", 0, now_a - time_a_min);
test_long_less_than("must finish faster than 6.5s", 0, time_a_max - now_a);
@@ -58,7 +58,7 @@
time_b_min = dispatch_time(0, 1.5*NSEC_PER_SEC);
time_b = dispatch_time(0, 2*NSEC_PER_SEC);
time_b_max = dispatch_time(0, 2.5*NSEC_PER_SEC);
- dispatch_after(time_b, dispatch_get_current_queue(), ^{
+ dispatch_after(time_b, dispatch_get_main_queue(), ^{
dispatch_time_t now_b = dispatch_time(0, 0);
test_long_less_than("can't finish faster than 1.5s", 0, now_b - time_b_min);
test_long_less_than("must finish faster than 2.5s", 0, time_b_max - now_b);
@@ -66,12 +66,12 @@
time_c_min = dispatch_time(0, 0*NSEC_PER_SEC);
time_c = dispatch_time(0, 0*NSEC_PER_SEC);
time_c_max = dispatch_time(0, .5*NSEC_PER_SEC);
- dispatch_after(time_c, dispatch_get_current_queue(), ^{
+ dispatch_after(time_c, dispatch_get_main_queue(), ^{
dispatch_time_t now_c = dispatch_time(0, 0);
test_long_less_than("can't finish faster than 0s", 0, now_c - time_c_min);
test_long_less_than("must finish faster than .5s", 0, time_c_max - now_c);
- dispatch_async_f(dispatch_get_current_queue(), NULL, done);
+ dispatch_async_f(dispatch_get_main_queue(), NULL, done);
});
});
});
Modified: trunk/testing/dispatch_api.c
===================================================================
--- trunk/testing/dispatch_api.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_api.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -33,8 +33,9 @@
int
main(void)
{
+ dispatch_queue_t q;
dispatch_test_start("Dispatch (Public) API");
- dispatch_queue_t q = dispatch_get_main_queue();
+ q = dispatch_get_main_queue();
test_ptr_notnull("dispatch_get_main_queue", q);
dispatch_async_f(dispatch_get_main_queue(), NULL, work);
Modified: trunk/testing/dispatch_apply.c
===================================================================
--- trunk/testing/dispatch_apply.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_apply.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -24,10 +24,88 @@
#include <stdlib.h>
#include <assert.h>
#include <libkern/OSAtomic.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
#include <bsdtests.h>
#include "dispatch_test.h"
+static volatile int32_t busy_threads_started, busy_threads_finished;
+
+/*
+ * Keep a thread busy, spinning on the CPU.
+ */
+#if TARGET_OS_EMBEDDED
+// iPhone 4
+#define ITERS_PER_SECOND 50000000UL
+#else
+// On a 2.7 4-core i5 iMac12,2, one thread of this loop runs at ROUGHLY:
+#define ITERS_PER_SECOND 1000000000UL
+#endif
+
+/* Fiddling with j in the middle and hitting this global will hopefully keep
+ * the optimizer from cutting the whole thing out as dead code.
+ */
+static volatile unsigned int busythread_useless;
+void busythread(void *ignored)
+{
+ (void)ignored;
+ uint64_t i = 0, j = 0;
+
+ OSAtomicIncrement32(&busy_threads_started);
+
+ for(i = 0; i < 2*ITERS_PER_SECOND; i++)
+ {
+ if(i == 500000) { j -= busythread_useless; }
+ j += i;
+ }
+
+ OSAtomicIncrement32(&busy_threads_finished);
+}
+
+/*
+ * Test that dispatch_apply can make progress and finish, even if there are
+ * so many other running and unblocked workqueue threads that the apply's
+ * helper threads never get a chance to come up.
+ *
+ * <rdar://problem/10718199> dispatch_apply should not block waiting on other
+ * threads while calling thread is available
+ */
+void test_apply_contended(dispatch_queue_t dq)
+{
+ uint32_t activecpu;
+ size_t s = sizeof(activecpu);
+ sysctlbyname("hw.activecpu", &activecpu, &s, NULL, 0);
+ int tIndex, n_threads = activecpu;
+ dispatch_group_t grp = dispatch_group_create();
+
+ for(tIndex = 0; tIndex < n_threads; tIndex++) {
+ dispatch_group_async_f(grp, dq, NULL, busythread);
+ }
+
+ // Spin until all the threads have actually started
+ while(busy_threads_started < n_threads) {
+ usleep(1);
+ }
+
+ volatile __block int32_t count = 0;
+ const int32_t final = 32;
+
+ unsigned int before = busy_threads_started;
+ dispatch_apply(final, dq, ^(size_t i __attribute__((unused))) {
+ OSAtomicIncrement32(&count);
+ });
+ unsigned int after = busy_threads_finished;
+
+ test_long("contended: threads started before apply", before, n_threads);
+ test_long("contended: count", count, final);
+ test_long("contended: threads finished before apply", after, 0);
+
+ dispatch_group_wait(grp, DISPATCH_TIME_FOREVER);
+ dispatch_release(grp);
+
+}
+
int
main(void)
{
@@ -54,6 +132,8 @@
});
test_long("nested count", count, final * final * final);
+ test_apply_contended(queue);
+
test_stop();
return 0;
Modified: trunk/testing/dispatch_concur.c
===================================================================
--- trunk/testing/dispatch_concur.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_concur.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -147,7 +147,7 @@
size_t c = __sync_add_and_fetch(&concur, 1), *m = ((size_t *)ctxt) + i;
if (c > *m) *m = c;
- usleep(10000);
+ usleep(100000);
__sync_sub_and_fetch(&concur, 1);
}
Modified: trunk/testing/dispatch_deadname.c
===================================================================
--- trunk/testing/dispatch_deadname.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_deadname.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -32,18 +32,17 @@
#if TEST_MACHPORT_DEBUG
#define test_mach_assume_zero(x) ({kern_return_t _kr = (x); \
if (_kr) fprintf(stderr, "mach error 0x%x \"%s\": %s\n", \
- _kr, mach_error_string(_kr), #x); _kr; })
+ _kr, mach_error_string(_kr), #x); (void)kr; })
void
-test_mach_debug_port(mach_port_t name, const char *str)
+test_mach_debug_port(mach_port_t name, const char *str, unsigned int line)
{
mach_port_type_t type;
mach_msg_bits_t ns = 0, nr = 0, nso = 0, nd = 0;
unsigned int dnreqs = 0, dnrsiz;
kern_return_t kr = mach_port_type(mach_task_self(), name, &type);
-
if (kr) {
- fprintf(stderr, "machport[0x%08x] = { error(0x%x) \"%s\" }: %s\n",
- name, kr, mach_error_string(kr), str);
+ fprintf(stderr, "machport[0x%08x] = { error(0x%x) \"%s\" }: %s %u\n",
+ name, kr, mach_error_string(kr), str, line);
return;
}
if (type & MACH_PORT_TYPE_SEND) {
@@ -58,8 +57,7 @@
test_mach_assume_zero(mach_port_get_refs(mach_task_self(), name,
MACH_PORT_RIGHT_DEAD_NAME, &nd));
}
- if (type & (MACH_PORT_TYPE_RECEIVE|MACH_PORT_TYPE_SEND|
- MACH_PORT_TYPE_SEND_ONCE)) {
+ if (type & (MACH_PORT_TYPE_RECEIVE|MACH_PORT_TYPE_SEND)) {
test_mach_assume_zero(mach_port_dnrequest_info(mach_task_self(), name,
&dnrsiz, &dnreqs));
}
@@ -71,24 +69,28 @@
test_mach_assume_zero(mach_port_get_attributes(mach_task_self(), name,
MACH_PORT_RECEIVE_STATUS, (void*)&status, &cnt));
fprintf(stderr, "machport[0x%08x] = { R(%03u) S(%03u) SO(%03u) D(%03u) "
- "dnreqs(%03u) nsreq(%s) pdreq(%s) srights(%s) sorights(%03u) "
- "qlim(%03u) msgcount(%03u) mkscount(%03u) seqno(%03u) }: %s\n",
- name, nr, ns, nso, nd, dnreqs, status.mps_nsrequest ? "Y":"N",
- status.mps_pdrequest ? "Y":"N", status.mps_srights ? "Y":"N",
- status.mps_sorights, status.mps_qlimit, status.mps_msgcount,
- status.mps_mscount, status.mps_seqno, str);
+ "dnreqs(%03u) spreq(%s) nsreq(%s) pdreq(%s) srights(%s) "
+ "sorights(%03u) qlim(%03u) msgcount(%03u) mkscount(%03u) "
+ "seqno(%03u) }: %s %u\n", name, nr, ns, nso, nd, dnreqs,
+ type & MACH_PORT_TYPE_SPREQUEST ? "Y":"N",
+ status.mps_nsrequest ? "Y":"N", status.mps_pdrequest ? "Y":"N",
+ status.mps_srights ? "Y":"N", status.mps_sorights,
+ status.mps_qlimit, status.mps_msgcount, status.mps_mscount,
+ status.mps_seqno, str, line);
} else if (type & (MACH_PORT_TYPE_SEND|MACH_PORT_TYPE_SEND_ONCE|
MACH_PORT_TYPE_DEAD_NAME)) {
fprintf(stderr, "machport[0x%08x] = { R(%03u) S(%03u) SO(%03u) D(%03u) "
- "dnreqs(%03u) }: %s\n", name, nr, ns, nso, nd, dnreqs, str);
+ "dnreqs(%03u) spreq(%s) }: %s %u\n", name, nr, ns, nso, nd,
+ dnreqs, type & MACH_PORT_TYPE_SPREQUEST ? "Y":"N", str, line);
} else {
- fprintf(stderr, "machport[0x%08x] = { type(0x%08x) }: %s\n", name, type,
- str);
+ fprintf(stderr, "machport[0x%08x] = { type(0x%08x) }: %s %u\n", name,
+ type, str, line);
}
+ fflush(stderr);
}
-#define test_mach_debug_port(x) test_mach_debug_port(x, __func__)
+#define test_mach_debug_port(x) test_mach_debug_port(x, __func__, __LINE__)
#else
-#define test_mach_debug_port(x)
+#define test_mach_debug_port(x) (void)(x)
#endif
static dispatch_group_t g;
@@ -112,6 +114,11 @@
dispatch_source_set_event_handler(ds0, ^{
test_long("DISPATCH_MACH_SEND_DEAD",
dispatch_source_get_handle(ds0), mp);
+ dispatch_source_cancel(ds0);
+ });
+ dispatch_source_set_cancel_handler(ds0, ^{
+ kern_return_t kr = mach_port_deallocate(mach_task_self(), mp);
+ test_mach_error("mach_port_deallocate", kr, KERN_SUCCESS);
dispatch_release(ds0);
dispatch_group_leave(g);
});
@@ -431,6 +438,7 @@
dispatch_source_cancel(ds);
dispatch_release(ds);
test_long("DISPATCH_SOURCE_TYPE_MACH_RECV", received, 0);
+ dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
}
int
Modified: trunk/testing/dispatch_drift.c
===================================================================
--- trunk/testing/dispatch_drift.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_drift.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -28,19 +28,16 @@
#include <bsdtests.h>
#include "dispatch_test.h"
-#if TARGET_OS_EMBEDDED
-#define ACCEPTABLE_DRIFT 0.002
-#else
#define ACCEPTABLE_DRIFT 0.001
-#endif
int
main(int argc __attribute__((unused)), char* argv[] __attribute__((unused)))
{
__block uint32_t count = 0;
__block double last_jitter = 0;
- // 10 times a second
- uint64_t interval = 1000000000 / 10;
+ __block double drift_sum = 0;
+ // 100 times a second
+ uint64_t interval = 1000000000 / 100;
double interval_d = interval / 1000000000.0;
// for 25 seconds
unsigned int target = 25 / interval_d;
@@ -67,15 +64,17 @@
double goal = first + interval_d * count;
double jitter = goal - now;
double drift = jitter - last_jitter;
+ drift_sum += drift;
printf("%4d: jitter %f, drift %f\n", count, jitter, drift);
if (target <= ++count) {
- if (drift < 0) {
- drift = -drift;
+ drift_sum /= count - 1;
+ if (drift_sum < 0) {
+ drift_sum = -drift_sum;
}
double acceptable_drift = ACCEPTABLE_DRIFT;
- test_double_less_than("drift", drift, acceptable_drift);
+ test_double_less_than("drift", drift_sum, acceptable_drift);
test_stop();
}
last_jitter = jitter;
Modified: trunk/testing/dispatch_group.c
===================================================================
--- trunk/testing/dispatch_group.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_group.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -33,6 +33,14 @@
#define NSEC_PER_SEC 1000000000
#endif
+#if TARGET_OS_EMBEDDED
+#define LOOP_COUNT 50000
+#else
+#define LOOP_COUNT 200000
+#endif
+
+static void test_group_notify(void*);
+
dispatch_group_t
create_group(size_t count, int delay)
{
@@ -57,13 +65,10 @@
return group;
}
-int
-main(void)
+static void
+test_group(void *ctxt __attribute__((unused)))
{
long res;
-
- dispatch_test_start("Dispatch Group");
-
dispatch_group_t group;
group = create_group(100, 0);
@@ -95,15 +100,95 @@
test_ptr_notnull("dispatch_group_async", group);
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
- dispatch_queue_t m = dispatch_get_main_queue();
- dispatch_queue_t c = dispatch_get_current_queue();
- test_ptr("Notification Received", m, c);
- test_stop();
+ dispatch_test_current("Notification Received", dispatch_get_main_queue());
+ dispatch_async_f(dispatch_get_main_queue(), NULL, test_group_notify);
});
dispatch_release(group);
group = NULL;
+}
+static long completed;
+
+static void
+test_group_notify2(long cycle, dispatch_group_t tested)
+{
+ static dispatch_queue_t rq, nq;
+ static dispatch_once_t once;
+ dispatch_once(&once, ^{
+ rq = dispatch_queue_create("release", 0);
+ dispatch_suspend(rq);
+ nq = dispatch_queue_create("notify", 0);
+ });
+ dispatch_resume(rq);
+
+ // n=4 works great for a 4CPU Mac Pro, this might work for a wider range of
+ // systems.
+ const int n = 1 + arc4random() % 8;
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_queue_t qa[n];
+
+ dispatch_group_enter(group);
+ for (int i = 0; i < n; i++) {
+ char buf[48];
+ sprintf(buf, "T%ld-%d", cycle, i);
+ qa[i] = dispatch_queue_create(buf, 0);
+ }
+
+ __block float eh = 0;
+ for (int i = 0; i < n; i++) {
+ dispatch_queue_t q = qa[i];
+ dispatch_group_async(group, q, ^{
+ // Seems to trigger a little more reliably with some work being
+ // done in this block
+ eh = sin(M_1_PI / cycle);
+ });
+ }
+ dispatch_group_leave(group);
+
+ dispatch_group_notify(group, nq, ^{
+ completed = cycle;
+ dispatch_group_leave(tested);
+ });
+
+ // Releasing qa's queues here seems to avoid the race, so we are arranging
+ // for the current iteration's queues to be released on the next iteration.
+ dispatch_sync(rq, ^{});
+ dispatch_suspend(rq);
+ for (int i = 0; i < n; i++) {
+ dispatch_queue_t q = qa[i];
+ dispatch_async(rq, ^{ dispatch_release(q); });
+ }
+ dispatch_release(group);
+}
+
+static void
+test_group_notify(void *ctxt __attribute__((unused)))
+{
+ // <rdar://problem/11445820>
+ dispatch_group_t tested = dispatch_group_create();
+ test_ptr_notnull("dispatch_group_create", tested);
+ long i;
+ for (i = 0; i < LOOP_COUNT; i++) {
+ if (!((i+1) % (LOOP_COUNT/10))) {
+ fprintf(stderr, "#%ld\n", i+1);
+ }
+ dispatch_group_enter(tested);
+ test_group_notify2(i, tested);
+ if (dispatch_group_wait(tested, dispatch_time(DISPATCH_TIME_NOW,
+ NSEC_PER_SEC))) {
+ break;
+ }
+ }
+ test_long("dispatch_group_notify", i, LOOP_COUNT);
+ test_stop();
+}
+
+int
+main(void)
+{
+ dispatch_test_start("Dispatch Group");
+ dispatch_async_f(dispatch_get_main_queue(), NULL, test_group);
dispatch_main();
return 0;
Modified: trunk/testing/dispatch_io.c
===================================================================
--- trunk/testing/dispatch_io.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_io.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -65,7 +65,7 @@
#endif
static void
-test_io_close(int with_timer)
+test_io_close(int with_timer, bool from_path)
{
#define chunks 4
#define READSIZE (512*1024)
@@ -80,8 +80,8 @@
test_errno("open", errno, 0);
test_stop();
}
- if (fcntl(fd, F_NOCACHE, 1)) {
- test_errno("fcntl F_NOCACHE", errno, 0);
+ if (fcntl(fd, F_GLOBAL_NOCACHE, 1) == -1) {
+ test_errno("fcntl F_GLOBAL_NOCACHE", errno, 0);
test_stop();
}
struct stat sb;
@@ -94,12 +94,21 @@
dispatch_source_t t = NULL;
dispatch_group_t g = dispatch_group_create();
dispatch_group_enter(g);
- dispatch_io_t io = dispatch_io_create(DISPATCH_IO_RANDOM, fd,
- dispatch_get_global_queue(0, 0), ^(int error) {
+ void (^cleanup_handler)(int error) = ^(int error) {
test_errno("create error", error, 0);
dispatch_group_leave(g);
close(fd);
- });
+ };
+ dispatch_io_t io;
+ if (!from_path) {
+ io = dispatch_io_create(DISPATCH_IO_RANDOM, fd,
+ dispatch_get_global_queue(0, 0), cleanup_handler);
+ } else {
+#if DISPATCHTEST_IO_PATH
+ io = dispatch_io_create_with_path(DISPATCH_IO_RANDOM, path, O_RDONLY, 0,
+ dispatch_get_global_queue(0, 0), cleanup_handler);
+#endif
+ }
dispatch_io_set_high_water(io, READSIZE);
if (with_timer == 1) {
dispatch_io_set_low_water(io, READSIZE);
@@ -147,7 +156,8 @@
}
});
}
- dispatch_io_close(io, /* NO STOP */ 0);
+ dispatch_io_close(io, 0);
+ dispatch_io_close(io, 0);
dispatch_io_read(io, 0, 1, dispatch_get_global_queue(0,0),
^(bool done, dispatch_data_t d, int error) {
test_long("closed done", done, true);
@@ -332,8 +342,8 @@
test_stop();
}
// disable caching also for extra fd opened by dispatch_io_create_with_path
- if (fcntl(fd, F_GLOBAL_NOCACHE, 1)) {
- test_errno("fcntl F_GLOBAL_NOCACHE failed", errno, 0);
+ if (fcntl(fd, F_GLOBAL_NOCACHE, 1) == -1) {
+ test_errno("fcntl F_GLOBAL_NOCACHE", errno, 0);
test_stop();
}
switch (option) {
@@ -476,7 +486,7 @@
static void
test_read_many_files(void)
{
- char *paths[] = {"/usr/include", NULL};
+ char *paths[] = {"/usr/lib", NULL};
dispatch_group_t g = dispatch_group_create();
dispatch_semaphore_t s = dispatch_semaphore_create(maxopenfiles);
uint64_t start;
@@ -664,9 +674,15 @@
dispatch_test_start("Dispatch IO");
dispatch_async(dispatch_get_main_queue(), ^{
#if DISPATCHTEST_IO
- test_io_close(0 /* without timer */ );
- test_io_close(1 /* with channel interval */);
- test_io_close(2 /* with external timer */);
+ int i; bool from_path = false;
+ do {
+ for (i = 0; i < 3; i++) {
+ test_io_close(i, from_path);
+ }
+#if DISPATCHTEST_IO_PATH
+ from_path = !from_path;
+#endif
+ } while (from_path);
test_io_stop();
test_io_from_io();
test_io_read_write();
Modified: trunk/testing/dispatch_priority.c
===================================================================
--- trunk/testing/dispatch_priority.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_priority.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -34,32 +34,40 @@
static volatile int done;
#ifdef DISPATCH_QUEUE_PRIORITY_BACKGROUND // <rdar://problem/7439794>
-
-#define PRIORITIES 4
-char *labels[PRIORITIES] = { "BACKGROUND", "LOW", "DEFAULT", "HIGH" };
-int priorities[PRIORITIES] = { DISPATCH_QUEUE_PRIORITY_BACKGROUND, DISPATCH_QUEUE_PRIORITY_LOW, DISPATCH_QUEUE_PRIORITY_DEFAULT, DISPATCH_QUEUE_PRIORITY_HIGH };
-
+#define USE_BACKGROUND_PRIORITY 1
#else
+#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
+#endif
-#define PRIORITIES 3
-char *labels[PRIORITIES] = { "LOW", "DEFAULT", "HIGH" };
-int priorities[PRIORITIES] = { DISPATCH_QUEUE_PRIORITY_LOW, DISPATCH_QUEUE_PRIORITY_DEFAULT, DISPATCH_QUEUE_PRIORITY_HIGH };
+#define QUEUE_PRIORITY_PTHREAD INT_MAX
+#if DISPATCH_API_VERSION < 20100518 // <rdar://problem/7790099>
+#define DISPATCH_QUEUE_CONCURRENT NULL
#endif
#if TARGET_OS_EMBEDDED
-#define LOOP_COUNT 2000000
+#define LOOP_COUNT 5000000
+const int importance = 24; // priority 55
#else
#define LOOP_COUNT 100000000
+const int importance = 4; // priority 35
#endif
+char *labels[] = { "BACKGROUND", "LOW", "DEFAULT", "HIGH", };
+int levels[] = {
+ DISPATCH_QUEUE_PRIORITY_BACKGROUND, DISPATCH_QUEUE_PRIORITY_LOW,
+ DISPATCH_QUEUE_PRIORITY_DEFAULT, DISPATCH_QUEUE_PRIORITY_HIGH,
+};
+#define PRIORITIES (sizeof(levels)/sizeof(*levels))
+
static union {
long count;
char padding[64];
} counts[PRIORITIES];
-#define ITERATIONS (long)(PRIORITIES * n_blocks() * 0.50)
static volatile long iterations;
+static long total;
+static size_t prio0, priorities = PRIORITIES;
int
n_blocks(void)
@@ -78,11 +86,12 @@
void
histogram(void)
{
- long total = 0;
- size_t x,y;
- for (y = 0; y < PRIORITIES; ++y) {
+ long completed = 0;
+ size_t x, y, i;
+ printf("\n");
+ for (y = prio0; y < prio0 + priorities; ++y) {
printf("%s: %ld\n", labels[y], counts[y].count);
- total += counts[y].count;
+ completed += counts[y].count;
double fraction = (double)counts[y].count / (double)n_blocks();
double value = fraction * (double)80;
@@ -92,9 +101,19 @@
printf("\n");
}
- test_long("blocks completed", total, ITERATIONS);
- test_long_less_than("high priority precedence", counts[0].count,
- counts[PRIORITIES-1].count);
+ test_long("blocks completed", completed, total);
+ for (i = prio0; i < prio0 + priorities; i++) {
+ if (levels[i] == DISPATCH_QUEUE_PRIORITY_HIGH) {
+ test_long_less_than_or_equal("high priority precedence",
+ counts[i-2].count, counts[i].count);
+ }
+#if USE_BACKGROUND_PRIORITY
+ if (levels[i] == DISPATCH_QUEUE_PRIORITY_BACKGROUND) {
+ test_long_less_than_or_equal("background priority precedence",
+ counts[i].count, counts[i+2].count);
+ }
+#endif
+ }
}
void
@@ -115,8 +134,10 @@
__sync_add_and_fetch(&done, 1);
usleep(100000);
histogram();
- test_stop();
- exit(0);
+ dispatch_time_t delay = DISPATCH_TIME_NOW;
+ dispatch_after(delay, dispatch_get_main_queue(), ^{
+ test_stop();
+ });
}
}
}
@@ -136,43 +157,46 @@
main(int argc __attribute__((unused)), char* argv[] __attribute__((unused)))
{
dispatch_queue_t q[PRIORITIES];
- int i;
+ size_t i;
- iterations = ITERATIONS;
+#if !USE_BACKGROUND_PRIORITY
+ prio0++;
+ priorities--;
+#endif
+ iterations = total = (priorities * n_blocks()) * 0.50;
+
#if USE_SET_TARGET_QUEUE
dispatch_test_start("Dispatch Priority (Set Target Queue)");
- for(i = 0; i < PRIORITIES; i++) {
-#if DISPATCH_API_VERSION < 20100518 // <rdar://problem/7790099>
- q[i] = dispatch_queue_create(labels[i], NULL);
#else
+ dispatch_test_start("Dispatch Priority");
+#endif
+
+ for (i = prio0; i < prio0 + priorities; i++) {
+ dispatch_queue_t rq = dispatch_get_global_queue(levels[i], 0);
+#if USE_SET_TARGET_QUEUE
q[i] = dispatch_queue_create(labels[i], DISPATCH_QUEUE_CONCURRENT);
-#endif
test_ptr_notnull("q[i]", q[i]);
assert(q[i]);
dispatch_suspend(q[i]);
- dispatch_set_target_queue(q[i], dispatch_get_global_queue(priorities[i], 0));
-#if DISPATCH_API_VERSION < 20100518 // <rdar://problem/7790099>
- dispatch_queue_set_width(q[i], LONG_MAX);
+ dispatch_set_target_queue(q[i], rq);
+ if (DISPATCH_QUEUE_CONCURRENT != NULL) {
+ dispatch_queue_set_width(q[i], LONG_MAX);
+ }
+ dispatch_release(rq);
+#else
+ q[i] = rq;
#endif
}
-#else
- dispatch_test_start("Dispatch Priority");
- for(i = 0; i < PRIORITIES; i++) {
- q[i] = dispatch_get_global_queue(priorities[i], 0);
- }
-#endif
- for(i = 0; i < PRIORITIES; i++) {
+ for (i = prio0; i < prio0 + priorities; i++) {
submit_work(q[i], &counts[i].count);
}
-#if USE_SET_TARGET_QUEUE
- for(i = 0; i < PRIORITIES; i++) {
+ for (i = prio0; i < prio0 + priorities; i++) {
dispatch_resume(q[i]);
dispatch_release(q[i]);
}
-#endif
dispatch_main();
Modified: trunk/testing/dispatch_queue_finalizer.c
===================================================================
--- trunk/testing/dispatch_queue_finalizer.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_queue_finalizer.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -69,6 +69,7 @@
dispatch_queue_t q_null_context = dispatch_queue_create("com.apple.testing.finalizer.context_null", NULL);
dispatch_set_context(q_null_context, NULL);
+ dispatch_set_finalizer_f(q_null_context, never_call);
dispatch_release(q_null_context);
// Don't test k
Modified: trunk/testing/dispatch_suspend_timer.c
===================================================================
--- trunk/testing/dispatch_suspend_timer.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_suspend_timer.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -45,7 +45,7 @@
dispatch_test_start("Dispatch Suspend Timer");
dispatch_queue_t main_q = dispatch_get_main_queue();
- test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue());
+ //test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue());
__block int i = 0, i_prime = 0;
__block int j = 0;
Modified: trunk/testing/dispatch_test.c
===================================================================
--- trunk/testing/dispatch_test.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_test.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -19,15 +19,20 @@
*/
#include "dispatch_test.h"
+#include "bsdtests.h"
#ifdef __OBJC_GC__
#include <objc/objc-auto.h>
#endif
+#include <stdlib.h>
+#include <stdio.h>
#include <unistd.h>
#include <sys/event.h>
#include <assert.h>
+#include <dispatch/dispatch.h>
+
void test_start(const char* desc);
void
@@ -56,3 +61,10 @@
close(kq);
return r > 0;
}
+
+void
+_dispatch_test_current(const char* file, long line, const char* desc, dispatch_queue_t expected)
+{
+ dispatch_queue_t actual = dispatch_get_current_queue();
+ _test_ptr(file, line, desc, actual, expected);
+}
Modified: trunk/testing/dispatch_test.h
===================================================================
--- trunk/testing/dispatch_test.h 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_test.h 2012-08-09 05:09:03 UTC (rev 215)
@@ -20,6 +20,7 @@
#include <sys/cdefs.h>
#include <stdbool.h>
+#include <dispatch/dispatch.h>
#define test_group_wait(g) do { \
if (dispatch_group_wait(g, dispatch_time(DISPATCH_TIME_NOW, \
@@ -34,4 +35,7 @@
bool dispatch_test_check_evfilt_read_for_fd(int fd);
+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)
+
__END_DECLS
Modified: trunk/testing/dispatch_timer.c
===================================================================
--- trunk/testing/dispatch_timer.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_timer.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -46,7 +46,7 @@
const int stop_at = 3;
dispatch_queue_t main_q = dispatch_get_main_queue();
- test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue());
+ //test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue());
uint64_t j;
@@ -73,16 +73,13 @@
__block int i = 0;
dispatch_source_t s = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, main_q);
- dispatch_debug(s, "fresh timer:");
test_ptr_notnull("dispatch_source_create", s);
dispatch_source_set_timer(s, dispatch_time(DISPATCH_TIME_NOW, 0), NSEC_PER_SEC, 0);
dispatch_source_set_cancel_handler(s, ^{
test_ptr_notnull("cancel handler run", s);
- dispatch_debug(s, "pre release timer:");
dispatch_release(s);
- dispatch_debug(s, "post release timer:");
});
dispatch_source_set_event_handler(s, ^{
Modified: trunk/testing/dispatch_timer_bit31.c
===================================================================
--- trunk/testing/dispatch_timer_bit31.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_timer_bit31.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -34,7 +34,7 @@
dispatch_test_start("Dispatch Source Timer, bit 31");
dispatch_queue_t main_q = dispatch_get_main_queue();
- test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue());
+ //test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue());
struct timeval start_time;
Modified: trunk/testing/dispatch_timer_set_time.c
===================================================================
--- trunk/testing/dispatch_timer_set_time.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_timer_set_time.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -35,7 +35,7 @@
dispatch_test_start("Dispatch Update Timer");
dispatch_queue_t main_q = dispatch_get_main_queue();
- test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue());
+ //test_ptr("dispatch_get_main_queue", main_q, dispatch_get_current_queue());
__block int i = 0;
struct timeval start_time;
Added: trunk/testing/dispatch_transform.c
===================================================================
--- trunk/testing/dispatch_transform.c (rev 0)
+++ trunk/testing/dispatch_transform.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -0,0 +1,875 @@
+/*
+ * Copyright (c) 2011-2012 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include <bsdtests.h>
+
+#if DISPATCH_API_VERSION >= 20111008 && !TARGET_OS_EMBEDDED
+
+#include <Security/Security.h>
+
+#include <dispatch/dispatch.h>
+#include <dispatch/private.h>
+#include <fcntl.h>
+
+#define printf_data(p, s) ({ \
+ typeof(s) _i; \
+ for (_i=0; _i<s; _i++) { \
+ printf("%c", ((uint8_t *)p)[_i]); \
+ } \
+ printf("\n"); \
+})
+
+#define test_data_equal(a, b, c) ({ \
+ const void * ptr, * ptr2; \
+ size_t size, size2; \
+ dispatch_data_t map = dispatch_data_create_map(b, &ptr, &size); \
+ assert(map); \
+ dispatch_data_t map2 = dispatch_data_create_map(c, &ptr2, &size2); \
+ assert(map); \
+ test_long(a ": length", size, size2); \
+ test_long(a ": memcmp", memcmp(ptr, ptr2, size), 0); \
+ if (size != size2 || (memcmp(ptr, ptr2, size) != 0)) { \
+ printf_data(ptr, size); \
+ printf_data(ptr2, size2); \
+ } \
+ dispatch_release(map); \
+ dispatch_release(map2); \
+})
+
+static bool
+dispatch_data_equal(dispatch_data_t a, dispatch_data_t b)
+{
+ const void * ptr, * ptr2;
+ size_t size, size2;
+ bool equal = true;
+
+ dispatch_data_t map = dispatch_data_create_map(a, &ptr, &size); \
+ assert(map);
+ dispatch_data_t map2 = dispatch_data_create_map(b, &ptr2, &size2); \
+ assert(map2);
+
+ if (size == size2) {
+ if (memcmp(ptr, ptr2, size) != 0) {
+ equal = false;
+ }
+ } else {
+ equal = false;
+ }
+ dispatch_release(map);
+ dispatch_release(map2);
+ return equal;
+}
+
+static dispatch_data_t
+execute_sectransform(SecTransformRef transformRef, dispatch_data_t data)
+{
+ const void * bytes;
+ size_t size;
+
+ dispatch_data_t map = dispatch_data_create_map(data, &bytes, &size);
+ assert(map);
+
+ CFDataRef dataRef = CFDataCreate(kCFAllocatorDefault, bytes, size);
+ assert(dataRef);
+
+ dispatch_release(map);
+
+ SecTransformSetAttribute(transformRef, kSecTransformInputAttributeName, dataRef, NULL);
+
+ CFDataRef transformedDataRef = SecTransformExecute(transformRef, NULL);
+ assert(transformedDataRef);
+
+ CFRelease(dataRef);
+
+ dispatch_data_t output = dispatch_data_create(CFDataGetBytePtr(transformedDataRef), CFDataGetLength(transformedDataRef), dispatch_get_main_queue(), DISPATCH_DATA_DESTRUCTOR_DEFAULT);
+ CFRelease(transformedDataRef);
+
+ return output;
+}
+
+#pragma mark - UTF tests
+
+static uint8_t utf8[] = {
+ 0x53, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x6b, 0x73, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x2e, 0x20, 0xeb, 0x84, 0x88, 0xeb, 0xac,
+ 0xb4, 0x20, 0xec, 0x98, 0xa4, 0xeb, 0x9e, 0x98, 0x20, 0xea, 0xb7, 0xb8, 0xeb, 0xa6, 0xac, 0xea, 0xb3, 0xa0, 0x20, 0xea, 0xb7,
+ 0xb8, 0x20, 0xeb, 0x8f, 0x99, 0xec, 0x95, 0x88, 0x20, 0xeb, 0xa7, 0x9b, 0xec, 0x9e, 0x88, 0xeb, 0x8a, 0x94, 0x20, 0xec, 0x83,
+ 0x9d, 0xec, 0x84, 0xa0, 0xec, 0x9d, 0x80, 0x20, 0xea, 0xb3, 0xa0, 0xeb, 0xa7, 0x88, 0xec, 0x9b, 0xa0, 0xec, 0x96, 0xb4, 0x2e,
+ 0x20, 0xf0, 0x9f, 0x98, 0x84, 0xf0, 0x9f, 0x98, 0x8a, 0xf0, 0x9f, 0x98, 0x83, 0xe2, 0x98, 0xba, 0xf0, 0x9f, 0x98, 0x89, 0xf0,
+ 0x9f, 0x98, 0x8d, 0xf0, 0x9f, 0x92, 0xa8, 0xf0, 0x9f, 0x92, 0xa9, 0xf0, 0x9f, 0x91, 0x8e, 0x2e,
+};
+
+static uint16_t utf16[] = {
+ 0xfeff, 0x53, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x6b, 0x73, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x2e, 0x20, 0xb108, 0xbb34, 0x20,
+ 0xc624, 0xb798, 0x20, 0xadf8, 0xb9ac, 0xace0, 0x20, 0xadf8, 0x20, 0xb3d9, 0xc548, 0x20, 0xb9db, 0xc788, 0xb294, 0x20, 0xc0dd,
+ 0xc120, 0xc740, 0x20, 0xace0, 0xb9c8, 0xc6e0, 0xc5b4, 0x2e, 0x20, 0xd83d, 0xde04, 0xd83d, 0xde0a, 0xd83d, 0xde03, 0x263a, 0xd83d,
+ 0xde09, 0xd83d, 0xde0d, 0xd83d, 0xdca8, 0xd83d, 0xdca9, 0xd83d, 0xdc4e, 0x2e,
+};
+
+static uint16_t utf16be[] = {
+ 0xfffe, 0x5300, 0x6f00, 0x2000, 0x6c00, 0x6f00, 0x6e00, 0x6700, 0x2000, 0x6100, 0x6e00, 0x6400, 0x2000, 0x7400, 0x6800, 0x6100,
+ 0x6e00, 0x6b00, 0x7300, 0x2000, 0x6600, 0x6f00, 0x7200, 0x2000, 0x6100, 0x6c00, 0x6c00, 0x2000, 0x7400, 0x6800, 0x6500, 0x2000,
+ 0x6600, 0x6900, 0x7300, 0x6800, 0x2e00, 0x2000, 0x8b1, 0x34bb, 0x2000, 0x24c6, 0x98b7, 0x2000, 0xf8ad, 0xacb9, 0xe0ac, 0x2000,
+ 0xf8ad, 0x2000, 0xd9b3, 0x48c5, 0x2000, 0xdbb9, 0x88c7, 0x94b2, 0x2000, 0xddc0, 0x20c1, 0x40c7, 0x2000, 0xe0ac, 0xc8b9, 0xe0c6,
+ 0xb4c5, 0x2e00, 0x2000, 0x3dd8, 0x4de, 0x3dd8, 0xade, 0x3dd8, 0x3de, 0x3a26, 0x3dd8, 0x9de, 0x3dd8, 0xdde, 0x3dd8, 0xa8dc,
+ 0x3dd8, 0xa9dc, 0x3dd8, 0x4edc, 0x2e00,
+};
+
+// Invalid due to half missing surrogate
+static uint16_t utf16le_invalid[] = {
+ 0xfeff, 0x53, 0x6f, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x6b, 0x73, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x2e, 0x20, 0xb108, 0xbb34, 0x20,
+ 0xc624, 0xb798, 0x20, 0xadf8, 0xb9ac, 0xace0, 0x20, 0xadf8, 0x20, 0xb3d9, 0xc548, 0x20, 0xb9db, 0xc788, 0xb294, 0x20, 0xc0dd,
+ 0xc120, 0xc740, 0x20, 0xace0, 0xb9c8, 0xc6e0, 0xc5b4, 0x2e, 0x20, 0xd83d, 0xde04, 0xd83d, 0xde0a, 0xd83d, 0xde03, 0x263a, 0xd83d,
+ 0xde09, 0xd83d, 0xde0d, 0xd83d, 0xdca8, 0xd83d, 0xd83d, 0xdc4e, 0x2e,
+};
+
+void
+invalid_utf8_test(void * context)
+{
+ dispatch_data_t utf8_data = dispatch_data_create(utf8 + sizeof(utf8) - 8, 8, NULL, ^{});
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF8, DISPATCH_DATA_FORMAT_TYPE_UTF16LE);
+ test_ptr_null("dispatch_data_create_with_transform (UTF8 (invalid start) -> UTF16LE)", transformed);
+
+ dispatch_release(utf8_data);
+
+ (void)context;
+}
+
+void
+truncated_utf8_test(void * context)
+{
+ dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8) - 3, NULL, ^{});
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF8, DISPATCH_DATA_FORMAT_TYPE_UTF16LE);
+ test_ptr_null("dispatch_data_create_with_transform (UTF8 (truncated) -> UTF16LE)", transformed);
+
+ dispatch_release(utf8_data);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, invalid_utf8_test);
+}
+
+void
+invalid_utf16le_surrogate_test(void * context)
+{
+ dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
+ dispatch_data_t utf16_data = dispatch_data_create(utf16le_invalid, sizeof(utf16le_invalid), NULL, ^{});
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF16LE, DISPATCH_DATA_FORMAT_TYPE_UTF8);
+ test_ptr_null("dispatch_data_create_with_transform (UTF16LE (missing surrogate) -> UTF8)", transformed);
+
+ dispatch_release(utf16_data);
+ dispatch_release(utf8_data);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, truncated_utf8_test);
+}
+
+void
+invalid_utf16le_test(void * context)
+{
+ dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
+ dispatch_data_t utf16_data = dispatch_data_create(utf16, (sizeof(utf16) % 2) + 1, NULL, ^{});
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF16LE, DISPATCH_DATA_FORMAT_TYPE_UTF8);
+ test_ptr_null("dispatch_data_create_with_transform (UTF16LE (invalid) -> UTF8)", transformed);
+
+ dispatch_release(utf16_data);
+ dispatch_release(utf8_data);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, invalid_utf16le_surrogate_test);
+}
+
+void
+utf16le_bytes_to_utf8_test(void * context)
+{
+ dispatch_data_t utf16_data = dispatch_data_empty;
+ dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
+
+ size_t i;
+ for (i=0; i<sizeof(utf16); i++) {
+ dispatch_data_t new = dispatch_data_create((char*)utf16 + i, 1, NULL, ^{});
+ dispatch_data_t concat = dispatch_data_create_concat(utf16_data, new);
+ dispatch_release(new);
+ dispatch_release(utf16_data);
+ utf16_data = concat;
+ }
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF8);
+ test_ptr_notnull("dispatch_data_create_with_transform (UTF16LE (any, single bytes) -> UTF8)", transformed);
+ test_data_equal("utf16le_bytes_to_utf8_test", transformed, utf8_data);
+
+ dispatch_release(transformed);
+ dispatch_release(utf8_data);
+ dispatch_release(utf16_data);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, invalid_utf16le_test);
+}
+
+void
+utf8_bytes_to_utf16le_test(void * context)
+{
+ dispatch_data_t utf8_data = dispatch_data_empty;
+ dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{});
+
+ size_t i;
+ for (i=0; i<sizeof(utf8); i++) {
+ dispatch_data_t new = dispatch_data_create(utf8 + i, 1, NULL, ^{});
+ dispatch_data_t concat = dispatch_data_create_concat(utf8_data, new);
+ dispatch_release(new);
+ dispatch_release(utf8_data);
+ utf8_data = concat;
+ }
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF16LE);
+ test_ptr_notnull("dispatch_data_create_with_transform (UTF8 (any, single bytes) -> UTF16LE)", transformed);
+ test_data_equal("utf8_bytes_to_utf16le_test", transformed, utf16_data);
+
+ dispatch_release(transformed);
+ dispatch_release(utf8_data);
+ dispatch_release(utf16_data);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16le_bytes_to_utf8_test);
+}
+
+void
+utf16be_detect_to_utf16le_test(void * context)
+{
+ dispatch_data_t utf16be_data = dispatch_data_create(utf16be, sizeof(utf16be), NULL, ^{});
+ dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{});
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf16be_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF16LE);
+ test_ptr_notnull("dispatch_data_create_with_transform (UTF16BE (any) -> UTF16LE)", transformed);
+ test_data_equal("utf16be_detect_to_utf16le_test", transformed, utf16_data);
+
+ dispatch_release(transformed);
+ dispatch_release(utf16be_data);
+ dispatch_release(utf16_data);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf8_bytes_to_utf16le_test);
+}
+
+void
+utf16be_detect_to_utf8_test(void * context)
+{
+ dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
+ dispatch_data_t utf16_data = dispatch_data_create(utf16be, sizeof(utf16be), NULL, ^{});
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF8);
+ test_ptr_notnull("dispatch_data_create_with_transform (UTF16BE (any) -> UTF8)", transformed);
+ test_data_equal("utf16be_detect_to_utf8_test", transformed, utf8_data);
+
+ dispatch_release(transformed);
+ dispatch_release(utf16_data);
+ dispatch_release(utf8_data);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16be_detect_to_utf16le_test);
+}
+
+void
+utf16le_detect_to_utf8_test(void * context)
+{
+ dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
+ dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{});
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF_ANY, DISPATCH_DATA_FORMAT_TYPE_UTF8);
+ test_ptr_notnull("dispatch_data_create_with_transform (UTF16LE (any) -> UTF8)", transformed);
+ test_data_equal("utf16le_detect_to_utf8_test", transformed, utf8_data);
+
+ dispatch_release(transformed);
+ dispatch_release(utf16_data);
+ dispatch_release(utf8_data);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16be_detect_to_utf8_test);
+}
+
+void
+utf16be_to_utf8_test(void * context)
+{
+ dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
+ dispatch_data_t utf16_data = dispatch_data_create(utf16be, sizeof(utf16be), NULL, ^{});
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF16BE, DISPATCH_DATA_FORMAT_TYPE_UTF8);
+ test_ptr_notnull("dispatch_data_create_with_transform (UTF16BE -> UTF8)", transformed);
+ test_data_equal("utf16be_to_utf8_test", transformed, utf8_data);
+
+ dispatch_release(transformed);
+ dispatch_release(utf16_data);
+ dispatch_release(utf8_data);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16le_detect_to_utf8_test);
+}
+
+void
+utf16le_to_utf8_test(void * context)
+{
+ dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
+ dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{});
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf16_data, DISPATCH_DATA_FORMAT_TYPE_UTF16LE, DISPATCH_DATA_FORMAT_TYPE_UTF8);
+ test_ptr_notnull("dispatch_data_create_with_transform (UTF16LE -> UTF8)", transformed);
+ test_data_equal("utf16le_to_utf8_test", transformed, utf8_data);
+
+ dispatch_release(transformed);
+ dispatch_release(utf16_data);
+ dispatch_release(utf8_data);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16be_to_utf8_test);
+}
+
+void
+utf8_to_utf16be_test(void * context)
+{
+ dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
+ dispatch_data_t utf16_data = dispatch_data_create(utf16be, sizeof(utf16be), NULL, ^{});
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF8, DISPATCH_DATA_FORMAT_TYPE_UTF16BE);
+ test_ptr_notnull("dispatch_data_create_with_transform (UTF8 -> UTF16BE)", transformed);
+ test_data_equal("utf8_to_utf16be_test", transformed, utf16_data);
+
+ dispatch_release(transformed);
+ dispatch_release(utf16_data);
+ dispatch_release(utf8_data);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf16le_to_utf8_test);
+}
+
+void
+utf8_to_utf16le_test(void * context)
+{
+ dispatch_data_t utf8_data = dispatch_data_create(utf8, sizeof(utf8), NULL, ^{});
+ dispatch_data_t utf16_data = dispatch_data_create(utf16, sizeof(utf16), NULL, ^{});
+
+ dispatch_data_t transformed = dispatch_data_create_with_transform(utf8_data, DISPATCH_DATA_FORMAT_TYPE_UTF8, DISPATCH_DATA_FORMAT_TYPE_UTF16LE);
+ test_ptr_notnull("dispatch_data_create_with_transform (UTF8 -> UTF16LE)", transformed);
+ test_data_equal("utf8_to_utf16le_test", transformed, utf16_data);
+
+ dispatch_release(transformed);
+ dispatch_release(utf16_data);
+ dispatch_release(utf8_data);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf8_to_utf16be_test);
+}
+
+#pragma mark - base32 tests
+
+void
+decode32_corrupt_test(void * context)
+{
+ dispatch_group_enter((dispatch_group_t)context);
+
+ int fd = open("/dev/random", O_RDONLY);
+ assert(fd >= 0);
+
+ dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) {
+ assert(error == 0);
+
+ SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL);
+ assert(transformRef);
+
+ dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
+ assert(sectransform_data);
+ CFRelease(transformRef);
+
+ void * corrupt_buffer = malloc(dispatch_data_get_size(sectransform_data));
+ const void * source;
+ size_t size;
+
+ dispatch_data_t map = dispatch_data_create_map(sectransform_data, &source, &size);
+ memcpy(corrupt_buffer, source, size);
+
+ size_t i;
+ for (i=0; i<size; i += (arc4random() % (int)(size * 0.05))) {
+ char x = arc4random() & 0xff;
+ while ((x >= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x >= '0' && x <= '9') || x == '/' || x == '+' || x == '=') {
+ x = arc4random() & 0xff;
+ }
+
+ ((char*)corrupt_buffer)[i] = x;
+ }
+
+ dispatch_release(map);
+ dispatch_release(sectransform_data);
+
+ dispatch_data_t corrupt_data = dispatch_data_create(corrupt_buffer, size, dispatch_get_main_queue(), DISPATCH_DATA_DESTRUCTOR_FREE);
+
+ dispatch_data_t transform_data = dispatch_data_create_with_transform(corrupt_data, DISPATCH_DATA_FORMAT_TYPE_BASE32, DISPATCH_DATA_FORMAT_TYPE_NONE);
+ test_ptr_null("decode32_corrupt_test: dispatch_data_create_with_transform", transform_data);
+
+ dispatch_release(corrupt_data);
+
+ close(fd);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, utf8_to_utf16le_test);
+ dispatch_group_leave((dispatch_group_t)context);
+ });
+}
+
+void
+chunking_decode32_test(void * context)
+{
+ (void)context;
+
+ int fd = open("/dev/random", O_RDONLY);
+ assert(fd >= 0);
+
+ dispatch_data_t __block data = dispatch_data_empty;
+
+ int i;
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_queue_t queue = dispatch_queue_create("read", 0);
+ for (i=0; i<4096; i++) {
+ dispatch_group_enter(group);
+
+ dispatch_read(fd, 1, queue, ^(dispatch_data_t d, int error) {
+ assert(error == 0);
+
+ dispatch_data_t concat = dispatch_data_create_concat(data, d);
+ dispatch_release(data);
+ data = concat;
+ dispatch_group_leave(group);
+ });
+ }
+ dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
+ dispatch_release(queue);
+ dispatch_release(group);
+
+ SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL);
+ assert(transformRef);
+
+ dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
+ assert(sectransform_data);
+ CFRelease(transformRef);
+
+ dispatch_data_t transformed_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE32, DISPATCH_DATA_FORMAT_TYPE_NONE);
+ test_ptr_notnull("chunking_decode32_test: dispatch_data_create_with_transform", transformed_data);
+ test_data_equal("chunking_decode32_test", transformed_data, data);
+
+ dispatch_release(sectransform_data);
+ dispatch_release(transformed_data);
+ dispatch_release(data);
+
+ close(fd);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, decode32_corrupt_test);
+}
+
+void
+chunking_encode32_test(void * context)
+{
+ (void)context;
+
+ int fd = open("/dev/random", O_RDONLY);
+ assert(fd >= 0);
+
+ dispatch_data_t __block data = dispatch_data_empty;
+
+ int i;
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_queue_t queue = dispatch_queue_create("read", 0);
+ for (i=0; i<4096; i++) {
+ dispatch_group_enter(group);
+
+ dispatch_read(fd, 1, queue, ^(dispatch_data_t d, int error) {
+ assert(error == 0);
+
+ dispatch_data_t concat = dispatch_data_create_concat(data, d);
+ dispatch_release(data);
+ data = concat;
+ dispatch_group_leave(group);
+ });
+ }
+ dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
+ dispatch_release(queue);
+ dispatch_release(group);
+
+ SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL);
+ assert(transformRef);
+
+ dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
+ assert(sectransform_data);
+ CFRelease(transformRef);
+
+ dispatch_data_t transformed_data = dispatch_data_create_with_transform(data, DISPATCH_DATA_FORMAT_TYPE_NONE, DISPATCH_DATA_FORMAT_TYPE_BASE32);
+ test_ptr_notnull("chunking_encode32_test: dispatch_data_create_with_transform", transformed_data);
+ test_data_equal("chunking_encode32_test", transformed_data, sectransform_data);
+
+ dispatch_release(sectransform_data);
+ dispatch_release(transformed_data);
+ dispatch_release(data);
+
+ close(fd);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, chunking_decode32_test);
+}
+
+void
+decode32_test(void * context)
+{
+ dispatch_group_enter((dispatch_group_t)context);
+
+ int fd = open("/dev/random", O_RDONLY);
+ assert(fd >= 0);
+
+ dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) {
+ assert(error == 0);
+
+ SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL);
+ assert(transformRef);
+
+ dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
+ assert(sectransform_data);
+ CFRelease(transformRef);
+
+ dispatch_data_t transform_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE32, DISPATCH_DATA_FORMAT_TYPE_NONE);
+ test_ptr_notnull("decode32_test: dispatch_data_create_with_transform", transform_data);
+ test_data_equal("decode32_test", transform_data, data);
+
+ dispatch_release(sectransform_data);
+ dispatch_release(transform_data);
+
+ close(fd);
+
+ dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, chunking_encode32_test);
+ dispatch_group_leave((dispatch_group_t)context);
+ });
+}
+
+void
+encode32_test(void * context)
+{
+ dispatch_group_enter((dispatch_group_t)context);
+
+ int fd = open("/dev/random", O_RDONLY);
+ assert(fd >= 0);
+
+ dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) {
+ assert(error == 0);
+
+ SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase32Encoding, NULL);
+ assert(transformRef);
+
+ dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
+ assert(sectransform_data);
+ CFRelease(transformRef);
+
+ dispatch_data_t transformed_data = dispatch_data_create_with_transform(data, DISPATCH_DATA_FORMAT_TYPE_NONE, DISPATCH_DATA_FORMAT_TYPE_BASE32);
+ test_ptr_notnull("encode32_test: dispatch_data_create_with_transform", transformed_data);
+ test_data_equal("encode32_test", transformed_data, sectransform_data);
+
+ dispatch_release(sectransform_data);
+ dispatch_release(transformed_data);
+
+ close(fd);
+
+ dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, decode32_test);
+ dispatch_group_leave((dispatch_group_t)context);
+ });
+}
+
+#pragma mark - base64 tests
+
+void
+decode64_loop_test(void * context)
+{
+ if (getenv("LOOP_SKIP") == NULL)
+ {
+ int fd = open("/dev/random", O_RDONLY);
+ assert(fd >= 0);
+
+ dispatch_semaphore_t sema = dispatch_semaphore_create(0);
+ size_t i, __block tests = 0;
+
+ for (i=1; i<4097; i++) {
+ dispatch_read(fd, i, dispatch_get_global_queue(0, 0), ^(dispatch_data_t data, int error) {
+ assert(error == 0);
+
+ SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL);
+ assert(transformRef);
+
+ dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
+ assert(sectransform_data);
+ CFRelease(transformRef);
+
+ dispatch_data_t transform_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE64, DISPATCH_DATA_FORMAT_TYPE_NONE);
+ if (dispatch_data_equal(transform_data, data)) {
+ tests++;
+ }
+
+ dispatch_release(sectransform_data);
+ dispatch_release(transform_data);
+
+ dispatch_semaphore_signal(sema);
+ });
+ dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
+ }
+ dispatch_release(sema);
+ close(fd);
+ test_long("decode64_loop_test", tests, 4096);
+ }
+ dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, encode32_test);
+}
+
+void
+decode64_corrupt_test(void * context)
+{
+ dispatch_group_enter((dispatch_group_t)context);
+
+ int fd = open("/dev/random", O_RDONLY);
+ assert(fd >= 0);
+
+ dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) {
+ assert(error == 0);
+
+ SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL);
+ assert(transformRef);
+
+ dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
+ assert(sectransform_data);
+ CFRelease(transformRef);
+
+ void * corrupt_buffer = malloc(dispatch_data_get_size(sectransform_data));
+ const void * source;
+ size_t size;
+
+ dispatch_data_t map = dispatch_data_create_map(sectransform_data, &source, &size);
+ memcpy(corrupt_buffer, source, size);
+
+ size_t i;
+ for (i=0; i<size; i += (arc4random() % (int)(size * 0.05))) {
+ char x = arc4random() & 0xff;
+ while ((x >= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z') || (x >= '0' && x <= '9') || x == '/' || x == '+' || x == '=') {
+ x = arc4random() & 0xff;
+ }
+
+ ((char*)corrupt_buffer)[i] = x;
+ }
+
+ dispatch_release(map);
+ dispatch_release(sectransform_data);
+
+ dispatch_data_t corrupt_data = dispatch_data_create(corrupt_buffer, size, dispatch_get_main_queue(), DISPATCH_DATA_DESTRUCTOR_FREE);
+
+ dispatch_data_t transform_data = dispatch_data_create_with_transform(corrupt_data, DISPATCH_DATA_FORMAT_TYPE_BASE64, DISPATCH_DATA_FORMAT_TYPE_NONE);
+ test_ptr_null("decode64_corrupt_test: dispatch_data_create_with_transform", transform_data);
+
+ dispatch_release(corrupt_data);
+
+ close(fd);
+
+ dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, decode64_loop_test);
+ dispatch_group_leave((dispatch_group_t)context);
+ });
+}
+
+void
+chunking_decode64_test(void * context)
+{
+ (void)context;
+
+ int fd = open("/dev/random", O_RDONLY);
+ assert(fd >= 0);
+
+ dispatch_data_t __block data = dispatch_data_empty;
+
+ int i;
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_queue_t queue = dispatch_queue_create("read", 0);
+ for (i=0; i<4096; i++) {
+ dispatch_group_enter(group);
+
+ dispatch_read(fd, 1, queue, ^(dispatch_data_t d, int error) {
+ assert(error == 0);
+
+ dispatch_data_t concat = dispatch_data_create_concat(data, d);
+ dispatch_release(data);
+ data = concat;
+ dispatch_group_leave(group);
+ });
+ }
+ dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
+ dispatch_release(queue);
+ dispatch_release(group);
+
+ SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL);
+ assert(transformRef);
+
+ dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
+ assert(sectransform_data);
+ CFRelease(transformRef);
+
+ dispatch_data_t transformed_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE64, DISPATCH_DATA_FORMAT_TYPE_NONE);
+ test_ptr_notnull("chunking_decode64_test: dispatch_data_create_with_transform", transformed_data);
+ test_data_equal("chunking_decode64_test", transformed_data, data);
+
+ dispatch_release(sectransform_data);
+ dispatch_release(transformed_data);
+ dispatch_release(data);
+
+ close(fd);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, decode64_corrupt_test);
+}
+
+void
+chunking_encode64_test(void * context)
+{
+ (void)context;
+
+ int fd = open("/dev/random", O_RDONLY);
+ assert(fd >= 0);
+
+ dispatch_data_t __block data = dispatch_data_empty;
+
+ int i;
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_queue_t queue = dispatch_queue_create("read", 0);
+ for (i=0; i<4097; i++) {
+ dispatch_group_enter(group);
+
+ dispatch_read(fd, 1, queue, ^(dispatch_data_t d, int error) {
+ assert(error == 0);
+
+ dispatch_data_t concat = dispatch_data_create_concat(data, d);
+ dispatch_release(data);
+ data = concat;
+ dispatch_group_leave(group);
+ });
+ }
+ dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
+ dispatch_release(queue);
+ dispatch_release(group);
+
+ SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL);
+ assert(transformRef);
+
+ dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
+ assert(sectransform_data);
+ CFRelease(transformRef);
+
+ dispatch_data_t transformed_data = dispatch_data_create_with_transform(data, DISPATCH_DATA_FORMAT_TYPE_NONE, DISPATCH_DATA_FORMAT_TYPE_BASE64);
+ test_ptr_notnull("chunking_encode64_test: dispatch_data_create_with_transform", transformed_data);
+ test_data_equal("chunking_encode64_test", transformed_data, sectransform_data);
+
+ dispatch_release(sectransform_data);
+ dispatch_release(transformed_data);
+ dispatch_release(data);
+
+ close(fd);
+
+ dispatch_group_async_f(context, dispatch_get_main_queue(), context, chunking_decode64_test);
+}
+
+void
+decode64_test(void * context)
+{
+ dispatch_group_enter((dispatch_group_t)context);
+
+ int fd = open("/dev/random", O_RDONLY);
+ assert(fd >= 0);
+
+ dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) {
+ assert(error == 0);
+
+ SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL);
+ assert(transformRef);
+
+ dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
+ assert(sectransform_data);
+ CFRelease(transformRef);
+
+ dispatch_data_t transform_data = dispatch_data_create_with_transform(sectransform_data, DISPATCH_DATA_FORMAT_TYPE_BASE64, DISPATCH_DATA_FORMAT_TYPE_NONE);
+ test_ptr_notnull("decode64_test: dispatch_data_create_with_transform", transform_data);
+ test_data_equal("decode64_test", transform_data, data);
+
+ dispatch_release(sectransform_data);
+ dispatch_release(transform_data);
+
+ close(fd);
+
+ dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, chunking_encode64_test);
+ dispatch_group_leave((dispatch_group_t)context);
+ });
+}
+
+void
+encode64_test(void * context)
+{
+ dispatch_group_enter((dispatch_group_t)context);
+
+ int fd = open("/dev/random", O_RDONLY);
+ assert(fd >= 0);
+
+ dispatch_read(fd, 4096, dispatch_get_main_queue(), ^(dispatch_data_t data, int error) {
+ assert(error == 0);
+
+ SecTransformRef transformRef = SecEncodeTransformCreate(kSecBase64Encoding, NULL);
+ assert(transformRef);
+
+ dispatch_data_t sectransform_data = execute_sectransform(transformRef, data);
+ assert(sectransform_data);
+ CFRelease(transformRef);
+
+ dispatch_data_t transformed_data = dispatch_data_create_with_transform(data, DISPATCH_DATA_FORMAT_TYPE_NONE, DISPATCH_DATA_FORMAT_TYPE_BASE64);
+ test_ptr_notnull("encode64_test: dispatch_data_create_with_transform", transformed_data);
+ test_data_equal("encode64_test", transformed_data, sectransform_data);
+
+ dispatch_release(sectransform_data);
+ dispatch_release(transformed_data);
+
+ close(fd);
+
+ dispatch_group_async_f((dispatch_group_t)context, dispatch_get_main_queue(), context, decode64_test);
+ dispatch_group_leave((dispatch_group_t)context);
+ });
+}
+
+#pragma mark - main
+
+int
+main(void)
+{
+ test_start("Dispatch data transforms test");
+
+ dispatch_group_t group = dispatch_group_create();
+ dispatch_group_async_f(group, dispatch_get_main_queue(), group, encode64_test);
+
+ dispatch_group_notify(group, dispatch_get_main_queue(), ^{
+ dispatch_release(group);
+ test_stop();
+ exit(0);
+ });
+
+ dispatch_main();
+ return 0;
+}
+
+#else
+
+int
+main(void)
+{
+ test_skip("Dispatch data transforms test");
+ return 0;
+}
+
+#endif
+
Modified: trunk/testing/dispatch_vm.c
===================================================================
--- trunk/testing/dispatch_vm.c 2012-08-09 05:08:56 UTC (rev 214)
+++ trunk/testing/dispatch_vm.c 2012-08-09 05:09:03 UTC (rev 215)
@@ -29,6 +29,7 @@
#include <time.h>
#include <dispatch/dispatch.h>
+#include <dispatch/private.h>
#include <bsdtests.h>
#include "dispatch_test.h"
@@ -36,7 +37,7 @@
#if defined(DISPATCH_SOURCE_TYPE_VM) && defined(NOTE_VM_PRESSURE)
#if TARGET_OS_EMBEDDED
-#define ALLOC_SIZE ((size_t)(1024*1024*5ul)) // 5MB
+#define ALLOC_SIZE ((size_t)(1024*1024*1ul)) // 1MB
#define NOTIFICATIONS 1
#else
#define ALLOC_SIZE ((size_t)(1024*1024*20ul)) // 20MB
@@ -60,7 +61,7 @@
#define log_msg(msg, ...) \
do { \
- fprintf(stderr, "[%2ds] " msg, (int)(time(NULL) - initial), ## __VA_ARGS__);\
+ fprintf(stderr, "[%2ds] " msg, (int)(time(NULL) - initial), ##__VA_ARGS__);\
} while (0)
static bool
@@ -102,7 +103,7 @@
int
main(void)
{
- dispatch_test_start("Dispatch VM Pressure test"); // <rdar://problem/7000945>
+ dispatch_test_start("Dispatch VM Pressure test"); // rdar://problem/7000945
if (!dispatch_test_check_evfilt_vm()) {
test_skip("EVFILT_VM not supported");
test_stop();
@@ -142,7 +143,8 @@
dispatch_resume(vm_source);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC),
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- while (handler_call_count < NOTIFICATIONS && page_count < max_page_count) {
+ while (handler_call_count < NOTIFICATIONS &&
+ page_count < max_page_count) {
void *p = valloc(ALLOC_SIZE);
if (!p) {
break;
@@ -163,9 +165,12 @@
dispatch_async(vm_queue, ^{cleanup();});
return;
}
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), vm_queue, ^{
- test_long_less_than("VM Pressure fired", NOTIFICATIONS - 1, handler_call_count);
- test_long_less_than("VM Pressure stopped firing", handler_call_count, 4);
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC),
+ vm_queue, ^{
+ test_long_greater_than_or_equal("VM Pressure fired",
+ handler_call_count, NOTIFICATIONS);
+ test_long_less_than("VM Pressure stopped firing",
+ handler_call_count, 4);
cleanup();
});
});
@@ -176,7 +181,8 @@
int
main(void)
{
- dispatch_test_start("Dispatch VM Pressure test - No DISPATCH_SOURCE_TYPE_VM");
+ dispatch_test_start("Dispatch VM Pressure test"
+ " - No DISPATCH_SOURCE_TYPE_VM");
test_stop();
return 0;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/libdispatch-changes/attachments/20120808/59c32e7d/attachment-0001.html>
More information about the libdispatch-changes
mailing list