1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/bind.h"
6#include "base/debug/stack_trace.h"
7#include "base/run_loop.h"
8#include "media/base/video_frame.h"
9#include "media/filters/clockless_video_frame_scheduler.h"
10#include "media/filters/test_video_frame_scheduler.h"
11#include "media/filters/video_frame_scheduler_impl.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace media {
15
16static void DoNothing(const scoped_refptr<VideoFrame>& frame) {
17}
18
19static void CheckForReentrancy(std::string* stack_trace,
20                               const scoped_refptr<VideoFrame>& frame,
21                               VideoFrameScheduler::Reason reason) {
22  *stack_trace = base::debug::StackTrace().ToString();
23  base::MessageLoop::current()->PostTask(FROM_HERE,
24                                         base::MessageLoop::QuitClosure());
25}
26
27// Type parameterized test harness for validating API contract of
28// VideoFrameScheduler implementations.
29//
30// NOTE: C++ requires using "this" for derived class templates when referencing
31// class members.
32template <typename T>
33class VideoFrameSchedulerTest : public testing::Test {
34 public:
35  VideoFrameSchedulerTest() {}
36  virtual ~VideoFrameSchedulerTest() {}
37
38  base::MessageLoop message_loop_;
39  T scheduler_;
40
41 private:
42  DISALLOW_COPY_AND_ASSIGN(VideoFrameSchedulerTest);
43};
44
45template <>
46VideoFrameSchedulerTest<ClocklessVideoFrameScheduler>::VideoFrameSchedulerTest()
47    : scheduler_(base::Bind(&DoNothing)) {
48}
49
50template <>
51VideoFrameSchedulerTest<VideoFrameSchedulerImpl>::VideoFrameSchedulerTest()
52    : scheduler_(message_loop_.message_loop_proxy(), base::Bind(&DoNothing)) {
53}
54
55TYPED_TEST_CASE_P(VideoFrameSchedulerTest);
56
57TYPED_TEST_P(VideoFrameSchedulerTest, ScheduleVideoFrameIsntReentrant) {
58  scoped_refptr<VideoFrame> frame =
59      VideoFrame::CreateBlackFrame(gfx::Size(8, 8));
60
61  std::string stack_trace;
62  this->scheduler_.ScheduleVideoFrame(
63      frame, base::TimeTicks(), base::Bind(&CheckForReentrancy, &stack_trace));
64  EXPECT_TRUE(stack_trace.empty()) << "Reentracy detected:\n" << stack_trace;
65}
66
67REGISTER_TYPED_TEST_CASE_P(VideoFrameSchedulerTest,
68                           ScheduleVideoFrameIsntReentrant);
69
70INSTANTIATE_TYPED_TEST_CASE_P(ClocklessVideoFrameScheduler,
71                              VideoFrameSchedulerTest,
72                              ClocklessVideoFrameScheduler);
73INSTANTIATE_TYPED_TEST_CASE_P(VideoFrameSchedulerImpl,
74                              VideoFrameSchedulerTest,
75                              VideoFrameSchedulerImpl);
76INSTANTIATE_TYPED_TEST_CASE_P(TestVideoFrameScheduler,
77                              VideoFrameSchedulerTest,
78                              TestVideoFrameScheduler);
79
80}  // namespace media
81