]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/lldb-perf/lib/TestCase.cpp
Vendor import of lldb trunk r256945:
[FreeBSD/FreeBSD.git] / tools / lldb-perf / lib / TestCase.cpp
1 //===-- TestCase.cpp --------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "TestCase.h"
11 #include "Results.h"
12 #include "Xcode.h"
13
14 using namespace lldb_perf;
15
16 TestCase::TestCase () :
17     m_debugger(),
18     m_target(),
19     m_process(),
20     m_thread(),
21     m_listener(),
22     m_verbose(false),
23     m_step(0)
24 {
25     SBDebugger::Initialize();
26         SBHostOS::ThreadCreated ("<lldb-tester.app.main>");
27         m_debugger = SBDebugger::Create(false);
28         m_listener = m_debugger.GetListener();
29     m_listener.StartListeningForEventClass (m_debugger, SBProcess::GetBroadcasterClass(), SBProcess::eBroadcastBitStateChanged | SBProcess::eBroadcastBitInterrupt);
30 }
31
32 static std::string
33 GetShortOptionString (struct option *long_options)
34 {
35     std::string option_string;
36     for (int i = 0; long_options[i].name != NULL; ++i)
37     {
38         if (long_options[i].flag == NULL)
39         {
40             option_string.push_back ((char) long_options[i].val);
41             switch (long_options[i].has_arg)
42             {
43                 default:
44                 case no_argument:
45                     break;
46                 case required_argument:
47                     option_string.push_back (':');
48                     break;
49                 case optional_argument:
50                     option_string.append (2, ':');
51                     break;
52             }
53         }
54     }
55     return option_string;
56 }
57
58 bool
59 TestCase::Setup (int& argc, const char**& argv)
60 {
61     bool done = false;
62     
63     struct option* long_options = GetLongOptions();
64     
65     if (long_options)
66     {
67         std::string short_option_string (GetShortOptionString(long_options));
68         
69     #if __GLIBC__
70         optind = 0;
71     #else
72         optreset = 1;
73         optind = 1;
74     #endif
75         while (!done)
76         {
77             int long_options_index = -1;
78             const int short_option = ::getopt_long_only (argc,
79                                                          const_cast<char **>(argv),
80                                                          short_option_string.c_str(),
81                                                          long_options,
82                                                          &long_options_index);
83             
84             switch (short_option)
85             {
86                 case 0:
87                     // Already handled
88                     break;
89                     
90                 case -1:
91                     done = true;
92                     break;
93                     
94                 default:
95                     done = !ParseOption(short_option, optarg);
96                     break;
97             }
98         }
99         argc -= optind;
100         argv += optind;
101     }
102     
103     return false;
104 }
105
106 bool
107 TestCase::Launch (lldb::SBLaunchInfo &launch_info)
108 {
109     lldb::SBError error;
110         m_process = m_target.Launch (launch_info, error);
111     if (!error.Success())
112         fprintf (stderr, "error: %s\n", error.GetCString());
113     if (m_process.IsValid())
114         return true;
115     return false;
116 }
117
118 bool
119 TestCase::Launch (std::initializer_list<const char*> args)
120 {
121     std::vector<const char*> args_vect(args);
122     args_vect.push_back(NULL);
123     lldb::SBLaunchInfo launch_info((const char**)&args_vect[0]);
124     return Launch(launch_info);
125 }
126
127 void
128 TestCase::SetVerbose (bool b)
129 {
130     m_verbose = b;
131 }
132
133 bool
134 TestCase::GetVerbose ()
135 {
136     return m_verbose;
137 }
138
139 void
140 TestCase::Loop ()
141 {
142         while (true)
143         {
144         bool call_test_step = false;
145         if (m_process.IsValid())
146         {
147             SBEvent evt;
148             m_listener.WaitForEvent (UINT32_MAX, evt);
149             StateType state = SBProcess::GetStateFromEvent (evt);
150             if (m_verbose)
151                 printf("event = %s\n",SBDebugger::StateAsCString(state));
152             if (SBProcess::GetRestartedFromEvent(evt))
153             {
154                 if (m_verbose)
155                 {
156                     const uint32_t num_threads = m_process.GetNumThreads();
157                     for (auto thread_index = 0; thread_index < num_threads; thread_index++)
158                     {
159                         SBThread thread(m_process.GetThreadAtIndex(thread_index));
160                         SBFrame frame(thread.GetFrameAtIndex(0));
161                         SBStream strm;
162                         strm.RedirectToFileHandle(stdout, false);
163                         frame.GetDescription(strm);
164                     }
165                     puts("restarted");
166                 }
167                 call_test_step = false;
168             }
169             else
170             {
171                 switch (state)
172                 {
173                 case eStateInvalid:
174                 case eStateDetached:
175                 case eStateCrashed:
176                 case eStateUnloaded:
177                     break;
178                 case eStateExited:
179                     return;
180                 case eStateConnected:
181                 case eStateAttaching:
182                 case eStateLaunching:
183                 case eStateRunning:
184                 case eStateStepping:
185                     call_test_step = false;
186                     break;
187         
188                 case eStateStopped:
189                 case eStateSuspended:
190                     {
191                         call_test_step = true;
192                         bool fatal = false;
193                         bool selected_thread = false;
194                         const uint32_t num_threads = m_process.GetNumThreads();
195                         for (auto thread_index = 0; thread_index < num_threads; thread_index++)
196                         {
197                             SBThread thread(m_process.GetThreadAtIndex(thread_index));
198                             SBFrame frame(thread.GetFrameAtIndex(0));
199                             SBStream strm;
200                             strm.RedirectToFileHandle(stdout, false);
201                             frame.GetDescription(strm);
202                             bool select_thread = false;
203                             StopReason stop_reason = thread.GetStopReason();
204                             if (m_verbose) printf("tid = 0x%llx pc = 0x%llx ",thread.GetThreadID(),frame.GetPC());
205                             switch (stop_reason)
206                             {
207                                 case eStopReasonNone:
208                                     if (m_verbose)
209                                         printf("none\n");
210                                     break;
211                                     
212                                 case eStopReasonTrace:
213                                     select_thread = true;
214                                     if (m_verbose)
215                                         printf("trace\n");
216                                     break;
217                                     
218                                 case eStopReasonPlanComplete:
219                                     select_thread = true;
220                                     if (m_verbose)
221                                         printf("plan complete\n");
222                                     break;
223                                 case eStopReasonThreadExiting:
224                                     if (m_verbose)
225                                         printf("thread exiting\n");
226                                     break;
227                                 case eStopReasonExec:
228                                     if (m_verbose)
229                                         printf("exec\n");
230                                     break;
231                                 case eStopReasonInvalid:
232                                     if (m_verbose)
233                                         printf("invalid\n");
234                                     break;
235                                 case eStopReasonException:
236                                     select_thread = true;
237                                     if (m_verbose)
238                                         printf("exception\n");
239                                     fatal = true;
240                                     break;
241                                 case eStopReasonBreakpoint:
242                                     select_thread = true;
243                                     if (m_verbose)
244                                         printf("breakpoint id = %lld.%lld\n",thread.GetStopReasonDataAtIndex(0),thread.GetStopReasonDataAtIndex(1));
245                                     break;
246                                 case eStopReasonWatchpoint:
247                                     select_thread = true;
248                                     if (m_verbose)
249                                         printf("watchpoint id = %lld\n",thread.GetStopReasonDataAtIndex(0));
250                                     break;
251                                 case eStopReasonSignal:
252                                     select_thread = true;
253                                     if (m_verbose)
254                                         printf("signal %d\n",(int)thread.GetStopReasonDataAtIndex(0));
255                                     break;
256                             }
257                             if (select_thread && !selected_thread)
258                             {
259                                 m_thread = thread;
260                                 selected_thread = m_process.SetSelectedThread(thread);
261                             }
262                         }
263                         if (fatal)
264                         {
265                             if (m_verbose) Xcode::RunCommand(m_debugger,"bt all",true);
266                             exit(1);
267                         }
268                     }
269                     break;
270                 }
271             }
272                 }
273         else
274         {
275             call_test_step = true;
276         }
277
278         if (call_test_step)
279         {
280         do_the_call:
281             if (m_verbose)
282                 printf("RUNNING STEP %d\n",m_step);
283             ActionWanted action;
284             TestStep(m_step, action);
285             m_step++;
286             SBError err;
287             switch (action.type)
288             {
289             case ActionWanted::Type::eNone:
290                 // Just exit and wait for the next event
291                 break;
292             case ActionWanted::Type::eContinue:
293                 err = m_process.Continue();
294                 break;
295             case ActionWanted::Type::eStepOut:
296                 if (action.thread.IsValid() == false)
297                 {
298                     if (m_verbose)
299                     {
300                         Xcode::RunCommand(m_debugger,"bt all",true);
301                         printf("error: invalid thread for step out on step %d\n", m_step);
302                     }
303                     exit(501);
304                 }
305                 m_process.SetSelectedThread(action.thread);
306                 action.thread.StepOut();
307                 break;
308             case ActionWanted::Type::eStepOver:
309                 if (action.thread.IsValid() == false)
310                 {
311                     if (m_verbose)
312                     {
313                         Xcode::RunCommand(m_debugger,"bt all",true);
314                         printf("error: invalid thread for step over %d\n",m_step);
315                     }
316                     exit(500);
317                 }
318                 m_process.SetSelectedThread(action.thread);
319                 action.thread.StepOver();
320                 break;
321             case ActionWanted::Type::eRelaunch:
322                 if (m_process.IsValid())
323                 {
324                     m_process.Kill();
325                     m_process.Clear();
326                 }
327                 Launch(action.launch_info);
328                 break;
329             case ActionWanted::Type::eKill:
330                 if (m_verbose)
331                     printf("kill\n");
332                 m_process.Kill();
333                 return;
334             case ActionWanted::Type::eCallNext:
335                 goto do_the_call;
336                 break;
337             }
338         }
339
340         }
341     
342         if (GetVerbose()) printf("I am gonna die at step %d\n",m_step);
343 }
344
345 int
346 TestCase::Run (TestCase& test, int argc, const char** argv)
347 {
348     if (test.Setup(argc, argv))
349     {
350         test.Loop();
351         Results results;
352         test.WriteResults(results);
353         return RUN_SUCCESS;
354     }
355     else
356         return RUN_SETUP_ERROR;
357 }
358