Move ScreenCapturer 'real' tests out of screen_capturer_unittest.cc.

This is a trivial change, I just cutted and pasted part of the code in
screen_capturer_unittest.cc to screen_capturer_integration_test.cc, removed
DISABLED_ prefixes, and updated build file.

BUG=webrtc:6366

Review-Url: https://codereview.webrtc.org/2444583002
Cr-Commit-Position: refs/heads/master@{#14806}
This commit is contained in:
zijiehe 2016-10-27 16:50:35 -07:00 committed by Commit bot
parent 32bcaf61f5
commit 6be0a657c5
6 changed files with 311 additions and 231 deletions

View File

@ -71,6 +71,7 @@ if (rtc_include_tests) {
"../system_wrappers",
"../test:test_support",
"../test:test_support_main",
"//testing/gmock",
"//testing/gtest",
]
@ -96,6 +97,11 @@ if (rtc_include_tests) {
"video_coding/codecs/vp8/test/vp8_impl_unittest.cc",
]
if (rtc_desktop_capture_supported) {
deps += [ "desktop_capture:desktop_capture_test_tools" ]
sources += [ "desktop_capture/screen_capturer_integration_test.cc" ]
}
data = modules_tests_resources
if (is_android) {
@ -534,7 +540,7 @@ if (rtc_include_tests) {
}
if (rtc_desktop_capture_supported) {
deps += [ "desktop_capture" ]
deps += [ "desktop_capture:desktop_capture_test_tools" ]
sources += [
"desktop_capture/desktop_and_cursor_composer_unittest.cc",
"desktop_capture/desktop_frame_generator.cc",
@ -543,20 +549,13 @@ if (rtc_include_tests) {
"desktop_capture/fake_screen_capturer.cc",
"desktop_capture/fake_screen_capturer.h",
"desktop_capture/mouse_cursor_monitor_unittest.cc",
"desktop_capture/rgba_color.cc",
"desktop_capture/rgba_color.h",
"desktop_capture/rgba_color_unittest.cc",
"desktop_capture/screen_capturer_differ_wrapper_unittest.cc",
"desktop_capture/screen_capturer_helper_unittest.cc",
"desktop_capture/screen_capturer_mac_unittest.cc",
"desktop_capture/screen_capturer_mock_objects.h",
"desktop_capture/screen_capturer_unittest.cc",
"desktop_capture/screen_drawer.cc",
"desktop_capture/screen_drawer.h",
"desktop_capture/screen_drawer_linux.cc",
"desktop_capture/screen_drawer_mac.cc",
"desktop_capture/screen_drawer_unittest.cc",
"desktop_capture/screen_drawer_win.cc",
"desktop_capture/win/cursor_unittest.cc",
"desktop_capture/win/cursor_unittest_resources.h",
"desktop_capture/win/cursor_unittest_resources.rc",

View File

@ -30,6 +30,26 @@ rtc_static_library("primitives") {
]
}
if (rtc_include_tests) {
source_set("desktop_capture_test_tools") {
testonly = true
public_deps = [
":desktop_capture",
]
sources = [
"rgba_color.cc",
"rgba_color.h",
"screen_drawer.cc",
"screen_drawer.h",
"screen_drawer_linux.cc",
"screen_drawer_mac.cc",
"screen_drawer_win.cc",
]
}
}
rtc_static_library("desktop_capture") {
sources = [
"cropped_desktop_frame.cc",

View File

@ -0,0 +1,277 @@
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <string.h>
#include <algorithm>
#include <initializer_list>
#include <memory>
#include <utility>
#include "webrtc/modules/desktop_capture/screen_capturer.h"
#include "webrtc/test/gmock.h"
#include "webrtc/test/gtest.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/logging.h"
#include "webrtc/modules/desktop_capture/rgba_color.h"
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "webrtc/modules/desktop_capture/desktop_frame.h"
#include "webrtc/modules/desktop_capture/desktop_region.h"
#include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
#include "webrtc/modules/desktop_capture/screen_drawer.h"
#if defined(WEBRTC_WIN)
#include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
#endif // defined(WEBRTC_WIN)
using ::testing::_;
namespace webrtc {
namespace {
ACTION_P(SaveUniquePtrArg, dest) {
*dest = std::move(*arg1);
}
// Returns true if color in |rect| of |frame| is |color|.
bool ArePixelsColoredBy(const DesktopFrame& frame,
DesktopRect rect,
RgbaColor color,
bool may_partially_draw) {
if (!may_partially_draw) {
// updated_region() should cover the painted area.
DesktopRegion updated_region(frame.updated_region());
updated_region.IntersectWith(rect);
if (!updated_region.Equals(DesktopRegion(rect))) {
return false;
}
}
// Color in the |rect| should be |color|.
uint8_t* row = frame.GetFrameDataAtPos(rect.top_left());
for (int i = 0; i < rect.height(); i++) {
uint8_t* column = row;
for (int j = 0; j < rect.width(); j++) {
if (color != RgbaColor(column)) {
return false;
}
column += DesktopFrame::kBytesPerPixel;
}
row += frame.stride();
}
return true;
}
} // namespace
class ScreenCapturerIntegrationTest : public testing::Test {
public:
void SetUp() override {
capturer_.reset(
ScreenCapturer::Create(DesktopCaptureOptions::CreateDefault()));
}
protected:
void TestCaptureUpdatedRegion(
std::initializer_list<ScreenCapturer*> capturers) {
RTC_DCHECK(capturers.size() > 0);
// A large enough area for the tests, which should be able to fulfill by
// most of systems.
const int kTestArea = 512;
const int kRectSize = 32;
std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create();
if (!drawer || drawer->DrawableRegion().is_empty()) {
LOG(LS_WARNING) << "No ScreenDrawer implementation for current platform.";
return;
}
if (drawer->DrawableRegion().width() < kTestArea ||
drawer->DrawableRegion().height() < kTestArea) {
LOG(LS_WARNING) << "ScreenDrawer::DrawableRegion() is too small for the "
"CaptureUpdatedRegion tests.";
return;
}
for (ScreenCapturer* capturer : capturers) {
capturer->Start(&callback_);
}
// Draw a set of |kRectSize| by |kRectSize| rectangles at (|i|, |i|), or
// |i| by |i| rectangles at (|kRectSize|, |kRectSize|). One of (controlled
// by |c|) its primary colors is |i|, and the other two are 0x7f. So we
// won't draw a black or white rectangle.
for (int c = 0; c < 3; c++) {
// A fixed size rectangle.
for (int i = 0; i < kTestArea - kRectSize; i += 16) {
DesktopRect rect = DesktopRect::MakeXYWH(i, i, kRectSize, kRectSize);
rect.Translate(drawer->DrawableRegion().top_left());
RgbaColor color((c == 0 ? (i & 0xff) : 0x7f),
(c == 1 ? (i & 0xff) : 0x7f),
(c == 2 ? (i & 0xff) : 0x7f));
TestCaptureOneFrame(capturers, drawer.get(), rect, color);
}
// A variable-size rectangle.
for (int i = 0; i < kTestArea - kRectSize; i += 16) {
DesktopRect rect = DesktopRect::MakeXYWH(kRectSize, kRectSize, i, i);
rect.Translate(drawer->DrawableRegion().top_left());
RgbaColor color((c == 0 ? (i & 0xff) : 0x7f),
(c == 1 ? (i & 0xff) : 0x7f),
(c == 2 ? (i & 0xff) : 0x7f));
TestCaptureOneFrame(capturers, drawer.get(), rect, color);
}
}
}
void TestCaptureUpdatedRegion() {
TestCaptureUpdatedRegion({capturer_.get()});
}
#if defined(WEBRTC_WIN)
// Enable allow_directx_capturer in DesktopCaptureOptions, but let
// ScreenCapturer::Create to decide whether a DirectX capturer should be used.
void MaybeCreateDirectxCapturer() {
DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault());
options.set_allow_directx_capturer(true);
capturer_.reset(ScreenCapturer::Create(options));
}
bool CreateDirectxCapturer() {
if (!ScreenCapturerWinDirectx::IsSupported()) {
LOG(LS_WARNING) << "Directx capturer is not supported";
return false;
}
MaybeCreateDirectxCapturer();
return true;
}
void CreateMagnifierCapturer() {
DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault());
options.set_allow_use_magnification_api(true);
capturer_.reset(ScreenCapturer::Create(options));
}
#endif // defined(WEBRTC_WIN)
std::unique_ptr<ScreenCapturer> capturer_;
MockScreenCapturerCallback callback_;
private:
// Repeats capturing the frame by using |capturers| one-by-one for 600 times,
// typically 30 seconds, until they succeeded captured a |color| rectangle at
// |rect|. This function uses |drawer|->WaitForPendingDraws() between two
// attempts to wait for the screen to update.
void TestCaptureOneFrame(std::vector<ScreenCapturer*> capturers,
ScreenDrawer* drawer,
DesktopRect rect,
RgbaColor color) {
const int wait_capture_round = 600;
drawer->Clear();
size_t succeeded_capturers = 0;
for (int i = 0; i < wait_capture_round; i++) {
drawer->DrawRectangle(rect, color);
drawer->WaitForPendingDraws();
for (size_t j = 0; j < capturers.size(); j++) {
if (capturers[j] == nullptr) {
// ScreenCapturer should return an empty updated_region() if no
// update detected. So we won't test it again if it has captured
// the rectangle we drew.
continue;
}
std::unique_ptr<DesktopFrame> frame = CaptureFrame(capturers[j]);
if (!frame) {
// CaptureFrame() has triggered an assertion failure already, we
// only need to return here.
return;
}
if (ArePixelsColoredBy(
*frame, rect, color, drawer->MayDrawIncompleteShapes())) {
capturers[j] = nullptr;
succeeded_capturers++;
}
}
if (succeeded_capturers == capturers.size()) {
break;
}
}
ASSERT_EQ(succeeded_capturers, capturers.size());
}
// Expects |capturer| to successfully capture a frame, and returns it.
std::unique_ptr<DesktopFrame> CaptureFrame(ScreenCapturer* capturer) {
std::unique_ptr<DesktopFrame> frame;
EXPECT_CALL(callback_,
OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
.WillOnce(SaveUniquePtrArg(&frame));
capturer->CaptureFrame();
EXPECT_TRUE(frame);
return frame;
}
};
TEST_F(ScreenCapturerIntegrationTest, CaptureUpdatedRegion) {
TestCaptureUpdatedRegion();
}
TEST_F(ScreenCapturerIntegrationTest, TwoCapturers) {
std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
SetUp();
TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
}
#if defined(WEBRTC_WIN)
TEST_F(ScreenCapturerIntegrationTest, CaptureUpdatedRegionWithDirectxCapturer) {
if (!CreateDirectxCapturer()) {
return;
}
TestCaptureUpdatedRegion();
}
TEST_F(ScreenCapturerIntegrationTest, TwoDirectxCapturers) {
if (!CreateDirectxCapturer()) {
return;
}
std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
RTC_CHECK(CreateDirectxCapturer());
TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
}
TEST_F(ScreenCapturerIntegrationTest,
CaptureUpdatedRegionWithMagnifierCapturer) {
CreateMagnifierCapturer();
TestCaptureUpdatedRegion();
}
TEST_F(ScreenCapturerIntegrationTest, TwoMagnifierCapturers) {
CreateMagnifierCapturer();
std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
CreateMagnifierCapturer();
TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
}
TEST_F(ScreenCapturerIntegrationTest,
MaybeCaptureUpdatedRegionWithDirectxCapturer) {
// Even DirectX capturer is not supported in current system, we should be able
// to select a usable capturer.
MaybeCreateDirectxCapturer();
TestCaptureUpdatedRegion();
}
#endif // defined(WEBRTC_WIN)
} // namespace webrtc

View File

@ -8,77 +8,29 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include <string.h>
#include <algorithm>
#include <initializer_list>
#include <memory>
#include <utility>
#include "webrtc/modules/desktop_capture/screen_capturer.h"
#include "webrtc/test/gmock.h"
#include "webrtc/test/gtest.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/logging.h"
#include "webrtc/modules/desktop_capture/rgba_color.h"
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "webrtc/modules/desktop_capture/desktop_frame.h"
#include "webrtc/modules/desktop_capture/desktop_region.h"
#include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
#include "webrtc/modules/desktop_capture/screen_drawer.h"
#include "webrtc/system_wrappers/include/sleep.h"
#if defined(WEBRTC_WIN)
#include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
#endif // defined(WEBRTC_WIN)
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Return;
const int kTestSharedMemoryId = 123;
namespace webrtc {
namespace {
ACTION_P(SaveUniquePtrArg, dest) {
*dest = std::move(*arg1);
}
// Returns true if color in |rect| of |frame| is |color|.
bool ArePixelsColoredBy(const DesktopFrame& frame,
DesktopRect rect,
RgbaColor color,
bool may_partially_draw) {
if (!may_partially_draw) {
// updated_region() should cover the painted area.
DesktopRegion updated_region(frame.updated_region());
updated_region.IntersectWith(rect);
if (!updated_region.Equals(DesktopRegion(rect))) {
return false;
}
}
// Color in the |rect| should be |color|.
uint8_t* row = frame.GetFrameDataAtPos(rect.top_left());
for (int i = 0; i < rect.height(); i++) {
uint8_t* column = row;
for (int j = 0; j < rect.width(); j++) {
if (color != RgbaColor(column)) {
return false;
}
column += DesktopFrame::kBytesPerPixel;
}
row += frame.stride();
}
return true;
}
} // namespace
class ScreenCapturerTest : public testing::Test {
public:
void SetUp() override {
@ -87,60 +39,6 @@ class ScreenCapturerTest : public testing::Test {
}
protected:
void TestCaptureUpdatedRegion(
std::initializer_list<ScreenCapturer*> capturers) {
RTC_DCHECK(capturers.size() > 0);
// A large enough area for the tests, which should be able to fulfill by
// most of systems.
const int kTestArea = 512;
const int kRectSize = 32;
std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create();
if (!drawer || drawer->DrawableRegion().is_empty()) {
LOG(LS_WARNING) << "No ScreenDrawer implementation for current platform.";
return;
}
if (drawer->DrawableRegion().width() < kTestArea ||
drawer->DrawableRegion().height() < kTestArea) {
LOG(LS_WARNING) << "ScreenDrawer::DrawableRegion() is too small for the "
"CaptureUpdatedRegion tests.";
return;
}
for (ScreenCapturer* capturer : capturers) {
capturer->Start(&callback_);
}
// Draw a set of |kRectSize| by |kRectSize| rectangles at (|i|, |i|), or
// |i| by |i| rectangles at (|kRectSize|, |kRectSize|). One of (controlled
// by |c|) its primary colors is |i|, and the other two are 0x7f. So we
// won't draw a black or white rectangle.
for (int c = 0; c < 3; c++) {
// A fixed size rectangle.
for (int i = 0; i < kTestArea - kRectSize; i += 16) {
DesktopRect rect = DesktopRect::MakeXYWH(i, i, kRectSize, kRectSize);
rect.Translate(drawer->DrawableRegion().top_left());
RgbaColor color((c == 0 ? (i & 0xff) : 0x7f),
(c == 1 ? (i & 0xff) : 0x7f),
(c == 2 ? (i & 0xff) : 0x7f));
TestCaptureOneFrame(capturers, drawer.get(), rect, color);
}
// A variable-size rectangle.
for (int i = 0; i < kTestArea - kRectSize; i += 16) {
DesktopRect rect = DesktopRect::MakeXYWH(kRectSize, kRectSize, i, i);
rect.Translate(drawer->DrawableRegion().top_left());
RgbaColor color((c == 0 ? (i & 0xff) : 0x7f),
(c == 1 ? (i & 0xff) : 0x7f),
(c == 2 ? (i & 0xff) : 0x7f));
TestCaptureOneFrame(capturers, drawer.get(), rect, color);
}
}
}
void TestCaptureUpdatedRegion() {
TestCaptureUpdatedRegion({capturer_.get()});
}
#if defined(WEBRTC_WIN)
// Enable allow_directx_capturer in DesktopCaptureOptions, but let
// ScreenCapturer::Create to decide whether a DirectX capturer should be used.
@ -169,61 +67,6 @@ class ScreenCapturerTest : public testing::Test {
std::unique_ptr<ScreenCapturer> capturer_;
MockScreenCapturerCallback callback_;
private:
// Repeats capturing the frame by using |capturers| one-by-one for 600 times,
// typically 30 seconds, until they succeeded captured a |color| rectangle at
// |rect|. This function uses |drawer|->WaitForPendingDraws() between two
// attempts to wait for the screen to update.
void TestCaptureOneFrame(std::vector<ScreenCapturer*> capturers,
ScreenDrawer* drawer,
DesktopRect rect,
RgbaColor color) {
const int wait_capture_round = 600;
drawer->Clear();
size_t succeeded_capturers = 0;
for (int i = 0; i < wait_capture_round; i++) {
drawer->DrawRectangle(rect, color);
drawer->WaitForPendingDraws();
for (size_t j = 0; j < capturers.size(); j++) {
if (capturers[j] == nullptr) {
// ScreenCapturer should return an empty updated_region() if no
// update detected. So we won't test it again if it has captured
// the rectangle we drew.
continue;
}
std::unique_ptr<DesktopFrame> frame = CaptureFrame(capturers[j]);
if (!frame) {
// CaptureFrame() has triggered an assertion failure already, we
// only need to return here.
return;
}
if (ArePixelsColoredBy(
*frame, rect, color, drawer->MayDrawIncompleteShapes())) {
capturers[j] = nullptr;
succeeded_capturers++;
}
}
if (succeeded_capturers == capturers.size()) {
break;
}
}
ASSERT_EQ(succeeded_capturers, capturers.size());
}
// Expects |capturer| to successfully capture a frame, and returns it.
std::unique_ptr<DesktopFrame> CaptureFrame(ScreenCapturer* capturer) {
std::unique_ptr<DesktopFrame> frame;
EXPECT_CALL(callback_,
OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
.WillOnce(SaveUniquePtrArg(&frame));
capturer->CaptureFrame();
EXPECT_TRUE(frame);
return frame;
}
};
class FakeSharedMemory : public SharedMemory {
@ -254,11 +97,15 @@ class FakeSharedMemoryFactory : public SharedMemoryFactory {
RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemoryFactory);
};
ACTION_P(SaveUniquePtrArg, dest) {
*dest = std::move(*arg1);
}
TEST_F(ScreenCapturerTest, GetScreenListAndSelectScreen) {
webrtc::ScreenCapturer::ScreenList screens;
EXPECT_TRUE(capturer_->GetScreenList(&screens));
for (webrtc::ScreenCapturer::ScreenList::iterator it = screens.begin();
it != screens.end(); ++it) {
it != screens.end(); ++it) {
EXPECT_TRUE(capturer_->SelectScreen(it->id));
}
}
@ -293,20 +140,6 @@ TEST_F(ScreenCapturerTest, Capture) {
EXPECT_TRUE(it.IsAtEnd());
}
// Disabled due to being flaky due to the fact that it uses rendering / UI, see
// webrtc/6366.
TEST_F(ScreenCapturerTest, DISABLED_CaptureUpdatedRegion) {
TestCaptureUpdatedRegion();
}
// Disabled due to being flaky due to the fact that it uses rendering / UI, see
// webrtc/6366.
TEST_F(ScreenCapturerTest, DISABLED_TwoCapturers) {
std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
SetUp();
TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
}
#if defined(WEBRTC_WIN)
TEST_F(ScreenCapturerTest, UseSharedBuffers) {
@ -327,7 +160,6 @@ TEST_F(ScreenCapturerTest, UseSharedBuffers) {
TEST_F(ScreenCapturerTest, UseMagnifier) {
CreateMagnifierCapturer();
std::unique_ptr<DesktopFrame> frame;
EXPECT_CALL(callback_,
OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
@ -372,54 +204,6 @@ TEST_F(ScreenCapturerTest, UseDirectxCapturerWithSharedBuffers) {
EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId);
}
// Disabled due to being flaky due to the fact that it uses rendering / UI, see
// webrtc/6366.
TEST_F(ScreenCapturerTest, DISABLED_CaptureUpdatedRegionWithDirectxCapturer) {
if (!CreateDirectxCapturer()) {
return;
}
TestCaptureUpdatedRegion();
}
// Disabled due to being flaky due to the fact that it uses rendering / UI, see
// webrtc/6366.
TEST_F(ScreenCapturerTest, DISABLED_TwoDirectxCapturers) {
if (!CreateDirectxCapturer()) {
return;
}
std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
RTC_CHECK(CreateDirectxCapturer());
TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
}
// Disabled due to being flaky due to the fact that it uses rendering / UI, see
// webrtc/6366.
TEST_F(ScreenCapturerTest, DISABLED_CaptureUpdatedRegionWithMagnifierCapturer) {
CreateMagnifierCapturer();
TestCaptureUpdatedRegion();
}
// Disabled due to being flaky due to the fact that it uses rendering / UI, see
// webrtc/6366.
TEST_F(ScreenCapturerTest, DISABLED_TwoMagnifierCapturers) {
CreateMagnifierCapturer();
std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
CreateMagnifierCapturer();
TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
}
// Disabled due to being flaky due to the fact that it uses rendering / UI, see
// webrtc/6366.
TEST_F(ScreenCapturerTest,
DISABLED_MaybeCaptureUpdatedRegionWithDirectxCapturer) {
// Even DirectX capturer is not supported in current system, we should be able
// to select a usable capturer.
MaybeCreateDirectxCapturer();
TestCaptureUpdatedRegion();
}
#endif // defined(WEBRTC_WIN)
} // namespace webrtc

View File

@ -30,7 +30,7 @@ static constexpr char kSemaphoreName[] =
class ScreenDrawerLockLinux : public ScreenDrawerLock {
public:
ScreenDrawerLockLinux();
~ScreenDrawerLockLinux();
~ScreenDrawerLockLinux() override;
private:
sem_t* semaphore_;

View File

@ -25,7 +25,7 @@ static constexpr TCHAR kMutexName[] =
class ScreenDrawerLockWin : public ScreenDrawerLock {
public:
ScreenDrawerLockWin();
~ScreenDrawerLockWin();
~ScreenDrawerLockWin() override;
private:
HANDLE mutex_;