/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. #import "GTMSenTestCase.h"
  34. #import "Breakpad.h"
  35. #include <mach/mach.h>
  36. @interface BreakpadFramework_Test : GTMTestCase {
  37. @private
  38. int last_exception_code_;
  39. int last_exception_type_;
  40. mach_port_t last_exception_thread_;
  41. // We're not using Obj-C BOOL because we need to interop with
  42. // Breakpad's callback.
  43. bool shouldHandleException_;
  44. }
  45. // This method is used by a callback used by test cases to determine
  46. // whether to return true or false to Breakpad when handling an
  47. // exception.
  48. - (bool)shouldHandleException;
  49. // This method returns a minimal dictionary that has what
  50. // Breakpad needs to initialize.
  51. - (NSMutableDictionary *)breakpadInitializationDictionary;
  52. // This method is used by the exception handling callback
  53. // to communicate to test cases the properites of the last
  54. // exception.
  55. - (void)setLastExceptionType:(int)type andCode:(int)code
  56. andThread:(mach_port_t)thread;
  57. @end
  58. // Callback for Breakpad exceptions
  59. bool myBreakpadCallback(int exception_type,
  60. int exception_code,
  61. mach_port_t crashing_thread,
  62. void *context);
  63. bool myBreakpadCallback(int exception_type,
  64. int exception_code,
  65. mach_port_t crashing_thread,
  66. void *context) {
  67. BreakpadFramework_Test *testCaseClass =
  68. (BreakpadFramework_Test *)context;
  69. [testCaseClass setLastExceptionType:exception_type
  70. andCode:exception_code
  71. andThread:crashing_thread];
  72. bool shouldHandleException =
  73. [testCaseClass shouldHandleException];
  74. NSLog(@"Callback returning %d", shouldHandleException);
  75. return shouldHandleException;
  76. }
  77. const int kNoLastExceptionCode = -1;
  78. const int kNoLastExceptionType = -1;
  79. const mach_port_t kNoLastExceptionThread = MACH_PORT_NULL;
  80. @implementation BreakpadFramework_Test
  81. - (void) initializeExceptionStateVariables {
  82. last_exception_code_ = kNoLastExceptionCode;
  83. last_exception_type_ = kNoLastExceptionType;
  84. last_exception_thread_ = kNoLastExceptionThread;
  85. }
  86. - (NSMutableDictionary *)breakpadInitializationDictionary {
  87. NSMutableDictionary *breakpadParams =
  88. [NSMutableDictionary dictionaryWithCapacity:3];
  89. [breakpadParams setObject:@"UnitTests" forKey:@BREAKPAD_PRODUCT];
  90. [breakpadParams setObject:@"1.0" forKey:@BREAKPAD_VERSION];
  91. [breakpadParams setObject:@"http://staging" forKey:@BREAKPAD_URL];
  92. return breakpadParams;
  93. }
  94. - (bool)shouldHandleException {
  95. return shouldHandleException_;
  96. }
  97. - (void)setLastExceptionType:(int)type
  98. andCode:(int)code
  99. andThread:(mach_port_t)thread {
  100. last_exception_type_ = type;
  101. last_exception_code_ = code;
  102. last_exception_thread_ = thread;
  103. }
  104. // Test that the parameters mark required actually enable Breakpad to
  105. // be initialized.
  106. - (void)testBreakpadInstantiationWithRequiredParameters {
  107. BreakpadRef b = BreakpadCreate([self breakpadInitializationDictionary]);
  108. STAssertNotNULL(b, @"BreakpadCreate failed with required parameters");
  109. BreakpadRelease(b);
  110. }
  111. // Test that Breakpad fails to initialize cleanly when required
  112. // parameters are not present.
  113. - (void)testBreakpadInstantiationWithoutRequiredParameters {
  114. NSMutableDictionary *breakpadDictionary =
  115. [self breakpadInitializationDictionary];
  116. // Skip setting version, so that BreakpadCreate fails.
  117. [breakpadDictionary removeObjectForKey:@BREAKPAD_VERSION];
  118. BreakpadRef b = BreakpadCreate(breakpadDictionary);
  119. STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
  120. " parameter!");
  121. breakpadDictionary = [self breakpadInitializationDictionary];
  122. // Now test with no product
  123. [breakpadDictionary removeObjectForKey:@BREAKPAD_PRODUCT];
  124. b = BreakpadCreate(breakpadDictionary);
  125. STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
  126. " parameter!");
  127. breakpadDictionary = [self breakpadInitializationDictionary];
  128. // Now test with no URL
  129. [breakpadDictionary removeObjectForKey:@BREAKPAD_URL];
  130. b = BreakpadCreate(breakpadDictionary);
  131. STAssertNULL(b, @"BreakpadCreate did not fail when missing a required"
  132. " parameter!");
  133. BreakpadRelease(b);
  134. }
  135. // Test to ensure that when we call BreakpadAddUploadParameter,
  136. // it's added to the dictionary correctly(this test depends on
  137. // some internal details of Breakpad, namely, the special prefix
  138. // that it uses to figure out which key/value pairs to upload).
  139. - (void)testAddingBreakpadServerVariable {
  140. NSMutableDictionary *breakpadDictionary =
  141. [self breakpadInitializationDictionary];
  142. BreakpadRef b = BreakpadCreate(breakpadDictionary);
  143. STAssertNotNULL(b, @"BreakpadCreate failed with valid dictionary!");
  144. BreakpadAddUploadParameter(b,
  145. @"key",
  146. @"value");
  147. // Test that it did not add the key/value directly, e.g. without
  148. // prepending the key with the prefix.
  149. STAssertNil(BreakpadKeyValue(b, @"key"),
  150. @"AddUploadParameter added key directly to dictionary"
  151. " instead of prepending it!");
  152. NSString *prependedKeyname =
  153. [@BREAKPAD_SERVER_PARAMETER_PREFIX stringByAppendingString:@"key"];
  154. STAssertEqualStrings(BreakpadKeyValue(b, prependedKeyname),
  155. @"value",
  156. @"Calling BreakpadAddUploadParameter did not prepend "
  157. "key name");
  158. BreakpadRelease(b);
  159. }
  160. // Test that when we do on-demand minidump generation,
  161. // the exception code/type/thread are set properly.
  162. - (void)testFilterCallbackReturnsFalse {
  163. NSMutableDictionary *breakpadDictionary =
  164. [self breakpadInitializationDictionary];
  165. BreakpadRef b = BreakpadCreate(breakpadDictionary);
  166. STAssertNotNULL(b, @"BreakpadCreate failed with valid dictionary!");
  167. BreakpadSetFilterCallback(b, &myBreakpadCallback, self);
  168. // This causes the callback to return false, meaning
  169. // Breakpad won't take the exception
  170. shouldHandleException_ = false;
  171. [self initializeExceptionStateVariables];
  172. STAssertEquals(last_exception_type_, kNoLastExceptionType,
  173. @"Last exception type not initialized correctly.");
  174. STAssertEquals(last_exception_code_, kNoLastExceptionCode,
  175. @"Last exception code not initialized correctly.");
  176. STAssertEquals(last_exception_thread_, kNoLastExceptionThread,
  177. @"Last exception thread is not initialized correctly.");
  178. // Cause Breakpad's exception handler to be invoked.
  179. BreakpadGenerateAndSendReport(b);
  180. STAssertEquals(last_exception_type_, 0,
  181. @"Last exception type is not 0 for on demand");
  182. STAssertEquals(last_exception_code_, 0,
  183. @"Last exception code is not 0 for on demand");
  184. STAssertEquals(last_exception_thread_, mach_thread_self(),
  185. @"Last exception thread is not mach_thread_self() "
  186. "for on demand");
  187. }
  188. @end