1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <variant>
17
18 #include <gtest/gtest.h>
19
20 #include "font_collection.h"
21 #include "font_styles.h"
22 #include "mock/mock_any_span.h"
23 #include "mock/mock_measurer.h"
24 #include "param_test_macros.h"
25 #include "texgine_exception.h"
26 #include "text_breaker.h"
27 #include "text_converter.h"
28
29 using namespace testing;
30 using namespace testing::ext;
31
32 namespace OHOS {
33 namespace Rosen {
34 namespace TextEngine {
35 std::vector<std::string> families_;
GenerateFontCollection(const std::vector<std::string> & families) const36 std::shared_ptr<FontCollection> FontProviders::GenerateFontCollection(
37 const std::vector<std::string> &families) const noexcept(true)
38 {
39 families_ = families;
40 std::vector<std::shared_ptr<VariantFontStyleSet>> sets;
41 return std::make_shared<FontCollection>(std::move(sets));
42 }
43
44 std::unique_ptr<Measurer> measurer = nullptr;
Create(const std::vector<uint16_t> & text,const FontCollection & fontCollection)45 std::unique_ptr<Measurer> Measurer::Create(const std::vector<uint16_t> &text, const FontCollection &fontCollection)
46 {
47 return std::move(measurer);
48 }
49
50 std::vector<Boundary> boundaries;
51
52 class MeasurerForTest : public Measurer {
53 public:
54 virtual ~MeasurerForTest() = default;
MeasurerForTest()55 MeasurerForTest() : Measurer({}, {{}}) {}
SetMeasurerArgs(int ret,const CharGroups & cgs)56 void SetMeasurerArgs(int ret, const CharGroups &cgs)
57 {
58 ret_ = ret;
59 cgs_ = cgs;
60 }
61
Measure(CharGroups & cgs)62 int Measure(CharGroups &cgs) override
63 {
64 cgs = cgs_;
65 return ret_;
66 }
67
GetWordBoundary() const68 const std::vector<Boundary> &GetWordBoundary() const override
69 {
70 return boundaries;
71 }
72
73 private:
74 CharGroups cgs_;
75 int ret_ = 0;
76 };
77
78 class TextBreakerTest : public testing::Test {
79 public:
SetUpTestCase()80 static void SetUpTestCase()
81 {
82 tpstyle_.fontFamilies = {"seguiemj"};
83 cgs1_.PushBack({.chars = TextConverter::ToUTF16("m"), .glyphs = {{0x013B, 13.664}}, .visibleWidth = 14});
84 cgs1_.PushBack({.chars = TextConverter::ToUTF16("o"), .glyphs = {{0x0145, 9.456}}, .visibleWidth = 10});
85 cgs1_.PushBack({.chars = TextConverter::ToUTF16("s"), .glyphs = {{0x0166, 7.28}}, .visibleWidth = 8});
86 cgs1_.PushBack({.chars = TextConverter::ToUTF16("t"), .glyphs = {{0x016E, 5.88}}, .visibleWidth = 6});
87
88 cgs2_ = cgs1_;
89 cgs2_.PushBack({.chars = TextConverter::ToUTF16(" "), .glyphs = {{0x0002, 4.32}}, .invisibleWidth = 5});
90 }
91
PrepareWordBreak(int ret,CharGroups & cgs,WordBreakType type=WordBreakType::BREAK_WORD)92 void PrepareWordBreak(int ret, CharGroups &cgs, WordBreakType type = WordBreakType::BREAK_WORD)
93 {
94 tpstyle_.wordBreakType = type;
95 auto m = std::make_unique<MeasurerForTest>();
96 m->SetMeasurerArgs(ret, cgs);
97 measurer = std::move(m);
98 // 1e9: the widthlimit
99 breaker.SetWidthLimit(1e9);
100 }
101
102 static inline TypographyStyle tpstyle_;
103 static inline TextStyle textStyle_;
104 std::shared_ptr<TextSpan> tsNullptr_ = nullptr;
105 std::shared_ptr<TextSpan> tsNormal_ = TextSpan::MakeFromText("most");
106 CharGroups emptyCgs_ = CharGroups::CreateEmpty();
107 static inline CharGroups cgs1_ = CharGroups::CreateEmpty();
108 static inline CharGroups cgs2_ = CharGroups::CreateEmpty();
109 FontCollection fontCollection_ = std::vector<std::shared_ptr<VariantFontStyleSet>>{};
110 std::vector<VariantSpan> spans_;
111 TextBreaker breaker;
112 std::vector<Boundary> boundaries_;
113 };
114
115 /**
116 * @tc.name: GenerateFontCollection1
117 * @tc.desc: Verify the GenerateFontCollection
118 * @tc.type:FUNC
119 */
120 HWTEST_F(TextBreakerTest, GenerateFontCollection1, TestSize.Level1)
121 {
122 textStyle_.fontFamilies = {};
123
124 EXPECT_NO_THROW({
125 auto ret = breaker.GenerateFontCollection(tpstyle_, textStyle_, FontProviders::Create());
126 ASSERT_NE(ret, nullptr);
127 ASSERT_EQ(tpstyle_.fontFamilies, families_);
128 });
129 }
130
131 /**
132 * @tc.name: GenerateFontCollection2
133 * @tc.desc: Verify the GenerateFontCollection
134 * @tc.type:FUNC
135 */
136 HWTEST_F(TextBreakerTest, GenerateFontCollection2, TestSize.Level1)
137 {
138 ASSERT_EXCEPTION(ExceptionType::INVALID_ARGUMENT, breaker.GenerateFontCollection(tpstyle_, textStyle_, nullptr));
139 }
140
141 /**
142 * @tc.name: GenerateFontCollection3
143 * @tc.desc: Verify the GenerateFontCollection
144 * @tc.type:FUNC
145 */
146 HWTEST_F(TextBreakerTest, GenerateFontCollection3, TestSize.Level1)
147 {
148 tpstyle_.fontFamilies = {"seguiemj"};
149 textStyle_.fontFamilies = {"robot"};
150
151 EXPECT_NO_THROW({
152 auto ret = breaker.GenerateFontCollection(tpstyle_, textStyle_, FontProviders::Create());
153 ASSERT_NE(ret, nullptr);
154 ASSERT_EQ(textStyle_.fontFamilies, families_);
155 });
156 }
157
158 /**
159 * @tc.name: Measure1
160 * @tc.desc: Verify the Measure
161 * @tc.type:FUNC
162 */
163 HWTEST_F(TextBreakerTest, Measure1, TestSize.Level1)
164 {
165 size_t leftIndex = 0;
166 size_t rightIndex = 5;
167 boundaries = {{ leftIndex, rightIndex }};
168 PrepareWordBreak(1, emptyCgs_);
169
170 EXPECT_NO_THROW({
171 auto ret = breaker.Measure({}, tsNormal_->u16vect_, fontCollection_, emptyCgs_, boundaries_);
172 ASSERT_NE(ret, 0);
173 });
174 }
175
176 /**
177 * @tc.name: Measure2
178 * @tc.desc: Verify the Measure
179 * @tc.type: FUNC
180 */
181 HWTEST_F(TextBreakerTest, Measure2, TestSize.Level1)
182 {
183 boundaries = {};
184 PrepareWordBreak(0, emptyCgs_);
185
186 EXPECT_NO_THROW({
187 auto ret = breaker.Measure({}, tsNormal_->u16vect_, fontCollection_, emptyCgs_, boundaries_);
188 ASSERT_EQ(ret, 1);
189 });
190 }
191
192 /**
193 * @tc.name: Measure3
194 * @tc.desc: Verify the Measure
195 * @tc.type:FUNC
196 */
197 HWTEST_F(TextBreakerTest, Measure3, TestSize.Level1)
198 {
199 size_t leftIndex = 0;
200 size_t rightIndex = 5;
201 boundaries = {{ leftIndex, rightIndex }};
202 PrepareWordBreak(0, emptyCgs_);
203
204 EXPECT_NO_THROW({
205 auto ret = breaker.Measure({}, tsNormal_->u16vect_, fontCollection_, emptyCgs_, boundaries_);
206 ASSERT_EQ(ret, 0);
207 });
208 }
209
210 /**
211 * @tc.name: BreakWord1
212 * @tc.desc: Verify the BreakWord
213 * @tc.type:FUNC
214 */
215 HWTEST_F(TextBreakerTest, BreakWord1, TestSize.Level1)
216 {
217 EXPECT_NO_THROW({
218 breaker.BreakWord(emptyCgs_, tpstyle_, textStyle_, spans_);
219 ASSERT_EQ(spans_.size(), 0);
220 });
221 }
222
223 /**
224 * @tc.name: BreakWord2
225 * @tc.desc: Verify the BreakWord
226 * @tc.type:FUNC
227 */
228 HWTEST_F(TextBreakerTest, BreakWord2, TestSize.Level1)
229 {
230 EXPECT_NO_THROW({
231 breaker.BreakWord(cgs1_, tpstyle_, textStyle_, spans_);
232 ASSERT_EQ(spans_.size(), 1);
233 auto span = spans_[0].TryToTextSpan();
234 ASSERT_EQ(span->GetPreBreak(), span->GetPostBreak());
235 });
236 }
237
238 /**
239 * @tc.name: BreakWord3
240 * @tc.desc: Verify the BreakWord
241 * @tc.type:FUNC
242 */
243 HWTEST_F(TextBreakerTest, BreakWord3, TestSize.Level1)
244 {
245 EXPECT_NO_THROW({
246 breaker.BreakWord(cgs2_, tpstyle_, textStyle_, spans_);
247 ASSERT_EQ(spans_.size(), 1);
248 auto span = spans_[0].TryToTextSpan();
249 ASSERT_NE(span->GetPreBreak(), span->GetPostBreak());
250 });
251 }
252
253 /**
254 * @tc.name: BreakWord4
255 * @tc.desc: Verify the BreakWord
256 * @tc.type:FUNC
257 */
258 HWTEST_F(TextBreakerTest, BreakWord4, TestSize.Level1)
259 {
260 tpstyle_.wordBreakType = WordBreakType::BREAK_ALL;
261
262 EXPECT_NO_THROW({
263 breaker.BreakWord(cgs1_, tpstyle_, textStyle_, spans_);
264 ASSERT_EQ(spans_.size(), 4);
265 for (int i = 0; i < 4; i++) {
266 auto span = spans_[i].TryToTextSpan();
267 ASSERT_EQ(span->GetPreBreak(), span->GetPostBreak());
268 }
269 });
270 }
271
272 /**
273 * @tc.name: BreakWord5
274 * @tc.desc: Verify the BreakWord
275 * @tc.type:FUNC
276 */
277 HWTEST_F(TextBreakerTest, BreakWord5, TestSize.Level1)
278 {
279 tpstyle_.wordBreakType = WordBreakType::BREAK_ALL;
280
281 EXPECT_NO_THROW({
282 breaker.BreakWord(cgs2_, tpstyle_, textStyle_, spans_);
283 ASSERT_EQ(spans_.size(), 5);
284 for (int i = 0; i < 4; i++) {
285 auto span = spans_[i].TryToTextSpan();
286 ASSERT_EQ(span->GetPreBreak(), span->GetPostBreak());
287 }
288 auto span = spans_[4].TryToTextSpan();
289 ASSERT_NE(span->GetPreBreak(), span->GetPostBreak());
290 });
291 }
292
293 /**
294 * @tc.name: GenerateSpan1
295 * @tc.desc: Verify the GenerateSpan
296 * @tc.type:FUNC
297 */
298 HWTEST_F(TextBreakerTest, GenerateSpan1, TestSize.Level1)
299 {
300 ASSERT_EXCEPTION(ExceptionType::INVALID_ARGUMENT,
301 breaker.GenerateSpan(emptyCgs_, tpstyle_, textStyle_, spans_));
302 }
303
304 /**
305 * @tc.name: GenerateSpan2
306 * @tc.desc: Verify the GenerateSpan
307 * @tc.type:FUNC
308 */
309 HWTEST_F(TextBreakerTest, GenerateSpan2, TestSize.Level1)
310 {
311 ASSERT_EXCEPTION(ExceptionType::INVALID_ARGUMENT,
312 breaker.GenerateSpan({}, tpstyle_, textStyle_, spans_));
313 }
314
315 /**
316 * @tc.name: GenerateSpan3
317 * @tc.desc: Verify the GenerateSpan
318 * @tc.type:FUNC
319 */
320 HWTEST_F(TextBreakerTest, GenerateSpan3, TestSize.Level1)
321 {
322 EXPECT_NO_THROW({
323 breaker.GenerateSpan(cgs2_, tpstyle_, textStyle_, spans_);
324 ASSERT_EQ(spans_.size(), 1);
325 });
326 }
327
328 /**
329 * @tc.name: WordBreak1
330 * @tc.desc: Verify the WordBreak
331 * @tc.type:FUNC
332 */
333 HWTEST_F(TextBreakerTest, WordBreak1, TestSize.Level1)
334 {
335 spans_ = {std::make_shared<MockAnySpan>()};
336 EXPECT_NO_THROW({
337 breaker.WordBreak(spans_, tpstyle_, FontProviders::Create());
338 ASSERT_EQ(spans_.size(), 1);
339 auto span = spans_[0].TryToAnySpan();
340 ASSERT_NE(span, nullptr);
341 });
342 }
343
344 /**
345 * @tc.name: WordBreak2
346 * @tc.desc: Verify the WordBreak
347 * @tc.type:FUNC
348 */
349 HWTEST_F(TextBreakerTest, WordBreak2, TestSize.Level1)
350 {
351 // 1: Set the Return value of Measurer
352 PrepareWordBreak(1, cgs1_);
353
354 spans_ = {tsNormal_};
355 EXPECT_NO_THROW({
356 breaker.WordBreak(spans_, tpstyle_, FontProviders::Create());
357 ASSERT_EQ(spans_.size(), 0);
358 });
359 }
360
361 /**
362 * @tc.name: WordBreak3
363 * @tc.desc: Verify the WordBreak
364 * @tc.type:FUNC
365 */
366 HWTEST_F(TextBreakerTest, WordBreak3, TestSize.Level1)
367 {
368 EXPECT_NO_THROW({
369 breaker.WordBreak(spans_, tpstyle_, FontProviders::Create());
370 ASSERT_EQ(spans_.size(), 0);
371 });
372 }
373
374 /**
375 * @tc.name: WordBreak4
376 * @tc.desc: Verify the WordBreak
377 * @tc.type:FUNC
378 */
379 HWTEST_F(TextBreakerTest, WordBreak4, TestSize.Level1)
380 {
381 auto type = WordBreakType::BREAK_WORD;
382 // {0, 4} is {leftIndex, rightIndex}
383 boundaries = {{ 0, 4 }};
384 PrepareWordBreak(0, cgs1_, type);
385
386 spans_ = {tsNormal_};
387 EXPECT_NO_THROW({
388 breaker.WordBreak(spans_, tpstyle_, FontProviders::Create());
389 ASSERT_EQ(spans_.size(), 1);
390 });
391 }
392
393 /**
394 * @tc.name: WordBreak5
395 * @tc.desc: Verify the WordBreak
396 * @tc.type:FUNC
397 */
398 HWTEST_F(TextBreakerTest, WordBreak5, TestSize.Level1)
399 {
400 auto type = WordBreakType::BREAK_ALL;
401 boundaries = {{ 0, 4 }};
402 PrepareWordBreak(0, cgs1_, type);
403
404 spans_ = {tsNormal_};
405 EXPECT_NO_THROW({
406 breaker.WordBreak(spans_, tpstyle_, FontProviders::Create());
407 ASSERT_EQ(spans_.size(), 4);
408 });
409 }
410
411 /**
412 * @tc.name: WordBreak6
413 * @tc.desc: Verify the WordBreak
414 * @tc.type:FUNC
415 */
416 HWTEST_F(TextBreakerTest, WordBreak6, TestSize.Level1)
417 {
418 auto type = WordBreakType::BREAK_ALL;
419 boundaries = {};
420 PrepareWordBreak(0, cgs1_, type);
421
422 spans_ = {tsNormal_};
423 EXPECT_NO_THROW({
424 breaker.WordBreak(spans_, tpstyle_, FontProviders::Create());
425 ASSERT_EQ(spans_.size(), 0);
426 });
427 }
428 } // namespace TextEngine
429 } // namespace Rosen
430 } // namespace OHOS
431