Update copyright to LGPL on all files
[dyninst.git] / testsuite / src / dyninst / test3_7.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: test3_7.C,v 1.1 2008/10/30 19:20:45 legendre Exp $
33 /*
34  * #Name: test3_7
35  * #Desc: Tests asynchronous one-time codes
36  * #Dep: 
37  * #Arch:
38  * #Notes:useAttach does not apply
39  */
40
41 #include "BPatch.h"
42 #include "BPatch_Vector.h"
43 #include "BPatch_thread.h"
44 #include "BPatch_snippet.h"
45
46 #include "test_lib.h"
47 //#include "test3.h"
48
49 #define MAX_MUTATEES    32
50 #define Mutatees                3
51
52 #include "dyninst_comp.h"
53 class test3_7_Mutator : public DyninstMutator {
54   BPatch_exitType expectedSignal;
55   int debugPrint;
56   char *pathname;
57   BPatch *bpatch;
58   const unsigned int TIMEOUT; // Timeout in seconds
59
60 public:
61   test3_7_Mutator();
62   virtual bool hasCustomExecutionPath() { return true; }
63   virtual test_results_t setup(ParameterDict &param);
64   virtual test_results_t executeTest();
65 };
66 extern "C" DLLEXPORT  TestMutator *test3_7_factory() {
67   return new test3_7_Mutator();
68 }
69
70 test3_7_Mutator::test3_7_Mutator()
71   : pathname(NULL), bpatch(NULL), TIMEOUT(120) {
72 #if defined(os_windows_test)
73   expectedSignal = ExitedNormally;
74 #else
75   expectedSignal = ExitedViaSignal;
76 #endif
77 }
78
79 static unsigned int num_callbacks_issued = 0;
80
81 #if defined (os_osf_test)
82 #define TEST7_NUM_ONETIMECODE 100
83 #else
84 #define TEST7_NUM_ONETIMECODE 400
85 #endif
86
87 static void test7_oneTimeCodeCallback(BPatch_thread * /*thread*/,
88                                 void *userData,
89                                 void * /*returnValue*/)
90 {
91   dprintf("%s[%d]:  inside oneTimeCode callback\n", __FILE__, __LINE__);
92   num_callbacks_issued++;
93   if (num_callbacks_issued == TEST7_NUM_ONETIMECODE) {
94     *((bool *)userData) = true; // we are done
95   }
96 }
97
98 //
99 // Start Test Case #7 - create processes and process events from each
100 //     Run a whole ton of asynchronous OneTimeCodes to test signal handling
101 //
102
103 // static int mutatorTest(char *pathname, BPatch *bpatch)
104 test_results_t test3_7_Mutator::executeTest() {
105     unsigned int n=0;
106     const char *child_argv[5];
107     child_argv[n++] = pathname;
108     if (debugPrint) child_argv[n++] = const_cast<char*>("-verbose");
109     child_argv[n++] = const_cast<char*>("-run");
110     child_argv[n++] = const_cast<char*>("test3_7"); // run test1 in mutatee
111     child_argv[n++] = NULL;
112
113     BPatch_thread *appThread[MAX_MUTATEES];
114
115     for (n=0; n<MAX_MUTATEES; n++) appThread[n]=NULL;
116
117     num_callbacks_issued = 0;
118
119     // Start the mutatees
120     for (n=0; n<Mutatees; n++) {
121         dprintf("Starting \"%s\" %d/%d\n", pathname, n, Mutatees);
122         appThread[n] = bpatch->createProcess(pathname, child_argv, NULL);
123         if (!appThread[n]) {
124             logerror("*ERROR*: unable to create handle%d for executable\n", n);
125             logerror("**Failed** test #7 (simultaneous multiple-process management - oneTimeCode)\n");
126                         if( n > 0 ) {
127                                 MopUpMutatees(n-1,appThread);
128                         }
129             return FAILED;
130         }
131         dprintf("Mutatee %d started, pid=%d\n", n, appThread[n]->getPid());
132         // Register for cleanup
133         registerPID(appThread[n]->getProcess()->getPid());
134     }
135
136         // Register a callback that we will use to check for done-ness
137     BPatchOneTimeCodeCallback oldCallback =
138         bpatch->registerOneTimeCodeCallback(test7_oneTimeCodeCallback);
139
140     dprintf("Letting mutatee processes run a short while (2s).\n");
141     for (n=0; n<Mutatees; n++) appThread[n]->continueExecution();
142
143    ////////////////////////////
144    ////////////////////////////
145
146     //  our oneTimeCode will just be a simple call to a function that increments a global variable
147     BPatch_snippet *irpcSnippets[Mutatees];
148
149     // Build snippets for each mutatee
150     for (unsigned i = 0; i < Mutatees; i++) {
151       BPatch_image *appImage = appThread[i]->getImage();
152       //  our oneTimeCode will just be a simple call to a function that increment
153       BPatch_Vector<BPatch_function *> bpfv;
154       char *funcname = "test3_7_call1";
155       if (NULL == appImage->findFunction(funcname, bpfv) || !bpfv.size()
156           || NULL == bpfv[0]){
157         logerror("    Unable to find function %s\n", funcname);
158         exit(1);
159       }
160       BPatch_function *call7_1 = bpfv[0];
161
162       BPatch_Vector<BPatch_snippet *> nullArgs;
163       BPatch_funcCallExpr *call7_1_snip = new BPatch_funcCallExpr(*call7_1, nullArgs);
164       irpcSnippets[i] = call7_1_snip;
165         }
166
167     dprintf("Pausing apps pre-iRPC...\n");
168     for (n=0; n<Mutatees; n++) appThread[n]->stopExecution();
169
170         //  Submit inferior RPCs to all of our mutatees equally...
171     unsigned doneFlag = 0;
172     for (unsigned int i = 0; i < TEST7_NUM_ONETIMECODE; ++i) {
173       int index = i % (Mutatees);
174       dprintf("%s[%d]:  issuing oneTimeCode to thread %d\n", __FILE__, __LINE__, index);
175       appThread[index]->oneTimeCodeAsync(*(irpcSnippets[index]), (void *)&doneFlag);
176     }
177
178     dprintf("Running mutatees post-iRPC...\n");
179     for (n=0; n<Mutatees; n++) appThread[n]->continueExecution();
180
181    ////////////////////////////
182    ////////////////////////////
183
184    // and wait for completion/timeout
185    int timeout = 0;
186    while (!doneFlag && (timeout < TIMEOUT)) {
187      P_sleep(1);
188      bpatch->pollForStatusChange();
189      timeout++;
190    }
191    int test7err = false;
192    if (!doneFlag) {
193             logerror("**Failed** test #7 (simultaneous multiple-process management - oneTimeCode)\n");
194             logerror("   did not receive the right # of events: got %d, expected %d\n", num_callbacks_issued, TEST7_NUM_ONETIMECODE);
195             test7err = true;
196    }
197
198     dprintf("Terminating mutatee processes.\n");
199
200
201     unsigned int numTerminated=0;
202     for (n=0; n<Mutatees; n++) {
203         bool dead = appThread[n]->terminateExecution();
204         if (!dead || !(appThread[n]->isTerminated())) {
205             logerror("**Failed** test #7 (simultaneous multiple-process management - oneTimeCode)\n");
206             logerror("    mutatee process [%d] was not terminated\n", n);
207             continue;
208         }
209         if(appThread[n]->terminationStatus() != expectedSignal) {
210             logerror("**Failed** test #7 (simultaneous multiple-process management - oneTimeCode)\n");
211             logerror("    mutatee process [%d] didn't get notice of termination\n", n);
212             continue;
213         }
214         int signalNum = appThread[n]->getExitSignal();
215         dprintf("Terminated mutatee [%d] from signal 0x%x\n", n, signalNum);
216         numTerminated++;
217     }
218
219     if (numTerminated == Mutatees && !test7err) {
220         logerror("Passed Test #7 (simultaneous multiple-process management - oneTimeCode)\n");
221         return PASSED;
222     }
223
224     return FAILED;
225 }
226
227 // extern "C" TEST_DLL_EXPORT int test3_7_mutatorMAIN(ParameterDict &param)
228 test_results_t test3_7_Mutator::setup(ParameterDict &param) {
229     pathname = param["pathname"]->getString();
230     bpatch = (BPatch *)(param["bpatch"]->getPtr());
231     debugPrint = param["debugPrint"]->getInt();
232
233 #if defined (sparc_sun_solaris2_4_test)
234     // we use some unsafe type operations in the test cases.
235     bpatch->setTypeChecking(false);
236 #endif
237     
238     return PASSED;
239 }