mirror of
https://github.com/firebase/firebase-ios-sdk
synced 2026-11-10 22:45:59 +05:45
297 lines
12 KiB
Objective-C
297 lines
12 KiB
Objective-C
// Copyright 2020 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#import <XCTest/XCTest.h>
|
|
|
|
#import "FirebaseCore/Extension/FirebaseCoreInternal.h"
|
|
|
|
#import "FirebasePerformance/Sources/Configurations/FPRConfigurations+Private.h"
|
|
#import "FirebasePerformance/Sources/FPRClient+Private.h"
|
|
#import "FirebasePerformance/Sources/FPRClient.h"
|
|
#import "FirebasePerformance/Sources/FPRNanoPbUtils.h"
|
|
#import "FirebasePerformance/Sources/Loggers/FPRGDTLogger.h"
|
|
#import "FirebasePerformance/Sources/Loggers/FPRGDTLogger_Private.h"
|
|
|
|
#import "FirebasePerformance/Tests/Unit/Configurations/FPRFakeRemoteConfig.h"
|
|
#import "FirebasePerformance/Tests/Unit/FPRTestCase.h"
|
|
#import "FirebasePerformance/Tests/Unit/FPRTestUtils.h"
|
|
#import "FirebasePerformance/Tests/Unit/Fakes/FPRFakeConfigurations.h"
|
|
#import "FirebasePerformance/Tests/Unit/Fakes/FPRFakeInstallations.h"
|
|
|
|
#import <OCMock/OCMock.h>
|
|
#import "SharedTestUtilities/GDTCORTransportFake.h"
|
|
|
|
NSString *const kFPRMockInstallationId = @"mockId";
|
|
|
|
@interface FPRClientTest : FPRTestCase
|
|
|
|
/** Configuration which can be assigned as a fake object for event dispatch control. */
|
|
@property(nonatomic) FPRConfigurations *configurations;
|
|
|
|
/** Fireperf client object which can be used for fake object injection and assertion . */
|
|
@property(nonatomic) FPRClient *client;
|
|
|
|
@end
|
|
|
|
@implementation FPRClientTest
|
|
|
|
- (void)setUp {
|
|
[super setUp];
|
|
|
|
// Arrange installations object.
|
|
FPRFakeInstallations *installations = [FPRFakeInstallations installations];
|
|
self.client = [[FPRClient alloc] init];
|
|
installations.identifier = kFPRMockInstallationId;
|
|
self.client.installations = (FIRInstallations *)installations;
|
|
|
|
// Arrange remote config object.
|
|
FPRFakeConfigurations *fakeConfigs =
|
|
[[FPRFakeConfigurations alloc] initWithSources:FPRConfigurationSourceRemoteConfig];
|
|
self.configurations = fakeConfigs;
|
|
fakeConfigs.dataCollectionEnabled = YES;
|
|
fakeConfigs.sdkEnabled = YES;
|
|
self.client.configuration = self.configurations;
|
|
|
|
// Arrange gdtLogger object for event dispatch.
|
|
self.client.gdtLogger = [[FPRGDTLogger alloc] initWithLogSource:1];
|
|
GDTCORTransportFake *fakeGdtTransport =
|
|
[[GDTCORTransportFake alloc] initWithMappingID:@"1" transformers:nil target:kGDTCORTargetFLL];
|
|
self.client.gdtLogger.gdtfllTransport = fakeGdtTransport;
|
|
}
|
|
|
|
/** Validates if the gdtTransport logger has received trace perfMetric. */
|
|
- (void)testLogAndProcessEventsForTrace {
|
|
// Trace type PerfMetric for event dispatch.
|
|
firebase_perf_v1_PerfMetric perfMetric = [FPRTestUtils createRandomPerfMetric:@"RandomTrace"];
|
|
|
|
// Act on event logging call.
|
|
[self.client processAndLogEvent:perfMetric];
|
|
|
|
firebase_perf_v1_PerfMetric expectedMetric = perfMetric;
|
|
expectedMetric.application_info.app_instance_id = FPREncodeString(kFPRMockInstallationId);
|
|
|
|
// Wait for async job to execute event logging.
|
|
dispatch_group_wait(self.client.eventsQueueGroup, DISPATCH_TIME_FOREVER);
|
|
|
|
// Validate the event is received by gdtTransport logger.
|
|
dispatch_sync(self.client.gdtLogger.queue, ^{
|
|
GDTCORTransportFake *fakeGdtTransport =
|
|
(GDTCORTransportFake *)self.client.gdtLogger.gdtfllTransport;
|
|
XCTAssertEqual(fakeGdtTransport.logEvents.count, 1);
|
|
GDTCOREvent *event = fakeGdtTransport.logEvents.firstObject;
|
|
XCTAssertNotNil(
|
|
FPRDecodeString([(FPRGDTEvent *)event.dataObject metric].application_info.app_instance_id));
|
|
XCTAssertEqualObjects([event.dataObject transportBytes],
|
|
[[FPRGDTEvent gdtEventForPerfMetric:expectedMetric] transportBytes]);
|
|
});
|
|
}
|
|
|
|
/** Validates if the gdtTransport logger has received network trace perfMetric. */
|
|
- (void)testLogAndProcessEventsForNetworkTrace {
|
|
// Network type PerfMetric for event dispatch.
|
|
firebase_perf_v1_PerfMetric perfMetric =
|
|
[FPRTestUtils createRandomNetworkPerfMetric:@"https://abc.xyz"];
|
|
|
|
// Act on event logging call.
|
|
[self.client processAndLogEvent:perfMetric];
|
|
|
|
firebase_perf_v1_PerfMetric expectedMetric = perfMetric;
|
|
expectedMetric.application_info.app_instance_id = FPREncodeString(kFPRMockInstallationId);
|
|
|
|
// Wait for async job to execute event logging.
|
|
dispatch_group_wait(self.client.eventsQueueGroup, DISPATCH_TIME_FOREVER);
|
|
|
|
// Validate the event is received by gdtTransport logger.
|
|
dispatch_sync(self.client.gdtLogger.queue, ^{
|
|
GDTCORTransportFake *fakeGdtTransport =
|
|
(GDTCORTransportFake *)self.client.gdtLogger.gdtfllTransport;
|
|
XCTAssertEqual(fakeGdtTransport.logEvents.count, 1);
|
|
GDTCOREvent *event = fakeGdtTransport.logEvents.firstObject;
|
|
XCTAssertNotNil(
|
|
FPRDecodeString([(FPRGDTEvent *)event.dataObject metric].application_info.app_instance_id));
|
|
XCTAssertEqualObjects([event.dataObject transportBytes],
|
|
[[FPRGDTEvent gdtEventForPerfMetric:expectedMetric] transportBytes]);
|
|
});
|
|
}
|
|
|
|
/** Validates if the gdtTransport logger has received session gauge perfMetric. */
|
|
- (void)testLogAndProcessEventsForGauge {
|
|
// Gauge type PerfMetric for event dispatch.
|
|
firebase_perf_v1_PerfMetric perfMetric = [FPRTestUtils createRandomGaugePerfMetric];
|
|
|
|
// Act on event logging call.
|
|
[self.client processAndLogEvent:perfMetric];
|
|
|
|
firebase_perf_v1_PerfMetric expectedMetric = perfMetric;
|
|
expectedMetric.application_info.app_instance_id = FPREncodeString(kFPRMockInstallationId);
|
|
|
|
// Wait for async job to execute event logging.
|
|
dispatch_group_wait(self.client.eventsQueueGroup, DISPATCH_TIME_FOREVER);
|
|
|
|
// Validate the event is received by gdtTransport logger.
|
|
dispatch_sync(self.client.gdtLogger.queue, ^{
|
|
GDTCORTransportFake *fakeGdtTransport =
|
|
(GDTCORTransportFake *)self.client.gdtLogger.gdtfllTransport;
|
|
XCTAssertEqual(fakeGdtTransport.logEvents.count, 1);
|
|
GDTCOREvent *event = fakeGdtTransport.logEvents.firstObject;
|
|
XCTAssertNotNil(
|
|
FPRDecodeString([(FPRGDTEvent *)event.dataObject metric].application_info.app_instance_id));
|
|
XCTAssertEqualObjects([event.dataObject transportBytes],
|
|
[[FPRGDTEvent gdtEventForPerfMetric:expectedMetric] transportBytes]);
|
|
});
|
|
}
|
|
|
|
/** Validates if the gdtTransport logger will not receive event when data collection is disabled. */
|
|
- (void)testLogAndProcessEventsNotDispatchWhenDisabled {
|
|
// Trace type PerfMetric for event dispatch.
|
|
firebase_perf_v1_PerfMetric perfMetric = [FPRTestUtils createRandomPerfMetric:@"RandomTrace"];
|
|
|
|
// Act on event logging call when data collection is disabled.
|
|
self.configurations.dataCollectionEnabled = NO;
|
|
[self.client processAndLogEvent:perfMetric];
|
|
|
|
// Wait for async job to execute event logging.
|
|
dispatch_group_wait(self.client.eventsQueueGroup, DISPATCH_TIME_FOREVER);
|
|
|
|
// Validate the event is not received by gdtTransport logger.
|
|
dispatch_sync(self.client.gdtLogger.queue, ^{
|
|
GDTCORTransportFake *fakeGdtTransport =
|
|
(GDTCORTransportFake *)self.client.gdtLogger.gdtfllTransport;
|
|
XCTAssertEqual(fakeGdtTransport.logEvents.count, 0);
|
|
});
|
|
}
|
|
|
|
/** Validates if the gdtTransport logger will resume receiving event when data collection is
|
|
* re-enabled. */
|
|
- (void)testLogAndProcessEventsAfterReenabled {
|
|
// Trace type PerfMetric for event dispatch.
|
|
firebase_perf_v1_PerfMetric perfMetric = [FPRTestUtils createRandomPerfMetric:@"RandomTrace"];
|
|
|
|
// Act on event logging call when data collection is disabled.
|
|
self.configurations.dataCollectionEnabled = NO;
|
|
[self.client processAndLogEvent:perfMetric];
|
|
|
|
// Wait for async job to execute event logging.
|
|
dispatch_group_wait(self.client.eventsQueueGroup, DISPATCH_TIME_FOREVER);
|
|
|
|
// Validate the event is not received by gdtTransport logger.
|
|
dispatch_sync(self.client.gdtLogger.queue, ^{
|
|
GDTCORTransportFake *fakeGdtTransport =
|
|
(GDTCORTransportFake *)self.client.gdtLogger.gdtfllTransport;
|
|
XCTAssertEqual(fakeGdtTransport.logEvents.count, 0);
|
|
});
|
|
|
|
// Act on event logging call after re-enable data collection.
|
|
self.configurations.dataCollectionEnabled = YES;
|
|
[self.client processAndLogEvent:perfMetric];
|
|
|
|
// Wait for async job to execute event logging.
|
|
dispatch_group_wait(self.client.eventsQueueGroup, DISPATCH_TIME_FOREVER);
|
|
|
|
// Validate the event is received by gdtTransport logger.
|
|
dispatch_sync(self.client.gdtLogger.queue, ^{
|
|
GDTCORTransportFake *fakeGdtTransport =
|
|
(GDTCORTransportFake *)self.client.gdtLogger.gdtfllTransport;
|
|
XCTAssertEqual(fakeGdtTransport.logEvents.count, 1);
|
|
});
|
|
}
|
|
|
|
/** Validates that the Clearcut log directory removal method is called. */
|
|
- (void)testClearcutLogDirectoryCleanupInitiates {
|
|
id clientMock = OCMClassMock(self.client.class);
|
|
[self.client startWithConfiguration:[[FPRConfiguration alloc] initWithAppID:@"RandomAppId"
|
|
APIKey:nil
|
|
autoPush:YES]
|
|
error:nil];
|
|
|
|
// Wait for async job to initiate cleanup logic.
|
|
dispatch_group_wait(self.client.eventsQueueGroup, DISPATCH_TIME_FOREVER);
|
|
|
|
OCMVerify([clientMock cleanupClearcutCacheDirectory]);
|
|
}
|
|
|
|
/**
|
|
* Validates that the log directory path in the cache directory created for Clearcut logs storage
|
|
* gets removed (if exist).
|
|
*/
|
|
- (void)testValidateClearcutLogDirectoryCleanupIfExists {
|
|
// Create the log directory and make sure it exists.
|
|
NSString *logDirectoryPath = [FPRClient logDirectoryPath];
|
|
[[NSFileManager defaultManager] createDirectoryAtPath:logDirectoryPath
|
|
withIntermediateDirectories:YES
|
|
attributes:nil
|
|
error:nil];
|
|
|
|
BOOL logDirectoryExists = [[NSFileManager defaultManager] fileExistsAtPath:logDirectoryPath];
|
|
XCTAssertTrue(logDirectoryExists);
|
|
|
|
[FPRClient cleanupClearcutCacheDirectory];
|
|
|
|
logDirectoryExists = [[NSFileManager defaultManager] fileExistsAtPath:logDirectoryPath];
|
|
XCTAssertFalse(logDirectoryExists);
|
|
}
|
|
|
|
/**
|
|
* Validates that the Clearcut log directory path removal logic doesn't explode if directory doesn't
|
|
* exist.
|
|
*/
|
|
- (void)testValidateClearcutLogDirectoryCleanupIfNotExists {
|
|
NSString *logDirectoryPath = [FPRClient logDirectoryPath];
|
|
BOOL logDirectoryExists = [[NSFileManager defaultManager] fileExistsAtPath:logDirectoryPath];
|
|
|
|
XCTAssertFalse(logDirectoryExists);
|
|
XCTAssertNoThrow([FPRClient cleanupClearcutCacheDirectory]);
|
|
}
|
|
|
|
#pragma mark - Component Registration Tests
|
|
|
|
- (void)testRegistersAsLibrary {
|
|
// Configure a test FIRApp.
|
|
NSString *appName = @"__FIRAPP_DEFAULT";
|
|
[FIRApp configureWithName:appName options:[self fakeOptions]];
|
|
FIRApp *app = [FIRApp appNamed:appName];
|
|
|
|
// Attempt to fetch the component and verify it's a valid instance.
|
|
id<FIRPerformanceProvider> provider = FIR_COMPONENT(FIRPerformanceProvider, app.container);
|
|
XCTAssertNotNil(provider);
|
|
|
|
// Ensure that the instance that comes from the container is cached.
|
|
id<FIRPerformanceProvider> sameProvider = FIR_COMPONENT(FIRPerformanceProvider, app.container);
|
|
XCTAssertNotNil(sameProvider);
|
|
XCTAssertEqual(provider, sameProvider);
|
|
}
|
|
|
|
- (void)testFailsRegistrationForNonDefaultApp {
|
|
// Configure a test FIRApp.
|
|
NSString *appName = @"some_random_app";
|
|
[FIRApp configureWithName:appName options:[self fakeOptions]];
|
|
FIRApp *app = [FIRApp appNamed:appName];
|
|
|
|
// Attempt to fetch the component and verify it's a valid instance.
|
|
id<FIRPerformanceProvider> provider = FIR_COMPONENT(FIRPerformanceProvider, app.container);
|
|
XCTAssertNil(provider);
|
|
}
|
|
|
|
#pragma mark - Helpers
|
|
|
|
- (FIROptions *)fakeOptions {
|
|
FIROptions *options = [[FIROptions alloc] initWithGoogleAppID:@"1:123:ios:123abc"
|
|
GCMSenderID:@"correct_gcm_sender_id"];
|
|
options.APIKey = @"AIzaSy-ApiKeyWithValidFormat_0123456789";
|
|
options.projectID = @"project-id";
|
|
return options;
|
|
}
|
|
|
|
@end
|