FIRCLSRolloutsPersistenceManagerTests.m 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Copyright 2024 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/Components/FIRCLSContext.h"
  17. #include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h"
  18. #import "Crashlytics/Crashlytics/Controllers/FIRCLSRolloutsPersistenceManager.h"
  19. #import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h"
  20. #import "Crashlytics/UnitTests/Mocks/FIRCLSTempMockFileManager.h"
  21. #if SWIFT_PACKAGE
  22. @import FirebaseCrashlyticsSwift;
  23. #else // Swift Package Manager
  24. #import <FirebaseCrashlytics/FirebaseCrashlytics-Swift.h>
  25. #endif // CocoaPods
  26. NSString *reportId = @"1234567";
  27. @interface FIRCLSRolloutsPersistenceManagerTests : XCTestCase
  28. @property(nonatomic, strong) FIRCLSTempMockFileManager *fileManager;
  29. @property(nonatomic, strong) dispatch_queue_t loggingQueue;
  30. @property(nonatomic, strong) FIRCLSRolloutsPersistenceManager *rolloutsPersistenceManager;
  31. @end
  32. @implementation FIRCLSRolloutsPersistenceManagerTests
  33. - (void)setUp {
  34. [super setUp];
  35. FIRCLSContextBaseInit();
  36. self.fileManager = [[FIRCLSTempMockFileManager alloc] init];
  37. [self.fileManager createReportDirectories];
  38. [self.fileManager setupNewPathForExecutionIdentifier:reportId];
  39. self.loggingQueue =
  40. dispatch_queue_create("com.google.firebase.FIRCLSRolloutsPersistence", DISPATCH_QUEUE_SERIAL);
  41. self.rolloutsPersistenceManager =
  42. [[FIRCLSRolloutsPersistenceManager alloc] initWithFileManager:self.fileManager
  43. andQueue:self.loggingQueue];
  44. }
  45. - (void)tearDown {
  46. [self.fileManager removeItemAtPath:_fileManager.rootPath];
  47. FIRCLSContextBaseDeinit();
  48. [super tearDown];
  49. }
  50. - (void)testUpdateRolloutsStateToPersistenceWithRollouts {
  51. XCTestExpectation *expectation = [[XCTestExpectation alloc]
  52. initWithDescription:@"Expect updating rollouts to finish writing."];
  53. NSString *encodedStateString =
  54. @"{rollouts:[{\"parameter_key\":\"6d795f66656174757265\",\"parameter_value\":"
  55. @"\"e8bf99e698af7468656d6973e79a84e6b58be8af95e695b0e68daeefbc8ce8be93e585a5e4b8ade69687\","
  56. @"\"rollout_id\":\"726f6c6c6f75745f31\",\"template_version\":1,\"variant_id\":"
  57. @"\"636f6e74726f6c\"}]}";
  58. NSData *data = [encodedStateString dataUsingEncoding:NSUTF8StringEncoding];
  59. NSString *rolloutsFilePath =
  60. [[[self.fileManager activePath] stringByAppendingPathComponent:reportId]
  61. stringByAppendingPathComponent:FIRCLSReportRolloutsFile];
  62. [self.rolloutsPersistenceManager updateRolloutsStateToPersistenceWithRollouts:data
  63. reportID:reportId];
  64. XCTAssertNotNil(self.loggingQueue);
  65. // Wait for the logging queue to finish.
  66. dispatch_async(self.loggingQueue, ^{
  67. [expectation fulfill];
  68. });
  69. [self waitForExpectations:@[ expectation ] timeout:3];
  70. XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:rolloutsFilePath]);
  71. NSFileHandle *rolloutsFile = [NSFileHandle fileHandleForUpdatingAtPath:rolloutsFilePath];
  72. NSData *fileData = [rolloutsFile readDataToEndOfFile];
  73. NSString *fileString = [[NSString alloc] initWithData:fileData encoding:NSUTF8StringEncoding];
  74. XCTAssertTrue([fileString isEqualToString:[encodedStateString stringByAppendingString:@"\n"]]);
  75. }
  76. - (void)testUpdateRolloutsStateToPersistenceEnsureNoHang {
  77. dispatch_queue_t testQueue = dispatch_queue_create("TestQueue", DISPATCH_QUEUE_SERIAL);
  78. XCTestExpectation *expectation =
  79. [[XCTestExpectation alloc] initWithDescription:@"Expect updating rollouts to return."];
  80. NSString *encodedStateString =
  81. @"{rollouts:[{\"parameter_key\":\"6d795f66656174757265\",\"parameter_value\":"
  82. @"\"e8bf99e698af7468656d6973e79a84e6b58be8af95e695b0e68daeefbc8ce8be93e585a5e4b8ade69687\","
  83. @"\"rollout_id\":\"726f6c6c6f75745f31\",\"template_version\":1,\"variant_id\":"
  84. @"\"636f6e74726f6c\"}]}";
  85. NSData *data = [encodedStateString dataUsingEncoding:NSUTF8StringEncoding];
  86. // Clog up the queue with a long running operation. This sleep time
  87. // must be longer than the expectation timeout.
  88. dispatch_async(self.loggingQueue, ^{
  89. sleep(10);
  90. });
  91. dispatch_async(testQueue, ^{
  92. // Ensure that calling this returns quickly so we don't hang
  93. [self.rolloutsPersistenceManager updateRolloutsStateToPersistenceWithRollouts:data
  94. reportID:reportId];
  95. [expectation fulfill];
  96. });
  97. [self waitForExpectations:@[ expectation ] timeout:3];
  98. }
  99. @end