]> git.saurik.com Git - wxWidgets.git/blame - utils/execmon/execmon.cpp
build fix (wx doesn't use bakefile 0.2.6 yet)
[wxWidgets.git] / utils / execmon / execmon.cpp
CommitLineData
aa113d87
FM
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
45class MonitoredProcess : public wxProcess
46{
47public:
48 MonitoredProcess()
49 { Redirect(); m_crashed=false; m_exitCode=0; }
50
51 void OnTerminate(int WXUNUSED(pid), int status)
52 {
53 wxStringOutputStream stdout, stderr;
54 if (GetInputStream()) stdout.Write(*GetInputStream());
55 if (GetErrorStream()) stderr.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 = stdout.GetString().Contains("assert") ||
66 stderr.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
85private:
86 bool m_crashed;
87 int m_exitCode;
88};
89
90class MonitorData
91{
92public:
93 MonitorData(const wxString& cmd) : program(cmd) {}
94
95 wxString program;
96 MonitoredProcess process;
97};
98
99// ----------------------------------------------------------------------------
100// the real main
101// ----------------------------------------------------------------------------
102
103bool TestExec(const wxVector<wxFileName>& programs, long timeout)
104{
105 wxVector<MonitorData*> data;
106
107 // run all programs specified as command line parameters
108 wxArrayLong procID;
109 for (size_t i=0; i<programs.size(); i++)
110 {
111 MonitorData *dt = new MonitorData(programs[i].GetFullPath());
112
113 long pid = wxExecute(programs[i].GetFullPath(), wxEXEC_ASYNC, &dt->process);
114 if (pid == 0)
115 wxLogError("could not run the program '%s'", programs[i].GetFullPath());
116 else
117 {
118 wxLogMessage("started program '%s' (pid %d)...",
119 programs[i].GetFullPath(), pid);
120 wxASSERT(dt->process.GetPid() == pid);
121
122 data.push_back(dt);
123 }
124 }
125
126 // sleep some moments
127 wxSleep(timeout);
128
129 // check if all processes are still running
130 bool allok = true;
131 for (size_t i=0; i<data.size(); i++)
132 {
133 MonitoredProcess& proc = data[i]->process;
134 const wxString& prog = data[i]->program;
135
136 if (wxProcess::Exists(proc.GetPid()))
137 proc.Kill();
138 else
139 {
140 // this typically never happens, at least when running wx-programs
141 // built with debug builds of wx (see MonitoredProcess::OnTerminate;
142 // even if an asserts fail the app doesn't automatically close!):
143
144 wxLogMessage("program '%s' (pid %d) is NOT running anymore...",
145 prog, proc.GetPid());
146 allok = false;
147 }
148
149 if (data[i]->process.Crashed())
150 {
151 allok = false;
152 wxLogMessage("program '%s' (pid %d) crashed...",
153 prog, proc.GetPid());
154 }
155 else
156 wxLogMessage("program '%s' (pid %d) ended with exit code %d...",
157 prog, proc.GetPid(), proc.GetExitCode());
158 }
159
160 return allok;
161}
162
163// ----------------------------------------------------------------------------
164// main
165// ----------------------------------------------------------------------------
166
167int main(int argc, char **argv)
168{
169 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "execmon");
170
171 wxInitializer initializer;
172 if ( !initializer )
173 {
174 fprintf(stderr, "Failed to initialize the wxWidgets library, aborting.");
175 return -1;
176 }
177
178 static const wxCmdLineEntryDesc cmdLineDesc[] =
179 {
180 { wxCMD_LINE_SWITCH, "h", "help",
181 "show this help message",
182 wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
183 { wxCMD_LINE_OPTION, "t", "timeout",
184 "kills all processes still alive after 'num' seconds",
185 wxCMD_LINE_VAL_NUMBER, 0 },
186 { wxCMD_LINE_PARAM, "", "",
187 "program-to-run",
188 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE },
189
190 { wxCMD_LINE_NONE }
191 };
192
193 wxLog::DisableTimestamp();
194
195 wxCmdLineParser parser(cmdLineDesc, argc, argv);
196 switch ( parser.Parse() )
197 {
198 case -1:
199 // help was shown
200 break;
201
202 case 0:
203 {
204 // check arguments
205 wxVector<wxFileName> programs;
206 for (unsigned int i=0; i<parser.GetParamCount(); i++)
207 {
208 wxFileName fn(parser.GetParam(i));
209 if (!fn.IsAbsolute())
210 fn.MakeAbsolute();
211
212 programs.push_back(fn);
213 }
214
215 long timeout;
216 if (!parser.Found("t", &timeout))
217 timeout = 3;
218
219 return TestExec(programs, timeout) ? 0 : 1;
220 }
221 break;
222
223 default:
224 // syntax error
225 break;
226 }
227
228 return 0;
229}
230