xref: /aosp_15_r20/external/google-breakpad/src/client/mac/testapp/Controller.m (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle// Copyright 2006 Google LLC
2*9712c20fSFrederick Mayle//
3*9712c20fSFrederick Mayle// Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle// modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle// met:
6*9712c20fSFrederick Mayle//
7*9712c20fSFrederick Mayle//     * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle// notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle//     * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle// copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle// in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle// distribution.
13*9712c20fSFrederick Mayle//     * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle// contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle// this software without specific prior written permission.
16*9712c20fSFrederick Mayle//
17*9712c20fSFrederick Mayle// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle
29*9712c20fSFrederick Mayle#import <Breakpad/Breakpad.h>
30*9712c20fSFrederick Mayle
31*9712c20fSFrederick Mayle#import "Controller.h"
32*9712c20fSFrederick Mayle#import "TestClass.h"
33*9712c20fSFrederick Mayle#import "GTMDefines.h"
34*9712c20fSFrederick Mayle#include <unistd.h>
35*9712c20fSFrederick Mayle#include <mach/mach.h>
36*9712c20fSFrederick Mayle
37*9712c20fSFrederick Mayle@implementation Controller
38*9712c20fSFrederick Mayle
39*9712c20fSFrederick Mayle- (void)causeCrash {
40*9712c20fSFrederick Mayle  float *aPtr = nil;
41*9712c20fSFrederick Mayle  NSLog(@"Crash!");
42*9712c20fSFrederick Mayle  NSLog(@"Bad programmer: %f", *aPtr);
43*9712c20fSFrederick Mayle}
44*9712c20fSFrederick Mayle
45*9712c20fSFrederick Mayle- (void)generateReportWithoutCrash:(id)sender {
46*9712c20fSFrederick Mayle  BreakpadGenerateAndSendReport(breakpad_);
47*9712c20fSFrederick Mayle}
48*9712c20fSFrederick Mayle
49*9712c20fSFrederick Mayle- (IBAction)showForkTestWindow:(id) sender {
50*9712c20fSFrederick Mayle  [forkTestOptions_ setIsVisible:YES];
51*9712c20fSFrederick Mayle}
52*9712c20fSFrederick Mayle
53*9712c20fSFrederick Mayle- (IBAction)forkTestOptions:(id)sender {
54*9712c20fSFrederick Mayle  NSInteger tag = [[sender selectedCell] tag];
55*9712c20fSFrederick Mayle  NSLog(@"sender tag: %d", tag);
56*9712c20fSFrederick Mayle  if (tag <= 2) {
57*9712c20fSFrederick Mayle    bpForkOption = tag;
58*9712c20fSFrederick Mayle  }
59*9712c20fSFrederick Mayle
60*9712c20fSFrederick Mayle  if (tag == 3) {
61*9712c20fSFrederick Mayle    useVFork = NO;
62*9712c20fSFrederick Mayle  }
63*9712c20fSFrederick Mayle
64*9712c20fSFrederick Mayle  if (tag == 4) {
65*9712c20fSFrederick Mayle    useVFork = YES;
66*9712c20fSFrederick Mayle  }
67*9712c20fSFrederick Mayle
68*9712c20fSFrederick Mayle  if (tag >= 5 && tag <= 7) {
69*9712c20fSFrederick Mayle    progCrashPoint = tag;
70*9712c20fSFrederick Mayle  }
71*9712c20fSFrederick Mayle
72*9712c20fSFrederick Mayle}
73*9712c20fSFrederick Mayle
74*9712c20fSFrederick Mayle- (IBAction)forkTestGo:(id)sender {
75*9712c20fSFrederick Mayle
76*9712c20fSFrederick Mayle  NSString *resourcePath = [[NSBundle bundleForClass:
77*9712c20fSFrederick Mayle                                        [self class]] resourcePath];
78*9712c20fSFrederick Mayle  NSString *execProgname = nil;
79*9712c20fSFrederick Mayle  if (progCrashPoint == DURINGLAUNCH) {
80*9712c20fSFrederick Mayle    execProgname = [resourcePath stringByAppendingString:@"/crashduringload"];
81*9712c20fSFrederick Mayle  } else if (progCrashPoint == AFTERLAUNCH) {
82*9712c20fSFrederick Mayle    execProgname = [resourcePath stringByAppendingString:@"/crashInMain"];
83*9712c20fSFrederick Mayle  }
84*9712c20fSFrederick Mayle
85*9712c20fSFrederick Mayle  const char *progName = NULL;
86*9712c20fSFrederick Mayle  if (progCrashPoint != BETWEENFORKEXEC) {
87*9712c20fSFrederick Mayle    progName = [execProgname UTF8String];
88*9712c20fSFrederick Mayle  }
89*9712c20fSFrederick Mayle
90*9712c20fSFrederick Mayle  int pid;
91*9712c20fSFrederick Mayle
92*9712c20fSFrederick Mayle  if (bpForkOption == UNINSTALL) {
93*9712c20fSFrederick Mayle    BreakpadRelease(breakpad_);
94*9712c20fSFrederick Mayle  }
95*9712c20fSFrederick Mayle
96*9712c20fSFrederick Mayle  if (useVFork) {
97*9712c20fSFrederick Mayle    pid = vfork();
98*9712c20fSFrederick Mayle  } else {
99*9712c20fSFrederick Mayle    pid = fork();
100*9712c20fSFrederick Mayle  }
101*9712c20fSFrederick Mayle
102*9712c20fSFrederick Mayle  if (pid == 0) {
103*9712c20fSFrederick Mayle    sleep(3);
104*9712c20fSFrederick Mayle    NSLog(@"Child continuing");
105*9712c20fSFrederick Mayle    FILE *fd = fopen("/tmp/childlog.txt","wt");
106*9712c20fSFrederick Mayle    kern_return_t kr;
107*9712c20fSFrederick Mayle    if (bpForkOption == RESETEXCEPTIONPORT) {
108*9712c20fSFrederick Mayle      kr = task_set_exception_ports(mach_task_self(),
109*9712c20fSFrederick Mayle                               EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION |
110*9712c20fSFrederick Mayle                               EXC_MASK_ARITHMETIC | EXC_MASK_BREAKPOINT,
111*9712c20fSFrederick Mayle                               MACH_PORT_NULL,
112*9712c20fSFrederick Mayle                               EXCEPTION_DEFAULT,
113*9712c20fSFrederick Mayle                               THREAD_STATE_NONE);
114*9712c20fSFrederick Mayle      fprintf(fd,"task_set_exception_ports returned %d\n", kr);
115*9712c20fSFrederick Mayle    }
116*9712c20fSFrederick Mayle
117*9712c20fSFrederick Mayle    if (progCrashPoint == BETWEENFORKEXEC) {
118*9712c20fSFrederick Mayle      fprintf(fd,"crashing post-fork\n");
119*9712c20fSFrederick Mayle      int *a = NULL;
120*9712c20fSFrederick Mayle      printf("%d\n",*a++);
121*9712c20fSFrederick Mayle    }
122*9712c20fSFrederick Mayle
123*9712c20fSFrederick Mayle    fprintf(fd,"about to call exec with %s\n", progName);
124*9712c20fSFrederick Mayle    fclose(fd);
125*9712c20fSFrederick Mayle    int i = execl(progName, progName, NULL);
126*9712c20fSFrederick Mayle    fprintf(fd, "exec returned! %d\n", i);
127*9712c20fSFrederick Mayle    fclose(fd);
128*9712c20fSFrederick Mayle  }
129*9712c20fSFrederick Mayle}
130*9712c20fSFrederick Mayle
131*9712c20fSFrederick Mayle- (IBAction)crash:(id)sender {
132*9712c20fSFrederick Mayle  NSInteger tag = [sender tag];
133*9712c20fSFrederick Mayle
134*9712c20fSFrederick Mayle  if (tag == 1) {
135*9712c20fSFrederick Mayle    [NSObject cancelPreviousPerformRequestsWithTarget:self];
136*9712c20fSFrederick Mayle    [self performSelector:@selector(causeCrash) withObject:nil afterDelay:10.0];
137*9712c20fSFrederick Mayle    [sender setState:NSOnState];
138*9712c20fSFrederick Mayle    return;
139*9712c20fSFrederick Mayle  }
140*9712c20fSFrederick Mayle
141*9712c20fSFrederick Mayle  if (tag == 2 && breakpad_) {
142*9712c20fSFrederick Mayle    BreakpadRelease(breakpad_);
143*9712c20fSFrederick Mayle    breakpad_ = NULL;
144*9712c20fSFrederick Mayle    return;
145*9712c20fSFrederick Mayle  }
146*9712c20fSFrederick Mayle
147*9712c20fSFrederick Mayle  [self causeCrash];
148*9712c20fSFrederick Mayle}
149*9712c20fSFrederick Mayle
150*9712c20fSFrederick Mayle- (void)anotherThread {
151*9712c20fSFrederick Mayle  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
152*9712c20fSFrederick Mayle  TestClass *tc = [[TestClass alloc] init];
153*9712c20fSFrederick Mayle
154*9712c20fSFrederick Mayle  [tc wait];
155*9712c20fSFrederick Mayle
156*9712c20fSFrederick Mayle  [pool release];
157*9712c20fSFrederick Mayle}
158*9712c20fSFrederick Mayle
159*9712c20fSFrederick Mayle- (void)awakeFromNib {
160*9712c20fSFrederick Mayle  NSBundle *bundle = [NSBundle mainBundle];
161*9712c20fSFrederick Mayle  NSDictionary *info = [bundle infoDictionary];
162*9712c20fSFrederick Mayle
163*9712c20fSFrederick Mayle
164*9712c20fSFrederick Mayle  breakpad_ = BreakpadCreate(info);
165*9712c20fSFrederick Mayle
166*9712c20fSFrederick Mayle  // Do some unit tests with keys
167*9712c20fSFrederick Mayle  // first a series of bogus values
168*9712c20fSFrederick Mayle  BreakpadSetKeyValue(breakpad_, nil, @"bad2");
169*9712c20fSFrederick Mayle  BreakpadSetKeyValue(nil, @"bad3", @"bad3");
170*9712c20fSFrederick Mayle
171*9712c20fSFrederick Mayle  // Now some good ones
172*9712c20fSFrederick Mayle  BreakpadSetKeyValue(breakpad_,@"key1", @"value1");
173*9712c20fSFrederick Mayle  BreakpadSetKeyValue(breakpad_,@"key2", @"value2");
174*9712c20fSFrederick Mayle  BreakpadSetKeyValue(breakpad_,@"key3", @"value3");
175*9712c20fSFrederick Mayle
176*9712c20fSFrederick Mayle  // Look for a bogus one that we didn't try to set
177*9712c20fSFrederick Mayle  NSString *test = BreakpadKeyValue(breakpad_, @"bad4");
178*9712c20fSFrederick Mayle  if (test) {
179*9712c20fSFrederick Mayle    NSLog(@"Bad BreakpadKeyValue (bad4)");
180*9712c20fSFrederick Mayle  }
181*9712c20fSFrederick Mayle
182*9712c20fSFrederick Mayle  // Look for a bogus one we did try to set
183*9712c20fSFrederick Mayle  test = BreakpadKeyValue(breakpad_, @"bad1");
184*9712c20fSFrederick Mayle  if (test) {
185*9712c20fSFrederick Mayle    NSLog(@"Bad BreakpadKeyValue (bad1)");
186*9712c20fSFrederick Mayle  }
187*9712c20fSFrederick Mayle
188*9712c20fSFrederick Mayle  // Test some bad args for BreakpadKeyValue
189*9712c20fSFrederick Mayle  test = BreakpadKeyValue(nil, @"bad5");
190*9712c20fSFrederick Mayle  if (test) {
191*9712c20fSFrederick Mayle    NSLog(@"Bad BreakpadKeyValue (bad5)");
192*9712c20fSFrederick Mayle  }
193*9712c20fSFrederick Mayle
194*9712c20fSFrederick Mayle  test = BreakpadKeyValue(breakpad_, nil);
195*9712c20fSFrederick Mayle  if (test) {
196*9712c20fSFrederick Mayle    NSLog(@"Bad BreakpadKeyValue (nil)");
197*9712c20fSFrederick Mayle  }
198*9712c20fSFrederick Mayle
199*9712c20fSFrederick Mayle  // Find some we did set
200*9712c20fSFrederick Mayle  test = BreakpadKeyValue(breakpad_, @"key1");
201*9712c20fSFrederick Mayle  if (![test isEqualToString:@"value1"]) {
202*9712c20fSFrederick Mayle    NSLog(@"Can't find BreakpadKeyValue (key1)");
203*9712c20fSFrederick Mayle  }
204*9712c20fSFrederick Mayle  test = BreakpadKeyValue(breakpad_, @"key2");
205*9712c20fSFrederick Mayle  if (![test isEqualToString:@"value2"]) {
206*9712c20fSFrederick Mayle    NSLog(@"Can't find BreakpadKeyValue (key2)");
207*9712c20fSFrederick Mayle  }
208*9712c20fSFrederick Mayle  test = BreakpadKeyValue(breakpad_, @"key3");
209*9712c20fSFrederick Mayle  if (![test isEqualToString:@"value3"]) {
210*9712c20fSFrederick Mayle    NSLog(@"Can't find BreakpadKeyValue (key3)");
211*9712c20fSFrederick Mayle  }
212*9712c20fSFrederick Mayle
213*9712c20fSFrederick Mayle  // Bad args for BreakpadRemoveKeyValue
214*9712c20fSFrederick Mayle  BreakpadRemoveKeyValue(nil, @"bad6");
215*9712c20fSFrederick Mayle  BreakpadRemoveKeyValue(breakpad_, nil);
216*9712c20fSFrederick Mayle
217*9712c20fSFrederick Mayle  // Remove one that is valid
218*9712c20fSFrederick Mayle  BreakpadRemoveKeyValue(breakpad_, @"key3");
219*9712c20fSFrederick Mayle
220*9712c20fSFrederick Mayle  // Try and find it
221*9712c20fSFrederick Mayle  test = BreakpadKeyValue(breakpad_, @"key3");
222*9712c20fSFrederick Mayle  if (test) {
223*9712c20fSFrederick Mayle    NSLog(@"Shouldn't find BreakpadKeyValue (key3)");
224*9712c20fSFrederick Mayle  }
225*9712c20fSFrederick Mayle
226*9712c20fSFrederick Mayle  // Try and remove it again
227*9712c20fSFrederick Mayle  BreakpadRemoveKeyValue(breakpad_, @"key3");
228*9712c20fSFrederick Mayle
229*9712c20fSFrederick Mayle  // Try removal by setting to nil
230*9712c20fSFrederick Mayle  BreakpadSetKeyValue(breakpad_,@"key2", nil);
231*9712c20fSFrederick Mayle  // Try and find it
232*9712c20fSFrederick Mayle  test = BreakpadKeyValue(breakpad_, @"key2");
233*9712c20fSFrederick Mayle  if (test) {
234*9712c20fSFrederick Mayle    NSLog(@"Shouldn't find BreakpadKeyValue (key2)");
235*9712c20fSFrederick Mayle  }
236*9712c20fSFrederick Mayle
237*9712c20fSFrederick Mayle  BreakpadAddUploadParameter(breakpad_,
238*9712c20fSFrederick Mayle                             @"MeaningOfLife",
239*9712c20fSFrederick Mayle                             @"42");
240*9712c20fSFrederick Mayle  [NSThread detachNewThreadSelector:@selector(anotherThread)
241*9712c20fSFrederick Mayle                           toTarget:self withObject:nil];
242*9712c20fSFrederick Mayle
243*9712c20fSFrederick Mayle  NSUserDefaults *args = [NSUserDefaults standardUserDefaults];
244*9712c20fSFrederick Mayle
245*9712c20fSFrederick Mayle  // If the user specified autocrash on the command line, toggle
246*9712c20fSFrederick Mayle  // Breakpad to not confirm and crash immediately.  This is for
247*9712c20fSFrederick Mayle  // automated testing.
248*9712c20fSFrederick Mayle  if ([args boolForKey:@"autocrash"]) {
249*9712c20fSFrederick Mayle    BreakpadSetKeyValue(breakpad_,
250*9712c20fSFrederick Mayle                        @BREAKPAD_SKIP_CONFIRM,
251*9712c20fSFrederick Mayle                        @"YES");
252*9712c20fSFrederick Mayle    [self causeCrash];
253*9712c20fSFrederick Mayle  }
254*9712c20fSFrederick Mayle
255*9712c20fSFrederick Mayle  progCrashPoint = DURINGLAUNCH;
256*9712c20fSFrederick Mayle  [window_ center];
257*9712c20fSFrederick Mayle  [window_ makeKeyAndOrderFront:self];
258*9712c20fSFrederick Mayle}
259*9712c20fSFrederick Mayle
260*9712c20fSFrederick Mayle@end
261