summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/media/smoothness_helper_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/media/smoothness_helper_unittest.cc')
-rw-r--r--chromium/third_party/blink/renderer/platform/media/smoothness_helper_unittest.cc206
1 files changed, 206 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/platform/media/smoothness_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/media/smoothness_helper_unittest.cc
new file mode 100644
index 00000000000..c693c2f3d54
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/media/smoothness_helper_unittest.cc
@@ -0,0 +1,206 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/platform/media/smoothness_helper.h"
+
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "media/learning/common/labelled_example.h"
+#include "media/learning/common/learning_task_controller.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+using ::media::learning::FeatureValue;
+using ::media::learning::FeatureVector;
+using ::media::learning::LearningTask;
+using ::media::learning::LearningTaskController;
+using ::media::learning::ObservationCompletion;
+using ::media::learning::TargetValue;
+using ::testing::_;
+using ::testing::ResultOf;
+using ::testing::Return;
+
+// Helper for EXPECT_CALL argument matching on Optional<TargetValue>. Applies
+// matcher |m| to the TargetValue as a double. For example:
+// void Foo(absl::optional<TargetValue>);
+// EXPECT_CALL(..., Foo(OPT_TARGET(Gt(0.9)))) will expect that the value of the
+// Optional<TargetValue> passed to Foo() to be greather than 0.9 .
+#define OPT_TARGET(m) \
+ ResultOf([](const absl::optional<TargetValue>& v) { return (*v).value(); }, m)
+
+// Same as above, but expects an ObservationCompletion.
+#define COMPLETION_TARGET(m) \
+ ResultOf( \
+ [](const ObservationCompletion& x) { return x.target_value.value(); }, \
+ m)
+
+class SmoothnessHelperTest : public testing::Test {
+ class MockLearningTaskController : public LearningTaskController {
+ public:
+ MOCK_METHOD4(BeginObservation,
+ void(base::UnguessableToken id,
+ const FeatureVector& features,
+ const absl::optional<TargetValue>& default_target,
+ const absl::optional<ukm::SourceId>& source_id));
+
+ MOCK_METHOD2(CompleteObservation,
+ void(base::UnguessableToken id,
+ const ObservationCompletion& completion));
+
+ MOCK_METHOD1(CancelObservation, void(base::UnguessableToken id));
+
+ MOCK_METHOD2(UpdateDefaultTarget,
+ void(base::UnguessableToken id,
+ const absl::optional<TargetValue>& default_target));
+
+ MOCK_METHOD0(GetLearningTask, const LearningTask&());
+ MOCK_METHOD2(PredictDistribution,
+ void(const FeatureVector& features, PredictionCB callback));
+ };
+
+ class MockClient : public SmoothnessHelper::Client {
+ public:
+ ~MockClient() override = default;
+
+ MOCK_CONST_METHOD0(DecodedFrameCount, unsigned(void));
+ MOCK_CONST_METHOD0(DroppedFrameCount, unsigned(void));
+ };
+
+ public:
+ void SetUp() override {
+ auto bad_ltc = std::make_unique<MockLearningTaskController>();
+ bad_ltc_ = bad_ltc.get();
+ auto nnr_ltc = std::make_unique<MockLearningTaskController>();
+ nnr_ltc_ = nnr_ltc.get();
+ features_.push_back(FeatureValue(123));
+ helper_ = SmoothnessHelper::Create(std::move(bad_ltc), std::move(nnr_ltc),
+ features_, &client_);
+ segment_size_ = SmoothnessHelper::SegmentSizeForTesting();
+ }
+
+ // Helper for EXPECT_CALL.
+ absl::optional<TargetValue> Opt(double x) {
+ return absl::optional<TargetValue>(TargetValue(x));
+ }
+
+ void FastForwardBy(base::TimeDelta amount) {
+ task_environment_.FastForwardBy(amount);
+ }
+
+ // Set the dropped / decoded totals that will be returned by the mock client.
+ void SetFrameCounters(int dropped, int decoded) {
+ ON_CALL(client_, DroppedFrameCount()).WillByDefault(Return(dropped));
+ ON_CALL(client_, DecodedFrameCount()).WillByDefault(Return(decoded));
+ }
+
+ protected:
+ base::test::SingleThreadTaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+
+ // Helper under test
+ std::unique_ptr<SmoothnessHelper> helper_;
+
+ // Max bad consecutive windows by frame drop LTC.
+ MockLearningTaskController* bad_ltc_;
+
+ // Max consecutive NNRs LTC.
+ MockLearningTaskController* nnr_ltc_;
+
+ MockClient client_;
+ FeatureVector features_;
+
+ base::TimeDelta segment_size_;
+};
+
+TEST_F(SmoothnessHelperTest, FeaturesAreReturned) {
+ EXPECT_EQ(features_, helper_->features());
+}
+
+TEST_F(SmoothnessHelperTest, MaxBadWindowsRecordsTrue) {
+ // Record three bad segments, and verify that it records 'true'.
+ SetFrameCounters(0, 0);
+ base::RunLoop().RunUntilIdle();
+ int dropped_frames = 0;
+ int total_frames = 0;
+
+ // First segment has no dropped frames. Should record 0.
+ EXPECT_CALL(*bad_ltc_, BeginObservation(_, _, OPT_TARGET(0.0), _)).Times(1);
+ SetFrameCounters(dropped_frames += 0, total_frames += 1000);
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(bad_ltc_);
+
+ // Second segment has a lot of dropped frames, so the target should increase.
+ EXPECT_CALL(*bad_ltc_, UpdateDefaultTarget(_, OPT_TARGET(1.0))).Times(1);
+ SetFrameCounters(dropped_frames += 999, total_frames += 1000);
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(bad_ltc_);
+
+ // Third segment looks nice, so nothing should update.
+ EXPECT_CALL(*bad_ltc_, UpdateDefaultTarget(_, OPT_TARGET(_))).Times(0);
+ SetFrameCounters(dropped_frames += 0, total_frames += 1000);
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(bad_ltc_);
+
+ // Fourth segment has dropped frames, but the default shouldn't change.
+ // It's okay if it changes to the same value, but we just memorize that it
+ // won't change at all.
+ EXPECT_CALL(*bad_ltc_, UpdateDefaultTarget(_, OPT_TARGET(_))).Times(0);
+ SetFrameCounters(dropped_frames += 999, total_frames += 1000);
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(bad_ltc_);
+
+ // The last segment is also bad, and should increase the max.
+ EXPECT_CALL(*bad_ltc_, UpdateDefaultTarget(_, OPT_TARGET(2.0))).Times(1);
+ SetFrameCounters(dropped_frames += 999, total_frames += 1000);
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(bad_ltc_);
+}
+
+TEST_F(SmoothnessHelperTest, NNRTaskRecordsMaxNNRs) {
+ // We should get the first target once a window has elapsed. We need some
+ // decoded frames before anything happens.
+ SetFrameCounters(0, 1);
+ EXPECT_CALL(*nnr_ltc_, BeginObservation(_, _, OPT_TARGET(0.0), _)).Times(1);
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ FastForwardBy(segment_size_);
+ base::RunLoop().RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(nnr_ltc_);
+
+ // Add some NNRs, which should be reported immediately now that a segment
+ // has started. Note that we don't care if NNRs are reported before a segment
+ // is started, because it's not really clear which behavior is right anyway.
+ EXPECT_CALL(*nnr_ltc_, UpdateDefaultTarget(_, OPT_TARGET(1))).Times(1);
+ helper_->NotifyNNR();
+ testing::Mock::VerifyAndClearExpectations(nnr_ltc_);
+
+ // Advance time by one window, and add an NNR. It's close enough that we
+ // should be notified that the max went up.
+ FastForwardBy(segment_size_);
+ EXPECT_CALL(*nnr_ltc_, UpdateDefaultTarget(_, OPT_TARGET(2))).Times(1);
+ helper_->NotifyNNR();
+ testing::Mock::VerifyAndClearExpectations(nnr_ltc_);
+
+ // Fast forward by a lot, so that the next NNR isn't consecutive. Nothing
+ // should be reported, because it's less than the current maximum.
+ EXPECT_CALL(*nnr_ltc_, UpdateDefaultTarget(_, OPT_TARGET(_))).Times(0);
+ FastForwardBy(base::TimeDelta::FromSeconds(1000));
+ helper_->NotifyNNR();
+ // It might be okay if this reported 2, since it's a tie.
+ helper_->NotifyNNR();
+ testing::Mock::VerifyAndClearExpectations(nnr_ltc_);
+
+ // The next NNR should advance the maximum to 3.
+ EXPECT_CALL(*nnr_ltc_, UpdateDefaultTarget(_, OPT_TARGET(3))).Times(1);
+ helper_->NotifyNNR();
+}
+
+} // namespace blink