blob: ac8c402ac8bbd8d94c2942863ddc2307b397a0c8 [file] [log] [blame]
Greg Clayton5dbe5d42013-03-21 03:39:51 +00001//===-- TestCase.cpp --------------------------------------------*- C++ -*-===//
Enrico Granataf58cece2013-03-08 20:29:13 +00002//
Greg Clayton5dbe5d42013-03-21 03:39:51 +00003// The LLVM Compiler Infrastructure
Enrico Granataf58cece2013-03-08 20:29:13 +00004//
Greg Clayton5dbe5d42013-03-21 03:39:51 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Enrico Granataf58cece2013-03-08 20:29:13 +00007//
Greg Clayton5dbe5d42013-03-21 03:39:51 +00008//===----------------------------------------------------------------------===//
Enrico Granataf58cece2013-03-08 20:29:13 +00009
10#include "TestCase.h"
Greg Clayton880afc52013-03-22 02:31:35 +000011#include "Results.h"
Enrico Granataf58cece2013-03-08 20:29:13 +000012#include "Xcode.h"
13
Greg Clayton7b8f7382013-03-18 22:34:00 +000014using namespace lldb_perf;
Enrico Granataf58cece2013-03-08 20:29:13 +000015
16TestCase::TestCase () :
Greg Claytone0b924e2013-03-19 04:41:22 +000017 m_debugger(),
18 m_target(),
19 m_process(),
20 m_thread(),
21 m_listener(),
Enrico Granatae16dfcd2013-03-20 22:42:34 +000022 m_verbose(false),
23 m_step(0)
Enrico Granataf58cece2013-03-08 20:29:13 +000024{
Enrico Granata86910572013-03-14 19:00:42 +000025 SBDebugger::Initialize();
Enrico Granataf58cece2013-03-08 20:29:13 +000026 SBHostOS::ThreadCreated ("<lldb-tester.app.main>");
27 m_debugger = SBDebugger::Create(false);
28 m_listener = m_debugger.GetListener();
29}
30
Enrico Granata8fab9fd2013-04-01 18:02:25 +000031static std::string
32GetShortOptionString (struct option *long_options)
Greg Claytone0b924e2013-03-19 04:41:22 +000033{
Enrico Granata8fab9fd2013-04-01 18:02:25 +000034 std::string option_string;
35 for (int i = 0; long_options[i].name != NULL; ++i)
36 {
37 if (long_options[i].flag == NULL)
38 {
39 option_string.push_back ((char) long_options[i].val);
40 switch (long_options[i].has_arg)
41 {
42 default:
43 case no_argument:
44 break;
45 case required_argument:
46 option_string.push_back (':');
47 break;
48 case optional_argument:
49 option_string.append (2, ':');
50 break;
51 }
52 }
53 }
54 return option_string;
55}
56
57bool
58TestCase::Setup (int& argc, const char**& argv)
59{
60 bool done = false;
61
62 struct option* long_options = GetLongOptions();
63
64 if (long_options)
65 {
66 std::string short_option_string (GetShortOptionString(long_options));
67
68 #if __GLIBC__
69 optind = 0;
70 #else
71 optreset = 1;
72 optind = 1;
73 #endif
74 while (!done)
75 {
76 int long_options_index = -1;
77 const int short_option = ::getopt_long_only (argc,
78 const_cast<char **>(argv),
79 short_option_string.c_str(),
80 long_options,
81 &long_options_index);
82
83 switch (short_option)
84 {
85 case 0:
86 // Already handled
87 break;
88
89 case -1:
90 done = true;
91 break;
92
93 default:
94 done = !ParseOption(short_option, optarg);
95 break;
96 }
97 }
98 argc -= optind;
99 argv += optind;
100 }
101
Greg Claytone0b924e2013-03-19 04:41:22 +0000102 return false;
103}
Enrico Granata86910572013-03-14 19:00:42 +0000104
Enrico Granataf58cece2013-03-08 20:29:13 +0000105bool
Greg Claytone0b924e2013-03-19 04:41:22 +0000106TestCase::Launch (lldb::SBLaunchInfo &launch_info)
Enrico Granataf58cece2013-03-08 20:29:13 +0000107{
Greg Claytone0b924e2013-03-19 04:41:22 +0000108 lldb::SBError error;
109 m_process = m_target.Launch (launch_info, error);
110 if (!error.Success())
111 fprintf (stderr, "error: %s\n", error.GetCString());
112 if (m_process.IsValid())
113 {
114 m_process.GetBroadcaster().AddListener(m_listener, SBProcess::eBroadcastBitStateChanged | SBProcess::eBroadcastBitInterrupt);
115 return true;
116 }
117 return false;
Enrico Granataf58cece2013-03-08 20:29:13 +0000118}
119
Enrico Granata4e969282013-04-02 21:31:18 +0000120bool
121TestCase::Launch (std::initializer_list<const char*> args)
122{
123 std::vector<const char*> args_vect(args);
124 args_vect.push_back(NULL);
125 lldb::SBLaunchInfo launch_info((const char**)&args_vect[0]);
126 return Launch(launch_info);
127}
128
Enrico Granataf58cece2013-03-08 20:29:13 +0000129void
130TestCase::SetVerbose (bool b)
131{
132 m_verbose = b;
133}
134
135bool
136TestCase::GetVerbose ()
137{
138 return m_verbose;
139}
140
141void
142TestCase::Loop ()
143{
Enrico Granataf58cece2013-03-08 20:29:13 +0000144 while (true)
145 {
Greg Clayton880afc52013-03-22 02:31:35 +0000146 bool call_test_step = false;
147 if (m_process.IsValid())
148 {
149 SBEvent evt;
150 m_listener.WaitForEvent (UINT32_MAX, evt);
151 StateType state = SBProcess::GetStateFromEvent (evt);
152 if (m_verbose)
153 printf("event = %s\n",SBDebugger::StateAsCString(state));
154 if (SBProcess::GetRestartedFromEvent(evt))
155 continue;
156 switch (state)
157 {
158 case eStateInvalid:
159 case eStateDetached:
160 case eStateCrashed:
161 case eStateUnloaded:
162 break;
163 case eStateExited:
164 return;
165 case eStateConnected:
166 case eStateAttaching:
167 case eStateLaunching:
168 case eStateRunning:
169 case eStateStepping:
170 continue;
171 case eStateStopped:
172 case eStateSuspended:
173 {
174 call_test_step = true;
175 bool fatal = false;
176 bool selected_thread = false;
177 for (auto thread_index = 0; thread_index < m_process.GetNumThreads(); thread_index++)
Greg Claytone0b924e2013-03-19 04:41:22 +0000178 {
Greg Clayton880afc52013-03-22 02:31:35 +0000179 SBThread thread(m_process.GetThreadAtIndex(thread_index));
180 SBFrame frame(thread.GetFrameAtIndex(0));
181 bool select_thread = false;
182 StopReason stop_reason = thread.GetStopReason();
183 if (m_verbose) printf("tid = 0x%llx pc = 0x%llx ",thread.GetThreadID(),frame.GetPC());
184 switch (stop_reason)
185 {
186 case eStopReasonNone:
187 if (m_verbose)
188 printf("none\n");
189 break;
190
191 case eStopReasonTrace:
192 select_thread = true;
193 if (m_verbose)
194 printf("trace\n");
195 break;
196
197 case eStopReasonPlanComplete:
198 select_thread = true;
199 if (m_verbose)
200 printf("plan complete\n");
201 break;
202 case eStopReasonThreadExiting:
203 if (m_verbose)
204 printf("thread exiting\n");
205 break;
206 case eStopReasonExec:
207 if (m_verbose)
208 printf("exec\n");
209 break;
210 case eStopReasonInvalid:
211 if (m_verbose)
212 printf("invalid\n");
213 break;
214 case eStopReasonException:
215 select_thread = true;
216 if (m_verbose)
217 printf("exception\n");
218 fatal = true;
219 break;
220 case eStopReasonBreakpoint:
221 select_thread = true;
222 if (m_verbose)
223 printf("breakpoint id = %lld.%lld\n",thread.GetStopReasonDataAtIndex(0),thread.GetStopReasonDataAtIndex(1));
224 break;
225 case eStopReasonWatchpoint:
226 select_thread = true;
227 if (m_verbose)
228 printf("watchpoint id = %lld\n",thread.GetStopReasonDataAtIndex(0));
229 break;
230 case eStopReasonSignal:
231 select_thread = true;
232 if (m_verbose)
233 printf("signal %d\n",(int)thread.GetStopReasonDataAtIndex(0));
234 break;
235 }
236 if (select_thread && !selected_thread)
237 {
238 m_thread = thread;
239 selected_thread = m_process.SetSelectedThread(thread);
240 }
Greg Claytone0b924e2013-03-19 04:41:22 +0000241 }
Greg Clayton880afc52013-03-22 02:31:35 +0000242 if (fatal)
243 {
244 if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true);
245 exit(1);
246 }
247 }
248 break;
Enrico Granataf58cece2013-03-08 20:29:13 +0000249 }
250 }
Greg Clayton880afc52013-03-22 02:31:35 +0000251 else
252 {
253 call_test_step = true;
254 }
255
256 if (call_test_step)
257 {
258 if (m_verbose)
259 printf("RUNNING STEP %d\n",m_step);
260 ActionWanted action;
261 TestStep(m_step, action);
262 m_step++;
263 SBError err;
264 switch (action.type)
265 {
266 case ActionWanted::Type::eContinue:
267 err = m_process.Continue();
268 break;
269 case ActionWanted::Type::eStepOut:
270 if (action.thread.IsValid() == false)
271 {
272 if (m_verbose)
273 {
274 Xcode::RunCommand(m_debugger,"bt all",true);
275 printf("error: invalid thread for step out on step %d\n", m_step);
276 }
277 exit(501);
278 }
279 m_process.SetSelectedThread(action.thread);
280 action.thread.StepOut();
281 break;
282 case ActionWanted::Type::eStepOver:
283 if (action.thread.IsValid() == false)
284 {
285 if (m_verbose)
286 {
287 Xcode::RunCommand(m_debugger,"bt all",true);
288 printf("error: invalid thread for step over %d\n",m_step);
289 }
290 exit(500);
291 }
292 m_process.SetSelectedThread(action.thread);
293 action.thread.StepOver();
294 break;
295 case ActionWanted::Type::eKill:
296 if (m_verbose)
297 printf("kill\n");
298 m_process.Kill();
299 return;
300 }
301 }
302
Enrico Granataf58cece2013-03-08 20:29:13 +0000303 }
Greg Clayton880afc52013-03-22 02:31:35 +0000304
Enrico Granatae16dfcd2013-03-20 22:42:34 +0000305 if (GetVerbose()) printf("I am gonna die at step %d\n",m_step);
Enrico Granataf58cece2013-03-08 20:29:13 +0000306}
307
Enrico Granata4e969282013-04-02 21:31:18 +0000308int
Enrico Granataf58cece2013-03-08 20:29:13 +0000309TestCase::Run (TestCase& test, int argc, const char** argv)
310{
Greg Claytone0b924e2013-03-19 04:41:22 +0000311 if (test.Setup(argc, argv))
312 {
313 test.Loop();
Greg Clayton880afc52013-03-22 02:31:35 +0000314 Results results;
315 test.WriteResults(results);
Enrico Granata4e969282013-04-02 21:31:18 +0000316 return RUN_SUCCESS;
Greg Claytone0b924e2013-03-19 04:41:22 +0000317 }
Enrico Granata4e969282013-04-02 21:31:18 +0000318 else
319 return RUN_SETUP_ERROR;
Enrico Granataf58cece2013-03-08 20:29:13 +0000320}
Greg Clayton880afc52013-03-22 02:31:35 +0000321