This source file includes following definitions.
- CreateOutput
- num_calls_update_xrandr_config
- num_calls_notify_observers
- set_cached_outputs
- num_calls_notify_observers_
- UpdateXRandRConfiguration
- GetCachedOutputs
- NotifyDisplayObservers
- test_tick_clock_
- DispatchScreenChangeEvent
- DispatchOutputChangeEvent
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include <X11/extensions/Xrandr.h>
#undef Bool
#undef None
#include "base/test/simple_test_tick_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/display/chromeos/x11/display_mode_x11.h"
#include "ui/display/chromeos/x11/display_snapshot_x11.h"
#include "ui/display/chromeos/x11/native_display_delegate_x11.h"
#include "ui/display/chromeos/x11/native_display_event_dispatcher_x11.h"
namespace ui {
namespace {
const DisplayModeX11 kDefaultDisplayMode(gfx::Size(1, 1), false, 60.0f, 20);
DisplaySnapshotX11* CreateOutput(RROutput output, RRCrtc crtc) {
DisplaySnapshotX11* snapshot = new DisplaySnapshotX11(
0,
false,
gfx::Point(0, 0),
gfx::Size(0, 0),
OUTPUT_TYPE_UNKNOWN,
false,
false,
std::string(),
std::vector<const DisplayMode*>(1, &kDefaultDisplayMode),
&kDefaultDisplayMode,
NULL,
output,
crtc,
0);
return snapshot;
}
class TestHelperDelegate : public NativeDisplayDelegateX11::HelperDelegate {
public:
TestHelperDelegate();
virtual ~TestHelperDelegate();
int num_calls_update_xrandr_config() const {
return num_calls_update_xrandr_config_;
}
int num_calls_notify_observers() const { return num_calls_notify_observers_; }
void set_cached_outputs(const std::vector<DisplaySnapshot*>& outputs) {
cached_outputs_ = outputs;
}
virtual void UpdateXRandRConfiguration(const base::NativeEvent& event)
OVERRIDE;
virtual const std::vector<DisplaySnapshot*>& GetCachedOutputs() const
OVERRIDE;
virtual void NotifyDisplayObservers() OVERRIDE;
private:
int num_calls_update_xrandr_config_;
int num_calls_notify_observers_;
std::vector<DisplaySnapshot*> cached_outputs_;
DISALLOW_COPY_AND_ASSIGN(TestHelperDelegate);
};
TestHelperDelegate::TestHelperDelegate()
: num_calls_update_xrandr_config_(0), num_calls_notify_observers_(0) {}
TestHelperDelegate::~TestHelperDelegate() {}
void TestHelperDelegate::UpdateXRandRConfiguration(
const base::NativeEvent& event) {
++num_calls_update_xrandr_config_;
}
const std::vector<DisplaySnapshot*>& TestHelperDelegate::GetCachedOutputs()
const {
return cached_outputs_;
}
void TestHelperDelegate::NotifyDisplayObservers() {
++num_calls_notify_observers_;
}
class NativeDisplayEventDispatcherX11Test : public testing::Test {
public:
NativeDisplayEventDispatcherX11Test();
virtual ~NativeDisplayEventDispatcherX11Test();
protected:
void DispatchScreenChangeEvent();
void DispatchOutputChangeEvent(RROutput output,
RRCrtc crtc,
RRMode mode,
bool connected);
int xrandr_event_base_;
scoped_ptr<TestHelperDelegate> helper_delegate_;
scoped_ptr<NativeDisplayEventDispatcherX11> dispatcher_;
base::SimpleTestTickClock* test_tick_clock_;
private:
DISALLOW_COPY_AND_ASSIGN(NativeDisplayEventDispatcherX11Test);
};
NativeDisplayEventDispatcherX11Test::NativeDisplayEventDispatcherX11Test()
: xrandr_event_base_(10),
helper_delegate_(new TestHelperDelegate()),
dispatcher_(new NativeDisplayEventDispatcherX11(helper_delegate_.get(),
xrandr_event_base_)),
test_tick_clock_(new base::SimpleTestTickClock) {
test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(1));
dispatcher_->SetTickClockForTest(
scoped_ptr<base::TickClock>(test_tick_clock_));
}
NativeDisplayEventDispatcherX11Test::~NativeDisplayEventDispatcherX11Test() {}
void NativeDisplayEventDispatcherX11Test::DispatchScreenChangeEvent() {
XRRScreenChangeNotifyEvent event = {0};
event.type = xrandr_event_base_ + RRScreenChangeNotify;
dispatcher_->Dispatch(reinterpret_cast<const base::NativeEvent>(&event));
}
void NativeDisplayEventDispatcherX11Test::DispatchOutputChangeEvent(
RROutput output,
RRCrtc crtc,
RRMode mode,
bool connected) {
XRROutputChangeNotifyEvent event = {0};
event.type = xrandr_event_base_ + RRNotify;
event.subtype = RRNotify_OutputChange;
event.output = output;
event.crtc = crtc;
event.mode = mode;
event.connection = connected ? RR_Connected : RR_Disconnected;
dispatcher_->Dispatch(reinterpret_cast<const base::NativeEvent>(&event));
}
}
TEST_F(NativeDisplayEventDispatcherX11Test, OnScreenChangedEvent) {
DispatchScreenChangeEvent();
EXPECT_EQ(1, helper_delegate_->num_calls_update_xrandr_config());
EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
}
TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnFirstEvent) {
DispatchOutputChangeEvent(1, 10, 20, true);
EXPECT_EQ(0, helper_delegate_->num_calls_update_xrandr_config());
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
}
TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationAfterSecondEvent) {
DispatchOutputChangeEvent(1, 10, 20, true);
ScopedVector<DisplaySnapshot> outputs;
outputs.push_back(CreateOutput(1, 10));
helper_delegate_->set_cached_outputs(outputs.get());
DispatchOutputChangeEvent(2, 11, 20, true);
EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
}
TEST_F(NativeDisplayEventDispatcherX11Test, AvoidNotificationOnDuplicateEvent) {
ScopedVector<DisplaySnapshot> outputs;
outputs.push_back(CreateOutput(1, 10));
helper_delegate_->set_cached_outputs(outputs.get());
DispatchOutputChangeEvent(1, 10, 20, true);
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
DispatchOutputChangeEvent(1, 10, 20, true);
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
}
TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnDisconnect) {
ScopedVector<DisplaySnapshot> outputs;
outputs.push_back(CreateOutput(1, 10));
helper_delegate_->set_cached_outputs(outputs.get());
DispatchOutputChangeEvent(1, 10, 20, false);
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
}
TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnModeChange) {
ScopedVector<DisplaySnapshot> outputs;
outputs.push_back(CreateOutput(1, 10));
helper_delegate_->set_cached_outputs(outputs.get());
DispatchOutputChangeEvent(1, 10, 21, true);
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
}
TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnSecondOutput) {
ScopedVector<DisplaySnapshot> outputs;
outputs.push_back(CreateOutput(1, 10));
helper_delegate_->set_cached_outputs(outputs.get());
DispatchOutputChangeEvent(2, 11, 20, true);
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
}
TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnDifferentCrtc) {
ScopedVector<DisplaySnapshot> outputs;
outputs.push_back(CreateOutput(1, 10));
helper_delegate_->set_cached_outputs(outputs.get());
DispatchOutputChangeEvent(1, 11, 20, true);
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
}
TEST_F(NativeDisplayEventDispatcherX11Test,
CheckNotificationOnSecondOutputDisconnect) {
ScopedVector<DisplaySnapshot> outputs;
outputs.push_back(CreateOutput(1, 10));
outputs.push_back(CreateOutput(2, 11));
helper_delegate_->set_cached_outputs(outputs.get());
DispatchOutputChangeEvent(2, 11, 20, false);
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
}
TEST_F(NativeDisplayEventDispatcherX11Test,
AvoidDuplicateNotificationOnSecondOutputDisconnect) {
ScopedVector<DisplaySnapshot> outputs;
outputs.push_back(CreateOutput(1, 10));
outputs.push_back(CreateOutput(2, 11));
helper_delegate_->set_cached_outputs(outputs.get());
DispatchOutputChangeEvent(2, 11, 20, false);
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
outputs.erase(outputs.begin() + 1);
helper_delegate_->set_cached_outputs(outputs.get());
DispatchOutputChangeEvent(2, 11, 20, false);
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
}
TEST_F(NativeDisplayEventDispatcherX11Test,
ForceUpdateAfterCacheExpiration) {
const int kHalfOfExpirationMs =
NativeDisplayEventDispatcherX11::kCachedOutputsExpirationMs / 2 + 1;
ScopedVector<DisplaySnapshot> outputs;
outputs.push_back(CreateOutput(1, 10));
outputs.push_back(CreateOutput(2, 11));
helper_delegate_->set_cached_outputs(outputs.get());
EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
DispatchOutputChangeEvent(2, 11, 20, true);
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
DispatchOutputChangeEvent(2, 11, 20, true);
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(
kHalfOfExpirationMs));
DispatchOutputChangeEvent(2, 11, 20, true);
EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
test_tick_clock_->Advance(
base::TimeDelta::FromMilliseconds(kHalfOfExpirationMs));
DispatchOutputChangeEvent(2, 11, 20, true);
EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
DispatchOutputChangeEvent(2, 11, 20, true);
EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(
kHalfOfExpirationMs));
DispatchOutputChangeEvent(2, 11, 20, true);
EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
}
}