Update copyright to LGPL on all files
[dyninst.git] / testsuite / src / dyninst / test_fork_10.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 // $Id: test_fork_10.C,v 1.1 2008/10/30 19:21:28 legendre Exp $
33 /*
34  * #Name: test7_6
35  * #Desc: OneTimeCode in parent & child
36  * #Arch: all
37  * #Dep: 
38  */
39
40 #include "BPatch.h"
41 #include "BPatch_Vector.h"
42 #include "BPatch_thread.h"
43 #include "BPatch_snippet.h"
44
45 #include "test_lib.h"
46 #include "test_lib_test7.h"
47
48 #include "dyninst_comp.h"
49 class test_fork_10_Mutator : public DyninstMutator {
50 private:
51   BPatch *bpatch;
52
53 public:
54   virtual bool hasCustomExecutionPath() { return true; }
55   virtual test_results_t setup(ParameterDict &param);
56   virtual test_results_t executeTest();
57 };
58 extern "C" DLLEXPORT TestMutator *test_fork_10_factory() {
59   return new test_fork_10_Mutator();
60 }
61
62 static bool parentDone;
63 static bool childDone;
64 static bool passedTest;
65 static BPatch_thread *parentThread;
66 static BPatch_thread *childThread;
67 static int msgid;
68
69 /* Run a oneTimeCode in both the parent and child and see if they both
70    happen.
71
72    parent/child: globalVariable7_6 initial value = 21
73
74    parent: run one time code, value += 5
75    child:  run one time code, value += 9
76    parent: value == 26
77    child:  value == 30
78 */
79
80 static void prepareTestCase6(procType proc_type, BPatch_thread *thread, forkWhen when)
81 {
82    if(proc_type == Parent_p  &&  when == PostFork) {
83       BPatch_image *parImage = thread->getImage();
84
85       BPatch_variableExpr *var7_6p = 
86          parImage->findVariable("test_fork_10_global1");
87       if(doError(&passedTest, (var7_6p==NULL),
88                  "  Unable to locate variable test_fork_10_global1\n")) return;
89
90       BPatch_arithExpr a_expr7_6p(BPatch_plus, *var7_6p, BPatch_constExpr(5));
91       BPatch_arithExpr b_expr7_6p(BPatch_assign, *var7_6p, a_expr7_6p);
92       thread->oneTimeCode(b_expr7_6p);
93       
94    } else if(proc_type == Child_p  &&  when == PostFork) {
95       BPatch_image *childImage = thread->getImage();
96
97       BPatch_variableExpr *var7_6c = 
98          childImage->findVariable("test_fork_10_global1");
99       if(doError(&passedTest, (var7_6c==NULL),
100                  "  Unable to locate variable test_fork_10_global1\n")) return;
101
102       BPatch_arithExpr a_expr7_6c(BPatch_plus, *var7_6c, BPatch_constExpr(9));
103       BPatch_arithExpr b_expr7_6c(BPatch_assign, *var7_6c, a_expr7_6c);
104       thread->oneTimeCode(b_expr7_6c);
105    }
106 }
107
108 static void checkTestCase6(procType proc_type, BPatch_thread *thread) {
109    if(proc_type == Parent_p) {
110       if(! verifyProcMemory(thread, "test_fork_10_global1", 26, proc_type)) {
111          passedTest = false;
112       }
113    } else if(proc_type == Child_p) {
114       if(! verifyProcMemory(thread, "test_fork_10_global1", 30, proc_type)) {
115          passedTest = false;
116       }
117    }
118 }
119
120
121
122 /* We make changes at post-fork */
123 static void postForkFunc(BPatch_thread *parent, BPatch_thread *child)
124 {
125     //dprintf("in postForkFunc\n");
126     /* For later identification */
127     childThread = child;
128     dprintf("Preparing tests on parent\n");
129     prepareTestCase6(Parent_p, parent, PostFork);
130     dprintf("Preparing tests on child\n");
131     prepareTestCase6(Child_p,  child,  PostFork);
132     dprintf("Fork handler finished (parent %p, child %p)\n", parent, child);
133 }
134
135 /* And verify them when they exit */
136 static void exitFunc(BPatch_thread *thread, BPatch_exitType exit_type) {
137     dprintf("Exit func called\n");
138     if (thread == parentThread) {
139         dprintf("Parent exit reached, checking...\n");
140         checkTestCase6(Parent_p, thread);
141         parentDone = true;
142         dprintf("Parent done\n");
143     }
144     else if (thread == childThread) {
145         dprintf("Child exit reached, checking...\n");
146         checkTestCase6(Child_p, thread);
147         dprintf("Child done\n");
148         childDone = true;
149     }
150     else {
151         dprintf("Thread ptr 0x%x, parent 0x%x, child 0x%x\n",
152                 thread, parentThread, childThread);
153         assert(0 && "Unexpected BPatch_thread in exitFunc");
154     }
155     return;
156 }
157
158 static void initialPreparation(BPatch_thread *parent)
159 {
160    //cerr << "in initialPreparation\n";
161    assert(parent->isStopped());
162
163    //cerr << "ok, inserting instr\n";
164    prepareTestCase6(Parent_p, parent, PreFork);
165 }
166
167 static int mutatorTest(BPatch *bpatch, BPatch_thread *appThread)
168 {
169     if ( !setupMessaging(&msgid) )
170     {
171        passedTest = false;
172        return passedTest;
173     }
174
175     parentThread = appThread;
176
177     initialPreparation(parentThread);
178     /* ok, do the fork */;
179     parentThread->continueExecution();
180
181     /* the rest of the execution occurs in postForkFunc() */
182     /* Secondary test: we should not have to manually continue
183        either parent or child at any point */
184
185     while ( !parentThread->isTerminated() ) 
186     {
187        bpatch->waitForStatusChange();
188     }
189
190     // At this point if childThread == NULL the postfork handler failed
191     // to run.  Fail gracefully instead of segfaulting on 
192     // childThread->isTerminated()
193     if (doError(&passedTest, childThread == NULL,
194              "childThread == NULL: postForkFunc must not have run\n") )
195     {
196        return passedTest;
197     }
198     
199     if ( !childThread->isTerminated() )
200     {
201        bpatch->waitForStatusChange();
202     }
203
204     return passedTest;
205 }
206
207 test_results_t test_fork_10_Mutator::executeTest() {
208   // Initialize global variables
209   parentDone = false;
210   childDone = false;
211   passedTest = true;
212   parentThread = NULL;
213   childThread = NULL;
214   msgid = -1;
215
216   // Register callbacks
217   bpatch->registerPostForkCallback(postForkFunc);
218   bpatch->registerExitCallback(exitFunc);
219
220   bool passed = mutatorTest(bpatch, appThread);
221
222   // Remove callbacks upon test completion
223   bpatch->registerPostForkCallback(NULL);
224   bpatch->registerExitCallback(NULL);
225
226   showFinalResults(passed, 6);
227   if ( passed )
228     return PASSED;
229   else
230     return FAILED;
231 }
232
233 // extern "C" int test7_6_mutatorMAIN(ParameterDict &param)
234 test_results_t test_fork_10_Mutator::setup(ParameterDict &param) {
235 #ifdef os_windows_test
236   return SKIPPED;
237 #else
238   bpatch = (BPatch *)(param["bpatch"]->getPtr());
239   appThread = (BPatch_thread *)(param["appThread"]->getPtr());
240   
241   return PASSED;
242 #endif
243 }