Update copyright to LGPL on all files
[dyninst.git] / testsuite / src / symtab / test_line_info.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include "symtab_comp.h"
33 #include "test_lib.h"
34
35 #include "Symtab.h"
36 #include "Symbol.h"
37 #include "Function.h"
38 #include "Variable.h"
39
40 using namespace Dyninst;
41 using namespace SymtabAPI;
42
43 class test_line_info_Mutator : public SymtabMutator {
44 public:
45    test_line_info_Mutator() { };
46    virtual test_results_t executeTest();
47    test_results_t basic_verification();
48
49    bool statement_ok(Statement *s)
50    {
51            if (!s)
52            {
53                    logerror( "%s[%d]:  NULL statement returned\n", FILE__, __LINE__);
54                    return false;
55            }
56
57            if (!s->getFile().length())
58            {
59                    logerror( "%s[%d]:  statement without file returned\n", FILE__, __LINE__);
60                    return false;
61            }
62
63            if ( 0 == s->getLine())
64            {
65                    //  a zero lineno may in fact be fine in the real world, but we don't really
66                    //  expect to see it here.  (This check can probably be removed if necessary)
67                    logerror( "%s[%d]:  statement with line = 0\n", FILE__, __LINE__);
68                    return false;
69            }
70
71            //  check for -1L because that's used in the default statement ctor.
72            if ( (0 == s->startAddr()) || (-1L == s->startAddr()))
73            {
74                    logerror( "%s[%d]:  statement with NULL startAddr: %s[%d]: %lu\n", 
75                                    FILE__, __LINE__, s->getFile().c_str(), s->getLine(), s->startAddr());
76                    return false;
77            }
78            //  check for -1L because that's used in the default statement ctor.
79            if ( (0 == s->endAddr()) || (-1L == s->endAddr()))
80            {
81                    logerror( "%s[%d]:  statement with NULL endAddr: %s[%d]: %lu\n", 
82                                    FILE__, __LINE__, s->getFile().c_str(), s->getLine(), s->endAddr());
83                    return false;
84            }
85
86            if (s->endAddr() < s->startAddr())
87            {
88                    logerror( "%s[%d]:  statement with endAddr (%lu) < startAddr (%lu)\n", 
89                                    FILE__, __LINE__, s->endAddr(), s->startAddr());
90                    return false;
91            }
92
93            return true;
94    }
95 };
96
97 extern "C" DLLEXPORT TestMutator* test_line_info_factory()
98 {
99    return new test_line_info_Mutator();
100 }
101
102 test_results_t test_line_info_Mutator::basic_verification()
103 {
104         std::vector<SymtabAPI::Module *> mods;
105         bool result = symtab->getAllModules(mods);
106
107         if (!result || !mods.size() )
108         {
109                 logerror("%s[%d]: Unable to getAllModules\n", FILE__, __LINE__);
110                 return FAILED;
111         }
112
113         //  First run over all statements and verify that we return sane-ish results.
114         
115         for (unsigned int i = 0; i < mods.size(); ++i)
116         {
117                 SymtabAPI::Module *mod = mods[i];
118                 if (!mod)
119                 {
120                         logerror("%s[%d]: Error: NULL module returned\n", FILE__, __LINE__);
121                         return FAILED;
122                 }
123
124                 std::string modname = mod->fileName();
125
126                 logerror("%s[%d]:  considering module %s\n", FILE__, __LINE__, modname.c_str());
127
128                 std::vector<Statement *> statements;
129
130                 if (!mod->getStatements(statements) || (0 == statements.size()))
131                 {
132                         //  We try to test all statements in all modules that have them,
133                         //  but not all do.  Thus we only fail here if the module that has
134                         //  no statements is one of ours.
135
136                         if ( (modname == "mutatee_util.c") 
137                                         || (modname == "solo_mutatee_boilerplate.c")
138                                         || (modname == "mutatee_driver.c"))
139                         {
140                                 logerror( "%s[%d]:  getStatements failed for module %s\n", 
141                                                 FILE__, __LINE__, modname.c_str());
142                                 return FAILED;
143                         }
144
145                         logerror("%s[%d]:  skipping module %s\n", FILE__, __LINE__, modname.c_str());
146                         continue;
147                 }
148
149                 for (unsigned int j = 0; j < statements.size(); ++j)
150                 {
151                         //  statement_ok does NULL check, so don't bother doing it here 
152
153                         if (!statement_ok(statements[j]))
154                         {
155                                 logerror( "%s[%d]:  bad statement returned for module %s\n", 
156                                                 FILE__, __LINE__, modname.c_str());
157                                 return FAILED;
158                         }
159                 }
160         }
161
162         return PASSED;
163 }
164
165 test_results_t test_line_info_Mutator::executeTest()
166 {
167
168 #if defined (os_solaris_test)
169         //  It appears that the sun compilers do not implement the
170         //  #line directive properly.  This would merit more investigation
171         //  if we had any users who cared about line info on solaris.
172         //
173         //  TODO:  figure out how to add this condition to the spec file
174
175         if ((compiler == std::string("CC")) 
176                         || (compiler == std::string("sun_cc")))
177         {
178                 return SKIPPED;
179         }
180
181 #endif
182 #if defined (os_aix_test)
183         //if (useAttach == DESERIALIZE)
184                 return SKIPPED;
185 #endif
186         if (FAILED == basic_verification())
187         {
188                 logerror( "%s[%d]:  failed basic verifications, skipping rest...\n", 
189                                 FILE__, __LINE__);
190                 return FAILED;
191         }
192
193         std::vector<Function *> funcs;
194         bool result = symtab->findFunctionsByName(funcs, std::string("test_line_info_func"));
195
196         if (!result || !funcs.size() )
197         {
198                 logerror("[%s:%u] - Unable to find test_line_info_func\n", 
199                                 __FILE__, __LINE__);
200                 return FAILED;
201         }
202
203         if (funcs.size() != 1)
204         {
205                 logerror("[%s:%u] - Too many functions found??: %d\n", 
206                                 __FILE__, __LINE__, funcs.size());
207                 return FAILED;
208         }
209
210         Function *f = funcs[0];
211         if (!f)
212         {
213                 logerror("[%s:%u] - NULL function returned\n", 
214                                 __FILE__, __LINE__);
215                 return FAILED;
216         }
217
218         std::vector<localVar *> params;
219         std::vector<localVar *> local_vars;
220
221     if (!f->getParams(params))
222         {
223                 logerror( "%s[%d]:  failed to getParams()\n", FILE__, __LINE__);
224                 return FAILED;
225         }
226
227         if (params.size() != 1)
228         {
229                 logerror( "%s[%d]:  bad number of params: %d, not 1\n", 
230                                 FILE__, __LINE__, params.size());
231                 return FAILED;
232         }
233
234         int param_line_no = params[0]->getLineNum();
235
236         //  we use the #line preprocessor directive in the mutatee to set the expected value
237         if (param_line_no != 1000)
238         {
239                 logerror( "%s[%d]:  param_line_no = %d not 1000\n", 
240                                 FILE__, __LINE__, param_line_no);
241                 return FAILED;
242         }
243
244     if (!f->getLocalVariables(local_vars))
245         {
246                 logerror( "%s[%d]:  failed to getLocalVariables()\n", FILE__, __LINE__);
247                 return FAILED;
248         }
249
250         if (local_vars.size() != 3)
251         {
252                 logerror( "%s[%d]:  bad number of local_vars: %d, not 3\n", 
253                                 FILE__, __LINE__, params.size());
254                 return FAILED;
255         }
256
257         //  we use the #line preprocessor directive in the mutatee to set the expected value
258         int expected_lv_line_no = 2000;
259         for (unsigned int i = 0; i < local_vars.size(); ++i)
260         {
261                 int lv_line_no = local_vars[i]->getLineNum();
262                 if (lv_line_no != expected_lv_line_no)
263                 {
264                         logerror( "%s[%d]:  local var %d:  line# = %d, expected %d\n", 
265                                         FILE__, __LINE__, i, lv_line_no, expected_lv_line_no);
266                         return FAILED;
267                 }
268                 expected_lv_line_no++;
269         }
270
271
272         return PASSED;
273 }
274