1 /*
2  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
3  *                         University Research and Technology
4  *                         Corporation.  All rights reserved.
5  * Copyright (c) 2004-2005 The University of Tennessee and The University
6  *                         of Tennessee Research Foundation.  All rights
7  *                         reserved.
8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
9  *                         University of Stuttgart.  All rights reserved.
10  * Copyright (c) 2004-2005 The Regents of the University of California.
11  *                         All rights reserved.
12  * Copyright (c) 2008-2014 Cisco Systems, Inc.  All rights reserved.
13  * Copyright (c) 2014-2015 Hewlett-Packard Development Company, LP.
14  *                         All rights reserved.
15  * Copyright (c) 2014-2015 Mellanox Technologies, Inc.
16  *                         All rights reserved.
17  * Copyright (c) 2014      Research Organization for Information Science
18  *                         and Technology (RIST). All rights reserved.
19  * $COPYRIGHT$
20  *
21  * Additional copyrights may follow
22  *
23  * $HEADER$
24  */
25 
26 #include "opal_config.h"
27 #include <stdint.h>
28 #include <string.h>
29 #include "support.h"
30 #include "opal/class/opal_object.h"
31 #include "opal/class/opal_hash_table.h"
32 #include "opal/runtime/opal.h"
33 #include "opal/constants.h"
34 
35 static FILE *error_out=NULL;
36 
37 char *num_keys[] = {
38     "0", "1234", "1234",
39     "0", "5678", "5678",
40     "1", "12450", "12450",
41     "1", "45623", "45623",
42     NULL
43 };
44 
45 
46 char *str_keys[] = {
47     "foo", "bar",
48     "2", "this cow jumped over the moon",
49     "this is another key", "this is another value",
50     "key key", "value value",
51     NULL
52 };
53 
54 
55 char *perm_keys[] = {
56     "abcdef", "abcdef",
57     "bcdefa", "bcdefa",
58     "cdefab", "cdefab",
59     "defabc", "defabc",
60     "efabcd", "efabcd",
61     "fabcde", "fabcde",
62     "badcfe", "badcfe",
63     "badcef", "badcef",
64     "abdcfe", "abdcfe",
65     "bcdaef", "bcdaef",
66     NULL
67 };
68 
69 #if 0
70 /*
71  * This data specifically knows about the April'2014 version of hash tables.
72  * It inserts some keys.
73  * It inserts some more with a capacity offset to generate collisions.
74  * Then it checks the table via traversal.
75  * Then... it removes a key and checks again (via traversal)
76  * and removes another key and re-checks.
77  */
78 static char* remove_keys[] = {
79     "1", "A", "2", "B", "4", "D", "6", "F", "10", "J", NULL, /* insert as-is: ...AB.D.F...J... */
80     "2", "b", "4", "d", "5", "e", "3", "c", NULL, /* insert with capacity-offset: ...ABbDdFec.J... */
81     "ABbDdFecJ",		/* traversal expectation */
82     "4", "ABbdeFcJ",		/* remove D (...ABbdeFc..J...) then expected traversal */
83     "2", "AbcdeFJ",		/* remove B (...AbcdeF...J...) then expected traversal */
84     NULL			/* end removals and expectations */
85 };
86 #endif
87 
88 typedef union {
89     opal_process_name_t uvalue;
90     void *vvalue;
91 } value_t;
92 
validate_table(opal_proc_table_t * table,char * keys[])93 static void validate_table(opal_proc_table_t *table, char *keys[])
94 {
95     int         j, ret;
96     value_t value;
97 
98     for ( j = 0; keys[j]; j += 3) {
99         opal_process_name_t key;
100         key.jobid = atoi(keys[j]);
101         key.vpid = atoi(keys[j+1]);
102         ret = opal_proc_table_get_value(table, key,
103                                         (void**) &value.uvalue);
104         if (OPAL_SUCCESS != ret) {
105             test_failure("opal_proc_table_get_value failed");
106         }
107         test_verify_str(keys[j+2], value.vvalue);
108     }
109 }
110 
111 #if 0
112 static void
113 validate_remove_traversal(opal_hash_table_t * table, const char * expected_chars)
114 {
115     /* all values are single-character strings */
116     /* expected_chars are those single characters as a string */
117     const int debug = 0;	/* turn this on if you want to see the details */
118     int rc, problems = 0;
119     const char * expected_scanner = expected_chars;
120     uint32_t key;
121     void * raw_value;
122     void * node;
123     if (debug) {
124 	fprintf(stderr, "debug: expecting '%s' capacity is %d\n",
125 		expected_chars, (int) table->ht_capacity);
126     }
127     for (rc = opal_hash_table_get_first_key_uint32(table, &key, &raw_value, &node);
128 	 OPAL_SUCCESS == rc;
129 	 rc = opal_hash_table_get_next_key_uint32(table, &key, &raw_value, node, &node)) {
130 	const char * value = (const char *) raw_value;
131 	char expected, actual;
132 	if (debug) {
133 	    fprintf(stderr, "key %d (probe at %d) value '%s' excpected_scanner '%s'\n",
134 		    key, (int) (key%table->ht_capacity), value, expected_scanner);
135 	}
136 	if (1 != strlen(value)) {
137 	    fprintf(stderr, "key %d's value '%s' is not a one-character string\n", key, value);
138 	    problems += 1;
139 	    continue;		/* might as well be completely noisy */
140 	}
141 	if ('\0' == *expected_scanner) {
142 	    fprintf(stderr, "Found key %d value '%s' but not expected!\n", key, value);
143 	    problems += 1;
144 	    continue;
145 	}
146 	expected = *expected_scanner++;
147 	actual = *value;
148 	if (actual != expected) {
149 	    fprintf(stderr, "Expected '%c' but got '%c'\n", expected, actual);
150 	    problems += 1;
151 	    continue;
152 	}
153     }
154     /* final checks */
155     if (OPAL_ERROR != rc) {
156 	fprintf(stderr, "table traversal did not end in OPAL_ERROR?!?\n");
157 	problems += 1;
158     }
159     if ('\0' != *expected_scanner) {
160 	fprintf(stderr, "Still expecting more key/values: '%s'\n", expected_scanner);
161 	problems += 1;
162     }
163 
164     /* resolution */
165     if (problems > 0) {
166 	fflush(stderr);
167 	test_failure("validate_remove_traversal");
168     } else {
169 	test_success();
170     }
171 }
172 #endif
173 
test_ptable(opal_proc_table_t * table)174 static void test_ptable(opal_proc_table_t *table)
175 {
176     int j;
177     char *n1, *n2;
178     char * v;
179     int rc;
180     opal_process_name_t key;
181     fprintf(error_out, "\nTesting integer keys...\n");
182     for ( j = 0; num_keys[j]; j += 3)
183     {
184         opal_process_name_t key;
185         key.jobid = atoi(num_keys[j]);
186         key.vpid = atoi(num_keys[j+1]);
187         opal_proc_table_set_value(table, key, num_keys[j+2]);
188     }
189     validate_table(table, num_keys);
190     rc = opal_proc_table_get_first_key(table, &key, (void **)&v, (void **)&n1, (void **)&n2);
191     if (OPAL_SUCCESS != rc) {
192         fprintf(error_out, "*** FAILED opal_proc_table_get_first_key ***\n");
193         return ;
194     }
195     for (j=0; num_keys[j]; j+=3) {
196         if (OPAL_SUCCESS != rc) {
197             fprintf(error_out, "*** FAILED opal_proc_table_get_next_key (%d) ***\n", j/3);
198         }
199 
200         if (key.jobid != (opal_jobid_t)atoi(num_keys[j]) ||
201             key.vpid != (opal_vpid_t)atoi(num_keys[j+1]) ||
202             0 != strcmp(num_keys[j+2], v)) {
203                 fprintf(error_out, "*** FAILED at %d, expected ((%s,%s),%s) got ((%d,%d),%s)\n", j/3,
204                         num_keys[j], num_keys[j+1], num_keys[j+2],
205                         key.jobid, key.vpid, v);
206         }
207 
208         rc = opal_proc_table_get_next_key(table, &key, (void **)&v, n1, (void **)&n1, n2, (void **)&n2);
209     }
210     if (OPAL_SUCCESS == rc) {
211         fprintf(error_out, "*** DID NOT FAIL last opal_proc_table_get_next_key %d\n", j/3);
212         return;
213     }
214 
215 
216 #if 0
217     /* remove all values for next test */
218     opal_proc_table_remove_all(table);
219     test_verify_int(0, opal_hash_table_get_size(table));
220 
221     fprintf(error_out, "\nTesting removal and traversal...\n");
222     j = 0;
223     char * str;
224     while (NULL != (str = remove_keys[j++])) {
225 	opal_hash_table_set_value_uint32(table, atoi(str), remove_keys[j++]);
226     }
227     while (NULL != (str = remove_keys[j++])) {
228 	/* generate collisions */
229 	opal_hash_table_set_value_uint32(table, atoi(str) + table->ht_capacity, remove_keys[j++]);
230     }
231     validate_remove_traversal(table, remove_keys[j++]);
232     while (NULL != (str = remove_keys[j++])) {
233 	opal_hash_table_remove_value_uint32(table, atoi(str));
234 	validate_remove_traversal(table, remove_keys[j++]);
235     }
236 
237     /* remove all values for next test */
238     opal_hash_table_remove_all(table);
239     test_verify_int(0, opal_hash_table_get_size(table));
240 #endif
241 
242     fprintf(error_out, "\n\n");
243 }
244 
245 
test_dynamic(void)246 static void test_dynamic(void)
247 {
248     opal_proc_table_t     *table;
249 
250     table = OBJ_NEW(opal_proc_table_t);
251     if ( NULL == table )
252     {
253         fprintf(error_out, "Error: Unable to create hash table.\n");
254         exit(-1);
255     }
256     fprintf(error_out, "Testing with dynamically created table...\n");
257     opal_proc_table_init(table, 2, 4);
258     test_ptable(table);
259 
260     OBJ_RELEASE(table);
261 }
262 
263 
test_static(void)264 static void test_static(void)
265 {
266     opal_proc_table_t     table;
267 
268     OBJ_CONSTRUCT(&table, opal_proc_table_t);
269     opal_proc_table_init(&table, 8, 128);
270 
271     fprintf(error_out, "Testing with statically created table...\n");
272     test_ptable(&table);
273 
274     OBJ_DESTRUCT(&table);
275 }
276 
277 
main(int argc,char ** argv)278 int main(int argc, char **argv)
279 {
280     int rc;
281 
282     test_init("opal_proc_table_t");
283 
284     rc = opal_init_util(&argc, &argv);
285     test_verify_int(OPAL_SUCCESS, rc);
286     if (OPAL_SUCCESS != rc) {
287         test_finalize();
288         exit(1);
289     }
290 
291 #ifdef STANDALONE
292     error_out = stderr;
293 #else
294     error_out = fopen( "./opal_proc_table_test_out.txt", "w" );
295     if( error_out == NULL ) error_out = stderr;
296 #endif
297 
298     test_dynamic();
299     test_static();
300 #ifndef STANDALONE
301     fclose( error_out );
302 #endif
303 
304     opal_finalize_util ();
305 
306     return test_finalize();
307 }
308