FIRCLSReportAdapterTests.m 7.1 KB

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