summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-12 04:59:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-12 04:59:58 +0000
commitb8d375bcb1f462d5af5d1f480b32d7b0038417f6 (patch)
tree93d48ade79cc9d5892f17ff41c33753be6bb0879 /test
parentAdding upstream version 1.7.2. (diff)
downloadapr-upstream.tar.xz
apr-upstream.zip
Adding upstream version 1.7.5.upstream/1.7.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--test/abts.c153
-rw-r--r--test/abts.h45
-rw-r--r--test/testatomic.c147
-rw-r--r--test/testdir.c49
-rw-r--r--test/testencode.c70
-rw-r--r--test/testescape.c2
-rw-r--r--test/testfile.c986
-rw-r--r--test/testmutexscope.c4
-rw-r--r--test/testpoll.c30
-rw-r--r--test/testproc.c3
-rw-r--r--test/testshm.c74
-rw-r--r--test/testshm.h56
-rw-r--r--test/testshmconsumer.c21
-rw-r--r--test/testshmproducer.c7
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 = "&#255&lt;&gt;&amp;'&quot;Hello World";
+ target = "&#255;&lt;&gt;&amp;'&quot;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));
}