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 }
99
100 static inline TypographyStyle tpstyle_;
101 static inline TextStyle textStyle_;
102 std::shared_ptr<TextSpan> tsNullptr_ = nullptr;
103 std::shared_ptr<TextSpan> tsNormal_ = TextSpan::MakeFromText("most");
104 CharGroups emptyCgs_ = CharGroups::CreateEmpty();
105 static inline CharGroups cgs1_ = CharGroups::CreateEmpty();
106 static inline CharGroups cgs2_ = CharGroups::CreateEmpty();
107 FontCollection fontCollection_ = std::vector<std::shared_ptr<VariantFontStyleSet>>{};
108 std::vector<VariantSpan> spans_;
109 TextBreaker breaker;
110 std::vector<Boundary> boundaries_;
111 };
112
113 /**
114 * @tc.name: GenerateFontCollection1
115 * @tc.desc: Verify the GenerateFontCollection
116 * @tc.type:FUNC
117 */
118 HWTEST_F(TextBreakerTest, GenerateFontCollection1, TestSize.Level1)
119 {
120 textStyle_.fontFamilies = {};
121
122 EXPECT_NO_THROW({
123 auto ret = breaker.GenerateFontCollection(tpstyle_, textStyle_, FontProviders::Create());
124 ASSERT_NE(ret, nullptr);
125 ASSERT_EQ(tpstyle_.fontFamilies, families_);
126 });
127 }
128
129 /**
130 * @tc.name: GenerateFontCollection2
131 * @tc.desc: Verify the GenerateFontCollection
132 * @tc.type:FUNC
133 */
134 HWTEST_F(TextBreakerTest, GenerateFontCollection2, TestSize.Level1)
135 {
136 ASSERT_EXCEPTION(ExceptionType::INVALID_ARGUMENT, breaker.GenerateFontCollection(tpstyle_, textStyle_, nullptr));
137 }
138
139 /**
140 * @tc.name: GenerateFontCollection3
141 * @tc.desc: Verify the GenerateFontCollection
142 * @tc.type:FUNC
143 */
144 HWTEST_F(TextBreakerTest, GenerateFontCollection3, TestSize.Level1)
145 {
146 tpstyle_.fontFamilies = {"seguiemj"};
147 textStyle_.fontFamilies = {"robot"};
148
149 EXPECT_NO_THROW({
150 auto ret = breaker.GenerateFontCollection(tpstyle_, textStyle_, FontProviders::Create());
151 ASSERT_NE(ret, nullptr);
152 ASSERT_EQ(textStyle_.fontFamilies, families_);
153 });
154 }
155
156 /**
157 * @tc.name: Measure1
158 * @tc.desc: Verify the Measure
159 * @tc.type:FUNC
160 */
161 HWTEST_F(TextBreakerTest, Measure1, TestSize.Level1)
162 {
163 size_t leftIndex = 0;
164 size_t rightIndex = 5;
165 boundaries = {{ leftIndex, rightIndex }};
166 PrepareWordBreak(1, emptyCgs_);
167
168 EXPECT_NO_THROW({
169 auto ret = breaker.Measure({}, tsNormal_->u16vect_, fontCollection_, emptyCgs_, boundaries_);
170 ASSERT_NE(ret, 0);
171 });
172 }
173
174 /**
175 * @tc.name: Measure2
176 * @tc.desc: Verify the Measure
177 * @tc.type: FUNC
178 */
179 HWTEST_F(TextBreakerTest, Measure2, TestSize.Level1)
180 {
181 boundaries = {};
182 PrepareWordBreak(0, emptyCgs_);
183
184 EXPECT_NO_THROW({
185 auto ret = breaker.Measure({}, tsNormal_->u16vect_, fontCollection_, emptyCgs_, boundaries_);
186 ASSERT_EQ(ret, 1);
187 });
188 }
189
190 /**
191 * @tc.name: Measure3
192 * @tc.desc: Verify the Measure
193 * @tc.type:FUNC
194 */
195 HWTEST_F(TextBreakerTest, Measure3, TestSize.Level1)
196 {
197 size_t leftIndex = 0;
198 size_t rightIndex = 5;
199 boundaries = {{ leftIndex, rightIndex }};
200 PrepareWordBreak(0, emptyCgs_);
201
202 EXPECT_NO_THROW({
203 auto ret = breaker.Measure({}, tsNormal_->u16vect_, fontCollection_, emptyCgs_, boundaries_);
204 ASSERT_EQ(ret, 0);
205 });
206 }
207
208 /**
209 * @tc.name: BreakWord1
210 * @tc.desc: Verify the BreakWord
211 * @tc.type:FUNC
212 */
213 HWTEST_F(TextBreakerTest, BreakWord1, TestSize.Level1)
214 {
215 EXPECT_NO_THROW({
216 breaker.BreakWord(emptyCgs_, tpstyle_, textStyle_, spans_);
217 ASSERT_EQ(spans_.size(), 0);
218 });
219 }
220
221 /**
222 * @tc.name: BreakWord2
223 * @tc.desc: Verify the BreakWord
224 * @tc.type:FUNC
225 */
226 HWTEST_F(TextBreakerTest, BreakWord2, TestSize.Level1)
227 {
228 EXPECT_NO_THROW({
229 breaker.BreakWord(cgs1_, tpstyle_, textStyle_, spans_);
230 ASSERT_EQ(spans_.size(), 1);
231 auto span = spans_[0].TryToTextSpan();
232 ASSERT_EQ(span->GetPreBreak(), span->GetPostBreak());
233 });
234 }
235
236 /**
237 * @tc.name: BreakWord3
238 * @tc.desc: Verify the BreakWord
239 * @tc.type:FUNC
240 */
241 HWTEST_F(TextBreakerTest, BreakWord3, TestSize.Level1)
242 {
243 EXPECT_NO_THROW({
244 breaker.BreakWord(cgs2_, tpstyle_, textStyle_, spans_);
245 ASSERT_EQ(spans_.size(), 1);
246 auto span = spans_[0].TryToTextSpan();
247 ASSERT_NE(span->GetPreBreak(), span->GetPostBreak());
248 });
249 }
250
251 /**
252 * @tc.name: BreakWord4
253 * @tc.desc: Verify the BreakWord
254 * @tc.type:FUNC
255 */
256 HWTEST_F(TextBreakerTest, BreakWord4, TestSize.Level1)
257 {
258 tpstyle_.wordBreakType = WordBreakType::BREAK_ALL;
259
260 EXPECT_NO_THROW({
261 breaker.BreakWord(cgs1_, tpstyle_, textStyle_, spans_);
262 ASSERT_EQ(spans_.size(), 4);
263 for (int i = 0; i < 4; i++) {
264 auto span = spans_[i].TryToTextSpan();
265 ASSERT_EQ(span->GetPreBreak(), span->GetPostBreak());
266 }
267 });
268 }
269
270 /**
271 * @tc.name: BreakWord5
272 * @tc.desc: Verify the BreakWord
273 * @tc.type:FUNC
274 */
275 HWTEST_F(TextBreakerTest, BreakWord5, TestSize.Level1)
276 {
277 tpstyle_.wordBreakType = WordBreakType::BREAK_ALL;
278
279 EXPECT_NO_THROW({
280 breaker.BreakWord(cgs2_, tpstyle_, textStyle_, spans_);
281 ASSERT_EQ(spans_.size(), 5);
282 for (int i = 0; i < 4; i++) {
283 auto span = spans_[i].TryToTextSpan();
284 ASSERT_EQ(span->GetPreBreak(), span->GetPostBreak());
285 }
286 auto span = spans_[4].TryToTextSpan();
287 ASSERT_NE(span->GetPreBreak(), span->GetPostBreak());
288 });
289 }
290
291 /**
292 * @tc.name: GenerateSpan1
293 * @tc.desc: Verify the GenerateSpan
294 * @tc.type:FUNC
295 */
296 HWTEST_F(TextBreakerTest, GenerateSpan1, TestSize.Level1)
297 {
298 ASSERT_EXCEPTION(ExceptionType::INVALID_ARGUMENT,
299 breaker.GenerateSpan(emptyCgs_, tpstyle_, textStyle_, spans_));
300 }
301
302 /**
303 * @tc.name: GenerateSpan2
304 * @tc.desc: Verify the GenerateSpan
305 * @tc.type:FUNC
306 */
307 HWTEST_F(TextBreakerTest, GenerateSpan2, TestSize.Level1)
308 {
309 ASSERT_EXCEPTION(ExceptionType::INVALID_ARGUMENT,
310 breaker.GenerateSpan({}, tpstyle_, textStyle_, spans_));
311 }
312
313 /**
314 * @tc.name: GenerateSpan3
315 * @tc.desc: Verify the GenerateSpan
316 * @tc.type:FUNC
317 */
318 HWTEST_F(TextBreakerTest, GenerateSpan3, TestSize.Level1)
319 {
320 EXPECT_NO_THROW({
321 breaker.GenerateSpan(cgs2_, tpstyle_, textStyle_, spans_);
322 ASSERT_EQ(spans_.size(), 1);
323 });
324 }
325
326 /**
327 * @tc.name: WordBreak1
328 * @tc.desc: Verify the WordBreak
329 * @tc.type:FUNC
330 */
331 HWTEST_F(TextBreakerTest, WordBreak1, TestSize.Level1)
332 {
333 spans_ = {std::make_shared<MockAnySpan>()};
334 EXPECT_NO_THROW({
335 breaker.WordBreak(spans_, tpstyle_, FontProviders::Create());
336 ASSERT_EQ(spans_.size(), 1);
337 auto span = spans_[0].TryToAnySpan();
338 ASSERT_NE(span, nullptr);
339 });
340 }
341
342 /**
343 * @tc.name: WordBreak2
344 * @tc.desc: Verify the WordBreak
345 * @tc.type:FUNC
346 */
347 HWTEST_F(TextBreakerTest, WordBreak2, TestSize.Level1)
348 {
349 // 1: Set the Return value of Measurer
350 PrepareWordBreak(1, cgs1_);
351
352 spans_ = {tsNormal_};
353 EXPECT_NO_THROW({
354 breaker.WordBreak(spans_, tpstyle_, FontProviders::Create());
355 ASSERT_EQ(spans_.size(), 0);
356 });
357 }
358
359 /**
360 * @tc.name: WordBreak3
361 * @tc.desc: Verify the WordBreak
362 * @tc.type:FUNC
363 */
364 HWTEST_F(TextBreakerTest, WordBreak3, TestSize.Level1)
365 {
366 EXPECT_NO_THROW({
367 breaker.WordBreak(spans_, tpstyle_, FontProviders::Create());
368 ASSERT_EQ(spans_.size(), 0);
369 });
370 }
371
372 /**
373 * @tc.name: WordBreak4
374 * @tc.desc: Verify the WordBreak
375 * @tc.type:FUNC
376 */
377 HWTEST_F(TextBreakerTest, WordBreak4, TestSize.Level1)
378 {
379 auto type = WordBreakType::BREAK_WORD;
380 // {0, 4} is {leftIndex, rightIndex}
381 boundaries = {{ 0, 4 }};
382 PrepareWordBreak(0, cgs1_, type);
383
384 spans_ = {tsNormal_};
385 EXPECT_NO_THROW({
386 breaker.WordBreak(spans_, tpstyle_, FontProviders::Create());
387 ASSERT_EQ(spans_.size(), 1);
388 });
389 }
390
391 /**
392 * @tc.name: WordBreak5
393 * @tc.desc: Verify the WordBreak
394 * @tc.type:FUNC
395 */
396 HWTEST_F(TextBreakerTest, WordBreak5, TestSize.Level1)
397 {
398 auto type = WordBreakType::BREAK_ALL;
399 boundaries = {{ 0, 4 }};
400 PrepareWordBreak(0, cgs1_, type);
401
402 spans_ = {tsNormal_};
403 EXPECT_NO_THROW({
404 breaker.WordBreak(spans_, tpstyle_, FontProviders::Create());
405 ASSERT_EQ(spans_.size(), 4);
406 });
407 }
408
409 /**
410 * @tc.name: WordBreak6
411 * @tc.desc: Verify the WordBreak
412 * @tc.type:FUNC
413 */
414 HWTEST_F(TextBreakerTest, WordBreak6, TestSize.Level1)
415 {
416 auto type = WordBreakType::BREAK_ALL;
417 boundaries = {};
418 PrepareWordBreak(0, cgs1_, type);
419
420 spans_ = {tsNormal_};
421 EXPECT_NO_THROW({
422 breaker.WordBreak(spans_, tpstyle_, FontProviders::Create());
423 ASSERT_EQ(spans_.size(), 0);
424 });
425 }
426 } // namespace TextEngine
427 } // namespace Rosen
428 } // namespace OHOS
429