service_browsertest.cc 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/test/gmock_callback_support.h"
  5. #include "base/test/scoped_feature_list.h"
  6. #include "build/build_config.h"
  7. #include "chrome/browser/browser_process.h"
  8. #include "chrome/browser/history/history_service_factory.h"
  9. #include "chrome/browser/profiles/profile.h"
  10. #include "chrome/browser/segmentation_platform/segmentation_platform_service_factory.h"
  11. #include "chrome/browser/segmentation_platform/ukm_data_manager_test_utils.h"
  12. #include "chrome/browser/segmentation_platform/ukm_database_client.h"
  13. #include "chrome/browser/ui/browser.h"
  14. #include "chrome/test/base/in_process_browser_test.h"
  15. #include "components/metrics_services_manager/metrics_services_manager.h"
  16. #include "components/prefs/pref_change_registrar.h"
  17. #include "components/prefs/pref_observer.h"
  18. #include "components/prefs/pref_service.h"
  19. #include "components/segmentation_platform/internal/constants.h"
  20. #include "components/segmentation_platform/internal/execution/mock_model_provider.h"
  21. #include "components/segmentation_platform/public/config.h"
  22. #include "components/segmentation_platform/public/features.h"
  23. #include "components/segmentation_platform/public/segment_selection_result.h"
  24. #include "components/segmentation_platform/public/segmentation_platform_service.h"
  25. #include "components/ukm/ukm_service.h"
  26. #include "content/public/test/browser_test.h"
  27. namespace segmentation_platform {
  28. using ::base::test::RunOnceCallback;
  29. using ::testing::_;
  30. using ::testing::Invoke;
  31. using ::testing::Return;
  32. using ::testing::SaveArg;
  33. constexpr SegmentId kSegmentId =
  34. SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT;
  35. constexpr char kSqlFeatureQuery[] = "SELECT COUNT(*) from metrics";
  36. class SegmentationPlatformTest : public InProcessBrowserTest {
  37. public:
  38. SegmentationPlatformTest() {
  39. feature_list_.InitWithFeaturesAndParameters(
  40. {base::test::ScopedFeatureList::FeatureAndParams(
  41. features::kSegmentationPlatformFeature, {}),
  42. base::test::ScopedFeatureList::FeatureAndParams(
  43. features::kSegmentationStructuredMetricsFeature, {}),
  44. base::test::ScopedFeatureList::FeatureAndParams(
  45. features::kSegmentationPlatformUkmEngine, {}),
  46. base::test::ScopedFeatureList::FeatureAndParams(
  47. features::kSegmentationPlatformLowEngagementFeature,
  48. {{"enable_default_model", "true"}})},
  49. {});
  50. }
  51. void SetUpCommandLine(base::CommandLine* command_line) override {
  52. command_line->AppendSwitch("segmentation-platform-refresh-results");
  53. }
  54. bool HasResultPref(base::StringPiece segmentation_key) {
  55. const base::Value::Dict& dictionary =
  56. browser()->profile()->GetPrefs()->GetValueDict(kSegmentationResultPref);
  57. return !!dictionary.FindByDottedPath(segmentation_key);
  58. }
  59. void OnResultPrefUpdated() {
  60. if (!wait_for_pref_callback_.is_null() &&
  61. HasResultPref(kChromeLowUserEngagementSegmentationKey)) {
  62. std::move(wait_for_pref_callback_).Run();
  63. }
  64. }
  65. void WaitForPrefUpdate() {
  66. if (HasResultPref(kChromeLowUserEngagementSegmentationKey))
  67. return;
  68. base::RunLoop wait_for_pref;
  69. wait_for_pref_callback_ = wait_for_pref.QuitClosure();
  70. pref_registrar_.Init(browser()->profile()->GetPrefs());
  71. pref_registrar_.Add(
  72. kSegmentationResultPref,
  73. base::BindRepeating(&SegmentationPlatformTest::OnResultPrefUpdated,
  74. weak_ptr_factory_.GetWeakPtr()));
  75. wait_for_pref.Run();
  76. pref_registrar_.RemoveAll();
  77. }
  78. void WaitForPlatformInit() {
  79. base::RunLoop wait_for_init;
  80. SegmentationPlatformService* service = segmentation_platform::
  81. SegmentationPlatformServiceFactory::GetForProfile(browser()->profile());
  82. while (!service->IsPlatformInitialized()) {
  83. wait_for_init.RunUntilIdle();
  84. }
  85. }
  86. void ExpectSegmentSelectionResult(const std::string& segmentation_key,
  87. bool result_expected) {
  88. SegmentationPlatformService* service = segmentation_platform::
  89. SegmentationPlatformServiceFactory::GetForProfile(browser()->profile());
  90. base::RunLoop wait_for_segment;
  91. service->GetSelectedSegment(
  92. segmentation_key, base::BindOnce(
  93. [](bool result_expected, base::OnceClosure quit,
  94. const SegmentSelectionResult& result) {
  95. EXPECT_EQ(result_expected, result.is_ready);
  96. std::move(quit).Run();
  97. },
  98. result_expected, wait_for_segment.QuitClosure()));
  99. wait_for_segment.Run();
  100. }
  101. protected:
  102. base::test::ScopedFeatureList feature_list_;
  103. PrefChangeRegistrar pref_registrar_;
  104. base::OnceClosure wait_for_pref_callback_;
  105. base::WeakPtrFactory<SegmentationPlatformTest> weak_ptr_factory_{this};
  106. };
  107. IN_PROC_BROWSER_TEST_F(SegmentationPlatformTest, PRE_RunDefaultModel) {
  108. WaitForPlatformInit();
  109. // The default model is executed and result stored in prefs.
  110. WaitForPrefUpdate();
  111. // The result from platform is not available since it only returns result from
  112. // a previous session.
  113. ExpectSegmentSelectionResult(kChromeLowUserEngagementSegmentationKey,
  114. /*result_expected=*/false);
  115. }
  116. IN_PROC_BROWSER_TEST_F(SegmentationPlatformTest, RunDefaultModel) {
  117. WaitForPlatformInit();
  118. // Result is available from previous session's selection.
  119. ExpectSegmentSelectionResult(kChromeLowUserEngagementSegmentationKey,
  120. /*result_expected=*/true);
  121. // This session runs default model and updates again.
  122. WaitForPrefUpdate();
  123. }
  124. class SegmentationPlatformUkmModelTest : public SegmentationPlatformTest {
  125. public:
  126. SegmentationPlatformUkmModelTest() : utils_(&ukm_recorder_) {}
  127. void CreatedBrowserMainParts(content::BrowserMainParts* parts) override {
  128. InProcessBrowserTest::CreatedBrowserMainParts(parts);
  129. utils_.PreProfileInit({kSegmentId});
  130. }
  131. void PreRunTestOnMainThread() override {
  132. SegmentationPlatformTest::PreRunTestOnMainThread();
  133. utils_.set_history_service(HistoryServiceFactory::GetForProfile(
  134. browser()->profile(), ServiceAccessType::IMPLICIT_ACCESS));
  135. }
  136. protected:
  137. ukm::TestUkmRecorder ukm_recorder_;
  138. UkmDataManagerTestUtils utils_;
  139. };
  140. // This test is disabled in CrOS because CrOS creates a signin profile that uses
  141. // incognito mode. This disables the segmentation platform data collection.
  142. // TODO(ssid): Fix this test for CrOS by waiting for signin profile to be
  143. // deleted at startup before adding metrics.
  144. #if BUILDFLAG(IS_CHROMEOS)
  145. #define MAYBE_PRE_RunUkmBasedModel DISABLED_PRE_RunUkmBasedModel
  146. #define MAYBE_RunUkmBasedModel DISABLED_RunUkmBasedModel
  147. #else
  148. #define MAYBE_PRE_RunUkmBasedModel PRE_RunUkmBasedModel
  149. #define MAYBE_RunUkmBasedModel RunUkmBasedModel
  150. #endif
  151. IN_PROC_BROWSER_TEST_F(SegmentationPlatformUkmModelTest,
  152. MAYBE_PRE_RunUkmBasedModel) {
  153. const GURL kUrl1("https://www.url1.com");
  154. MockModelProvider* provider = utils_.GetDefaultOverride(kSegmentId);
  155. EXPECT_CALL(*provider, ExecuteModelWithInput(_, _))
  156. .WillRepeatedly(Invoke([&](const std::vector<float>& inputs,
  157. ModelProvider::ExecutionCallback callback) {
  158. // There are no UKM metrics written to the database, count = 0.
  159. EXPECT_EQ(std::vector<float>({0}), inputs);
  160. std::move(callback).Run(0.5);
  161. }));
  162. WaitForPlatformInit();
  163. utils_.WaitForModelRequestAndUpdateWith(
  164. kSegmentId, utils_.GetSamplePageLoadMetadata(kSqlFeatureQuery));
  165. // Wait for the default model to run and save results to prefs.
  166. WaitForPrefUpdate();
  167. // Record page load UKM that should be recorded in the database, persisted
  168. // across sessions.
  169. utils_.RecordPageLoadUkm(kUrl1, base::Time::Now());
  170. while (!utils_.IsUrlInDatabase(kUrl1)) {
  171. base::RunLoop().RunUntilIdle();
  172. }
  173. }
  174. IN_PROC_BROWSER_TEST_F(SegmentationPlatformUkmModelTest,
  175. MAYBE_RunUkmBasedModel) {
  176. const GURL kUrl1("https://www.url1.com");
  177. MockModelProvider* provider = utils_.GetDefaultOverride(kSegmentId);
  178. EXPECT_CALL(*provider, ExecuteModelWithInput(_, _))
  179. .WillRepeatedly(Invoke([](const std::vector<float>& inputs,
  180. ModelProvider::ExecutionCallback callback) {
  181. // Expected input is 2 since we recorded 2 UKM metrics in the previous
  182. // session.
  183. EXPECT_EQ(std::vector<float>({2}), inputs);
  184. std::move(callback).Run(0.5);
  185. }));
  186. WaitForPlatformInit();
  187. // Verify that the URL recorded in last session is still in database.
  188. EXPECT_TRUE(utils_.IsUrlInDatabase(kUrl1));
  189. // Result is available from previous session's selection.
  190. ExpectSegmentSelectionResult(kChromeLowUserEngagementSegmentationKey,
  191. /*result_expected=*/true);
  192. utils_.WaitForModelRequestAndUpdateWith(
  193. kSegmentId, utils_.GetSamplePageLoadMetadata(kSqlFeatureQuery));
  194. WaitForPrefUpdate();
  195. }
  196. } // namespace segmentation_platform