• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/metrics/structured/structured_metrics_provider.h"
6 #include <cstdint>
7 
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/test/bind.h"
13 #include "base/test/metrics/histogram_tester.h"
14 #include "base/test/scoped_feature_list.h"
15 #include "base/test/task_environment.h"
16 #include "base/threading/scoped_blocking_call.h"
17 #include "components/metrics/structured/event.h"
18 #include "components/metrics/structured/recorder.h"
19 #include "components/metrics/structured/storage.pb.h"
20 #include "components/metrics/structured/structured_events.h"
21 #include "components/metrics/structured/structured_metrics_features.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
24 
25 namespace metrics::structured {
26 
27 namespace {
28 
29 // These project, event, and metric names are used for testing.
30 
31 // The name hash of "TestProjectOne".
32 constexpr uint64_t kProjectOneHash = UINT64_C(16881314472396226433);
33 // The name hash of "TestProjectTwo".
34 constexpr uint64_t kProjectTwoHash = UINT64_C(5876808001962504629);
35 // The name hash of "TestProjectThree".
36 constexpr uint64_t kProjectThreeHash = UINT64_C(10860358748803291132);
37 // The name hash of "TestProjectFour".
38 constexpr uint64_t kProjectFourHash = UINT64_C(6801665881746546626);
39 // The name hash of "TestProjectFive"
40 constexpr uint64_t kProjectFiveHash = UINT64_C(3960582687892677139);
41 // The name hash of "TestProjectSix"
42 constexpr uint64_t kProjectSixHash = UINT64_C(6972396123792667134);
43 // The name hash of "CrOSEvents"
44 constexpr uint64_t kCrOSEventsProjectHash = UINT64_C(12657197978410187837);
45 
46 // The name hash of "chrome::TestProjectOne::TestEventOne".
47 constexpr uint64_t kEventOneHash = UINT64_C(13593049295042080097);
48 // The name hash of "chrome::TestProjectTwo::TestEventTwo".
49 constexpr uint64_t kEventTwoHash = UINT64_C(8995967733561999410);
50 // The name hash of "chrome::TestProjectTwo::TestEventThree".
51 constexpr uint64_t kEventThreeHash = UINT64_C(5848687377041124372);
52 // The name hash of "chrome::TestProjectThree::TestEventFour".
53 constexpr uint64_t kEventFourHash = UINT64_C(1718797808092246258);
54 // The name hash of "chrome::TestProjectFour::TestEventFive".
55 constexpr uint64_t kEventFiveHash = UINT64_C(7045523601811399253);
56 // The name hash of "chrome::TestProjectFour::TestEventSix".
57 constexpr uint64_t kEventSixHash = UINT64_C(2873337042686447043);
58 // The name hash of "chrome::TestProjectSix::TestEventSeven".
59 constexpr uint64_t kEventSevenHash = UINT64_C(16749091071228286247);
60 // The name hash of "chrome::CrOSEvents::NoMetricsEvent".
61 constexpr uint64_t kNoMetricsEventHash = UINT64_C(5106854608989380457);
62 
63 // The name hash of "TestMetricOne".
64 constexpr uint64_t kMetricOneHash = UINT64_C(637929385654885975);
65 // The name hash of "TestMetricTwo".
66 constexpr uint64_t kMetricTwoHash = UINT64_C(14083999144141567134);
67 // The name hash of "TestMetricThree".
68 constexpr uint64_t kMetricThreeHash = UINT64_C(13469300759843809564);
69 // The name hash of "TestMetricFour".
70 constexpr uint64_t kMetricFourHash = UINT64_C(2917855408523247722);
71 // The name hash of "TestMetricFive".
72 constexpr uint64_t kMetricFiveHash = UINT64_C(8665976921794972190);
73 // The name hash of "TestMetricSix".
74 constexpr uint64_t kMetricSixHash = UINT64_C(3431522567539822144);
75 // The name hash of "TestMetricSeven".
76 constexpr uint64_t kMetricSevenHash = UINT64_C(8395865158198697574);
77 
78 // The hex-encoded first 8 bytes of SHA256("aaa...a")
79 constexpr char kProjectOneId[] = "3BA3F5F43B926026";
80 // The hex-encoded first 8 bytes of SHA256("bbb...b")
81 constexpr char kProjectTwoId[] = "BDB339768BC5E4FE";
82 // The hex-encoded first 8 bytes of SHA256("ddd...d")
83 constexpr char kProjectFourId[] = "FBBBB6DE2AA74C3C";
84 
85 // Test values.
86 constexpr char kValueOne[] = "value one";
87 constexpr char kValueTwo[] = "value two";
88 
89 constexpr char kHwid[] = "hwid";
90 constexpr size_t kUserCount = 3;
91 
HashToHex(const uint64_t hash)92 std::string HashToHex(const uint64_t hash) {
93   return base::HexEncode(&hash, sizeof(uint64_t));
94 }
95 
96 // Make a simple testing proto with one |uma_events| message for each id in
97 // |ids|.
MakeExternalEventProto(const std::vector<uint64_t> & ids)98 EventsProto MakeExternalEventProto(const std::vector<uint64_t>& ids) {
99   EventsProto proto;
100 
101   for (const auto id : ids) {
102     auto* event = proto.add_uma_events();
103     event->set_profile_event_id(id);
104   }
105 
106   return proto;
107 }
108 
109 class TestRecorder : public StructuredMetricsClient::RecordingDelegate {
110  public:
111   TestRecorder() = default;
112   TestRecorder(const TestRecorder& recorder) = delete;
113   TestRecorder& operator=(const TestRecorder& recorder) = delete;
114   ~TestRecorder() override = default;
115 
RecordEvent(Event && event)116   void RecordEvent(Event&& event) override {
117     Recorder::GetInstance()->RecordEvent(std::move(event));
118   }
119 
IsReadyToRecord() const120   bool IsReadyToRecord() const override { return true; }
121 };
122 
123 class TestSystemProfileProvider : public metrics::MetricsProvider {
124  public:
125   TestSystemProfileProvider() = default;
126   TestSystemProfileProvider(const TestSystemProfileProvider& recorder) = delete;
127   TestSystemProfileProvider& operator=(
128       const TestSystemProfileProvider& recorder) = delete;
129   ~TestSystemProfileProvider() override = default;
130 
ProvideSystemProfileMetrics(metrics::SystemProfileProto * proto)131   void ProvideSystemProfileMetrics(
132       metrics::SystemProfileProto* proto) override {
133     proto->set_multi_profile_user_count(kUserCount);
134     proto->mutable_hardware()->set_full_hardware_class(kHwid);
135   }
136 };
137 
138 }  // namespace
139 
140 class StructuredMetricsProviderTest : public testing::Test {
141  protected:
SetUp()142   void SetUp() override {
143     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
144     Recorder::GetInstance()->SetUiTaskRunner(
145         task_environment_.GetMainThreadTaskRunner());
146     StructuredMetricsClient::Get()->SetDelegate(&recorder_);
147     // Move the mock date forward from day 0, because KeyData assumes that day 0
148     // is a bug.
149     task_environment_.AdvanceClock(base::Days(1000));
150   }
151 
TempDirPath()152   base::FilePath TempDirPath() { return temp_dir_.GetPath(); }
153 
ProfileKeyFilePath()154   base::FilePath ProfileKeyFilePath() {
155     return temp_dir_.GetPath().Append("structured_metrics").Append("keys");
156   }
157 
DeviceKeyFilePath()158   base::FilePath DeviceKeyFilePath() {
159     return temp_dir_.GetPath()
160         .Append("structured_metrics")
161         .Append("device_keys");
162   }
163 
Wait()164   void Wait() { task_environment_.RunUntilIdle(); }
165 
WriteTestingProfileKeys()166   void WriteTestingProfileKeys() {
167     const int today = (base::Time::Now() - base::Time::UnixEpoch()).InDays();
168 
169     KeyDataProto proto;
170     KeyProto& key_one = (*proto.mutable_keys())[kProjectOneHash];
171     key_one.set_key("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
172     key_one.set_last_rotation(today);
173     key_one.set_rotation_period(90);
174 
175     KeyProto& key_two = (*proto.mutable_keys())[kProjectTwoHash];
176     key_two.set_key("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
177     key_two.set_last_rotation(today);
178     key_two.set_rotation_period(90);
179 
180     KeyProto& key_three = (*proto.mutable_keys())[kProjectThreeHash];
181     key_three.set_key("cccccccccccccccccccccccccccccccc");
182     key_three.set_last_rotation(today);
183     key_three.set_rotation_period(90);
184 
185     base::CreateDirectory(ProfileKeyFilePath().DirName());
186     ASSERT_TRUE(
187         base::WriteFile(ProfileKeyFilePath(), proto.SerializeAsString()));
188     Wait();
189   }
190 
WriteTestingDeviceKeys()191   void WriteTestingDeviceKeys() {
192     const int today = (base::Time::Now() - base::Time::UnixEpoch()).InDays();
193 
194     KeyDataProto proto;
195     KeyProto& key = (*proto.mutable_keys())[kProjectFourHash];
196     key.set_key("dddddddddddddddddddddddddddddddd");
197     key.set_last_rotation(today);
198     key.set_rotation_period(90);
199 
200     base::CreateDirectory(DeviceKeyFilePath().DirName());
201     ASSERT_TRUE(
202         base::WriteFile(DeviceKeyFilePath(), proto.SerializeAsString()));
203     Wait();
204   }
205 
ReadKeys(const base::FilePath & filepath)206   KeyDataProto ReadKeys(const base::FilePath& filepath) {
207     base::ScopedBlockingCall scoped_blocking_call(
208         FROM_HERE, base::BlockingType::MAY_BLOCK);
209     Wait();
210     CHECK(base::PathExists(filepath));
211 
212     std::string proto_str;
213     CHECK(base::ReadFileToString(filepath, &proto_str));
214 
215     KeyDataProto proto;
216     CHECK(proto.ParseFromString(proto_str));
217     return proto;
218   }
219 
220   // Adds a project to the disallowed projects list.
AddDisallowedProject(uint64_t project_name_hash)221   void AddDisallowedProject(uint64_t project_name_hash) {
222     provider_->AddDisallowedProjectForTest(project_name_hash);
223   }
224 
225   // Simulates the three external events that the structure metrics system cares
226   // about: the metrics service initializing and enabling its providers, and a
227   // user logging in.
Init()228   void Init() {
229     // Create a system profile, normally done by ChromeMetricsServiceClient.
230     system_profile_provider_ = std::make_unique<TestSystemProfileProvider>();
231     // Create the provider, normally done by the ChromeMetricsServiceClient.
232     provider_ = std::unique_ptr<StructuredMetricsProvider>(
233         new StructuredMetricsProvider(
234             DeviceKeyFilePath(),
235             /*write_delay=*/base::Seconds(0),
236             /*min_independent_metrics_interval=*/base::Seconds(0),
237             system_profile_provider_.get()));
238     // Enable recording, normally done after the metrics service has checked
239     // consent allows recording.
240     provider_->OnRecordingEnabled();
241     // Add a profile, normally done by the ChromeMetricsServiceClient after a
242     // user logs in.
243     provider_->OnProfileAdded(TempDirPath());
244     Wait();
245   }
246 
247   // Enables recording without adding a profile.
InitWithoutLogin()248   void InitWithoutLogin() {
249     // Create a system profile, normally done by ChromeMetricsServiceClient.
250     system_profile_provider_ = std::make_unique<TestSystemProfileProvider>();
251     // Create the provider, normally done by the ChromeMetricsServiceClient.
252     provider_ = std::unique_ptr<StructuredMetricsProvider>(
253         new StructuredMetricsProvider(
254             DeviceKeyFilePath(),
255             /*write_delay=*/base::Seconds(0),
256             /*min_independent_metrics_interval=*/base::Seconds(0),
257             system_profile_provider_.get()));
258     // Enable recording, normally done after the metrics service has checked
259     // consent allows recording.
260     provider_->OnRecordingEnabled();
261   }
262 
is_initialized()263   bool is_initialized() {
264     return provider_->init_state_ ==
265            StructuredMetricsProvider::InitState::kInitialized;
266   }
267 
is_recording_enabled()268   bool is_recording_enabled() { return provider_->recording_enabled_; }
269 
OnRecordingEnabled()270   void OnRecordingEnabled() { provider_->OnRecordingEnabled(); }
271 
OnRecordingDisabled()272   void OnRecordingDisabled() { provider_->OnRecordingDisabled(); }
273 
OnReportingStateChanged(bool enabled)274   void OnReportingStateChanged(bool enabled) {
275     provider_->OnReportingStateChanged(enabled);
276   }
277 
OnProfileAdded(const base::FilePath & path)278   void OnProfileAdded(const base::FilePath& path) {
279     provider_->OnProfileAdded(path);
280   }
281 
WriteNow()282   void WriteNow() {
283     provider_->WriteNowForTest();
284     Wait();
285   }
286 
GetSessionData()287   StructuredDataProto GetSessionData() {
288     ChromeUserMetricsExtension uma_proto;
289     provider_->ProvideCurrentSessionData(&uma_proto);
290     Wait();
291     return uma_proto.structured_data();
292   }
293 
GetIndependentMetrics()294   StructuredDataProto GetIndependentMetrics() {
295     ChromeUserMetricsExtension uma_proto;
296     if (provider_->HasIndependentMetrics()) {
297       provider_->ProvideIndependentMetrics(
298           base::BindOnce([](bool success) { CHECK(success); }), &uma_proto,
299           nullptr);
300       Wait();
301       return uma_proto.structured_data();
302     }
303 
304     auto p = StructuredDataProto();
305     return p;
306   }
307 
GetUmaProto()308   ChromeUserMetricsExtension GetUmaProto() {
309     ChromeUserMetricsExtension uma_proto;
310     if (provider_->HasIndependentMetrics()) {
311       provider_->ProvideIndependentMetrics(
312           base::BindOnce([](bool success) { CHECK(success); }), &uma_proto,
313           nullptr);
314       Wait();
315       return uma_proto;
316     }
317 
318     auto p = ChromeUserMetricsExtension();
319     return p;
320   }
321 
ExpectNoErrors()322   void ExpectNoErrors() {
323     histogram_tester_.ExpectTotalCount("UMA.StructuredMetrics.InternalError",
324                                        0);
325   }
326 
SetExternalMetricsDirForTest(const base::FilePath dir)327   void SetExternalMetricsDirForTest(const base::FilePath dir) {
328     provider_->SetExternalMetricsDirForTest(dir);
329   }
330 
InitializeSystemProfile()331   void InitializeSystemProfile() { provider_->OnSystemProfileInitialized(); }
332 
333  protected:
334   std::unique_ptr<MetricsProvider> system_profile_provider_;
335   std::unique_ptr<StructuredMetricsProvider> provider_;
336   // Feature list should be constructed before task environment.
337   base::test::ScopedFeatureList scoped_feature_list_;
338   base::test::TaskEnvironment task_environment_{
339       base::test::TaskEnvironment::MainThreadType::UI,
340       base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED,
341       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
342   base::HistogramTester histogram_tester_;
343   base::ScopedTempDir temp_dir_;
344 
345  private:
346   TestRecorder recorder_;
347 };
348 
349 // Simple test to ensure initialization works correctly in the case of a
350 // first-time run.
TEST_F(StructuredMetricsProviderTest,ProviderInitializesFromBlankSlate)351 TEST_F(StructuredMetricsProviderTest, ProviderInitializesFromBlankSlate) {
352   Init();
353   EXPECT_TRUE(is_initialized());
354   EXPECT_TRUE(is_recording_enabled());
355   ExpectNoErrors();
356 }
357 
358 // Ensure a call to OnRecordingDisabled prevents reporting.
TEST_F(StructuredMetricsProviderTest,EventsNotReportedWhenRecordingDisabled)359 TEST_F(StructuredMetricsProviderTest, EventsNotReportedWhenRecordingDisabled) {
360   Init();
361   OnRecordingDisabled();
362   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
363   events::v2::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
364   EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
365   EXPECT_EQ(GetSessionData().events_size(), 0);
366   ExpectNoErrors();
367 }
368 
369 // Ensure that disabling the structured metrics feature flag prevents all
370 // structured metrics reporting.
TEST_F(StructuredMetricsProviderTest,EventsNotReportedWhenFeatureDisabled)371 TEST_F(StructuredMetricsProviderTest, EventsNotReportedWhenFeatureDisabled) {
372   scoped_feature_list_.InitAndDisableFeature(kStructuredMetrics);
373 
374   Init();
375   // OnRecordingEnabled should not actually enable recording because the flag is
376   // disabled.
377   OnRecordingEnabled();
378   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
379   events::v2::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
380   EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
381   EXPECT_EQ(GetSessionData().events_size(), 0);
382   ExpectNoErrors();
383 }
384 
385 // Ensure that keys and unsent logs are deleted when reporting is disabled, and
386 // that reporting resumes when re-enabled.
TEST_F(StructuredMetricsProviderTest,ReportingStateChangesHandledCorrectly)387 TEST_F(StructuredMetricsProviderTest, ReportingStateChangesHandledCorrectly) {
388   Init();
389 
390   // Record an event and read the keys, there should be one.
391   events::v2::test_project_one::TestEventOne().Record();
392   EXPECT_EQ(GetIndependentMetrics().events_size(), 1);
393 
394   const KeyDataProto enabled_proto = ReadKeys(ProfileKeyFilePath());
395   EXPECT_EQ(enabled_proto.keys_size(), 1);
396 
397   // Record an event, disable reporting, then record another event. Both of
398   // these events should have been ignored.
399   events::v2::test_project_one::TestEventOne().Record();
400   OnReportingStateChanged(false);
401   events::v2::test_project_one::TestEventOne().Record();
402   EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
403 
404   // Read the keys again, it should be empty.
405   const KeyDataProto disabled_proto = ReadKeys(ProfileKeyFilePath());
406   EXPECT_EQ(disabled_proto.keys_size(), 0);
407 
408   // Enable reporting again, and record an event.
409   OnReportingStateChanged(true);
410   OnRecordingEnabled();
411   events::v2::test_project_one::TestEventOne().Record();
412   EXPECT_EQ(GetIndependentMetrics().events_size(), 1);
413   const KeyDataProto reenabled_proto = ReadKeys(ProfileKeyFilePath());
414   EXPECT_EQ(reenabled_proto.keys_size(), 1);
415 
416   ExpectNoErrors();
417 }
418 
419 // Ensure that disabling independent upload of non-client_id metrics via feature
420 // flag instead uploads them in the main UMA upload.
TEST_F(StructuredMetricsProviderTest,DisableIndependentUploads)421 TEST_F(StructuredMetricsProviderTest, DisableIndependentUploads) {
422   scoped_feature_list_.InitAndEnableFeatureWithParameters(
423       kStructuredMetrics, {{"enable_independent_metrics_upload", "false"}});
424 
425   Init();
426   OnRecordingEnabled();
427   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
428   events::v2::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
429   EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
430   EXPECT_EQ(GetSessionData().events_size(), 2);
431   ExpectNoErrors();
432 }
433 
434 // Ensure that, if recording is disabled part-way through initialization, the
435 // initialization still completes correctly, but recording is correctly set to
436 // disabled.
TEST_F(StructuredMetricsProviderTest,RecordingDisabledDuringInitialization)437 TEST_F(StructuredMetricsProviderTest, RecordingDisabledDuringInitialization) {
438   system_profile_provider_ = std::make_unique<TestSystemProfileProvider>();
439   provider_ = std::make_unique<StructuredMetricsProvider>(
440       system_profile_provider_.get());
441 
442   OnProfileAdded(TempDirPath());
443   OnRecordingDisabled();
444   EXPECT_FALSE(is_initialized());
445   EXPECT_FALSE(is_recording_enabled());
446 
447   Wait();
448   EXPECT_TRUE(is_initialized());
449   EXPECT_FALSE(is_recording_enabled());
450 
451   ExpectNoErrors();
452 }
453 
454 // Ensure that recording is disabled until explicitly enabled with a call to
455 // OnRecordingEnabled.
TEST_F(StructuredMetricsProviderTest,RecordingDisabledByDefault)456 TEST_F(StructuredMetricsProviderTest, RecordingDisabledByDefault) {
457   system_profile_provider_ = std::make_unique<TestSystemProfileProvider>();
458   provider_ = std::make_unique<StructuredMetricsProvider>(
459       system_profile_provider_.get());
460 
461   OnProfileAdded(TempDirPath());
462   Wait();
463   EXPECT_TRUE(is_initialized());
464   EXPECT_FALSE(is_recording_enabled());
465 
466   OnRecordingEnabled();
467   EXPECT_TRUE(is_recording_enabled());
468 
469   ExpectNoErrors();
470 }
471 
TEST_F(StructuredMetricsProviderTest,RecordedEventAppearsInReport)472 TEST_F(StructuredMetricsProviderTest, RecordedEventAppearsInReport) {
473   Init();
474 
475   events::v2::test_project_one::TestEventOne()
476       .SetTestMetricOne("a string")
477       .SetTestMetricTwo(12345)
478       .Record();
479   events::v2::test_project_one::TestEventOne()
480       .SetTestMetricOne("a string")
481       .SetTestMetricTwo(12345)
482       .Record();
483   events::v2::test_project_one::TestEventOne()
484       .SetTestMetricOne("a string")
485       .SetTestMetricTwo(12345)
486       .Record();
487 
488   EXPECT_EQ(GetIndependentMetrics().events_size(), 3);
489   // TestProjectOne is not UMA ID'd, so GetSessionData should be empty.
490   EXPECT_EQ(GetSessionData().events_size(), 0);
491   ExpectNoErrors();
492 }
493 
TEST_F(StructuredMetricsProviderTest,UmaEventsReportedCorrectly)494 TEST_F(StructuredMetricsProviderTest, UmaEventsReportedCorrectly) {
495   WriteTestingProfileKeys();
496   Init();
497 
498   events::v2::test_project_three::TestEventFour()
499       .SetTestMetricFour(12345)
500       .Record();
501   events::v2::test_project_three::TestEventFour()
502       .SetTestMetricFour(67890)
503       .Record();
504 
505   const auto data = GetSessionData();
506   ASSERT_EQ(data.events_size(), 2);
507 
508   {  // First event
509     const auto& event = data.events(0);
510     EXPECT_EQ(event.event_name_hash(), kEventFourHash);
511     EXPECT_EQ(event.project_name_hash(), kProjectThreeHash);
512     // TODO(crbug.com/1148168): The UMA ID currently isn't attached to UMA
513     // events, so just check it isn't set.
514     EXPECT_FALSE(event.has_profile_event_id());
515     ASSERT_EQ(event.metrics_size(), 1);
516     const auto& metric = event.metrics(0);
517     EXPECT_EQ(metric.name_hash(), kMetricFourHash);
518     EXPECT_EQ(metric.value_int64(), 12345);
519   }
520 
521   {  // Second event
522     const auto& event = data.events(1);
523     EXPECT_EQ(event.event_name_hash(), kEventFourHash);
524     EXPECT_EQ(event.project_name_hash(), kProjectThreeHash);
525     // TODO(crbug.com/1148168): The UMA ID currently isn't attached to UMA
526     // events, so just check it isn't set.
527     EXPECT_FALSE(event.has_profile_event_id());
528     ASSERT_EQ(event.metrics_size(), 1);
529     const auto& metric = event.metrics(0);
530     EXPECT_EQ(metric.name_hash(), kMetricFourHash);
531     EXPECT_EQ(metric.value_int64(), 67890);
532   }
533 
534   histogram_tester_.ExpectTotalCount("UMA.StructuredMetrics.InternalError", 0);
535 }
536 
TEST_F(StructuredMetricsProviderTest,IndependentEventsReportedCorrectly)537 TEST_F(StructuredMetricsProviderTest, IndependentEventsReportedCorrectly) {
538   WriteTestingProfileKeys();
539   Init();
540 
541   events::v2::test_project_one::TestEventOne()
542       .SetTestMetricOne(kValueOne)
543       .SetTestMetricTwo(12345)
544       .Record();
545   events::v2::test_project_two::TestEventTwo()
546       .SetTestMetricThree(kValueTwo)
547       .Record();
548 
549   const auto data = GetIndependentMetrics();
550   ASSERT_EQ(data.events_size(), 2);
551 
552   {  // First event
553     const auto& event = data.events(0);
554     EXPECT_EQ(event.event_name_hash(), kEventOneHash);
555     EXPECT_EQ(event.project_name_hash(), kProjectOneHash);
556     EXPECT_EQ(HashToHex(event.profile_event_id()), kProjectOneId);
557     ASSERT_EQ(event.metrics_size(), 2);
558 
559     {  // First metric
560       const auto& metric = event.metrics(0);
561       EXPECT_EQ(metric.name_hash(), kMetricOneHash);
562       EXPECT_EQ(HashToHex(metric.value_hmac()),
563                 // Value of HMAC_256("aaa...a", concat(hex(kMetricOneHash),
564                 // kValueOne))
565                 "8C2469269D142715");
566     }
567 
568     {  // Second metric
569       const auto& metric = event.metrics(1);
570       EXPECT_EQ(metric.name_hash(), kMetricTwoHash);
571       EXPECT_EQ(metric.value_int64(), 12345);
572     }
573   }
574 
575   {  // Second event
576     const auto& event = data.events(1);
577     EXPECT_EQ(event.event_name_hash(), kEventTwoHash);
578     EXPECT_EQ(event.project_name_hash(), kProjectTwoHash);
579     EXPECT_EQ(HashToHex(event.profile_event_id()), kProjectTwoId);
580     ASSERT_EQ(event.metrics_size(), 1);
581 
582     {  // First metric
583       const auto& metric = event.metrics(0);
584       EXPECT_EQ(metric.name_hash(), kMetricThreeHash);
585       EXPECT_EQ(HashToHex(metric.value_hmac()),
586                 // Value of HMAC_256("bbb...b", concat(hex(kProjectTwoHash),
587                 // kValueTwo))
588                 "86F0169868588DC7");
589     }
590   }
591 
592   histogram_tester_.ExpectTotalCount("UMA.StructuredMetrics.InternalError", 0);
593 }
594 
TEST_F(StructuredMetricsProviderTest,IndependentMetricsProvideSystemProfile)595 TEST_F(StructuredMetricsProviderTest, IndependentMetricsProvideSystemProfile) {
596   WriteTestingProfileKeys();
597   Init();
598   InitializeSystemProfile();
599 
600   events::v2::test_project_one::TestEventOne()
601       .SetTestMetricOne(kValueOne)
602       .SetTestMetricTwo(12345)
603       .Record();
604   events::v2::test_project_two::TestEventTwo()
605       .SetTestMetricThree(kValueTwo)
606       .Record();
607 
608   const auto uma_proto = GetUmaProto();
609   CHECK(uma_proto.has_system_profile());
610 
611   {
612     const auto structured_profile = uma_proto.system_profile();
613     EXPECT_EQ(structured_profile.multi_profile_user_count(), kUserCount);
614     EXPECT_EQ(structured_profile.hardware().full_hardware_class(), kHwid);
615   }
616 
617   const auto data = uma_proto.structured_data();
618   ASSERT_EQ(data.events_size(), 2);
619 
620   {  // First event
621     const auto& event = data.events(0);
622     EXPECT_EQ(event.event_name_hash(), kEventOneHash);
623     EXPECT_EQ(HashToHex(event.profile_event_id()), kProjectOneId);
624     ASSERT_EQ(event.metrics_size(), 2);
625     {}
626 
627     {  // First metric
628       const auto& metric = event.metrics(0);
629       EXPECT_EQ(metric.name_hash(), kMetricOneHash);
630       EXPECT_EQ(HashToHex(metric.value_hmac()),
631                 // Value of HMAC_256("aaa...a", concat(hex(kMetricOneHash),
632                 // kValueOne))
633                 "8C2469269D142715");
634     }
635 
636     {  // Second metric
637       const auto& metric = event.metrics(1);
638       EXPECT_EQ(metric.name_hash(), kMetricTwoHash);
639       EXPECT_EQ(metric.value_int64(), 12345);
640     }
641   }
642 
643   {  // Second event
644     const auto& event = data.events(1);
645     EXPECT_EQ(event.event_name_hash(), kEventTwoHash);
646     EXPECT_EQ(HashToHex(event.profile_event_id()), kProjectTwoId);
647     ASSERT_EQ(event.metrics_size(), 1);
648 
649     {  // First metric
650       const auto& metric = event.metrics(0);
651       EXPECT_EQ(metric.name_hash(), kMetricThreeHash);
652       EXPECT_EQ(HashToHex(metric.value_hmac()),
653                 // Value of HMAC_256("bbb...b", concat(hex(kProjectTwoHash),
654                 // kValueTwo))
655                 "86F0169868588DC7");
656     }
657   }
658 
659   histogram_tester_.ExpectTotalCount("UMA.StructuredMetrics.InternalError", 0);
660 }
661 
662 // Ensure that events containing raw string metrics are reported correctly.
TEST_F(StructuredMetricsProviderTest,RawStringMetricsReportedCorrectly)663 TEST_F(StructuredMetricsProviderTest, RawStringMetricsReportedCorrectly) {
664   Init();
665 
666   const std::string test_string = "a raw string value";
667   events::v2::test_project_five::TestEventSix()
668       .SetTestMetricSix(test_string)
669       .Record();
670 
671   const auto data = GetIndependentMetrics();
672   ASSERT_EQ(data.events_size(), 1);
673 
674   const auto& event = data.events(0);
675   EXPECT_EQ(event.event_name_hash(), kEventSixHash);
676   EXPECT_EQ(event.project_name_hash(), kProjectFiveHash);
677   EXPECT_FALSE(event.has_profile_event_id());
678   EXPECT_EQ(event.event_type(), StructuredEventProto_EventType_RAW_STRING);
679 
680   ASSERT_EQ(event.metrics_size(), 1);
681   const auto& metric = event.metrics(0);
682 
683   EXPECT_EQ(metric.name_hash(), kMetricSixHash);
684   EXPECT_EQ(metric.value_string(), test_string);
685 }
686 
TEST_F(StructuredMetricsProviderTest,FloatMetricsReportedCorrectly)687 TEST_F(StructuredMetricsProviderTest, FloatMetricsReportedCorrectly) {
688   Init();
689 
690   const float test_float = 3.4;
691   const float test_float2 = 3.14e-8;
692 
693   events::v2::test_project_six::TestEventSeven()
694       .SetTestMetricSeven(test_float)
695       .Record();
696 
697   events::v2::test_project_six::TestEventSeven()
698       .SetTestMetricSeven(test_float2)
699       .Record();
700 
701   const auto data = GetIndependentMetrics();
702   ASSERT_EQ(data.events_size(), 2);
703 
704   const auto& event = data.events(0);
705   EXPECT_EQ(event.event_name_hash(), kEventSevenHash);
706   EXPECT_EQ(event.project_name_hash(), kProjectSixHash);
707   EXPECT_FALSE(event.has_profile_event_id());
708 
709   ASSERT_EQ(event.metrics_size(), 1);
710   const auto& metric = event.metrics(0);
711 
712   EXPECT_EQ(metric.name_hash(), kMetricSevenHash);
713   EXPECT_EQ(metric.value_double(), test_float);
714 
715   const auto& event2 = data.events(1);
716   EXPECT_EQ(event2.event_name_hash(), kEventSevenHash);
717   EXPECT_EQ(event2.project_name_hash(), kProjectSixHash);
718   EXPECT_FALSE(event2.has_profile_event_id());
719 
720   ASSERT_EQ(event2.metrics_size(), 1);
721   const auto& metric2 = event2.metrics(0);
722 
723   EXPECT_EQ(metric2.name_hash(), kMetricSevenHash);
724   EXPECT_EQ(metric2.value_double(), test_float2);
725 }
726 
TEST_F(StructuredMetricsProviderTest,DeviceKeysUsedForDeviceScopedProjects)727 TEST_F(StructuredMetricsProviderTest, DeviceKeysUsedForDeviceScopedProjects) {
728   WriteTestingProfileKeys();
729   WriteTestingDeviceKeys();
730   Init();
731 
732   // This event's project has device scope set, so should use the per-device
733   // keys set by WriteTestingDeviceKeys. In this case the expected key is
734   // "ddd...d", which we observe by checking the ID and HMAC have the correct
735   // value given that key.
736   events::v2::test_project_four::TestEventFive()
737       .SetTestMetricFive("value")
738       .Record();
739 
740   const auto data = GetIndependentMetrics();
741   ASSERT_EQ(data.events_size(), 1);
742 
743   const auto& event = data.events(0);
744   EXPECT_EQ(event.event_name_hash(), kEventFiveHash);
745   EXPECT_EQ(event.project_name_hash(), kProjectFourHash);
746   // The hex-encoded first 8 bytes of SHA256("ddd...d").
747   EXPECT_EQ(HashToHex(event.profile_event_id()), kProjectFourId);
748   ASSERT_EQ(event.metrics_size(), 1);
749 
750   const auto& metric = event.metrics(0);
751   EXPECT_EQ(metric.name_hash(), kMetricFiveHash);
752   EXPECT_EQ(HashToHex(metric.value_hmac()),
753             // Value of HMAC_256("ddd...d", concat(hex(kMetricFiveHash),
754             // "value"))
755             "4CC202FAA78FDC7A");
756 
757   histogram_tester_.ExpectTotalCount("UMA.StructuredMetrics.InternalError", 0);
758 }
759 
760 // Check that a full int64 can be recorded, and is not truncated to an int32.
TEST_F(StructuredMetricsProviderTest,Int64MetricsNotTruncated)761 TEST_F(StructuredMetricsProviderTest, Int64MetricsNotTruncated) {
762   Init();
763   const int64_t big = 1ll << 60;
764   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(big).Record();
765 
766   const auto data = GetIndependentMetrics();
767   ASSERT_EQ(data.events_size(), 1);
768   const auto& event = data.events(0);
769   ASSERT_EQ(event.metrics_size(), 1);
770   const auto& metric = event.metrics(0);
771   EXPECT_EQ(metric.value_int64(), big);
772 }
773 
TEST_F(StructuredMetricsProviderTest,EventsWithinProjectReportedWithSameID)774 TEST_F(StructuredMetricsProviderTest, EventsWithinProjectReportedWithSameID) {
775   WriteTestingProfileKeys();
776   Init();
777 
778   events::v2::test_project_one::TestEventOne().Record();
779   events::v2::test_project_two::TestEventTwo().Record();
780   events::v2::test_project_two::TestEventThree().Record();
781 
782   const auto data = GetIndependentMetrics();
783   // TestProjectOne is not UMA ID'd, so GetSessionData should be empty.
784   EXPECT_EQ(GetSessionData().events_size(), 0);
785   ASSERT_EQ(data.events_size(), 3);
786 
787   const auto& event_one = data.events(0);
788   const auto& event_two = data.events(1);
789   const auto& event_three = data.events(2);
790 
791   // Check events are in the right order.
792   EXPECT_EQ(event_one.event_name_hash(), kEventOneHash);
793   EXPECT_EQ(event_two.event_name_hash(), kEventTwoHash);
794   EXPECT_EQ(event_three.event_name_hash(), kEventThreeHash);
795 
796   // Events two and three share a project, so should have the same project
797   // name hash. Event one should have its own project name hash.
798   EXPECT_EQ(event_one.project_name_hash(), kProjectOneHash);
799   EXPECT_EQ(event_two.project_name_hash(), kProjectTwoHash);
800   EXPECT_EQ(event_three.project_name_hash(), kProjectTwoHash);
801 
802   // Events two and three share a project, so should have the same ID. Event
803   // one should have its own ID.
804   EXPECT_EQ(HashToHex(event_one.profile_event_id()), kProjectOneId);
805   EXPECT_EQ(HashToHex(event_two.profile_event_id()), kProjectTwoId);
806   EXPECT_EQ(HashToHex(event_three.profile_event_id()), kProjectTwoId);
807 
808   histogram_tester_.ExpectTotalCount("UMA.StructuredMetrics.InternalError", 0);
809 }
810 
TEST_F(StructuredMetricsProviderTest,EventWithoutMetricsReportCorrectly)811 TEST_F(StructuredMetricsProviderTest, EventWithoutMetricsReportCorrectly) {
812   Init();
813 
814   const int test_time = 50;
815 
816   events::v2::cr_os_events::NoMetricsEvent test_event;
817   EXPECT_TRUE(test_event.IsEventSequenceType());
818   test_event.SetEventSequenceMetadata(Event::EventSequenceMetadata(1));
819   test_event.SetRecordedTimeSinceBoot(base::Milliseconds(test_time));
820   test_event.Record();
821 
822   const auto data = GetIndependentMetrics();
823 
824   EXPECT_EQ(data.events_size(), 1);
825 
826   const auto& event = data.events(0);
827 
828   EXPECT_EQ(event.project_name_hash(), kCrOSEventsProjectHash);
829   EXPECT_EQ(event.event_name_hash(), kNoMetricsEventHash);
830 }
831 
832 // Test that a call to ProvideCurrentSessionData clears the provided events from
833 // the cache, and a subsequent call does not return those events again.
TEST_F(StructuredMetricsProviderTest,EventsClearedAfterReport)834 TEST_F(StructuredMetricsProviderTest, EventsClearedAfterReport) {
835   Init();
836 
837   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
838   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(2).Record();
839   // TestProjectOne is not UMA ID'd, so GetSessionData should be empty.
840   EXPECT_EQ(GetSessionData().events_size(), 0);
841   // Should provide both the previous events.
842   EXPECT_EQ(GetIndependentMetrics().events_size(), 2);
843 
844   // But the previous events shouldn't appear in the second report.
845   EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
846 
847   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(3).Record();
848   // The third request should only contain the third event.
849   EXPECT_EQ(GetIndependentMetrics().events_size(), 1);
850 
851   ExpectNoErrors();
852 }
853 
854 // Test that events recorded in one session are correctly persisted and are
855 // uploaded in the first report from a subsequent session.
TEST_F(StructuredMetricsProviderTest,EventsFromPreviousSessionAreReported)856 TEST_F(StructuredMetricsProviderTest, EventsFromPreviousSessionAreReported) {
857   // Start first session and record one event.
858   Init();
859   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1234).Record();
860 
861   // Write events to disk, then destroy the provider.
862   WriteNow();
863   provider_.reset();
864 
865   // Start a second session and ensure the event is reported.
866   Init();
867   const auto data = GetIndependentMetrics();
868   ASSERT_EQ(data.events_size(), 1);
869   ASSERT_EQ(data.events(0).metrics_size(), 1);
870   EXPECT_EQ(data.events(0).metrics(0).value_int64(), 1234);
871   EXPECT_EQ(GetSessionData().events_size(), 0);
872 
873   ExpectNoErrors();
874 }
875 
TEST_F(StructuredMetricsProviderTest,ExternalMetricsAreReported)876 TEST_F(StructuredMetricsProviderTest, ExternalMetricsAreReported) {
877   const base::FilePath events_dir(TempDirPath().Append("events"));
878   base::CreateDirectory(events_dir);
879 
880   const auto proto = MakeExternalEventProto({111, 222, 333});
881   ASSERT_TRUE(
882       base::WriteFile(events_dir.Append("event"), proto.SerializeAsString()));
883 
884   system_profile_provider_ = std::make_unique<TestSystemProfileProvider>();
885   provider_ = std::make_unique<StructuredMetricsProvider>(
886       system_profile_provider_.get());
887   OnProfileAdded(TempDirPath());
888   OnRecordingEnabled();
889   SetExternalMetricsDirForTest(events_dir);
890   task_environment_.AdvanceClock(base::Hours(10));
891   Wait();
892   EXPECT_EQ(GetSessionData().events_size(), 3);
893 }
894 
TEST_F(StructuredMetricsProviderTest,ExternalMetricsDroppedWhenRecordingDisabled)895 TEST_F(StructuredMetricsProviderTest,
896        ExternalMetricsDroppedWhenRecordingDisabled) {
897   const base::FilePath events_dir(TempDirPath().Append("events"));
898   base::CreateDirectory(events_dir);
899 
900   const auto proto = MakeExternalEventProto({111, 222, 333});
901   ASSERT_TRUE(
902       base::WriteFile(events_dir.Append("event"), proto.SerializeAsString()));
903 
904   system_profile_provider_ = std::make_unique<TestSystemProfileProvider>();
905   provider_ = std::make_unique<StructuredMetricsProvider>(
906       system_profile_provider_.get());
907   OnProfileAdded(TempDirPath());
908   OnRecordingDisabled();
909   SetExternalMetricsDirForTest(events_dir);
910   task_environment_.AdvanceClock(base::Hours(10));
911   Wait();
912   EXPECT_EQ(GetSessionData().events_size(), 0);
913 }
914 
915 // Test that events reported before recording is enabled are ignored.
TEST_F(StructuredMetricsProviderTest,EventsNotRecordedBeforeRecordingEnabled)916 TEST_F(StructuredMetricsProviderTest, EventsNotRecordedBeforeRecordingEnabled) {
917   // Manually create and initialize the provider, adding recording calls between
918   // each step. All of these events should be ignored.
919   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
920   system_profile_provider_ = std::make_unique<TestSystemProfileProvider>();
921   provider_ = std::make_unique<StructuredMetricsProvider>(
922       system_profile_provider_.get());
923   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
924   OnRecordingEnabled();
925   Wait();
926 
927   EXPECT_EQ(GetSessionData().events_size(), 0);
928   EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
929 
930   ExpectNoErrors();
931 }
932 
933 // Test that events reported after recording is enabled but before the keys are
934 // loaded are hashed and stored after keys are loaded.
TEST_F(StructuredMetricsProviderTest,EventsRecordedBeforeKeysInitialized)935 TEST_F(StructuredMetricsProviderTest, EventsRecordedBeforeKeysInitialized) {
936   InitWithoutLogin();
937   // Emulate metric before login.
938   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
939 
940   OnProfileAdded(TempDirPath());
941   // Called before user key is loaded.
942   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
943   Wait();
944 
945   EXPECT_EQ(GetSessionData().events_size(), 0);
946   EXPECT_EQ(GetIndependentMetrics().events_size(), 2);
947 
948   ExpectNoErrors();
949 }
950 
951 // Ensure a call to OnRecordingDisabled not only prevents the reporting of new
952 // events, but also clears the cache of any existing events that haven't yet
953 // been reported.
TEST_F(StructuredMetricsProviderTest,ExistingEventsClearedWhenRecordingDisabled)954 TEST_F(StructuredMetricsProviderTest,
955        ExistingEventsClearedWhenRecordingDisabled) {
956   Init();
957   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
958   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
959   events::v2::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
960   OnRecordingDisabled();
961   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
962   events::v2::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
963   EXPECT_EQ(GetSessionData().events_size(), 0);
964   EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
965 
966   ExpectNoErrors();
967 }
968 
969 // Ensure that recording and reporting is re-enabled after recording is disabled
970 // and then enabled again.
TEST_F(StructuredMetricsProviderTest,ReportingResumesWhenEnabled)971 TEST_F(StructuredMetricsProviderTest, ReportingResumesWhenEnabled) {
972   Init();
973   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
974   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
975   events::v2::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
976 
977   OnRecordingDisabled();
978   OnRecordingEnabled();
979 
980   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
981   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
982   events::v2::test_project_three::TestEventFour().SetTestMetricFour(1).Record();
983 
984   EXPECT_EQ(GetSessionData().events_size(), 2);
985   EXPECT_EQ(GetIndependentMetrics().events_size(), 4);
986 
987   ExpectNoErrors();
988 }
989 
990 // Ensure that a call to ProvideCurrentSessionData before initialization
991 // completes returns no events.
TEST_F(StructuredMetricsProviderTest,ReportsNothingBeforeInitializationComplete)992 TEST_F(StructuredMetricsProviderTest,
993        ReportsNothingBeforeInitializationComplete) {
994   system_profile_provider_ = std::make_unique<TestSystemProfileProvider>();
995   provider_ = std::make_unique<StructuredMetricsProvider>(
996       system_profile_provider_.get());
997   EXPECT_EQ(GetSessionData().events_size(), 0);
998   EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
999   OnRecordingEnabled();
1000   EXPECT_EQ(GetSessionData().events_size(), 0);
1001   EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
1002   OnProfileAdded(TempDirPath());
1003   EXPECT_EQ(GetSessionData().events_size(), 0);
1004   EXPECT_EQ(GetIndependentMetrics().events_size(), 0);
1005 }
1006 
1007 // Check that LastKeyRotation returns a value in the correct range of possible
1008 // last rotations for a newly generated key.
TEST_F(StructuredMetricsProviderTest,LastKeyRotation)1009 TEST_F(StructuredMetricsProviderTest, LastKeyRotation) {
1010   Init();
1011 
1012   events::v2::test_project_one::TestEventOne event;
1013 
1014   // Record a metric so that the key is created.
1015   event.Record();
1016 
1017   const int today = (base::Time::Now() - base::Time::UnixEpoch()).InDays();
1018   const absl::optional<int> last_rotation =
1019       Recorder::GetInstance()->LastKeyRotation(event);
1020 
1021   // The last rotation should be a random day between today and 90 days in the
1022   // past, ie. the rotation period for this project.
1023   ASSERT_TRUE(last_rotation.has_value());
1024   EXPECT_GE(last_rotation, today - 90);
1025 }
1026 
1027 // Ensures that events part of event sequence are recorded properly.
TEST_F(StructuredMetricsProviderTest,EventSequenceLogging)1028 TEST_F(StructuredMetricsProviderTest, EventSequenceLogging) {
1029   Init();
1030 
1031   scoped_feature_list_.InitAndEnableFeature(
1032       metrics::structured::kEventSequenceLogging);
1033 
1034   const int test_time = 50;
1035   const double test_metric = 1.0;
1036 
1037   events::v2::cr_os_events::Test1 test_event;
1038   EXPECT_TRUE(test_event.IsEventSequenceType());
1039   test_event.SetEventSequenceMetadata(Event::EventSequenceMetadata(1));
1040   test_event.SetRecordedTimeSinceBoot(base::Milliseconds(test_time));
1041   test_event.SetMetric1(test_metric).Record();
1042 
1043   const auto data = GetIndependentMetrics();
1044   ASSERT_EQ(data.events_size(), 1);
1045 
1046   const auto& event = data.events(0);
1047   EXPECT_EQ(event.project_name_hash(), kCrOSEventsProjectHash);
1048 
1049   // Sequence events should have both a device and user project id.
1050   EXPECT_TRUE(event.has_device_project_id());
1051   EXPECT_TRUE(event.has_user_project_id());
1052 
1053   // Verify that event sequence metadata has been serialized correctly.
1054   const auto& event_metadata = event.event_sequence_metadata();
1055   EXPECT_EQ(event_metadata.reset_counter(), 1);
1056   EXPECT_TRUE(event_metadata.has_event_unique_id());
1057   EXPECT_EQ(event_metadata.system_uptime(), test_time);
1058 
1059   ASSERT_EQ(event.metrics_size(), 1);
1060   const auto& metric = event.metrics(0);
1061   EXPECT_EQ(metric.value_double(), 1.0);
1062 
1063   ExpectNoErrors();
1064 }
1065 
TEST_F(StructuredMetricsProviderTest,EventsClone)1066 TEST_F(StructuredMetricsProviderTest, EventsClone) {
1067   Init();
1068 
1069   events::v2::cr_os_events::Test1 event;
1070 
1071   const int test_time = 50;
1072   const double test_metric = 1.0;
1073 
1074   event.SetEventSequenceMetadata(Event::EventSequenceMetadata(1));
1075   event.SetRecordedTimeSinceBoot(base::Milliseconds(test_time));
1076   event.SetMetric1(test_metric);
1077 
1078   auto cloned_event = event.Clone();
1079 
1080   EXPECT_EQ(event.event_sequence_metadata().reset_counter,
1081             cloned_event.event_sequence_metadata().reset_counter);
1082   EXPECT_EQ(event.project_name(), cloned_event.project_name());
1083   EXPECT_EQ(event.event_name(), cloned_event.event_name());
1084   EXPECT_EQ(event.is_event_sequence(), cloned_event.is_event_sequence());
1085   EXPECT_EQ(event.recorded_time_since_boot(),
1086             cloned_event.recorded_time_since_boot());
1087   EXPECT_EQ(event.metric_values(), cloned_event.metric_values());
1088 }
1089 
TEST_F(StructuredMetricsProviderTest,DisallowedProjectAreDropped)1090 TEST_F(StructuredMetricsProviderTest, DisallowedProjectAreDropped) {
1091   Init();
1092 
1093   AddDisallowedProject(kProjectOneHash);
1094 
1095   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
1096   events::v2::test_project_one::TestEventOne().SetTestMetricTwo(1).Record();
1097   events::v2::test_project_two::TestEventThree()
1098       .SetTestMetricFour("value")
1099       .Record();
1100 
1101   const auto data = GetIndependentMetrics();
1102   ASSERT_EQ(data.events_size(), 1);
1103   ASSERT_EQ(data.events(0).project_name_hash(), kProjectTwoHash);
1104 }
1105 
1106 }  // namespace metrics::structured
1107