| Index: ios/chrome/app/application_delegate/metrics_mediator_unittest.mm
|
| diff --git a/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm b/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..67b1ca2c13a5072e047da273d24f56219fd17f94
|
| --- /dev/null
|
| +++ b/ios/chrome/app/application_delegate/metrics_mediator_unittest.mm
|
| @@ -0,0 +1,276 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#import "ios/chrome/app/application_delegate/metrics_mediator.h"
|
| +#import "ios/chrome/app/application_delegate/metrics_mediator_testing.h"
|
| +
|
| +#import <Foundation/Foundation.h>
|
| +
|
| +#include "base/mac/scoped_block.h"
|
| +#include "base/mac/scoped_nsobject.h"
|
| +#import "breakpad/src/client/ios/BreakpadController.h"
|
| +#include "components/metrics/metrics_service.h"
|
| +#import "ios/chrome/app/application_delegate/startup_information.h"
|
| +#include "ios/chrome/browser/application_context.h"
|
| +#import "ios/chrome/browser/metrics/previous_session_info.h"
|
| +#import "ios/chrome/browser/metrics/previous_session_info_private.h"
|
| +#import "ios/chrome/browser/tabs/tab_model.h"
|
| +#import "ios/chrome/browser/ui/main/browser_view_information.h"
|
| +#import "ios/chrome/test/base/scoped_block_swizzler.h"
|
| +#import "ios/chrome/test/ocmock/OCMockObject+BreakpadControllerTesting.h"
|
| +#include "net/base/network_change_notifier.h"
|
| +#include "testing/platform_test.h"
|
| +#import "third_party/ocmock/OCMock/OCMock.h"
|
| +#include "third_party/ocmock/gtest_support.h"
|
| +
|
| +#pragma mark - connectionTypeChanged tests.
|
| +
|
| +// Mock class for testing MetricsMediator.
|
| +@interface MetricsMediatorMock : MetricsMediator
|
| +@property(nonatomic) NSInteger reportingValue;
|
| +@property(nonatomic) NSInteger breakpadUpload;
|
| +- (void)reset;
|
| +- (void)setReporting:(BOOL)enableReporting;
|
| +@end
|
| +
|
| +@implementation MetricsMediatorMock
|
| +@synthesize reportingValue = _reportingValue;
|
| +@synthesize breakpadUpload = _breakpadUpload;
|
| +
|
| +- (void)reset {
|
| + _reportingValue = -1;
|
| + _breakpadUpload = -1;
|
| +}
|
| +- (void)setBreakpadUploadingEnabled:(BOOL)enableUploading {
|
| + _breakpadUpload = enableUploading ? 1 : 0;
|
| +}
|
| +- (void)setReporting:(BOOL)enableReporting {
|
| + _reportingValue = enableReporting ? 1 : 0;
|
| +}
|
| +- (BOOL)isMetricsReportingEnabledWifiOnly {
|
| + return YES;
|
| +}
|
| +- (BOOL)areMetricsEnabled {
|
| + return YES;
|
| +}
|
| +
|
| +@end
|
| +
|
| +// Gives the differents net::NetworkChangeNotifier::ConnectionType based on
|
| +// scenario number.
|
| +net::NetworkChangeNotifier::ConnectionType getConnectionType(int number) {
|
| + switch (number) {
|
| + case 0:
|
| + return net::NetworkChangeNotifier::CONNECTION_UNKNOWN;
|
| + case 1:
|
| + return net::NetworkChangeNotifier::CONNECTION_ETHERNET;
|
| + case 2:
|
| + return net::NetworkChangeNotifier::CONNECTION_WIFI;
|
| + case 3:
|
| + return net::NetworkChangeNotifier::CONNECTION_2G;
|
| + case 4:
|
| + return net::NetworkChangeNotifier::CONNECTION_3G;
|
| + case 5:
|
| + return net::NetworkChangeNotifier::CONNECTION_4G;
|
| + case 6:
|
| + return net::NetworkChangeNotifier::CONNECTION_NONE;
|
| + case 7:
|
| + return net::NetworkChangeNotifier::CONNECTION_BLUETOOTH;
|
| + default:
|
| + return net::NetworkChangeNotifier::CONNECTION_UNKNOWN;
|
| + }
|
| +}
|
| +
|
| +// Gives the differents expected value based on scenario number.
|
| +int getExpectedValue(int number) {
|
| + if (number > 2 && number < 6)
|
| + return 0;
|
| + return 1;
|
| +}
|
| +
|
| +// Verifies that connectionTypeChanged correctly enables or disables the
|
| +// uploading in the breakpad and in the metrics service.
|
| +TEST(MetricsMediatorTest, connectionTypeChanged) {
|
| + [[PreviousSessionInfo sharedInstance] setIsFirstSessionAfterUpgrade:NO];
|
| + base::scoped_nsobject<MetricsMediatorMock> mock_metrics_helper(
|
| + [[MetricsMediatorMock alloc] init]);
|
| +
|
| + // Checks all different scenarios.
|
| + for (int i = 0; i < 8; ++i) {
|
| + [mock_metrics_helper reset];
|
| + [mock_metrics_helper connectionTypeChanged:getConnectionType(i)];
|
| + EXPECT_EQ(getExpectedValue(i), [mock_metrics_helper reportingValue]);
|
| + EXPECT_EQ(getExpectedValue(i), [mock_metrics_helper breakpadUpload]);
|
| + }
|
| +
|
| + // Checks that no new ConnectionType has been added.
|
| + EXPECT_EQ(net::NetworkChangeNotifier::CONNECTION_BLUETOOTH,
|
| + net::NetworkChangeNotifier::CONNECTION_LAST);
|
| +}
|
| +
|
| +#pragma mark - logLaunchMetrics tests.
|
| +
|
| +// A block that takes as arguments the caller and the arguments from
|
| +// UserActivityHandler +handleStartupParameters and returns nothing.
|
| +typedef void (^logLaunchMetricsBlock)(id, const char*, int);
|
| +
|
| +class MetricsMediatorLogLaunchTest : public PlatformTest {
|
| + protected:
|
| + MetricsMediatorLogLaunchTest() : has_been_called_(FALSE) {}
|
| +
|
| + void initiateMetricsMediator(BOOL coldStart, int tabCount) {
|
| + id mainTabModel = [OCMockObject mockForClass:[TabModel class]];
|
| + [[[mainTabModel stub] andReturnValue:@(tabCount)] count];
|
| + browser_view_information_ =
|
| + [OCMockObject mockForProtocol:@protocol(BrowserViewInformation)];
|
| + [[[browser_view_information_ stub] andReturn:mainTabModel] mainTabModel];
|
| +
|
| + swizzle_block_.reset([^(id self, int numTab) {
|
| + has_been_called_ = YES;
|
| + // Tests.
|
| + EXPECT_EQ(tabCount, numTab);
|
| + } copy]);
|
| + if (coldStart) {
|
| + uma_histogram_swizzler_.reset(new ScopedBlockSwizzler(
|
| + [MetricsMediator class], @selector(recordNumTabAtStartup:),
|
| + swizzle_block_));
|
| + } else {
|
| + uma_histogram_swizzler_.reset(new ScopedBlockSwizzler(
|
| + [MetricsMediator class], @selector(recordNumTabAtResume:),
|
| + swizzle_block_));
|
| + }
|
| + }
|
| +
|
| + void verifySwizzleHasBeenCalled() { EXPECT_TRUE(has_been_called_); }
|
| +
|
| + id getBrowserViewInformation() { return browser_view_information_; }
|
| +
|
| + private:
|
| + id browser_view_information_;
|
| + __block BOOL has_been_called_;
|
| + base::mac::ScopedBlock<logLaunchMetricsBlock> swizzle_block_;
|
| + std::unique_ptr<ScopedBlockSwizzler> uma_histogram_swizzler_;
|
| +};
|
| +
|
| +// Verifies that the log of the number of open tabs is sent and verifies
|
| +TEST_F(MetricsMediatorLogLaunchTest,
|
| + logLaunchMetricsWithEnteredBackgroundDate) {
|
| + // Setup.
|
| + BOOL coldStart = YES;
|
| + initiateMetricsMediator(coldStart, 23);
|
| +
|
| + const NSTimeInterval kFirstUserActionTimeout = 30.0;
|
| +
|
| + id startupInformation =
|
| + [OCMockObject niceMockForProtocol:@protocol(StartupInformation)];
|
| + [[[startupInformation stub] andReturnValue:@(coldStart)] isColdStart];
|
| + [[startupInformation expect]
|
| + expireFirstUserActionRecorderAfterDelay:kFirstUserActionTimeout];
|
| +
|
| + id currentTabModel = [OCMockObject mockForClass:[TabModel class]];
|
| + [[[currentTabModel stub] andReturn:nil] currentTab];
|
| +
|
| + id browserViewInformation = getBrowserViewInformation();
|
| + [[[browserViewInformation stub] andReturn:currentTabModel] currentTabModel];
|
| +
|
| + [[NSUserDefaults standardUserDefaults]
|
| + setObject:[NSDate date]
|
| + forKey:metrics_mediator::kAppEnteredBackgroundDateKey];
|
| +
|
| + // Action.
|
| + [MetricsMediator
|
| + logLaunchMetricsWithStartupInformation:startupInformation
|
| + browserViewInformation:getBrowserViewInformation()];
|
| +
|
| + // Tests.
|
| + NSDate* dateStored = [[NSUserDefaults standardUserDefaults]
|
| + objectForKey:metrics_mediator::kAppEnteredBackgroundDateKey];
|
| + EXPECT_EQ(nil, dateStored);
|
| + verifySwizzleHasBeenCalled();
|
| + EXPECT_OCMOCK_VERIFY(startupInformation);
|
| +}
|
| +
|
| +// Verifies that +logLaunchMetrics logs of the number of open tabs and nothing
|
| +// more if the background date is not set;
|
| +TEST_F(MetricsMediatorLogLaunchTest, logLaunchMetricsNoBackgroundDate) {
|
| + // Setup.
|
| + BOOL coldStart = NO;
|
| + initiateMetricsMediator(coldStart, 32);
|
| +
|
| + id startupInformation =
|
| + [OCMockObject mockForProtocol:@protocol(StartupInformation)];
|
| + [[[startupInformation stub] andReturnValue:@(coldStart)] isColdStart];
|
| +
|
| + [[NSUserDefaults standardUserDefaults]
|
| + removeObjectForKey:metrics_mediator::kAppEnteredBackgroundDateKey];
|
| +
|
| + // Action.
|
| + [MetricsMediator
|
| + logLaunchMetricsWithStartupInformation:startupInformation
|
| + browserViewInformation:getBrowserViewInformation()];
|
| +
|
| + // Tests.
|
| + verifySwizzleHasBeenCalled();
|
| +}
|
| +
|
| +// Tests that +logDateInUserDefaults logs the date in UserDefaults.
|
| +TEST(MetricsMediatorNoFixtureTest, logDateInUserDefaultsTest) {
|
| + // Setup.
|
| + [[NSUserDefaults standardUserDefaults]
|
| + removeObjectForKey:metrics_mediator::kAppEnteredBackgroundDateKey];
|
| +
|
| + NSDate* lastAppClose = [[NSUserDefaults standardUserDefaults]
|
| + objectForKey:metrics_mediator::kAppEnteredBackgroundDateKey];
|
| +
|
| + ASSERT_EQ(nil, lastAppClose);
|
| +
|
| + // Action.
|
| + [MetricsMediator logDateInUserDefaults];
|
| +
|
| + // Setup.
|
| + lastAppClose = [[NSUserDefaults standardUserDefaults]
|
| + objectForKey:metrics_mediator::kAppEnteredBackgroundDateKey];
|
| + EXPECT_NE(nil, lastAppClose);
|
| +}
|
| +
|
| +#pragma mark - processCrashReportsPresentAtStartup tests.
|
| +
|
| +class MetricsMediatorShutdownTypeTest : public testing::TestWithParam<int> {};
|
| +
|
| +// Verifies that the Breakpad controller gets called appropriately when
|
| +// processCrashReportsPresentAtStartup is invoked.
|
| +//
|
| +// This parameterized test receives an int parameter that is the crash log
|
| +// count waiting to be processed.
|
| +TEST_P(MetricsMediatorShutdownTypeTest, ProcessCrashReportsPresentAtStartup) {
|
| + // Create a MainController.
|
| + base::scoped_nsobject<MetricsMediator> metric_helper(
|
| + [[MetricsMediator alloc] init]);
|
| +
|
| + // Create a mock for BreakpadController and swizzle
|
| + // +[BreakpadController sharedInstance] to return the mock instead of the
|
| + // normal singleton instance.
|
| + base::scoped_nsobject<id> mock_breakpad_controller(
|
| + [[OCMockObject mockForClass:[BreakpadController class]] retain]);
|
| +
|
| + id implementation_block = ^BreakpadController*(id self) {
|
| + return mock_breakpad_controller.get();
|
| + };
|
| + ScopedBlockSwizzler breakpad_controller_shared_instance_swizzler(
|
| + [BreakpadController class], @selector(sharedInstance),
|
| + implementation_block);
|
| +
|
| + // Create the mock expectation for calling
|
| + // -[BreakpadController getCrashReportCount].
|
| + [mock_breakpad_controller cr_expectGetCrashReportCount:GetParam()];
|
| +
|
| + // Now call the method under test and verify that the Breakpad controller got
|
| + // called appropriately.
|
| + [metric_helper processCrashReportsPresentAtStartup];
|
| + EXPECT_OCMOCK_VERIFY(mock_breakpad_controller.get());
|
| +}
|
| +
|
| +INSTANTIATE_TEST_CASE_P(/* No InstantiationName */,
|
| + MetricsMediatorShutdownTypeTest,
|
| + ::testing::Values(0, 1, 42));
|
|
|