1 /*
2  * Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana
3  *                         University Research and Technology
4  *                         Corporation.  All rights reserved.
5  * Copyright (c) 2004-2011 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) 2006-2013 Los Alamos National Security, LLC.
13  *                         All rights reserved.
14  * Copyright (c) 2009-2012 Cisco Systems, Inc.  All rights reserved.
15  * Copyright (c) 2011      Oak Ridge National Labs.  All rights reserved.
16  * Copyright (c) 2013-2019 Intel, Inc.  All rights reserved.
17  * Copyright (c) 2015      Research Organization for Information Science
18  *                         and Technology (RIST). All rights reserved.
19  * Copyright (c) 2015      Mellanox Technologies, Inc.
20  *                         All rights reserved.
21  * $COPYRIGHT$
22  *
23  * Additional copyrights may follow
24  *
25  * $HEADER$
26  *
27  */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 
33 #include "src/util/pmix_environ.h"
34 #include "src/util/output.h"
35 
36 #include "server_callbacks.h"
37 #include "utils.h"
38 #include "src/include/pmix_globals.h"
39 
40 bool spawn_wait = false;
41 
main(int argc,char ** argv)42 int main(int argc, char **argv)
43 {
44     char **client_env=NULL;
45     char **client_argv=NULL;
46     int rc;
47     struct stat stat_buf;
48     struct timeval tv;
49     double test_start;
50     test_params params;
51     INIT_TEST_PARAMS(params);
52     int test_fail = 0;
53     char *tmp;
54     int ns_nprocs;
55 
56     gettimeofday(&tv, NULL);
57     test_start = tv.tv_sec + 1E-6*tv.tv_usec;
58 
59     /* smoke test */
60     if (PMIX_SUCCESS != 0) {
61         TEST_ERROR(("ERROR IN COMPUTING CONSTANTS: PMIX_SUCCESS = %d", PMIX_SUCCESS));
62         exit(1);
63     }
64 
65     TEST_VERBOSE(("Testing version %s", PMIx_Get_version()));
66 
67     parse_cmd(argc, argv, &params);
68     TEST_VERBOSE(("Start PMIx_lite smoke test (timeout is %d)", params.timeout));
69 
70     /* verify executable */
71     if( 0 > ( rc = stat(params.binary, &stat_buf) ) ){
72         TEST_ERROR(("Cannot stat() executable \"%s\": %d: %s", params.binary, errno, strerror(errno)));
73         FREE_TEST_PARAMS(params);
74         return 0;
75     } else if( !S_ISREG(stat_buf.st_mode) ){
76         TEST_ERROR(("Client executable \"%s\": is not a regular file", params.binary));
77         FREE_TEST_PARAMS(params);
78         return 0;
79     }else if( !(stat_buf.st_mode & S_IXUSR) ){
80         TEST_ERROR(("Client executable \"%s\": has no executable flag", params.binary));
81         FREE_TEST_PARAMS(params);
82         return 0;
83     }
84 
85     /* setup the server library */
86     pmix_info_t info[1];
87     (void)strncpy(info[0].key, PMIX_SOCKET_MODE, PMIX_MAX_KEYLEN);
88     info[0].value.type = PMIX_UINT32;
89     info[0].value.data.uint32 = 0666;
90 
91     if (PMIX_SUCCESS != (rc = PMIx_server_init(&mymodule, info, 1))) {
92         TEST_ERROR(("Init failed with error %d", rc));
93         FREE_TEST_PARAMS(params);
94         return rc;
95     }
96     /* register the errhandler */
97     PMIx_Register_event_handler(NULL, 0, NULL, 0,
98                                 errhandler, errhandler_reg_callbk, NULL);
99 
100     cli_init(params.nprocs);
101 
102     /* set common argv and env */
103     client_env = pmix_argv_copy(environ);
104     set_client_argv(&params, &client_argv);
105 
106     tmp = pmix_argv_join(client_argv, ' ');
107     TEST_VERBOSE(("Executing test: %s", tmp));
108     free(tmp);
109 
110     int launched = 0;
111     /* set namespaces and fork clients */
112     if (NULL == params.ns_dist) {
113         /* we have a single namespace for all clients */
114         ns_nprocs = params.nprocs;
115         rc = launch_clients(ns_nprocs, params.binary, &client_env, &client_argv);
116         if (PMIX_SUCCESS != rc) {
117             FREE_TEST_PARAMS(params);
118             return rc;
119         }
120         launched += ns_nprocs;
121     } else {
122         char *pch;
123         pch = strtok(params.ns_dist, ":");
124         while (NULL != pch) {
125             ns_nprocs = (int)strtol(pch, NULL, 10);
126             if (params.nprocs < (uint32_t)(launched+ns_nprocs)) {
127                 TEST_ERROR(("Total number of processes doesn't correspond number specified by ns_dist parameter."));
128                 FREE_TEST_PARAMS(params);
129                 return PMIX_ERROR;
130             }
131             if (0 < ns_nprocs) {
132                 rc = launch_clients(ns_nprocs, params.binary, &client_env, &client_argv);
133                 if (PMIX_SUCCESS != rc) {
134                     FREE_TEST_PARAMS(params);
135                     return rc;
136                 }
137             }
138             pch = strtok (NULL, ":");
139             launched += ns_nprocs;
140         }
141     }
142     if (params.nprocs != (uint32_t)launched) {
143         TEST_ERROR(("Total number of processes doesn't correspond number specified by ns_dist parameter."));
144         cli_kill_all();
145         test_fail = 1;
146     }
147 
148     /* hang around until the client(s) finalize */
149     while (!test_terminated()) {
150         // To avoid test hang we want to interrupt the loop each 0.1s
151         double test_current;
152 
153         // check if we exceed the max time
154         gettimeofday(&tv, NULL);
155         test_current = tv.tv_sec + 1E-6*tv.tv_usec;
156         if( (test_current - test_start) > params.timeout ){
157             break;
158         }
159         cli_wait_all(0);
160     }
161 
162     if( !test_terminated() ){
163         TEST_ERROR(("Test exited by a timeout!"));
164         cli_kill_all();
165         test_fail = 1;
166     }
167 
168     if( test_abort ){
169         TEST_ERROR(("Test was aborted!"));
170         /* do not simply kill the clients as that generates
171          * event notifications which these tests then print
172          * out, flooding the log */
173       //  cli_kill_all();
174         test_fail = 1;
175     }
176 
177     if (0 != params.test_spawn) {
178         PMIX_WAIT_FOR_COMPLETION(spawn_wait);
179     }
180 
181     pmix_argv_free(client_argv);
182     pmix_argv_free(client_env);
183 
184     /* deregister the errhandler */
185     PMIx_Deregister_event_handler(0, op_callbk, NULL);
186 
187     cli_wait_all(1.0);
188 
189     /* finalize the server library */
190     if (PMIX_SUCCESS != (rc = PMIx_server_finalize())) {
191         TEST_ERROR(("Finalize failed with error %d", rc));
192     }
193 
194     FREE_TEST_PARAMS(params);
195 
196     if (0 == test_fail) {
197         TEST_OUTPUT(("Test finished OK!"));
198     }
199 
200     return test_fail;
201 }
202