device_activity_client_unittest.cc 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394
  1. // Copyright 2021 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 "ash/components/device_activity/device_activity_client.h"
  5. #include "ash/components/device_activity/daily_use_case_impl.h"
  6. #include "ash/components/device_activity/device_activity_controller.h"
  7. #include "ash/components/device_activity/fresnel_pref_names.h"
  8. #include "ash/components/device_activity/fresnel_service.pb.h"
  9. #include "ash/components/device_activity/monthly_use_case_impl.h"
  10. #include "ash/constants/ash_features.h"
  11. #include "base/files/file_path.h"
  12. #include "base/files/file_util.h"
  13. #include "base/no_destructor.h"
  14. #include "base/path_service.h"
  15. #include "base/test/metrics/histogram_tester.h"
  16. #include "base/test/scoped_feature_list.h"
  17. #include "base/test/task_environment.h"
  18. #include "base/time/time.h"
  19. #include "base/timer/mock_timer.h"
  20. #include "chromeos/ash/components/dbus/system_clock/system_clock_client.h"
  21. #include "chromeos/ash/components/network/network_state_handler_observer.h"
  22. #include "chromeos/ash/components/network/network_state_test_helper.h"
  23. #include "chromeos/system/fake_statistics_provider.h"
  24. #include "components/prefs/testing_pref_service.h"
  25. #include "components/version_info/channel.h"
  26. #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
  27. #include "services/network/test/test_shared_url_loader_factory.h"
  28. #include "services/network/test/test_url_loader_factory.h"
  29. #include "testing/gmock/include/gmock/gmock.h"
  30. #include "testing/gtest/include/gtest/gtest.h"
  31. #include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
  32. #include "third_party/private_membership/src/internal/testing/regression_test_data/regression_test_data.pb.h"
  33. #include "third_party/private_membership/src/private_membership_rlwe_client.h"
  34. namespace ash {
  35. namespace device_activity {
  36. namespace psm_rlwe = private_membership::rlwe;
  37. namespace {
  38. // Holds data used to create deterministic PSM network request/response protos.
  39. struct PsmTestData {
  40. // Holds the response bodies used to test the case where the plaintext id is
  41. // a member of the PSM dataset.
  42. psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase
  43. member_test_case;
  44. // Holds the response bodies used to test the case where the plaintext id is
  45. // not a member of the PSM dataset.
  46. psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase
  47. nonmember_test_case;
  48. };
  49. PsmTestData* GetPsmTestData() {
  50. static base::NoDestructor<PsmTestData> data;
  51. return data.get();
  52. }
  53. // TODO(https://crbug.com/1272922): Move shared configuration constants to
  54. // separate file.
  55. //
  56. // URLs for the different network requests being performed.
  57. const char kTestFresnelBaseUrl[] = "https://dummy.googleapis.com";
  58. const char kPsmImportRequestEndpoint[] = "/v1/fresnel/psmRlweImport";
  59. const char kPsmOprfRequestEndpoint[] = "/v1/fresnel/psmRlweOprf";
  60. const char kPsmQueryRequestEndpoint[] = "/v1/fresnel/psmRlweQuery";
  61. // Create fake secrets used by the |DeviceActivityClient|.
  62. constexpr char kFakePsmDeviceActiveSecret[] = "FAKE_PSM_DEVICE_ACTIVE_SECRET";
  63. constexpr char kFakeFresnelApiKey[] = "FAKE_FRESNEL_API_KEY";
  64. constexpr ChromeDeviceMetadataParameters kFakeChromeParameters = {
  65. version_info::Channel::STABLE /* chromeos_channel */,
  66. MarketSegment::MARKET_SEGMENT_UNKNOWN /* market_segment */,
  67. };
  68. // Number of test cases exist in cros_test_data.binarypb file, which is part of
  69. // private_membership third_party library.
  70. const int kNumberOfPsmTestCases = 10;
  71. // PrivateSetMembership regression tests maximum file size which is 4MB.
  72. const size_t kMaxFileSizeInBytes = 4 * (1 << 20);
  73. std::string GetFresnelTestEndpoint(const std::string& endpoint) {
  74. return kTestFresnelBaseUrl + endpoint;
  75. }
  76. bool ParseProtoFromFile(const base::FilePath& file_path,
  77. google::protobuf::MessageLite* out_proto) {
  78. if (!out_proto)
  79. return false;
  80. std::string file_content;
  81. if (!base::ReadFileToStringWithMaxSize(file_path, &file_content,
  82. kMaxFileSizeInBytes)) {
  83. return false;
  84. }
  85. return out_proto->ParseFromString(file_content);
  86. }
  87. base::TimeDelta TimeUntilNextUTCMidnight() {
  88. const auto now = base::Time::Now();
  89. return (now.UTCMidnight() + base::Hours(base::Time::kHoursPerDay) - now);
  90. }
  91. base::TimeDelta TimeUntilNewUTCMonth() {
  92. const auto current_ts = base::Time::Now();
  93. base::Time::Exploded exploded_current_ts;
  94. current_ts.UTCExplode(&exploded_current_ts);
  95. // Exploded structure uses 1-based month (values 1 = January, etc.)
  96. // Increment current ts to be the new month/year.
  97. if (exploded_current_ts.month == 12) {
  98. exploded_current_ts.month = 1;
  99. exploded_current_ts.year += 1;
  100. } else {
  101. exploded_current_ts.month += 1;
  102. }
  103. // New timestamp should reflect first day of new month.
  104. exploded_current_ts.day_of_month = 1;
  105. base::Time new_ts;
  106. EXPECT_TRUE(base::Time::FromUTCExploded(exploded_current_ts, &new_ts));
  107. return new_ts - current_ts;
  108. }
  109. } // namespace
  110. class FakePsmDelegate : public PsmDelegate {
  111. public:
  112. FakePsmDelegate(const std::string& ec_cipher_key,
  113. const std::string& seed,
  114. const std::vector<psm_rlwe::RlwePlaintextId>& plaintext_ids)
  115. : ec_cipher_key_(ec_cipher_key),
  116. seed_(seed),
  117. plaintext_ids_(plaintext_ids) {}
  118. FakePsmDelegate(const FakePsmDelegate&) = delete;
  119. FakePsmDelegate& operator=(const FakePsmDelegate&) = delete;
  120. ~FakePsmDelegate() override = default;
  121. // PsmDelegate:
  122. rlwe::StatusOr<
  123. std::unique_ptr<private_membership::rlwe::PrivateMembershipRlweClient>>
  124. CreatePsmClient(private_membership::rlwe::RlweUseCase use_case,
  125. const std::vector<private_membership::rlwe::RlwePlaintextId>&
  126. plaintext_ids) override {
  127. return psm_rlwe::PrivateMembershipRlweClient::CreateForTesting(
  128. use_case, plaintext_ids_, ec_cipher_key_, seed_);
  129. }
  130. private:
  131. // Used by the PSM client to generate deterministic request/response protos.
  132. std::string ec_cipher_key_;
  133. std::string seed_;
  134. std::vector<psm_rlwe::RlwePlaintextId> plaintext_ids_;
  135. };
  136. class FakeDailyUseCaseImpl : public DailyUseCaseImpl {
  137. public:
  138. FakeDailyUseCaseImpl(
  139. const std::string& psm_device_active_secret,
  140. const ChromeDeviceMetadataParameters& chrome_passed_device_params,
  141. PrefService* local_state)
  142. : DailyUseCaseImpl(psm_device_active_secret,
  143. chrome_passed_device_params,
  144. local_state) {}
  145. FakeDailyUseCaseImpl(const FakeDailyUseCaseImpl&) = delete;
  146. FakeDailyUseCaseImpl& operator=(const FakeDailyUseCaseImpl&) = delete;
  147. ~FakeDailyUseCaseImpl() override = default;
  148. };
  149. class FakeMonthlyUseCaseImpl : public MonthlyUseCaseImpl {
  150. public:
  151. FakeMonthlyUseCaseImpl(
  152. const std::string& psm_device_active_secret,
  153. const ChromeDeviceMetadataParameters& chrome_passed_device_params,
  154. PrefService* local_state)
  155. : MonthlyUseCaseImpl(psm_device_active_secret,
  156. chrome_passed_device_params,
  157. local_state) {}
  158. FakeMonthlyUseCaseImpl(const FakeMonthlyUseCaseImpl&) = delete;
  159. FakeMonthlyUseCaseImpl& operator=(const FakeMonthlyUseCaseImpl&) = delete;
  160. ~FakeMonthlyUseCaseImpl() override = default;
  161. };
  162. // TODO(crbug/1317652): Refactor checking if current use case local pref is
  163. // unset. We may also want to abstract the psm network responses for the unit
  164. // tests.
  165. class DeviceActivityClientTest : public testing::Test {
  166. public:
  167. DeviceActivityClientTest()
  168. : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
  169. // Remote env. runs unit tests assuming base::Time::Now() is epoch.
  170. // Forward current time to 2022-01-01 00:00:00.
  171. base::Time new_current_ts;
  172. EXPECT_TRUE(
  173. base::Time::FromUTCString("2022-01-01 00:00:00", &new_current_ts));
  174. task_environment_.FastForwardBy(new_current_ts - base::Time::Now());
  175. task_environment_.RunUntilIdle();
  176. }
  177. DeviceActivityClientTest(const DeviceActivityClientTest&) = delete;
  178. DeviceActivityClientTest& operator=(const DeviceActivityClientTest&) = delete;
  179. ~DeviceActivityClientTest() override = default;
  180. protected:
  181. static void SetUpTestSuite() {
  182. // Initialize |psm_test_case_| which is used to generate deterministic psm
  183. // protos.
  184. CreatePsmTestCase();
  185. }
  186. static void CreatePsmTestCase() {
  187. base::FilePath src_root_dir;
  188. ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &src_root_dir));
  189. const base::FilePath kPsmTestDataPath =
  190. src_root_dir.AppendASCII("third_party")
  191. .AppendASCII("private_membership")
  192. .AppendASCII("src")
  193. .AppendASCII("internal")
  194. .AppendASCII("testing")
  195. .AppendASCII("regression_test_data")
  196. .AppendASCII("test_data.binarypb");
  197. ASSERT_TRUE(base::PathExists(kPsmTestDataPath));
  198. psm_rlwe::PrivateMembershipRlweClientRegressionTestData test_data;
  199. ASSERT_TRUE(ParseProtoFromFile(kPsmTestDataPath, &test_data));
  200. // Note that the test cases can change since it's read from the binarypb.
  201. // This can cause unexpected failures for the unit tests below.
  202. // As a safety precaution, check whether the number of tests change.
  203. ASSERT_EQ(test_data.test_cases_size(), kNumberOfPsmTestCases);
  204. // Sets |psm_test_case_| to have one of the fake PSM request/response
  205. // protos.
  206. //
  207. // Test case 0 contains a response where check membership returns true.
  208. // Test case 5 contains a response where check membership returns false.
  209. GetPsmTestData()->member_test_case = test_data.test_cases(0);
  210. GetPsmTestData()->nonmember_test_case = test_data.test_cases(5);
  211. }
  212. std::vector<psm_rlwe::RlwePlaintextId> GetPlaintextIds(
  213. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  214. test_case) {
  215. // Return well formed plaintext ids used in faking PSM network requests.
  216. return {test_case.plaintext_id()};
  217. }
  218. // Initialize well formed OPRF response body used to deterministically fake
  219. // PSM network responses.
  220. const std::string GetFresnelOprfResponse(
  221. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  222. test_case) {
  223. FresnelPsmRlweOprfResponse psm_oprf_response;
  224. *psm_oprf_response.mutable_rlwe_oprf_response() = test_case.oprf_response();
  225. return psm_oprf_response.SerializeAsString();
  226. }
  227. // Initialize well formed Query response body used to deterministically fake
  228. // PSM network responses.
  229. const std::string GetFresnelQueryResponse(
  230. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  231. test_case) {
  232. FresnelPsmRlweQueryResponse psm_query_response;
  233. *psm_query_response.mutable_rlwe_query_response() =
  234. test_case.query_response();
  235. return psm_query_response.SerializeAsString();
  236. }
  237. // testing::Test:
  238. void SetUp() override {
  239. scoped_feature_list_.InitWithFeatures(
  240. /*enabled_features=*/{features::kDeviceActiveClientMonthlyCheckIn,
  241. features::kDeviceActiveClientDailyCheckMembership,
  242. features::
  243. kDeviceActiveClientMonthlyCheckMembership},
  244. /*disabled_features*/ {});
  245. // Initialize pointer to our fake |PsmTestData| object.
  246. psm_test_data_ = GetPsmTestData();
  247. // Default network to being synchronized and available.
  248. SystemClockClient::InitializeFake();
  249. GetSystemClockTestInterface()->SetServiceIsAvailable(true);
  250. GetSystemClockTestInterface()->SetNetworkSynchronized(true);
  251. network_state_test_helper_ = std::make_unique<NetworkStateTestHelper>(
  252. /*use_default_devices_and_services=*/false);
  253. CreateWifiNetworkConfig();
  254. // Initialize |local_state_| prefs used by device_activity_client class.
  255. DeviceActivityController::RegisterPrefs(local_state_.registry());
  256. test_shared_loader_factory_ =
  257. base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
  258. &test_url_loader_factory_);
  259. chromeos::system::StatisticsProvider::SetTestProvider(
  260. &statistics_provider_);
  261. // Create vector of device active use cases, which device activity client
  262. // should maintain ownership of.
  263. std::vector<std::unique_ptr<DeviceActiveUseCase>> use_cases;
  264. use_cases.push_back(std::make_unique<FakeDailyUseCaseImpl>(
  265. kFakePsmDeviceActiveSecret, kFakeChromeParameters, &local_state_));
  266. use_cases.push_back(std::make_unique<FakeMonthlyUseCaseImpl>(
  267. kFakePsmDeviceActiveSecret, kFakeChromeParameters, &local_state_));
  268. device_activity_client_ = std::make_unique<DeviceActivityClient>(
  269. network_state_test_helper_->network_state_handler(),
  270. test_shared_loader_factory_,
  271. // |FakePsmDelegate| can use any test case parameters.
  272. std::make_unique<FakePsmDelegate>(
  273. psm_test_data_->nonmember_test_case.ec_cipher_key(),
  274. psm_test_data_->nonmember_test_case.seed(),
  275. GetPlaintextIds(psm_test_data_->nonmember_test_case)),
  276. std::make_unique<base::MockRepeatingTimer>(), kTestFresnelBaseUrl,
  277. kFakeFresnelApiKey, std::move(use_cases));
  278. }
  279. void TearDown() override {
  280. device_activity_client_.reset();
  281. // The system clock must be shutdown after the |device_activity_client_| is
  282. // destroyed.
  283. SystemClockClient::Shutdown();
  284. }
  285. SystemClockClient::TestInterface* GetSystemClockTestInterface() {
  286. return SystemClockClient::Get()->GetTestInterface();
  287. }
  288. void SimulateLocalStateOnPowerwash() {
  289. // Simulate powerwashing device by removing the local state prefs.
  290. local_state_.RemoveUserPref(
  291. prefs::kDeviceActiveLastKnownDailyPingTimestamp);
  292. local_state_.RemoveUserPref(
  293. prefs::kDeviceActiveLastKnownMonthlyPingTimestamp);
  294. }
  295. void SimulateOprfResponse(const std::string& serialized_response_body,
  296. net::HttpStatusCode response_code) {
  297. test_url_loader_factory_.SimulateResponseForPendingRequest(
  298. GetFresnelTestEndpoint(kPsmOprfRequestEndpoint),
  299. serialized_response_body, response_code);
  300. }
  301. void SimulateQueryResponse(const std::string& serialized_response_body,
  302. net::HttpStatusCode response_code) {
  303. test_url_loader_factory_.SimulateResponseForPendingRequest(
  304. GetFresnelTestEndpoint(kPsmQueryRequestEndpoint),
  305. serialized_response_body, response_code);
  306. }
  307. void SimulateImportResponse(const std::string& serialized_response_body,
  308. net::HttpStatusCode response_code) {
  309. test_url_loader_factory_.SimulateResponseForPendingRequest(
  310. GetFresnelTestEndpoint(kPsmImportRequestEndpoint),
  311. serialized_response_body, response_code);
  312. }
  313. void CreateWifiNetworkConfig() {
  314. ASSERT_TRUE(wifi_network_service_path_.empty());
  315. std::stringstream ss;
  316. ss << "{"
  317. << " \"GUID\": \""
  318. << "wifi_guid"
  319. << "\","
  320. << " \"Type\": \"" << shill::kTypeWifi << "\","
  321. << " \"State\": \"" << shill::kStateOffline << "\""
  322. << "}";
  323. wifi_network_service_path_ =
  324. network_state_test_helper_->ConfigureService(ss.str());
  325. }
  326. // |network_state| is a shill network state, e.g. "shill::kStateIdle".
  327. void SetWifiNetworkState(std::string network_state) {
  328. network_state_test_helper_->SetServiceProperty(wifi_network_service_path_,
  329. shill::kStateProperty,
  330. base::Value(network_state));
  331. task_environment_.RunUntilIdle();
  332. }
  333. // Used in tests, after |device_activity_client_| is generated.
  334. // Triggers the repeating timer in the client code.
  335. void FireTimer() {
  336. base::MockRepeatingTimer* mock_timer =
  337. static_cast<base::MockRepeatingTimer*>(
  338. device_activity_client_->GetReportTimer());
  339. if (mock_timer->IsRunning())
  340. mock_timer->Fire();
  341. // Ensure all pending tasks after the timer fires are executed
  342. // synchronously.
  343. task_environment_.RunUntilIdle();
  344. }
  345. base::test::TaskEnvironment task_environment_;
  346. // The underlying |psm_test_data_| object will outlive this testing class.
  347. PsmTestData* psm_test_data_ = nullptr;
  348. base::test::ScopedFeatureList scoped_feature_list_;
  349. std::unique_ptr<NetworkStateTestHelper> network_state_test_helper_;
  350. TestingPrefServiceSimple local_state_;
  351. scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
  352. network::TestURLLoaderFactory test_url_loader_factory_;
  353. std::unique_ptr<DeviceActivityClient> device_activity_client_;
  354. std::string wifi_network_service_path_;
  355. base::HistogramTester histogram_tester_;
  356. chromeos::system::FakeStatisticsProvider statistics_provider_;
  357. };
  358. TEST_F(DeviceActivityClientTest,
  359. StayIdleIfSystemClockServiceUnavailableOnNetworkConnection) {
  360. EXPECT_EQ(device_activity_client_->GetState(),
  361. DeviceActivityClient::State::kIdle);
  362. GetSystemClockTestInterface()->SetServiceIsAvailable(false);
  363. GetSystemClockTestInterface()->NotifyObserversSystemClockUpdated();
  364. // Network has come online.
  365. SetWifiNetworkState(shill::kStateOnline);
  366. histogram_tester_.ExpectBucketCount(
  367. "Ash.DeviceActivity.MethodCalled",
  368. DeviceActivityClient::DeviceActivityMethod::
  369. kDeviceActivityClientOnNetworkOnline,
  370. 1);
  371. // |OnSystemClockSyncResult| is not called because the service for syncing the
  372. // clock is unavailble.
  373. histogram_tester_.ExpectBucketCount(
  374. "Ash.DeviceActivity.MethodCalled",
  375. DeviceActivityClient::DeviceActivityMethod::
  376. kDeviceActivityClientOnSystemClockSyncResult,
  377. 0);
  378. histogram_tester_.ExpectBucketCount(
  379. "Ash.DeviceActivity.MethodCalled",
  380. DeviceActivityClient::DeviceActivityMethod::
  381. kDeviceActivityClientReportUseCases,
  382. 0);
  383. EXPECT_EQ(device_activity_client_->GetState(),
  384. DeviceActivityClient::State::kIdle);
  385. }
  386. TEST_F(DeviceActivityClientTest,
  387. StayIdleIfSystemClockIsNotNetworkSynchronized) {
  388. EXPECT_EQ(device_activity_client_->GetState(),
  389. DeviceActivityClient::State::kIdle);
  390. GetSystemClockTestInterface()->SetNetworkSynchronized(false);
  391. GetSystemClockTestInterface()->NotifyObserversSystemClockUpdated();
  392. // Network has come online.
  393. SetWifiNetworkState(shill::kStateOnline);
  394. histogram_tester_.ExpectBucketCount(
  395. "Ash.DeviceActivity.MethodCalled",
  396. DeviceActivityClient::DeviceActivityMethod::
  397. kDeviceActivityClientOnNetworkOnline,
  398. 1);
  399. // |OnSystemClockSyncResult| callback is not executed if the network is not
  400. // synchronized.
  401. histogram_tester_.ExpectBucketCount(
  402. "Ash.DeviceActivity.MethodCalled",
  403. DeviceActivityClient::DeviceActivityMethod::
  404. kDeviceActivityClientOnSystemClockSyncResult,
  405. 0);
  406. histogram_tester_.ExpectBucketCount(
  407. "Ash.DeviceActivity.MethodCalled",
  408. DeviceActivityClient::DeviceActivityMethod::
  409. kDeviceActivityClientReportUseCases,
  410. 0);
  411. EXPECT_EQ(device_activity_client_->GetState(),
  412. DeviceActivityClient::State::kIdle);
  413. }
  414. TEST_F(DeviceActivityClientTest,
  415. CheckMembershipOnTimerRetryIfSystemClockIsNotInitiallySynced) {
  416. EXPECT_EQ(device_activity_client_->GetState(),
  417. DeviceActivityClient::State::kIdle);
  418. GetSystemClockTestInterface()->SetNetworkSynchronized(false);
  419. GetSystemClockTestInterface()->NotifyObserversSystemClockUpdated();
  420. // Network has come online.
  421. SetWifiNetworkState(shill::kStateOnline);
  422. histogram_tester_.ExpectBucketCount(
  423. "Ash.DeviceActivity.MethodCalled",
  424. DeviceActivityClient::DeviceActivityMethod::
  425. kDeviceActivityClientOnNetworkOnline,
  426. 1);
  427. // |OnSystemClockSyncResult| callback is not executed if the network is not
  428. // synchronized.
  429. histogram_tester_.ExpectBucketCount(
  430. "Ash.DeviceActivity.MethodCalled",
  431. DeviceActivityClient::DeviceActivityMethod::
  432. kDeviceActivityClientOnSystemClockSyncResult,
  433. 0);
  434. histogram_tester_.ExpectBucketCount(
  435. "Ash.DeviceActivity.MethodCalled",
  436. DeviceActivityClient::DeviceActivityMethod::
  437. kDeviceActivityClientReportUseCases,
  438. 0);
  439. EXPECT_EQ(device_activity_client_->GetState(),
  440. DeviceActivityClient::State::kIdle);
  441. // Timer executes client and blocks to wait for the system clock
  442. // synchronization result.
  443. FireTimer();
  444. // Synchronously complete pending tasks before validating histogram counts
  445. // below.
  446. GetSystemClockTestInterface()->SetNetworkSynchronized(true);
  447. GetSystemClockTestInterface()->NotifyObserversSystemClockUpdated();
  448. task_environment_.RunUntilIdle();
  449. histogram_tester_.ExpectBucketCount(
  450. "Ash.DeviceActivity.MethodCalled",
  451. DeviceActivityClient::DeviceActivityMethod::
  452. kDeviceActivityClientOnSystemClockSyncResult,
  453. 1);
  454. histogram_tester_.ExpectBucketCount(
  455. "Ash.DeviceActivity.MethodCalled",
  456. DeviceActivityClient::DeviceActivityMethod::
  457. kDeviceActivityClientReportUseCases,
  458. 1);
  459. // Begins check membership flow.
  460. EXPECT_EQ(device_activity_client_->GetState(),
  461. DeviceActivityClient::State::kCheckingMembershipOprf);
  462. }
  463. TEST_F(DeviceActivityClientTest,
  464. CheckMembershipIfSystemClockServiceAvailableOnNetworkConnection) {
  465. EXPECT_EQ(device_activity_client_->GetState(),
  466. DeviceActivityClient::State::kIdle);
  467. // Network has come online.
  468. SetWifiNetworkState(shill::kStateOnline);
  469. histogram_tester_.ExpectBucketCount(
  470. "Ash.DeviceActivity.MethodCalled",
  471. DeviceActivityClient::DeviceActivityMethod::
  472. kDeviceActivityClientOnNetworkOnline,
  473. 1);
  474. histogram_tester_.ExpectBucketCount(
  475. "Ash.DeviceActivity.MethodCalled",
  476. DeviceActivityClient::DeviceActivityMethod::
  477. kDeviceActivityClientOnSystemClockSyncResult,
  478. 1);
  479. histogram_tester_.ExpectBucketCount(
  480. "Ash.DeviceActivity.MethodCalled",
  481. DeviceActivityClient::DeviceActivityMethod::
  482. kDeviceActivityClientReportUseCases,
  483. 1);
  484. EXPECT_EQ(device_activity_client_->GetState(),
  485. DeviceActivityClient::State::kCheckingMembershipOprf);
  486. }
  487. TEST_F(DeviceActivityClientTest, DefaultStatesAreInitializedProperly) {
  488. EXPECT_EQ(device_activity_client_->GetState(),
  489. DeviceActivityClient::State::kIdle);
  490. for (auto* use_case : device_activity_client_->GetUseCases()) {
  491. SCOPED_TRACE(testing::Message()
  492. << "PSM use case: "
  493. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  494. EXPECT_FALSE(use_case->IsLastKnownPingTimestampSet());
  495. }
  496. EXPECT_TRUE(device_activity_client_->GetReportTimer()->IsRunning());
  497. }
  498. TEST_F(DeviceActivityClientTest, NetworkRequestsUseFakeApiKey) {
  499. // When network comes online, the device performs a check membership
  500. // network request.
  501. SetWifiNetworkState(shill::kStateOnline);
  502. network::TestURLLoaderFactory::PendingRequest* request =
  503. test_url_loader_factory_.GetPendingRequest(0);
  504. task_environment_.RunUntilIdle();
  505. std::string api_key_header_value;
  506. request->request.headers.GetHeader("X-Goog-Api-Key", &api_key_header_value);
  507. EXPECT_EQ(api_key_header_value, kFakeFresnelApiKey);
  508. }
  509. // Fire timer to run |TransitionOutOfIdle|. Network is currently disconnected
  510. // so the client is expected to go back to |kIdle| state.
  511. TEST_F(DeviceActivityClientTest,
  512. FireTimerWithoutNetworkKeepsClientinIdleState) {
  513. SetWifiNetworkState(shill::kStateOffline);
  514. FireTimer();
  515. EXPECT_EQ(device_activity_client_->GetState(),
  516. DeviceActivityClient::State::kIdle);
  517. }
  518. TEST_F(DeviceActivityClientTest, NetworkReconnectsAfterSuccessfulCheckIn) {
  519. // Device active reporting starts check membership on network connect.
  520. SetWifiNetworkState(shill::kStateOnline);
  521. // |nonmember_test_case| is used to return psm response bodies for
  522. // the OPRF, and Query requests. The query request returns nonmember status.
  523. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  524. nonmember_test_case = psm_test_data_->nonmember_test_case;
  525. for (auto* use_case : device_activity_client_->GetUseCases()) {
  526. SCOPED_TRACE(testing::Message()
  527. << "PSM use case: "
  528. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  529. EXPECT_EQ(device_activity_client_->GetState(),
  530. DeviceActivityClient::State::kCheckingMembershipOprf);
  531. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  532. net::HTTP_OK);
  533. SimulateQueryResponse(GetFresnelQueryResponse(nonmember_test_case),
  534. net::HTTP_OK);
  535. SimulateImportResponse(std::string(), net::HTTP_OK);
  536. task_environment_.RunUntilIdle();
  537. }
  538. // Reconnecting network connection triggers |TransitionOutOfIdle|.
  539. SetWifiNetworkState(shill::kStateOffline);
  540. SetWifiNetworkState(shill::kStateOnline);
  541. // Check that no additional network requests are pending since all use cases
  542. // have already been imported.
  543. EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
  544. }
  545. TEST_F(DeviceActivityClientTest,
  546. CheckMembershipOnLocalStateUnsetAndPingRequired) {
  547. // Device active reporting starts check membership on network connect.
  548. SetWifiNetworkState(shill::kStateOnline);
  549. // |nonmember_test_case| is used to return psm response bodies for
  550. // the OPRF, and Query requests. The query request returns nonmember status.
  551. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  552. nonmember_test_case = psm_test_data_->nonmember_test_case;
  553. for (auto* use_case : device_activity_client_->GetUseCases()) {
  554. SCOPED_TRACE(testing::Message()
  555. << "PSM use case: "
  556. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  557. // On first ever ping, we begin the check membership protocol
  558. // since the local state pref for that use case is by default unix
  559. // epoch.
  560. EXPECT_FALSE(use_case->IsLastKnownPingTimestampSet());
  561. EXPECT_EQ(device_activity_client_->GetState(),
  562. DeviceActivityClient::State::kCheckingMembershipOprf);
  563. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  564. net::HTTP_OK);
  565. SimulateQueryResponse(GetFresnelQueryResponse(nonmember_test_case),
  566. net::HTTP_OK);
  567. SimulateImportResponse(std::string(), net::HTTP_OK);
  568. task_environment_.RunUntilIdle();
  569. EXPECT_TRUE(use_case->IsLastKnownPingTimestampSet());
  570. }
  571. EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
  572. EXPECT_EQ(device_activity_client_->GetState(),
  573. DeviceActivityClient::State::kIdle);
  574. }
  575. TEST_F(DeviceActivityClientTest, CheckInOnLocalStateSetAndPingRequired) {
  576. // Set the use cases last ping timestamps to a previous month.
  577. // This date must be ahead of unix epoch, since that is the default value
  578. // of the local state time pref.
  579. // The current time in the unit tests is 10 years after unix epoch.
  580. base::Time expected;
  581. ASSERT_TRUE(base::Time::FromUTCString("2000-01-01 00:00:00", &expected));
  582. for (auto* use_case : device_activity_client_->GetUseCases()) {
  583. use_case->SetLastKnownPingTimestamp(expected);
  584. }
  585. // Device active reporting starts check in on network connect.
  586. SetWifiNetworkState(shill::kStateOnline);
  587. for (auto* use_case : device_activity_client_->GetUseCases()) {
  588. SCOPED_TRACE(testing::Message()
  589. << "PSM use case: "
  590. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  591. EXPECT_TRUE(use_case->IsLastKnownPingTimestampSet());
  592. EXPECT_EQ(device_activity_client_->GetState(),
  593. DeviceActivityClient::State::kCheckingIn);
  594. SimulateImportResponse(std::string(), net::HTTP_OK);
  595. task_environment_.RunUntilIdle();
  596. // base::Time::Now() is updated in |DeviceActivityClientTest| constructor.
  597. EXPECT_GE(use_case->GetLastKnownPingTimestamp(), expected);
  598. }
  599. EXPECT_EQ(device_activity_client_->GetState(),
  600. DeviceActivityClient::State::kIdle);
  601. }
  602. TEST_F(DeviceActivityClientTest, TransitionClientToIdleOnInvalidOprfResponse) {
  603. // Device active reporting starts check membership on network connect.
  604. SetWifiNetworkState(shill::kStateOnline);
  605. for (auto* use_case : device_activity_client_->GetUseCases()) {
  606. SCOPED_TRACE(testing::Message()
  607. << "PSM use case: "
  608. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  609. EXPECT_EQ(device_activity_client_->GetState(),
  610. DeviceActivityClient::State::kCheckingMembershipOprf);
  611. // Return an invalid Fresnel OPRF response.
  612. SimulateOprfResponse(/*fresnel_oprf_response*/ std::string(), net::HTTP_OK);
  613. task_environment_.RunUntilIdle();
  614. }
  615. EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
  616. EXPECT_EQ(device_activity_client_->GetState(),
  617. DeviceActivityClient::State::kIdle);
  618. }
  619. TEST_F(DeviceActivityClientTest, TransitionClientToIdleOnInvalidQueryResponse) {
  620. // Device active reporting starts check membership on network connect.
  621. SetWifiNetworkState(shill::kStateOnline);
  622. // |nonmember_test_case| is used to return psm response bodies for
  623. // the OPRF, and Query requests. The query request returns nonmember status.
  624. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  625. nonmember_test_case = psm_test_data_->nonmember_test_case;
  626. for (auto* use_case : device_activity_client_->GetUseCases()) {
  627. SCOPED_TRACE(testing::Message()
  628. << "PSM use case: "
  629. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  630. EXPECT_EQ(device_activity_client_->GetState(),
  631. DeviceActivityClient::State::kCheckingMembershipOprf);
  632. // Return a valid OPRF response.
  633. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  634. net::HTTP_OK);
  635. // Return an invalid Query response.
  636. SimulateQueryResponse(std::string(), net::HTTP_OK);
  637. task_environment_.RunUntilIdle();
  638. }
  639. EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
  640. EXPECT_EQ(device_activity_client_->GetState(),
  641. DeviceActivityClient::State::kIdle);
  642. }
  643. TEST_F(DeviceActivityClientTest, DailyCheckInFailsButMonthlyCheckInSucceeds) {
  644. // Device active reporting starts check membership on network connect.
  645. SetWifiNetworkState(shill::kStateOnline);
  646. // |nonmember_test_case| is used to return psm response bodies for
  647. // the OPRF, and Query requests. The query request returns nonmember status.
  648. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  649. nonmember_test_case = psm_test_data_->nonmember_test_case;
  650. for (auto* use_case : device_activity_client_->GetUseCases()) {
  651. SCOPED_TRACE(testing::Message()
  652. << "PSM use case: "
  653. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  654. // On first ever ping, we begin the check membership protocol
  655. // since the local state pref for that use case is by default unix
  656. // epoch.
  657. EXPECT_FALSE(use_case->IsLastKnownPingTimestampSet());
  658. EXPECT_EQ(device_activity_client_->GetState(),
  659. DeviceActivityClient::State::kCheckingMembershipOprf);
  660. if (use_case->GetPsmUseCase() ==
  661. psm_rlwe::RlweUseCase::CROS_FRESNEL_DAILY) {
  662. // Daily use case will terminate while failing to parse
  663. // this invalid OPRF response.
  664. SimulateOprfResponse(std::string(), net::HTTP_OK);
  665. task_environment_.RunUntilIdle();
  666. // Failed to update the local state since the OPRF response was invalid.
  667. EXPECT_FALSE(use_case->IsLastKnownPingTimestampSet());
  668. } else if (use_case->GetPsmUseCase() ==
  669. psm_rlwe::RlweUseCase::CROS_FRESNEL_MONTHLY) {
  670. // Monthly use case will return valid psm network request responses.
  671. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  672. net::HTTP_OK);
  673. SimulateQueryResponse(GetFresnelQueryResponse(nonmember_test_case),
  674. net::HTTP_OK);
  675. SimulateImportResponse(std::string(), net::HTTP_OK);
  676. task_environment_.RunUntilIdle();
  677. // Successfully imported and updated the last ping timestamp to the
  678. // current mocked time for this test.
  679. EXPECT_EQ(use_case->GetLastKnownPingTimestamp(), base::Time::Now());
  680. } else {
  681. // Currently we only support daily, and monthly use cases.
  682. NOTREACHED() << "Invalid Use Case.";
  683. }
  684. }
  685. EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
  686. EXPECT_EQ(device_activity_client_->GetState(),
  687. DeviceActivityClient::State::kIdle);
  688. }
  689. TEST_F(DeviceActivityClientTest, MonthlyCheckInFailsButDailyCheckInSucceeds) {
  690. // Device active reporting starts check membership on network connect.
  691. SetWifiNetworkState(shill::kStateOnline);
  692. // |nonmember_test_case| is used to return psm response bodies for
  693. // the OPRF, and Query requests. The query request returns nonmember status.
  694. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  695. nonmember_test_case = psm_test_data_->nonmember_test_case;
  696. for (auto* use_case : device_activity_client_->GetUseCases()) {
  697. SCOPED_TRACE(testing::Message()
  698. << "PSM use case: "
  699. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  700. // On first ever ping, we begin the check membership protocol
  701. // since the local state pref for that use case is by default unix
  702. // epoch.
  703. EXPECT_FALSE(use_case->IsLastKnownPingTimestampSet());
  704. EXPECT_EQ(device_activity_client_->GetState(),
  705. DeviceActivityClient::State::kCheckingMembershipOprf);
  706. if (use_case->GetPsmUseCase() ==
  707. psm_rlwe::RlweUseCase::CROS_FRESNEL_DAILY) {
  708. // Daily use case will return valid psm network request responses.
  709. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  710. net::HTTP_OK);
  711. SimulateQueryResponse(GetFresnelQueryResponse(nonmember_test_case),
  712. net::HTTP_OK);
  713. SimulateImportResponse(std::string(), net::HTTP_OK);
  714. task_environment_.RunUntilIdle();
  715. // Successfully imported and updated the last ping timestamp to the
  716. // current mocked time for this test.
  717. EXPECT_EQ(use_case->GetLastKnownPingTimestamp(), base::Time::Now());
  718. } else if (use_case->GetPsmUseCase() ==
  719. psm_rlwe::RlweUseCase::CROS_FRESNEL_MONTHLY) {
  720. // Monthly use case will terminate while failing to parse
  721. // this invalid OPRF response.
  722. SimulateOprfResponse(std::string(), net::HTTP_OK);
  723. task_environment_.RunUntilIdle();
  724. // Failed to update the local state since the OPRF response was invalid.
  725. EXPECT_FALSE(use_case->IsLastKnownPingTimestampSet());
  726. } else {
  727. // Currently we only support daily, and monthly use cases.
  728. NOTREACHED() << "Invalid Use Case.";
  729. }
  730. }
  731. EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
  732. EXPECT_EQ(device_activity_client_->GetState(),
  733. DeviceActivityClient::State::kIdle);
  734. }
  735. TEST_F(DeviceActivityClientTest, CurrentTimeIsBeforeLocalStateTimeStamp) {
  736. // Update last ping timestamps to a time in the future.
  737. base::Time expected;
  738. ASSERT_TRUE(base::Time::FromUTCString("2100-01-01 00:00:00", &expected));
  739. for (auto* use_case : device_activity_client_->GetUseCases()) {
  740. use_case->SetLastKnownPingTimestamp(expected);
  741. }
  742. // Device active reporting is triggered by network connection.
  743. SetWifiNetworkState(shill::kStateOnline);
  744. // Device pings are not required since the last ping timestamps are in the
  745. // future. Client will stay in |kIdle| state.
  746. EXPECT_EQ(device_activity_client_->GetState(),
  747. DeviceActivityClient::State::kIdle);
  748. }
  749. TEST_F(DeviceActivityClientTest, StayIdleIfTimerFiresWithoutNetworkConnected) {
  750. EXPECT_EQ(device_activity_client_->GetState(),
  751. DeviceActivityClient::State::kIdle);
  752. SetWifiNetworkState(shill::kStateOffline);
  753. FireTimer();
  754. // Verify that no network requests were sent.
  755. EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
  756. EXPECT_EQ(device_activity_client_->GetState(),
  757. DeviceActivityClient::State::kIdle);
  758. }
  759. TEST_F(DeviceActivityClientTest, CheckInIfCheckMembershipReturnsFalse) {
  760. // Device active reporting starts check membership on network connect.
  761. SetWifiNetworkState(shill::kStateOnline);
  762. // |nonmember_test_case| is used to return psm response bodies for
  763. // the OPRF, and Query requests. The query request returns nonmember status.
  764. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  765. nonmember_test_case = psm_test_data_->nonmember_test_case;
  766. for (auto* use_case : device_activity_client_->GetUseCases()) {
  767. SCOPED_TRACE(testing::Message()
  768. << "PSM use case: "
  769. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  770. EXPECT_EQ(device_activity_client_->GetState(),
  771. DeviceActivityClient::State::kCheckingMembershipOprf);
  772. base::Time prev_time = use_case->GetLastKnownPingTimestamp();
  773. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  774. net::HTTP_OK);
  775. SimulateQueryResponse(GetFresnelQueryResponse(nonmember_test_case),
  776. net::HTTP_OK);
  777. SimulateImportResponse(std::string(), net::HTTP_OK);
  778. task_environment_.RunUntilIdle();
  779. // After a PSM identifier is checked in, local state prefs is updated.
  780. EXPECT_LT(prev_time, use_case->GetLastKnownPingTimestamp());
  781. }
  782. EXPECT_EQ(device_activity_client_->GetState(),
  783. DeviceActivityClient::State::kIdle);
  784. }
  785. TEST_F(DeviceActivityClientTest, NetworkDisconnectsWhileWaitingForResponse) {
  786. // Device active reporting starts check membership on network connect.
  787. SetWifiNetworkState(shill::kStateOnline);
  788. // We expect the size of the use cases to be greater than 0.
  789. EXPECT_GT(device_activity_client_->GetUseCases().size(), 0);
  790. EXPECT_EQ(device_activity_client_->GetState(),
  791. DeviceActivityClient::State::kCheckingMembershipOprf);
  792. // Currently there is at least 1 pending request that has not received it's
  793. // response.
  794. EXPECT_GT(test_url_loader_factory_.NumPending(), 0);
  795. // Disconnect network.
  796. SetWifiNetworkState(shill::kStateOffline);
  797. // All pending requests should be cancelled, and our device activity client
  798. // should get set back to |kIdle|.
  799. EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
  800. EXPECT_EQ(device_activity_client_->GetState(),
  801. DeviceActivityClient::State::kIdle);
  802. }
  803. TEST_F(DeviceActivityClientTest,
  804. ReportGracefullyAfterNetworkDisconnectsDuringPreviousRun) {
  805. // Device active reporting starts check membership on network connect.
  806. SetWifiNetworkState(shill::kStateOnline);
  807. DeviceActiveUseCase* first_use_case =
  808. device_activity_client_->GetUseCases().front();
  809. EXPECT_EQ(device_activity_client_->GetState(),
  810. DeviceActivityClient::State::kCheckingMembershipOprf);
  811. EXPECT_NE(first_use_case->GetWindowIdentifier(), absl::nullopt);
  812. EXPECT_NE(first_use_case->GetPsmIdentifier(), absl::nullopt);
  813. EXPECT_NE(first_use_case->GetPsmRlweClient(), nullptr);
  814. // While waiting for OPRF request, simulate network disconnection.
  815. SetWifiNetworkState(shill::kStateOffline);
  816. // Network offline should cancel all pending use cases, and clear the saved
  817. // state of the attempted pings.
  818. for (auto* use_case : device_activity_client_->GetUseCases()) {
  819. SCOPED_TRACE(testing::Message()
  820. << "PSM use case: "
  821. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  822. // Currently the use cases stores window id, psm id, and psm rlwe client
  823. // pointer in state.
  824. EXPECT_EQ(use_case->GetWindowIdentifier(), absl::nullopt);
  825. EXPECT_EQ(use_case->GetPsmIdentifier(), absl::nullopt);
  826. EXPECT_EQ(use_case->GetPsmRlweClient(), nullptr);
  827. }
  828. // Return back to |kIdle| state after a successful check-in.
  829. EXPECT_EQ(device_activity_client_->GetState(),
  830. DeviceActivityClient::State::kIdle);
  831. // Attempt to report actives gracefully.
  832. // Device active reporting starts check membership on network connect.
  833. SetWifiNetworkState(shill::kStateOnline);
  834. // |nonmember_test_case| is used to return psm response bodies for
  835. // the OPRF, and Query requests. The query request returns nonmember status.
  836. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  837. nonmember_test_case = psm_test_data_->nonmember_test_case;
  838. for (auto* use_case : device_activity_client_->GetUseCases()) {
  839. SCOPED_TRACE(testing::Message()
  840. << "PSM use case: "
  841. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  842. EXPECT_EQ(device_activity_client_->GetState(),
  843. DeviceActivityClient::State::kCheckingMembershipOprf);
  844. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  845. net::HTTP_OK);
  846. SimulateQueryResponse(GetFresnelQueryResponse(nonmember_test_case),
  847. net::HTTP_OK);
  848. SimulateImportResponse(std::string(), net::HTTP_OK);
  849. task_environment_.RunUntilIdle();
  850. }
  851. // Return back to |kIdle| state after a successful check-in.
  852. EXPECT_EQ(device_activity_client_->GetState(),
  853. DeviceActivityClient::State::kIdle);
  854. // Verify that |OnCheckInDone| is called for each use case.
  855. histogram_tester_.ExpectBucketCount(
  856. "Ash.DeviceActivity.MethodCalled",
  857. DeviceActivityClient::DeviceActivityMethod::
  858. kDeviceActivityClientOnCheckInDone,
  859. 2);
  860. // Verify the last known ping timestamp is set for each use case.
  861. for (auto* use_case : device_activity_client_->GetUseCases()) {
  862. SCOPED_TRACE(testing::Message()
  863. << "PSM use case: "
  864. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  865. EXPECT_TRUE(use_case->IsLastKnownPingTimestampSet());
  866. }
  867. // Returned back to |kIdle| state after a successful check-in.
  868. EXPECT_EQ(device_activity_client_->GetState(),
  869. DeviceActivityClient::State::kIdle);
  870. }
  871. TEST_F(DeviceActivityClientTest, NetworkDisconnectionClearsUseCaseState) {
  872. // Device active reporting starts check membership on network connect.
  873. SetWifiNetworkState(shill::kStateOnline);
  874. // After the network comes online, the client triggers device active reporting
  875. // for the front use case first. It will block on waiting for a response from
  876. // the OPRF network request. At this point the window id, psm id, and psm rlwe
  877. // client should be set by the client for just the front use case.
  878. DeviceActiveUseCase* first_use_case =
  879. device_activity_client_->GetUseCases().front();
  880. EXPECT_EQ(device_activity_client_->GetState(),
  881. DeviceActivityClient::State::kCheckingMembershipOprf);
  882. EXPECT_NE(first_use_case->GetWindowIdentifier(), absl::nullopt);
  883. EXPECT_NE(first_use_case->GetPsmIdentifier(), absl::nullopt);
  884. EXPECT_NE(first_use_case->GetPsmRlweClient(), nullptr);
  885. // While waiting for OPRF response, simulate network disconnection.
  886. SetWifiNetworkState(shill::kStateOffline);
  887. // Network offline should cancel all pending use cases, and clear the saved
  888. // state of the attempted pings.
  889. for (auto* use_case : device_activity_client_->GetUseCases()) {
  890. SCOPED_TRACE(testing::Message()
  891. << "PSM use case: "
  892. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  893. // Currently the use cases stores window id, psm id, and psm rlwe client
  894. // pointer in state.
  895. EXPECT_EQ(use_case->GetWindowIdentifier(), absl::nullopt);
  896. EXPECT_EQ(use_case->GetPsmIdentifier(), absl::nullopt);
  897. EXPECT_EQ(use_case->GetPsmRlweClient(), nullptr);
  898. }
  899. // Return back to |kIdle| state after the network goes offline.
  900. EXPECT_EQ(device_activity_client_->GetState(),
  901. DeviceActivityClient::State::kIdle);
  902. }
  903. TEST_F(DeviceActivityClientTest, CheckInAfterNextUtcMidnight) {
  904. // Device active reporting starts check membership on network connect.
  905. SetWifiNetworkState(shill::kStateOnline);
  906. // |nonmember_test_case| is used to return psm response bodies for
  907. // the OPRF, and Query requests. The query request returns nonmember status.
  908. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  909. nonmember_test_case = psm_test_data_->nonmember_test_case;
  910. for (auto* use_case : device_activity_client_->GetUseCases()) {
  911. SCOPED_TRACE(testing::Message()
  912. << "PSM use case: "
  913. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  914. EXPECT_EQ(device_activity_client_->GetState(),
  915. DeviceActivityClient::State::kCheckingMembershipOprf);
  916. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  917. net::HTTP_OK);
  918. SimulateQueryResponse(GetFresnelQueryResponse(nonmember_test_case),
  919. net::HTTP_OK);
  920. SimulateImportResponse(std::string(), net::HTTP_OK);
  921. task_environment_.RunUntilIdle();
  922. }
  923. // Return back to |kIdle| state after a successful check-in.
  924. EXPECT_EQ(device_activity_client_->GetState(),
  925. DeviceActivityClient::State::kIdle);
  926. task_environment_.FastForwardBy(TimeUntilNextUTCMidnight());
  927. task_environment_.RunUntilIdle();
  928. FireTimer();
  929. // Check that at least 1 network request is pending since the PSM id
  930. // has NOT been imported for the new UTC period.
  931. EXPECT_GT(test_url_loader_factory_.NumPending(), 0);
  932. // Verify state is |kCheckingIn| since local state was updated
  933. // with the last check in timestamp during the previous day check ins.
  934. EXPECT_EQ(device_activity_client_->GetState(),
  935. DeviceActivityClient::State::kCheckingIn);
  936. // Return well formed Import response body for the DAILY use case.
  937. // The time was forwarded by 1 day, which means only the daily use case will
  938. // report actives again.
  939. SimulateImportResponse(std::string(), net::HTTP_OK);
  940. task_environment_.RunUntilIdle();
  941. // Return back to |kIdle| state after successful check-in of daily use case.
  942. EXPECT_EQ(device_activity_client_->GetState(),
  943. DeviceActivityClient::State::kIdle);
  944. }
  945. TEST_F(DeviceActivityClientTest, DoNotCheckInTwiceBeforeNextUtcDay) {
  946. // Device active reporting starts check membership on network connect.
  947. SetWifiNetworkState(shill::kStateOnline);
  948. // |nonmember_test_case| is used to return psm response bodies for
  949. // the OPRF, and Query requests. The query request returns nonmember status.
  950. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  951. nonmember_test_case = psm_test_data_->nonmember_test_case;
  952. for (auto* use_case : device_activity_client_->GetUseCases()) {
  953. SCOPED_TRACE(testing::Message()
  954. << "PSM use case: "
  955. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  956. EXPECT_EQ(device_activity_client_->GetState(),
  957. DeviceActivityClient::State::kCheckingMembershipOprf);
  958. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  959. net::HTTP_OK);
  960. SimulateQueryResponse(GetFresnelQueryResponse(nonmember_test_case),
  961. net::HTTP_OK);
  962. SimulateImportResponse(std::string(), net::HTTP_OK);
  963. task_environment_.RunUntilIdle();
  964. }
  965. // Return back to |kIdle| state after the first successful check-in.
  966. EXPECT_EQ(device_activity_client_->GetState(),
  967. DeviceActivityClient::State::kIdle);
  968. base::TimeDelta before_utc_meridian =
  969. TimeUntilNextUTCMidnight() - base::Minutes(1);
  970. task_environment_.FastForwardBy(before_utc_meridian);
  971. task_environment_.RunUntilIdle();
  972. // Trigger attempt to report device active.
  973. FireTimer();
  974. // Client should not send any network requests since device is still in same
  975. // UTC day.
  976. EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
  977. // Remains in |kIdle| state since the device is still in same UTC day.
  978. EXPECT_EQ(device_activity_client_->GetState(),
  979. DeviceActivityClient::State::kIdle);
  980. }
  981. TEST_F(DeviceActivityClientTest, CheckInAfterNextUtcMonth) {
  982. // Device active reporting starts check membership on network connect.
  983. SetWifiNetworkState(shill::kStateOnline);
  984. // |nonmember_test_case| is used to return psm response bodies for
  985. // the OPRF, and Query requests. The query request returns nonmember status.
  986. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  987. nonmember_test_case = psm_test_data_->nonmember_test_case;
  988. for (auto* use_case : device_activity_client_->GetUseCases()) {
  989. SCOPED_TRACE(testing::Message()
  990. << "PSM use case: "
  991. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  992. EXPECT_EQ(device_activity_client_->GetState(),
  993. DeviceActivityClient::State::kCheckingMembershipOprf);
  994. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  995. net::HTTP_OK);
  996. SimulateQueryResponse(GetFresnelQueryResponse(nonmember_test_case),
  997. net::HTTP_OK);
  998. SimulateImportResponse(std::string(), net::HTTP_OK);
  999. task_environment_.RunUntilIdle();
  1000. }
  1001. // Return back to |kIdle| state after a successful check-in.
  1002. EXPECT_EQ(device_activity_client_->GetState(),
  1003. DeviceActivityClient::State::kIdle);
  1004. task_environment_.FastForwardBy(TimeUntilNewUTCMonth());
  1005. task_environment_.RunUntilIdle();
  1006. FireTimer();
  1007. // Check that at least 1 network request is pending since the PSM id
  1008. // has NOT been imported for the new UTC period.
  1009. EXPECT_GT(test_url_loader_factory_.NumPending(), 0);
  1010. // Verify state is |kCheckingIn| since local state was updated
  1011. // with the last check in timestamp during the previous day check ins.
  1012. EXPECT_EQ(device_activity_client_->GetState(),
  1013. DeviceActivityClient::State::kCheckingIn);
  1014. // Return well formed Import response body for daily and monthly use case.
  1015. // The time was forwarded to a new month, which means the daily and monthly
  1016. // use cases will report active again.
  1017. for (auto* use_case : device_activity_client_->GetUseCases()) {
  1018. psm_rlwe::RlweUseCase psm_use_case = use_case->GetPsmUseCase();
  1019. SCOPED_TRACE(testing::Message()
  1020. << "PSM use case: "
  1021. << psm_rlwe::RlweUseCase_Name(psm_use_case));
  1022. if (psm_use_case == psm_rlwe::RlweUseCase::CROS_FRESNEL_DAILY ||
  1023. psm_use_case == psm_rlwe::RlweUseCase::CROS_FRESNEL_MONTHLY) {
  1024. EXPECT_EQ(device_activity_client_->GetState(),
  1025. DeviceActivityClient::State::kCheckingIn);
  1026. SimulateImportResponse(std::string(), net::HTTP_OK);
  1027. task_environment_.RunUntilIdle();
  1028. }
  1029. }
  1030. // Return back to |kIdle| state after successful check-in of daily use case.
  1031. EXPECT_EQ(device_activity_client_->GetState(),
  1032. DeviceActivityClient::State::kIdle);
  1033. }
  1034. // Powerwashing a device resets the local state. This will result in the
  1035. // client re-importing a PSM ID, on the same day.
  1036. TEST_F(DeviceActivityClientTest, CheckInAgainOnLocalStateReset) {
  1037. // Device active reporting starts check membership on network connect.
  1038. SetWifiNetworkState(shill::kStateOnline);
  1039. // |nonmember_test_case| is used to return psm response bodies for
  1040. // the OPRF, and Query requests. The query request returns nonmember status.
  1041. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  1042. nonmember_test_case = psm_test_data_->nonmember_test_case;
  1043. for (auto* use_case : device_activity_client_->GetUseCases()) {
  1044. SCOPED_TRACE(testing::Message()
  1045. << "PSM use case: "
  1046. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  1047. base::Time prev_time = use_case->GetLastKnownPingTimestamp();
  1048. // Mock Successful |kCheckingMembershipOprf|.
  1049. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  1050. net::HTTP_OK);
  1051. // Mock Successful |kCheckingMembershipQuery|.
  1052. SimulateQueryResponse(GetFresnelQueryResponse(nonmember_test_case),
  1053. net::HTTP_OK);
  1054. // Mock Successful |kCheckingIn|.
  1055. SimulateImportResponse(std::string(), net::HTTP_OK);
  1056. task_environment_.RunUntilIdle();
  1057. base::Time new_time = use_case->GetLastKnownPingTimestamp();
  1058. // After a PSM identifier is checked in, local state prefs is updated.
  1059. EXPECT_LT(prev_time, new_time);
  1060. }
  1061. // Simulate powerwashing device by removing related local state prefs.
  1062. SimulateLocalStateOnPowerwash();
  1063. // Retrigger |TransitionOutOfIdle| codepath by either firing timer or
  1064. // reconnecting network.
  1065. FireTimer();
  1066. // Verify each use case performs check in successfully after local state prefs
  1067. // is reset.
  1068. for (auto* use_case : device_activity_client_->GetUseCases()) {
  1069. SCOPED_TRACE(testing::Message()
  1070. << "PSM use case: "
  1071. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  1072. // Verify that the |kCheckingIn| state is reached.
  1073. // Indicator is used to verify that we are checking in the PSM ID again
  1074. // after powerwash/recovery scenario.
  1075. EXPECT_EQ(device_activity_client_->GetState(),
  1076. DeviceActivityClient::State::kCheckingMembershipOprf);
  1077. base::Time prev_time = use_case->GetLastKnownPingTimestamp();
  1078. // Mock Successful |kCheckingMembershipOprf|.
  1079. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  1080. net::HTTP_OK);
  1081. // Mock Successful |kCheckingMembershipQuery|.
  1082. SimulateQueryResponse(GetFresnelQueryResponse(nonmember_test_case),
  1083. net::HTTP_OK);
  1084. // Mock Successful |kCheckingIn|.
  1085. SimulateImportResponse(std::string(), net::HTTP_OK);
  1086. task_environment_.RunUntilIdle();
  1087. base::Time new_time = use_case->GetLastKnownPingTimestamp();
  1088. // After a PSM identifier is checked in, local state prefs is updated.
  1089. EXPECT_LT(prev_time, new_time);
  1090. }
  1091. // Transitions back to |kIdle| state.
  1092. EXPECT_EQ(device_activity_client_->GetState(),
  1093. DeviceActivityClient::State::kIdle);
  1094. }
  1095. TEST_F(DeviceActivityClientTest, InitialUmaHistogramStateCount) {
  1096. histogram_tester_.ExpectBucketCount(
  1097. "Ash.DeviceActiveClient.StateCount",
  1098. DeviceActivityClient::State::kCheckingMembershipOprf, 0);
  1099. histogram_tester_.ExpectBucketCount(
  1100. "Ash.DeviceActiveClient.StateCount",
  1101. DeviceActivityClient::State::kCheckingMembershipQuery, 0);
  1102. histogram_tester_.ExpectBucketCount("Ash.DeviceActiveClient.StateCount",
  1103. DeviceActivityClient::State::kCheckingIn,
  1104. 0);
  1105. }
  1106. TEST_F(DeviceActivityClientTest, UmaHistogramStateCountAfterFirstCheckIn) {
  1107. // Device active reporting starts membership check on network connect.
  1108. SetWifiNetworkState(shill::kStateOnline);
  1109. std::vector<DeviceActiveUseCase*> use_cases =
  1110. device_activity_client_->GetUseCases();
  1111. // |nonmember_test_case| is used to return psm response bodies for
  1112. // the OPRF, and Query requests. The query request returns nonmember status.
  1113. const psm_rlwe::PrivateMembershipRlweClientRegressionTestData::TestCase&
  1114. nonmember_test_case = psm_test_data_->nonmember_test_case;
  1115. for (auto* use_case : use_cases) {
  1116. SCOPED_TRACE(testing::Message()
  1117. << "PSM use case: "
  1118. << psm_rlwe::RlweUseCase_Name(use_case->GetPsmUseCase()));
  1119. // Mock Successful |kCheckingMembershipOprf|.
  1120. SimulateOprfResponse(GetFresnelOprfResponse(nonmember_test_case),
  1121. net::HTTP_OK);
  1122. // Mock Successful |kCheckingMembershipQuery|.
  1123. SimulateQueryResponse(GetFresnelQueryResponse(nonmember_test_case),
  1124. net::HTTP_OK);
  1125. // Mock Successful |kCheckingIn|.
  1126. SimulateImportResponse(std::string(), net::HTTP_OK);
  1127. task_environment_.RunUntilIdle();
  1128. }
  1129. histogram_tester_.ExpectBucketCount("Ash.DeviceActiveClient.StateCount",
  1130. DeviceActivityClient::State::kCheckingIn,
  1131. use_cases.size());
  1132. }
  1133. } // namespace device_activity
  1134. } // namespace ash