blob: dad9c170cac8ed75717d4ab0831d760cf1091d20 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/app/app_metrics_app_state_agent.h"
#import "base/test/task_environment.h"
#import "ios/chrome/app/application_delegate/app_init_stage_test_utils.h"
#import "ios/chrome/app/application_delegate/app_state.h"
#import "ios/chrome/app/application_delegate/metrics_mediator.h"
#import "ios/chrome/browser/shared/coordinator/scene/scene_state.h"
#import "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#import "third_party/ocmock/gtest_support.h"
// A fake that allows overriding connectedScenes.
@interface FakeAppState : AppState
@property(nonatomic, strong) NSArray<SceneState*>* connectedScenes;
// Init stage that will be returned by the initStage getter when testing.
@property(nonatomic, assign) AppInitStage initStageForTesting;
@end
@implementation FakeAppState
- (AppInitStage)initStage {
return self.initStageForTesting;
}
@end
AppInitStage GetMinimalInitStageThatAllowsLogging() {
return AppInitStage::kBrowserObjectsForBackgroundHandlers;
}
AppInitStage GetMaximalInitStageThatDontAllowLogging() {
return PreviousAppInitStage(GetMinimalInitStageThatAllowsLogging());
}
class AppMetricsAppStateAgentTest : public PlatformTest {
protected:
AppMetricsAppStateAgentTest() {
agent_ = [[AppMetricsAppStateAgent alloc] init];
app_state_ = [[FakeAppState alloc] initWithStartupInformation:nil];
}
void SetUp() override {
PlatformTest::SetUp();
app_state_.initStageForTesting = GetMinimalInitStageThatAllowsLogging();
[agent_ setAppState:app_state_];
}
void SimulateTransitionToCurrentStage() {
AppInitStage previousStage =
app_state_.initStage == AppInitStage::kStart
? AppInitStage::kStart
: PreviousAppInitStage(app_state_.initStage);
[agent_ appState:app_state_ didTransitionFromInitStage:previousStage];
}
AppMetricsAppStateAgent* agent_;
FakeAppState* app_state_;
};
// Tests that -logStartupDuration: and -createStartupTrackingTask are called
// once and in the right order for a regular startup (no safe mode).
TEST_F(AppMetricsAppStateAgentTest, LogStartupDuration) {
base::test::SingleThreadTaskEnvironment task_environment;
id metricsMediator = [OCMockObject mockForClass:[MetricsMediator class]];
[[metricsMediator expect] createStartupTrackingTask];
[[metricsMediator expect] logStartupDuration:nil];
[metricsMediator setExpectationOrderMatters:YES];
SceneState* sceneA = [[SceneState alloc] initWithAppState:app_state_];
SceneState* sceneB = [[SceneState alloc] initWithAppState:app_state_];
app_state_.connectedScenes = @[ sceneA, sceneB ];
[agent_ appState:app_state_ sceneConnected:sceneA];
[agent_ appState:app_state_ sceneConnected:sceneB];
// Simulate transitioning to the current app init stage before scenes going on
// the foreground.
AppInitStage previousInitStage = PreviousAppInitStage(app_state_.initStage);
[agent_ appState:app_state_ didTransitionFromInitStage:previousInitStage];
// Should not log startup duration until the scene is active.
sceneA.activationLevel = SceneActivationLevelForegroundInactive;
sceneB.activationLevel = SceneActivationLevelForegroundInactive;
// Should only log startup once when the first scene becomes active.
sceneA.activationLevel = SceneActivationLevelForegroundActive;
sceneB.activationLevel = SceneActivationLevelForegroundActive;
// Should not log startup when scene becomes active again.
sceneA.activationLevel = SceneActivationLevelBackground;
sceneB.activationLevel = SceneActivationLevelBackground;
sceneA.activationLevel = SceneActivationLevelForegroundActive;
sceneB.activationLevel = SceneActivationLevelForegroundActive;
EXPECT_OCMOCK_VERIFY(metricsMediator);
}
// Tests that -logStartupDuration: and and -createStartupTrackingTask are not
// called when there is safe mode during startup.
TEST_F(AppMetricsAppStateAgentTest, LogStartupDurationWhenSafeMode) {
id metricsMediator = [OCMockObject mockForClass:[MetricsMediator class]];
[[metricsMediator reject] createStartupTrackingTask];
[[metricsMediator reject] logStartupDuration:nil];
app_state_.initStageForTesting = GetMaximalInitStageThatDontAllowLogging();
SceneState* sceneA = [[SceneState alloc] initWithAppState:app_state_];
app_state_.connectedScenes = @[ sceneA ];
[agent_ appState:app_state_ sceneConnected:sceneA];
// Simulate transitioning to the current app init stage before scenes going on
// the foreground.
AppInitStage previousInitStage = PreviousAppInitStage(app_state_.initStage);
[agent_ appState:app_state_ didTransitionFromInitStage:previousInitStage];
// This would normally log startup information, but not when in safe mode.
sceneA.activationLevel = SceneActivationLevelForegroundActive;
EXPECT_OCMOCK_VERIFY(metricsMediator);
}