]> git.saurik.com Git - wxWidgets.git/blob - utils/execmon/execmon.cpp
a0c7adf53ae8fc6390225d306de2fe4721ad44a8
[wxWidgets.git] / utils / execmon / execmon.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: execmon.cpp
3 // Purpose: A simple execution monitor to test if wx samples crash at startup or not
4 // Author: Francesco Montorsi
5 // Modified by:
6 // Created: 25/3/09
7 // RCS-ID: $Id$
8 // Copyright: (c) 2009 Francesco Montorsi
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #endif // WX_PRECOMP
29
30 #include "wx/cmdline.h"
31 #include "wx/vector.h"
32 #include "wx/process.h"
33 #include "wx/sstream.h"
34 #include "wx/utils.h"
35 #include "wx/filename.h"
36
37 // ============================================================================
38 // implementation
39 // ============================================================================
40
41 // ----------------------------------------------------------------------------
42 // utility classes
43 // ----------------------------------------------------------------------------
44
45 class MonitoredProcess : public wxProcess
46 {
47 public:
48 MonitoredProcess()
49 { Redirect(); m_crashed=false; m_exitCode=0; }
50
51 void OnTerminate(int WXUNUSED(pid), int status)
52 {
53 wxStringOutputStream out, err;
54 if (GetInputStream()) out.Write(*GetInputStream());
55 if (GetErrorStream()) err.Write(*GetErrorStream());
56
57 //wxPrintf("%s\n", stdout.GetString());
58 //wxPrintf("%s\n", stderr.GetString());
59
60 // when wx programs assert on wxGTK/wxMac, they put on stderr a message like:
61 // [Debug] date somefilename.pp(nnnn): assert "xxxxx" failed in yyyy
62 // but then the assert dialog pop-ups and thus the app doesn't exit
63 // FIXME: make assertion detection work also under other platforms
64 // see http://trac.wxwidgets.org/ticket/10697
65 m_crashed = out.GetString().Contains("assert") ||
66 err.GetString().Contains("assert");
67 m_exitCode = status;
68 }
69
70 void Kill()
71 {
72 wxProcess::Kill(GetPid());
73
74 // wxProcess::Kill doesn't trigger a call to OnTerminate() normally...
75 // but we still need to call it!
76 OnTerminate(0, -1);
77 }
78
79 bool Crashed() const
80 { return m_crashed; }
81
82 int GetExitCode() const
83 { return m_exitCode; }
84
85 private:
86 bool m_crashed;
87 int m_exitCode;
88 };
89
90 class MonitorData
91 {
92 public:
93 MonitorData(const wxString& cmd) : program(cmd) {}
94
95 wxString program;
96 MonitoredProcess process;
97 };
98
99 // ----------------------------------------------------------------------------
100 // the real main
101 // ----------------------------------------------------------------------------
102
103 bool TestExec(const wxVector<wxFileName>& programs, long timeout)
104 {
105 size_t i;
106 wxVector<MonitorData*> data;
107
108 // run all programs specified as command line parameters
109 wxArrayLong procID;
110 for (i=0; i<programs.size(); i++)
111 {
112 MonitorData *dt = new MonitorData(programs[i].GetFullPath());
113
114 long pid = wxExecute(programs[i].GetFullPath(), wxEXEC_ASYNC, &dt->process);
115 if (pid == 0)
116 wxLogError("could not run the program '%s'", programs[i].GetFullPath());
117 else
118 {
119 wxLogMessage("started program '%s' (pid %d)...",
120 programs[i].GetFullPath(), pid);
121 wxASSERT(dt->process.GetPid() == pid);
122
123 data.push_back(dt);
124 }
125 }
126
127 // sleep some moments
128 wxSleep(timeout);
129
130 // check if all processes are still running
131 bool allok = true;
132 for (i=0; i<data.size(); i++)
133 {
134 MonitoredProcess& proc = data[i]->process;
135 const wxString& prog = data[i]->program;
136
137 if (wxProcess::Exists(proc.GetPid()))
138 proc.Kill();
139 else
140 {
141 // this typically never happens, at least when running wx-programs
142 // built with debug builds of wx (see MonitoredProcess::OnTerminate;
143 // even if an asserts fail the app doesn't automatically close!):
144
145 wxLogMessage("program '%s' (pid %d) is NOT running anymore...",
146 prog, proc.GetPid());
147 allok = false;
148 }
149
150 if (data[i]->process.Crashed())
151 {
152 allok = false;
153 wxLogMessage("program '%s' (pid %d) crashed...",
154 prog, proc.GetPid());
155 }
156 else
157 wxLogMessage("program '%s' (pid %d) ended with exit code %d...",
158 prog, proc.GetPid(), proc.GetExitCode());
159 }
160
161 return allok;
162 }
163
164 // ----------------------------------------------------------------------------
165 // main
166 // ----------------------------------------------------------------------------
167
168 int main(int argc, char **argv)
169 {
170 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "execmon");
171
172 wxInitializer initializer;
173 if ( !initializer )
174 {
175 fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.");
176 return -1;
177 }
178
179 static const wxCmdLineEntryDesc cmdLineDesc[] =
180 {
181 { wxCMD_LINE_SWITCH, "h", "help",
182 "show this help message",
183 wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
184 { wxCMD_LINE_OPTION, "t", "timeout",
185 "kills all processes still alive after 'num' seconds",
186 wxCMD_LINE_VAL_NUMBER, 0 },
187 { wxCMD_LINE_PARAM, "", "",
188 "program-to-run",
189 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE },
190
191 { wxCMD_LINE_NONE }
192 };
193
194 wxLog::DisableTimestamp();
195
196 wxCmdLineParser parser(cmdLineDesc, argc, argv);
197 switch ( parser.Parse() )
198 {
199 case -1:
200 // help was shown
201 break;
202
203 case 0:
204 {
205 // check arguments
206 wxVector<wxFileName> programs;
207 for (unsigned int i=0; i<parser.GetParamCount(); i++)
208 {
209 wxFileName fn(parser.GetParam(i));
210 if (!fn.IsAbsolute())
211 fn.MakeAbsolute();
212
213 programs.push_back(fn);
214 }
215
216 long timeout;
217 if (!parser.Found("t", &timeout))
218 timeout = 3;
219
220 return TestExec(programs, timeout) ? 0 : 1;
221 }
222 break;
223
224 default:
225 // syntax error
226 break;
227 }
228
229 return 0;
230 }
231