[M120 Migration][MM][CAPI] Fix the logic for media using capi player.
[platform/framework/web/chromium-efl.git] / media / mojo / services / video_decode_perf_history_unittest.cc
1 // Copyright 2017 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 <map>
6 #include <memory>
7 #include <string>
8
9 #include "base/functional/bind.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/test/bind.h"
14 #include "base/test/scoped_feature_list.h"
15 #include "base/test/task_environment.h"
16 #include "components/ukm/test_ukm_recorder.h"
17 #include "media/base/key_systems.h"
18 #include "media/base/media_switches.h"
19 #include "media/capabilities/video_decode_stats_db.h"
20 #include "media/mojo/mojom/media_types.mojom.h"
21 #include "media/mojo/services/test_helpers.h"
22 #include "media/mojo/services/video_decode_perf_history.h"
23 #include "services/metrics/public/cpp/ukm_builders.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "url/gurl.h"
27 #include "url/origin.h"
28
29 using UkmEntry = ukm::builders::Media_VideoDecodePerfRecord;
30 using testing::IsNull;
31 using testing::_;
32
33 namespace {
34
35 // Aliases for readability.
36 const bool kIsSmooth = true;
37 const bool kIsNotSmooth = false;
38 const bool kIsPowerEfficient = true;
39 const bool kIsNotPowerEfficient = false;
40 const bool kIsTopFrame = true;
41 const uint64_t kPlayerId = 1234u;
42
43 }  // namespace
44
45 namespace media {
46
47 class FakeVideoDecodeStatsDB : public VideoDecodeStatsDB {
48  public:
49   FakeVideoDecodeStatsDB() = default;
50   ~FakeVideoDecodeStatsDB() override = default;
51
52   // Call CompleteInitialize(...) to run |init_cb| callback.
53   void Initialize(base::OnceCallback<void(bool)> init_cb) override {
54     EXPECT_FALSE(!!pendnding_init_cb_);
55     pendnding_init_cb_ = std::move(init_cb);
56   }
57
58   // Completes fake initialization, running |init_cb| with the supplied value
59   // for success.
60   void CompleteInitialize(bool success) {
61     DVLOG(2) << __func__ << " running with success = " << success;
62     EXPECT_TRUE(!!pendnding_init_cb_);
63     std::move(pendnding_init_cb_).Run(success);
64   }
65
66   // Simple hooks to fail the next calls to AppendDecodeStats() and
67   // GetDecodeStats(). Will be reset to false after the call.
68   void set_fail_next_append(bool fail_append) {
69     fail_next_append_ = fail_append;
70   }
71   void set_fail_next_get(bool fail_get) { fail_next_get_ = fail_get; }
72
73   void AppendDecodeStats(const VideoDescKey& key,
74                          const DecodeStatsEntry& new_entry,
75                          AppendDecodeStatsCB append_done_cb) override {
76     if (fail_next_append_) {
77       fail_next_append_ = false;
78       std::move(append_done_cb).Run(false);
79       return;
80     }
81
82     std::string key_str = key.Serialize();
83     if (entries_.find(key_str) == entries_.end()) {
84       entries_.emplace(std::make_pair(key_str, new_entry));
85     } else {
86       const DecodeStatsEntry& known_entry = entries_.at(key_str);
87       entries_.at(key_str) = DecodeStatsEntry(
88           known_entry.frames_decoded + new_entry.frames_decoded,
89           known_entry.frames_dropped + new_entry.frames_dropped,
90           known_entry.frames_power_efficient +
91               new_entry.frames_power_efficient);
92     }
93
94     std::move(append_done_cb).Run(true);
95   }
96
97   void GetDecodeStats(const VideoDescKey& key,
98                       GetDecodeStatsCB get_stats_cb) override {
99     if (fail_next_get_) {
100       fail_next_get_ = false;
101       std::move(get_stats_cb).Run(false, nullptr);
102       return;
103     }
104
105     auto entry_it = entries_.find(key.Serialize());
106     if (entry_it == entries_.end()) {
107       std::move(get_stats_cb).Run(true, nullptr);
108     } else {
109       std::move(get_stats_cb)
110           .Run(true, std::make_unique<DecodeStatsEntry>(entry_it->second));
111     }
112   }
113
114   void ClearStats(base::OnceClosure clear_done_cb) override {
115     entries_.clear();
116     std::move(clear_done_cb).Run();
117   }
118
119  private:
120   friend class VideoDecodePerfHistoryTest;
121
122   // Private method for immediate retrieval of stats for test helpers.
123   std::unique_ptr<DecodeStatsEntry> GetDecodeStatsSync(
124       const VideoDescKey& key) {
125     auto entry_it = entries_.find(key.Serialize());
126     if (entry_it == entries_.end()) {
127       return nullptr;
128     } else {
129       return std::make_unique<DecodeStatsEntry>(entry_it->second);
130     }
131   }
132
133   bool fail_next_append_ = false;
134   bool fail_next_get_ = false;
135
136   std::map<std::string, DecodeStatsEntry> entries_;
137
138   base::OnceCallback<void(bool)> pendnding_init_cb_;
139 };
140
141 class VideoDecodePerfHistoryTest : public testing::Test {
142  public:
143   // Indicates what type of UKM verification should be performed upon saving
144   // new stats to the perf history.
145   enum class UkmVerifcation {
146     kNoUkmsAdded,
147     kSaveTriggersUkm,
148   };
149
150   void SetUp() override {
151     test_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
152     perf_history_ = std::make_unique<VideoDecodePerfHistory>(
153         std::make_unique<FakeVideoDecodeStatsDB>());
154   }
155
156   void TearDown() override { perf_history_.reset(); }
157
158   FakeVideoDecodeStatsDB* GetFakeDB() {
159     return static_cast<FakeVideoDecodeStatsDB*>(perf_history_->db_.get());
160   }
161
162   void PreInitializeDB(bool initialize_success) {
163     // Invoke private method to start initialization. Usually invoked by first
164     // API call requiring DB access.
165     perf_history_->InitDatabase();
166     // Complete initialization by firing callback from our fake DB.
167     GetFakeDB()->CompleteInitialize(initialize_success);
168   }
169
170   double GetMaxSmoothDroppedFramesPercent(bool is_eme = false) {
171     return VideoDecodePerfHistory::GetMaxSmoothDroppedFramesPercent(is_eme);
172   }
173
174   static base::FieldTrialParams GetFieldTrialParams() {
175     return VideoDecodePerfHistory::GetFieldTrialParams();
176   }
177
178   // Tests may set this as the callback for VideoDecodePerfHistory::GetPerfInfo
179   // to check the results of the call.
180   MOCK_METHOD2(MockGetPerfInfoCB,
181                void(bool is_smooth, bool is_power_efficient));
182
183   // Tests should EXPECT_CALL this method prior to ClearHistory() to know that
184   // the operation has completed.
185   MOCK_METHOD0(MockOnClearedHistory, void());
186
187   MOCK_METHOD1(MockGetVideoDecodeStatsDBCB, void(VideoDecodeStatsDB* db));
188
189   // Internal check that the UKM verification is complete before the test exits.
190   MOCK_METHOD0(UkmVerifyDoneCb, void());
191
192   void SavePerfRecord(UkmVerifcation ukm_verification,
193                       const url::Origin& origin,
194                       bool is_top_frame,
195                       mojom::PredictionFeatures features,
196                       mojom::PredictionTargets targets,
197                       uint64_t player_id) {
198     // Manually associate URL with |source_id|. In production this happens
199     // externally at a higher layer.
200     const ukm::SourceId source_id = test_recorder_->GetNewSourceID();
201     test_recorder_->UpdateSourceURL(source_id, origin.GetURL());
202
203     // Use save callback to verify UKM reporting.
204     base::OnceClosure save_done_cb;
205     switch (ukm_verification) {
206       case UkmVerifcation::kSaveTriggersUkm: {
207         // Expect UKM report with given properties upon successful save. Use
208         // old stats values from DB to set expectations about what API would
209         // have claimed pre-save.
210         std::unique_ptr<DecodeStatsEntry> old_stats =
211             GetStatsForFeatures(features);
212         save_done_cb =
213             base::BindOnce(&VideoDecodePerfHistoryTest::VerifyLastUkmReport,
214                            base::Unretained(this), origin, is_top_frame,
215                            features, targets, player_id, std::move(old_stats));
216         break;
217       }
218       case UkmVerifcation::kNoUkmsAdded: {
219         // Expect no additional UKM entries upon failing to save. Capture the
220         // current entry count before save to verify no new entries are added.
221         size_t current_num_entries =
222             test_recorder_->GetEntriesByName(UkmEntry::kEntryName).size();
223         save_done_cb = base::BindOnce(
224             &VideoDecodePerfHistoryTest::VerifyNoUkmReportForFailedSave,
225             base::Unretained(this), current_num_entries);
226         break;
227       }
228     }
229
230     // Check that the UKM verification is complete before the test exits.
231     EXPECT_CALL(*this, UkmVerifyDoneCb());
232
233     perf_history_->GetSaveCallback().Run(
234         source_id, learning::FeatureValue(kOrigin.host()), is_top_frame,
235         features, targets, player_id, std::move(save_done_cb));
236   }
237
238  protected:
239   using VideoDescKey = VideoDecodeStatsDB::VideoDescKey;
240   using DecodeStatsEntry = VideoDecodeStatsDB::DecodeStatsEntry;
241
242   // Private helper to public test methods. This bypasses  VPH::GetPerfInfo()
243   // to synchronously grab stats from the fake DB. Tests should instead use
244   // the VPH::GetPerfInfo().
245   std::unique_ptr<DecodeStatsEntry> GetStatsForFeatures(
246       mojom::PredictionFeatures features) {
247     VideoDecodeStatsDB::VideoDescKey video_key =
248         VideoDecodeStatsDB::VideoDescKey::MakeBucketedKey(
249             features.profile, features.video_size, features.frames_per_sec,
250             features.key_system, features.use_hw_secure_codecs);
251     return GetFakeDB()->GetDecodeStatsSync(video_key);
252   }
253
254   // Lookup up the most recent recorded entry and verify its properties against
255   // method arguments.
256   void VerifyLastUkmReport(const url::Origin& origin,
257                            bool is_top_frame,
258                            mojom::PredictionFeatures features,
259                            mojom::PredictionTargets new_targets,
260                            uint64_t player_id,
261                            std::unique_ptr<DecodeStatsEntry> old_stats) {
262 #define EXPECT_UKM(name, value) \
263   test_recorder_->ExpectEntryMetric(entry, name, value)
264 #define EXPECT_NO_UKM(name) \
265   EXPECT_FALSE(test_recorder_->EntryHasMetric(entry, name))
266
267     const auto& entries =
268         test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
269     ASSERT_GE(entries.size(), 1U);
270     auto* entry = entries.back();
271
272     // Verify stream properties. Make a key to ensure we check bucketed values.
273     VideoDecodeStatsDB::VideoDescKey key =
274         VideoDecodeStatsDB::VideoDescKey::MakeBucketedKey(
275             features.profile, features.video_size, features.frames_per_sec,
276             features.key_system, features.use_hw_secure_codecs);
277     test_recorder_->ExpectEntrySourceHasUrl(entry, origin.GetURL());
278     EXPECT_UKM(UkmEntry::kVideo_InTopFrameName, is_top_frame);
279     EXPECT_UKM(UkmEntry::kVideo_PlayerIDName, player_id);
280     EXPECT_UKM(UkmEntry::kVideo_CodecProfileName, key.codec_profile);
281     EXPECT_UKM(UkmEntry::kVideo_FramesPerSecondName, key.frame_rate);
282     EXPECT_UKM(UkmEntry::kVideo_NaturalHeightName, key.size.height());
283     EXPECT_UKM(UkmEntry::kVideo_NaturalWidthName, key.size.width());
284     if (key.key_system.empty()) {
285       EXPECT_NO_UKM(UkmEntry::kVideo_EME_KeySystemName);
286       EXPECT_NO_UKM(UkmEntry::kVideo_EME_UseHwSecureCodecsName);
287     } else {
288       EXPECT_UKM(UkmEntry::kVideo_EME_KeySystemName,
289                  GetKeySystemIntForUKM(key.key_system));
290       EXPECT_UKM(UkmEntry::kVideo_EME_UseHwSecureCodecsName,
291                  key.use_hw_secure_codecs);
292     }
293
294     // Verify past stats.
295     bool past_is_smooth = false;
296     bool past_is_efficient = false;
297     perf_history_->AssessStats(key, old_stats.get(), &past_is_smooth,
298                                &past_is_efficient);
299     EXPECT_UKM(UkmEntry::kPerf_ApiWouldClaimIsSmoothName, past_is_smooth);
300     EXPECT_UKM(UkmEntry::kPerf_ApiWouldClaimIsPowerEfficientName,
301                past_is_efficient);
302     // Zero it out to make verification readable.
303     if (!old_stats)
304       old_stats = std::make_unique<DecodeStatsEntry>(0, 0, 0);
305     EXPECT_UKM(UkmEntry::kPerf_PastVideoFramesDecodedName,
306                old_stats->frames_decoded);
307     EXPECT_UKM(UkmEntry::kPerf_PastVideoFramesDroppedName,
308                old_stats->frames_dropped);
309     EXPECT_UKM(UkmEntry::kPerf_PastVideoFramesPowerEfficientName,
310                old_stats->frames_power_efficient);
311
312     // Verify latest stats.
313     VideoDecodeStatsDB::DecodeStatsEntry new_stats(
314         new_targets.frames_decoded, new_targets.frames_dropped,
315         new_targets.frames_power_efficient);
316     bool new_is_smooth = false;
317     bool new_is_efficient = false;
318     perf_history_->AssessStats(key, &new_stats, &new_is_smooth,
319                                &new_is_efficient);
320     EXPECT_UKM(UkmEntry::kPerf_RecordIsSmoothName, new_is_smooth);
321     EXPECT_UKM(UkmEntry::kPerf_RecordIsPowerEfficientName, new_is_efficient);
322     EXPECT_UKM(UkmEntry::kPerf_VideoFramesDecodedName,
323                new_stats.frames_decoded);
324     EXPECT_UKM(UkmEntry::kPerf_VideoFramesDroppedName,
325                new_stats.frames_dropped);
326     EXPECT_UKM(UkmEntry::kPerf_VideoFramesPowerEfficientName,
327                new_stats.frames_power_efficient);
328
329 #undef EXPECT_UKM
330 #undef EXPECT_NO_UKM
331
332     UkmVerifyDoneCb();
333   }
334
335   void VerifyNoUkmReportForFailedSave(size_t expected_num_ukm_entries) {
336     // Verify no new UKM entries appear after failed save.
337     const auto& entries =
338         test_recorder_->GetEntriesByName(UkmEntry::kEntryName);
339     EXPECT_EQ(expected_num_ukm_entries, entries.size());
340
341     UkmVerifyDoneCb();
342   }
343
344   static constexpr double kMinPowerEfficientDecodedFramePercent =
345       VideoDecodePerfHistory::kMinPowerEfficientDecodedFramePercent;
346
347   base::test::TaskEnvironment task_environment_;
348
349   std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_recorder_;
350
351   // The VideoDecodeStatsReporter being tested.
352   std::unique_ptr<VideoDecodePerfHistory> perf_history_;
353
354   const url::Origin kOrigin = url::Origin::Create(GURL("http://example.com"));
355 };
356
357 struct PerfHistoryTestParams {
358   const bool defer_initialize;
359   const std::string key_system;
360   const bool use_hw_secure_codecs;
361 };
362
363 // When bool param is true, tests should wait until the end to run
364 // GetFakeDB()->CompleteInitialize(). Otherwise run PreInitializeDB() at the
365 // test start.
366 class VideoDecodePerfHistoryParamTest
367     : public testing::WithParamInterface<PerfHistoryTestParams>,
368       public VideoDecodePerfHistoryTest {};
369
370 TEST_P(VideoDecodePerfHistoryParamTest, GetPerfInfo_Smooth) {
371   // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then
372   // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
373   // that EXPECT_CALLs arrive in top-to-bottom order.
374   PerfHistoryTestParams params = GetParam();
375   testing::InSequence dummy;
376
377   // Complete initialization in advance of API calls when not asked to defer.
378   if (!params.defer_initialize)
379     PreInitializeDB(/* success */ true);
380
381   // First add 2 records to the history. The second record has a higher frame
382   // rate and a higher number of dropped frames such that it is "not smooth".
383   const VideoCodecProfile kKnownProfile = VP9PROFILE_PROFILE0;
384   const gfx::Size kKownSize(100, 200);
385   const int kSmoothFrameRate = 30;
386   const int kNotSmoothFrameRate = 90;
387   const int kFramesDecoded = 1000;
388   const int kNotPowerEfficientFramesDecoded = 0;
389   // Sets the ratio of dropped frames to barely qualify as smooth.
390   const int kSmoothFramesDropped =
391       kFramesDecoded * GetMaxSmoothDroppedFramesPercent();
392   // Set the ratio of dropped frames to barely qualify as NOT smooth.
393   const int kNotSmoothFramesDropped =
394       kFramesDecoded * GetMaxSmoothDroppedFramesPercent() + 1;
395
396   // Add the entries.
397   SavePerfRecord(UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame,
398                  MakeFeatures(kKnownProfile, kKownSize, kSmoothFrameRate,
399                               params.key_system, params.use_hw_secure_codecs),
400                  MakeTargets(kFramesDecoded, kSmoothFramesDropped,
401                              kNotPowerEfficientFramesDecoded),
402                  kPlayerId);
403   SavePerfRecord(UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame,
404                  MakeFeatures(kKnownProfile, kKownSize, kNotSmoothFrameRate,
405                               params.key_system, params.use_hw_secure_codecs),
406                  MakeTargets(kFramesDecoded, kNotSmoothFramesDropped,
407                              kNotPowerEfficientFramesDecoded),
408                  kPlayerId);
409
410   // Verify perf history returns is_smooth = true for the smooth entry.
411   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsNotPowerEfficient));
412   perf_history_->GetPerfInfo(
413       MakeFeaturesPtr(kKnownProfile, kKownSize, kSmoothFrameRate,
414                       params.key_system, params.use_hw_secure_codecs),
415       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
416                      base::Unretained(this)));
417
418   // Verify perf history returns is_smooth = false for the NOT smooth entry.
419   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsNotPowerEfficient));
420   perf_history_->GetPerfInfo(
421       MakeFeaturesPtr(kKnownProfile, kKownSize, kNotSmoothFrameRate,
422                       params.key_system, params.use_hw_secure_codecs),
423       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
424                      base::Unretained(this)));
425
426   // Verify perf history optimistically returns is_smooth = true when no entry
427   // can be found with the given configuration.
428   const VideoCodecProfile kUnknownProfile = VP9PROFILE_PROFILE2;
429   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
430   perf_history_->GetPerfInfo(
431       MakeFeaturesPtr(kUnknownProfile, kKownSize, kNotSmoothFrameRate),
432       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
433                      base::Unretained(this)));
434
435   // Complete successful deferred DB initialization (see comment at top of test)
436   if (params.defer_initialize) {
437     GetFakeDB()->CompleteInitialize(true);
438
439     // Allow initialize-deferred API calls to complete.
440     task_environment_.RunUntilIdle();
441   }
442 }
443
444 TEST_P(VideoDecodePerfHistoryParamTest, GetPerfInfo_PowerEfficient) {
445   // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then
446   // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
447   // that EXPECT_CALLs arrive in top-to-bottom order.
448   PerfHistoryTestParams params = GetParam();
449   testing::InSequence dummy;
450
451   // Complete initialization in advance of API calls when not asked to defer.
452   if (!params.defer_initialize)
453     PreInitializeDB(/* success */ true);
454
455   // First add 3 records to the history:
456   // - the first has a high number of power efficiently decoded frames;
457   // - the second has a low number of power efficiently decoded frames;
458   // - the third is similar to the first with a high number of dropped frames.
459   const VideoCodecProfile kPowerEfficientProfile = VP9PROFILE_PROFILE0;
460   const VideoCodecProfile kNotPowerEfficientProfile = VP8PROFILE_ANY;
461   const gfx::Size kKownSize(100, 200);
462   const int kSmoothFrameRate = 30;
463   const int kNotSmoothFrameRate = 90;
464   const int kFramesDecoded = 1000;
465   const int kPowerEfficientFramesDecoded =
466       kFramesDecoded * kMinPowerEfficientDecodedFramePercent;
467   const int kNotPowerEfficientFramesDecoded =
468       kFramesDecoded * kMinPowerEfficientDecodedFramePercent - 1;
469   // Sets the ratio of dropped frames to barely qualify as smooth.
470   const int kSmoothFramesDropped =
471       kFramesDecoded * GetMaxSmoothDroppedFramesPercent();
472   // Set the ratio of dropped frames to barely qualify as NOT smooth.
473   const int kNotSmoothFramesDropped =
474       kFramesDecoded * GetMaxSmoothDroppedFramesPercent() + 1;
475
476   // Add the entries.
477   SavePerfRecord(
478       UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame,
479       MakeFeatures(kPowerEfficientProfile, kKownSize, kSmoothFrameRate,
480                    params.key_system, params.use_hw_secure_codecs),
481       MakeTargets(kFramesDecoded, kSmoothFramesDropped,
482                   kPowerEfficientFramesDecoded),
483       kPlayerId);
484   SavePerfRecord(
485       UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame,
486       MakeFeatures(kNotPowerEfficientProfile, kKownSize, kSmoothFrameRate,
487                    params.key_system, params.use_hw_secure_codecs),
488       MakeTargets(kFramesDecoded, kSmoothFramesDropped,
489                   kNotPowerEfficientFramesDecoded),
490       kPlayerId);
491   SavePerfRecord(
492       UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame,
493       MakeFeatures(kPowerEfficientProfile, kKownSize, kNotSmoothFrameRate,
494                    params.key_system, params.use_hw_secure_codecs),
495       MakeTargets(kFramesDecoded, kNotSmoothFramesDropped,
496                   kPowerEfficientFramesDecoded),
497       kPlayerId);
498
499   // Verify perf history returns is_smooth = true, is_power_efficient = true.
500   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
501   perf_history_->GetPerfInfo(
502       MakeFeaturesPtr(kPowerEfficientProfile, kKownSize, kSmoothFrameRate,
503                       params.key_system, params.use_hw_secure_codecs),
504       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
505                      base::Unretained(this)));
506
507   // Verify perf history returns is_smooth = true, is_power_efficient = false.
508   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsNotPowerEfficient));
509   perf_history_->GetPerfInfo(
510       MakeFeaturesPtr(kNotPowerEfficientProfile, kKownSize, kSmoothFrameRate,
511                       params.key_system, params.use_hw_secure_codecs),
512       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
513                      base::Unretained(this)));
514
515   // Verify perf history returns is_smooth = false, is_power_efficient = true.
516   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsPowerEfficient));
517   perf_history_->GetPerfInfo(
518       MakeFeaturesPtr(kPowerEfficientProfile, kKownSize, kNotSmoothFrameRate,
519                       params.key_system, params.use_hw_secure_codecs),
520       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
521                      base::Unretained(this)));
522
523   // Verify perf history optimistically returns is_smooth = true and
524   // is_power_efficient = true when no entry can be found with the given
525   // configuration.
526   const VideoCodecProfile kUnknownProfile = VP9PROFILE_PROFILE2;
527   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
528   perf_history_->GetPerfInfo(
529       MakeFeaturesPtr(kUnknownProfile, kKownSize, kNotSmoothFrameRate,
530                       params.key_system, params.use_hw_secure_codecs),
531       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
532                      base::Unretained(this)));
533
534   // Complete successful deferred DB initialization (see comment at top of test)
535   if (params.defer_initialize) {
536     GetFakeDB()->CompleteInitialize(true);
537
538     // Allow initialize-deferred API calls to complete.
539     task_environment_.RunUntilIdle();
540   }
541 }
542
543 TEST_P(VideoDecodePerfHistoryParamTest, GetPerfInfo_FailedInitialize) {
544   PerfHistoryTestParams params = GetParam();
545   // Fail initialization in advance of API calls when not asked to defer.
546   if (!params.defer_initialize)
547     PreInitializeDB(/* success */ false);
548
549   const VideoCodecProfile kProfile = VP9PROFILE_PROFILE0;
550   const gfx::Size kSize(100, 200);
551   const int kFrameRate = 30;
552
553   // When initialization fails, callback should optimistically claim both smooth
554   // and power efficient performance.
555   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
556   perf_history_->GetPerfInfo(
557       MakeFeaturesPtr(kProfile, kSize, kFrameRate, params.key_system,
558                       params.use_hw_secure_codecs),
559       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
560                      base::Unretained(this)));
561
562   // Fail deferred DB initialization (see comment at top of test).
563   if (params.defer_initialize) {
564     GetFakeDB()->CompleteInitialize(false);
565
566     // Allow initialize-deferred API calls to complete.
567     task_environment_.RunUntilIdle();
568   }
569 }
570
571 TEST_P(VideoDecodePerfHistoryParamTest, AppendAndDestroyStats) {
572   // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then
573   // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
574   // that EXPECT_CALLs arrive in top-to-bottom order.
575   PerfHistoryTestParams params = GetParam();
576   testing::InSequence dummy;
577
578   // Complete initialization in advance of API calls when not asked to defer.
579   if (!params.defer_initialize)
580     PreInitializeDB(/* success */ true);
581
582   // Add a simple record to the history.
583   const VideoCodecProfile kProfile = VP9PROFILE_PROFILE0;
584   const gfx::Size kSize(100, 200);
585   const int kFrameRate = 30;
586   const int kFramesDecoded = 1000;
587   const int kManyFramesDropped = kFramesDecoded / 2;
588   const int kFramesPowerEfficient = kFramesDecoded;
589   SavePerfRecord(
590       UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame,
591       MakeFeatures(kProfile, kSize, kFrameRate, params.key_system,
592                    params.use_hw_secure_codecs),
593       MakeTargets(kFramesDecoded, kManyFramesDropped, kFramesPowerEfficient),
594       kPlayerId);
595
596   // Verify its there before we ClearHistory(). Note that perf is NOT smooth.
597   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsPowerEfficient));
598   perf_history_->GetPerfInfo(
599       MakeFeaturesPtr(kProfile, kSize, kFrameRate, params.key_system,
600                       params.use_hw_secure_codecs),
601       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
602                      base::Unretained(this)));
603
604   // Initiate async clearing of history.
605   EXPECT_CALL(*this, MockOnClearedHistory());
606   perf_history_->ClearHistory(
607       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockOnClearedHistory,
608                      base::Unretained(this)));
609
610   // Verify record we added above is no longer present.
611   // SUBTLE: The PerfHistory will optimistically respond kIsSmooth when no data
612   // is found. So the signal that the entry was removed is the CB now claims
613   // "smooth" when it claimed NOT smooth just moments before.
614   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
615   perf_history_->GetPerfInfo(
616       MakeFeaturesPtr(kProfile, kSize, kFrameRate, params.key_system,
617                       params.use_hw_secure_codecs),
618       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
619                      base::Unretained(this)));
620
621   // Complete successful deferred DB initialization (see comment at top of test)
622   if (params.defer_initialize) {
623     GetFakeDB()->CompleteInitialize(true);
624
625     // Allow initialize-deferred API calls to complete.
626     task_environment_.RunUntilIdle();
627   }
628 }
629
630 TEST_P(VideoDecodePerfHistoryParamTest, GetVideoDecodeStatsDB) {
631   // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then
632   // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
633   // that EXPECT_CALLs arrive in top-to-bottom order.
634   PerfHistoryTestParams params = GetParam();
635   testing::InSequence dummy;
636
637   // Complete initialization in advance of API calls when not asked to defer.
638   if (!params.defer_initialize)
639     PreInitializeDB(/* success */ true);
640
641   // Request a pointer to VideoDecodeStatsDB and verify the callback.
642   EXPECT_CALL(*this, MockGetVideoDecodeStatsDBCB(_))
643       .WillOnce([&](const auto* db_ptr) {
644         // Not able to simply use a matcher because the DB does not exist at the
645         // time we setup the EXPECT_CALL.
646         EXPECT_EQ(GetFakeDB(), db_ptr);
647       });
648
649   perf_history_->GetVideoDecodeStatsDB(
650       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetVideoDecodeStatsDBCB,
651                      base::Unretained(this)));
652
653   task_environment_.RunUntilIdle();
654
655   // Complete successful deferred DB initialization (see comment at top of test)
656   if (params.defer_initialize) {
657     GetFakeDB()->CompleteInitialize(true);
658
659     // Allow initialize-deferred API calls to complete.
660     task_environment_.RunUntilIdle();
661   }
662 }
663
664 TEST_P(VideoDecodePerfHistoryParamTest,
665        GetVideoDecodeStatsDB_FailedInitialize) {
666   // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then
667   // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
668   // that EXPECT_CALLs arrive in top-to-bottom order.
669   PerfHistoryTestParams params = GetParam();
670   testing::InSequence dummy;
671
672   // Complete initialization in advance of API calls when not asked to defer.
673   if (!params.defer_initialize)
674     PreInitializeDB(/* success */ false);
675
676   // Request a pointer to VideoDecodeStatsDB and verify the callback provides
677   // a nullptr due to failed initialization.
678   EXPECT_CALL(*this, MockGetVideoDecodeStatsDBCB(IsNull()));
679   perf_history_->GetVideoDecodeStatsDB(
680       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetVideoDecodeStatsDBCB,
681                      base::Unretained(this)));
682
683   task_environment_.RunUntilIdle();
684
685   // Complete failed deferred DB initialization (see comment at top of test)
686   if (params.defer_initialize) {
687     GetFakeDB()->CompleteInitialize(false);
688
689     // Allow initialize-deferred API calls to complete.
690     task_environment_.RunUntilIdle();
691   }
692 }
693
694 TEST_P(VideoDecodePerfHistoryParamTest, FailedDatabaseGetForAppend) {
695   // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then
696   // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
697   // that EXPECT_CALLs arrive in top-to-bottom order.
698   PerfHistoryTestParams params = GetParam();
699
700   // Complete initialization in advance of API calls when not asked to defer.
701   if (!params.defer_initialize)
702     PreInitializeDB(/* success */ true);
703
704   // Create a record that is neither smooth nor power efficient. After we fail
705   // to save this record we should find smooth = power_efficient = true (the
706   // default for no-data-found).
707   const VideoCodecProfile kProfile = VP9PROFILE_PROFILE0;
708   const gfx::Size kSize(100, 200);
709   const int kFrameRate = 30;
710   const int kFramesDecoded = 1000;
711   const int kFramesDropped =
712       kFramesDecoded * GetMaxSmoothDroppedFramesPercent() + 1;
713   const int kFramesPowerEfficient = 0;
714
715   // Fail the "get" step of the save (we always get existing stats prior to
716   // save for UKM reporting).
717   GetFakeDB()->set_fail_next_get(true);
718
719   // Attempt (and fail) the save. UKM report depends on successful retrieval
720   // of stats from the DB, so no UKM reporting should occur here.
721   SavePerfRecord(
722       UkmVerifcation::kNoUkmsAdded, kOrigin, kIsTopFrame,
723       MakeFeatures(kProfile, kSize, kFrameRate, params.key_system,
724                    params.use_hw_secure_codecs),
725       MakeTargets(kFramesDecoded, kFramesDropped, kFramesPowerEfficient),
726       kPlayerId);
727
728   // Verify perf history still returns is_smooth = power_efficient = true since
729   // no data was successfully saved for the given configuration.
730   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
731   perf_history_->GetPerfInfo(
732       MakeFeaturesPtr(kProfile, kSize, kFrameRate, params.key_system,
733                       params.use_hw_secure_codecs),
734       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
735                      base::Unretained(this)));
736
737   // Complete successful deferred DB initialization (see comment at top of test)
738   if (params.defer_initialize) {
739     GetFakeDB()->CompleteInitialize(true);
740
741     // Allow initialize-deferred API calls to complete.
742     task_environment_.RunUntilIdle();
743   }
744 }
745
746 TEST_P(VideoDecodePerfHistoryParamTest, FailedDatabaseAppend) {
747   // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then
748   // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
749   // that EXPECT_CALLs arrive in top-to-bottom order.
750   PerfHistoryTestParams params = GetParam();
751
752   // Complete initialization in advance of API calls when not asked to defer.
753   if (!params.defer_initialize)
754     PreInitializeDB(/* success */ true);
755
756   // Force the DB to fail on the next append.
757   GetFakeDB()->set_fail_next_append(true);
758
759   // Create a record that is neither smooth nor power efficient. After we fail
760   // to save this record we should find smooth = power_efficient = true (the
761   // default for no-data-found).
762   const VideoCodecProfile kProfile = VP9PROFILE_PROFILE0;
763   const gfx::Size kSize(100, 200);
764   const int kFrameRate = 30;
765   const int kFramesDecoded = 1000;
766   const int kFramesDropped =
767       kFramesDecoded * GetMaxSmoothDroppedFramesPercent() + 1;
768   const int kFramesPowerEfficient = 0;
769
770   // Attempt (and fail) the save. Note that we still expect UKM to be reported
771   // because we successfully retrieved stats from the DB, we just fail to append
772   // the new stats. UKM reporting occurs between retrieval and appending.
773   SavePerfRecord(
774       UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame,
775       MakeFeatures(kProfile, kSize, kFrameRate, params.key_system,
776                    params.use_hw_secure_codecs),
777       MakeTargets(kFramesDecoded, kFramesDropped, kFramesPowerEfficient),
778       kPlayerId);
779
780   // Verify perf history still returns is_smooth = power_efficient = true since
781   // no data was successfully saved for the given configuration.
782   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsPowerEfficient));
783   perf_history_->GetPerfInfo(
784       MakeFeaturesPtr(kProfile, kSize, kFrameRate, params.key_system,
785                       params.use_hw_secure_codecs),
786       base::BindOnce(&VideoDecodePerfHistoryTest::MockGetPerfInfoCB,
787                      base::Unretained(this)));
788
789   // Complete successful deferred DB initialization (see comment at top of test)
790   if (params.defer_initialize) {
791     GetFakeDB()->CompleteInitialize(true);
792
793     // Allow initialize-deferred API calls to complete.
794     task_environment_.RunUntilIdle();
795   }
796 }
797
798 // Tests that the feature parameters are used to override constants for the
799 // Media Capabilities feature.
800 // To avoid race conditions when setting the parameter, the test sets it when
801 // starting and make sure the values recorded to the DB wouldn't be smooth per
802 // the default value.
803 TEST_P(VideoDecodePerfHistoryParamTest,
804        SmoothThresholdFinchOverride_NoEmeOverride) {
805   base::test::ScopedFeatureList scoped_feature_list;
806
807   // EME and non EME threshold should initially be the same (neither is
808   // overridden).
809   double previous_smooth_dropped_frames_threshold =
810       GetMaxSmoothDroppedFramesPercent(false /* is_eme */);
811   EXPECT_EQ(previous_smooth_dropped_frames_threshold,
812             GetMaxSmoothDroppedFramesPercent(true /* is_eme */));
813
814   double new_smooth_dropped_frames_threshold =
815       previous_smooth_dropped_frames_threshold / 2;
816
817   ASSERT_LT(new_smooth_dropped_frames_threshold,
818             previous_smooth_dropped_frames_threshold);
819
820   // Override field trial.
821   base::FieldTrialParams trial_params;
822   trial_params
823       [VideoDecodePerfHistory::kMaxSmoothDroppedFramesPercentParamName] =
824           base::NumberToString(new_smooth_dropped_frames_threshold);
825   scoped_feature_list.InitAndEnableFeatureWithParameters(
826       media::kMediaCapabilitiesWithParameters, trial_params);
827
828   EXPECT_EQ(GetFieldTrialParams(), trial_params);
829
830   // Non EME threshold is overridden.
831   EXPECT_EQ(new_smooth_dropped_frames_threshold,
832             GetMaxSmoothDroppedFramesPercent(false /* is_eme */));
833
834   // EME threshold is also implicitly overridden (we didn't set an EME specific
835   // value, so it should defer to the non-EME override).
836   EXPECT_EQ(new_smooth_dropped_frames_threshold,
837             GetMaxSmoothDroppedFramesPercent(true /* is_eme */));
838
839   // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then
840   // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
841   // that EXPECT_CALLs arrive in top-to-bottom order.
842   PerfHistoryTestParams params = GetParam();
843   testing::InSequence dummy;
844
845   // Complete initialization in advance of API calls when not asked to defer.
846   if (!params.defer_initialize)
847     PreInitializeDB(/* success */ true);
848
849   // First add 2 records to the history. The second record has a higher frame
850   // rate and a higher number of dropped frames such that it is "not smooth".
851   const VideoCodecProfile kKnownProfile = VP9PROFILE_PROFILE0;
852   const gfx::Size kKownSize(100, 200);
853   const int kSmoothFrameRatePrevious = 30;
854   const int kSmoothFrameRateNew = 90;
855   const int kFramesDecoded = 1000;
856   const int kNotPowerEfficientFramesDecoded = 0;
857
858   // Sets the ratio of dropped frames to qualify as smooth per the default
859   // threshold.
860   const int kSmoothFramesDroppedPrevious =
861       kFramesDecoded * previous_smooth_dropped_frames_threshold;
862   // Sets the ratio of dropped frames to quality as smooth per the new
863   // threshold.
864   const int kSmoothFramesDroppedNew =
865       kFramesDecoded * new_smooth_dropped_frames_threshold;
866
867   // Add the entry.
868   SavePerfRecord(
869       UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame,
870       MakeFeatures(kKnownProfile, kKownSize, kSmoothFrameRatePrevious,
871                    params.key_system, params.use_hw_secure_codecs),
872       MakeTargets(kFramesDecoded, kSmoothFramesDroppedPrevious,
873                   kNotPowerEfficientFramesDecoded),
874       kPlayerId);
875
876   SavePerfRecord(UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame,
877                  MakeFeatures(kKnownProfile, kKownSize, kSmoothFrameRateNew,
878                               params.key_system, params.use_hw_secure_codecs),
879                  MakeTargets(kFramesDecoded, kSmoothFramesDroppedNew,
880                              kNotPowerEfficientFramesDecoded),
881                  kPlayerId);
882
883   // Verify perf history returns is_smooth = false for entry that would be
884   // smooth per previous smooth threshold.
885   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsNotPowerEfficient));
886   perf_history_->GetPerfInfo(
887       MakeFeaturesPtr(kKnownProfile, kKownSize, kSmoothFrameRatePrevious,
888                       params.key_system, params.use_hw_secure_codecs),
889       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
890                      base::Unretained(this)));
891
892   // Verify perf history returns is_smooth = true for entry that would be
893   // smooth per new smooth theshold.
894   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsNotPowerEfficient));
895   perf_history_->GetPerfInfo(
896       MakeFeaturesPtr(kKnownProfile, kKownSize, kSmoothFrameRateNew,
897                       params.key_system, params.use_hw_secure_codecs),
898       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
899                      base::Unretained(this)));
900
901   // Complete successful deferred DB initialization (see comment at top of test)
902   if (params.defer_initialize) {
903     GetFakeDB()->CompleteInitialize(true);
904
905     // Allow initialize-deferred API calls to complete.
906     task_environment_.RunUntilIdle();
907   }
908 }
909
910 TEST_P(VideoDecodePerfHistoryParamTest,
911        SmoothThresholdFinchOverride_WithEmeOverride) {
912   base::test::ScopedFeatureList scoped_feature_list;
913
914   // EME and non EME threshold should initially be the same (neither is
915   // overridden).
916   double previous_smooth_dropped_frames_threshold =
917       GetMaxSmoothDroppedFramesPercent(false /* is_eme */);
918   EXPECT_EQ(previous_smooth_dropped_frames_threshold,
919             GetMaxSmoothDroppedFramesPercent(true /* is_eme */));
920
921   double new_CLEAR_smooth_dropped_frames_threshold =
922       previous_smooth_dropped_frames_threshold / 2;
923   double new_EME_smooth_dropped_frames_threshold =
924       previous_smooth_dropped_frames_threshold / 3;
925
926   ASSERT_LT(new_CLEAR_smooth_dropped_frames_threshold,
927             previous_smooth_dropped_frames_threshold);
928   ASSERT_LT(new_EME_smooth_dropped_frames_threshold,
929             new_CLEAR_smooth_dropped_frames_threshold);
930
931   // Override field trial.
932   base::FieldTrialParams trial_params;
933   trial_params
934       [VideoDecodePerfHistory::kMaxSmoothDroppedFramesPercentParamName] =
935           base::NumberToString(new_CLEAR_smooth_dropped_frames_threshold);
936   trial_params
937       [VideoDecodePerfHistory::kEmeMaxSmoothDroppedFramesPercentParamName] =
938           base::NumberToString(new_EME_smooth_dropped_frames_threshold);
939
940   scoped_feature_list.InitAndEnableFeatureWithParameters(
941       media::kMediaCapabilitiesWithParameters, trial_params);
942
943   EXPECT_EQ(GetFieldTrialParams(), trial_params);
944
945   // Both thresholds should be overridden.
946   EXPECT_EQ(new_CLEAR_smooth_dropped_frames_threshold,
947             GetMaxSmoothDroppedFramesPercent(false /* is_eme */));
948   EXPECT_EQ(new_EME_smooth_dropped_frames_threshold,
949             GetMaxSmoothDroppedFramesPercent(true /* is_eme */));
950
951   // NOTE: The when the DB initialization is deferred, All EXPECT_CALLs are then
952   // delayed until we db_->CompleteInitialize(). testing::InSequence enforces
953   // that EXPECT_CALLs arrive in top-to-bottom order.
954   PerfHistoryTestParams params = GetParam();
955   testing::InSequence dummy;
956
957   // Complete initialization in advance of API calls when not asked to defer.
958   if (!params.defer_initialize)
959     PreInitializeDB(/* success */ true);
960
961   // First add 2 records to the history. The second record has a higher frame
962   // rate and a higher number of dropped frames such that it is "not smooth".
963   const VideoCodecProfile kKnownProfile = VP9PROFILE_PROFILE0;
964   const gfx::Size kKownSize(100, 200);
965   const int kSmoothFrameRatePrevious = 30;
966   const int kSmoothFrameRateNew = 90;
967   const int kFramesDecoded = 1000;
968   const int kNotPowerEfficientFramesDecoded = 0;
969
970   // Sets the ratio of dropped frames to qualify as NOT smooth. For CLEAR, use
971   // the previous smooth threshold. For EME, use the new CLEAR threshold to
972   // verify that the EME threshold is lower than CLEAR.
973   const int kSmoothFramesDroppedPrevious =
974       params.key_system.empty()
975           ? kFramesDecoded * previous_smooth_dropped_frames_threshold
976           : kFramesDecoded * new_CLEAR_smooth_dropped_frames_threshold;
977   // Sets the ratio of dropped frames to quality as smooth per the new threshold
978   // depending on whether the key indicates this record is EME.
979   const int kSmoothFramesDroppedNew =
980       params.key_system.empty()
981           ? kFramesDecoded * new_CLEAR_smooth_dropped_frames_threshold
982           : kFramesDecoded * new_EME_smooth_dropped_frames_threshold;
983
984   // Add the entry.
985   SavePerfRecord(
986       UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame,
987       MakeFeatures(kKnownProfile, kKownSize, kSmoothFrameRatePrevious,
988                    params.key_system, params.use_hw_secure_codecs),
989       MakeTargets(kFramesDecoded, kSmoothFramesDroppedPrevious,
990                   kNotPowerEfficientFramesDecoded),
991       kPlayerId);
992
993   SavePerfRecord(UkmVerifcation::kSaveTriggersUkm, kOrigin, kIsTopFrame,
994                  MakeFeatures(kKnownProfile, kKownSize, kSmoothFrameRateNew,
995                               params.key_system, params.use_hw_secure_codecs),
996                  MakeTargets(kFramesDecoded, kSmoothFramesDroppedNew,
997                              kNotPowerEfficientFramesDecoded),
998                  kPlayerId);
999
1000   // Verify perf history returns is_smooth = false for entry that would be
1001   // smooth per previous smooth threshold.
1002   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsNotSmooth, kIsNotPowerEfficient));
1003   perf_history_->GetPerfInfo(
1004       MakeFeaturesPtr(kKnownProfile, kKownSize, kSmoothFrameRatePrevious,
1005                       params.key_system, params.use_hw_secure_codecs),
1006       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
1007                      base::Unretained(this)));
1008
1009   // Verify perf history returns is_smooth = true for entry that would be
1010   // smooth per new smooth threshold.
1011   EXPECT_CALL(*this, MockGetPerfInfoCB(kIsSmooth, kIsNotPowerEfficient));
1012   perf_history_->GetPerfInfo(
1013       MakeFeaturesPtr(kKnownProfile, kKownSize, kSmoothFrameRateNew,
1014                       params.key_system, params.use_hw_secure_codecs),
1015       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockGetPerfInfoCB,
1016                      base::Unretained(this)));
1017
1018   // Complete successful deferred DB initialization (see comment at top of test)
1019   if (params.defer_initialize) {
1020     GetFakeDB()->CompleteInitialize(true);
1021
1022     // Allow initialize-deferred API calls to complete.
1023     task_environment_.RunUntilIdle();
1024   }
1025 }
1026
1027 const PerfHistoryTestParams kPerfHistoryTestParams[] = {
1028     {true, "", false},
1029     {false, "", false},
1030     {true, "com.widevine.alpha", false},
1031     {true, "com.widevine.alpha", true},
1032 };
1033
1034 INSTANTIATE_TEST_SUITE_P(VaryDBInitTiming,
1035                          VideoDecodePerfHistoryParamTest,
1036                          ::testing::ValuesIn(kPerfHistoryTestParams));
1037
1038 //
1039 // The following test are not parameterized. They instead always hard code
1040 // deferred initialization.
1041 //
1042
1043 TEST_F(VideoDecodePerfHistoryTest, ClearHistoryTriggersSuccessfulInitialize) {
1044   // Clear the DB. Completion callback shouldn't fire until initialize
1045   // completes.
1046   EXPECT_CALL(*this, MockOnClearedHistory()).Times(0);
1047   perf_history_->ClearHistory(
1048       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockOnClearedHistory,
1049                      base::Unretained(this)));
1050
1051   // Give completion callback a chance to fire. Confirm it did not fire.
1052   task_environment_.RunUntilIdle();
1053   testing::Mock::VerifyAndClearExpectations(this);
1054
1055   // Expect completion callback after we successfully initialize.
1056   EXPECT_CALL(*this, MockOnClearedHistory());
1057   GetFakeDB()->CompleteInitialize(true);
1058
1059   // Give deferred callback a chance to fire.
1060   task_environment_.RunUntilIdle();
1061 }
1062
1063 TEST_F(VideoDecodePerfHistoryTest, ClearHistoryTriggersFailedInitialize) {
1064   // Clear the DB. Completion callback shouldn't fire until initialize
1065   // completes.
1066   EXPECT_CALL(*this, MockOnClearedHistory()).Times(0);
1067   perf_history_->ClearHistory(
1068       base::BindOnce(&VideoDecodePerfHistoryParamTest::MockOnClearedHistory,
1069                      base::Unretained(this)));
1070
1071   // Give completion callback a chance to fire. Confirm it did not fire.
1072   task_environment_.RunUntilIdle();
1073   testing::Mock::VerifyAndClearExpectations(this);
1074
1075   // Expect completion callback after completing initialize. "Failure" is still
1076   // a form of completion.
1077   EXPECT_CALL(*this, MockOnClearedHistory());
1078   GetFakeDB()->CompleteInitialize(false);
1079
1080   // Give deferred callback a chance to fire.
1081   task_environment_.RunUntilIdle();
1082 }
1083
1084 }  // namespace media