• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "bidi_processer.h"
17 #include "mock/mock_any_span.h"
18 #include "texgine_exception.h"
19 #include "text_breaker.h"
20 #include "text_converter.h"
21 #include "text_span.h"
22 
23 #include <gtest/gtest.h>
24 #include <unicode/ubidi.h>
25 
26 using namespace testing;
27 using namespace testing::ext;
28 
29 struct UBiDi {};
30 
31 namespace {
32 std::unique_ptr<UBiDi> g_bidi = nullptr;
33 std::vector<int> g_start;
34 std::vector<int> g_length;
35 } // namespace
36 
37 U_STABLE UBiDi *U_EXPORT2
ubidi_open(void)38 ubidi_open(void)
39 {
40     return g_bidi.get();
41 }
42 
43 U_STABLE void U_EXPORT2
ubidi_close(UBiDi * pBiDi)44 ubidi_close(UBiDi *pBiDi) {}
45 
46 auto g_status = U_ZERO_ERROR;
47 U_STABLE void U_EXPORT2
ubidi_setPara(UBiDi * pBiDi,const UChar * text,int32_t length,UBiDiLevel paraLevel,UBiDiLevel * embeddingLevels,UErrorCode * pErrorCode)48 ubidi_setPara(UBiDi *pBiDi, const UChar *text, int32_t length,
49               UBiDiLevel paraLevel, UBiDiLevel *embeddingLevels,
50               UErrorCode *pErrorCode)
51 {
52     *pErrorCode = g_status;
53 }
54 
55 int g_size = 0;
56 U_STABLE int32_t U_EXPORT2
ubidi_countRuns(UBiDi * pBiDi,UErrorCode * pErrorCode)57 ubidi_countRuns(UBiDi *pBiDi, UErrorCode *pErrorCode)
58 {
59     return g_size;
60 }
61 
62 int g_count = 0;
63 UBiDiDirection g_rtl = UBIDI_RTL;
64 U_STABLE UBiDiDirection U_EXPORT2
ubidi_getVisualRun(UBiDi * pBiDi,int32_t runIndex,int32_t * pLogicalStart,int32_t * pLength)65 ubidi_getVisualRun(UBiDi *pBiDi, int32_t runIndex,
66                    int32_t *pLogicalStart, int32_t *pLength)
67 {
68     assert(g_count < g_size);
69     *pLogicalStart = (g_start[g_count]);
70     *pLength = (g_length[g_count]);
71     g_count++;
72     return g_rtl;
73 }
74 
75 struct Style {
76     int size = 1;
77     std::unique_ptr<UBiDi> bidi = std::make_unique<UBiDi>();
78     UErrorCode status = U_ZERO_ERROR;
79     UBiDiDirection rtl = UBIDI_RTL;
80     std::vector<int> start = {0};
81     std::vector<int> length = {4};
82 };
83 
84 namespace {
InitMyMockVars(Style style)85 void InitMyMockVars(Style style)
86 {
87     g_count = 0;
88     g_size = style.size;
89     g_bidi = std::move(style.bidi);
90     g_status = style.status;
91     g_rtl = style.rtl;
92     g_start = style.start;
93     g_length = style.length;
94 }
95 } // namespace
96 
97 namespace OHOS {
98 namespace Rosen {
99 namespace TextEngine {
100 class BidiProcesserTest : public testing::Test {
101 public:
SetUpTestCase()102     static void SetUpTestCase()
103     {
104         tpstyle_ = std::make_shared<TypographyStyle>();
105         cgs1_.PushBack({.chars = TextConverter::ToUTF16("m"), .glyphs = {{0x013B, 13.664}}});
106         cgs1_.PushBack({.chars = TextConverter::ToUTF16("o"), .glyphs = {{0x0145, 9.456}}});
107         cgs1_.PushBack({.chars = TextConverter::ToUTF16("s"), .glyphs = {{0x0166, 7.28}}});
108         cgs1_.PushBack({.chars = TextConverter::ToUTF16("t"), .glyphs = {{0x016E, 5.88}}});
109     }
110 
111     static inline std::shared_ptr<TypographyStyle> tpstyle_ = nullptr;
112     static inline TextStyle textStyle_;
113     static inline CharGroups cgs1_ = CharGroups::CreateEmpty();
114     std::vector<VariantSpan> spans_;
115     BidiProcesser bp;
116 };
117 
118 /**
119  * @tc.name: DoBidiProcess1
120  * @tc.desc: Verify the DoBidiProcess
121  * @tc.type:FUNC
122  * @tc.require: issueI6V6J4
123  */
124 HWTEST_F(BidiProcesserTest, DoBidiProcess1, TestSize.Level1)
125 {
126     CharGroups cgs = CharGroups::CreateEmpty();
127 
128     try {
129         bp.DoBidiProcess(cgs, TextDirection::LTR);
130     } catch(const TexgineException &err) {
131         ASSERT_EQ(ExceptionType::INVALID_ARGUMENT, err.code);
132     }
133 }
134 
135 /**
136  * @tc.name: DoBidiProcess2
137  * @tc.desc: Verify the DoBidiProcess
138  * @tc.type:FUNC
139  * @tc.require: issueI6V6J4
140  */
141 HWTEST_F(BidiProcesserTest, DoBidiProcess2, TestSize.Level1)
142 {
143     CharGroups cgs = {};
144 
145     try {
146         bp.DoBidiProcess(cgs, TextDirection::LTR);
147     } catch(const TexgineException &err) {
148         ASSERT_EQ(ExceptionType::INVALID_ARGUMENT, err.code);
149     }
150 }
151 
152 /**
153  * @tc.name: DoBidiProcess3
154  * @tc.desc: Verify the DoBidiProcess
155  * @tc.type:FUNC
156  * @tc.require: issueI6V6J4
157  */
158 HWTEST_F(BidiProcesserTest, DoBidiProcess3, TestSize.Level1)
159 {
160     InitMyMockVars({.bidi = nullptr});
161 
162     try {
163         bp.DoBidiProcess(cgs1_, TextDirection::LTR);
164     } catch(const TexgineException &err) {
165         ASSERT_EQ(ExceptionType::API_FAILED, err.code);
166     }
167 }
168 
169 /**
170  * @tc.name: DoBidiProcess4
171  * @tc.desc: Verify the DoBidiProcess
172  * @tc.type:FUNC
173  * @tc.require: issueI6V6J4
174  */
175 HWTEST_F(BidiProcesserTest, DoBidiProcess4, TestSize.Level1)
176 {
177     InitMyMockVars({.status = U_ILLEGAL_ARGUMENT_ERROR});
178 
179     try {
180         bp.DoBidiProcess(cgs1_, TextDirection::LTR);
181     } catch(const TexgineException &err) {
182         ASSERT_EQ(ExceptionType::API_FAILED, err.code);
183     }
184 }
185 
186 /**
187  * @tc.name: DoBidiProcess5
188  * @tc.desc: Verify the DoBidiProcess
189  * @tc.type:FUNC
190  * @tc.require: issueI6V6J4
191  */
192 HWTEST_F(BidiProcesserTest, DoBidiProcess5, TestSize.Level1)
193 {
194     // set ubidi_countRuns return 0
195     InitMyMockVars({.size = 0,});
196 
197     EXPECT_NO_THROW({
198         auto ret = bp.DoBidiProcess(cgs1_, TextDirection::LTR);
199         ASSERT_EQ(ret.size(), 0);
200     });
201 }
202 
203 /**
204  * @tc.name: DoBidiProcess6
205  * @tc.desc: Verify the DoBidiProcess
206  * @tc.type:FUNC
207  * @tc.require: issueI6V6J4
208  */
209 HWTEST_F(BidiProcesserTest, DoBidiProcess6, TestSize.Level1)
210 {
211     // -1, 1: Set the output parameter of ubidi_getVisualRun
212     InitMyMockVars({.start = {-1}, .length = {1},});
213 
214     try {
215         bp.DoBidiProcess(cgs1_, TextDirection::LTR);
216     } catch(const TexgineException &err) {
217         ASSERT_EQ(ExceptionType::API_FAILED, err.code);
218     }
219 }
220 
221 /**
222  * @tc.name: DoBidiProcess7
223  * @tc.desc: Verify the DoBidiProcess
224  * @tc.type:FUNC
225  * @tc.require: issueI6V6J4
226  */
227 HWTEST_F(BidiProcesserTest, DoBidiProcess7, TestSize.Level1)
228 {
229     InitMyMockVars({.start = {1}, .length = {-1},});
230 
231     try {
232         bp.DoBidiProcess(cgs1_, TextDirection::LTR);
233     } catch(const TexgineException &err) {
234         ASSERT_EQ(ExceptionType::API_FAILED, err.code);
235     }
236 }
237 
238 /**
239  * @tc.name: DoBidiProcess8
240  * @tc.desc: Verify the DoBidiProcess
241  * @tc.type:FUNC
242  * @tc.require: issueI6V6J4
243  */
244 HWTEST_F(BidiProcesserTest, DoBidiProcess8, TestSize.Level1)
245 {
246     InitMyMockVars({.size = 4, .start = {0, 1, 2, 3}, .length = {1, 1, 1, 1}});
247     auto c = cgs1_.GetSub(0, 1);
248     EXPECT_NO_THROW({
249         auto ret = bp.DoBidiProcess(c, TextDirection::LTR);
250         ASSERT_EQ(ret.size(), 1);
251     });
252 }
253 
254 /**
255  * @tc.name: DoBidiProcess9
256  * @tc.desc: Verify the DoBidiProcess
257  * @tc.type:FUNC
258  * @tc.require: issueI6V6J4
259  */
260 HWTEST_F(BidiProcesserTest, DoBidiProcess9, TestSize.Level1)
261 {
262     InitMyMockVars({});
263 
264     EXPECT_NO_THROW({
265         auto ret = bp.DoBidiProcess(cgs1_, TextDirection::LTR);
266         ASSERT_EQ(ret.size(), 1);
267         ASSERT_EQ(ret[0].rtl, true);
268     });
269 }
270 
271 /**
272  * @tc.name: DoBidiProcess10
273  * @tc.desc: Verify the DoBidiProcess
274  * @tc.type:FUNC
275  * @tc.require: issueI6V6J4
276  */
277 HWTEST_F(BidiProcesserTest, DoBidiProcess10, TestSize.Level1)
278 {
279     InitMyMockVars({.rtl = UBIDI_LTR,});
280 
281     EXPECT_NO_THROW({
282         auto ret = bp.DoBidiProcess(cgs1_, TextDirection::LTR);
283         ASSERT_EQ(ret.size(), 1);
284         ASSERT_EQ(ret[0].rtl, false);
285     });
286 }
287 
288 /**
289  * @tc.name: ProcessBidiText1
290  * @tc.desc: Verify the ProcessBidiText
291  * @tc.type:FUNC
292  * @tc.require: issueI6V6J4
293  */
294 HWTEST_F(BidiProcesserTest, ProcessBidiText1, TestSize.Level1)
295 {
296     InitMyMockVars({});
297     spans_ = {std::make_shared<MockAnySpan>(), TextSpan::MakeFromCharGroups(cgs1_), std::make_shared<MockAnySpan>()};
298 
299     EXPECT_NO_THROW({
300         auto ret = bp.ProcessBidiText(spans_, TextDirection::LTR);
301         ASSERT_EQ(ret.size(), 3);
302         ASSERT_NE(ret[0].TryToAnySpan(), nullptr);
303         ASSERT_NE(ret[1].TryToTextSpan(), nullptr);
304         ASSERT_NE(ret[2].TryToAnySpan(), nullptr);
305     });
306 }
307 
308 /**
309  * @tc.name: ProcessBidiText2
310  * @tc.desc: Verify the ProcessBidiText
311  * @tc.type:FUNC
312  * @tc.require: issueI6V6J4
313  */
314 HWTEST_F(BidiProcesserTest, ProcessBidiText2, TestSize.Level1)
315 {
316     EXPECT_NO_THROW({
317         auto ret = bp.ProcessBidiText(spans_, TextDirection::LTR);
318         ASSERT_EQ(ret.size(), 0);
319     });
320 }
321 
322 /**
323  * @tc.name: ProcessBidiText3
324  * @tc.desc: Verify the ProcessBidiText
325  * @tc.type:FUNC
326  * @tc.require: issueI6V6J4
327  */
328 HWTEST_F(BidiProcesserTest, ProcessBidiText3, TestSize.Level1)
329 {
330     InitMyMockVars({.size = 4, .start = {0, 1, 2, 3}, .length = {1, 1, 1, 1}});
331     auto c = cgs1_.GetSub(0, 1);
332     spans_ = {std::make_shared<MockAnySpan>(), TextSpan::MakeFromCharGroups(c), std::make_shared<MockAnySpan>()};
333 
334     EXPECT_NO_THROW({
335         auto ret = bp.ProcessBidiText(spans_, TextDirection::LTR);
336         ASSERT_EQ(ret.size(), 3);
337         ASSERT_NE(ret[0].TryToAnySpan(), nullptr);
338         auto span1 = ret[1].TryToTextSpan();
339         ASSERT_NE(span1, nullptr);
340         ASSERT_EQ(span1->IsRTL(), true);
341         ASSERT_NE(ret[2].TryToAnySpan(), nullptr);
342     });
343 }
344 } // namespace TextEngine
345 } // namespace Rosen
346 } // namespace OHOS
347