Added some more #ifdef BPATCH_LIBRARYs to eliminate some Dyninst API
[dyninst.git] / dyninstAPI / tests / src / test2.C
1
2 //
3 //
4 // libdyninst validation suite test #2
5 //    Author: Jeff Hollingsworth (7/10/97)
6 //
7
8 //  This program tests the error features of the dyninst API.  
9 //      The mutatee that goes with this file is test2.mutatee.c
10 //      
11 //  Naming conventions:
12 //      All functions, variables, etc are name funcXX_YY, exprXX_YY, etc.
13 //          XX is the test number
14 //          YY is the instance withing the test
15 //          func1_2 is the second function used in test case #1.
16 //
17
18 #include <stdio.h>
19 #include <signal.h>
20 #include <string.h>
21 #ifdef i386_unknown_nt4_0
22 #include <io.h>
23 #define WIN32_LEAN_AND_MEAN
24 #include <windows.h>
25 #else
26 #include <unistd.h>
27 #endif
28
29 #include "BPatch.h"
30 #include "BPatch_Vector.h"
31 #include "BPatch_thread.h"
32 #include "BPatch_snippet.h"
33 #include "test_util.h"
34 #include "test2.h"
35
36 #ifdef i386_unknown_nt4_0
37 #define access _access
38 #define unlink _unlink
39 #define F_OK 0
40 #endif
41
42 #ifdef i386_unknown_nt4_0
43 #define MUTATEE_NAME    "test2.mutatee.exe"
44 #else
45 #define MUTATEE_NAME    "./test2.mutatee"
46 #endif
47
48 int debugPrint = 0;
49 bool expectErrors = false;
50 bool gotError = false;
51
52 BPatch *bpatch;
53
54 // control debug printf statements
55 #define dprintf if (debugPrint) printf
56
57 BPatch_thread *mutatorMAIN(char *pathname, bool useAttach)
58 {
59     BPatch_thread *appThread;
60
61     // Start the mutatee
62     printf("Starting \"%s\"\n", pathname);
63
64     char *child_argv[4];
65    
66     int n = 0;
67     child_argv[n++] = pathname;
68     if (useAttach) child_argv[n++] = "-attach";
69     if (debugPrint) child_argv[n++] = "-verbose";
70     child_argv[n] = NULL;
71
72     if (useAttach) {
73         int pid = startNewProcess(pathname, child_argv);
74         if (pid < 0 && !expectErrors) {
75             printf("*ERROR*: unable to start tests due to error starting mutatee process\n");
76             exit(-1);
77         }
78         appThread = bpatch->attachProcess(pathname, pid);
79     } else {
80         appThread = bpatch->createProcess(pathname, child_argv);
81     }
82     return appThread;
83 }
84
85 void errorFunc(BPatchErrorLevel level, int num, const char **params)
86 {
87     char line[256];
88
89     const char *msg = bpatch->getEnglishErrorString(num);
90     bpatch->formatErrorString(line, sizeof(line), msg, params);
91
92     gotError = true;
93
94     if (expectErrors) {
95         if (debugPrint)
96             printf("Error (expected) #%d (level %d): %s\n", num, level, line);
97     } else {
98         printf("Error #%d (level %d): %s\n", num, level, line);
99     }
100 }
101
102 //
103 // main - decide our role and call the correct "main"
104 //
105 main(int argc, char *argv[])
106 {
107     BPatch_thread *ret;
108     bool useAttach = false;
109     bool failed = false;
110
111     // Create an instance of the bpatch library
112     bpatch = new BPatch;
113
114     bpatch->registerErrorCallback(errorFunc);
115
116     int i;
117     for (i=1; i < argc; i++) {
118         if (!strcmp(argv[i], "-verbose")) {
119             debugPrint = 1;
120         } else if (!strcmp(argv[i], "-attach")) {
121             useAttach = true;
122         } else {
123             fprintf(stderr, "Usage: test1 [-attach] [-verbose]\n");
124             exit(-1);
125         }
126     }
127
128 #if defined(sparc_sun_sunos4_1_3) || defined(rs6000_ibm_aix4_1)
129     if (useAttach) {
130         printf("Attach is not supported on this platform.\n");
131         exit(1);
132     }
133 #endif
134
135     // Try failure cases
136     expectErrors = true;
137
138     if (useAttach) {
139         printf("Skipping test #1 (run an executable that does not exist)\n");
140         printf("    not relevant with -attach option\n");
141     } else {
142         // try to run a program that does not exist
143         gotError = false;
144         ret = mutatorMAIN("./noSuchFile", useAttach);
145         if (ret || !gotError) {
146             failed = true;
147             printf("**Failed** test #1 (run an executable that does not exist)\n");
148             if (ret)
149                 printf("    created a thread handle for a non-existant file\n");
150             if (!gotError)
151                 printf("    the error callback should have been called but wasn't\n");
152         } else {
153             printf("Passed test #1 (run an executable that does not exist)\n");
154         }
155     }
156
157     // try to run a files that is not a valid program
158     gotError = false;
159 #ifdef i386_unknown_nt4_0
160     ret = mutatorMAIN("nul:", false);
161 #else
162     ret = mutatorMAIN("/dev/null", false);
163 #endif
164     if (ret || !gotError) {
165         printf("**Failed** test #2 (try to execute a file that is not a valid program)\n");
166         failed = true;
167         if (ret)
168             printf("    created a thread handle for invalid executable\n");
169         if (!gotError)
170             printf("    the error callback should have been called but wasn't\n");
171     } else {
172         printf("Passed test #2 (try to execute a file that is not a valid program)\n");
173     }
174
175 #if defined(sparc_sun_sunos4_1_3) || defined(rs6000_ibm_aix4_1)
176     printf("Skipping test #3 (attach to an invalid pid)\n");
177     printf("Skipping test #4 (attach to a protected pid)\n");
178     printf("    attach is not supported on this platform\n");
179 #else
180     // attach to an an invalid pid
181     gotError = false;
182     ret = bpatch->attachProcess(MUTATEE_NAME, 65539);
183     if (ret || !gotError) {
184         printf("**Failed** test #3 (attach to an invalid pid)\n");
185         failed = true;
186         if (ret)
187             printf("    created a thread handle for invalid executable\n");
188         if (!gotError)
189             printf("    the error callback should have been called but wasn't\n");
190     } else {
191         printf("Passed test #3 (attach to an invalid pid)\n");
192     }
193
194     // attach to an a protected pid
195     gotError = false;
196     ret = bpatch->attachProcess(MUTATEE_NAME, 1);
197     if (ret || !gotError) {
198         printf("**Failed** test #4 (attach to a protected pid)\n");
199         failed = true;
200         if (ret)
201             printf("    created a thread handle for invalid executable\n");
202         if (!gotError)
203             printf("    the error callback should have been called but wasn't\n");
204     } else {
205         printf("Passed test #4 (attach to a protected pid)\n");
206     }
207 #endif
208
209     // Finished trying failure cases
210     expectErrors = false;
211
212     // now start a real program
213     gotError = false;
214     ret = mutatorMAIN(MUTATEE_NAME, false);
215     if (!ret || gotError) {
216         printf("*ERROR*: unable to create handle for executable\n");
217         failed = true;
218     }
219
220     BPatch_image *img = ret->getImage();
221
222     gotError = false;
223     BPatch_function *func = img->findFunction("NoSuchFunction");
224     if (func || !gotError) {
225         printf("**Failed** test #5 (look up nonexistent function)\n");
226         failed = true;
227         if (func)
228             printf("    non-null for findFunction on non-existant func\n");
229         if (!gotError)
230             printf("    the error callback should have been called but wasn't\n");
231     } else {
232         printf("Passed test #5 (look up nonexistent function)\n");
233     }
234
235     ret->continueExecution();
236
237 #ifndef sparc_sun_solaris2_4
238     printf("Skipping test #6 (load a dynamically linked library)\n");
239     printf("    feature not implemented on this platform\n");
240 #else
241     waitUntilStopped(ret, 6, "load a dynamically linked library");
242
243     // see if the dlopen happended.
244     bool found = false;
245     BPatch_Vector<BPatch_module *> *m = img->getModules();
246     for (i=0; i < m->size(); i++) {
247             char name[80];
248             (*m)[i]->getName(name, sizeof(name));
249             if (strcmp(name, TEST_DYNAMIC_LIB) == 0) {
250                 found = true;
251                 break;
252             }
253     }
254     if (found) {
255         printf("Passed test #6 (load a dynamically linked library)\n");
256     } else {
257         printf("**Failed** test #6 (load a dynamically linked library)\n");
258         printf("    image::getModules() did not indicate that the library had been loaded\n");
259         failed = true;
260     }
261
262     ret->continueExecution();
263 #endif
264
265     ret->stopExecution();
266
267     // dump core, but do not terminate.
268     // this doesn't seem to do anything - jkh 7/12/97
269     if (access("mycore", F_OK) == 0) {
270         printf("File \"mycore\" exists.  Deleting it.\n");
271         if (unlink("mycore") != 0) {
272             printf("Couldn't delete the file \"mycore\".  Exiting.\n");
273             exit(-1);
274         }
275     }
276
277 #ifndef sparc_sun_sunos4_1_3
278     printf("Skipping test #7 (dump core but do not terminate)\n");
279     printf("    BPatch_thread::dumpCore() not implemented on this platform\n");
280 #else
281     gotError = false;
282     ret->dumpCore("mycore", true);
283     bool coreExists = (access("mycore", F_OK) == 0);
284     if (gotError || !coreExists) {
285         printf("**Failed** test #7 (dump core but do not terminate)\n");
286         failed = true;
287         if (gotError)
288             printf("    error reported by dumpCore\n");
289         if (!coreExists)
290             printf("    the core file wasn't written\n");
291     } else {
292         printf("Passed test #7 (dump core but do not terminate)\n");
293     }
294 #endif
295
296     int pid = ret->getPid();
297
298 #ifndef i386_unknown_nt4_0 /* Not yet implemented on NT. */
299     // detach from the process.
300     ret->detach(true);
301 #endif
302
303     // now kill the process.
304 #ifdef i386_unknown_nt4_0
305     HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
306     if (h != NULL) {
307         TerminateProcess(h, 0);
308         CloseHandle(h);
309     }
310 #else
311     kill(pid, SIGKILL);
312 #endif
313
314     delete (ret);
315     BPatch_Vector<BPatch_thread *> *threads = bpatch->getThreads();
316     for (i=0; i < threads->size(); i++) {
317         if ((*threads)[i] == ret) {
318             printf("**Failed** test #7 (delete thread)\n");
319             printf("    thread %d was deleted, but getThreads found it\n",
320                 ret->getPid());
321             failed = true;
322         }
323     }
324
325     delete (bpatch);
326
327     if (failed) {
328         printf("**Failed** tests\n");
329     } else {
330         printf("Passed all tests\n");
331     }
332
333
334     return 0;
335 }