OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/message_loop.h" | 5 #include "base/message_loop.h" |
6 #include "base/task.h" | 6 #include "base/task.h" |
7 #include "remoting/base/mock_objects.h" | 7 #include "remoting/base/mock_objects.h" |
8 #include "remoting/host/mock_objects.h" | 8 #include "remoting/host/mock_objects.h" |
9 #include "remoting/host/screen_recorder.h" | 9 #include "remoting/host/screen_recorder.h" |
10 #include "remoting/proto/video.pb.h" | 10 #include "remoting/proto/video.pb.h" |
11 #include "remoting/protocol/mock_objects.h" | 11 #include "remoting/protocol/mock_objects.h" |
12 #include "testing/gmock/include/gmock/gmock.h" | 12 #include "testing/gmock/include/gmock/gmock.h" |
13 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
14 | 14 |
15 using ::remoting::protocol::MockConnectionToClient; | 15 using ::remoting::protocol::MockConnectionToClient; |
16 using ::remoting::protocol::MockVideoStub; | 16 using ::remoting::protocol::MockVideoStub; |
17 | 17 |
18 using ::testing::_; | 18 using ::testing::_; |
19 using ::testing::AtLeast; | 19 using ::testing::AtLeast; |
| 20 using ::testing::DeleteArg; |
| 21 using ::testing::DoAll; |
| 22 using ::testing::InSequence; |
| 23 using ::testing::InvokeWithoutArgs; |
20 using ::testing::NotNull; | 24 using ::testing::NotNull; |
21 using ::testing::Return; | 25 using ::testing::Return; |
22 using ::testing::SaveArg; | 26 using ::testing::SaveArg; |
23 | 27 |
24 namespace remoting { | 28 namespace remoting { |
25 | 29 |
| 30 namespace { |
| 31 |
| 32 ACTION_P2(RunCallback, rects, data) { |
| 33 InvalidRects& dirty_rects = data->mutable_dirty_rects(); |
| 34 InvalidRects temp_rects; |
| 35 std::set_union(dirty_rects.begin(), dirty_rects.end(), |
| 36 rects.begin(), rects.end(), |
| 37 std::inserter(temp_rects, temp_rects.begin())); |
| 38 dirty_rects.swap(temp_rects); |
| 39 arg0->Run(data); |
| 40 delete arg0; |
| 41 } |
| 42 |
| 43 ACTION(FinishEncode) { |
| 44 scoped_ptr<VideoPacket> packet(new VideoPacket()); |
| 45 packet->set_flags(VideoPacket::LAST_PACKET | VideoPacket::LAST_PARTITION); |
| 46 arg2->Run(packet.release()); |
| 47 delete arg2; |
| 48 } |
| 49 |
| 50 ACTION(FinishSend) { |
| 51 arg1->Run(); |
| 52 delete arg1; |
| 53 } |
| 54 |
| 55 // Helper method to quit the main message loop. |
| 56 void QuitMessageLoop(MessageLoop* message_loop) { |
| 57 message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |
| 58 } |
| 59 |
| 60 ACTION_P2(StopScreenRecorder, recorder, task) { |
| 61 recorder->Stop(task); |
| 62 } |
| 63 |
| 64 } // namespace |
| 65 |
26 static const int kWidth = 640; | 66 static const int kWidth = 640; |
27 static const int kHeight = 480; | 67 static const int kHeight = 480; |
28 static const media::VideoFrame::Format kFormat = media::VideoFrame::RGB32; | 68 static const media::VideoFrame::Format kFormat = media::VideoFrame::RGB32; |
29 static const VideoPacketFormat::Encoding kEncoding = | 69 static const VideoPacketFormat::Encoding kEncoding = |
30 VideoPacketFormat::ENCODING_VERBATIM; | 70 VideoPacketFormat::ENCODING_VERBATIM; |
31 | 71 |
32 class ScreenRecorderTest : public testing::Test { | 72 class ScreenRecorderTest : public testing::Test { |
33 public: | 73 public: |
34 ScreenRecorderTest() { | 74 ScreenRecorderTest() { |
35 } | 75 } |
(...skipping 13 matching lines...) Expand all Loading... |
49 scoped_refptr<MockConnectionToClient> connection_; | 89 scoped_refptr<MockConnectionToClient> connection_; |
50 | 90 |
51 // The following mock objects are owned by ScreenRecorder. | 91 // The following mock objects are owned by ScreenRecorder. |
52 MockCapturer* capturer_; | 92 MockCapturer* capturer_; |
53 MockEncoder* encoder_; | 93 MockEncoder* encoder_; |
54 MessageLoop message_loop_; | 94 MessageLoop message_loop_; |
55 private: | 95 private: |
56 DISALLOW_COPY_AND_ASSIGN(ScreenRecorderTest); | 96 DISALLOW_COPY_AND_ASSIGN(ScreenRecorderTest); |
57 }; | 97 }; |
58 | 98 |
59 ACTION_P2(RunCallback, rects, data) { | 99 // This test mocks capturer, encoder and network layer to operate one recording |
60 InvalidRects& dirty_rects = data->mutable_dirty_rects(); | 100 // cycle. |
61 InvalidRects temp_rects; | |
62 std::set_union(dirty_rects.begin(), dirty_rects.end(), | |
63 rects.begin(), rects.end(), | |
64 std::inserter(temp_rects, temp_rects.begin())); | |
65 dirty_rects.swap(temp_rects); | |
66 arg0->Run(data); | |
67 delete arg0; | |
68 } | |
69 | |
70 ACTION_P(FinishEncode, msg) { | |
71 arg2->Run(msg); | |
72 delete arg2; | |
73 } | |
74 | |
75 TEST_F(ScreenRecorderTest, OneRecordCycle) { | 101 TEST_F(ScreenRecorderTest, OneRecordCycle) { |
76 InvalidRects update_rects; | 102 InvalidRects update_rects; |
77 update_rects.insert(gfx::Rect(0, 0, 10, 10)); | 103 update_rects.insert(gfx::Rect(0, 0, 10, 10)); |
78 DataPlanes planes; | 104 DataPlanes planes; |
79 for (int i = 0; i < DataPlanes::kPlaneCount; ++i) { | 105 for (int i = 0; i < DataPlanes::kPlaneCount; ++i) { |
80 planes.data[i] = reinterpret_cast<uint8*>(i); | 106 planes.data[i] = reinterpret_cast<uint8*>(i); |
81 planes.strides[i] = kWidth * 4; | 107 planes.strides[i] = kWidth * 4; |
82 } | 108 } |
83 scoped_refptr<CaptureData> data(new CaptureData(planes, kWidth, | 109 scoped_refptr<CaptureData> data(new CaptureData(planes, kWidth, |
84 kHeight, kFormat)); | 110 kHeight, kFormat)); |
85 // Set the recording rate to very low to avoid capture twice. | |
86 record_->SetMaxRate(0.01); | |
87 | |
88 // Add the mock client connection to the session. | |
89 EXPECT_CALL(*capturer_, width()).WillRepeatedly(Return(kWidth)); | 111 EXPECT_CALL(*capturer_, width()).WillRepeatedly(Return(kWidth)); |
90 EXPECT_CALL(*capturer_, height()).WillRepeatedly(Return(kHeight)); | 112 EXPECT_CALL(*capturer_, height()).WillRepeatedly(Return(kHeight)); |
91 record_->AddConnection(connection_); | |
92 | 113 |
93 // First the capturer is called. | 114 // First the capturer is called. |
94 EXPECT_CALL(*capturer_, CaptureInvalidRects(NotNull())) | 115 EXPECT_CALL(*capturer_, CaptureInvalidRects(NotNull())) |
95 .WillOnce(RunCallback(update_rects, data)); | 116 .WillOnce(RunCallback(update_rects, data)); |
96 | 117 |
97 // Expect the encoder be called. | 118 // Expect the encoder be called. |
98 VideoPacket* packet = new VideoPacket(); | |
99 EXPECT_CALL(*encoder_, Encode(data, false, NotNull())) | 119 EXPECT_CALL(*encoder_, Encode(data, false, NotNull())) |
100 .WillOnce(FinishEncode(packet)); | 120 .WillOnce(FinishEncode()); |
101 | 121 |
102 MockVideoStub video_stub; | 122 MockVideoStub video_stub; |
103 EXPECT_CALL(*connection_, video_stub()) | 123 EXPECT_CALL(*connection_, video_stub()) |
104 .WillRepeatedly(Return(&video_stub)); | 124 .WillRepeatedly(Return(&video_stub)); |
105 | 125 |
106 Task* done_task = NULL; | |
107 | |
108 // Expect the client be notified. | 126 // Expect the client be notified. |
109 EXPECT_CALL(video_stub, ProcessVideoPacket(_, _)) | 127 EXPECT_CALL(video_stub, ProcessVideoPacket(_, _)) |
110 .Times(1) | 128 .Times(1) |
111 .WillOnce(SaveArg<1>(&done_task)); | 129 .WillOnce(DoAll(DeleteArg<0>(), DeleteArg<1>())); |
112 EXPECT_CALL(video_stub, GetPendingPackets()) | 130 EXPECT_CALL(video_stub, GetPendingPackets()) |
113 .Times(AtLeast(0)) | 131 .Times(AtLeast(0)) |
114 .WillRepeatedly(Return(0)); | 132 .WillRepeatedly(Return(0)); |
115 | 133 |
| 134 // Set the recording rate to very low to avoid capture twice. |
| 135 record_->SetMaxRate(0.01); |
| 136 |
| 137 // Add the mock client connection to the session. |
| 138 record_->AddConnection(connection_); |
| 139 |
116 // Start the recording. | 140 // Start the recording. |
117 record_->Start(); | 141 record_->Start(); |
118 | 142 |
119 // Make sure all tasks are completed. | 143 // Make sure all tasks are completed. |
120 message_loop_.RunAllPending(); | 144 message_loop_.RunAllPending(); |
| 145 } |
121 | 146 |
122 done_task->Run(); | 147 // This test mocks capturer, encoder and network layer to simulate one recording |
123 delete done_task; | 148 // cycle. When the first encoded packet is submitted to the network |
| 149 // ScreenRecorder is instructed to come to a complete stop. We expect the stop |
| 150 // sequence to be executed successfully. |
| 151 TEST_F(ScreenRecorderTest, StartAndStop) { |
| 152 InvalidRects update_rects; |
| 153 update_rects.insert(gfx::Rect(0, 0, 10, 10)); |
| 154 DataPlanes planes; |
| 155 for (int i = 0; i < DataPlanes::kPlaneCount; ++i) { |
| 156 planes.data[i] = reinterpret_cast<uint8*>(i); |
| 157 planes.strides[i] = kWidth * 4; |
| 158 } |
| 159 scoped_refptr<CaptureData> data(new CaptureData(planes, kWidth, |
| 160 kHeight, kFormat)); |
| 161 EXPECT_CALL(*capturer_, width()).WillRepeatedly(Return(kWidth)); |
| 162 EXPECT_CALL(*capturer_, height()).WillRepeatedly(Return(kHeight)); |
| 163 |
| 164 // First the capturer is called. |
| 165 EXPECT_CALL(*capturer_, CaptureInvalidRects(NotNull())) |
| 166 .WillRepeatedly(RunCallback(update_rects, data)); |
| 167 |
| 168 // Expect the encoder be called. |
| 169 EXPECT_CALL(*encoder_, Encode(data, false, NotNull())) |
| 170 .WillRepeatedly(FinishEncode()); |
| 171 |
| 172 MockVideoStub video_stub; |
| 173 EXPECT_CALL(*connection_, video_stub()) |
| 174 .WillRepeatedly(Return(&video_stub)); |
| 175 |
| 176 // By default delete the arguments when ProcessVideoPacket is received. |
| 177 EXPECT_CALL(video_stub, ProcessVideoPacket(_, _)) |
| 178 .WillRepeatedly(FinishSend()); |
| 179 |
| 180 // For the first time when ProcessVideoPacket is received we stop the |
| 181 // ScreenRecorder. |
| 182 EXPECT_CALL(video_stub, ProcessVideoPacket(_, _)) |
| 183 .WillOnce(DoAll( |
| 184 FinishSend(), |
| 185 StopScreenRecorder(record_, |
| 186 NewRunnableFunction(&QuitMessageLoop, |
| 187 &message_loop_)))) |
| 188 .RetiresOnSaturation(); |
| 189 |
| 190 // Add the mock client connection to the session. |
| 191 record_->AddConnection(connection_); |
| 192 |
| 193 // Start the recording. |
| 194 record_->Start(); |
| 195 message_loop_.Run(); |
124 } | 196 } |
125 | 197 |
126 // TODO(hclam): Add test for double buffering. | 198 // TODO(hclam): Add test for double buffering. |
127 // TODO(hclam): Add test for multiple captures. | 199 // TODO(hclam): Add test for multiple captures. |
128 // TODO(hclam): Add test for interruption. | |
129 | 200 |
130 } // namespace remoting | 201 } // namespace remoting |
OLD | NEW |