blob: 7f3757e1b37a890463626130aa38c27df40e6eea [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/infolist_window.h"
#include "base/number_util.h"
#include "renderer/unix/cairo_factory_mock.h"
#include "renderer/unix/const.h"
#include "renderer/unix/draw_tool_mock.h"
#include "renderer/unix/gtk_wrapper_mock.h"
#include "renderer/unix/text_renderer_mock.h"
#include "testing/base/public/gmock.h"
#include "testing/base/public/gunit.h"
using ::testing::Return;
using ::testing::StrEq;
using ::testing::StrictMock;
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);
const char kSampleTitle[] = "TITLE";
const char kSampleDescription[] = "DESCRIPTION";
void SetInformations(int count, commands::InformationList *usages) {
usages->Clear();
for (int i = 0; i < count; ++i) {
commands::Information *info = usages->add_information();
const string id_str = NumberUtil::SimpleItoa(i);
info->set_title(kSampleTitle + id_str);
info->set_description(kSampleDescription + id_str);
}
}
string GetExpectedTitle(int row) {
const string id_str = NumberUtil::SimpleItoa(row);
return kSampleTitle + id_str;
}
string GetExpectedDescription(int row) {
const string id_str = NumberUtil::SimpleItoa(row);
return kSampleDescription + id_str;
}
MATCHER_P(RectEq, expected_rect, "The expected rect does not match") {
return (arg.origin.x == expected_rect.origin.x) &&
(arg.origin.y == expected_rect.origin.y) &&
(arg.size.width == expected_rect.size.width) &&
(arg.size.height == expected_rect.size.height);
}
MATCHER_P(RGBAEq, expected_rgba, "The expected RGBA does not match") {
return (arg.red == expected_rgba.red) &&
(arg.green == expected_rgba.green) &&
(arg.blue == expected_rgba.blue) &&
(arg.alpha == expected_rgba.alpha);
}
RGBA StyleColorToRGBA(
const RendererStyle::RGBAColor &rgbacolor) {
const RGBA rgba = {
static_cast<uint8>(rgbacolor.r()),
static_cast<uint8>(rgbacolor.g()),
static_cast<uint8>(rgbacolor.b()),
0xFF };
return rgba;
}
} // namespace
class InfolistWindowTest : public testing::Test {
protected:
struct InfolistWindowTestKit {
GtkWrapperMock *gtk_mock;
TextRendererMock *text_renderer_mock;
DrawToolMock *draw_tool_mock;
CairoFactoryMock *cairo_factory_mock;
InfolistWindow *window;
};
void SetUpInfolistWindowConstractorCallExpectations(
InfolistWindowTestKit *testkit) {
// Following functions are expected to be called by constructor.
EXPECT_CALL(*testkit->gtk_mock, GtkWindowNew(GTK_WINDOW_POPUP))
.WillOnce(Return(kDummyWindow));
EXPECT_CALL(*testkit->gtk_mock, GtkDrawingAreaNew())
.WillOnce(Return(kDummyCanvas));
EXPECT_CALL(*testkit->gtk_mock, GSignalConnect(
kDummyWindow, StrEq("destroy"),
G_CALLBACK(GtkWindowBase::OnDestroyThunk), _));
EXPECT_CALL(*testkit->gtk_mock, GSignalConnect(
kDummyWindow, StrEq("button-press-event"),
G_CALLBACK(GtkWindowBase::OnMouseDownThunk), _));
EXPECT_CALL(*testkit->gtk_mock, GSignalConnect(
kDummyWindow, StrEq("button-release-event"),
G_CALLBACK(GtkWindowBase::OnMouseUpThunk), _));
EXPECT_CALL(*testkit->gtk_mock, GSignalConnect(
kDummyCanvas, StrEq("expose-event"),
G_CALLBACK(GtkWindowBase::OnPaintThunk), _));
EXPECT_CALL(*testkit->gtk_mock,
GtkContainerAdd(kDummyWindow, kDummyCanvas));
EXPECT_CALL(*testkit->gtk_mock,
GtkWidgetAddEvents(kDummyWindow, GDK_BUTTON_PRESS_MASK));
EXPECT_CALL(*testkit->gtk_mock,
GtkWidgetAddEvents(kDummyWindow, GDK_BUTTON_RELEASE_MASK));
EXPECT_CALL(*testkit->gtk_mock, GtkWidgetRealize(kDummyWindow));
EXPECT_CALL(*testkit->gtk_mock,
GdkWindowSetTypeHint(kDummyWindow,
GDK_WINDOW_TYPE_HINT_POPUP_MENU));
}
InfolistWindowTestKit SetUpInfolistWindow() {
InfolistWindowTestKit testkit;
testkit.gtk_mock = new GtkWrapperMock();
testkit.text_renderer_mock = new TextRendererMock();
testkit.draw_tool_mock = new DrawToolMock();
testkit.cairo_factory_mock = new CairoFactoryMock();
SetUpInfolistWindowConstractorCallExpectations(&testkit);
testkit.window = new InfolistWindow(testkit.text_renderer_mock,
testkit.draw_tool_mock,
testkit.gtk_mock,
testkit.cairo_factory_mock);
return testkit;
}
InfolistWindowTestKit SetUpInfolistWindowWithStrictMock() {
InfolistWindowTestKit testkit;
testkit.gtk_mock = new StrictMock<GtkWrapperMock>();
testkit.text_renderer_mock = new StrictMock<TextRendererMock>();
testkit.draw_tool_mock = new StrictMock<DrawToolMock>();
testkit.cairo_factory_mock = new StrictMock<CairoFactoryMock>();
SetUpInfolistWindowConstractorCallExpectations(&testkit);
testkit.window = new InfolistWindow(testkit.text_renderer_mock,
testkit.draw_tool_mock,
testkit.gtk_mock,
testkit.cairo_factory_mock);
return testkit;
}
void FinalizeTestKit(InfolistWindowTestKit *testkit) {
delete testkit->window;
}
};
TEST_F(InfolistWindowTest, DrawFrameTest) {
InfolistWindowTestKit testkit = SetUpInfolistWindow();
const RendererStyle::InfolistStyle &infostyle
= testkit.window->style_->infolist_style();
const int height = 1234;
const Rect expected_rect(0, 0, infostyle.window_width(), height);
EXPECT_CALL(*testkit.draw_tool_mock,
FrameRect(RectEq(expected_rect),
RGBAEq(StyleColorToRGBA(infostyle.border_color())),
1));
testkit.window->DrawFrame(height);
FinalizeTestKit(&testkit);
}
TEST_F(InfolistWindowTest, GetRowRectsTest) {
InfolistWindowTestKit testkit = SetUpInfolistWindow();
const RendererStyle::InfolistStyle &infostyle
= testkit.window->style_->infolist_style();
const renderer::RendererStyle::TextStyle title_style
= infostyle.title_style();
const renderer::RendererStyle::TextStyle description_style
= infostyle.description_style();
const int ypos = 123;
const FontSpecInterface::FONT_TYPE infolist_font_type
= FontSpecInterface::FONTSET_INFOLIST_TITLE;
const FontSpecInterface::FONT_TYPE description_font_type
= FontSpecInterface::FONTSET_INFOLIST_DESCRIPTION;
const Size text_size(10, 20);
SetInformations(10, testkit.window->candidates_.mutable_usages());
EXPECT_CALL(*testkit.text_renderer_mock,
GetMultiLinePixelSize(infolist_font_type,
GetExpectedTitle(0), _))
.WillOnce(Return(text_size));
EXPECT_CALL(*testkit.text_renderer_mock,
GetMultiLinePixelSize(description_font_type,
GetExpectedDescription(0), _))
.WillOnce(Return(text_size));
InfolistWindow::RenderingRowRects row_rects
= testkit.window->GetRowRects(0, ypos);
EXPECT_EQ(row_rects.title_back_rect.Height(),
row_rects.desc_back_rect.Top() - row_rects.title_back_rect.Top());
EXPECT_EQ(row_rects.title_back_rect.Top(), row_rects.whole_rect.Top());
EXPECT_EQ(row_rects.title_back_rect.Left(), row_rects.whole_rect.Left());
EXPECT_EQ(row_rects.title_back_rect.Width(), row_rects.whole_rect.Width());
EXPECT_EQ(row_rects.title_back_rect.Height()
+ row_rects.desc_back_rect.Height(),
row_rects.whole_rect.Height());
FinalizeTestKit(&testkit);
}
TEST_F(InfolistWindowTest, DrawRowTest) {
{
SCOPED_TRACE("Draw focused area");
for (int i = 0; i < 10; ++i) {
InfolistWindowTestKit testkit = SetUpInfolistWindow();
const RendererStyle::InfolistStyle &infostyle
= testkit.window->style_->infolist_style();
const FontSpecInterface::FONT_TYPE infolist_font_type
= FontSpecInterface::FONTSET_INFOLIST_TITLE;
const FontSpecInterface::FONT_TYPE description_font_type
= FontSpecInterface::FONTSET_INFOLIST_DESCRIPTION;
const Size text_size(10, 20);
SetInformations(10, testkit.window->candidates_.mutable_usages());
const int ypos = i * 15;
testkit.window->candidates_.mutable_usages()->set_focused_index(i);
EXPECT_CALL(*testkit.text_renderer_mock,
GetMultiLinePixelSize(infolist_font_type,
GetExpectedTitle(i), _))
.WillRepeatedly(Return(text_size));
EXPECT_CALL(*testkit.text_renderer_mock,
GetMultiLinePixelSize(description_font_type,
GetExpectedDescription(i), _))
.WillRepeatedly(Return(text_size));
const InfolistWindow::RenderingRowRects sample_row_rects =
testkit.window->GetRowRects(i, ypos);
EXPECT_CALL(*testkit.draw_tool_mock,
FillRect(RectEq(sample_row_rects.whole_rect),
RGBAEq(StyleColorToRGBA(
infostyle.focused_background_color()))));
EXPECT_CALL(*testkit.draw_tool_mock,
FrameRect(RectEq(sample_row_rects.whole_rect),
RGBAEq(StyleColorToRGBA(
infostyle.focused_border_color())),
1));
EXPECT_CALL(*testkit.text_renderer_mock,
RenderText(StrEq(GetExpectedTitle(i)),
RectEq(sample_row_rects.title_rect),
FontSpecInterface::FONTSET_INFOLIST_TITLE));
EXPECT_CALL(*testkit.text_renderer_mock,
RenderText(StrEq(GetExpectedDescription(i)),
RectEq(sample_row_rects.desc_rect),
FontSpecInterface::FONTSET_INFOLIST_DESCRIPTION));
testkit.window->DrawRow(i, ypos);
FinalizeTestKit(&testkit);
}
}
{
SCOPED_TRACE("Draw focus-outed area with default color");
for (int i = 0; i < 10; ++i) {
InfolistWindowTestKit testkit = SetUpInfolistWindow();
RendererStyle::InfolistStyle *infostyle
= testkit.window->style_->mutable_infolist_style();
infostyle->mutable_title_style()->clear_background_color();
infostyle->mutable_description_style()->clear_background_color();
const FontSpecInterface::FONT_TYPE infolist_font_type
= FontSpecInterface::FONTSET_INFOLIST_TITLE;
const FontSpecInterface::FONT_TYPE description_font_type
= FontSpecInterface::FONTSET_INFOLIST_DESCRIPTION;
const Size text_size(10, 20);
SetInformations(10, testkit.window->candidates_.mutable_usages());
const int ypos = i * 15;
SetInformations(10, testkit.window->candidates_.mutable_usages());
EXPECT_CALL(*testkit.text_renderer_mock,
GetMultiLinePixelSize(infolist_font_type,
GetExpectedTitle(i), _))
.WillRepeatedly(Return(text_size));
EXPECT_CALL(*testkit.text_renderer_mock,
GetMultiLinePixelSize(description_font_type,
GetExpectedDescription(i), _))
.WillRepeatedly(Return(text_size));
const InfolistWindow::RenderingRowRects sample_row_rects =
testkit.window->GetRowRects(i, ypos);
EXPECT_CALL(*testkit.draw_tool_mock,
FillRect(RectEq(sample_row_rects.title_back_rect),
RGBAEq(kWhite)));
EXPECT_CALL(*testkit.draw_tool_mock,
FillRect(RectEq(sample_row_rects.desc_back_rect),
RGBAEq(kWhite)));
EXPECT_CALL(*testkit.text_renderer_mock,
RenderText(StrEq(GetExpectedTitle(i)),
RectEq(sample_row_rects.title_rect),
FontSpecInterface::FONTSET_INFOLIST_TITLE));
EXPECT_CALL(*testkit.text_renderer_mock,
RenderText(StrEq(GetExpectedDescription(i)),
RectEq(sample_row_rects.desc_rect),
FontSpecInterface::FONTSET_INFOLIST_DESCRIPTION));
testkit.window->DrawRow(i, ypos);
FinalizeTestKit(&testkit);
}
}
{
SCOPED_TRACE("Draw focus-outed area with specified color");
for (int i = 0; i < 10; ++i) {
InfolistWindowTestKit testkit = SetUpInfolistWindow();
RendererStyle::InfolistStyle *infostyle
= testkit.window->style_->mutable_infolist_style();
infostyle->mutable_title_style()->mutable_background_color();
infostyle->mutable_description_style()->mutable_background_color();
const FontSpecInterface::FONT_TYPE infolist_font_type
= FontSpecInterface::FONTSET_INFOLIST_TITLE;
const FontSpecInterface::FONT_TYPE description_font_type
= FontSpecInterface::FONTSET_INFOLIST_DESCRIPTION;
const Size text_size(10, 20);
SetInformations(10, testkit.window->candidates_.mutable_usages());
const int ypos = i * 15;
SetInformations(10, testkit.window->candidates_.mutable_usages());
EXPECT_CALL(*testkit.text_renderer_mock,
GetMultiLinePixelSize(infolist_font_type,
GetExpectedTitle(i), _))
.WillRepeatedly(Return(text_size));
EXPECT_CALL(*testkit.text_renderer_mock,
GetMultiLinePixelSize(description_font_type,
GetExpectedDescription(i), _))
.WillRepeatedly(Return(text_size));
const InfolistWindow::RenderingRowRects sample_row_rects =
testkit.window->GetRowRects(i, ypos);
EXPECT_CALL(*testkit.draw_tool_mock,
FillRect(RectEq(sample_row_rects.title_back_rect),
RGBAEq(StyleColorToRGBA(
infostyle->title_style().background_color()))));
EXPECT_CALL(*testkit.draw_tool_mock,
FillRect(RectEq(sample_row_rects.desc_back_rect),
RGBAEq(StyleColorToRGBA(
infostyle->description_style().background_color()))));
EXPECT_CALL(*testkit.text_renderer_mock,
RenderText(StrEq(GetExpectedTitle(i)),
RectEq(sample_row_rects.title_rect),
FontSpecInterface::FONTSET_INFOLIST_TITLE));
EXPECT_CALL(*testkit.text_renderer_mock,
RenderText(StrEq(GetExpectedDescription(i)),
RectEq(sample_row_rects.desc_rect),
FontSpecInterface::FONTSET_INFOLIST_DESCRIPTION));
testkit.window->DrawRow(i, ypos);
FinalizeTestKit(&testkit);
}
}
}
TEST_F(InfolistWindowTest, DrawCaptionTest) {
{
SCOPED_TRACE("If there is no caption, do nothing");
InfolistWindowTestKit testkit = SetUpInfolistWindowWithStrictMock();
testkit.window->style_.reset(new RendererStyle());
testkit.window->DrawCaption();
FinalizeTestKit(&testkit);
}
{
InfolistWindowTestKit testkit = SetUpInfolistWindow();
const RendererStyle::InfolistStyle &infostyle
= testkit.window->style_->infolist_style();
const RendererStyle::TextStyle &caption_style = infostyle.caption_style();
const Rect bg_expected_rect(
infostyle.window_border(),
infostyle.window_border(),
infostyle.window_width() - infostyle.window_border() * 2,
infostyle.caption_height());
const RGBA bg_expected_color
= StyleColorToRGBA(infostyle.caption_background_color());
EXPECT_CALL(*testkit.draw_tool_mock,
FillRect(RectEq(bg_expected_rect), RGBAEq(bg_expected_color)));
const Rect caption_expected_rect(
bg_expected_rect.Left()
+ infostyle.caption_padding() + caption_style.left_padding(),
bg_expected_rect.Top() + infostyle.caption_padding(),
bg_expected_rect.Width()
- infostyle.caption_padding() - caption_style.left_padding(),
infostyle.caption_height() - infostyle.caption_padding());
EXPECT_CALL(*testkit.text_renderer_mock,
RenderText(infostyle.caption_string(),
RectEq(caption_expected_rect),
FontSpecInterface::FONTSET_INFOLIST_CAPTION));
EXPECT_EQ(infostyle.caption_height(), testkit.window->DrawCaption());
FinalizeTestKit(&testkit);
}
}
TEST_F(InfolistWindowTest, GetRenderingRectsTest) {
// TODO(nona): rectangle argument verification.
{
SCOPED_TRACE("title style");
InfolistWindowTestKit testkit = SetUpInfolistWindow();
const RendererStyle::InfolistStyle &infostyle
= testkit.window->style_->infolist_style();
const renderer::RendererStyle::TextStyle title_style
= infostyle.title_style();
const int ypos = 123;
const FontSpecInterface::FONT_TYPE font_type
= FontSpecInterface::FONTSET_INFOLIST_TITLE;
const Size text_size(10, 20);
EXPECT_CALL(*testkit.text_renderer_mock,
GetMultiLinePixelSize(font_type, kSampleTitle, _))
.WillOnce(Return(text_size));
Rect bg_rect, text_rect;
testkit.window->GetRenderingRects(title_style, kSampleTitle,
font_type, ypos, &bg_rect, &text_rect);
FinalizeTestKit(&testkit);
}
{
SCOPED_TRACE("description style");
InfolistWindowTestKit testkit = SetUpInfolistWindow();
const RendererStyle::InfolistStyle &infostyle
= testkit.window->style_->infolist_style();
const renderer::RendererStyle::TextStyle description_style
= infostyle.description_style();
const int ypos = 234;
const FontSpecInterface::FONT_TYPE font_type
= FontSpecInterface::FONTSET_INFOLIST_DESCRIPTION;
const Size text_size(10, 20);
EXPECT_CALL(*testkit.text_renderer_mock,
GetMultiLinePixelSize(font_type, kSampleDescription, _))
.WillOnce(Return(text_size));
Rect bg_rect, text_rect;
testkit.window->GetRenderingRects(description_style, kSampleDescription,
font_type, ypos, &bg_rect, &text_rect);
FinalizeTestKit(&testkit);
}
}
TEST_F(InfolistWindowTest, ReloadFontConfigTest) {
InfolistWindowTestKit testkit = SetUpInfolistWindow();
const char kDummyFontDescription[] = "Foo,Bar,Baz";
EXPECT_CALL(*testkit.text_renderer_mock,
ReloadFontConfig(StrEq(kDummyFontDescription)));
testkit.window->ReloadFontConfig(kDummyFontDescription);
FinalizeTestKit(&testkit);
}
} // namespace gtk
} // namespace renderer
} // namespace mozc