Commit 24ddbe83 authored by Caitlin Fischer's avatar Caitlin Fischer Committed by Commit Bot

Add UKM Demographic Earl Grey tests.

The tests in ukm_egtest.mm should be kept in sync with those in
//chrome/browser/metrics/ukm_browsertest.cc. The test in
ukm_browsertest.cc for which EG are being added is
AddSyncedUserBirthYearAndGenderToProtoData.

(A second CL will be sent for tests corresponding to those in
metrics_service_user_demographics_browsertest.cc.)

Bug: 1065870
Change-Id: I5ad386a0b96cbb1feea51676a908374d13863819
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2127247
Commit-Queue: Caitlin Fischer <caitlinfischer@google.com>
Reviewed-by: default avatarAlexei Svitkine <asvitkine@chromium.org>
Reviewed-by: default avatarRoger McFarlane <rogerm@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#755470}
parent d97ba0b8
......@@ -228,6 +228,7 @@ source_set("eg_tests") {
configs += [ "//build/config/compiler:enable_arc" ]
testonly = true
sources = [
"demographics_egtest.mm",
"tab_usage_recorder_egtest.mm",
"ukm_egtest.mm",
]
......@@ -239,6 +240,7 @@ source_set("eg_tests") {
"//base/test:test_support",
"//components/browser_sync",
"//components/metrics",
"//components/metrics:demographic_metrics_provider",
"//components/metrics_services_manager",
"//components/strings",
"//components/ukm",
......@@ -283,6 +285,7 @@ source_set("eg2_tests") {
]
testonly = true
sources = [
"demographics_egtest.mm",
"tab_usage_recorder_egtest.mm",
"ukm_egtest.mm",
]
......@@ -290,7 +293,9 @@ source_set("eg2_tests") {
":eg_test_support+eg2",
":tab_usage_recorder_metrics",
"//base/test:test_support",
"//components/metrics:demographic_metrics_provider",
"//components/strings:components_strings_grit",
"//components/ukm",
"//ios/chrome/app/strings:ios_strings_grit",
"//ios/chrome/browser/ui/authentication:eg_test_support+eg2",
"//ios/chrome/test:eg_test_support+eg2",
......@@ -316,11 +321,15 @@ source_set("test_support") {
":metrics",
"//base",
"//base/test:test_support",
"//components/metrics",
"//components/metrics_services_manager",
"//components/network_time",
"//components/sync/base",
"//components/ukm",
"//ios/chrome/app:app_internal",
"//ios/chrome/app/strings",
"//ios/chrome/browser",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/metrics:metrics_internal",
"//ios/chrome/browser/tabs",
"//ios/chrome/browser/ui/main",
......@@ -333,6 +342,10 @@ source_set("test_support") {
"//ios/testing/earl_grey:earl_grey_support",
"//net:test_support",
"//services/metrics/public/cpp:metrics_cpp",
"//third_party/metrics_proto",
#TODO(crbug.com/1066297): Remove the below line.
"//third_party/zlib/google:compression_utils",
"//ui/base",
]
configs += [ "//build/config/compiler:enable_arc" ]
......@@ -365,15 +378,20 @@ source_set("eg_app_support+eg2") {
deps = [
"//base",
"//base/test:test_support",
"//components/metrics",
"//components/metrics_services_manager",
"//components/metrics_services_manager:metrics_services_manager",
"//components/network_time",
"//components/sync/base",
"//components/ukm",
"//ios/chrome/browser",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/metrics",
"//ios/chrome/browser/metrics:metrics_internal",
"//ios/chrome/test/app:test_support",
"//ios/testing:nserror_support",
"//services/metrics/public/cpp:metrics_cpp",
"//third_party/metrics_proto",
"//third_party/zlib/google:compression_utils",
]
}
......
......@@ -4,4 +4,8 @@ specific_include_rules = {
"tab_usage_recorder_egtest\.mm": [
"+ios/web/public/test/http_server",
],
"metrics_app_interface\.mm": [
"+third_party/zlib/google/compression_utils.h",
],
}
// Copyright 2020 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.
#include "base/macros.h"
#import "base/test/ios/wait_util.h"
#include "base/time/default_clock.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "components/metrics/demographic_metrics_provider.h"
#include "components/ukm/ukm_service.h"
#import "ios/chrome/browser/metrics/metrics_app_interface.h"
#import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h"
#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
#import "ios/chrome/test/earl_grey/chrome_test_case.h"
#import "ios/testing/earl_grey/app_launch_configuration.h"
#import "ios/testing/earl_grey/earl_grey_test.h"
#include "third_party/metrics_proto/user_demographics.pb.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
const int kTestBirthYear = 1990;
// TODO(crbug.com/1066910): Use a proto instead.
// Corresponds to GENDER_MALE in UserDemographicsProto::Gender.
const int kTestGender = 1;
} // namespace
@interface DemographicsTestCase : ChromeTestCase
@end
@implementation DemographicsTestCase
- (void)setUp {
[super setUp];
GREYAssertNil([MetricsAppInterface setupHistogramTester],
@"Failed to set up histogram tester.");
[MetricsAppInterface overrideMetricsAndCrashReportingForTesting];
[self addUserDemographicsToSyncServerWithBirthYear:kTestBirthYear
gender:kTestGender];
[self signInAndSync];
[self grantMetricsConsent];
// Set a network time so that SyncPrefs::GetUserNoisedBirthYearAndGender
// does not return a UserDemographicsResult for the kCannotGetTime status.
[MetricsAppInterface setNetworkTimeForTesting];
// Record a source in the UKM service so that there is data with which to
// generate a UKM Report.
[self addDummyUKMSource];
[MetricsAppInterface buildAndStoreUKMLog];
GREYAssertTrue([MetricsAppInterface hasUnsentLogs],
@"The UKM service should have unsent logs.");
}
- (void)tearDown {
[MetricsAppInterface stopOverridingMetricsAndCrashReportingForTesting];
GREYAssertNil([MetricsAppInterface releaseHistogramTester],
@"Failed to release histogram tester.");
[super tearDown];
}
- (AppLaunchConfiguration)appConfigurationForTestCase {
NSString* testName = [self getTestName];
AppLaunchConfiguration config;
// Features are enabled or disabled based on the name of the test that is
// running. This is done because (A) parameterized tests do not exist in Earl
// Grey and (B) it is inefficient to use ensureAppLaunchedWithConfiguration
// for each test.
//
// Note that in the if statements, @selector(testSomething) is used rather
// than @"testSomething" because the former checks that the testSomething
// method exists somewhere--but not necessarily in this class.
if ([testName isEqual:NSStringFromSelector(@selector(
testSyncAndRecordUserDemographicsEnabled))]) {
config.features_enabled.push_back(
metrics::DemographicMetricsProvider::kDemographicMetricsReporting);
config.features_enabled.push_back(
ukm::UkmService::kReportUserNoisedUserBirthYearAndGender);
} else if ([testName
isEqual:NSStringFromSelector(@selector(
testSyncAndRecordUserDemographicsDisabled))]) {
config.features_disabled.push_back(
metrics::DemographicMetricsProvider::kDemographicMetricsReporting);
config.features_disabled.push_back(
ukm::UkmService::kReportUserNoisedUserBirthYearAndGender);
}
return config;
}
#pragma mark - Helpers
// Adds user demographics, which are ModelType::PRIORITY_PREFERENCES, to the
// fake sync server. The year is the un-noised birth year, and the gender
// corresponds to the options in UserDemographicsProto::Gender.
//
// Also, verifies (A) that before adding the demographics, the server has no
// priority preferences and (B) that after adding the demographics, the server
// has one priority preference.
- (void)addUserDemographicsToSyncServerWithBirthYear:(int)year
gender:(int)gender {
GREYAssertEqual(
[ChromeEarlGrey
numberOfSyncEntitiesWithType:syncer::PRIORITY_PREFERENCES],
0, @"The fake sync server should have no priority preferences.");
[ChromeEarlGrey addUserDemographicsToSyncServerWithBirthYear:year
gender:gender];
GREYAssertEqual(
[ChromeEarlGrey
numberOfSyncEntitiesWithType:syncer::PRIORITY_PREFERENCES],
1, @"The fake sync server should have one priority preference.");
}
// Signs into Chrome with a fake identity, turns on sync, and then waits up to
// kSyncUKMOperationsTimeout for sync to initialize.
- (void)signInAndSync {
// Note that there is only one profile on iOS. Additionally, URL-keyed
// anonymized data collection is turned on as part of the flow to Sign in to
// Chrome and Turn on sync. This matches the main user flow that enables
// UKM.
[SigninEarlGreyUI signinWithFakeIdentity:[SigninEarlGreyUtils fakeIdentity1]];
[ChromeEarlGrey waitForSyncInitialized:YES
syncTimeout:syncher::kSyncUKMOperationsTimeout];
}
// Adds a dummy UKM source to the UKM service's recordings. The presence of this
// dummy source allows UKM reports to be built and logged.
- (void)addDummyUKMSource {
const uint64_t sourceId = 0x54321;
[MetricsAppInterface UKMRecordDummySource:sourceId];
GREYAssert([MetricsAppInterface UKMHasDummySource:sourceId],
@"Failed to record dummy source.");
}
// Turns on metrics collection for testing and verifies that this has been
// successfully done.
- (void)grantMetricsConsent {
GREYAssertFalse(
[MetricsAppInterface setMetricsAndCrashReportingForTesting:YES],
@"User consent has already been granted.");
GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES],
@"Failed to assert that UKM recording is enabled.");
// The client ID is non-zero after metrics uploading permissions are updated.
GREYAssertNotEqual(0U, [MetricsAppInterface UKMClientID],
@"Client ID should be non-zero.");
}
// Returns the short test name, e.g. "testSomething" of the test that is
// currently running. The short test name is extracted from the string for the
// test's name property, e.g. "-[DemographicsTestCase testSomething]".
- (NSString*)getTestName {
int testNameStart = [self.name rangeOfString:@"test"].location;
return [self.name
substringWithRange:NSMakeRange(testNameStart,
self.name.length - testNameStart - 1)];
}
#pragma mark - Tests
// The tests in this file should correspond to the demographics-related tests in
// //chrome/browser/metrics/ukm_browsertest.cc.
// Tests that user demographics are synced, recorded by UKM, and logged in
// histograms.
//
// Corresponds to AddSyncedUserBirthYearAndGenderToProtoData in
// //chrome/browser/metrics/ukm_browsertest.cc with features enabled.
- (void)testSyncAndRecordUserDemographicsEnabled {
#if defined(CHROME_EARL_GREY_1)
EARL_GREY_TEST_DISABLED(@"This test relies on EG2 utilities.");
#endif
// See |appConfigurationForTestCase| for feature set-up. The kUkmFeature is
// enabled by default.
GREYAssertTrue([ChromeEarlGrey isDemographicMetricsReportingEnabled] &&
[MetricsAppInterface
isReportUserNoisedUserBirthYearAndGenderEnabled] &&
[ChromeEarlGrey isUKMEnabled],
@"Failed to enable the requisite features.");
GREYAssertTrue([MetricsAppInterface UKMReportHasBirthYear:kTestBirthYear
gender:kTestGender],
@"The report should contain the specified user demographics");
int successBucket = 0; // 0 denotes UserDemographicsStatus::kSuccess.
GREYAssertNil([MetricsAppInterface
expectUniqueSampleWithCount:1
forBucket:successBucket
forHistogram:@"UKM.UserDemographics.Status"],
@"Unexpected histogram contents");
}
// Tests that user demographics are neither recorded by UKM nor logged in
// histograms when sync is turned on.
//
// Corresponds to AddSyncedUserBirthYearAndGenderToProtoData in
// //chrome/browser/metrics/ukm_browsertest.cc with features disabled.
- (void)testSyncAndRecordUserDemographicsDisabled {
#if defined(CHROME_EARL_GREY_1)
EARL_GREY_TEST_DISABLED(@"This test relies on EG2 utilities.");
#endif
// See |appConfigurationForTestCase| for feature set-up. The kUkmFeature is
// enabled by default.
GREYAssertFalse([ChromeEarlGrey isDemographicMetricsReportingEnabled],
@"Failed to disable kDemographicMetricsReporting.");
GREYAssertFalse(
[MetricsAppInterface isReportUserNoisedUserBirthYearAndGenderEnabled],
@"Failed to disable kReportUserNoisedUserBirthYearAndGender.");
GREYAssertTrue([ChromeEarlGrey isUKMEnabled],
@"Failed to enable kUkmFeature.");
GREYAssertFalse([MetricsAppInterface UKMReportHasUserDemographics],
@"The report should not contain user demographics.");
GREYAssertNil([MetricsAppInterface expectSum:0
forHistogram:@"UKM.UserDemographics.Status"],
@"Unexpected histogram contents.");
}
@end
......@@ -9,39 +9,73 @@
#include "base/compiler_specific.h"
// MetricsAppInterface contains the app-side
// implementation for helpers. These helpers are compiled into
// the app binary and can be called from either app or test code.
namespace syncher {
// Constant for timeout while waiting for asynchronous sync and UKM operations.
const NSTimeInterval kSyncUKMOperationsTimeout = 10.0;
} // namespace syncher
// MetricsAppInterface contains the app-side implementation for helpers. These
// helpers are compiled into the app binary and can be called from either app or
// test code.
@interface MetricsAppInterface : NSObject
// Enable/Disable the metrics in the app for test.
// |overrideMetricsAndCrashReportingForTesting| must be called before setting
// the value
// the value.
// |stopOverridingMetricsAndCrashReportingForTesting| must be called at the end
// of the test for cleanup.
// |setMetricsAndCrashReportingForTesting:| can be called to set to
// enable/disable metrics. It returns whether metrics were previously enabled.
// |setMetricsAndCrashReportingForTesting:| can be called to enable/disable
// metrics. It returns whether metrics were previously enabled.
+ (void)overrideMetricsAndCrashReportingForTesting;
+ (void)stopOverridingMetricsAndCrashReportingForTesting;
+ (BOOL)setMetricsAndCrashReportingForTesting:(BOOL)enabled;
// Returns whether the UKM recording is |enabled|.
// TODO(crbug.com/1066297): Refactor to remove duplicate code.
// Returns whether UKM recording is |enabled|.
+ (BOOL)checkUKMRecordingEnabled:(BOOL)enabled;
// Returns YES if the ReportUserNoisedUserBirthYearAndGender feature is enabled.
+ (BOOL)isReportUserNoisedUserBirthYearAndGenderEnabled WARN_UNUSED_RESULT;
// TODO(crbug.com/1066297): Refactor to remove duplicate code.
// Returns the current UKM client ID.
+ (uint64_t)UKMClientID;
// TODO(crbug.com/1066297): Refactor to remove duplicate code.
// Checks whether a sourceID is registered for UKM.
+ (BOOL)UKMHasDummySource:(int64_t)sourceId;
// TODO(crbug.com/1066297): Refactor to remove duplicate code.
// Adds a new sourceID for UKM.
+ (void)UKMRecordDummySource:(int64_t)sourceId;
// Creates a chrome_test_util::HistogramTester that will record every histograms
// TODO(crbug.com/1066297): Refactor to remove duplicate code.
// Sets the network time to approximately now.
+ (void)setNetworkTimeForTesting;
// TODO(crbug.com/1066297): Refactor to remove duplicate code.
// If new data are available, creates a UKM Report and stores it in the
// UKM service's UnsentLogStore.
+ (void)buildAndStoreUKMLog;
// TODO(crbug.com/1066297): Refactor to remove duplicate code.
// Returns YES if the UKM service has logs to send.
+ (BOOL)hasUnsentLogs;
// Returns YES if the UKM service's report has the expected year and gender.
// Gender corresponds to the options in UserDemographicsProto::Gender.
+ (BOOL)UKMReportHasBirthYear:(int)year gender:(int)gender;
// Returns YES if the UKM service's report has user demographics.
+ (BOOL)UKMReportHasUserDemographics;
// Creates a chrome_test_util::HistogramTester that will record every histogram
// sent during test.
+ (NSError*)setupHistogramTester WARN_UNUSED_RESULT;
// Released the chrome_test_util::HistogramTester.
// Releases the chrome_test_util::HistogramTester.
+ (NSError*)releaseHistogramTester WARN_UNUSED_RESULT;
// We don't know the values of the samples, but we know how many there are.
......
......@@ -4,24 +4,37 @@
#include "ios/chrome/browser/metrics/metrics_app_interface.h"
#include <memory>
#include "base/feature_list.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h"
#import "base/test/ios/wait_util.h"
#include "base/time/default_clock.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "components/metrics/unsent_log_store.h"
#include "components/metrics_services_manager/metrics_services_manager.h"
#include "components/network_time/network_time_tracker.h"
#include "components/sync/base/pref_names.h"
#include "components/ukm/ukm_service.h"
#include "ios/chrome/browser/application_context.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state_manager.h"
#include "ios/chrome/browser/metrics/ios_chrome_metrics_service_accessor.h"
#import "ios/chrome/test/app/histogram_test_util.h"
#import "ios/testing/nserror_util.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/metrics_proto/ukm/report.pb.h"
#include "third_party/metrics_proto/user_demographics.pb.h"
#include "third_party/zlib/google/compression_utils.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Constant for timeout while waiting for asynchronous sync and UKM operations.
const NSTimeInterval kSyncUKMOperationsTimeout = 10.0;
bool g_metrics_enabled = false;
......@@ -43,6 +56,11 @@ class UkmEGTestHelper {
return service ? service->recording_enabled_ : false;
}
static bool IsReportUserNoisedUserBirthYearAndGenderEnabled() {
return base::FeatureList::IsEnabled(
ukm::UkmService::kReportUserNoisedUserBirthYearAndGender);
}
static uint64_t client_id() {
auto* service = ukm_service();
return service ? service->client_id_ : 0;
......@@ -61,6 +79,53 @@ class UkmEGTestHelper {
service->UpdateSourceURL(source_id, GURL("http://example.com"));
}
static void BuildAndStoreUkmLog() {
ukm::UkmService* service = ukm_service();
// Wait for initialization to complete before flushing.
base::RunLoop run_loop;
service->SetInitializationCompleteCallbackForTesting(
run_loop.QuitClosure());
run_loop.Run();
service->Flush();
}
static bool HasUnsentLogs() {
ukm::UkmService* service = ukm_service();
return service->reporting_service_.ukm_log_store()->has_unsent_logs();
}
static std::unique_ptr<ukm::Report> GetUKMReport() {
if (!HasUnsentLogs()) {
return nullptr;
}
metrics::UnsentLogStore* log_store =
ukm_service()->reporting_service_.ukm_log_store();
if (log_store->has_staged_log()) {
// For testing purposes, we are examining the content of a staged log
// without ever sending the log, so discard any previously staged log.
log_store->DiscardStagedLog();
}
log_store->StageNextLog();
if (!log_store->has_staged_log()) {
return nullptr;
}
std::string uncompressed_log_data;
if (!compression::GzipUncompress(log_store->staged_log(),
&uncompressed_log_data)) {
return nullptr;
}
std::unique_ptr<ukm::Report> report = std::make_unique<ukm::Report>();
if (!report->ParseFromString(uncompressed_log_data)) {
return nullptr;
}
return report;
}
private:
static ukm::UkmService* ukm_service() {
return GetApplicationContext()
......@@ -95,8 +160,13 @@ class UkmEGTestHelper {
ConditionBlock condition = ^{
return metrics::UkmEGTestHelper::ukm_enabled() == enabled;
};
return base::test::ios::WaitUntilConditionOrTimeout(kSyncUKMOperationsTimeout,
condition);
return base::test::ios::WaitUntilConditionOrTimeout(
syncher::kSyncUKMOperationsTimeout, condition);
}
+ (BOOL)isReportUserNoisedUserBirthYearAndGenderEnabled {
return metrics::UkmEGTestHelper::
IsReportUserNoisedUserBirthYearAndGenderEnabled();
}
+ (uint64_t)UKMClientID {
......@@ -108,7 +178,51 @@ class UkmEGTestHelper {
}
+ (void)UKMRecordDummySource:(int64_t)sourceID {
return metrics::UkmEGTestHelper::RecordDummySource(sourceID);
metrics::UkmEGTestHelper::RecordDummySource(sourceID);
}
+ (void)setNetworkTimeForTesting {
// The resolution was arbitrarily chosen.
base::TimeDelta resolution = base::TimeDelta::FromMilliseconds(17);
// Simulate the latency in the network to get the network time from the remote
// server.
base::TimeDelta latency = base::TimeDelta::FromMilliseconds(50);
base::DefaultClock clock;
base::DefaultTickClock tickClock;
GetApplicationContext()->GetNetworkTimeTracker()->UpdateNetworkTime(
clock.Now() - latency / 2, resolution, latency, tickClock.NowTicks());
}
+ (void)buildAndStoreUKMLog {
metrics::UkmEGTestHelper::BuildAndStoreUkmLog();
}
+ (BOOL)hasUnsentLogs {
return metrics::UkmEGTestHelper::HasUnsentLogs();
}
+ (BOOL)UKMReportHasBirthYear:(int)year gender:(int)gender {
std::unique_ptr<ukm::Report> report =
metrics::UkmEGTestHelper::GetUKMReport();
int birthYearOffset =
GetApplicationContext()
->GetChromeBrowserStateManager()
->GetLastUsedBrowserState()
->GetPrefs()
->GetInteger(syncer::prefs::kSyncDemographicsBirthYearOffset);
int noisedBirthYear = year + birthYearOffset;
return report && gender == report->user_demographics().gender() &&
noisedBirthYear == report->user_demographics().birth_year();
}
+ (BOOL)UKMReportHasUserDemographics {
std::unique_ptr<ukm::Report> report =
metrics::UkmEGTestHelper::GetUKMReport();
return report && report->has_user_demographics();
}
+ (NSError*)setupHistogramTester {
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <XCTest/XCTest.h>
#include "base/ios/ios_util.h"
#include "base/macros.h"
#include "base/stl_util.h"
......@@ -12,6 +10,7 @@
#import "ios/chrome/browser/metrics/metrics_app_interface.h"
#import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h"
#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h"
#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h"
#include "ios/chrome/grit/ios_strings.h"
#import "ios/chrome/test/earl_grey/chrome_actions.h"
#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
......@@ -41,9 +40,6 @@ using chrome_test_util::TurnSyncSwitchOn;
namespace {
// Constant for timeout while waiting for asynchronous sync and UKM operations.
const NSTimeInterval kSyncUKMOperationsTimeout = 10.0;
void ClearBrowsingData() {
[ChromeEarlGreyUI openSettingsMenu];
[ChromeEarlGreyUI tapSettingsMenuButton:SettingsMenuPrivacyButton()];
......@@ -95,26 +91,6 @@ void OpenNewRegularTab() {
[ChromeEarlGrey waitForMainTabCount:(tab_count + 1)];
}
// Signs out of sync.
void SignOut() {
[ChromeEarlGreyUI openSettingsMenu];
[ChromeEarlGreyUI tapSettingsMenuButton:SettingsAccountButton()];
// Remove |identity| from the device.
FakeChromeIdentity* identity = [SigninEarlGreyUtils fakeIdentity1];
[[EarlGrey
selectElementWithMatcher:ButtonWithAccessibilityLabel(identity.userEmail)]
performAction:grey_tap()];
[[EarlGrey
selectElementWithMatcher:ButtonWithAccessibilityLabel(@"Remove account")]
performAction:grey_tap()];
[[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
performAction:grey_tap()];
[SigninEarlGreyUtils checkSignedOut];
}
} // namespace
// UKM tests.
......@@ -150,7 +126,7 @@ void SignOut() {
[super setUp];
[ChromeEarlGrey waitForSyncInitialized:NO
syncTimeout:kSyncUKMOperationsTimeout];
syncTimeout:syncher::kSyncUKMOperationsTimeout];
GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO],
@"Failed to assert that UKM was not enabled.");
// Sign in to Chrome and turn sync on.
......@@ -160,7 +136,7 @@ void SignOut() {
// flow that enables UKM.
[SigninEarlGreyUI signinWithFakeIdentity:[SigninEarlGreyUtils fakeIdentity1]];
[ChromeEarlGrey waitForSyncInitialized:YES
syncTimeout:kSyncUKMOperationsTimeout];
syncTimeout:syncher::kSyncUKMOperationsTimeout];
// Grant metrics consent and update MetricsServicesManager.
[MetricsAppInterface overrideMetricsAndCrashReportingForTesting];
......@@ -172,7 +148,7 @@ void SignOut() {
- (void)tearDown {
[ChromeEarlGrey waitForSyncInitialized:YES
syncTimeout:kSyncUKMOperationsTimeout];
syncTimeout:syncher::kSyncUKMOperationsTimeout];
GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES],
@"Failed to assert that UKM was enabled.");
......@@ -183,14 +159,17 @@ void SignOut() {
GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO],
@"Failed to assert that UKM was not enabled.");
// Sign out of Chrome and Turn sync off.
// Sign out of Chrome and Turn off sync.
//
// Note: URL-keyed anonymized data collection is turned off as part of the
// flow to Sign out of Chrome and Turn sync off. This matchers the main user
// flow to Sign out of Chrome and Turn sync off. This matches the main user
// flow that disables UKM.
SignOut();
if (![SigninEarlGreyUtilsAppInterface isSignedOut]) {
[SigninEarlGreyUtilsAppInterface signOut];
}
[ChromeEarlGrey waitForSyncInitialized:NO
syncTimeout:kSyncUKMOperationsTimeout];
syncTimeout:syncher::kSyncUKMOperationsTimeout];
[ChromeEarlGrey clearSyncServerData];
[super tearDown];
......@@ -295,7 +274,7 @@ void SignOut() {
// Make sure that providing metrics consent doesn't enable UKM w/o sync.
- (void)testConsentAddedButNoSync {
SignOut();
[SigninEarlGreyUtilsAppInterface signOut];
[MetricsAppInterface setMetricsAndCrashReportingForTesting:NO];
GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO],
@"Failed to assert that UKM was not enabled.");
......@@ -364,7 +343,7 @@ void SignOut() {
#endif
uint64_t originalClientID = [MetricsAppInterface UKMClientID];
SignOut();
[SigninEarlGreyUtilsAppInterface signOut];
GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:NO],
@"Failed to assert that UKM was not enabled.");
......
......@@ -44,6 +44,7 @@ source_set("test_support") {
"//components/metrics",
"//components/prefs",
"//components/signin/public/base",
"//components/sync/base",
"//components/sync/test/fake_server",
"//components/sync_device_info",
"//google_apis",
......
......@@ -40,15 +40,18 @@ BOOL VerifyNumberOfSyncEntitiesWithName(syncer::ModelType type,
NSError** error);
// Injects a bookmark into the fake sync server with |url| and |title|.
void InjectBookmarkOnFakeSyncServer(std::string url, std::string title);
void AddBookmarkToFakeSyncServer(std::string url, std::string title);
// Injects a legacy bookmark into the fake sync server. The legacy bookmark
// means 2015 and earlier, prior to the adoption of GUIDs for originator client
// item ID.
void InjectLegacyBookmarkOnFakeSyncServer(
std::string url,
std::string title,
std::string originator_client_item_id);
void AddLegacyBookmarkToFakeSyncServer(std::string url,
std::string title,
std::string originator_client_item_id);
// Injects user demographics into the fake sync server.
// TODO(crbug.com/1066297): Refactor to remove duplicate code.
void AddUserDemographicsToSyncServer(int birth_year, int gender);
// Injects an autofill profile into the fake sync server with |guid| and
// |full_name|.
......@@ -83,11 +86,11 @@ bool IsAutofillProfilePresent(std::string guid, std::string full_name);
BOOL VerifySessionsOnSyncServer(const std::multiset<std::string>& expected_urls,
NSError** error);
// Adds typed URL into HistoryService.
void AddTypedURLOnClient(const GURL& url);
// Adds typed URL to HistoryService.
void AddTypedURLToClient(const GURL& url);
// Injects typed URL to sync FakeServer.
void InjectTypedURLOnFakeSyncServer(const std::string& url);
// Injects a typed URL into the fake sync server.
void AddTypedURLToFakeSyncServer(const std::string& url);
// Returns YES if the provided |url| is present (or not) if |expected_present|
// is YES (or NO).
......
......@@ -17,6 +17,7 @@
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/history/core/browser/history_service.h"
#include "components/keyed_service/core/service_access_type.h"
#include "components/sync/base/pref_names.h"
#include "components/sync/driver/profile_sync_service.h"
#include "components/sync/driver/sync_service.h"
#include "components/sync/test/fake_server/entity_builder_factory.h"
......@@ -110,7 +111,6 @@ void ClearSyncServerData() {
}
int GetNumberOfSyncEntities(syncer::ModelType type) {
DCHECK(gSyncFakeServer);
std::unique_ptr<base::DictionaryValue> entities =
gSyncFakeServer->GetEntitiesAsDictionaryValue();
......@@ -142,19 +142,16 @@ BOOL VerifyNumberOfSyncEntitiesWithName(syncer::ModelType type,
return result == testing::AssertionSuccess();
}
void InjectBookmarkOnFakeSyncServer(std::string url, std::string title) {
DCHECK(gSyncFakeServer);
void AddBookmarkToFakeSyncServer(std::string url, std::string title) {
fake_server::EntityBuilderFactory entity_builder_factory;
fake_server::BookmarkEntityBuilder bookmark_builder =
entity_builder_factory.NewBookmarkEntityBuilder(title);
gSyncFakeServer->InjectEntity(bookmark_builder.BuildBookmark(GURL(url)));
}
void InjectLegacyBookmarkOnFakeSyncServer(
std::string url,
std::string title,
std::string originator_client_item_id) {
DCHECK(gSyncFakeServer);
void AddLegacyBookmarkToFakeSyncServer(std::string url,
std::string title,
std::string originator_client_item_id) {
DCHECK(!base::IsValidGUID(originator_client_item_id));
fake_server::EntityBuilderFactory entity_builder_factory;
fake_server::BookmarkEntityBuilder bookmark_builder =
......@@ -184,9 +181,26 @@ std::string GetSyncCacheGuid() {
return info_provider->GetLocalDeviceInfo()->guid();
}
void AddUserDemographicsToSyncServer(int birth_year, int gender) {
sync_pb::EntitySpecifics specifics;
specifics.mutable_priority_preference()->mutable_preference()->set_name(
syncer::prefs::kSyncDemographics);
specifics.mutable_priority_preference()->mutable_preference()->set_value(
base::StringPrintf("{\"birth_year\":%d,\"gender\":%d}", birth_year,
gender));
std::unique_ptr<syncer::LoopbackServerEntity> entity =
syncer::PersistentUniqueClientEntity::CreateFromSpecificsForTesting(
/*non_unique_name=*/syncer::prefs::kSyncDemographics,
/*client_tag=*/specifics.preference().name(), specifics,
/*creation_time=*/0,
/*last_modified_time=*/0);
gSyncFakeServer->InjectEntity(std::move(entity));
}
void AddAutofillProfileToFakeSyncServer(std::string guid,
std::string full_name) {
DCHECK(gSyncFakeServer);
sync_pb::EntitySpecifics entity_specifics;
sync_pb::AutofillProfileSpecifics* autofill_profile =
entity_specifics.mutable_autofill_profile();
......@@ -201,7 +215,6 @@ void AddAutofillProfileToFakeSyncServer(std::string guid,
}
void DeleteAutofillProfileFromFakeSyncServer(std::string guid) {
DCHECK(gSyncFakeServer);
std::vector<sync_pb::SyncEntity> autofill_profiles =
gSyncFakeServer->GetSyncEntitiesByModelType(syncer::AUTOFILL_PROFILE);
std::string entity_id;
......@@ -265,7 +278,7 @@ BOOL VerifySessionsOnSyncServer(const std::multiset<std::string>& expected_urls,
return result == testing::AssertionSuccess();
}
void AddTypedURLOnClient(const GURL& url) {
void AddTypedURLToClient(const GURL& url) {
ChromeBrowserState* browser_state =
chrome_test_util::GetOriginalBrowserState();
history::HistoryService* historyService =
......@@ -277,8 +290,7 @@ void AddTypedURLOnClient(const GURL& url) {
history::SOURCE_BROWSED, false);
}
void InjectTypedURLOnFakeSyncServer(const std::string& url) {
DCHECK(gSyncFakeServer);
void AddTypedURLToFakeSyncServer(const std::string& url) {
sync_pb::EntitySpecifics entitySpecifics;
sync_pb::TypedUrlSpecifics* typedUrl = entitySpecifics.mutable_typed_url();
typedUrl->set_url(url);
......@@ -355,7 +367,6 @@ void DeleteTypedUrlFromClient(const GURL& url) {
}
void DeleteTypedUrlFromFakeSyncServer(std::string url) {
DCHECK(gSyncFakeServer);
std::vector<sync_pb::SyncEntity> typed_urls =
gSyncFakeServer->GetSyncEntitiesByModelType(syncer::TYPED_URLS);
std::string entity_id;
......
......@@ -248,6 +248,7 @@ source_set("test_support") {
"//components/autofill/core/browser",
"//components/browsing_data/core",
"//components/content_settings/core/browser",
"//components/metrics:demographic_metrics_provider",
"//components/strings",
"//components/sync/base",
"//components/translate/core/browser",
......@@ -388,6 +389,7 @@ source_set("eg_app_support+eg2") {
"//components/autofill/core/browser",
"//components/browsing_data/core",
"//components/content_settings/core/browser",
"//components/metrics:demographic_metrics_provider",
"//components/strings",
"//components/sync/base",
"//components/translate/core/browser",
......
......@@ -155,6 +155,12 @@ id ExecuteJavaScript(NSString* javascript, NSError* __autoreleasing* out_error);
// Stops the sync server. The server should be running when calling this.
- (void)stopSync;
// Injects user demographics into the fake sync server. The year is the
// un-noised birth year, and the gender corresponds to the options in
// UserDemographicsProto::Gender.
- (void)addUserDemographicsToSyncServerWithBirthYear:(int)birthYear
gender:(int)gender;
// Clears the autofill profile for the given |GUID|.
- (void)clearAutofillProfileWithGUID:(const std::string&)GUID;
......@@ -479,6 +485,9 @@ id ExecuteJavaScript(NSString* javascript, NSError* __autoreleasing* out_error);
// Returns YES if AutofillEnableCompanyName feature is enabled.
- (BOOL)isAutofillCompanyNameEnabled WARN_UNUSED_RESULT;
// Returns YES if DemographicMetricsReporting feature is enabled.
- (BOOL)isDemographicMetricsReportingEnabled WARN_UNUSED_RESULT;
// Returns YES if the |launchSwitch| is found in host app launch switches.
- (BOOL)appHasLaunchSwitch:(const std::string&)launchSwitch;
......
......@@ -621,6 +621,13 @@ GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(ChromeEarlGreyAppInterface)
[ChromeEarlGreyAppInterface stopSync];
}
- (void)addUserDemographicsToSyncServerWithBirthYear:(int)birthYear
gender:(int)gender {
[ChromeEarlGreyAppInterface
addUserDemographicsToSyncServerWithBirthYear:birthYear
gender:gender];
}
- (void)clearAutofillProfileWithGUID:(const std::string&)UTF8GUID {
NSString* GUID = base::SysUTF8ToNSString(UTF8GUID);
[ChromeEarlGreyAppInterface clearAutofillProfileWithGUID:GUID];
......@@ -847,6 +854,10 @@ GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(ChromeEarlGreyAppInterface)
return [ChromeEarlGreyAppInterface isAutofillCompanyNameEnabled];
}
- (BOOL)isDemographicMetricsReportingEnabled {
return [ChromeEarlGreyAppInterface isDemographicMetricsReportingEnabled];
}
- (BOOL)appHasLaunchSwitch:(const std::string&)launchSwitch {
return [ChromeEarlGreyAppInterface
appHasLaunchSwitch:base::SysUTF8ToNSString(launchSwitch)];
......
......@@ -229,21 +229,6 @@
// Returns the size of the current WebState's web view.
+ (CGSize)webStateWebViewSize;
#pragma mark - Sync Utilities (EG2)
// Clears the autofill profile for the given |GUID|.
+ (void)clearAutofillProfileWithGUID:(NSString*)GUID;
// Injects an autofill profile into the fake sync server with |GUID| and
// |full_name|.
+ (void)addAutofillProfileToFakeSyncServerWithGUID:(NSString*)GUID
autofillProfileName:(NSString*)fullName;
// Returns YES if there is an autofilll profile with the corresponding |GUID|
// and |full_name|.
+ (BOOL)isAutofillProfilePresentWithGUID:(NSString*)GUID
autofillProfileName:(NSString*)fullName;
#pragma mark - Bookmarks Utilities (EG2)
// Waits for the bookmark internal state to be done loading.
......@@ -320,6 +305,25 @@
// Triggers a sync cycle for a |type|.
+ (void)triggerSyncCycleForType:(syncer::ModelType)type;
// Injects user demographics into the fake sync server. The year is the
// un-noised birth year, and the gender corresponds to the options in
// UserDemographicsProto::Gender..
+ (void)addUserDemographicsToSyncServerWithBirthYear:(int)birthYear
gender:(int)gender;
// Clears the autofill profile for the given |GUID|.
+ (void)clearAutofillProfileWithGUID:(NSString*)GUID;
// Injects an autofill profile into the fake sync server with |GUID| and
// |full_name|.
+ (void)addAutofillProfileToFakeSyncServerWithGUID:(NSString*)GUID
autofillProfileName:(NSString*)fullName;
// Returns YES if there is an autofilll profile with the corresponding |GUID|
// and |full_name|.
+ (BOOL)isAutofillProfilePresentWithGUID:(NSString*)GUID
autofillProfileName:(NSString*)fullName;
// Deletes an autofill profile from the fake sync server with |GUID|, if it
// exists. If it doesn't exist, nothing is done.
+ (void)deleteAutofillProfileFromFakeSyncServerWithGUID:(NSString*)GUID;
......@@ -384,6 +388,9 @@
// Returns YES if AutofillEnableCompanyName feature is enabled.
+ (BOOL)isAutofillCompanyNameEnabled WARN_UNUSED_RESULT;
// Returns YES if DemographicMetricsReporting feature is enabled.
+ (BOOL)isDemographicMetricsReportingEnabled WARN_UNUSED_RESULT;
// Returns YES if the |launchSwitch| is found in host app launch switches.
+ (BOOL)appHasLaunchSwitch:(NSString*)launchSwitch;
......
......@@ -13,6 +13,7 @@
#include "components/autofill/core/common/autofill_features.h"
#include "components/browsing_data/core/pref_names.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/metrics/demographic_metrics_provider.h"
#include "components/prefs/pref_service.h"
#import "components/ukm/ios/features.h"
#include "components/variations/variations_associated_data.h"
......@@ -425,27 +426,6 @@ NSString* SerializedPref(const PrefService::Preference* pref) {
return [web_state->GetWebViewProxy() bounds].size;
}
#pragma mark - Sync Utilities (EG2)
+ (void)clearAutofillProfileWithGUID:(NSString*)GUID {
std::string utfGUID = base::SysNSStringToUTF8(GUID);
chrome_test_util::ClearAutofillProfile(utfGUID);
}
+ (void)addAutofillProfileToFakeSyncServerWithGUID:(NSString*)GUID
autofillProfileName:(NSString*)fullName {
std::string utfGUID = base::SysNSStringToUTF8(GUID);
std::string utfFullName = base::SysNSStringToUTF8(fullName);
chrome_test_util::AddAutofillProfileToFakeSyncServer(utfGUID, utfFullName);
}
+ (BOOL)isAutofillProfilePresentWithGUID:(NSString*)GUID
autofillProfileName:(NSString*)fullName {
std::string utfGUID = base::SysNSStringToUTF8(GUID);
std::string utfFullName = base::SysNSStringToUTF8(fullName);
return chrome_test_util::IsAutofillProfilePresent(utfGUID, utfFullName);
}
#pragma mark - Bookmarks Utilities (EG2)
+ (NSError*)waitForBookmarksToFinishinLoading {
......@@ -482,26 +462,25 @@ NSString* SerializedPref(const PrefService::Preference* pref) {
}
+ (void)addFakeSyncServerBookmarkWithURL:(NSString*)URL title:(NSString*)title {
chrome_test_util::InjectBookmarkOnFakeSyncServer(
base::SysNSStringToUTF8(URL), base::SysNSStringToUTF8(title));
chrome_test_util::AddBookmarkToFakeSyncServer(base::SysNSStringToUTF8(URL),
base::SysNSStringToUTF8(title));
}
+ (void)addFakeSyncServerLegacyBookmarkWithURL:(NSString*)URL
title:(NSString*)title
originator_client_item_id:
(NSString*)originator_client_item_id {
chrome_test_util::InjectLegacyBookmarkOnFakeSyncServer(
chrome_test_util::AddLegacyBookmarkToFakeSyncServer(
base::SysNSStringToUTF8(URL), base::SysNSStringToUTF8(title),
base::SysNSStringToUTF8(originator_client_item_id));
}
+ (void)addFakeSyncServerTypedURL:(NSString*)URL {
chrome_test_util::InjectTypedURLOnFakeSyncServer(
base::SysNSStringToUTF8(URL));
chrome_test_util::AddTypedURLToFakeSyncServer(base::SysNSStringToUTF8(URL));
}
+ (void)addHistoryServiceTypedURL:(NSString*)URL {
chrome_test_util::AddTypedURLOnClient(GURL(base::SysNSStringToUTF8(URL)));
chrome_test_util::AddTypedURLToClient(GURL(base::SysNSStringToUTF8(URL)));
}
+ (void)deleteHistoryServiceTypedURL:(NSString*)URL {
......@@ -521,6 +500,30 @@ NSString* SerializedPref(const PrefService::Preference* pref) {
chrome_test_util::TriggerSyncCycle(type);
}
+ (void)addUserDemographicsToSyncServerWithBirthYear:(int)birthYear
gender:(int)gender {
chrome_test_util::AddUserDemographicsToSyncServer(birthYear, gender);
}
+ (void)clearAutofillProfileWithGUID:(NSString*)GUID {
std::string utfGUID = base::SysNSStringToUTF8(GUID);
chrome_test_util::ClearAutofillProfile(utfGUID);
}
+ (void)addAutofillProfileToFakeSyncServerWithGUID:(NSString*)GUID
autofillProfileName:(NSString*)fullName {
std::string utfGUID = base::SysNSStringToUTF8(GUID);
std::string utfFullName = base::SysNSStringToUTF8(fullName);
chrome_test_util::AddAutofillProfileToFakeSyncServer(utfGUID, utfFullName);
}
+ (BOOL)isAutofillProfilePresentWithGUID:(NSString*)GUID
autofillProfileName:(NSString*)fullName {
std::string utfGUID = base::SysNSStringToUTF8(GUID);
std::string utfFullName = base::SysNSStringToUTF8(fullName);
return chrome_test_util::IsAutofillProfilePresent(utfGUID, utfFullName);
}
+ (void)deleteAutofillProfileFromFakeSyncServerWithGUID:(NSString*)GUID {
chrome_test_util::DeleteAutofillProfileFromFakeSyncServer(
base::SysNSStringToUTF8(GUID));
......@@ -691,6 +694,11 @@ NSString* SerializedPref(const PrefService::Preference* pref) {
autofill::features::kAutofillEnableCompanyName);
}
+ (BOOL)isDemographicMetricsReportingEnabled {
return base::FeatureList::IsEnabled(
metrics::DemographicMetricsProvider::kDemographicMetricsReporting);
}
+ (BOOL)appHasLaunchSwitch:(NSString*)launchSwitch {
return base::CommandLine::ForCurrentProcess()->HasSwitch(
base::SysNSStringToUTF8(launchSwitch));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment