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