1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/message_center/views/bounded_label.h"
#include <limits>
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/text_utils.h"
#include "ui/views/controls/label.h"
namespace message_center {
namespace test {
/* Test fixture ***************************************************************/
class BoundedLabelTest : public testing::Test {
public:
BoundedLabelTest() {
digit_pixels_ = gfx::GetStringWidth(base::UTF8ToUTF16("0"), font_list_);
space_pixels_ = gfx::GetStringWidth(base::UTF8ToUTF16(" "), font_list_);
ellipsis_pixels_ = gfx::GetStringWidth(base::UTF8ToUTF16("\xE2\x80\xA6"),
font_list_);
}
~BoundedLabelTest() override {}
// Replaces all occurences of three periods ("...") in the specified string
// with an ellipses character (UTF8 "\xE2\x80\xA6") and returns a string16
// with the results. This allows test strings to be specified as ASCII const
// char* strings, making tests more readable and easier to write.
base::string16 ToString(const char* string) {
const base::string16 periods = base::UTF8ToUTF16("...");
const base::string16 ellipses = base::UTF8ToUTF16("\xE2\x80\xA6");
base::string16 result = base::UTF8ToUTF16(string);
ReplaceSubstringsAfterOffset(&result, 0, periods, ellipses);
return result;
}
// Converts the specified elision width to pixels. To make tests somewhat
// independent of the fonts of the platform on which they're run, the elision
// widths are specified as XYZ integers, with the corresponding width in
// pixels being X times the width of digit characters plus Y times the width
// of spaces plus Z times the width of ellipses in the default font of the
// test plaform. It is assumed that all digits have the same width in that
// font, that this width is greater than the width of spaces, and that the
// width of 3 digits is greater than the width of ellipses.
int ToPixels(int width) {
return digit_pixels_ * width / 100 +
space_pixels_ * (width % 100) / 10 +
ellipsis_pixels_ * (width % 10);
}
// Exercise BounderLabel::GetWrappedText() using the fixture's test label.
base::string16 GetWrappedText(int width) {
return label_->GetWrappedTextForTest(width, lines_);
}
// Exercise BounderLabel::GetLinesForWidthAndLimit() using the test label.
int GetLinesForWidth(int width) {
label_->SetBounds(0, 0, width, font_list_.GetHeight() * lines_);
return label_->GetLinesForWidthAndLimit(width, lines_);
}
protected:
// Creates a label to test with. Returns this fixture, which can be used to
// test the newly created label using the exercise methods above.
BoundedLabelTest& Label(base::string16 text, int lines) {
lines_ = lines;
label_.reset(new BoundedLabel(text, font_list_));
label_->SetLineLimit(lines_);
return *this;
}
private:
// The default font list, which will be used for tests.
gfx::FontList font_list_;
int digit_pixels_;
int space_pixels_;
int ellipsis_pixels_;
scoped_ptr<BoundedLabel> label_;
int lines_;
};
/* Test macro *****************************************************************/
#define TEST_WRAP(expected, text, width, lines) \
EXPECT_EQ(ToString(expected), \
Label(ToString(text), lines).GetWrappedText(ToPixels(width)))
#define TEST_LINES(expected, text, width, lines) \
EXPECT_EQ(expected, \
Label(ToString(text), lines).GetLinesForWidth(ToPixels(width)))
/* Elision tests **************************************************************/
TEST_F(BoundedLabelTest, GetWrappedTextTest) {
// One word per line: No ellision should be made when not necessary.
TEST_WRAP("123", "123", 301, 1);
TEST_WRAP("123", "123", 301, 2);
TEST_WRAP("123", "123", 301, 3);
TEST_WRAP("123\n456", "123 456", 301, 2);
TEST_WRAP("123\n456", "123 456", 301, 3);
TEST_WRAP("123\n456\n789", "123 456 789", 301, 3);
// One word per line: Ellisions should be made when necessary.
TEST_WRAP("123...", "123 456", 301, 1);
TEST_WRAP("123...", "123 456 789", 301, 1);
TEST_WRAP("123\n456...", "123 456 789", 301, 2);
// Two words per line: No ellision should be made when not necessary.
TEST_WRAP("123 456", "123 456", 621, 1);
TEST_WRAP("123 456", "123 456", 621, 2);
TEST_WRAP("123 456", "123 456", 621, 3);
TEST_WRAP("123 456\n789 012", "123 456 789 012", 621, 2);
TEST_WRAP("123 456\n789 012", "123 456 789 012", 621, 3);
TEST_WRAP("123 456\n789 012\n345 678", "123 456 789 012 345 678", 621, 3);
// Two words per line: Ellisions should be made when necessary.
TEST_WRAP("123 456...", "123 456 789 012", 621, 1);
TEST_WRAP("123 456...", "123 456 789 012 345 678", 621, 1);
TEST_WRAP("123 456\n789 012...", "123 456 789 012 345 678", 621, 2);
// Single trailing spaces: No ellipses should be added.
TEST_WRAP("123", "123 ", 301, 1);
TEST_WRAP("123\n456", "123 456 ", 301, 2);
TEST_WRAP("123\n456\n789", "123 456 789 ", 301, 3);
TEST_WRAP("123 456", "123 456 ", 611, 1);
TEST_WRAP("123 456\n789 012", "123 456 789 012 ", 611, 2);
TEST_WRAP("123 456\n789 012\n345 678", "123 456 789 012 345 678 ", 611, 3);
// Multiple trailing spaces: No ellipses should be added.
TEST_WRAP("123", "123 ", 301, 1);
TEST_WRAP("123\n456", "123 456 ", 301, 2);
TEST_WRAP("123\n456\n789", "123 456 789 ", 301, 3);
TEST_WRAP("123 456", "123 456 ", 611, 1);
TEST_WRAP("123 456\n789 012", "123 456 789 012 ", 611, 2);
TEST_WRAP("123 456\n789 012\n345 678",
"123 456 789 012 345 678 ", 611, 3);
// Multiple spaces between words on the same line: Spaces should be preserved.
// Test cases for single spaces between such words are included in the "Two
// words per line" sections above.
TEST_WRAP("123 456", "123 456", 621, 1);
TEST_WRAP("123 456...", "123 456 789 012", 631, 1);
TEST_WRAP("123 456\n789 012", "123 456 789 012", 631, 2);
TEST_WRAP("123 456...", "123 456 789 012 345 678", 621, 1);
TEST_WRAP("123 456\n789 012...", "123 456 789 012 345 678", 631, 2);
TEST_WRAP("123 456\n789 012\n345 678",
"123 456 789 012 345 678", 641, 3);
// Multiple spaces between words split across lines: Spaces should be removed
// even if lines are wide enough to include those spaces. Test cases for
// single spaces between such words are included in the "Two words per line"
// sections above.
TEST_WRAP("123\n456", "123 456", 321, 2);
TEST_WRAP("123\n456", "123 456", 391, 2);
TEST_WRAP("123\n456...", "123 456 789", 321, 2);
TEST_WRAP("123\n456...", "123 456 789", 391, 2);
TEST_WRAP("123 456\n789 012", "123 456 789 012", 641, 2);
TEST_WRAP("123 456\n789 012...", "123 456 789 012 345 678", 641, 2);
// Long words without spaces should be wrapped when necessary.
TEST_WRAP("123\n456", "123456", 300, 9);
// TODO(dharcourt): Add test cases to verify that:
// - Spaces before elisions are removed
// - Leading spaces are preserved
// - Words are split when they are longer than lines
// - Words are clipped when they are longer than the last line
// - No blank line are created before or after clipped word
// - Spaces at the end of the text are removed
// TODO(dharcourt): Add test cases for:
// - Empty and very large strings
// - Zero, very large, and negative line limit values
// - Other input boundary conditions
// TODO(dharcourt): Add some randomly generated fuzz test cases.
}
/* GetLinesTest ***************************************************************/
TEST_F(BoundedLabelTest, GetLinesTest) {
// Zero and negative width values should yield zero lines.
TEST_LINES(0, "123 456", 0, 1);
TEST_LINES(0, "123 456", -1, 1);
TEST_LINES(0, "123 456", -2, 1);
TEST_LINES(0, "123 456", std::numeric_limits<int>::min(), 1);
// Small width values should yield one word per line.
TEST_LINES(1, "123 456", 1, 1);
TEST_LINES(2, "123 456", 1, 2);
TEST_LINES(1, "123 456", 2, 1);
TEST_LINES(2, "123 456", 2, 2);
TEST_LINES(1, "123 456", 3, 1);
TEST_LINES(2, "123 456", 3, 2);
// Large width values should yield all words on one line.
TEST_LINES(1, "123 456", 610, 1);
TEST_LINES(1, "123 456", std::numeric_limits<int>::max(), 1);
}
/* Other tests ****************************************************************/
// TODO(dharcourt): Add test cases to verify that:
// - SetMaxLines() affects the return values of some methods but not others.
// - Bound changes affects GetPreferredLines(), GetTextSize(), and
// GetWrappedText() return values.
// - GetTextFlags are as expected.
} // namespace test
} // namespace message_center
|