示例#1
0
static void test_buffered_write_size(abts_case *tc, void *data)
{
    const apr_size_t data_len = strlen(NEWFILEDATA);
    apr_file_t *thefile;
    apr_finfo_t finfo;
    apr_status_t rv;
    apr_size_t bytes;

    rv = apr_file_open(&thefile, NEWFILENAME,
                       APR_READ | APR_WRITE | APR_CREATE | APR_TRUNCATE
                       | APR_BUFFERED | APR_DELONCLOSE,
                       APR_OS_DEFAULT, p);
    APR_ASSERT_SUCCESS(tc, "open file", rv);

    /* A funny thing happened to me the other day: I wrote something
     * into a buffered file, then asked for its size using
     * apr_file_info_get; and guess what? The size was 0! That's not a
     * nice way to behave.
     */
    bytes = data_len;
    rv = apr_file_write(thefile, NEWFILEDATA, &bytes);
    APR_ASSERT_SUCCESS(tc, "write file contents", rv);
    ABTS_TRUE(tc, data_len == bytes);

    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, thefile);
    APR_ASSERT_SUCCESS(tc, "get file size", rv);
    ABTS_TRUE(tc, bytes == (apr_size_t) finfo.size);
    apr_file_close(thefile);
}
示例#2
0
文件: teststr.c 项目: ohmann/checkapi
static void test_strtok(abts_case *tc, void *data)
{
    struct {
        char *input;
        char *sep;
    }
    cases[] = {
        {
            "",
            "Z"
        },
        {
            "      asdf jkl; 77889909            \r\n\1\2\3Z",
            " \r\n\3\2\1"
        },
        {
            NULL,  /* but who cares if apr_strtok() segfaults? */
            " \t"
        },
#if 0     /* don't do this... you deserve to segfault */
        {
            "a b c              ",
            NULL
        },
#endif
        {
            "   a       b        c   ",
            ""
        },
        {
            "a              b c         ",
            " "
        }
    };
    int curtc;

    for (curtc = 0; curtc < sizeof cases / sizeof cases[0]; curtc++) {
        char *retval1, *retval2;
        char *str1, *str2;
        char *state;

        str1 = apr_pstrdup(p, cases[curtc].input);
        str2 = apr_pstrdup(p, cases[curtc].input);

        do {
            retval1 = apr_strtok(str1, cases[curtc].sep, &state);
            retval2 = strtok(str2, cases[curtc].sep);

            if (!retval1) {
                ABTS_TRUE(tc, retval2 == NULL);
            }
            else {
                ABTS_TRUE(tc, retval2 != NULL);
                ABTS_STR_EQUAL(tc, retval2, retval1);
            }

            str1 = str2 = NULL; /* make sure we pass NULL on subsequent calls */
        } while (retval1);
    }
}
示例#3
0
static void test_singleton_subnets(abts_case *tc, void *data)
{
    const char *v4addrs[] = {
        "127.0.0.1", "129.42.18.99", "63.161.155.20", "207.46.230.229", "64.208.42.36",
        "198.144.203.195", "192.18.97.241", "198.137.240.91", "62.156.179.119", 
        "204.177.92.181"
    };
    apr_ipsubnet_t *ipsub;
    apr_sockaddr_t *sa;
    apr_status_t rv;
    int i, j, rc;

    for (i = 0; i < sizeof v4addrs / sizeof v4addrs[0]; i++) {
        rv = apr_ipsubnet_create(&ipsub, v4addrs[i], NULL, p);
        ABTS_TRUE(tc, rv == APR_SUCCESS);
        for (j = 0; j < sizeof v4addrs / sizeof v4addrs[0]; j++) {
            rv = apr_sockaddr_info_get(&sa, v4addrs[j], APR_INET, 0, 0, p);
            ABTS_TRUE(tc, rv == APR_SUCCESS);
            rc = apr_ipsubnet_test(ipsub, sa);
            if (!strcmp(v4addrs[i], v4addrs[j])) {
                ABTS_TRUE(tc, rc != 0);
            }
            else {
                ABTS_TRUE(tc, rc == 0);
            }
        }
    }

    /* same for v6? */
}
示例#4
0
文件: teststr.c 项目: ohmann/checkapi
static void string_cpystrn(abts_case *tc, void *data)
{
    char buf[6], *ret;

    buf[5] = 'Z';

    ret = apr_cpystrn(buf, "123456", 5);

    ABTS_STR_EQUAL(tc, "1234", buf);
    ABTS_PTR_EQUAL(tc, buf + 4, ret);
    ABTS_TRUE(tc, *ret == '\0');
    ABTS_TRUE(tc, ret[1] == 'Z');
}
示例#5
0
static void test_print_addr(abts_case *tc, void *data)
{
    apr_sockaddr_t *sa;
    apr_status_t rv;
    char *s;

    rv = apr_sockaddr_info_get(&sa, "0.0.0.0", APR_INET, 80, 0, p);
    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);

    s = apr_psprintf(p, "foo %pI bar", sa);

    ABTS_STR_EQUAL(tc, "foo 0.0.0.0:80 bar", s);

