1
1
openmpi/test/class/opal_proc_table.c
Ralph Castain 780c93ee57 Per the PR and discussion on today's telecon, extend the process name definition as a two-field struct of uint32_t's down to the OPAL layer. This resolves issues created by prior commits that impacted both heterogeneous and SPARC support. This also simplifies the OMPI code base by removing the need for frequent memcpy's when transitioning between the OMPI/ORTE layers and OPAL.
We recognize that this means other users of OPAL will need to "wrap" the opal_process_name_t if they desire to abstract it in some fashion. This is regrettable, and we are looking at possible alternatives that might mitigate that requirement. Meantime, however, we have to put the needs of the OMPI community first, and are taking this step to restore hetero and SPARC support.
2014-11-11 17:00:42 -08:00

308 строки
8.9 KiB
C

/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2008-2010 Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2014-2015 Hewlett-Packard Development Company, LP.
* All rights reserved.
* Copyright (c) 2014-2015 Mellanox Technologies, Inc.
* All rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <string.h>
#include "support.h"
#include "opal/class/opal_object.h"
#include "opal/class/opal_hash_table.h"
#include "opal/runtime/opal.h"
#include "opal/constants.h"
static FILE *error_out=NULL;
char *num_keys[] = {
"0", "1234", "1234",
"0", "5678", "5678",
"1", "12450", "12450",
"1", "45623", "45623",
NULL
};
char *str_keys[] = {
"foo", "bar",
"2", "this cow jumped over the moon",
"this is another key", "this is another value",
"key key", "value value",
NULL
};
char *perm_keys[] = {
"abcdef", "abcdef",
"bcdefa", "bcdefa",
"cdefab", "cdefab",
"defabc", "defabc",
"efabcd", "efabcd",
"fabcde", "fabcde",
"badcfe", "badcfe",
"badcef", "badcef",
"abdcfe", "abdcfe",
"bcdaef", "bcdaef",
NULL
};
/*
* This data specifically knows about the April'2014 version of hash tables.
* It inserts some keys.
* It inserts some more with a capacity offset to generate collisions.
* Then it checks the table via traversal.
* Then... it removes a key and checks again (via traversal)
* and removes another key and re-checks.
*/
static char* remove_keys[] = {
"1", "A", "2", "B", "4", "D", "6", "F", "10", "J", NULL, /* insert as-is: ...AB.D.F...J... */
"2", "b", "4", "d", "5", "e", "3", "c", NULL, /* insert with capacity-offset: ...ABbDdFec.J... */
"ABbDdFecJ", /* traversal expectation */
"4", "ABbdeFcJ", /* remove D (...ABbdeFc..J...) then expected traversal */
"2", "AbcdeFJ", /* remove B (...AbcdeF...J...) then expected traversal */
NULL /* end removals and expectations */
};
typedef union {
opal_process_name_t uvalue;
void *vvalue;
} value_t;
static void validate_table(opal_proc_table_t *table, char *keys[])
{
int j, ret;
value_t value;
for ( j = 0; keys[j]; j += 3) {
opal_process_name_t key;
key.jobid = atoi(keys[j]);
key.vpid = atoi(keys[j+1]);
ret = opal_proc_table_get_value(table, key,
(void**) &value.uvalue);
if (OPAL_SUCCESS != ret) {
test_failure("opal_proc_table_get_value failed");
}
test_verify_str(keys[j+2], value.vvalue);
}
}
#if 0
static void
validate_remove_traversal(opal_hash_table_t * table, const char * expected_chars)
{
/* all values are single-character strings */
/* expected_chars are those single characters as a string */
const int debug = 0; /* turn this on if you want to see the details */
int rc, problems = 0;
const char * expected_scanner = expected_chars;
uint32_t key;
void * raw_value;
void * node;
if (debug) {
fprintf(stderr, "debug: expecting '%s' capacity is %d\n",
expected_chars, (int) table->ht_capacity);
}
for (rc = opal_hash_table_get_first_key_uint32(table, &key, &raw_value, &node);
OPAL_SUCCESS == rc;
rc = opal_hash_table_get_next_key_uint32(table, &key, &raw_value, node, &node)) {
const char * value = (const char *) raw_value;
char expected, actual;
if (debug) {
fprintf(stderr, "key %d (probe at %d) value '%s' excpected_scanner '%s'\n",
key, (int) (key%table->ht_capacity), value, expected_scanner);
}
if (1 != strlen(value)) {
fprintf(stderr, "key %d's value '%s' is not a one-character string\n", key, value);
problems += 1;
continue; /* might as well be completely noisy */
}
if ('\0' == *expected_scanner) {
fprintf(stderr, "Found key %d value '%s' but not expected!\n", key, value);
problems += 1;
continue;
}
expected = *expected_scanner++;
actual = *value;
if (actual != expected) {
fprintf(stderr, "Expected '%c' but got '%c'\n", expected, actual);
problems += 1;
continue;
}
}
/* final checks */
if (OPAL_ERROR != rc) {
fprintf(stderr, "table traversal did not end in OPAL_ERROR?!?\n");
problems += 1;
}
if ('\0' != *expected_scanner) {
fprintf(stderr, "Still expecting more key/values: '%s'\n", expected_scanner);
problems += 1;
}
/* resolution */
if (problems > 0) {
fflush(stderr);
test_failure("validate_remove_traversal");
} else {
test_success();
}
}
#endif
static void test_ptable(opal_proc_table_t *table)
{
int j;
char *n1, *n2;
char * v;
int rc;
opal_process_name_t key;
fprintf(error_out, "\nTesting integer keys...\n");
for ( j = 0; num_keys[j]; j += 3)
{
opal_process_name_t key;
key.jobid = atoi(num_keys[j]);
key.vpid = atoi(num_keys[j+1]);
opal_proc_table_set_value(table, key, num_keys[j+2]);
}
validate_table(table, num_keys);
rc = opal_proc_table_get_first_key(table, &key, (void **)&v, (void **)&n1, (void **)&n2);
if (OPAL_SUCCESS != rc) {
fprintf(error_out, "*** FAILED opal_proc_table_get_first_key ***\n");
return ;
}
for (j=0; num_keys[j]; j+=3) {
if (OPAL_SUCCESS != rc) {
fprintf(error_out, "*** FAILED opal_proc_table_get_next_key (%d) ***\n", j/3);
}
if (key.jobid != atoi(num_keys[j]) ||
key.vpid != atoi(num_keys[j+1]) ||
0 != strcmp(num_keys[j+2], v)) {
fprintf(error_out, "*** FAILED at %d, expected ((%s,%s),%s) got ((%d,%d),%s)\n", j/3,
num_keys[j], num_keys[j+1], num_keys[j+2],
key.jobid, key.vpid, v);
}
rc = opal_proc_table_get_next_key(table, &key, (void **)&v, n1, (void **)&n1, n2, (void **)&n2);
}
if (OPAL_SUCCESS == rc) {
fprintf(error_out, "*** DID NOT FAIL last opal_proc_table_get_next_key %d\n", j/3);
return;
}
#if 0
/* remove all values for next test */
opal_proc_table_remove_all(table);
test_verify_int(0, opal_hash_table_get_size(table));
fprintf(error_out, "\nTesting removal and traversal...\n");
j = 0;
char * str;
while (NULL != (str = remove_keys[j++])) {
opal_hash_table_set_value_uint32(table, atoi(str), remove_keys[j++]);
}
while (NULL != (str = remove_keys[j++])) {
/* generate collisions */
opal_hash_table_set_value_uint32(table, atoi(str) + table->ht_capacity, remove_keys[j++]);
}
validate_remove_traversal(table, remove_keys[j++]);
while (NULL != (str = remove_keys[j++])) {
opal_hash_table_remove_value_uint32(table, atoi(str));
validate_remove_traversal(table, remove_keys[j++]);
}
/* remove all values for next test */
opal_hash_table_remove_all(table);
test_verify_int(0, opal_hash_table_get_size(table));
#endif
fprintf(error_out, "\n\n");
}
static void test_dynamic(void)
{
opal_proc_table_t *table;
table = OBJ_NEW(opal_proc_table_t);
if ( NULL == table )
{
fprintf(error_out, "Error: Unable to create hash table.\n");
exit(-1);
}
fprintf(error_out, "Testing with dynamically created table...\n");
opal_proc_table_init(table, 2, 4);
test_ptable(table);
OBJ_RELEASE(table);
}
static void test_static(void)
{
opal_proc_table_t table;
OBJ_CONSTRUCT(&table, opal_proc_table_t);
opal_proc_table_init(&table, 8, 128);
fprintf(error_out, "Testing with statically created table...\n");
test_ptable(&table);
OBJ_DESTRUCT(&table);
}
int main(int argc, char **argv)
{
int rc;
test_init("opal_proc_table_t");
rc = opal_init(&argc, &argv);
test_verify_int(OPAL_SUCCESS, rc);
if (OPAL_SUCCESS != rc) {
test_finalize();
exit(1);
}
#ifdef STANDALONE
error_out = stderr;
#else
error_out = fopen( "./opal_proc_table_test_out.txt", "w" );
if( error_out == NULL ) error_out = stderr;
#endif
test_dynamic();
test_static();
#ifndef STANDALONE
fclose( error_out );
#endif
opal_finalize();
return test_finalize();
}