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