FIRCLSReportAdapterTests.m 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // Copyright 2020 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #import <Foundation/Foundation.h>
  15. #import <XCTest/XCTest.h>
  16. #import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.h"
  17. #import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.h"
  18. #import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.h"
  19. #import "Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.h"
  20. #import "Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter_Private.h"
  21. #import "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h"
  22. #import <GoogleDataTransport/GoogleDataTransport.h>
  23. @interface FIRCLSReportAdapterTests : XCTestCase
  24. @end
  25. @implementation FIRCLSReportAdapterTests
  26. /// Attempt sending a proto report to the reporting endpoint
  27. - (void)testSendProtoReport {
  28. NSString *minCrash =
  29. [[FIRCLSReportAdapterTests resourcePath] stringByAppendingPathComponent:@"bare_min_crash"];
  30. FIRCLSReportAdapter *adapter =
  31. [[FIRCLSReportAdapter alloc] initWithPath:minCrash
  32. googleAppId:@"1:17586535263:ios:83778f4dc7e8a26ef794ea"];
  33. GDTCORTransport *transport = [[GDTCORTransport alloc] initWithMappingID:@"1206"
  34. transformers:nil
  35. target:kGDTCORTargetCSH];
  36. GDTCOREvent *event = [transport eventForTransport];
  37. event.dataObject = adapter;
  38. event.qosTier = GDTCOREventQoSFast; // Bypass batching and have the event get sent out ASAP
  39. [transport sendDataEvent:event];
  40. }
  41. /// This test is useful for testing the binary output of the proto message
  42. - (void)testProtoOutput {
  43. NSString *minCrash =
  44. [[FIRCLSReportAdapterTests resourcePath] stringByAppendingPathComponent:@"bare_min_crash"];
  45. FIRCLSReportAdapter *adapter =
  46. [[FIRCLSReportAdapter alloc] initWithPath:minCrash
  47. googleAppId:@"1:17586535263:ios:83778f4dc7e8a26ef794ea"];
  48. NSData *data = adapter.transportBytes;
  49. NSError *error = nil;
  50. NSString *outputPath =
  51. [[FIRCLSReportAdapterTests resourcePath] stringByAppendingPathComponent:@"output.proto"];
  52. [data writeToFile:outputPath options:NSDataWritingAtomic error:&error];
  53. NSLog(@"Output path: %@", outputPath);
  54. if (error) {
  55. NSLog(@"Write returned error: %@", [error localizedDescription]);
  56. }
  57. // Put a breakpoint here to copy the file from the output path.
  58. }
  59. /// It is important that a crash does not occur when reading persisted crash files
  60. /// Verify various invalid input cases.
  61. - (void)testInvalidRecordCases {
  62. id adapter __unused = [[FIRCLSReportAdapter alloc] initWithPath:@"nonExistentPath"
  63. googleAppId:@"appID"];
  64. id application __unused = [[FIRCLSRecordApplication alloc] initWithDict:nil];
  65. id host __unused = [[FIRCLSRecordHost alloc] initWithDict:nil];
  66. id identity __unused = [[FIRCLSRecordIdentity alloc] initWithDict:nil];
  67. NSDictionary *emptyDict = [[NSDictionary alloc] init];
  68. id application2 __unused = [[FIRCLSRecordApplication alloc] initWithDict:emptyDict];
  69. id host2 __unused = [[FIRCLSRecordHost alloc] initWithDict:emptyDict];
  70. id identity2 __unused = [[FIRCLSRecordIdentity alloc] initWithDict:emptyDict];
  71. }
  72. - (void)testCorruptMetadataCLSRecordFile {
  73. id adapter __unused = [FIRCLSReportAdapterTests adapterForCorruptMetadata];
  74. }
  75. - (void)testRecordMetadataFile {
  76. FIRCLSReportAdapter *adapter = [FIRCLSReportAdapterTests adapterForValidMetadata];
  77. // Verify identity
  78. XCTAssertTrue([adapter.identity.build_version isEqualToString:@"4.0.0-beta.1"]);
  79. XCTAssertTrue(
  80. [adapter.identity.install_id isEqualToString:@"169DB25B-8F1D-4115-8364-3887DA9DE73C"]);
  81. // Verify host
  82. XCTAssertTrue([adapter.host.platform isEqualToString:@"ios"]);
  83. // Verify application
  84. XCTAssertTrue([adapter.application.build_version isEqualToString:@"1"]);
  85. XCTAssertTrue([adapter.application.display_version isEqualToString:@"1.0"]);
  86. }
  87. - (void)testReportProto {
  88. FIRCLSReportAdapter *adapter = [FIRCLSReportAdapterTests adapterForAllCrashes];
  89. google_crashlytics_Report report = [adapter protoReport];
  90. XCTAssertTrue([self isPBData:report.sdk_version equalToString:adapter.identity.build_version]);
  91. XCTAssertTrue([self isPBData:report.gmp_app_id equalToString:@"appID"]);
  92. XCTAssertEqual(report.platform, google_crashlytics_Platforms_IOS);
  93. XCTAssertTrue([self isPBData:report.installation_uuid equalToString:adapter.identity.install_id]);
  94. XCTAssertTrue([self isPBData:report.display_version
  95. equalToString:adapter.application.display_version]);
  96. // Files payload
  97. XCTAssertEqual(report.apple_payload.files_count, 11);
  98. NSArray<NSString *> *clsRecords = adapter.clsRecordFilePaths;
  99. for (NSUInteger i = 0; i < clsRecords.count; i++) {
  100. XCTAssertTrue([self isPBData:report.apple_payload.files[i].filename
  101. equalToString:clsRecords[i].lastPathComponent]);
  102. NSData *data = [NSData dataWithContentsOfFile:clsRecords[i] options:0 error:nil];
  103. XCTAssertTrue([self isPBData:report.apple_payload.files[i].contents equalToData:data]);
  104. }
  105. }
  106. // Helper functions
  107. #pragma mark - Helper Functions
  108. + (FIRCLSReportAdapter *)adapterForAllCrashes {
  109. return [[FIRCLSReportAdapter alloc]
  110. initWithPath:[[FIRCLSReportAdapterTests resourcePath]
  111. stringByAppendingPathComponent:@"ios_all_files_crash"]
  112. googleAppId:@"appID"];
  113. }
  114. + (FIRCLSReportAdapter *)adapterForCorruptMetadata {
  115. return [[FIRCLSReportAdapter alloc]
  116. initWithPath:[[FIRCLSReportAdapterTests resourcePath]
  117. stringByAppendingPathComponent:@"corrupt_metadata"]
  118. googleAppId:@"appID"];
  119. }
  120. + (FIRCLSReportAdapter *)adapterForValidMetadata {
  121. return [[FIRCLSReportAdapter alloc]
  122. initWithPath:[[FIRCLSReportAdapterTests resourcePath]
  123. stringByAppendingPathComponent:@"valid_metadata"]
  124. googleAppId:@"appID"];
  125. }
  126. + (NSString *)resourcePath {
  127. return [[NSBundle bundleForClass:[self class]] resourcePath];
  128. }
  129. #pragma mark - Assertion Helpers for NanoPB Types
  130. - (BOOL)isPBData:(pb_bytes_array_t *)pbString equalToString:(NSString *)str {
  131. pb_bytes_array_t *expected = FIRCLSEncodeString(str);
  132. return [self isPBArray:pbString equalToArray:expected];
  133. }
  134. - (BOOL)isPBData:(pb_bytes_array_t *)pbString equalToData:(NSData *)data {
  135. pb_bytes_array_t *expected = FIRCLSEncodeData(data);
  136. return [self isPBArray:pbString equalToArray:expected];
  137. }
  138. - (BOOL)isPBArray:(pb_bytes_array_t *)array equalToArray:(pb_bytes_array_t *)expected {
  139. // Treat the empty string as the same as a missing field
  140. if ((!array) && expected->size == 0) {
  141. return true;
  142. }
  143. if (array->size != expected->size) {
  144. return false;
  145. }
  146. for (int i = 0; i < array->size; i++) {
  147. if (expected->bytes[i] != array->bytes[i]) {
  148. return false;
  149. }
  150. }
  151. return true;
  152. }
  153. @end