1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/Controller.m Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,261 @@ 1.4 +// Copyright (c) 2006, Google Inc. 1.5 +// All rights reserved. 1.6 +// 1.7 +// Redistribution and use in source and binary forms, with or without 1.8 +// modification, are permitted provided that the following conditions are 1.9 +// met: 1.10 +// 1.11 +// * Redistributions of source code must retain the above copyright 1.12 +// notice, this list of conditions and the following disclaimer. 1.13 +// * Redistributions in binary form must reproduce the above 1.14 +// copyright notice, this list of conditions and the following disclaimer 1.15 +// in the documentation and/or other materials provided with the 1.16 +// distribution. 1.17 +// * Neither the name of Google Inc. nor the names of its 1.18 +// contributors may be used to endorse or promote products derived from 1.19 +// this software without specific prior written permission. 1.20 +// 1.21 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.22 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.23 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.24 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.25 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.26 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.27 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.28 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.29 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.30 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.31 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.32 + 1.33 +#import <Breakpad/Breakpad.h> 1.34 + 1.35 +#import "Controller.h" 1.36 +#import "TestClass.h" 1.37 +#import "GTMDefines.h" 1.38 +#include <unistd.h> 1.39 +#include <mach/mach.h> 1.40 + 1.41 +@implementation Controller 1.42 + 1.43 +- (void)causeCrash { 1.44 + float *aPtr = nil; 1.45 + NSLog(@"Crash!"); 1.46 + NSLog(@"Bad programmer: %f", *aPtr); 1.47 +} 1.48 + 1.49 +- (void)generateReportWithoutCrash:(id)sender { 1.50 + BreakpadGenerateAndSendReport(breakpad_); 1.51 +} 1.52 + 1.53 +- (IBAction)showForkTestWindow:(id) sender { 1.54 + [forkTestOptions_ setIsVisible:YES]; 1.55 +} 1.56 + 1.57 +- (IBAction)forkTestOptions:(id)sender { 1.58 + NSInteger tag = [[sender selectedCell] tag]; 1.59 + NSLog(@"sender tag: %d", tag); 1.60 + if (tag <= 2) { 1.61 + bpForkOption = tag; 1.62 + } 1.63 + 1.64 + if (tag == 3) { 1.65 + useVFork = NO; 1.66 + } 1.67 + 1.68 + if (tag == 4) { 1.69 + useVFork = YES; 1.70 + } 1.71 + 1.72 + if (tag >= 5 && tag <= 7) { 1.73 + progCrashPoint = tag; 1.74 + } 1.75 + 1.76 +} 1.77 + 1.78 +- (IBAction)forkTestGo:(id)sender { 1.79 + 1.80 + NSString *resourcePath = [[NSBundle bundleForClass: 1.81 + [self class]] resourcePath]; 1.82 + NSString *execProgname = nil; 1.83 + if (progCrashPoint == DURINGLAUNCH) { 1.84 + execProgname = [resourcePath stringByAppendingString:@"/crashduringload"]; 1.85 + } else if (progCrashPoint == AFTERLAUNCH) { 1.86 + execProgname = [resourcePath stringByAppendingString:@"/crashInMain"]; 1.87 + } 1.88 + 1.89 + const char *progName = NULL; 1.90 + if (progCrashPoint != BETWEENFORKEXEC) { 1.91 + progName = [execProgname UTF8String]; 1.92 + } 1.93 + 1.94 + int pid; 1.95 + 1.96 + if (bpForkOption == UNINSTALL) { 1.97 + BreakpadRelease(breakpad_); 1.98 + } 1.99 + 1.100 + if (useVFork) { 1.101 + pid = vfork(); 1.102 + } else { 1.103 + pid = fork(); 1.104 + } 1.105 + 1.106 + if (pid == 0) { 1.107 + sleep(3); 1.108 + NSLog(@"Child continuing"); 1.109 + FILE *fd = fopen("/tmp/childlog.txt","wt"); 1.110 + kern_return_t kr; 1.111 + if (bpForkOption == RESETEXCEPTIONPORT) { 1.112 + kr = task_set_exception_ports(mach_task_self(), 1.113 + EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | 1.114 + EXC_MASK_ARITHMETIC | EXC_MASK_BREAKPOINT, 1.115 + MACH_PORT_NULL, 1.116 + EXCEPTION_DEFAULT, 1.117 + THREAD_STATE_NONE); 1.118 + fprintf(fd,"task_set_exception_ports returned %d\n", kr); 1.119 + } 1.120 + 1.121 + if (progCrashPoint == BETWEENFORKEXEC) { 1.122 + fprintf(fd,"crashing post-fork\n"); 1.123 + int *a = NULL; 1.124 + printf("%d\n",*a++); 1.125 + } 1.126 + 1.127 + fprintf(fd,"about to call exec with %s\n", progName); 1.128 + fclose(fd); 1.129 + int i = execl(progName, progName, NULL); 1.130 + fprintf(fd, "exec returned! %d\n", i); 1.131 + fclose(fd); 1.132 + } 1.133 +} 1.134 + 1.135 +- (IBAction)crash:(id)sender { 1.136 + NSInteger tag = [sender tag]; 1.137 + 1.138 + if (tag == 1) { 1.139 + [NSObject cancelPreviousPerformRequestsWithTarget:self]; 1.140 + [self performSelector:@selector(causeCrash) withObject:nil afterDelay:10.0]; 1.141 + [sender setState:NSOnState]; 1.142 + return; 1.143 + } 1.144 + 1.145 + if (tag == 2 && breakpad_) { 1.146 + BreakpadRelease(breakpad_); 1.147 + breakpad_ = NULL; 1.148 + return; 1.149 + } 1.150 + 1.151 + [self causeCrash]; 1.152 +} 1.153 + 1.154 +- (void)anotherThread { 1.155 + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 1.156 + TestClass *tc = [[TestClass alloc] init]; 1.157 + 1.158 + [tc wait]; 1.159 + 1.160 + [pool release]; 1.161 +} 1.162 + 1.163 +- (void)awakeFromNib { 1.164 + NSBundle *bundle = [NSBundle mainBundle]; 1.165 + NSDictionary *info = [bundle infoDictionary]; 1.166 + 1.167 + 1.168 + breakpad_ = BreakpadCreate(info); 1.169 + 1.170 + // Do some unit tests with keys 1.171 + // first a series of bogus values 1.172 + BreakpadSetKeyValue(breakpad_, nil, @"bad2"); 1.173 + BreakpadSetKeyValue(nil, @"bad3", @"bad3"); 1.174 + 1.175 + // Now some good ones 1.176 + BreakpadSetKeyValue(breakpad_,@"key1", @"value1"); 1.177 + BreakpadSetKeyValue(breakpad_,@"key2", @"value2"); 1.178 + BreakpadSetKeyValue(breakpad_,@"key3", @"value3"); 1.179 + 1.180 + // Look for a bogus one that we didn't try to set 1.181 + NSString *test = BreakpadKeyValue(breakpad_, @"bad4"); 1.182 + if (test) { 1.183 + NSLog(@"Bad BreakpadKeyValue (bad4)"); 1.184 + } 1.185 + 1.186 + // Look for a bogus one we did try to set 1.187 + test = BreakpadKeyValue(breakpad_, @"bad1"); 1.188 + if (test) { 1.189 + NSLog(@"Bad BreakpadKeyValue (bad1)"); 1.190 + } 1.191 + 1.192 + // Test some bad args for BreakpadKeyValue 1.193 + test = BreakpadKeyValue(nil, @"bad5"); 1.194 + if (test) { 1.195 + NSLog(@"Bad BreakpadKeyValue (bad5)"); 1.196 + } 1.197 + 1.198 + test = BreakpadKeyValue(breakpad_, nil); 1.199 + if (test) { 1.200 + NSLog(@"Bad BreakpadKeyValue (nil)"); 1.201 + } 1.202 + 1.203 + // Find some we did set 1.204 + test = BreakpadKeyValue(breakpad_, @"key1"); 1.205 + if (![test isEqualToString:@"value1"]) { 1.206 + NSLog(@"Can't find BreakpadKeyValue (key1)"); 1.207 + } 1.208 + test = BreakpadKeyValue(breakpad_, @"key2"); 1.209 + if (![test isEqualToString:@"value2"]) { 1.210 + NSLog(@"Can't find BreakpadKeyValue (key2)"); 1.211 + } 1.212 + test = BreakpadKeyValue(breakpad_, @"key3"); 1.213 + if (![test isEqualToString:@"value3"]) { 1.214 + NSLog(@"Can't find BreakpadKeyValue (key3)"); 1.215 + } 1.216 + 1.217 + // Bad args for BreakpadRemoveKeyValue 1.218 + BreakpadRemoveKeyValue(nil, @"bad6"); 1.219 + BreakpadRemoveKeyValue(breakpad_, nil); 1.220 + 1.221 + // Remove one that is valid 1.222 + BreakpadRemoveKeyValue(breakpad_, @"key3"); 1.223 + 1.224 + // Try and find it 1.225 + test = BreakpadKeyValue(breakpad_, @"key3"); 1.226 + if (test) { 1.227 + NSLog(@"Shouldn't find BreakpadKeyValue (key3)"); 1.228 + } 1.229 + 1.230 + // Try and remove it again 1.231 + BreakpadRemoveKeyValue(breakpad_, @"key3"); 1.232 + 1.233 + // Try removal by setting to nil 1.234 + BreakpadSetKeyValue(breakpad_,@"key2", nil); 1.235 + // Try and find it 1.236 + test = BreakpadKeyValue(breakpad_, @"key2"); 1.237 + if (test) { 1.238 + NSLog(@"Shouldn't find BreakpadKeyValue (key2)"); 1.239 + } 1.240 + 1.241 + BreakpadAddUploadParameter(breakpad_, 1.242 + @"MeaningOfLife", 1.243 + @"42"); 1.244 + [NSThread detachNewThreadSelector:@selector(anotherThread) 1.245 + toTarget:self withObject:nil]; 1.246 + 1.247 + NSUserDefaults *args = [NSUserDefaults standardUserDefaults]; 1.248 + 1.249 + // If the user specified autocrash on the command line, toggle 1.250 + // Breakpad to not confirm and crash immediately. This is for 1.251 + // automated testing. 1.252 + if ([args boolForKey:@"autocrash"]) { 1.253 + BreakpadSetKeyValue(breakpad_, 1.254 + @BREAKPAD_SKIP_CONFIRM, 1.255 + @"YES"); 1.256 + [self causeCrash]; 1.257 + } 1.258 + 1.259 + progCrashPoint = DURINGLAUNCH; 1.260 + [window_ center]; 1.261 + [window_ makeKeyAndOrderFront:self]; 1.262 +} 1.263 + 1.264 +@end