diff options
Diffstat (limited to '')
-rw-r--r-- | test/abts.c | 153 | ||||
-rw-r--r-- | test/abts.h | 45 | ||||
-rw-r--r-- | test/testatomic.c | 147 | ||||
-rw-r--r-- | test/testdir.c | 49 | ||||
-rw-r--r-- | test/testencode.c | 70 | ||||
-rw-r--r-- | test/testescape.c | 2 | ||||
-rw-r--r-- | test/testfile.c | 986 | ||||
-rw-r--r-- | test/testmutexscope.c | 4 | ||||
-rw-r--r-- | test/testpoll.c | 30 | ||||
-rw-r--r-- | test/testproc.c | 3 | ||||
-rw-r--r-- | test/testshm.c | 74 | ||||
-rw-r--r-- | test/testshm.h | 56 | ||||
-rw-r--r-- | test/testshmconsumer.c | 21 | ||||
-rw-r--r-- | test/testshmproducer.c | 7 |
14 files changed, 1406 insertions, 241 deletions
diff --git a/test/abts.c b/test/abts.c index ef9f9db..e03ccc4 100644 --- a/test/abts.c +++ b/test/abts.c @@ -76,6 +76,10 @@ static void end_suite(abts_suite *suite) fprintf(stdout, "\b"); fflush(stdout); } + if (last->skipped > 0) { + fprintf(stdout, "SKIPPED %d of %d\n", last->skipped, last->num_test); + fflush(stdout); + } if (last->failed == 0) { fprintf(stdout, "SUCCESS\n"); fflush(stdout); @@ -102,6 +106,7 @@ abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full) subsuite = malloc(sizeof(*subsuite)); subsuite->num_test = 0; subsuite->failed = 0; + subsuite->skipped = 0; subsuite->next = NULL; /* suite_name_full may be an absolute path depending on __FILE__ * expansion */ @@ -178,6 +183,7 @@ void abts_run_test(abts_suite *ts, test_func f, void *value) ss = ts->tail; tc.failed = 0; + tc.skipped = 0; tc.suite = ss; ss->num_test++; @@ -188,11 +194,25 @@ void abts_run_test(abts_suite *ts, test_func f, void *value) if (tc.failed) { ss->failed++; } + + if (tc.skipped) { + ss->skipped++; + } +} + +static void report_summary(const char *kind_header, + const char *name_header, + const char *percent_header) +{ + fprintf(stdout, "%-15s\t\tTotal\t%s\t%s\n", + kind_header, name_header, percent_header); + fprintf(stdout, "===================================================\n"); } static int report(abts_suite *suite) { - int count = 0; + int failed_count = 0; + int skipped_count = 0; sub_suite *dptr; if (suite && suite->tail &&!suite->tail->not_run) { @@ -200,25 +220,46 @@ static int report(abts_suite *suite) } for (dptr = suite->head; dptr; dptr = dptr->next) { - count += dptr->failed; + failed_count += dptr->failed; + } + + for (dptr = suite->head; dptr; dptr = dptr->next) { + skipped_count += dptr->skipped; } if (list_tests) { return 0; } - if (count == 0) { + /* Report skipped tests */ + if (skipped_count > 0) { + dptr = suite->head; + report_summary("Skipped Tests", "Skip", "Skipped %"); + while (dptr != NULL) { + if (dptr->skipped != 0) { + float percent = ((float)dptr->skipped / (float)dptr->num_test); + fprintf(stdout, "%-15s\t\t%5d\t%4d\t%8.2f%%\n", dptr->name, + dptr->num_test, dptr->skipped, percent * 100); + } + dptr = dptr->next; + } + } + + if (failed_count == 0) { printf("All tests passed.\n"); return 0; } + /* Report failed tests */ dptr = suite->head; - fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests"); - fprintf(stdout, "===================================================\n"); + if (skipped_count > 0) { + fprintf(stdout, "\n"); + } + report_summary("Failed Tests", "Fail", " Failed %"); while (dptr != NULL) { if (dptr->failed != 0) { float percent = ((float)dptr->failed / (float)dptr->num_test); - fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name, + fprintf(stdout, "%-15s\t\t%5d\t%4d\t%8.2f%%\n", dptr->name, dptr->num_test, dptr->failed, percent * 100); } dptr = dptr->next; @@ -240,50 +281,52 @@ void abts_log_message(const char *fmt, ...) } } -void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno) -{ - update_status(); - if (tc->failed) return; - - if (expected == actual) return; - - tc->failed = TRUE; - if (verbose) { - fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual); - fflush(stderr); - } +#define IMPL_abts_T_equal(T, NAME, FMT, CAST) \ +void abts_##NAME##_equal(abts_case *tc, const T expected, const T actual, int lineno) \ +{ \ + update_status(); \ + if (tc->failed) return; \ + \ + if (expected == actual) return; \ + \ + tc->failed = TRUE; \ + if (verbose) { \ + fprintf(stderr, "Line %d: expected <%" FMT ">, but saw <%" FMT ">\n", \ + lineno, CAST expected, CAST actual); \ + fflush(stderr); \ + } \ } - -void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno) -{ - update_status(); - if (tc->failed) return; - - if (expected != actual) return; - - tc->failed = TRUE; - if (verbose) { - fprintf(stderr, "Line %d: expected something other than <%d>, but saw <%d>\n", - lineno, expected, actual); - fflush(stderr); - } -} - -void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno) -{ - update_status(); - if (tc->failed) return; - - if (expected == actual) return; - - tc->failed = TRUE; - if (verbose) { - /* Note that the comparison is type-exact, reporting must be a best-fit */ - fprintf(stderr, "Line %d: expected %lu, but saw %lu\n", lineno, - (unsigned long)expected, (unsigned long)actual); - fflush(stderr); - } +IMPL_abts_T_equal(int, int, "d", (int)) +IMPL_abts_T_equal(unsigned int, uint, "u", (unsigned int)) +IMPL_abts_T_equal(long, long, "ld", (long)) +IMPL_abts_T_equal(unsigned long, ulong, "lu", (unsigned long)) +IMPL_abts_T_equal(long long, llong, "lld", (long long)) +IMPL_abts_T_equal(unsigned long long, ullong, "llu", (unsigned long long)) +IMPL_abts_T_equal(size_t, size, "lu", (unsigned long)) + +#define IMPL_abts_T_nequal(T, NAME, FMT, CAST) \ +void abts_##NAME##_nequal(abts_case *tc, const T expected, const T actual, int lineno) \ +{ \ + update_status(); \ + if (tc->failed) return; \ + \ + if (expected != actual) return; \ + \ + tc->failed = TRUE; \ + if (verbose) { \ + fprintf(stderr, "Line %d: expected something other than <%" FMT ">, " \ + "but saw <%" FMT ">\n", \ + lineno, CAST expected, CAST actual); \ + fflush(stderr); \ + } \ } +IMPL_abts_T_nequal(int, int, "d", (int)) +IMPL_abts_T_nequal(unsigned int, uint, "u", (unsigned int)) +IMPL_abts_T_nequal(long, long, "ld", (long)) +IMPL_abts_T_nequal(unsigned long, ulong, "lu", (unsigned long)) +IMPL_abts_T_nequal(long long, llong, "lld", (long long)) +IMPL_abts_T_nequal(unsigned long long, ullong, "llu", (unsigned long long)) +IMPL_abts_T_nequal(size_t, size, "lu", (unsigned long)) void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno) { @@ -356,7 +399,19 @@ void abts_fail(abts_case *tc, const char *message, int lineno) fflush(stderr); } } - + +void abts_skip(abts_case *tc, const char *message, int lineno) +{ + update_status(); + if (tc->skipped) return; + + tc->skipped = TRUE; + if (verbose) { + fprintf(stderr, "\bSKIP: Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + void abts_assert(abts_case *tc, const char *message, int condition, int lineno) { update_status(); diff --git a/test/abts.h b/test/abts.h index ed1c092..dffb0c5 100644 --- a/test/abts.h +++ b/test/abts.h @@ -42,6 +42,7 @@ struct sub_suite { char *name; int num_test; int failed; + int skipped; int not_run; int not_impl; struct sub_suite *next; @@ -56,6 +57,7 @@ typedef struct abts_suite abts_suite; struct abts_case { int failed; + int skipped; sub_suite *suite; }; typedef struct abts_case abts_case; @@ -70,6 +72,28 @@ void abts_log_message(const char *fmt, ...); void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno); void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno); +void abts_uint_equal(abts_case *tc, const unsigned int expected, + const unsigned int actual, int lineno); +void abts_uint_nequal(abts_case *tc, const unsigned int expected, + const unsigned int actual, int lineno); +void abts_long_equal(abts_case *tc, const long expected, + const long actual, int lineno); +void abts_long_nequal(abts_case *tc, const long expected, + const long actual, int lineno); +void abts_ulong_equal(abts_case *tc, const unsigned long expected, + const unsigned long actual, int lineno); +void abts_ulong_nequal(abts_case *tc, const unsigned long expected, + const unsigned long actual, int lineno); +void abts_llong_equal(abts_case *tc, const long long expected, + const long long actual, int lineno); +void abts_llong_nequal(abts_case *tc, const long long expected, + const long long actual, int lineno); +void abts_ullong_equal(abts_case *tc, const unsigned long long expected, + const unsigned long long actual, int lineno); +void abts_ullong_nequal(abts_case *tc, const unsigned long long expected, + const unsigned long long actual, int lineno); +void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno); +void abts_size_nequal(abts_case *tc, size_t expected, size_t actual, int lineno); void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno); void abts_str_nequal(abts_case *tc, const char *expected, const char *actual, size_t n, int lineno); @@ -77,13 +101,25 @@ void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno); void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno); void abts_true(abts_case *tc, int condition, int lineno); void abts_fail(abts_case *tc, const char *message, int lineno); +void abts_skip(abts_case *tc, const char *message, int lineno); void abts_not_impl(abts_case *tc, const char *message, int lineno); void abts_assert(abts_case *tc, const char *message, int condition, int lineno); -void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno); /* Convenience macros. Ryan hates these! */ #define ABTS_INT_EQUAL(a, b, c) abts_int_equal(a, b, c, __LINE__) #define ABTS_INT_NEQUAL(a, b, c) abts_int_nequal(a, b, c, __LINE__) +#define ABTS_UINT_EQUAL(a, b, c) abts_uint_equal(a, b, c, __LINE__) +#define ABTS_UINT_NEQUAL(a, b, c) abts_uint_nequal(a, b, c, __LINE__) +#define ABTS_LONG_EQUAL(a, b, c) abts_long_equal(a, b, c, __LINE__) +#define ABTS_LONG_NEQUAL(a, b, c) abts_long_nequal(a, b, c, __LINE__) +#define ABTS_ULONG_EQUAL(a, b, c) abts_ulong_equal(a, b, c, __LINE__) +#define ABTS_ULONG_NEQUAL(a, b, c) abts_ulong_nequal(a, b, c, __LINE__) +#define ABTS_LLONG_EQUAL(a, b, c) abts_llong_equal(a, b, c, __LINE__) +#define ABTS_LLONG_NEQUAL(a, b, c) abts_llong_nequal(a, b, c, __LINE__) +#define ABTS_ULLONG_EQUAL(a, b, c) abts_ullong_equal(a, b, c, __LINE__) +#define ABTS_ULLONG_NEQUAL(a, b, c) abts_ullong_nequal(a, b, c, __LINE__) +#define ABTS_SIZE_EQUAL(a, b, c) abts_size_equal(a, b, c, __LINE__) +#define ABTS_SIZE_NEQUAL(a, b, c) abts_size_nequal(a, b, c, __LINE__) #define ABTS_STR_EQUAL(a, b, c) abts_str_equal(a, b, c, __LINE__) #define ABTS_STR_NEQUAL(a, b, c, d) abts_str_nequal(a, b, c, d, __LINE__) #define ABTS_PTR_NOTNULL(a, b) abts_ptr_notnull(a, b, __LINE__) @@ -93,8 +129,13 @@ void abts_size_equal(abts_case *tc, size_t expected, size_t actual, int lineno); #define ABTS_NOT_IMPL(a, b) abts_not_impl(a, b, __LINE__); #define ABTS_ASSERT(a, b, c) abts_assert(a, b, c, __LINE__); -#define ABTS_SIZE_EQUAL(a, b, c) abts_size_equal(a, b, c, __LINE__) +/* When skipping tests, make a reference to the test data parameter + to avoid unused variable warnings. */ +#define ABTS_SKIP(tc, data, msg) do { \ + ((void)(data)); \ + abts_skip((tc), (msg), __LINE__); \ + } while (0) abts_suite *run_tests(abts_suite *suite); abts_suite *run_tests1(abts_suite *suite); diff --git a/test/testatomic.c b/test/testatomic.c index bf388c7..efcc148 100644 --- a/test/testatomic.c +++ b/test/testatomic.c @@ -43,14 +43,14 @@ static void test_set32(abts_case *tc, void *data) { apr_uint32_t y32; apr_atomic_set32(&y32, 2); - ABTS_INT_EQUAL(tc, 2, y32); + ABTS_UINT_EQUAL(tc, 2, y32); } static void test_read32(abts_case *tc, void *data) { apr_uint32_t y32; apr_atomic_set32(&y32, 2); - ABTS_INT_EQUAL(tc, 2, apr_atomic_read32(&y32)); + ABTS_UINT_EQUAL(tc, 2, apr_atomic_read32(&y32)); } static void test_dec32(abts_case *tc, void *data) @@ -61,11 +61,11 @@ static void test_dec32(abts_case *tc, void *data) apr_atomic_set32(&y32, 2); rv = apr_atomic_dec32(&y32); - ABTS_INT_EQUAL(tc, 1, y32); + ABTS_UINT_EQUAL(tc, 1, y32); ABTS_ASSERT(tc, "atomic_dec returned zero when it shouldn't", rv != 0); rv = apr_atomic_dec32(&y32); - ABTS_INT_EQUAL(tc, 0, y32); + ABTS_UINT_EQUAL(tc, 0, y32); ABTS_ASSERT(tc, "atomic_dec didn't returned zero when it should", rv == 0); } @@ -77,8 +77,8 @@ static void test_xchg32(abts_case *tc, void *data) apr_atomic_set32(&y32, 100); oldval = apr_atomic_xchg32(&y32, 50); - ABTS_INT_EQUAL(tc, 100, oldval); - ABTS_INT_EQUAL(tc, 50, y32); + ABTS_UINT_EQUAL(tc, 100, oldval); + ABTS_UINT_EQUAL(tc, 50, y32); } static void test_xchgptr(abts_case *tc, void *data) @@ -99,8 +99,8 @@ static void test_cas_equal(abts_case *tc, void *data) apr_uint32_t oldval; oldval = apr_atomic_cas32(&casval, 12, 0); - ABTS_INT_EQUAL(tc, 0, oldval); - ABTS_INT_EQUAL(tc, 12, casval); + ABTS_UINT_EQUAL(tc, 0, oldval); + ABTS_UINT_EQUAL(tc, 12, casval); } static void test_cas_equal_nonnull(abts_case *tc, void *data) @@ -109,8 +109,8 @@ static void test_cas_equal_nonnull(abts_case *tc, void *data) apr_uint32_t oldval; oldval = apr_atomic_cas32(&casval, 23, 12); - ABTS_INT_EQUAL(tc, 12, oldval); - ABTS_INT_EQUAL(tc, 23, casval); + ABTS_UINT_EQUAL(tc, 12, oldval); + ABTS_UINT_EQUAL(tc, 23, casval); } static void test_cas_notequal(abts_case *tc, void *data) @@ -119,8 +119,8 @@ static void test_cas_notequal(abts_case *tc, void *data) apr_uint32_t oldval; oldval = apr_atomic_cas32(&casval, 23, 2); - ABTS_INT_EQUAL(tc, 12, oldval); - ABTS_INT_EQUAL(tc, 12, casval); + ABTS_UINT_EQUAL(tc, 12, oldval); + ABTS_UINT_EQUAL(tc, 12, casval); } static void test_casptr_equal(abts_case *tc, void *data) @@ -163,8 +163,8 @@ static void test_add32(abts_case *tc, void *data) apr_atomic_set32(&y32, 23); oldval = apr_atomic_add32(&y32, 4); - ABTS_INT_EQUAL(tc, 23, oldval); - ABTS_INT_EQUAL(tc, 27, y32); + ABTS_UINT_EQUAL(tc, 23, oldval); + ABTS_UINT_EQUAL(tc, 27, y32); } static void test_add32_neg(abts_case *tc, void *data) @@ -174,8 +174,8 @@ static void test_add32_neg(abts_case *tc, void *data) apr_atomic_set32(&y32, 23); oldval = apr_atomic_add32(&y32, -10); - ABTS_INT_EQUAL(tc, 23, oldval); - ABTS_INT_EQUAL(tc, 13, y32); + ABTS_UINT_EQUAL(tc, 23, oldval); + ABTS_UINT_EQUAL(tc, 13, y32); } static void test_inc32(abts_case *tc, void *data) @@ -185,8 +185,8 @@ static void test_inc32(abts_case *tc, void *data) apr_atomic_set32(&y32, 23); oldval = apr_atomic_inc32(&y32); - ABTS_INT_EQUAL(tc, 23, oldval); - ABTS_INT_EQUAL(tc, 24, y32); + ABTS_UINT_EQUAL(tc, 23, oldval); + ABTS_UINT_EQUAL(tc, 24, y32); } static void test_set_add_inc_sub(abts_case *tc, void *data) @@ -198,7 +198,7 @@ static void test_set_add_inc_sub(abts_case *tc, void *data) apr_atomic_inc32(&y32); apr_atomic_sub32(&y32, 10); - ABTS_INT_EQUAL(tc, 11, y32); + ABTS_UINT_EQUAL(tc, 11, y32); } static void test_wrap_zero(abts_case *tc, void *data) @@ -234,14 +234,14 @@ static void test_set64(abts_case *tc, void *data) { apr_uint64_t y64; apr_atomic_set64(&y64, 2); - ABTS_INT_EQUAL(tc, 2, y64); + ABTS_ULLONG_EQUAL(tc, 2, y64); } static void test_read64(abts_case *tc, void *data) { apr_uint64_t y64; apr_atomic_set64(&y64, 2); - ABTS_INT_EQUAL(tc, 2, apr_atomic_read64(&y64)); + ABTS_ULLONG_EQUAL(tc, 2, apr_atomic_read64(&y64)); } static void test_dec64(abts_case *tc, void *data) @@ -252,11 +252,11 @@ static void test_dec64(abts_case *tc, void *data) apr_atomic_set64(&y64, 2); rv = apr_atomic_dec64(&y64); - ABTS_INT_EQUAL(tc, 1, y64); + ABTS_ULLONG_EQUAL(tc, 1, y64); ABTS_ASSERT(tc, "atomic_dec returned zero when it shouldn't", rv != 0); rv = apr_atomic_dec64(&y64); - ABTS_INT_EQUAL(tc, 0, y64); + ABTS_ULLONG_EQUAL(tc, 0, y64); ABTS_ASSERT(tc, "atomic_dec didn't returned zero when it should", rv == 0); } @@ -268,8 +268,8 @@ static void test_xchg64(abts_case *tc, void *data) apr_atomic_set64(&y64, 100); oldval = apr_atomic_xchg64(&y64, 50); - ABTS_INT_EQUAL(tc, 100, oldval); - ABTS_INT_EQUAL(tc, 50, y64); + ABTS_ULLONG_EQUAL(tc, 100, oldval); + ABTS_ULLONG_EQUAL(tc, 50, y64); } static void test_add64(abts_case *tc, void *data) @@ -279,8 +279,8 @@ static void test_add64(abts_case *tc, void *data) apr_atomic_set64(&y64, 23); oldval = apr_atomic_add64(&y64, 4); - ABTS_INT_EQUAL(tc, 23, oldval); - ABTS_INT_EQUAL(tc, 27, y64); + ABTS_ULLONG_EQUAL(tc, 23, oldval); + ABTS_ULLONG_EQUAL(tc, 27, y64); } static void test_add64_neg(abts_case *tc, void *data) @@ -290,8 +290,8 @@ static void test_add64_neg(abts_case *tc, void *data) apr_atomic_set64(&y64, 23); oldval = apr_atomic_add64(&y64, -10); - ABTS_INT_EQUAL(tc, 23, oldval); - ABTS_INT_EQUAL(tc, 13, y64); + ABTS_ULLONG_EQUAL(tc, 23, oldval); + ABTS_ULLONG_EQUAL(tc, 13, y64); } static void test_inc64(abts_case *tc, void *data) @@ -301,8 +301,8 @@ static void test_inc64(abts_case *tc, void *data) apr_atomic_set64(&y64, 23); oldval = apr_atomic_inc64(&y64); - ABTS_INT_EQUAL(tc, 23, oldval); - ABTS_INT_EQUAL(tc, 24, y64); + ABTS_ULLONG_EQUAL(tc, 23, oldval); + ABTS_ULLONG_EQUAL(tc, 24, y64); } static void test_set_add_inc_sub64(abts_case *tc, void *data) @@ -314,7 +314,7 @@ static void test_set_add_inc_sub64(abts_case *tc, void *data) apr_atomic_inc64(&y64); apr_atomic_sub64(&y64, 10); - ABTS_INT_EQUAL(tc, 11, y64); + ABTS_ULLONG_EQUAL(tc, 11, y64); } static void test_wrap_zero64(abts_case *tc, void *data) @@ -356,10 +356,18 @@ void *APR_THREAD_FUNC thread_func_atomic64(apr_thread_t *thd, void *data); apr_thread_mutex_t *thread_lock; apr_thread_mutex_t *thread_lock64; -volatile apr_uint32_t mutex_locks = 0; -volatile apr_uint64_t mutex_locks64 = 0; -volatile apr_uint32_t atomic_ops = 0; -volatile apr_uint64_t atomic_ops64 = 0; +apr_uint32_t mutex_locks = 0; +apr_uint64_t mutex_locks64 = 0; +apr_uint32_t atomic_ops = 0; +apr_uint64_t atomic_ops64 = 0; +#ifndef CACHELINE_SIZE +#define CACHELINE_SIZE 64 +#endif +struct { + char pad[CACHELINE_SIZE - 5]; + apr_uint64_t ops64; +} atomic_pad __attribute__((aligned(CACHELINE_SIZE))); + apr_status_t exit_ret_val = 123; /* just some made up number to check on later */ #define NUM_THREADS 40 @@ -422,9 +430,9 @@ static void test_atomics_threaded(abts_case *tc, void *data) s1 == exit_ret_val && s2 == exit_ret_val); } - ABTS_INT_EQUAL(tc, NUM_THREADS * NUM_ITERATIONS, mutex_locks); - ABTS_INT_EQUAL(tc, NUM_THREADS * NUM_ITERATIONS, - apr_atomic_read32(&atomic_ops)); + ABTS_UINT_EQUAL(tc, NUM_THREADS * NUM_ITERATIONS, mutex_locks); + ABTS_UINT_EQUAL(tc, NUM_THREADS * NUM_ITERATIONS, + apr_atomic_read32(&atomic_ops)); rv = apr_thread_mutex_destroy(thread_lock); ABTS_ASSERT(tc, "Failed creating threads", rv == APR_SUCCESS); @@ -475,7 +483,7 @@ static void busyloop_add32(tbox_t *tbox) busyloop_read32(tbox); val = apr_atomic_add32(tbox->mem, tbox->postval); apr_thread_mutex_lock(thread_lock); - ABTS_INT_EQUAL(tbox->tc, val, tbox->preval); + ABTS_UINT_EQUAL(tbox->tc, val, tbox->preval); apr_thread_mutex_unlock(thread_lock); } while (--tbox->loop); } @@ -496,7 +504,7 @@ static void busyloop_inc32(tbox_t *tbox) busyloop_read32(tbox); val = apr_atomic_inc32(tbox->mem); apr_thread_mutex_lock(thread_lock); - ABTS_INT_EQUAL(tbox->tc, val, tbox->preval); + ABTS_UINT_EQUAL(tbox->tc, val, tbox->preval); apr_thread_mutex_unlock(thread_lock); } while (--tbox->loop); } @@ -509,7 +517,7 @@ static void busyloop_dec32(tbox_t *tbox) busyloop_read32(tbox); val = apr_atomic_dec32(tbox->mem); apr_thread_mutex_lock(thread_lock); - ABTS_INT_NEQUAL(tbox->tc, 0, val); + ABTS_UINT_NEQUAL(tbox->tc, 0, val); apr_thread_mutex_unlock(thread_lock); } while (--tbox->loop); } @@ -538,7 +546,7 @@ static void busyloop_xchg32(tbox_t *tbox) busyloop_read32(tbox); val = apr_atomic_xchg32(tbox->mem, tbox->postval); apr_thread_mutex_lock(thread_lock); - ABTS_INT_EQUAL(tbox->tc, val, tbox->preval); + ABTS_UINT_EQUAL(tbox->tc, val, tbox->preval); apr_thread_mutex_unlock(thread_lock); } while (--tbox->loop); } @@ -617,7 +625,7 @@ static void test_atomics_busyloop_threaded(abts_case *tc, void *data) ABTS_ASSERT(tc, "Invalid return value from thread_join", retval == 0); } - ABTS_INT_EQUAL(tbox->tc, 98, count); + ABTS_UINT_EQUAL(tbox->tc, 98, count); rv = apr_thread_mutex_destroy(thread_lock); ABTS_ASSERT(tc, "Failed creating threads", rv == APR_SUCCESS); @@ -639,13 +647,14 @@ void *APR_THREAD_FUNC thread_func_mutex64(apr_thread_t *thd, void *data) void *APR_THREAD_FUNC thread_func_atomic64(apr_thread_t *thd, void *data) { + apr_uint64_t *ops64 = data; int i; for (i = 0; i < NUM_ITERATIONS ; i++) { - apr_atomic_inc64(&atomic_ops64); - apr_atomic_add64(&atomic_ops64, 2); - apr_atomic_dec64(&atomic_ops64); - apr_atomic_dec64(&atomic_ops64); + apr_atomic_inc64(ops64); + apr_atomic_add64(ops64, 2); + apr_atomic_dec64(ops64); + apr_atomic_dec64(ops64); } apr_thread_exit(thd, exit_ret_val); return NULL; @@ -653,6 +662,7 @@ void *APR_THREAD_FUNC thread_func_atomic64(apr_thread_t *thd, void *data) static void test_atomics_threaded64(abts_case *tc, void *data) { + apr_uint64_t *ops64 = data; apr_thread_t *t1[NUM_THREADS]; apr_thread_t *t2[NUM_THREADS]; apr_status_t rv; @@ -662,13 +672,16 @@ static void test_atomics_threaded64(abts_case *tc, void *data) pthread_setconcurrency(8); #endif + mutex_locks64 = 0; + apr_atomic_set64(ops64, 0); + rv = apr_thread_mutex_create(&thread_lock64, APR_THREAD_MUTEX_DEFAULT, p); APR_ASSERT_SUCCESS(tc, "Could not create lock", rv); for (i = 0; i < NUM_THREADS; i++) { apr_status_t r1, r2; r1 = apr_thread_create(&t1[i], NULL, thread_func_mutex64, NULL, p); - r2 = apr_thread_create(&t2[i], NULL, thread_func_atomic64, NULL, p); + r2 = apr_thread_create(&t2[i], NULL, thread_func_atomic64, ops64, p); ABTS_ASSERT(tc, "Failed creating threads", !r1 && !r2); } @@ -681,9 +694,9 @@ static void test_atomics_threaded64(abts_case *tc, void *data) s1 == exit_ret_val && s2 == exit_ret_val); } - ABTS_INT_EQUAL(tc, NUM_THREADS * NUM_ITERATIONS, mutex_locks64); - ABTS_INT_EQUAL(tc, NUM_THREADS * NUM_ITERATIONS, - apr_atomic_read64(&atomic_ops64)); + ABTS_ULLONG_EQUAL(tc, NUM_THREADS * NUM_ITERATIONS, mutex_locks64); + ABTS_ULLONG_EQUAL(tc, NUM_THREADS * NUM_ITERATIONS, + apr_atomic_read64(ops64)); rv = apr_thread_mutex_destroy(thread_lock64); ABTS_ASSERT(tc, "Failed creating threads", rv == APR_SUCCESS); @@ -728,7 +741,7 @@ static void busyloop_add64(tbox_t64 *tbox) busyloop_read64(tbox); val = apr_atomic_add64(tbox->mem, tbox->postval); apr_thread_mutex_lock(thread_lock64); - ABTS_INT_EQUAL(tbox->tc, val, tbox->preval); + ABTS_ULLONG_EQUAL(tbox->tc, val, tbox->preval); apr_thread_mutex_unlock(thread_lock64); } while (--tbox->loop); } @@ -749,7 +762,7 @@ static void busyloop_inc64(tbox_t64 *tbox) busyloop_read64(tbox); val = apr_atomic_inc64(tbox->mem); apr_thread_mutex_lock(thread_lock64); - ABTS_INT_EQUAL(tbox->tc, val, tbox->preval); + ABTS_ULLONG_EQUAL(tbox->tc, val, tbox->preval); apr_thread_mutex_unlock(thread_lock64); } while (--tbox->loop); } @@ -762,7 +775,7 @@ static void busyloop_dec64(tbox_t64 *tbox) busyloop_read64(tbox); val = apr_atomic_dec64(tbox->mem); apr_thread_mutex_lock(thread_lock64); - ABTS_INT_NEQUAL(tbox->tc, 0, val); + ABTS_ULLONG_NEQUAL(tbox->tc, 0, val); apr_thread_mutex_unlock(thread_lock64); } while (--tbox->loop); } @@ -791,7 +804,7 @@ static void busyloop_xchg64(tbox_t64 *tbox) busyloop_read64(tbox); val = apr_atomic_xchg64(tbox->mem, tbox->postval); apr_thread_mutex_lock(thread_lock64); - ABTS_INT_EQUAL(tbox->tc, val, tbox->preval); + ABTS_ULLONG_EQUAL(tbox->tc, val, tbox->preval); apr_thread_mutex_unlock(thread_lock64); } while (--tbox->loop); } @@ -870,7 +883,7 @@ static void test_atomics_busyloop_threaded64(abts_case *tc, void *data) ABTS_ASSERT(tc, "Invalid return value from thread_join", retval == 0); } - ABTS_INT_EQUAL(tbox->tc, 98, count); + ABTS_ULLONG_EQUAL(tbox->tc, 98, count); rv = apr_thread_mutex_destroy(thread_lock64); ABTS_ASSERT(tc, "Failed creating threads", rv == APR_SUCCESS); @@ -878,11 +891,12 @@ static void test_atomics_busyloop_threaded64(abts_case *tc, void *data) static void *APR_THREAD_FUNC test_func_set64(apr_thread_t *thd, void *data) { + apr_uint64_t *ops64 = data; int i; for (i = 0; i < 1000 * 1000; i++) { - apr_atomic_set64(&atomic_ops64, APR_UINT64_C(0x1111222233334444)); - apr_atomic_set64(&atomic_ops64, APR_UINT64_C(0x4444555566667777)); + apr_atomic_set64(ops64, APR_UINT64_C(0x1111222233334444)); + apr_atomic_set64(ops64, APR_UINT64_C(0x4444555566667777)); } apr_thread_exit(thd, APR_SUCCESS); @@ -891,16 +905,17 @@ static void *APR_THREAD_FUNC test_func_set64(apr_thread_t *thd, void *data) static void test_atomics_threaded_setread64(abts_case *tc, void *data) { - apr_status_t retval; + apr_uint64_t *ops64 = data; apr_thread_t *thread; + apr_status_t retval; int i; - apr_atomic_set64(&atomic_ops64, APR_UINT64_C(0x1111222233334444)); + apr_atomic_set64(ops64, APR_UINT64_C(0x1111222233334444)); - apr_thread_create(&thread, NULL, test_func_set64, NULL, p); + apr_thread_create(&thread, NULL, test_func_set64, ops64, p); for (i = 0; i < 1000 * 1000 * 2; i++) { - apr_uint64_t val = apr_atomic_read64(&atomic_ops64); + apr_uint64_t val = apr_atomic_read64(ops64); if (val != APR_UINT64_C(0x1111222233334444) && val != APR_UINT64_C(0x4444555566667777)) @@ -950,10 +965,12 @@ abts_suite *testatomic(abts_suite *suite) #if APR_HAS_THREADS abts_run_test(suite, test_atomics_threaded, NULL); - abts_run_test(suite, test_atomics_threaded64, NULL); + abts_run_test(suite, test_atomics_threaded64, &atomic_ops64); + abts_run_test(suite, test_atomics_threaded64, &atomic_pad.ops64); abts_run_test(suite, test_atomics_busyloop_threaded, NULL); abts_run_test(suite, test_atomics_busyloop_threaded64, NULL); - abts_run_test(suite, test_atomics_threaded_setread64, NULL); + abts_run_test(suite, test_atomics_threaded_setread64, &atomic_ops64); + abts_run_test(suite, test_atomics_threaded_setread64, &atomic_pad.ops64); #endif return suite; diff --git a/test/testdir.c b/test/testdir.c index ac1bcfa..95b559d 100644 --- a/test/testdir.c +++ b/test/testdir.c @@ -60,43 +60,51 @@ static void test_mkdir_recurs(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype); } -struct thread_data -{ - abts_case *tc; - apr_pool_t *pool; -}; - -static void *APR_THREAD_FUNC thread_mkdir_func(apr_thread_t *thd, void *data) +static void mkdir_func(abts_case *tc, apr_pool_t *pool) { - struct thread_data *td = data; apr_status_t s1, s2, s3, s4, s5; s1 = apr_dir_make_recursive("data/prll/one/thwo/three", APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE, - td->pool); + pool); s2 = apr_dir_make_recursive("data/prll/four/five/six/seven/eight", APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE, - td->pool); + pool); s3 = apr_dir_make_recursive("data/prll/nine/ten", APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE, - td->pool); + pool); s4 = apr_dir_make_recursive("data/prll/11/12/13/14/15/16/17/18/19/20", APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE, - td->pool); + pool); s5 = apr_dir_make_recursive("data/fortytwo", APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_UEXECUTE, - td->pool); + pool); - ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s1); - ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s2); - ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s3); - ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s4); - ABTS_INT_EQUAL(td->tc, APR_SUCCESS, s5); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s1); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s2); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s3); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s4); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s5); +} + +#if APR_HAS_THREADS +struct thread_data +{ + abts_case *tc; + apr_pool_t *pool; +}; + +static void *APR_THREAD_FUNC thread_mkdir_func(apr_thread_t *thd, void *data) +{ + struct thread_data *td = data; + mkdir_func(td->tc, td->pool); return NULL; } +#endif /* APR_HAS_THREADS */ static void test_mkdir_recurs_parallel(abts_case *tc, void *data) { +#if APR_HAS_THREADS struct thread_data td1, td2, td3, td4; apr_thread_t *t1, *t2, *t3, *t4; apr_status_t s1, s2, s3, s4; @@ -125,6 +133,11 @@ static void test_mkdir_recurs_parallel(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, APR_SUCCESS, s2); ABTS_INT_EQUAL(tc, APR_SUCCESS, s3); ABTS_INT_EQUAL(tc, APR_SUCCESS, s4); +#else + /* Create the test directories for test_removeall anwyay. */ + mkdir_func(tc, p); + ABTS_SKIP(tc, data, "This test requires APR thread support."); +#endif /* APR_HAS_THREADS */ } static void test_remove(abts_case *tc, void *data) diff --git a/test/testencode.c b/test/testencode.c index 6d78310..ca9ddb3 100644 --- a/test/testencode.c +++ b/test/testencode.c @@ -189,42 +189,42 @@ static void test_decode_base64_binary(abts_case * tc, void *data) src = ""; udest = apr_pdecode_base64_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base64_binary target!=dest", memcmp(ufoobar, udest, 0) == 0); - ABTS_INT_EQUAL(tc, len, 0); + ABTS_SIZE_EQUAL(tc, len, 0); src = "Zg=="; udest = apr_pdecode_base64_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base64_binary target!=dest", memcmp(ufoobar, udest, 1) == 0); - ABTS_INT_EQUAL(tc, len, 1); + ABTS_SIZE_EQUAL(tc, len, 1); src = "Zg="; udest = apr_pdecode_base64_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base64_binary target!=dest", memcmp(ufoobar, udest, 1) == 0); - ABTS_INT_EQUAL(tc, len, 1); + ABTS_SIZE_EQUAL(tc, len, 1); src = "Zg"; udest = apr_pdecode_base64_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base64_binary target!=dest", memcmp(ufoobar, udest, 1) == 0); - ABTS_INT_EQUAL(tc, len, 1); + ABTS_SIZE_EQUAL(tc, len, 1); src = "Zm8="; udest = apr_pdecode_base64_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base64_binary target!=dest", memcmp(ufoobar, udest, 2) == 0); - ABTS_INT_EQUAL(tc, len, 2); + ABTS_SIZE_EQUAL(tc, len, 2); src = "Zm8"; udest = apr_pdecode_base64_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base64_binary target!=dest", memcmp(ufoobar, udest, 2) == 0); - ABTS_INT_EQUAL(tc, len, 2); + ABTS_SIZE_EQUAL(tc, len, 2); src = "Zm9v"; udest = apr_pdecode_base64_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base64_binary target!=dest", memcmp(ufoobar, udest, 3) == 0); - ABTS_INT_EQUAL(tc, len, 3); + ABTS_SIZE_EQUAL(tc, len, 3); src = "Zm9v"; udest = apr_pdecode_base64_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base64_binary target!=dest", memcmp(ufoobar, udest, 3) == 0); - ABTS_INT_EQUAL(tc, len, 3); + ABTS_SIZE_EQUAL(tc, len, 3); apr_pool_destroy(pool); } @@ -639,127 +639,127 @@ static void test_decode_base32_binary(abts_case * tc, void *data) src = ""; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 0) == 0); - ABTS_INT_EQUAL(tc, 0, len); + ABTS_SIZE_EQUAL(tc, 0, len); src = "MY======"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 1) == 0); - ABTS_INT_EQUAL(tc, 1, len); + ABTS_SIZE_EQUAL(tc, 1, len); src = "MY"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 1) == 0); - ABTS_INT_EQUAL(tc, 1, len); + ABTS_SIZE_EQUAL(tc, 1, len); src = "CO======"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_BASE32HEX, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 1) == 0); - ABTS_INT_EQUAL(tc, 1, len); + ABTS_SIZE_EQUAL(tc, 1, len); src = "CO"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_BASE32HEX, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 1) == 0); - ABTS_INT_EQUAL(tc, 1, len); + ABTS_SIZE_EQUAL(tc, 1, len); src = "MZXQ===="; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 2) == 0); - ABTS_INT_EQUAL(tc, 2, len); + ABTS_SIZE_EQUAL(tc, 2, len); src = "MZXQ"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 2) == 0); - ABTS_INT_EQUAL(tc, 2, len); + ABTS_SIZE_EQUAL(tc, 2, len); src = "CPNG===="; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_BASE32HEX, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 2) == 0); - ABTS_INT_EQUAL(tc, 2, len); + ABTS_SIZE_EQUAL(tc, 2, len); src = "CPNG"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_BASE32HEX, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 2) == 0); - ABTS_INT_EQUAL(tc, 2, len); + ABTS_SIZE_EQUAL(tc, 2, len); src = "MZXW6==="; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 3) == 0); - ABTS_INT_EQUAL(tc, 3, len); + ABTS_SIZE_EQUAL(tc, 3, len); src = "MZXW6"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 3) == 0); - ABTS_INT_EQUAL(tc, 3, len); + ABTS_SIZE_EQUAL(tc, 3, len); src = "CPNMU==="; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_BASE32HEX, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 3) == 0); - ABTS_INT_EQUAL(tc, 3, len); + ABTS_SIZE_EQUAL(tc, 3, len); src = "CPNMU"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_BASE32HEX, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 3) == 0); - ABTS_INT_EQUAL(tc, 3, len); + ABTS_SIZE_EQUAL(tc, 3, len); src = "MZXW6YQ="; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 4) == 0); - ABTS_INT_EQUAL(tc, 4, len); + ABTS_SIZE_EQUAL(tc, 4, len); src = "MZXW6YQ="; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 4) == 0); - ABTS_INT_EQUAL(tc, 4, len); + ABTS_SIZE_EQUAL(tc, 4, len); src = "CPNMUOG="; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_BASE32HEX, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 4) == 0); - ABTS_INT_EQUAL(tc, 4, len); + ABTS_SIZE_EQUAL(tc, 4, len); src = "CPNMUOG"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_BASE32HEX, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 4) == 0); - ABTS_INT_EQUAL(tc, 4, len); + ABTS_SIZE_EQUAL(tc, 4, len); src = "MZXW6YTB"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 5) == 0); - ABTS_INT_EQUAL(tc, 5, len); + ABTS_SIZE_EQUAL(tc, 5, len); src = "MZXW6YTB"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 5) == 0); - ABTS_INT_EQUAL(tc, 5, len); + ABTS_SIZE_EQUAL(tc, 5, len); src = "CPNMUOJ1"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_BASE32HEX, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 5) == 0); - ABTS_INT_EQUAL(tc, 5, len); + ABTS_SIZE_EQUAL(tc, 5, len); src = "CPNMUOJ1"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_BASE32HEX, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 5) == 0); - ABTS_INT_EQUAL(tc, 5, len); + ABTS_SIZE_EQUAL(tc, 5, len); src = "MZXW6YTBOI======"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 6) == 0); - ABTS_INT_EQUAL(tc, 6, len); + ABTS_SIZE_EQUAL(tc, 6, len); src = "MZXW6YTBOI"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_NONE, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 6) == 0); - ABTS_INT_EQUAL(tc, 6, len); + ABTS_SIZE_EQUAL(tc, 6, len); src = "CPNMUOJ1E8======"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_BASE32HEX, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 6) == 0); - ABTS_INT_EQUAL(tc, 6, len); + ABTS_SIZE_EQUAL(tc, 6, len); src = "CPNMUOJ1E8"; udest = apr_pdecode_base32_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_BASE32HEX, &len); ABTS_ASSERT(tc, "apr_pdecode_base32_binary target!=dest", memcmp(ufoobar, udest, 6) == 0); - ABTS_INT_EQUAL(tc, 6, len); + ABTS_SIZE_EQUAL(tc, 6, len); apr_pool_destroy(pool); } @@ -872,7 +872,7 @@ static void test_decode_base16(abts_case * tc, void *data) target = ":;<="; dest = apr_pdecode_base16(pool, src, APR_ENCODE_STRING, APR_ENCODE_COLON, &len); ABTS_STR_EQUAL(tc, target, dest); - ABTS_INT_EQUAL(tc, 4, (int)len); + ABTS_SIZE_EQUAL(tc, 4, len); apr_decode_base16(NULL, src, APR_ENCODE_STRING, APR_ENCODE_COLON, &len); ABTS_ASSERT(tc, apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, (apr_size_t) 5), @@ -896,7 +896,7 @@ static void test_decode_base16_binary(abts_case * tc, void *data) src = "ff:00:ff:00"; udest = apr_pdecode_base16_binary(pool, src, APR_ENCODE_STRING, APR_ENCODE_COLON, &vlen); ABTS_ASSERT(tc, "apr_pdecode_base16_binary target!=dest", memcmp(utarget, udest, 4) == 0); - ABTS_INT_EQUAL(tc, (int)vlen, 4); + ABTS_SIZE_EQUAL(tc, vlen, 4); apr_decode_base16_binary(NULL, src, APR_ENCODE_STRING, APR_ENCODE_COLON, &len); ABTS_ASSERT(tc, apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, (apr_size_t) 4), diff --git a/test/testescape.c b/test/testescape.c index 6645227..bd6c072 100644 --- a/test/testescape.c +++ b/test/testescape.c @@ -172,7 +172,7 @@ static void test_escape(abts_case *tc, void *data) ABTS_PTR_EQUAL(tc, src, dest); src = "\xFF<>&\'\"Hello World"; - target = "ÿ<>&'"Hello World"; + target = "ÿ<>&'"Hello World"; dest = apr_pescape_entity(pool, src, 1); ABTS_STR_EQUAL(tc, target, dest); apr_escape_entity(NULL, src, APR_ESCAPE_STRING, 1, &len); diff --git a/test/testfile.c b/test/testfile.c index b1e9c55..f135bed 100644 --- a/test/testfile.c +++ b/test/testfile.c @@ -21,6 +21,8 @@ #include "apr_general.h" #include "apr_poll.h" #include "apr_lib.h" +#include "apr_strings.h" +#include "apr_thread_proc.h" #include "testutil.h" #define DIRNAME "data" @@ -430,6 +432,10 @@ static void test_gets(abts_case *tc, void *data) rv = apr_file_gets(str, 256, f); ABTS_INT_EQUAL(tc, APR_EOF, rv); ABTS_STR_EQUAL(tc, "", str); + /* Calling gets after EOF should return EOF. */ + rv = apr_file_gets(str, 256, f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", str); apr_file_close(f); } @@ -453,6 +459,214 @@ static void test_gets_buffered(abts_case *tc, void *data) rv = apr_file_gets(str, 256, f); ABTS_INT_EQUAL(tc, APR_EOF, rv); ABTS_STR_EQUAL(tc, "", str); + /* Calling gets after EOF should return EOF. */ + rv = apr_file_gets(str, 256, f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", str); + apr_file_close(f); +} + +static void test_gets_empty(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testgets_empty.dat"; + char buf[256]; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file", rv); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "re-open test file", rv); + + rv = apr_file_gets(buf, sizeof(buf), f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", buf); + /* Calling gets after EOF should return EOF. */ + rv = apr_file_gets(buf, sizeof(buf), f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", buf); + apr_file_close(f); +} + +static void test_gets_multiline(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testgets_multiline.dat"; + char buf[256]; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file", rv); + rv = apr_file_puts("a\nb\n", f); + APR_ASSERT_SUCCESS(tc, "write test data", rv); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "re-open test file", rv); + + memset(buf, 0, sizeof(buf)); + rv = apr_file_gets(buf, sizeof(buf), f); + APR_ASSERT_SUCCESS(tc, "read first line", rv); + ABTS_STR_EQUAL(tc, "a\n", buf); + + memset(buf, 0, sizeof(buf)); + rv = apr_file_gets(buf, sizeof(buf), f); + APR_ASSERT_SUCCESS(tc, "read second line", rv); + ABTS_STR_EQUAL(tc, "b\n", buf); + + rv = apr_file_gets(buf, sizeof(buf), f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", buf); + /* Calling gets after EOF should return EOF. */ + rv = apr_file_gets(buf, sizeof(buf), f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", buf); + apr_file_close(f); +} + +static void test_gets_small_buf(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testgets_small_buf.dat"; + char buf[2]; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file", rv); + rv = apr_file_puts("ab\n", f); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "re-open test file", rv); + /* Buffer is too small to hold the full line, test that gets properly + * returns the line content character by character. + */ + memset(buf, 0, sizeof(buf)); + rv = apr_file_gets(buf, sizeof(buf), f); + APR_ASSERT_SUCCESS(tc, "read first chunk", rv); + ABTS_STR_EQUAL(tc, "a", buf); + + memset(buf, 0, sizeof(buf)); + rv = apr_file_gets(buf, sizeof(buf), f); + APR_ASSERT_SUCCESS(tc, "read second chunk", rv); + ABTS_STR_EQUAL(tc, "b", buf); + + memset(buf, 0, sizeof(buf)); + rv = apr_file_gets(buf, sizeof(buf), f); + APR_ASSERT_SUCCESS(tc, "read third chunk", rv); + ABTS_STR_EQUAL(tc, "\n", buf); + + rv = apr_file_gets(buf, sizeof(buf), f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", buf); + /* Calling gets after EOF should return EOF. */ + rv = apr_file_gets(buf, sizeof(buf), f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", buf); + apr_file_close(f); +} + +static void test_gets_ungetc(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testgets_ungetc.dat"; + char buf[256]; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file", rv); + rv = apr_file_puts("a\n", f); + APR_ASSERT_SUCCESS(tc, "write test data", rv); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "re-open test file", rv); + + rv = apr_file_ungetc('b', f); + APR_ASSERT_SUCCESS(tc, "call ungetc", rv); + memset(buf, 0, sizeof(buf)); + rv = apr_file_gets(buf, sizeof(buf), f); + APR_ASSERT_SUCCESS(tc, "read line", rv); + ABTS_STR_EQUAL(tc, "ba\n", buf); + + rv = apr_file_ungetc('\n', f); + APR_ASSERT_SUCCESS(tc, "call ungetc with EOL", rv); + memset(buf, 0, sizeof(buf)); + rv = apr_file_gets(buf, sizeof(buf), f); + APR_ASSERT_SUCCESS(tc, "read line", rv); + ABTS_STR_EQUAL(tc, "\n", buf); + + rv = apr_file_gets(buf, sizeof(buf), f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", buf); + /* Calling gets after EOF should return EOF. */ + rv = apr_file_gets(buf, sizeof(buf), f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", buf); + apr_file_close(f); +} + +static void test_gets_buffered_big(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testgets_buffered_big.dat"; + char hugestr[APR_BUFFERSIZE + 2]; + char buf[APR_BUFFERSIZE + 2]; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file", rv); + /* Test an edge case with a buffered file and the line that exceeds + * the default buffer size by 1 (the line itself fits into the buffer, + * but the line + EOL does not). + */ + memset(hugestr, 'a', sizeof(hugestr)); + hugestr[sizeof(hugestr) - 2] = '\n'; + hugestr[sizeof(hugestr) - 1] = '\0'; + rv = apr_file_puts(hugestr, f); + APR_ASSERT_SUCCESS(tc, "write first line", rv); + rv = apr_file_puts("b\n", f); + APR_ASSERT_SUCCESS(tc, "write second line", rv); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "re-open test file", rv); + + memset(buf, 0, sizeof(buf)); + rv = apr_file_gets(buf, sizeof(buf), f); + APR_ASSERT_SUCCESS(tc, "read first line", rv); + ABTS_STR_EQUAL(tc, hugestr, buf); + + memset(buf, 0, sizeof(buf)); + rv = apr_file_gets(buf, sizeof(buf), f); + APR_ASSERT_SUCCESS(tc, "read second line", rv); + ABTS_STR_EQUAL(tc, "b\n", buf); + + rv = apr_file_gets(buf, sizeof(buf), f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", buf); + /* Calling gets after EOF should return EOF. */ + rv = apr_file_gets(buf, sizeof(buf), f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", buf); apr_file_close(f); } @@ -1260,6 +1474,759 @@ static void test_datasync_on_stream(abts_case *tc, void *data) } } +#if APR_HAS_THREADS +typedef struct thread_file_append_ctx_t { + apr_pool_t *pool; + const char *fname; + apr_size_t chunksize; + char val; + int num_writes; + char *errmsg; +} thread_file_append_ctx_t; + +static void * APR_THREAD_FUNC thread_file_append_func(apr_thread_t *thd, void *data) +{ + thread_file_append_ctx_t *ctx = data; + apr_status_t rv; + apr_file_t *f; + int i; + char *writebuf; + char *readbuf; + + rv = apr_file_open(&f, ctx->fname, + APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_APPEND, + APR_FPROT_OS_DEFAULT, ctx->pool); + if (rv) { + apr_thread_exit(thd, rv); + return NULL; + } + + writebuf = apr_palloc(ctx->pool, ctx->chunksize); + memset(writebuf, ctx->val, ctx->chunksize); + readbuf = apr_palloc(ctx->pool, ctx->chunksize); + + for (i = 0; i < ctx->num_writes; i++) { + apr_size_t bytes_written; + apr_size_t bytes_read; + apr_off_t offset; + + rv = apr_file_write_full(f, writebuf, ctx->chunksize, &bytes_written); + if (rv) { + apr_thread_exit(thd, rv); + return NULL; + } + /* After writing the data, seek back from the current offset and + * verify what we just wrote. */ + offset = -((apr_off_t)ctx->chunksize); + rv = apr_file_seek(f, APR_CUR, &offset); + if (rv) { + apr_thread_exit(thd, rv); + return NULL; + } + rv = apr_file_read_full(f, readbuf, ctx->chunksize, &bytes_read); + if (rv) { + apr_thread_exit(thd, rv); + return NULL; + } + if (memcmp(readbuf, writebuf, ctx->chunksize) != 0) { + ctx->errmsg = apr_psprintf( + ctx->pool, + "Unexpected data at file offset %" APR_OFF_T_FMT, + offset); + apr_thread_exit(thd, APR_SUCCESS); + return NULL; + } + } + + apr_file_close(f); + apr_thread_exit(thd, APR_SUCCESS); + + return NULL; +} +#endif /* APR_HAS_THREADS */ + +static void test_atomic_append(abts_case *tc, void *data) +{ +#if APR_HAS_THREADS + apr_status_t rv; + apr_status_t thread_rv; + apr_file_t *f; + const char *fname = "data/testatomic_append.dat"; + unsigned int seed; + thread_file_append_ctx_t ctx1 = {0}; + thread_file_append_ctx_t ctx2 = {0}; + apr_thread_t *t1; + apr_thread_t *t2; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_WRITE | APR_FOPEN_CREATE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "create file", rv); + apr_file_close(f); + + seed = (unsigned int)apr_time_now(); + abts_log_message("Random seed for test_atomic_append() is %u", seed); + srand(seed); + + /* Create two threads appending data to the same file. */ + apr_pool_create(&ctx1.pool, p); + ctx1.fname = fname; + ctx1.chunksize = 1 + rand() % 8192; + ctx1.val = 'A'; + ctx1.num_writes = 1000; + rv = apr_thread_create(&t1, NULL, thread_file_append_func, &ctx1, p); + APR_ASSERT_SUCCESS(tc, "create thread", rv); + + apr_pool_create(&ctx2.pool, p); + ctx2.fname = fname; + ctx2.chunksize = 1 + rand() % 8192; + ctx2.val = 'B'; + ctx2.num_writes = 1000; + rv = apr_thread_create(&t2, NULL, thread_file_append_func, &ctx2, p); + APR_ASSERT_SUCCESS(tc, "create thread", rv); + + rv = apr_thread_join(&thread_rv, t1); + APR_ASSERT_SUCCESS(tc, "join thread", rv); + APR_ASSERT_SUCCESS(tc, "no thread errors", thread_rv); + if (ctx1.errmsg) { + ABTS_FAIL(tc, ctx1.errmsg); + } + rv = apr_thread_join(&thread_rv, t2); + APR_ASSERT_SUCCESS(tc, "join thread", rv); + APR_ASSERT_SUCCESS(tc, "no thread errors", thread_rv); + if (ctx2.errmsg) { + ABTS_FAIL(tc, ctx2.errmsg); + } + + apr_file_remove(fname, p); +#else + ABTS_SKIP(tc, data, "This test requires APR thread support."); +#endif /* APR_HAS_THREADS */ +} + +static void test_append_locked(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testappend_locked.dat"; + apr_size_t bytes_written; + apr_size_t bytes_read; + char buf[64] = {0}; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, + APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_APPEND, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "create file", rv); + + rv = apr_file_lock(f, APR_FLOCK_EXCLUSIVE); + APR_ASSERT_SUCCESS(tc, "lock file", rv); + + /* PR50058: Appending to a locked file should not deadlock. */ + rv = apr_file_write_full(f, "abc", 3, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + + apr_file_unlock(f); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open file", rv); + + rv = apr_file_read_full(f, buf, sizeof(buf), &bytes_read); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_INT_EQUAL(tc, 3, (int)bytes_read); + ABTS_STR_EQUAL(tc, "abc", buf); + + apr_file_close(f); + apr_file_remove(fname, p); +} + +static void test_large_write_buffered(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testlarge_write_buffered.dat"; + apr_size_t len; + apr_size_t bytes_written; + apr_size_t bytes_read; + char *buf; + char *buf2; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, + APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for writing", rv); + + /* Test a single large write. */ + len = 80000; + buf = apr_palloc(p, len); + memset(buf, 'a', len); + rv = apr_file_write_full(f, buf, len, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + ABTS_INT_EQUAL(tc, (int)len, (int)bytes_written); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for reading", rv); + + buf2 = apr_palloc(p, len + 1); + rv = apr_file_read_full(f, buf2, len + 1, &bytes_read); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_INT_EQUAL(tc, (int)len, (int)bytes_read); + ABTS_TRUE(tc, memcmp(buf, buf2, len) == 0); + apr_file_close(f); + + apr_file_remove(fname, p); +} + +static void test_two_large_writes_buffered(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testtwo_large_writes_buffered.dat"; + apr_size_t len; + apr_size_t bytes_written; + apr_size_t bytes_read; + char *buf; + char *buf2; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, + APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for writing", rv); + + /* Test two consecutive large writes. */ + len = 80000; + buf = apr_palloc(p, len); + memset(buf, 'a', len); + + rv = apr_file_write_full(f, buf, len / 2, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + ABTS_INT_EQUAL(tc, (int)(len / 2), (int)bytes_written); + + rv = apr_file_write_full(f, buf, len / 2, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + ABTS_INT_EQUAL(tc, (int)(len / 2), (int)bytes_written); + + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for reading", rv); + + buf2 = apr_palloc(p, len + 1); + rv = apr_file_read_full(f, buf2, len + 1, &bytes_read); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_INT_EQUAL(tc, (int) len, (int)bytes_read); + ABTS_TRUE(tc, memcmp(buf, buf2, len) == 0); + apr_file_close(f); + + apr_file_remove(fname, p); +} + +static void test_small_and_large_writes_buffered(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testtwo_large_writes_buffered.dat"; + apr_size_t len; + apr_size_t bytes_written; + apr_size_t bytes_read; + char *buf; + char *buf2; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, + APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for writing", rv); + + /* Test small write followed by a large write. */ + len = 80000; + buf = apr_palloc(p, len); + memset(buf, 'a', len); + + rv = apr_file_write_full(f, buf, 5, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + ABTS_INT_EQUAL(tc, 5, (int)bytes_written); + + rv = apr_file_write_full(f, buf, len - 5, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + ABTS_INT_EQUAL(tc, (int)(len - 5), (int)bytes_written); + + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for reading", rv); + + buf2 = apr_palloc(p, len + 1); + rv = apr_file_read_full(f, buf2, len + 1, &bytes_read); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_INT_EQUAL(tc, (int) len, (int)bytes_read); + ABTS_TRUE(tc, memcmp(buf, buf2, len) == 0); + apr_file_close(f); + + apr_file_remove(fname, p); +} + +static void test_write_buffered_spanning_over_bufsize(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testwrite_buffered_spanning_over_bufsize.dat"; + apr_size_t len; + apr_size_t bytes_written; + apr_size_t bytes_read; + char *buf; + char *buf2; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, + APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for writing", rv); + + /* Test three writes than span over the default buffer size. */ + len = APR_BUFFERSIZE + 1; + buf = apr_palloc(p, len); + memset(buf, 'a', len); + + rv = apr_file_write_full(f, buf, APR_BUFFERSIZE - 1, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + ABTS_INT_EQUAL(tc, APR_BUFFERSIZE - 1, (int)bytes_written); + + rv = apr_file_write_full(f, buf, 2, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + ABTS_INT_EQUAL(tc, 2, (int)bytes_written); + + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for reading", rv); + + buf2 = apr_palloc(p, len + 1); + rv = apr_file_read_full(f, buf2, len + 1, &bytes_read); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_INT_EQUAL(tc, (int)len, (int)bytes_read); + ABTS_TRUE(tc, memcmp(buf, buf2, len) == 0); + apr_file_close(f); + + apr_file_remove(fname, p); +} + +static void test_empty_read_buffered(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testempty_read_buffered.dat"; + apr_size_t len; + apr_size_t bytes_read; + char buf[64]; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "create empty test file", rv); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for reading", rv); + + /* Test an empty read. */ + len = 1; + rv = apr_file_read_full(f, buf, len, &bytes_read); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_INT_EQUAL(tc, 0, (int)bytes_read); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + apr_file_close(f); + + apr_file_remove(fname, p); +} + +static void test_large_read_buffered(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testlarge_read_buffered.dat"; + apr_size_t len; + apr_size_t bytes_written; + apr_size_t bytes_read; + char *buf; + char *buf2; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for writing", rv); + len = 80000; + buf = apr_palloc(p, len); + memset(buf, 'a', len); + rv = apr_file_write_full(f, buf, len, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for reading", rv); + + /* Test a single large read. */ + buf2 = apr_palloc(p, len); + rv = apr_file_read_full(f, buf2, len, &bytes_read); + APR_ASSERT_SUCCESS(tc, "read from file", rv); + ABTS_INT_EQUAL(tc, (int)len, (int)bytes_read); + ABTS_TRUE(tc, memcmp(buf, buf2, bytes_read) == 0); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* Test that we receive an EOF. */ + len = 1; + rv = apr_file_read_full(f, buf2, len, &bytes_read); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_INT_EQUAL(tc, 0, (int)bytes_read); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + apr_file_close(f); + + apr_file_remove(fname, p); +} + +static void test_two_large_reads_buffered(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testtwo_large_reads_buffered.dat"; + apr_size_t len; + apr_size_t bytes_written; + apr_size_t bytes_read; + char *buf; + char *buf2; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for writing", rv); + len = 80000; + buf = apr_palloc(p, len); + memset(buf, 'a', len); + rv = apr_file_write_full(f, buf, len, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for reading", rv); + + /* Test two consecutive large reads. */ + buf2 = apr_palloc(p, len); + memset(buf2, 0, len); + rv = apr_file_read_full(f, buf2, len / 2, &bytes_read); + APR_ASSERT_SUCCESS(tc, "read from file", rv); + ABTS_INT_EQUAL(tc, (int)(len / 2), (int)bytes_read); + ABTS_TRUE(tc, memcmp(buf, buf2, bytes_read) == 0); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + memset(buf2, 0, len); + rv = apr_file_read_full(f, buf2, len / 2, &bytes_read); + APR_ASSERT_SUCCESS(tc, "read from file", rv); + ABTS_INT_EQUAL(tc, (int)(len / 2), (int)bytes_read); + ABTS_TRUE(tc, memcmp(buf + len / 2, buf2, bytes_read) == 0); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* Test that we receive an EOF. */ + len = 1; + rv = apr_file_read_full(f, buf2, len, &bytes_read); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_INT_EQUAL(tc, 0, (int)bytes_read); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + apr_file_close(f); + + apr_file_remove(fname, p); +} + +static void test_small_and_large_reads_buffered(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testtwo_large_reads_buffered.dat"; + apr_size_t len; + apr_size_t bytes_written; + apr_size_t bytes_read; + char *buf; + char *buf2; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for writing", rv); + len = 80000; + buf = apr_palloc(p, len); + memset(buf, 'a', len); + rv = apr_file_write_full(f, buf, len, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for reading", rv); + + /* Test small read followed by a large read. */ + buf2 = apr_palloc(p, len); + memset(buf2, 0, len); + rv = apr_file_read_full(f, buf2, 5, &bytes_read); + APR_ASSERT_SUCCESS(tc, "read from file", rv); + ABTS_INT_EQUAL(tc, 5, (int)bytes_read); + ABTS_TRUE(tc, memcmp(buf, buf2, bytes_read) == 0); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + memset(buf2, 0, len); + rv = apr_file_read_full(f, buf2, len - 5, &bytes_read); + APR_ASSERT_SUCCESS(tc, "read from file", rv); + ABTS_INT_EQUAL(tc, (int)(len - 5), (int)bytes_read); + ABTS_TRUE(tc, memcmp(buf + 5, buf2, bytes_read) == 0); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* Test that we receive an EOF. */ + len = 1; + rv = apr_file_read_full(f, buf2, len, &bytes_read); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_INT_EQUAL(tc, 0, (int)bytes_read); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + apr_file_close(f); + + apr_file_remove(fname, p); +} + +static void test_read_buffered_spanning_over_bufsize(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testread_buffered_spanning_over_bufsize.dat"; + apr_size_t len; + apr_size_t bytes_written; + apr_size_t bytes_read; + char *buf; + char *buf2; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for writing", rv); + len = APR_BUFFERSIZE + 1; + buf = apr_palloc(p, len); + memset(buf, 'a', len); + rv = apr_file_write_full(f, buf, len, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for reading", rv); + + /* Test reads than span over the default buffer size. */ + buf2 = apr_palloc(p, len); + memset(buf2, 0, len); + rv = apr_file_read_full(f, buf2, APR_BUFFERSIZE - 1, &bytes_read); + APR_ASSERT_SUCCESS(tc, "read from file", rv); + ABTS_INT_EQUAL(tc, APR_BUFFERSIZE - 1, (int)bytes_read); + ABTS_TRUE(tc, memcmp(buf, buf2, bytes_read) == 0); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + memset(buf2, 0, len); + rv = apr_file_read_full(f, buf2, 2, &bytes_read); + APR_ASSERT_SUCCESS(tc, "read from file", rv); + ABTS_INT_EQUAL(tc, 2, (int)bytes_read); + ABTS_TRUE(tc, memcmp(buf, buf2, bytes_read) == 0); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* Test that we receive an EOF. */ + len = 1; + rv = apr_file_read_full(f, buf2, len, &bytes_read); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_INT_EQUAL(tc, 0, (int)bytes_read); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + apr_file_close(f); + + apr_file_remove(fname, p); +} + +static void test_single_byte_reads_buffered(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testsingle_byte_reads_buffered.dat"; + apr_size_t len; + apr_size_t bytes_written; + apr_size_t bytes_read; + char *buf; + apr_size_t total; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for writing", rv); + len = 40000; + buf = apr_palloc(p, len); + memset(buf, 'a', len); + rv = apr_file_write_full(f, buf, len, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for reading", rv); + + total = 0; + while (1) { + memset(buf, 0, len); + rv = apr_file_read_full(f, buf, 1, &bytes_read); + if (rv == APR_EOF) { + break; + } + APR_ASSERT_SUCCESS(tc, "read from file", rv); + ABTS_INT_EQUAL(tc, 1, (int)bytes_read); + ABTS_INT_EQUAL(tc, 'a', buf[0]); + total += bytes_read; + } + ABTS_INT_EQUAL(tc, (int)len, (int)total); + + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + apr_file_close(f); + + apr_file_remove(fname, p); +} + +static void test_read_buffered_seek(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testtest_read_buffered_seek.dat"; + apr_size_t len; + apr_size_t bytes_written; + apr_size_t bytes_read; + char buf[64]; + apr_off_t off; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for writing", rv); + rv = apr_file_write_full(f, "abcdef", 6, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open test file for reading", rv); + + /* Read one byte. */ + memset(buf, 0, sizeof(buf)); + rv = apr_file_read_full(f, buf, 1, &bytes_read); + APR_ASSERT_SUCCESS(tc, "read from file", rv); + ABTS_INT_EQUAL(tc, 1, (int)bytes_read); + ABTS_INT_EQUAL(tc, 'a', buf[0]); + + /* Seek into the middle of the file. */ + off = 3; + rv = apr_file_seek(f, APR_SET, &off); + APR_ASSERT_SUCCESS(tc, "change file read offset", rv); + ABTS_INT_EQUAL(tc, 3, (int)off); + + /* Read three bytes. */ + memset(buf, 0, sizeof(buf)); + rv = apr_file_read_full(f, buf, 3, &bytes_read); + APR_ASSERT_SUCCESS(tc, "read from file", rv); + ABTS_INT_EQUAL(tc, 3, (int)bytes_read); + ABTS_TRUE(tc, memcmp(buf, "def", bytes_read) == 0); + + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* Test that we receive an EOF. */ + len = 1; + rv = apr_file_read_full(f, buf, len, &bytes_read); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_INT_EQUAL(tc, 0, (int)bytes_read); + rv = apr_file_eof(f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + apr_file_close(f); + + apr_file_remove(fname, p); +} + +static void test_append_buffered(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testappend_buffered.dat"; + apr_size_t bytes_written; + char buf[64]; + + apr_file_remove(fname, p); + + /* Create file with contents. */ + rv = apr_file_open(&f, fname, APR_FOPEN_WRITE | APR_FOPEN_CREATE, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "create file", rv); + + rv = apr_file_write_full(f, "abc", 3, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + apr_file_close(f); + + /* Re-open it with APR_FOPEN_APPEND and APR_FOPEN_BUFFERED. */ + rv = apr_file_open(&f, fname, + APR_FOPEN_READ | APR_FOPEN_WRITE | + APR_FOPEN_APPEND | APR_FOPEN_BUFFERED, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open file", rv); + + /* Append to the file. */ + rv = apr_file_write_full(f, "def", 3, &bytes_written); + APR_ASSERT_SUCCESS(tc, "write to file", rv); + apr_file_close(f); + + rv = apr_file_open(&f, fname, APR_FOPEN_READ, + APR_FPROT_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open file", rv); + + /* Test the file contents. */ + rv = apr_file_gets(buf, sizeof(buf), f); + APR_ASSERT_SUCCESS(tc, "read from file", rv); + ABTS_STR_EQUAL(tc, "abcdef", buf); + + apr_file_close(f); + apr_file_remove(fname, p); +} + abts_suite *testfile(abts_suite *suite) { suite = ADD_SUITE(suite) @@ -1286,6 +2253,11 @@ abts_suite *testfile(abts_suite *suite) abts_run_test(suite, test_ungetc, NULL); abts_run_test(suite, test_gets, NULL); abts_run_test(suite, test_gets_buffered, NULL); + abts_run_test(suite, test_gets_empty, NULL); + abts_run_test(suite, test_gets_multiline, NULL); + abts_run_test(suite, test_gets_small_buf, NULL); + abts_run_test(suite, test_gets_ungetc, NULL); + abts_run_test(suite, test_gets_buffered_big, NULL); abts_run_test(suite, test_puts, NULL); abts_run_test(suite, test_writev, NULL); abts_run_test(suite, test_writev_full, NULL); @@ -1306,6 +2278,20 @@ abts_suite *testfile(abts_suite *suite) abts_run_test(suite, test_xthread, NULL); abts_run_test(suite, test_datasync_on_file, NULL); abts_run_test(suite, test_datasync_on_stream, NULL); + abts_run_test(suite, test_atomic_append, NULL); + abts_run_test(suite, test_append_locked, NULL); + abts_run_test(suite, test_large_write_buffered, NULL); + abts_run_test(suite, test_two_large_writes_buffered, NULL); + abts_run_test(suite, test_small_and_large_writes_buffered, NULL); + abts_run_test(suite, test_write_buffered_spanning_over_bufsize, NULL); + abts_run_test(suite, test_empty_read_buffered, NULL); + abts_run_test(suite, test_large_read_buffered, NULL); + abts_run_test(suite, test_two_large_reads_buffered, NULL); + abts_run_test(suite, test_small_and_large_reads_buffered, NULL); + abts_run_test(suite, test_read_buffered_spanning_over_bufsize, NULL); + abts_run_test(suite, test_single_byte_reads_buffered, NULL); + abts_run_test(suite, test_read_buffered_seek, NULL); + abts_run_test(suite, test_append_buffered, NULL); return suite; } diff --git a/test/testmutexscope.c b/test/testmutexscope.c index 2120fff..8dc1afc 100644 --- a/test/testmutexscope.c +++ b/test/testmutexscope.c @@ -93,7 +93,7 @@ static void lock_release(test_mode_e test_mode) static void * APR_THREAD_FUNC eachThread(apr_thread_t *id, void *p) { - test_mode_e test_mode = (test_mode_e)p; + test_mode_e test_mode = (test_mode_e)(apr_uintptr_t)p; lock_grab(test_mode); ++counter; @@ -142,7 +142,7 @@ static void test_mech_mode(apr_lockmech_e mech, const char *mech_name, rv = apr_thread_create(&threads[i], NULL, eachThread, - (void *)test_mode, + (void *)(apr_uintptr_t)test_mode, p); if (rv != APR_SUCCESS) { fprintf(stderr, "apr_thread_create->%d\n", rv); diff --git a/test/testpoll.c b/test/testpoll.c index 9f90af2..960b6a7 100644 --- a/test/testpoll.c +++ b/test/testpoll.c @@ -22,6 +22,13 @@ #include "apr_network_io.h" #include "apr_poll.h" +#if defined(__linux__) +#include "arch/unix/apr_private.h" +#endif +#ifndef HAVE_EPOLL_WAIT_RELIABLE_TIMEOUT +#define HAVE_EPOLL_WAIT_RELIABLE_TIMEOUT 0 +#endif + #define SMALL_NUM_SOCKETS 3 /* We can't use 64 here, because some platforms *ahem* Solaris *ahem* have * a default limit of 64 open file descriptors per process. If we use @@ -854,6 +861,16 @@ static void pollcb_wakeup(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, APR_EINTR, rv); } +#define JUSTSLEEP_DELAY apr_time_from_msec(200) +#if HAVE_EPOLL_WAIT_RELIABLE_TIMEOUT +#define JUSTSLEEP_ENOUGH(ts, te) \ + ((te) - (ts) >= JUSTSLEEP_DELAY) +#else +#define JUSTSLEEP_JIFFY apr_time_from_msec(10) +#define JUSTSLEEP_ENOUGH(ts, te) \ + ((te) - (ts) >= JUSTSLEEP_DELAY - JUSTSLEEP_JIFFY) +#endif + static void justsleep(abts_case *tc, void *data) { apr_int32_t nsds; @@ -872,13 +889,13 @@ static void justsleep(abts_case *tc, void *data) nsds = 1; t1 = apr_time_now(); - rv = apr_poll(NULL, 0, &nsds, apr_time_from_msec(200)); + rv = apr_poll(NULL, 0, &nsds, JUSTSLEEP_DELAY); t2 = apr_time_now(); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); ABTS_INT_EQUAL(tc, 0, nsds); ABTS_ASSERT(tc, "apr_poll() didn't sleep", - (t2 - t1) > apr_time_from_msec(100)); + JUSTSLEEP_ENOUGH(t1, t2)); for (i = 0; i < sizeof methods / sizeof methods[0]; i++) { rv = apr_pollset_create_ex(&pollset, 5, p, 0, methods[i]); @@ -887,14 +904,13 @@ static void justsleep(abts_case *tc, void *data) nsds = 1; t1 = apr_time_now(); - rv = apr_pollset_poll(pollset, apr_time_from_msec(200), &nsds, - &hot_files); + rv = apr_pollset_poll(pollset, JUSTSLEEP_DELAY, &nsds, &hot_files); t2 = apr_time_now(); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); ABTS_INT_EQUAL(tc, 0, nsds); ABTS_ASSERT(tc, "apr_pollset_poll() didn't sleep", - (t2 - t1) > apr_time_from_msec(100)); + JUSTSLEEP_ENOUGH(t1, t2)); rv = apr_pollset_destroy(pollset); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); @@ -905,12 +921,12 @@ static void justsleep(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); t1 = apr_time_now(); - rv = apr_pollcb_poll(pollcb, apr_time_from_msec(200), NULL, NULL); + rv = apr_pollcb_poll(pollcb, JUSTSLEEP_DELAY, NULL, NULL); t2 = apr_time_now(); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); ABTS_ASSERT(tc, "apr_pollcb_poll() didn't sleep", - (t2 - t1) > apr_time_from_msec(100)); + JUSTSLEEP_ENOUGH(t1, t2)); /* no apr_pollcb_destroy() */ } diff --git a/test/testproc.c b/test/testproc.c index 096ecfd..3c32465 100644 --- a/test/testproc.c +++ b/test/testproc.c @@ -65,6 +65,9 @@ static void test_create_proc(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_SIZE_EQUAL(tc, strlen(TESTSTR), length); + rv = apr_file_close(testfile); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + testfile = newproc.out; length = 256; buf = apr_pcalloc(p, length); diff --git a/test/testshm.c b/test/testshm.c index 7387069..3b97471 100644 --- a/test/testshm.c +++ b/test/testshm.c @@ -31,36 +31,6 @@ #if APR_HAS_SHARED_MEMORY -#if APR_HAS_FORK -static int msgwait(int sleep_sec, int first_box, int last_box) -{ - int i; - int recvd = 0; - apr_time_t start = apr_time_now(); - apr_interval_time_t sleep_duration = apr_time_from_sec(sleep_sec); - while (apr_time_now() - start < sleep_duration) { - for (i = first_box; i < last_box; i++) { - if (boxes[i].msgavail && !strcmp(boxes[i].msg, MSG)) { - recvd++; - boxes[i].msgavail = 0; /* reset back to 0 */ - /* reset the msg field. 1024 is a magic number and it should - * be a macro, but I am being lazy. - */ - memset(boxes[i].msg, 0, 1024); - } - } - apr_sleep(apr_time_make(0, 10000)); /* 10ms */ - } - return recvd; -} - -static void msgput(int boxnum, char *msg) -{ - apr_cpystrn(boxes[boxnum].msg, msg, strlen(msg) + 1); - boxes[boxnum].msgavail = 1; -} -#endif /* APR_HAS_FORK */ - static void test_anon_create(abts_case *tc, void *data) { apr_status_t rv; @@ -102,6 +72,7 @@ static void test_shm_allocate(abts_case *tc, void *data) boxes = apr_shm_baseaddr_get(shm); ABTS_PTR_NOTNULL(tc, boxes); + memset(boxes, 0, SHARED_SIZE); rv = apr_shm_destroy(shm); APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv); @@ -126,10 +97,13 @@ static void test_anon(abts_case *tc, void *data) boxes = apr_shm_baseaddr_get(shm); ABTS_PTR_NOTNULL(tc, boxes); + memset(boxes, 0, SHARED_SIZE); rv = apr_proc_fork(&proc, p); if (rv == APR_INCHILD) { /* child */ - int num = msgwait(5, 0, N_BOXES); + int num = msgwait("anon_test", N_MESSAGES, + 5, /* wait for 5s */ + 10 /* with 10ms spin delay */); /* exit with the number of messages received so that the parent * can check that all messages were received. */ @@ -142,8 +116,10 @@ static void test_anon(abts_case *tc, void *data) if ((i-=3) < 0) { i += N_BOXES; /* start over at the top */ } - msgput(i, MSG); - apr_sleep(apr_time_make(0, 10000)); + if (!msgput("anon_test", i)) { + cnt--; + } + apr_sleep(apr_time_from_msec(10)); } } else { @@ -183,6 +159,7 @@ static void test_named(abts_case *tc, void *data) boxes = apr_shm_baseaddr_get(shm); ABTS_PTR_NOTNULL(tc, boxes); + memset(boxes, 0, SHARED_SIZE); rv = apr_procattr_create(&attr1, p); ABTS_PTR_NOTNULL(tc, attr1); @@ -308,6 +285,36 @@ static void test_named_delete(abts_case *tc, void *data) ABTS_TRUE(tc, rv != 0); } +static void test_named_perms(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_shm_t *shm; + apr_uid_t uid; + apr_gid_t gid; + + apr_shm_remove(SHARED_FILENAME, p); + + rv = apr_shm_create(&shm, SHARED_SIZE, SHARED_FILENAME, p); + APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv); + if (rv != APR_SUCCESS) { + return; + } + ABTS_PTR_NOTNULL(tc, shm); + + rv = apr_uid_current(&uid, &gid, p); + APR_ASSERT_SUCCESS(tc, "retrieve current uid/gid", rv); + if (rv) return; + + rv = apr_shm_perms_set(shm, + APR_FPROT_UREAD|APR_FPROT_UWRITE, uid, gid); + apr_shm_destroy(shm); + + if (rv == APR_ENOTIMPL) + ABTS_SKIP(tc, data, "apr_shm_perms_set not implemented for named shm"); + else + APR_ASSERT_SUCCESS(tc, "Could not change permissions of shm segment", rv); +} + #endif abts_suite *testshm(abts_suite *suite) @@ -324,6 +331,7 @@ abts_suite *testshm(abts_suite *suite) abts_run_test(suite, test_named, NULL); abts_run_test(suite, test_named_remove, NULL); abts_run_test(suite, test_named_delete, NULL); + abts_run_test(suite, test_named_perms, NULL); #endif return suite; diff --git a/test/testshm.h b/test/testshm.h index 5b24a9d..4d4f0c5 100644 --- a/test/testshm.h +++ b/test/testshm.h @@ -17,17 +17,67 @@ #ifndef TESTSHM_H #define TESTSHM_H +#include "apr.h" +#include "apr_time.h" +#include "apr_atomic.h" +#include "apr_strings.h" + +#include <assert.h> + typedef struct mbox { char msg[1024]; - int msgavail; + apr_uint32_t msgavail; } mbox; mbox *boxes; #define N_BOXES 10 +#define N_MESSAGES 100 #define SHARED_SIZE (apr_size_t)(N_BOXES * sizeof(mbox)) #define SHARED_FILENAME "data/apr.testshm.shm" -#define N_MESSAGES 100 #define MSG "Sending a message" -#endif +#if APR_HAS_SHARED_MEMORY +static APR_INLINE +int msgwait(const char *msg, int count, int duration, int sleep_ms) +{ + int recvd = 0, i; + apr_time_t start = apr_time_now(); + apr_interval_time_t sleep_duration = apr_time_from_sec(duration); + apr_interval_time_t sleep_delay = apr_time_from_msec(sleep_ms); + while (apr_time_now() - start < sleep_duration) { + for (i = 0; i < N_BOXES; i++) { + if (apr_atomic_cas32(&boxes[i].msgavail, 0, 1) == 1) { + if (msg) { + assert(strcmp(boxes[i].msg, msg) == 0); + } + *boxes[i].msg = '\0'; + if (++recvd == count) { + return recvd; + } + } + } + apr_sleep(sleep_delay); + } + return recvd; +} + +static APR_INLINE +int msgput(const char *msg, int boxnum) +{ + if (apr_atomic_cas32(&boxes[boxnum].msgavail, -1, 0) != 0) { + return 0; + } + if (msg) { + apr_cpystrn(boxes[boxnum].msg, msg, sizeof(boxes[boxnum].msg)); + } + else { + *boxes[boxnum].msg = '\0'; + } + apr_atomic_set32(&boxes[boxnum].msgavail, 1); + return 1; +} + +#endif /* APR_HAS_SHARED_MEMORY */ + +#endif diff --git a/test/testshmconsumer.c b/test/testshmconsumer.c index 6a2a3c3..bf70e72 100644 --- a/test/testshmconsumer.c +++ b/test/testshmconsumer.c @@ -30,25 +30,6 @@ #if APR_HAS_SHARED_MEMORY -static int msgwait(int sleep_sec, int first_box, int last_box) -{ - int i; - int recvd = 0; - apr_time_t start = apr_time_now(); - apr_interval_time_t sleep_duration = apr_time_from_sec(sleep_sec); - while (apr_time_now() - start < sleep_duration) { - for (i = first_box; i < last_box; i++) { - if (boxes[i].msgavail && !strcmp(boxes[i].msg, MSG)) { - recvd++; - boxes[i].msgavail = 0; /* reset back to 0 */ - memset(boxes[i].msg, 0, 1024); - } - } - apr_sleep(apr_time_from_sec(1)); - } - return recvd; -} - int main(void) { apr_status_t rv; @@ -70,7 +51,7 @@ int main(void) boxes = apr_shm_baseaddr_get(shm); /* consume messages on all of the boxes */ - recvd = msgwait(30, 0, N_BOXES); /* wait for 30 seconds for messages */ + recvd = msgwait(MSG, N_MESSAGES, 30, 1); rv = apr_shm_detach(shm); if (rv != APR_SUCCESS) { diff --git a/test/testshmproducer.c b/test/testshmproducer.c index 58eb94f..eb61e76 100644 --- a/test/testshmproducer.c +++ b/test/testshmproducer.c @@ -29,11 +29,6 @@ #if APR_HAS_SHARED_MEMORY -static void msgput(int boxnum, char *msg) -{ - apr_cpystrn(boxes[boxnum].msg, msg, strlen(msg) + 1); - boxes[boxnum].msgavail = 1; -} int main(void) { @@ -63,7 +58,7 @@ int main(void) * are returning the right number. */ for (i = N_BOXES - 1, sent = 0; i >= 0; i--, sent++) { - msgput(i, MSG); + msgput(MSG, i); apr_sleep(apr_time_from_sec(1)); } |