blob: ef2eebda23b97195f62d468b2e7d313a0a7b0ae8 [file] [log] [blame]
// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "renderer/unix/gtk_window_base.h"
#include "renderer/unix/gtk_wrapper_mock.h"
#include "testing/base/public/gmock.h"
#include "testing/base/public/gunit.h"
using ::testing::DoAll;
using ::testing::Return;
using ::testing::SetArgPointee;
using ::testing::StrEq;
using ::testing::_;
namespace mozc {
namespace renderer {
namespace gtk {
namespace {
// Following variable is used testing and it is contant but due to API
// restriction, can not modify const modifier.
GtkWidget *kDummyWindow = reinterpret_cast<GtkWidget*>(0x12345678);
GtkWidget *kDummyCanvas = reinterpret_cast<GtkWidget*>(0x87654321);
GdkWindow *kDummyGdkWindow = reinterpret_cast<GdkWindow*>(0x29828374);
MATCHER_P(PointEq, expected_point, "The expected point does not match") {
return (arg.x == expected_point.x) && (arg.y == expected_point.y);
}
} // namespace
class GtkWindowBaseTest : public testing::Test {
protected:
GtkWrapperMock *GetGtkMock() {
GtkWrapperMock *mock = new GtkWrapperMock();
// Following functions are expected called by constructor.
EXPECT_CALL(*mock, GtkWindowNew(GTK_WINDOW_POPUP))
.WillOnce(Return(kDummyWindow));
EXPECT_CALL(*mock, GtkDrawingAreaNew()).WillOnce(Return(kDummyCanvas));
EXPECT_CALL(*mock, GSignalConnect(
kDummyWindow, StrEq("destroy"),
G_CALLBACK(GtkWindowBase::OnDestroyThunk), _));
EXPECT_CALL(*mock, GSignalConnect(
kDummyWindow, StrEq("button-press-event"),
G_CALLBACK(GtkWindowBase::OnMouseDownThunk), _));
EXPECT_CALL(*mock, GSignalConnect(
kDummyWindow, StrEq("button-release-event"),
G_CALLBACK(GtkWindowBase::OnMouseUpThunk), _));
EXPECT_CALL(*mock, GSignalConnect(
kDummyCanvas, StrEq("expose-event"),
G_CALLBACK(GtkWindowBase::OnPaintThunk), _));
EXPECT_CALL(*mock, GtkContainerAdd(kDummyWindow, kDummyCanvas));
EXPECT_CALL(*mock, GtkWidgetAddEvents(kDummyWindow, GDK_BUTTON_PRESS_MASK));
EXPECT_CALL(*mock, GtkWidgetAddEvents(kDummyWindow,
GDK_BUTTON_RELEASE_MASK));
EXPECT_CALL(*mock, GtkWidgetRealize(kDummyWindow));
EXPECT_CALL(*mock, GdkWindowSetTypeHint(kDummyWindow,
GDK_WINDOW_TYPE_HINT_POPUP_MENU));
return mock;
}
};
TEST_F(GtkWindowBaseTest, ShowWindowTest) {
GtkWrapperMock *mock = GetGtkMock();
EXPECT_CALL(*mock, GtkWidgetShowAll(kDummyWindow));
GtkWindowBase window(mock);
window.ShowWindow();
}
TEST_F(GtkWindowBaseTest, HideWindowTest) {
GtkWrapperMock *mock = GetGtkMock();
EXPECT_CALL(*mock, GtkWidgetHideAll(kDummyWindow));
GtkWindowBase window(mock);
window.HideWindow();
}
TEST_F(GtkWindowBaseTest, GetWindowWidgetTest) {
GtkWrapperMock *mock = GetGtkMock();
GtkWindowBase window(mock);
EXPECT_EQ(kDummyWindow, window.GetWindowWidget());
}
TEST_F(GtkWindowBaseTest, GetCanvasWidgetTest) {
GtkWrapperMock *mock = GetGtkMock();
GtkWindowBase window(mock);
EXPECT_EQ(kDummyCanvas, window.GetCanvasWidget());
}
TEST_F(GtkWindowBaseTest, GetWindowPosTest) {
GtkWrapperMock *mock = GetGtkMock();
const Point expected_pos(10, 20);
EXPECT_CALL(*mock, GtkWindowGetPosition(kDummyWindow, _, _)).
WillOnce(DoAll(SetArgPointee<1>(expected_pos.x),
SetArgPointee<2>(expected_pos.y)));
GtkWindowBase window(mock);
Point actual_pos = window.GetWindowPos();
EXPECT_EQ(expected_pos.x, actual_pos.x);
EXPECT_EQ(expected_pos.y, actual_pos.y);
}
TEST_F(GtkWindowBaseTest, GetWindowSizeTest) {
GtkWrapperMock *mock = GetGtkMock();
const Size expected_size(15, 25);
EXPECT_CALL(*mock, GtkWindowGetSize(kDummyWindow, _, _)).
WillOnce(DoAll(SetArgPointee<1>(expected_size.width),
SetArgPointee<2>(expected_size.height)));
GtkWindowBase window(mock);
Size actual_size = window.GetWindowSize();
EXPECT_EQ(expected_size.width, actual_size.width);
EXPECT_EQ(expected_size.height, actual_size.height);
}
TEST_F(GtkWindowBaseTest, GetWindowRectTest) {
GtkWrapperMock *mock = GetGtkMock();
const Rect expected_rect(10, 20, 15, 25);
EXPECT_CALL(*mock, GtkWindowGetPosition(kDummyWindow, _, _)).
WillOnce(DoAll(SetArgPointee<1>(expected_rect.origin.x),
SetArgPointee<2>(expected_rect.origin.y)));
EXPECT_CALL(*mock, GtkWindowGetSize(kDummyWindow, _, _)).
WillOnce(DoAll(SetArgPointee<1>(expected_rect.size.width),
SetArgPointee<2>(expected_rect.size.height)));
GtkWindowBase window(mock);
Rect actual_rect = window.GetWindowRect();
EXPECT_EQ(expected_rect.origin.x, actual_rect.origin.x);
EXPECT_EQ(expected_rect.origin.y, actual_rect.origin.y);
EXPECT_EQ(expected_rect.size.width, actual_rect.size.width);
EXPECT_EQ(expected_rect.size.height, actual_rect.size.height);
}
TEST_F(GtkWindowBaseTest, IsActiveTest) {
GtkWrapperMock *mock = GetGtkMock();
EXPECT_CALL(*mock, GtkWindowIsActive(kDummyWindow));
GtkWindowBase window(mock);
window.IsActive();
}
TEST_F(GtkWindowBaseTest, DestroyWindowTest) {
// TODO(nona): Implement this.
}
TEST_F(GtkWindowBaseTest, MoveTest) {
GtkWrapperMock *mock = GetGtkMock();
const Point pos(10, 20);
EXPECT_CALL(*mock, GtkWindowMove(kDummyWindow, pos.x, pos.y));
GtkWindowBase window(mock);
window.Move(pos);
}
TEST_F(GtkWindowBaseTest, ResizeTest) {
GtkWrapperMock *mock = GetGtkMock();
const Size size(15, 25);
EXPECT_CALL(*mock, GtkWindowResize(kDummyWindow, size.width, size.height));
GtkWindowBase window(mock);
window.Resize(size);
}
TEST_F(GtkWindowBaseTest, RedrawTest) {
GtkWrapperMock *mock = GetGtkMock();
const Size expected_size(15, 25);
EXPECT_CALL(*mock, GtkWindowGetSize(kDummyWindow, _, _)).
WillOnce(DoAll(SetArgPointee<1>(expected_size.width),
SetArgPointee<2>(expected_size.height)));
EXPECT_CALL(*mock, GtkWidgetQueueDrawArea(kDummyWindow,
0,
0,
expected_size.width,
expected_size.height));
GtkWindowBase window(mock);
window.Redraw();
}
class OverriddenCallTestableGtkWindowBase : public GtkWindowBase {
public:
explicit OverriddenCallTestableGtkWindowBase(GtkWrapperInterface *gtk)
: GtkWindowBase(gtk) {}
MOCK_METHOD1(OnMouseLeftDown, void(const Point &pos));
MOCK_METHOD1(OnMouseLeftUp, void(const Point &pos));
MOCK_METHOD1(OnMouseRightDown, void(const Point &pos));
MOCK_METHOD1(OnMouseRightUp, void(const Point &pos));
};
TEST_F(GtkWindowBaseTest, LeftRightTest) {
const Point expected_pos(10, 15);
{
SCOPED_TRACE("Left button is pressed, then call OnMouseLeftDown");
GtkWrapperMock *mock = GetGtkMock();
GdkEventButton event;
event.window = kDummyGdkWindow;
event.x = static_cast<double>(expected_pos.x);
event.y = static_cast<double>(expected_pos.y);
event.state = GDK_BUTTON1_MASK;
OverriddenCallTestableGtkWindowBase window(mock);
EXPECT_CALL(window, OnMouseLeftDown(PointEq(expected_pos)));
EXPECT_EQ(TRUE, window.OnMouseDown(kDummyWindow, &event));
}
{
SCOPED_TRACE("Right button is pressed, then call OnMouseRightDown");
GtkWrapperMock *mock = GetGtkMock();
GdkEventButton event;
event.window = kDummyGdkWindow;
event.x = static_cast<double>(expected_pos.x);
event.y = static_cast<double>(expected_pos.y);
event.state = GDK_BUTTON3_MASK;
OverriddenCallTestableGtkWindowBase window(mock);
EXPECT_CALL(window, OnMouseRightDown(PointEq(expected_pos)));
EXPECT_EQ(TRUE, window.OnMouseDown(kDummyWindow, &event));
}
{
SCOPED_TRACE("Left button is released, then call OnMouseLeftUp");
GtkWrapperMock *mock = GetGtkMock();
GdkEventButton event;
event.window = kDummyGdkWindow;
event.x = static_cast<double>(expected_pos.x);
event.y = static_cast<double>(expected_pos.y);
event.state = GDK_BUTTON1_MASK;
OverriddenCallTestableGtkWindowBase window(mock);
EXPECT_CALL(window, OnMouseLeftUp(PointEq(expected_pos)));
EXPECT_EQ(TRUE, window.OnMouseUp(kDummyWindow, &event));
}
{
SCOPED_TRACE("Right button is released, then call OnMouseRightUp");
GtkWrapperMock *mock = GetGtkMock();
GdkEventButton event;
event.window = kDummyGdkWindow;
event.x = static_cast<double>(expected_pos.x);
event.y = static_cast<double>(expected_pos.y);
event.state = GDK_BUTTON3_MASK;
OverriddenCallTestableGtkWindowBase window(mock);
EXPECT_CALL(window, OnMouseRightUp(PointEq(expected_pos)));
EXPECT_EQ(TRUE, window.OnMouseUp(kDummyWindow, &event));
}
{
SCOPED_TRACE("Other button is ignored and return 0");
// The state mask is up to 2^12, so try all state.
for (size_t flags = 0; flags < (1 << 13); ++flags) {
GtkWrapperMock *mock = GetGtkMock();
GdkEventButton event;
event.window = kDummyGdkWindow;
event.x = static_cast<double>(expected_pos.x);
event.y = static_cast<double>(expected_pos.y);
event.state = flags & ~(GDK_BUTTON1_MASK | GDK_BUTTON3_MASK);
OverriddenCallTestableGtkWindowBase window(mock);
EXPECT_CALL(window, OnMouseLeftDown(_)).Times(0);
EXPECT_CALL(window, OnMouseLeftUp(_)).Times(0);
EXPECT_CALL(window, OnMouseRightDown(_)).Times(0);
EXPECT_CALL(window, OnMouseRightUp(_)).Times(0);
EXPECT_EQ(TRUE, window.OnMouseUp(kDummyWindow, &event));
}
}
}
} // namespace gtk
} // namespace renderer
} // namespace mozc