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