1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <string> 6#include <utility> 7 8#include "base/basictypes.h" 9#include "base/logging.h" 10#include "testing/gtest/include/gtest/gtest.h" 11#include "ui/base/gtk/gtk_im_context_util.h" 12#include "ui/base/ime/composition_text.h" 13 14namespace { 15 16struct AttributeInfo { 17 int type; 18 int value; 19 int start_offset; 20 int end_offset; 21}; 22 23struct Underline { 24 unsigned start_offset; 25 unsigned end_offset; 26 uint32 color; 27 bool thick; 28}; 29 30struct TestData { 31 const char* text; 32 const AttributeInfo attrs[10]; 33 const Underline underlines[10]; 34}; 35 36const TestData kTestData[] = { 37 // Normal case 38 { "One Two Three", 39 { { PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 0, 3 }, 40 { PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_DOUBLE, 4, 7 }, 41 { PANGO_ATTR_BACKGROUND, 0, 4, 7 }, 42 { PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 8, 13 }, 43 { 0, 0, 0, 0 } }, 44 { { 0, 3, SK_ColorBLACK, false }, 45 { 4, 7, SK_ColorBLACK, true }, 46 { 8, 13, SK_ColorBLACK, false }, 47 { 0, 0, 0, false } } 48 }, 49 50 // Offset overflow. 51 { "One Two Three", 52 { { PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 0, 3 }, 53 { PANGO_ATTR_BACKGROUND, 0, 4, 7 }, 54 { PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 8, 20 }, 55 { 0, 0, 0, 0 } }, 56 { { 0, 3, SK_ColorBLACK, false }, 57 { 4, 7, SK_ColorBLACK, true }, 58 { 8, 13, SK_ColorBLACK, false }, 59 { 0, 0, 0, false} } 60 }, 61 62 // Error underline. 63 { "One Two Three", 64 { { PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 0, 3 }, 65 { PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_ERROR, 4, 7 }, 66 { PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 8, 13 }, 67 { 0, 0, 0, 0 } }, 68 { { 0, 3, SK_ColorBLACK, false }, 69 { 4, 7, SK_ColorRED, false }, 70 { 8, 13, SK_ColorBLACK, false }, 71 { 0, 0, 0, false} } 72 }, 73 74 // Default underline. 75 { "One Two Three", 76 { { 0, 0, 0, 0 } }, 77 { { 0, 13, SK_ColorBLACK, false }, 78 { 0, 0, 0, false } } 79 }, 80 81 // Unicode, including non-BMP characters: "123你好一丁 456" 82 { "123\xE4\xBD\xA0\xE5\xA5\xBD\xF0\xA0\x80\x80\xF0\xA0\x80\x81\xE4\xB8\x80" 83 "\xE4\xB8\x81 456", 84 { { PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 0, 3 }, 85 { PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 3, 5 }, 86 { PANGO_ATTR_BACKGROUND, 0, 5, 7 }, 87 { PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 7, 13 }, 88 { 0, 0, 0, 0 } }, 89 { { 0, 3, SK_ColorBLACK, false }, 90 { 3, 5, SK_ColorBLACK, false }, 91 { 5, 9, SK_ColorBLACK, true }, 92 { 9, 15, SK_ColorBLACK, false }, 93 { 0, 0, 0, false } } 94 }, 95}; 96 97void CompareUnderline(const Underline& a, 98 const ui::CompositionUnderline& b) { 99 EXPECT_EQ(a.start_offset, b.start_offset); 100 EXPECT_EQ(a.end_offset, b.end_offset); 101 EXPECT_EQ(a.color, b.color); 102 EXPECT_EQ(a.thick, b.thick); 103} 104 105class GtkIMContextWrapperTest : public testing::Test { 106}; 107 108TEST(GtkIMContextUtilTest, ExtractCompositionText) { 109 for (size_t i = 0; i < arraysize(kTestData); ++i) { 110 const char* text = kTestData[i].text; 111 const AttributeInfo* attrs = kTestData[i].attrs; 112 SCOPED_TRACE(testing::Message() << "Testing:" << i 113 << " text:" << text); 114 115 PangoAttrList* pango_attrs = pango_attr_list_new(); 116 for (size_t a = 0; attrs[a].type; ++a) { 117 PangoAttribute* pango_attr = NULL; 118 switch (attrs[a].type) { 119 case PANGO_ATTR_UNDERLINE: 120 pango_attr = pango_attr_underline_new( 121 static_cast<PangoUnderline>(attrs[a].value)); 122 break; 123 case PANGO_ATTR_BACKGROUND: 124 pango_attr = pango_attr_background_new(0, 0, 0); 125 break; 126 default: 127 NOTREACHED(); 128 } 129 pango_attr->start_index = 130 g_utf8_offset_to_pointer(text, attrs[a].start_offset) - text; 131 pango_attr->end_index = 132 g_utf8_offset_to_pointer(text, attrs[a].end_offset) - text; 133 pango_attr_list_insert(pango_attrs, pango_attr); 134 } 135 136 ui::CompositionText result; 137 ui::ExtractCompositionTextFromGtkPreedit(text, pango_attrs, 0, &result); 138 139 const Underline* underlines = kTestData[i].underlines; 140 for (size_t u = 0; underlines[u].color && 141 u < result.underlines.size(); ++u) { 142 SCOPED_TRACE(testing::Message() << "Underline:" << u); 143 CompareUnderline(underlines[u], result.underlines[u]); 144 } 145 146 pango_attr_list_unref(pango_attrs); 147 } 148} 149 150} // namespace 151