Remove old testsuite
[dyninst.git] / testsuite / src / dyninst / test_fork_5.C
1 /*
2  * Copyright (c) 1996-2004 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  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: test_fork_5.C,v 1.1 2008/10/30 19:21:36 legendre Exp $
43 /*
44  * #Name: test7_1
45  * #Desc: Delete snippet in parent
46  * #Arch: all
47  * #Dep: 
48  */
49
50 #include "BPatch.h"
51 #include "BPatch_Vector.h"
52 #include "BPatch_thread.h"
53 #include "BPatch_snippet.h"
54
55 #include "test_lib.h"
56 #include "test_lib_test7.h"
57
58 #include "dyninst_comp.h"
59 class test_fork_5_Mutator : public DyninstMutator {
60   BPatch *bpatch;
61
62 public:
63   virtual bool hasCustomExecutionPath() { return true; }
64   virtual test_results_t setup(ParameterDict &param);
65   virtual test_results_t executeTest();
66 };
67 extern "C" DLLEXPORT TestMutator *test_fork_5_factory() {
68   return new test_fork_5_Mutator();
69 }
70
71 static bool parentDone;
72 static bool childDone;
73 static bool passedTest;
74 static BPatch_thread *parentThread;
75 static BPatch_thread *childThread;
76 static int msgid;
77
78
79 /* Make sure deleting a snippet in a parent process doesn't delete the
80    snippet in the child process.
81
82    parent: snippetHandleA  = insert snippetA at pointA
83    child:  snippetHandleA' = pointA.getCurrentSnippets()
84    --- fork ---
85    parent: deleteSnippet( snippetHandleA )
86    --- run  ---
87    child:  verify snippetHandleA' still ran
88 */
89
90 static void prepareTestCase1(procType proc_type, BPatch_thread *thread, forkWhen when)
91 {
92   static BPatchSnippetHandle *parSnippetHandle1;
93    
94   if(proc_type == Parent_p  &&  when == PreFork) {
95     BPatch_image *parImage = thread->getImage();
96        
97     BPatch_Vector<BPatch_function *> found_funcs;
98     const char *inFunction = "test_fork_5_func1";
99     if ((NULL == parImage->findFunction(inFunction, found_funcs, 1))
100         || !found_funcs.size()) {
101       logerror("    Unable to find function %s\n",
102                inFunction);
103       // FIXME Don't just exit() here!
104       exit(1);
105     }
106        
107     if (1 < found_funcs.size()) {
108       logerror("%s[%d]:  WARNING  : found %d functions named %s.  Using the first.\n", 
109                __FILE__, __LINE__, found_funcs.size(), inFunction);
110     }
111        
112     BPatch_Vector<BPatch_point *> *point7_1p =
113         found_funcs[0]->findPoint(BPatch_entry);
114
115     // FIXME This call will not compile.  Need to fix it to work and print
116     // out the correct error message
117     if(doError(&passedTest, !point7_1p || ((*point7_1p).size() == 0),
118                "  Unable to find entry point to \"test_fork_5_func1\".\n")) return;
119        
120     BPatch_variableExpr *var7_1p = 
121       parImage->findVariable("test_fork_5_global1");
122     if(doError(&passedTest, (var7_1p==NULL),
123                "  Unable to locate variable test_fork_5_global1\n")) return;
124        
125     BPatch_arithExpr expr7_1p(BPatch_assign, *var7_1p,BPatch_constExpr(321));
126        
127     parSnippetHandle1 =
128       thread->insertSnippet(expr7_1p, *point7_1p, BPatch_callBefore);
129     if(doError(&passedTest, (parSnippetHandle1 == NULL),
130                "  Unable to insert snippet into parent for test 1\n")) return;
131   } else if(proc_type == Parent_p  &&  when == PostFork) {
132     thread->deleteSnippet(parSnippetHandle1);
133   }
134 }
135
136 static void checkTestCase1(procType proc_type, BPatch_thread *thread) {
137    if(proc_type == Parent_p) {
138       if(! verifyProcMemory(thread, "test_fork_5_global1", 123, proc_type)) {
139          passedTest = false;
140       }
141    } else if(proc_type == Child_p) {
142       if(! verifyProcMemory(thread, "test_fork_5_global1", 321, proc_type)) {
143          passedTest = false;
144       }
145    }
146 }
147
148 /* We make changes at post-fork */
149 static void postForkFunc(BPatch_thread *parent, BPatch_thread *child)
150 {
151     //dprintf("in postForkFunc\n");
152     /* For later identification */
153     childThread = child;
154     dprintf("Preparing tests on parent\n");
155     prepareTestCase1(Parent_p, parent, PostFork);
156     dprintf("Preparing tests on child\n");
157     prepareTestCase1(Child_p,  child,  PostFork);
158     dprintf("Fork handler finished (parent %p, child %p)\n", parent, child);
159 }
160
161 /* And verify them when they exit */
162 static void exitFunc(BPatch_thread *thread, BPatch_exitType exit_type) {
163     dprintf("Exit func called\n");
164     if (thread == parentThread) {
165         dprintf("Parent exit reached, checking...\n");
166         checkTestCase1(Parent_p, thread);
167         parentDone = true;
168         dprintf("Parent done\n");
169     }
170     else if (thread == childThread) {
171         dprintf("Child exit reached, checking...\n");
172         checkTestCase1(Child_p, thread);
173         dprintf("Child done\n");
174         childDone = true;
175     }
176     else {
177         dprintf("Thread ptr 0x%x, parent 0x%x, child 0x%x\n",
178                 thread, parentThread, childThread);
179         assert(0 && "Unexpected BPatch_thread in exitFunc");
180     }
181     return;
182 }
183
184 static void initialPreparation(BPatch_thread *parent)
185 {
186    //cerr << "in initialPreparation\n";
187    assert(parent->isStopped());
188
189    //cerr << "ok, inserting instr\n";
190    prepareTestCase1(Parent_p, parent, PreFork);
191 }
192
193 static test_results_t mutatorTest(BPatch *bpatch, BPatch_thread *appThread)
194 {
195     if ( !setupMessaging(&msgid) )
196     {
197        passedTest = false;
198        return FAILED;
199     }
200
201     parentThread = appThread;
202
203     initialPreparation(parentThread);
204     /* ok, do the fork */;
205     parentThread->continueExecution();
206
207     /* the rest of the execution occurs in postForkFunc() */
208     /* Secondary test: we should not have to manually continue
209        either parent or child at any point */
210
211     while ( !parentThread->isTerminated() ) 
212     {
213        bpatch->waitForStatusChange();
214     }
215
216     // At this point if childThread == NULL the postfork handler failed
217     // to run.  Fail gracefully instead of segfaulting on 
218     // childThread->isTerminated()
219     if (doError(&passedTest, childThread == NULL,
220              "childThread == NULL: postForkFunc must not have run\n") )
221     {
222        return FAILED;
223     }
224     
225     while ( !childThread->isTerminated() )
226     {
227        bpatch->waitForStatusChange();
228     }
229
230     if (passedTest) {
231       return PASSED;
232     } else {
233       return FAILED;
234     }
235 }
236
237 test_results_t test_fork_5_Mutator::executeTest() {
238   // initialize global variables
239   parentDone = false;
240   childDone = false;
241   passedTest = true;
242   parentThread = NULL;
243   childThread = NULL;
244   msgid = -1;
245
246   // Register callbacks
247   bpatch->registerPostForkCallback(postForkFunc);
248   bpatch->registerExitCallback(exitFunc);
249
250   test_results_t result = mutatorTest(bpatch, appThread);
251
252   // Remove callbacks upon test completion
253   bpatch->registerPostForkCallback(NULL);
254   bpatch->registerExitCallback(NULL);
255
256   if (FAILED == result) {
257     logerror("Failed test_fork_5 (Delete snippet in parent)\n");
258   } else { // Assuming PASSED rather than SKIPPED
259     logerror("Passed test_fork_5 (Delete snippet in parent)\n");
260   }
261   return result;
262 }
263
264 // extern "C" int test7_1_mutatorMAIN(ParameterDict &param)
265 test_results_t test_fork_5_Mutator::setup(ParameterDict &param) {
266 #ifdef os_windows_test
267   return SKIPPED;
268 #else
269   bpatch = (BPatch *)(param["bpatch"]->getPtr());
270   appThread = (BPatch_thread *)(param["appThread"]->getPtr());
271
272   return PASSED;
273 #endif
274 }