PageRenderTime 35ms CodeModel.GetById 23ms app.highlight 5ms RepoModel.GetById 2ms app.codeStats 0ms

/thirdparty/breakpad/client/mac/tests/BreakpadFramework_Test.mm

http://github.com/tomahawk-player/tomahawk
Objective C++ | 217 lines | 127 code | 29 blank | 61 comment | 0 complexity | 7a182322b57debbf72c0aca40eb0137d MD5 | raw file
  1// Copyright (c) 2009, Google Inc.
  2// All rights reserved.
  3//
  4// Redistribution and use in source and binary forms, with or without
  5// modification, are permitted provided that the following conditions are
  6// met:
  7//
  8//     * Redistributions of source code must retain the above copyright
  9// notice, this list of conditions and the following disclaimer.
 10//     * Redistributions in binary form must reproduce the above
 11// copyright notice, this list of conditions and the following disclaimer
 12// in the documentation and/or other materials provided with the
 13// distribution.
 14//     * Neither the name of Google Inc. nor the names of its
 15// contributors may be used to endorse or promote products derived from
 16// this software without specific prior written permission.
 17//
 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 29//
 30// BreakpadFramework_Test.mm
 31// Test case file for Breakpad.h/mm.
 32//
 33
 34#import "GTMSenTestCase.h"
 35#import "Breakpad.h"
 36
 37#include <mach/mach.h>
 38
 39@interface BreakpadFramework_Test : GTMTestCase {
 40 @private
 41  int last_exception_code_;
 42  int last_exception_type_;
 43  mach_port_t last_exception_thread_;
 44  // We're not using Obj-C BOOL because we need to interop with
 45  // Breakpad's callback.
 46  bool shouldHandleException_;
 47}
 48
 49// This method is used by a callback used by test cases to determine
 50// whether to return true or false to Breakpad when handling an
 51// exception.
 52- (bool)shouldHandleException;
 53// This method returns a minimal dictionary that has what
 54// Breakpad needs to initialize.
 55- (NSMutableDictionary *)breakpadInitializationDictionary;
 56// This method is used by the exception handling callback
 57// to communicate to test cases the properites of the last
 58// exception.
 59- (void)setLastExceptionType:(int)type andCode:(int)code
 60                   andThread:(mach_port_t)thread;
 61@end
 62
 63// Callback for Breakpad exceptions
 64bool myBreakpadCallback(int exception_type,
 65                        int exception_code,
 66                        mach_port_t crashing_thread,
 67                        void *context);
 68
 69bool myBreakpadCallback(int exception_type,
 70                        int exception_code,
 71                        mach_port_t crashing_thread,
 72                        void *context) {
 73  BreakpadFramework_Test *testCaseClass =
 74    (BreakpadFramework_Test *)context;
 75  [testCaseClass setLastExceptionType:exception_type
 76                              andCode:exception_code
 77                            andThread:crashing_thread];
 78  bool shouldHandleException =
 79    [testCaseClass shouldHandleException];
 80  NSLog(@"Callback returning %d", shouldHandleException);
 81  return shouldHandleException;
 82}
 83const int kNoLastExceptionCode = -1;
 84const int kNoLastExceptionType = -1;
 85const mach_port_t kNoLastExceptionThread = MACH_PORT_NULL;
 86
 87@implementation BreakpadFramework_Test
 88- (void) initializeExceptionStateVariables {
 89  last_exception_code_ = kNoLastExceptionCode;
 90  last_exception_type_ = kNoLastExceptionType;
 91  last_exception_thread_ = kNoLastExceptionThread;
 92}
 93
 94- (NSMutableDictionary *)breakpadInitializationDictionary {
 95  NSMutableDictionary *breakpadParams =
 96    [NSMutableDictionary dictionaryWithCapacity:3];
 97
 98  [breakpadParams setObject:@"UnitTests" forKey:@BREAKPAD_PRODUCT];
 99  [breakpadParams setObject:@"1.0" forKey:@BREAKPAD_VERSION];
100  [breakpadParams setObject:@"http://staging" forKey:@BREAKPAD_URL];
101  return breakpadParams;
102}
103
104- (bool)shouldHandleException {
105  return shouldHandleException_;
106}
107
108- (void)setLastExceptionType:(int)type 
109		     andCode:(int)code
110                   andThread:(mach_port_t)thread {
111  last_exception_type_ = type;
112  last_exception_code_ = code;
113  last_exception_thread_ = thread;
114}
115
116// Test that the parameters mark required actually enable Breakpad to
117// be initialized.
118- (void)testBreakpadInstantiationWithRequiredParameters {
119  BreakpadRef b = BreakpadCreate([self breakpadInitializationDictionary]);
120  STAssertNotNULL(b, @"BreakpadCreate failed with required parameters");
121  BreakpadRelease(b);
122}
123
124// Test that Breakpad fails to initialize cleanly when required
125// parameters are not present.
126- (void)testBreakpadInstantiationWithoutRequiredParameters {
127  NSMutableDictionary *breakpadDictionary =
128    [self breakpadInitializationDictionary];
129
130  // Skip setting version, so that BreakpadCreate fails.
131  [breakpadDictionary removeObjectForKey:@BREAKPAD_VERSION];
132  BreakpadRef b = BreakpadCreate(breakpadDictionary);
133  STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
134               " parameter!");
135
136  breakpadDictionary = [self breakpadInitializationDictionary];
137  // Now test with no product
138  [breakpadDictionary removeObjectForKey:@BREAKPAD_PRODUCT];
139  b = BreakpadCreate(breakpadDictionary);
140  STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
141               " parameter!");
142
143  breakpadDictionary = [self breakpadInitializationDictionary];
144  // Now test with no URL
145  [breakpadDictionary removeObjectForKey:@BREAKPAD_URL];
146  b = BreakpadCreate(breakpadDictionary);
147  STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
148               " parameter!");
149  BreakpadRelease(b);
150}
151
152// Test to ensure that when we call BreakpadAddUploadParameter,
153// it's added to the dictionary correctly(this test depends on
154// some internal details of Breakpad, namely, the special prefix
155// that it uses to figure out which key/value pairs to upload).
156- (void)testAddingBreakpadServerVariable {
157  NSMutableDictionary *breakpadDictionary =
158    [self breakpadInitializationDictionary];
159
160  BreakpadRef b = BreakpadCreate(breakpadDictionary);
161  STAssertNotNULL(b, @"BreakpadCreate failed with valid dictionary!");
162
163  BreakpadAddUploadParameter(b,
164                             @"key",
165                             @"value");
166
167  // Test that it did not add the key/value directly, e.g. without
168  // prepending the key with the prefix.
169  STAssertNil(BreakpadKeyValue(b, @"key"),
170              @"AddUploadParameter added key directly to dictionary"
171              " instead of prepending it!");
172
173  NSString *prependedKeyname =
174    [@BREAKPAD_SERVER_PARAMETER_PREFIX stringByAppendingString:@"key"];
175    
176  STAssertEqualStrings(BreakpadKeyValue(b, prependedKeyname),
177                       @"value",
178                       @"Calling BreakpadAddUploadParameter did not prepend "
179                       "key name");
180  BreakpadRelease(b);
181}
182
183// Test that when we do on-demand minidump generation,
184// the exception code/type/thread are set properly.
185- (void)testFilterCallbackReturnsFalse {
186  NSMutableDictionary *breakpadDictionary =
187    [self breakpadInitializationDictionary];
188
189  BreakpadRef b = BreakpadCreate(breakpadDictionary);
190  STAssertNotNULL(b, @"BreakpadCreate failed with valid dictionary!");
191  BreakpadSetFilterCallback(b, &myBreakpadCallback, self);
192
193  // This causes the callback to return false, meaning
194  // Breakpad won't take the exception
195  shouldHandleException_ = false;
196
197  [self initializeExceptionStateVariables];
198  STAssertEquals(last_exception_type_, kNoLastExceptionType,
199                 @"Last exception type not initialized correctly.");
200  STAssertEquals(last_exception_code_, kNoLastExceptionCode,
201                 @"Last exception code not initialized correctly.");
202  STAssertEquals(last_exception_thread_, kNoLastExceptionThread,
203                 @"Last exception thread is not initialized correctly.");
204
205  // Cause Breakpad's exception handler to be invoked.
206  BreakpadGenerateAndSendReport(b);
207
208  STAssertEquals(last_exception_type_, 0,
209                 @"Last exception type is not 0 for on demand");
210  STAssertEquals(last_exception_code_, 0,
211                 @"Last exception code is not 0 for on demand");
212  STAssertEquals(last_exception_thread_, mach_thread_self(),
213                 @"Last exception thread is not mach_thread_self() "
214                 "for on demand");
215}
216
217@end