/* test what happens when we run out of arenas */

#include <unistd.h>
#include <my_assert.h>

#ifndef USE_TLS
#error USE_TLS must be set for this test
#endif

int __dfwmalloc_get_max_arenas (void);

static int log_count = 0;

#define my_assert(x)       (void) (!(x) && (write (2, #x, strlen (#x)), write (2, "\n", 1), (*((int *) ~((uintptr_t) 0)) = -1)))

void my_log (void *dummy, const char *msg, int len)
{
    const char *s = "DFWMALLOC: out of arenas";
    int r;
    (void) dummy;
    r = write (2, msg, len);
    r += write (2, "\n", 1);
    (void) r;
    my_assert (len == (int) strlen (s));
    my_assert (!strncmp (s, msg, len));
    my_assert (!log_count);
    log_count++;
}

void entry (void)
{
    struct dfwmalloc **dfw;
    char **p;
    int i;
    int total = 0;

/* don't try this test if it is going to run out of pages: */
    if (__dfwmalloc_get_max_arenas () > 4096) {
        printf ("%d arenas is too big -- skipping test\n", (int) __dfwmalloc_get_max_arenas ());
        return;
    }

    dfwmalloc_set_log (my_log, NULL);

    dfw = (struct dfwmalloc **) malloc (sizeof (struct dfwmalloc *) * __dfwmalloc_get_max_arenas ());
    p = (char **) malloc (sizeof (char *) * __dfwmalloc_get_max_arenas ());

    for (i = 0; i < __dfwmalloc_get_max_arenas (); i++) {
        dfw[i] = dfwmalloc_new ();
        if (!dfw[i]) {
            printf ("\nerrno=%d total=%d\n", errno, total);
/* can't abort here because it generates huge core files. */
            if (errno != ENOMEM) {
                printf ("error 1\n");
                exit (1);
            }
            if (total <= 30) {
                printf ("error 2\n");
                exit (1);
            }
            printf ("log_count=%d\n", log_count);
            if (log_count != 1) {
                printf ("error 3\n");
                exit (1);
            }
            printf ("test-arena.c success\n");
            exit (0);
        }
        total++;
        p[i] = (char *) dfwmalloc_malloc (dfw[i], 32);
#if 0
        printf ("%d: %p, ", i, p[i]);
        fflush (stdout);
#endif
    }

    exit (1);
}

