/*
 * Copyright (C) by Argonne National Laboratory
 *     See COPYRIGHT in top-level directory
 */

/* Test of info that makes use of the extended handles, including
   inserts and deletes */
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include "mpitest.h"
#include "mpitestconf.h"
#ifdef HAVE_STRING_H
#include <string.h>
#endif

#ifndef MAX_INFOS
#define MAX_INFOS 4000
#endif
#define MAX_ERRORS 10
#define info_list 16
/* #define DBG  */

#ifdef DEBUG
#define DBGPRINTF(a) printf a; fflush(stdout)
#else
#define DBGPRINTF(a)
#endif

int main(int argc, char *argv[])
{
    MPI_Info infos[MAX_INFOS];
    char key[64], value[64];
    int errs = 0;
    int i, j;

    MTest_Init(&argc, &argv);

    /* We create max_info items, then delete the middle third of them,
     * then recreate them, then check them, then
     * delete them all.  This checks that the MPICH algorithm for
     * handling large numbers of items works correctly; other MPI
     * implementations should also be able to handle this */

    /* Create them all */
    for (i = 0; i < MAX_INFOS; i++) {
        MPI_Info_create(&infos[i]);
        DBGPRINTF(("Info handle is %x\n", infos[i]));
        for (j = 0; j < info_list; j++) {
            sprintf(key, "key%d-%d", i, j);
            sprintf(value, "value%d-%d", i, j);
            DBGPRINTF(("Creating key/value %s=%s\n", key, value));
            MPI_Info_set(infos[i], key, value);
        }
#ifdef DBG
        {
            int nkeys;
            MPI_Info_get_nkeys(infos[0], &nkeys);
            if (nkeys != info_list) {
                printf("infos[0] changed at %d info\n", i);
            }
        }
#endif
    }

    /* Delete the middle set */
    for (i = MAX_INFOS / 3; i < (2 * MAX_INFOS / 3); i++) {
        MPI_Info_free(&infos[i]);
    }

    /* Recreate the middle set */
    for (i = MAX_INFOS / 3; i < (2 * MAX_INFOS / 3); i++) {
        MPI_Info_create(&infos[i]);
        DBGPRINTF(("Info handle is %x\n", infos[i]));
        for (j = 0; j < info_list; j++) {
            sprintf(key, "key%d-%d", i, j);
            sprintf(value, "value%d-%d", i, j);
            DBGPRINTF(("Creating key/value %s=%s\n", key, value));
            MPI_Info_set(infos[i], key, value);
        }
    }

    /* Now, check that they are still valid */
    for (i = 0; i < MAX_INFOS; i++) {
        int nkeys;
        /*printf("info = %x\n", infos[i]);
         * print_handle(infos[i]); printf("\n"); */
        MPI_Info_get_nkeys(infos[i], &nkeys);
        if (nkeys != info_list) {
            errs++;
            if (errs < MAX_ERRORS) {
                printf("Wrong number of keys for info %d; got %d, should be %d\n",
                       i, nkeys, info_list);
            }
        }
        for (j = 0; j < nkeys; j++) {
            char keystr[64];
            char valstr[64];
            int flag;
            MPI_Info_get_nthkey(infos[i], j, key);
            sprintf(keystr, "key%d-%d", i, j);
            if (strcmp(keystr, key) != 0) {
                errs++;
                if (errs < MAX_ERRORS) {
                    printf("Wrong key for info %d; got %s expected %s\n", i, key, keystr);
                }
                continue;
            }
            MPI_Info_get(infos[i], key, 64, value, &flag);
            if (!flag) {
                errs++;
                if (errs < MAX_ERRORS) {
                    printf("Get failed to return value for info %d\n", i);
                }
                continue;
            }
            sprintf(valstr, "value%d-%d", i, j);
            if (strcmp(valstr, value) != 0) {
                errs++;
                if (errs < MAX_ERRORS) {
                    printf("Wrong value for info %d; got %s expected %s\n", i, value, valstr);
                }
            }
        }
    }
    for (i = 0; i < MAX_INFOS; i++) {
        MPI_Info_free(&infos[i]);
    }

    MTest_Finalize(errs);
    return MTestReturnValue(errs);
}