#if APR_HAVE_IPV6
    rv = apr_sockaddr_info_get(&sa, "::ffff:0.0.0.0", APR_INET6, 80, 0, p);
    APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
    if (rv == APR_SUCCESS)
        ABTS_TRUE(tc, sa != NULL);
    if (rv == APR_SUCCESS && sa) {
        /* sa should now be a v4-mapped IPv6 address. */
        char buf[128];
        int rc;

        rc = apr_sockaddr_is_wildcard(sa);
        ABTS_INT_NEQUAL(tc, 0, rc);

        memset(buf, 'z', sizeof buf);
        
        APR_ASSERT_SUCCESS(tc, "could not get IP address",
                           apr_sockaddr_ip_getbuf(buf, 22, sa));
        
        ABTS_STR_EQUAL(tc, "0.0.0.0", buf);
    }
#endif
}
示例#6
0
static void test_timeout(abts_case *tc, apr_reslist_t *rl)
{
    apr_status_t rv;
    my_resource_t *resources[RESLIST_HMAX];
    my_resource_t *res;
    void *vp;
    int i;

    apr_reslist_timeout_set(rl, 1000);

    /* deplete all possible resources from the resource list
     * so that the next call will block until timeout is reached
     * (since there are no other threads to make a resource
     * available)
     */

    for (i = 0; i < RESLIST_HMAX; i++) {
        rv = apr_reslist_acquire(rl, (void**)&resources[i]);
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    }

    /* next call will block until timeout is reached */
    rv = apr_reslist_acquire(rl, &vp);
    ABTS_TRUE(tc, APR_STATUS_IS_TIMEUP(rv));

    res = vp;

    /* release the resources; otherwise the destroy operation
     * will blow
     */
    for (i = 0; i < RESLIST_HMAX; i++) {
        rv = apr_reslist_release(rl, resources[i]);
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    }
}
示例#7
0
static void sendto_receivefrom6(abts_case *tc, void *data)
{
    int failed;
    sendto_receivefrom_helper(tc, "::1", APR_INET6);
    failed = tc->failed; tc->failed = 0;
    ABTS_TRUE(tc, !failed);
}
示例#8
0
文件: testldap.c 项目: 0jpq0/kbengine
static void test_ldap_connection(abts_case *tc, LDAP *ldap)
{
    int version  = LDAP_VERSION3;
    int failures, result;
    
    /* always default to LDAP V3 */
    ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &version);

    for (failures=0; failures<10; failures++)
    {
        result = ldap_simple_bind_s(ldap,
                                    (char *)NULL,
                                    (char *)NULL);
        if (LDAP_SERVER_DOWN != result)
            break;
    }

    ABTS_TRUE(tc, result == LDAP_SUCCESS);
    if (result != LDAP_SUCCESS) {
        abts_log_message("%s\n", ldap_err2string(result));
    }

    ldap_unbind_s(ldap);

    return;
}
示例#9
0
static void pong(toolbox_t *box)
{
    apr_status_t rv;
    abts_case *tc = box->tc;

    rv = apr_thread_mutex_lock(box->mutex);
    ABTS_SUCCESS(rv);

    if (state == TOSS)
        state = PONG;

    do {
        rv = apr_thread_cond_signal(box->cond);
        ABTS_SUCCESS(rv);

        state = PING;

        rv = apr_thread_cond_wait(box->cond, box->mutex);
        ABTS_SUCCESS(rv);

        ABTS_TRUE(tc, state == PONG || state == OVER);
    } while (state != OVER);

    rv = apr_thread_mutex_unlock(box->mutex);
    ABTS_SUCCESS(rv);

    rv = apr_thread_cond_broadcast(box->cond);
    ABTS_SUCCESS(rv);
}
示例#10
0
static void sleep_one(abts_case *tc, void *data)
{
    time_t pretime = time(NULL);
    time_t posttime;
    time_t timediff;

    apr_sleep(apr_time_from_sec(SLEEP_INTERVAL));
    posttime = time(NULL);

    /* normalize the timediff.  We should have slept for SLEEP_INTERVAL, so
     * we should just subtract that out.
     */
    timediff = posttime - pretime - SLEEP_INTERVAL;
    ABTS_TRUE(tc, timediff >= 0);
    ABTS_TRUE(tc, timediff <= 1);
}
示例#11
0
static void test_mtime_set(abts_case *tc, void *data)
{
    apr_file_t *thefile;
    apr_finfo_t finfo;
    apr_time_t epoch = 0;
    apr_status_t rv;

    /* This test sort of depends on the system clock being at least
     * marginally ccorrect; We'll be setting the modification time to
     * the epoch.
     */
    rv = apr_file_open(&thefile, NEWFILENAME,
                       APR_READ | APR_WRITE | APR_CREATE | APR_TRUNCATE
                       | APR_BUFFERED | APR_DELONCLOSE,
                       APR_OS_DEFAULT, p);
    APR_ASSERT_SUCCESS(tc, "open file", rv);

    /* Check that the current mtime is not the epoch */
    rv = apr_stat(&finfo, NEWFILENAME, APR_FINFO_MTIME, p);
    if (rv  == APR_INCOMPLETE) {
        char *str;
	int i;
        str = apr_pstrdup(p, "APR_INCOMPLETE:  Missing ");
        for (i = 0; vfi[i].bits; ++i) {
            if (vfi[i].bits & ~finfo.valid) {
                str = apr_pstrcat(p, str, vfi[i].description, " ", NULL);
            }
        }
        ABTS_FAIL(tc, str);
    }
    APR_ASSERT_SUCCESS(tc, "get initial mtime", rv);
    ABTS_TRUE(tc, finfo.mtime != epoch);

    /* Reset the mtime to the epoch and verify the result.
     * Note: we blindly assume that if the first apr_stat succeeded,
     * the second one will, too.
     */
    rv = apr_file_mtime_set(NEWFILENAME, epoch, p);
    APR_ASSERT_SUCCESS(tc, "set mtime", rv);

    rv = apr_stat(&finfo, NEWFILENAME, APR_FINFO_MTIME, p);
    APR_ASSERT_SUCCESS(tc, "get modified mtime", rv);
    ABTS_TRUE(tc, finfo.mtime == epoch);

    apr_file_close(thefile);
}
示例#12
0
static void create_filename(abts_case *tc, void *data)
{
    char *oldfileptr;

    apr_filepath_get(&file1, 0, p);
#ifndef NETWARE
#ifdef WIN32
    ABTS_TRUE(tc, file1[1] == ':');
#else
    ABTS_TRUE(tc, file1[0] == '/');
#endif
#endif
    ABTS_TRUE(tc, file1[strlen(file1) - 1] != '/');

    oldfileptr = file1;
    file1 = apr_pstrcat(p, file1,"/data/mmap_datafile.txt" ,NULL);
    ABTS_TRUE(tc, oldfileptr != file1);
}
示例#13
0
文件: testfile.c 项目: aptana/Jaxer
static void test_open_excl(abts_case *tc, void *data)
{
    apr_status_t rv;
    apr_file_t *thefile = NULL;

    rv = apr_file_open(&thefile, FILENAME,
                       APR_CREATE | APR_EXCL | APR_WRITE, 
                       APR_UREAD | APR_UWRITE | APR_GREAD, p);
    ABTS_TRUE(tc, rv != APR_SUCCESS);
    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EEXIST(rv));
    ABTS_PTR_EQUAL(tc, NULL, thefile); 
}
示例#14
0
文件: testfile.c 项目: cmjonze/apr
static void test_open_noreadwrite(abts_case *tc, void *data)
{
    apr_status_t rv;
    apr_file_t *thefile = NULL;

    rv = apr_file_open(&thefile, FILENAME,
                       APR_FOPEN_CREATE | APR_FOPEN_EXCL,
                       APR_FPROT_UREAD | APR_FPROT_UWRITE | APR_FPROT_GREAD, p);
    ABTS_TRUE(tc, rv != APR_SUCCESS);
    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EACCES(rv));
    ABTS_PTR_EQUAL(tc, NULL, thefile); 
}
示例#15
0
static void test_interesting_subnets(abts_case *tc, void *data)
{
    struct {
        const char *ipstr, *mask;
        int family;
        char *in_subnet, *not_in_subnet;
    } testcases[] =
    {
        {"9.67",              NULL,            APR_INET,  "9.67.113.15",         "10.1.2.3"}
        ,{"9.67.0.0",         "16",            APR_INET,  "9.67.113.15",         "10.1.2.3"}
        ,{"9.67.0.0",         "255.255.0.0",   APR_INET,  "9.67.113.15",         "10.1.2.3"}
        ,{"9.67.113.99",      "16",            APR_INET,  "9.67.113.15",         "10.1.2.3"}
        ,{"9.67.113.99",      "255.255.255.0", APR_INET,  "9.67.113.15",         "10.1.2.3"}
#if APR_HAVE_IPV6
        ,{"fe80::",           "8",             APR_INET6, "fe80::1",             "ff01::1"}
        ,{"ff01::",           "8",             APR_INET6, "ff01::1",             "fe80::1"}
        ,{"3FFE:8160::",      "28",            APR_INET6, "3ffE:816e:abcd:1234::1", "3ffe:8170::1"}
        ,{"127.0.0.1",        NULL,            APR_INET6, "::ffff:127.0.0.1",    "fe80::1"}
        ,{"127.0.0.1",        "8",             APR_INET6, "::ffff:127.0.0.1",    "fe80::1"}
#endif
    };
    apr_ipsubnet_t *ipsub;
    apr_sockaddr_t *sa;
    apr_status_t rv;
    int i, rc;

    for (i = 0; i < sizeof testcases / sizeof testcases[0]; i++) {
        rv = apr_ipsubnet_create(&ipsub, testcases[i].ipstr, testcases[i].mask, p);
        ABTS_TRUE(tc, rv == APR_SUCCESS);
        rv = apr_sockaddr_info_get(&sa, testcases[i].in_subnet, testcases[i].family, 0, 0, p);
        ABTS_TRUE(tc, rv == APR_SUCCESS);
        rc = apr_ipsubnet_test(ipsub, sa);
        ABTS_TRUE(tc, rc != 0);
        rv = apr_sockaddr_info_get(&sa, testcases[i].not_in_subnet, testcases[i].family, 0, 0, p);
        ABTS_TRUE(tc, rv == APR_SUCCESS);
        rc = apr_ipsubnet_test(ipsub, sa);
        ABTS_TRUE(tc, rc == 0);
    }
}
示例#16
0
文件: testldap.c 项目: 0jpq0/kbengine
static int add_ldap_certs(abts_case *tc)
{
    apr_status_t status;
    apr_dir_t *thedir;
    apr_finfo_t dirent;
    apr_ldap_err_t *result = NULL;

    if ((status = apr_dir_open(&thedir, DIRNAME, p)) == APR_SUCCESS) {
        apr_ldap_opt_tls_cert_t *cert = (apr_ldap_opt_tls_cert_t *)apr_pcalloc(p, sizeof(apr_ldap_opt_tls_cert_t));

        do {
            status = apr_dir_read(&dirent, APR_FINFO_MIN | APR_FINFO_NAME, thedir);
            if (APR_STATUS_IS_INCOMPLETE(status)) {
                continue; /* ignore un-stat()able files */
            }
            else if (status != APR_SUCCESS) {
                break;
            }

            if (strstr(dirent.name, ".der")) {
                cert->type = APR_LDAP_CA_TYPE_DER;
                cert->path = apr_pstrcat (p, DIRNAME, "/", dirent.name, NULL);
                apr_ldap_set_option(p, NULL, APR_LDAP_OPT_TLS_CERT, (void *)cert, &result);
                ABTS_TRUE(tc, result->rc == LDAP_SUCCESS);
            }
            if (strstr(dirent.name, ".b64")) {
                cert->type = APR_LDAP_CA_TYPE_BASE64;
                cert->path = apr_pstrcat (p, DIRNAME, "/", dirent.name, NULL);
                apr_ldap_set_option(p, NULL, APR_LDAP_OPT_TLS_CERT, (void *)cert, &result);
                ABTS_TRUE(tc, result->rc == LDAP_SUCCESS);
            }

        } while (1);

        apr_dir_close(thedir);
    }
    return 0;
}
示例#17
0
文件: testldap.c 项目: 0jpq0/kbengine
static void test_ldap_tls(abts_case *tc, void *data)
{
    apr_pool_t *pool = p;
    LDAP *ldap;
    apr_ldap_err_t *result = NULL;

    apr_ldap_init(pool, &ldap,
                  ldap_host, LDAP_PORT,
                  APR_LDAP_STARTTLS, &(result));

    ABTS_TRUE(tc, ldap != NULL);
    ABTS_PTR_NOTNULL(tc, result);

    if (result->rc == LDAP_SUCCESS) {
        add_ldap_certs(tc);

        test_ldap_connection(tc, ldap);
    }
}
示例#18
0
文件: teststr.c 项目: ohmann/checkapi
static void string_error(abts_case *tc, void *data)
{
     char buf[128], *rv;
     apr_status_t n;

     buf[0] = '\0';
     rv = apr_strerror(APR_ENOENT, buf, sizeof buf);
     ABTS_PTR_EQUAL(tc, buf, rv);
     ABTS_TRUE(tc, strlen(buf) > 0);

     rv = apr_strerror(APR_TIMEUP, buf, sizeof buf);
     ABTS_PTR_EQUAL(tc, buf, rv);
     ABTS_STR_EQUAL(tc, "The timeout specified has expired", buf);

     /* throw some randomish numbers at it to check for robustness */
     for (n = 1; n < 1000000; n *= 2) {
         apr_strerror(n, buf, sizeof buf);
     }
}
示例#19
0
文件: teststr.c 项目: ohmann/checkapi
static void snprintf_overflow(abts_case *tc, void *data)
{
    char buf[4];
    int rv;

    buf[2] = '4';
    buf[3] = '2';

    rv = apr_snprintf(buf, 2, "%s", "a");
    ABTS_INT_EQUAL(tc, 1, rv);

    rv = apr_snprintf(buf, 2, "%s", "abcd");
    ABTS_INT_EQUAL(tc, 1, rv);

    ABTS_STR_EQUAL(tc, "a", buf);

    /* Check the buffer really hasn't been overflowed. */
    ABTS_TRUE(tc, buf[2] == '4' && buf[3] == '2');
}
示例#20
0
文件: testldap.c 项目: 0jpq0/kbengine
static void test_ldap(abts_case *tc, void *data)
{
    apr_pool_t *pool = p;
    LDAP *ldap;
    apr_ldap_err_t *result = NULL;


    ABTS_ASSERT(tc, "failed to get host", ldap_host[0] != '\0');
    
    apr_ldap_init(pool, &ldap,
                  ldap_host, LDAP_PORT,
                  APR_LDAP_NONE, &(result));

    ABTS_TRUE(tc, ldap != NULL);
    ABTS_PTR_NOTNULL(tc, result);

    if (result->rc == LDAP_SUCCESS) {
        test_ldap_connection(tc, ldap);
    }
}
示例#21
0
static void pipe_consumer(toolbox_t *box)
{
    char ch;
    apr_status_t rv;
    apr_size_t nbytes;
    abts_case *tc = box->tc;
    apr_file_t *out = box->data;
    apr_uint32_t consumed = 0;

    do {
        rv = apr_thread_mutex_lock(box->mutex);
        ABTS_SUCCESS(rv);

        while (!pipe_count && !exiting) {
            rv = apr_thread_cond_wait(box->cond, box->mutex);
            ABTS_SUCCESS(rv);
        }

        if (!pipe_count && exiting) {
            rv = apr_thread_mutex_unlock(box->mutex);
            ABTS_SUCCESS(rv);
            break;
        }

        pipe_count--;
        consumed++;

        rv = apr_thread_mutex_unlock(box->mutex);
        ABTS_SUCCESS(rv);

        rv = apr_file_read_full(out, &ch, 1, &nbytes);
        ABTS_SUCCESS(rv);
        ABTS_SIZE_EQUAL(tc, 1, nbytes);
        ABTS_TRUE(tc, ch == '.');
    } while (1);

    /* naive fairness test - it would be good to introduce or solidify
     * a solid test to ensure one thread is not starved.
     * ABTS_INT_EQUAL(tc, 1, !!consumed);
     */
}
示例#22
0
文件: testshm.c 项目: 0jpq0/kbengine
static void test_named_remove(abts_case *tc, void *data)
{
    apr_status_t rv;
    apr_shm_t *shm, *shm2;

    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_shm_remove(SHARED_FILENAME, p);

    /* On platforms which acknowledge the removal of the shared resource,
     * ensure another of the same name may be created after removal;
     */
    if (rv == APR_SUCCESS)
    {
      rv = apr_shm_create(&shm2, SHARED_SIZE, SHARED_FILENAME, p);
      APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
      if (rv != APR_SUCCESS) {
          return;
      }
      ABTS_PTR_NOTNULL(tc, shm2);

      rv = apr_shm_destroy(shm2);
      APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
    }

    rv = apr_shm_destroy(shm);
    APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);

    /* Now ensure no named resource remains which we may attach to */
    rv = apr_shm_attach(&shm, SHARED_FILENAME, p);
    ABTS_TRUE(tc, rv != 0);
}
示例#23
0
文件: testrmm.c 项目: 0jpq0/kbengine
static void test_rmm(abts_case *tc, void *data)
{
    apr_status_t rv;
    apr_pool_t *pool;
    apr_shm_t *shm;
    apr_rmm_t *rmm;
    apr_size_t size, fragsize;
    apr_rmm_off_t *off, off2;
    int i;
    void *entity;

    rv = apr_pool_create(&pool, p);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    /* We're going to want 10 blocks of data from our target rmm. */
    size = SHARED_SIZE + apr_rmm_overhead_get(FRAG_COUNT + 1);
    rv = apr_shm_create(&shm, size, NULL, pool);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    if (rv != APR_SUCCESS)
        return;

    rv = apr_rmm_init(&rmm, NULL, apr_shm_baseaddr_get(shm), size, pool);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    if (rv != APR_SUCCESS)
        return;

    /* Creating each fragment of size fragsize */
    fragsize = SHARED_SIZE / FRAG_COUNT;
    off = apr_palloc(pool, FRAG_COUNT * sizeof(apr_rmm_off_t));
    for (i = 0; i < FRAG_COUNT; i++) {
        off[i] = apr_rmm_malloc(rmm, fragsize);
    }

    /* Checking for out of memory allocation */
    off2 = apr_rmm_malloc(rmm, FRAG_SIZE * FRAG_COUNT);
    ABTS_TRUE(tc, !off2);

    /* Checking each fragment for address alignment */
    for (i = 0; i < FRAG_COUNT; i++) {
        char *c = apr_rmm_addr_get(rmm, off[i]);
        apr_size_t sc = (apr_size_t)c;

        ABTS_TRUE(tc, !!off[i]);
        ABTS_TRUE(tc, !(sc & 7));
    }

    /* Setting each fragment to a unique value */
    for (i = 0; i < FRAG_COUNT; i++) {
        int j;
        char **c = apr_rmm_addr_get(rmm, off[i]);
        for (j = 0; j < FRAG_SIZE; j++, c++) {
            *c = apr_itoa(pool, i + j);
        }
    }

    /* Checking each fragment for its unique value */
    for (i = 0; i < FRAG_COUNT; i++) {
        int j;
        char **c = apr_rmm_addr_get(rmm, off[i]);
        for (j = 0; j < FRAG_SIZE; j++, c++) {
            char *d = apr_itoa(pool, i + j);
            ABTS_STR_EQUAL(tc, d, *c);
        }
    }

    /* Freeing each fragment */
    for (i = 0; i < FRAG_COUNT; i++) {
        rv = apr_rmm_free(rmm, off[i]);
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    }

    /* Creating one large segment */
    off[0] = apr_rmm_calloc(rmm, SHARED_SIZE);

    /* Setting large segment */
    for (i = 0; i < FRAG_COUNT * FRAG_SIZE; i++) {
        char **c = apr_rmm_addr_get(rmm, off[0]);
        c[i] = apr_itoa(pool, i);
    }

    /* Freeing large segment */
    rv = apr_rmm_free(rmm, off[0]);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    /* Creating each fragment of size fragsize */
    for (i = 0; i < FRAG_COUNT; i++) {
        off[i] = apr_rmm_malloc(rmm, fragsize);
    }

    /* Freeing each fragment backwards */
    for (i = FRAG_COUNT - 1; i >= 0; i--) {
        rv = apr_rmm_free(rmm, off[i]);
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    }

    /* Creating one large segment (again) */
    off[0] = apr_rmm_calloc(rmm, SHARED_SIZE);

    /* Freeing large segment */
    rv = apr_rmm_free(rmm, off[0]);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    /* Checking realloc */
    off[0] = apr_rmm_calloc(rmm, SHARED_SIZE - 100);
    off[1] = apr_rmm_calloc(rmm, 100);
    ABTS_TRUE(tc, !!off[0]);
    ABTS_TRUE(tc, !!off[1]);

    entity = apr_rmm_addr_get(rmm, off[1]);
    rv = apr_rmm_free(rmm, off[0]);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    {
        unsigned char *c = entity;

        /* Fill in the region; the first half with zereos, which will
         * likely catch the apr_rmm_realloc offset calculation bug by
         * making it think the old region was zero length. */
        for (i = 0; i < 100; i++) {
            c[i] = (i < 50) ? 0 : i;
        }
    }

    /* now we can realloc off[1] and get many more bytes */
    off[0] = apr_rmm_realloc(rmm, entity, SHARED_SIZE - 100);
    ABTS_TRUE(tc, !!off[0]);

    {
        unsigned char *c = apr_rmm_addr_get(rmm, off[0]);

        /* fill in the region */
        for (i = 0; i < 100; i++) {
            ABTS_TRUE(tc, c[i] == (i < 50 ? 0 : i));
        }
    }

    rv = apr_rmm_destroy(rmm);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    rv = apr_shm_destroy(shm);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    apr_pool_destroy(pool);
}