1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 /*=========================================================================
19  *
20  *  Portions of this file are subject to the VTK Toolkit Version 3 copyright.
21  *
22  *  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
23  *
24  *  For complete copyright, license and disclaimer of warranty information
25  *  please refer to the NOTICE file at the top of the ITK source tree.
26  *
27  *=========================================================================*/
28 
29 #include "itkTestDriverIncludeRequiredIOFactories.h"
30 
31 
32 /* Select the environment variable holding the shared library runtime
33    search path for this platform.  */
34 
35 /* Linux */
36 #if defined(__linux) || (defined(__FreeBSD__)||defined(__DragonFly__)) || defined(__OpenBSD__)
37 # define ITK_TEST_DRIVER_LDPATH "LD_LIBRARY_PATH"
38 # define ITK_TEST_DRIVER_LDPATH64 ITK_TEST_DRIVER_LDPATH
39 
40 /* OSX */
41 #elif defined(__APPLE__)
42 # define ITK_TEST_DRIVER_LDPATH "DYLD_LIBRARY_PATH"
43 # define ITK_TEST_DRIVER_LDPATH64 ITK_TEST_DRIVER_LDPATH
44 
45 /* AIX */
46 #elif defined(_AIX)
47 # define ITK_TEST_DRIVER_LDPATH "LIBPATH"
48 # define ITK_TEST_DRIVER_LDPATH64 ITK_TEST_DRIVER_LDPATH
49 
50 /* SUN */
51 #elif defined(__sun)
52 #  define ITK_TEST_DRIVER_LDPATH "LD_LIBRARY_PATH"
53 #  define ITK_TEST_DRIVER_LDPATH64 "LD_LIBRARY_PATH_64"
54 
55 /* HP-UX */
56 #elif defined(__hpux)
57 #  define ITK_TEST_DRIVER_LDPATH "SHLIB_PATH"
58 #  define ITK_TEST_DRIVER_LDPATH64 "LD_LIBRARY_PATH"
59 
60 /* SGI MIPS */
61 #elif defined(__sgi) && defined(_MIPS_SIM)
62 # if _MIPS_SIM == _ABIO32
63 #  define ITK_TEST_DRIVER_LDPATH "LD_LIBRARY_PATH"
64 # elif _MIPS_SIM == _ABIN32
65 #  define ITK_TEST_DRIVER_LDPATH "LD_LIBRARYN32_PATH"
66 # endif
67 #  define ITK_TEST_DRIVER_LDPATH64 "LD_LIBRARY64_PATH"
68 
69 /* Cygwin */
70 #elif defined(__CYGWIN__)
71 # define ITK_TEST_DRIVER_LDPATH "PATH"
72 # define ITK_TEST_DRIVER_LDPATH64 ITK_TEST_DRIVER_LDPATH
73 
74 /* Windows */
75 #elif defined(_WIN32)
76 # define ITK_TEST_DRIVER_LDPATH "PATH"
77 # define ITK_TEST_DRIVER_LDPATH64 ITK_TEST_DRIVER_LDPATH
78 
79 /* Guess on this unknown system.  */
80 #else
81 # define ITK_TEST_DRIVER_LDPATH "LD_LIBRARY_PATH"
82 # define ITK_TEST_DRIVER_LDPATH64 ITK_TEST_DRIVER_LDPATH
83 #endif
84 
85 #if defined(_WIN32) && !defined(__CYGWIN__)
86 # define ITK_TEST_DRIVER_PATH_SEP ';'
87 # define ITK_TEST_DRIVER_PATH_SLASH '\\'
88 #else
89 # define ITK_TEST_DRIVER_PATH_SEP ':'
90 # define ITK_TEST_DRIVER_PATH_SLASH '/'
91 #endif
92 
93 
AddEntriesBeforeLibraryPath(const ArgumentsList & args)94 void AddEntriesBeforeLibraryPath( const ArgumentsList & args )
95 {
96   unsigned int i = 0;
97 
98   while( i < args.size() )
99     {
100     std::string libpath = ITK_TEST_DRIVER_LDPATH;
101     libpath += "=";
102     libpath += args[i];
103     char *oldenv = getenv(ITK_TEST_DRIVER_LDPATH);
104     if ( oldenv )
105       {
106       libpath += ITK_TEST_DRIVER_PATH_SEP;
107       libpath += oldenv;
108       }
109     itksys::SystemTools::PutEnv( libpath.c_str() );
110     // on some 64 bit systems, LD_LIBRARY_PATH_64 is used before
111     // LD_LIBRARY_PATH if it is set. It can lead the test to load
112     // the system library instead of the expected one, so this
113     // var must also be set
114     if ( std::string(ITK_TEST_DRIVER_LDPATH) != ITK_TEST_DRIVER_LDPATH64 )
115       {
116       std::string libpath64 = ITK_TEST_DRIVER_LDPATH64;
117       libpath64 += "=";
118       libpath64 += args[i];
119       char *oldenv64 = getenv(ITK_TEST_DRIVER_LDPATH64);
120       if ( oldenv64 )
121         {
122         libpath64 += ITK_TEST_DRIVER_PATH_SEP;
123         libpath64 += oldenv64;
124         }
125       itksys::SystemTools::PutEnv( libpath64.c_str() );
126       }
127 
128     i++;
129     }
130 }
131 
132 
AddEntriesBeforeEnvironment(const ArgumentsList & args)133 void AddEntriesBeforeEnvironment( const ArgumentsList & args )
134 {
135   unsigned int i = 0;
136 
137   while( i < args.size() )
138     {
139     std::string env = args[i];
140     env += "=";
141     env += args[i+1];
142     char *oldenv = getenv( args[i] );
143     if ( oldenv )
144       {
145       env += ITK_TEST_DRIVER_PATH_SEP;
146       env += oldenv;
147       }
148     itksys::SystemTools::PutEnv( env.c_str() );
149 
150     i += 2;
151     }
152 }
153 
154 
AddEntriesBeforeEnvironmentWithSeparator(const ArgumentsList & args)155 void AddEntriesBeforeEnvironmentWithSeparator( const ArgumentsList & args )
156 {
157   unsigned int i = 0;
158 
159   while( i < args.size() )
160     {
161     std::string env = args[i];
162     env += "=";
163     env += args[i+1];
164     char *oldenv = getenv( args[i] );
165     if ( oldenv )
166       {
167       env += args[i+2];
168       env += oldenv;
169       }
170     itksys::SystemTools::PutEnv( env.c_str() );
171 
172     i += 3;
173     }
174 }
175 
176 
TestDriverInvokeProcess(const ArgumentsList & args)177 int TestDriverInvokeProcess( const ArgumentsList & args )
178 {
179   // a nullptr is required at the end of the table
180   auto ** argv = new char *[args.size() + 1];
181   for ( unsigned int i = 0; i < args.size(); i++ )
182     {
183     argv[i] = args[i];
184     }
185   argv[args.size()] = nullptr;
186 
187   itksysProcess *process = itksysProcess_New();
188   itksysProcess_SetCommand(process, argv);
189   itksysProcess_SetPipeShared(process, itksysProcess_Pipe_STDOUT, true);
190   itksysProcess_SetPipeShared(process, itksysProcess_Pipe_STDERR, true);
191   itksysProcess_Execute(process);
192   itksysProcess_WaitForExit(process, nullptr);
193 
194   delete[] argv;
195 
196   int state = itksysProcess_GetState(process);
197   switch( state )
198     {
199     case itksysProcess_State_Error:
200       {
201       std::cerr << "itkTestDriver: Process error: " << itksysProcess_GetErrorString(process) << std::endl;
202       itksysProcess_Delete(process);
203       return 1;
204       }
205     case itksysProcess_State_Exception:
206       {
207       std::cerr << "itkTestDriver: Process exception: " << itksysProcess_GetExceptionString(process) << std::endl;
208       itksysProcess_Delete(process);
209       return 1;
210       }
211     case itksysProcess_State_Executing:
212       {
213       // this is not a possible state after itksysProcess_WaitForExit
214       std::cerr << "itkTestDriver: Internal error: process can't be in Executing State." << std::endl;
215       itksysProcess_Delete(process);
216       return 1;
217       }
218     case itksysProcess_State_Exited:
219       {
220       // this is the normal case - it is treated later
221       break;
222       }
223     case itksysProcess_State_Expired:
224       {
225       // this is not a possible state after itksysProcess_WaitForExit
226       std::cerr << "itkTestDriver: Internal error: process can't be in Expired State." << std::endl;
227       itksysProcess_Delete(process);
228       return 1;
229       }
230     case itksysProcess_State_Killed:
231       {
232       std::cerr << "itkTestDriver: The process has been killed." << std::endl;
233       itksysProcess_Delete(process);
234       return 1;
235       }
236     case itksysProcess_State_Disowned:
237       {
238       std::cerr << "itkTestDriver: Process disowned." << std::endl;
239       itksysProcess_Delete(process);
240       return 1;
241       }
242     default:
243       {
244       // this is not a possible state after itksysProcess_WaitForExit
245       std::cerr << "itkTestDriver: Internal error: unknown State." << std::endl;
246       itksysProcess_Delete(process);
247       return 1;
248       }
249     }
250 
251   int retCode = itksysProcess_GetExitValue(process);
252   if ( retCode != 0 )
253     {
254     std::cerr << "itkTestDriver: Process exited with return value: " << retCode << std::endl;
255     }
256   itksysProcess_Delete(process);
257 return retCode;
258 }
259 
260 
main(int ac,char * av[])261 int main(int ac, char *av[])
262 {
263   try
264     {
265     RegisterRequiredFactories();
266     }
267   catch( itk::ExceptionObject & err )
268     {
269     err.Print(std::cerr);
270     return EXIT_FAILURE;
271     }
272 
273 
274   ProcessedOutputType po;
275 
276   int result = ProcessArguments(&ac, &av, &po);
277 
278   if( result )
279     {
280     // There was a problem parsing the arguments, so usage has already
281     // been printed, just return
282     return 1;
283     }
284 
285   if ( po.externalProcessMustBeCalled && po.args.empty() )
286     {
287     usage();
288     return 1;
289     }
290 
291   if ( !po.externalProcessMustBeCalled && !po.args.empty() )
292     {
293     usage();
294     return 1;
295     }
296 
297 
298   if ( !result && po.externalProcessMustBeCalled )
299     {
300     AddEntriesBeforeLibraryPath( po.add_before_libpath );
301 
302     AddEntriesBeforeEnvironment( po.add_before_env );
303 
304     AddEntriesBeforeEnvironmentWithSeparator( po.add_before_env_with_sep );
305 
306     result = TestDriverInvokeProcess( po.args );
307     }
308 
309   if (result == 0)
310     {
311     #include "itkTestDriverBeforeTest.inc"
312     #include "itkTestDriverAfterTest.inc"
313     }
314 
315   return result;
316 }
317