1 /*
2  * Copyright (c) 2021 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 "percent_tdd_test.h"
17 
18 #include "ace_log.h"
19 #include "component.h"
20 #include "component_utils.h"
21 #include "js_app_context.h"
22 #include "js_app_environment.h"
23 #include "js_fwk_common.h"
24 #include "number_parser.h"
25 
26 namespace OHOS {
27 namespace ACELite {
28 const char * const PercentTddTest::ATTR_STATIC_STYLE_NAME = "staticStyle";
29 const char * const PercentTddTest::STYLE_WIDTH_NAME = "width";
30 const char * const PercentTddTest::STYLE_HEIGHT_NAME = "height";
31 const char * const PercentTddTest::STYLE_TOP_NAME = "top";
32 const char * const PercentTddTest::STYLE_LEFT_NAME = "left";
33 const char * const PercentTddTest::STYLE_MARGINTOP_NAME = "marginTop";
34 const char * const PercentTddTest::STYLE_MARGINLEFT_NAME = "marginLeft";
35 const char * const PercentTddTest::STYLE_MARGINRIGHT_NAME = "marginRight";
36 const char * const PercentTddTest::STYLE_MARGINBOTTOM_NAME = "marginBottom";
37 const char * const PercentTddTest::FUNC_CREATE_ELEMENT = "_c";
SetUp()38 void PercentTddTest::SetUp()
39 {
40     JsAppEnvironment *env = JsAppEnvironment::GetInstance();
41     if (env == nullptr) {
42         // should never happen
43         return;
44     }
45     env->InitJsFramework();
46 }
47 
TearDown()48 void PercentTddTest::TearDown()
49 {
50     JsAppEnvironment *env = JsAppEnvironment::GetInstance();
51     JsAppContext *context = JsAppContext::GetInstance();
52     if (env == nullptr || context == nullptr) {
53         // should never happen
54         return;
55     }
56     context->ReleaseStyles();
57     env->Cleanup();
58 }
59 
PrepareOptions(JSValue & options,JSValue & staticStyle) const60 void PercentTddTest::PrepareOptions(JSValue &options, JSValue &staticStyle) const
61 {
62     // prepare component options
63     options = JSObject::Create();
64     staticStyle = JSObject::Create();
65     JSObject::Set(options, ATTR_STATIC_STYLE_NAME, staticStyle);
66 }
67 
SetStyleWithValue(JSValue target,const char * key,const char * value) const68 void PercentTddTest::SetStyleWithValue(JSValue target, const char *key, const char *value) const
69 {
70     if ((JSUndefined::Is(target)) || (key == nullptr) || (value == nullptr)) {
71         return;
72     }
73     JSValue propValue = JSString::Create(value);
74     JSObject::Set(target, key, propValue);
75     ReleaseJerryValue(propValue, VA_ARG_END_FLAG);
76 }
77 
ConfigStylesWithRect(JSValue staticStyle,const char * widthValue,const char * heightValue) const78 void PercentTddTest::ConfigStylesWithRect(JSValue staticStyle, const char *widthValue, const char *heightValue) const
79 {
80     SetStyleWithValue(staticStyle, STYLE_WIDTH_NAME, widthValue);
81     SetStyleWithValue(staticStyle, STYLE_HEIGHT_NAME, heightValue);
82 }
83 
ConfigStylesWithPosition(JSValue staticStyle,const char * topValue,const char * leftValue) const84 void PercentTddTest::ConfigStylesWithPosition(JSValue staticStyle, const char *topValue, const char *leftValue) const
85 {
86     SetStyleWithValue(staticStyle, STYLE_TOP_NAME, topValue);
87     SetStyleWithValue(staticStyle, STYLE_LEFT_NAME, leftValue);
88 }
89 
ConfigStylesWithMargin(JSValue staticStyle,const char * marginValue) const90 void PercentTddTest::ConfigStylesWithMargin(JSValue staticStyle, const char *marginValue) const
91 {
92     ConfigStylesWithMargins(staticStyle, marginValue, marginValue, marginValue, marginValue);
93 }
94 
ConfigStylesWithMargins(JSValue staticStyle,const char * marginTopValue,const char * marginLeftValue,const char * marginRightValue,const char * marginBottomValue) const95 void PercentTddTest::ConfigStylesWithMargins(JSValue staticStyle,
96                                              const char *marginTopValue,
97                                              const char *marginLeftValue,
98                                              const char *marginRightValue,
99                                              const char *marginBottomValue) const
100 {
101     SetStyleWithValue(staticStyle, STYLE_MARGINTOP_NAME, marginTopValue);
102     SetStyleWithValue(staticStyle, STYLE_MARGINLEFT_NAME, marginLeftValue);
103     SetStyleWithValue(staticStyle, STYLE_MARGINRIGHT_NAME, marginRightValue);
104     SetStyleWithValue(staticStyle, STYLE_MARGINBOTTOM_NAME, marginBottomValue);
105 }
106 
DumpJSObjectJson(JSValue value) const107 void PercentTddTest::DumpJSObjectJson(JSValue value) const
108 {
109     if (JSUndefined::Is(value)) {
110         return;
111     }
112     char *jsonStr = MallocStringOf(jerry_json_stringify(value));
113     HILOG_DEBUG(HILOG_MODULE_ACE, "JSObject: %{public}s", jsonStr);
114     ACE_FREE(jsonStr);
115 }
116 
BuildViewTree(JSValue element,int16_t parentWidth,int16_t parentHeight) const117 Component *PercentTddTest::BuildViewTree(JSValue element, int16_t parentWidth, int16_t parentHeight) const
118 {
119     if (JSUndefined::Is(element)) {
120         return nullptr;
121     }
122 
123     Component *component = ComponentUtils::GetComponentFromBindingObject(element);
124     if (component != nullptr) {
125         ConstrainedParameter parentParameter = {parentWidth, parentHeight};
126         Component::BuildViewTree(component, nullptr, parentParameter);
127     }
128     return component;
129 }
130 
VerifyDimension(JSValue element,uint16_t keyID,int16_t targetPX) const131 void PercentTddTest::VerifyDimension(JSValue element, uint16_t keyID, int16_t targetPX) const
132 {
133     EXPECT_FALSE(JSUndefined::Is(element));
134     Component *component = ComponentUtils::GetComponentFromBindingObject(element);
135     EXPECT_FALSE(component == nullptr);
136     if (component == nullptr) {
137         HILOG_ERROR(HILOG_MODULE_ACE, "can not fetch component from element");
138         return;
139     }
140     Dimension dimension = component->GetDimension(keyID);
141     EXPECT_EQ(dimension.type, DimensionType::TYPE_PIXEL);
142     EXPECT_EQ(dimension.value.pixel, targetPX);
143 }
144 
145 /**
146  * @tc.name: AceliteFrameworkPercentParse001
147  * @tc.desc: Verify the percent converting process
148  */
149 HWTEST_F(PercentTddTest, PercentParse001, TestSize.Level1)
150 {
151     uint16_t strLength = 5;
152     float percentValue = 0;
153     /**
154      * @tc.steps: step1. pass nullptr for parsing
155      */
156     bool result = NumberParser::ParsePercentValue(nullptr, strLength, percentValue);
157     /**
158      * @tc.steps: step2. check if parse failed
159      */
160     EXPECT_FALSE(result);
161 }
162 
163 /**
164  * @tc.name: AceliteFrameworkPercentParse002
165  * @tc.desc: Verify the percent converting process
166  */
167 HWTEST_F(PercentTddTest, PercentParse002, TestSize.Level1)
168 {
169     uint16_t strLength = 1;
170     const char *strBuffer = "100%";
171     float percentValue = 0;
172     /**
173      * @tc.steps: step1. give the length small than the min length
174      */
175     bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
176     /**
177      * @tc.steps: step2. check if parse failed
178      */
179     EXPECT_FALSE(result);
180 }
181 
182 /**
183  * @tc.name: AceliteFrameworkPercentParse003
184  * @tc.desc: Verify the percent converting process
185  */
186 HWTEST_F(PercentTddTest, PercentParse003, TestSize.Level1)
187 {
188     uint16_t strLength = 4;
189     const char *strBuffer = "100%";
190     float percentValue = 0;
191     /**
192      * @tc.steps: step1. give the corrent string and length
193      */
194     bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
195     EXPECT_TRUE(result);
196     float correctValue = 100;
197     /**
198      * @tc.steps: step2. check if parse successfully
199      */
200     EXPECT_EQ(percentValue, correctValue);
201 }
202 
203 /**
204  * @tc.name: AceliteFrameworkPercentParse004
205  * @tc.desc: Verify the percent converting process
206  */
207 HWTEST_F(PercentTddTest, PercentParse004, TestSize.Level1)
208 {
209     uint16_t strLength = 7;
210     /**
211      * @tc.steps: step1. give one string not in digit format
212      */
213     const char *strBuffer = "abcdef%";
214     float percentValue = 0;
215     bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
216     /**
217      * @tc.steps: step2. check if parse failed
218      */
219     EXPECT_FALSE(result);
220 }
221 
222 /**
223  * @tc.name: AceliteFrameworkPercentParse005
224  * @tc.desc: Verify the percent converting process
225  */
226 HWTEST_F(PercentTddTest, PercentParse005, TestSize.Level1)
227 {
228     uint16_t strLength = 20;
229     /**
230      * @tc.steps: step1. give one string which is too long
231      */
232     const char *strBuffer = "1567890123343433434%";
233     float percentValue = 0;
234     bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
235     /**
236      * @tc.steps: step2. check if parse failed
237      */
238     EXPECT_FALSE(result);
239 }
240 
241 /**
242  * @tc.name: AceliteFrameworkPercentParse006
243  * @tc.desc: Verify the percent converting process
244  */
245 HWTEST_F(PercentTddTest, PercentParse006, TestSize.Level1)
246 {
247     uint16_t strLength = 4;
248     /**
249      * @tc.steps: step1. give one string which includes no-digit charater
250      */
251     const char *strBuffer = "50a%";
252     float percentValue = 0;
253     bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
254     /**
255      * @tc.steps: step2. check if parse failed
256      */
257     EXPECT_FALSE(result);
258 }
259 
260 /**
261  * @tc.name: AceliteFrameworkPercentParse007
262  * @tc.desc: Verify the percent converting process
263  */
264 HWTEST_F(PercentTddTest, PercentParse007, TestSize.Level1)
265 {
266     uint16_t strLength = 4;
267     /**
268      * @tc.steps: step1. give one negative number
269      */
270     const char *strBuffer = "-40%";
271     float percentValue = 0;
272     bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
273     /**
274      * @tc.steps: step2. check if parse successfully and the result is negative number
275      */
276     EXPECT_TRUE(result);
277     float correctValue = -40;
278     EXPECT_EQ(percentValue, correctValue);
279 }
280 
281 /**
282  * @tc.name: AceliteFrameworkPercentParse008
283  * @tc.desc: Verify the percent converting process
284  */
285 HWTEST_F(PercentTddTest, PercentParse008, TestSize.Level1)
286 {
287     uint16_t strLength = 6;
288     /**
289      * @tc.steps: step1. give one string which is not number and not including %
290      */
291     const char *strBuffer = "abcdef";
292     float percentValue = 0;
293     bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
294     /**
295      * @tc.steps: step2. check if parse failed
296      */
297     EXPECT_FALSE(result);
298 }
299 
300 /**
301  * @tc.name: AceliteFrameworkPercentParse009
302  * @tc.desc: Verify the percent converting process
303  */
304 HWTEST_F(PercentTddTest, PercentParse009, TestSize.Level1)
305 {
306     uint16_t strLength = 100;
307     /**
308      * @tc.steps: step1. give one string which is not number and including %
309      */
310     const char *strBuffer = "abcdef%";
311     float percentValue = 0;
312     bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
313     /**
314      * @tc.steps: step2. check if parse failed
315      */
316     EXPECT_FALSE(result);
317 }
318 
319 /**
320  * @tc.name: AceliteFrameworkPercentParse010
321  * @tc.desc: Verify the percent converting process
322  */
323 HWTEST_F(PercentTddTest, PercentParse010, TestSize.Level1)
324 {
325     /**
326      * @tc.steps: step1. give one string which is bigger than float range
327      */
328     const char *strBuffer = "123456789012345%";
329     uint16_t strLength = 16;
330     float percentValue = 0;
331     bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
332     EXPECT_TRUE(result);
333     /**
334      * @tc.steps: step2. check the value is correct
335      */
336     float correctValue = static_cast<float>(123456789012345);
337     EXPECT_EQ(percentValue, correctValue);
338 }
339 
340 /**
341  * @tc.name: AceliteFrameworkPercentParse011
342  * @tc.desc: Verify the percent converting process
343  */
344 HWTEST_F(PercentTddTest, PercentParse011, TestSize.Level1)
345 {
346     float percentValue = 0;
347     uint16_t strLength = 16;
348     /**
349      * @tc.steps: step1. give one very small value
350      */
351     const char *strBuffer = "-12345678901234%";
352     bool result = NumberParser::ParsePercentValue(strBuffer, strLength, percentValue);
353     EXPECT_TRUE(result);
354     /**
355      * @tc.steps: step2. check the value is correct
356      */
357     float correctValue = static_cast<float>(-12345678901234);
358     EXPECT_EQ(percentValue, correctValue);
359 }
360 
361 /**
362  * @tc.name: AceliteFrameworkPercentSupport001
363  * @tc.desc: Verify the percent processing on div.
364  */
365 HWTEST_F(PercentTddTest, PercentSupport001, TestSize.Level1)
366 {
367     TDD_CASE_BEGIN();
368     /**
369      * @tc.steps: step1. prepare child component
370      */
371     JSValue textTag = JSString::Create("text");
372     JSValue textOption;
373     JSValue textStaticStyle;
374     PrepareOptions(textOption, textStaticStyle);
375     ConfigStylesWithRect(textStaticStyle, "50%", "50%");
376     JSValue textArgs[ARG_LENGTH_2] = {textTag, textOption};
377     JSValue textEl = JSGlobal::Call(FUNC_CREATE_ELEMENT, textArgs, ARG_LENGTH_2);
378     /**
379      * @tc.steps: step2. prepare parent component
380      */
381     JSValue divTag = JSString::Create("div");
382     JSValue divOption;
383     JSValue divStaticStyle;
384     PrepareOptions(divOption, divStaticStyle);
385     ConfigStylesWithRect(divStaticStyle, "100%", "100%");
386     JSValue divChildren = JSArray::Create(0);
387     JSArray::Push(divChildren, textEl);
388     JSValue divArgs[ARG_LENGTH_3] = {divTag, divOption, divChildren};
389     JSValue divEl = JSGlobal::Call(FUNC_CREATE_ELEMENT, divArgs, ARG_LENGTH_3);
390     /**
391      * @tc.steps: step3. trigger render and build
392      */
393     const int16_t screenWidth = 454;
394     const int16_t screenHeight = 454;
395     Component *divComponent = BuildViewTree(divEl, screenWidth, screenHeight);
396     /**
397      * @tc.steps: step4. verify
398      */
399     VerifyDimension(divEl, K_WIDTH, screenWidth);
400     const int16_t halfNum = 2;
401     VerifyDimension(textEl, K_HEIGHT, (screenHeight / halfNum));
402     /**
403      * @tc.steps: step5. release resource
404      */
405     ComponentUtils::ReleaseComponents(divComponent);
406     ReleaseJerryValue(textTag, textStaticStyle, textOption, textEl, VA_ARG_END_FLAG);
407     ReleaseJerryValue(divTag, divStaticStyle, divOption, divEl, divChildren, VA_ARG_END_FLAG);
408     TDD_CASE_END();
409 }
410 
411 /**
412  * @tc.name: AceliteFrameworkPercentSupport002
413  * @tc.desc: Verify the percent processing on component.
414  */
415 HWTEST_F(PercentTddTest, PercentSupport002, TestSize.Level0)
416 {
417     TDD_CASE_BEGIN();
418     /**
419      * @tc.steps: step1. prepare child component
420      */
421     JSValue textTag = JSString::Create("text");
422     JSValue textOption;
423     JSValue textStaticStyle;
424     PrepareOptions(textOption, textStaticStyle);
425     ConfigStylesWithPosition(textStaticStyle, "10%", "10%");
426     JSValue textArgs[ARG_LENGTH_2] = {textTag, textOption};
427     JSValue textEl = JSGlobal::Call(FUNC_CREATE_ELEMENT, textArgs, ARG_LENGTH_2);
428     /**
429      * @tc.steps: step2. prepare parent component
430      */
431     JSValue stackTag = JSString::Create("stack");
432     JSValue stackOption;
433     JSValue stackStaticStyle;
434     PrepareOptions(stackOption, stackStaticStyle);
435     ConfigStylesWithRect(stackStaticStyle, "50%", "50%");
436     JSValue stackChildren = JSArray::Create(0);
437     JSArray::Push(stackChildren, textEl);
438     JSValue stackArgs[ARG_LENGTH_3] = {stackTag, stackOption, stackChildren};
439     JSValue stackEl = JSGlobal::Call(FUNC_CREATE_ELEMENT, stackArgs, ARG_LENGTH_3);
440     /**
441      * @tc.steps: step3. trigger render and build
442      */
443     const int16_t screenWidth = 1024;
444     const int16_t screenHeight = 768;
445     Component *stackComponent = BuildViewTree(stackEl, screenWidth, screenHeight);
446     /**
447      * @tc.steps: step4. verify
448      */
449     const int16_t halfNum = 2;
450     const int16_t marginPercentNum = 10;
451     VerifyDimension(stackEl, K_WIDTH, (screenWidth / halfNum));
452     VerifyDimension(textEl, K_TOP, ((screenHeight / halfNum) / marginPercentNum));
453     /**
454      * @tc.steps: step5. release resource
455      */
456     ComponentUtils::ReleaseComponents(stackComponent);
457     ReleaseJerryValue(textTag, textStaticStyle, textOption, textEl, VA_ARG_END_FLAG);
458     ReleaseJerryValue(stackTag, stackStaticStyle, stackOption, stackEl, stackChildren, VA_ARG_END_FLAG);
459     TDD_CASE_END();
460 }
461 
462 /**
463  * @tc.name: AceliteFrameworkPercentSupport003
464  * @tc.desc: Verify the percent processing on component.
465  */
466 HWTEST_F(PercentTddTest, PercentSupport003, TestSize.Level0)
467 {
468     TDD_CASE_BEGIN();
469     /**
470      * @tc.steps: step1. prepare child component
471      */
472     JSValue labelTag = JSString::Create("text");
473     JSValue labelOption;
474     JSValue labelStaticStyle;
475     PrepareOptions(labelOption, labelStaticStyle);
476     ConfigStylesWithMargins(labelStaticStyle, "10%", "10%", "10%", "10%");
477     JSValue labelArgs[ARG_LENGTH_2] = {labelTag, labelOption};
478     JSValue textEl = JSGlobal::Call(FUNC_CREATE_ELEMENT, labelArgs, ARG_LENGTH_2);
479     /**
480      * @tc.steps: step2. prepare parent component
481      */
482     JSValue containerTag = JSString::Create("div");
483     JSValue containerOption;
484     JSValue containerStaticStyle;
485     PrepareOptions(containerOption, containerStaticStyle);
486     ConfigStylesWithRect(containerStaticStyle, "100%", "100%");
487     JSValue containerChildren = JSArray::Create(0);
488     JSArray::Push(containerChildren, textEl);
489     JSValue containerArgs[ARG_LENGTH_3] = {containerTag, containerOption, containerChildren};
490     JSValue containerEl = JSGlobal::Call(FUNC_CREATE_ELEMENT, containerArgs, ARG_LENGTH_3);
491     /**
492      * @tc.steps: step3. trigger render and build
493      */
494     const int16_t screenWidth = 600;
495     const int16_t screenHeight = 800;
496     Component *containerComponent = BuildViewTree(containerEl, screenWidth, screenHeight);
497     /**
498      * @tc.steps: step4. verify
499      */
500     const int16_t marginPercent = 10;
501     VerifyDimension(textEl, K_MARGIN_TOP, (screenHeight / marginPercent));
502     /**
503      * @tc.steps: step5. release resource
504      */
505     ComponentUtils::ReleaseComponents(containerComponent);
506     ReleaseJerryValue(labelTag, labelStaticStyle, labelOption, textEl, VA_ARG_END_FLAG);
507     ReleaseJerryValue(containerTag, containerStaticStyle, containerOption, containerEl, containerChildren,
508                       VA_ARG_END_FLAG);
509     TDD_CASE_END();
510 }
511 
512 /**
513  * used for debugging TDD implementation on simulator
514  */
RunTests()515 void PercentTddTest::RunTests()
516 {
517 #ifndef TDD_ASSERTIONS
518     PercentParse001();
519     PercentParse002();
520     PercentParse003();
521     PercentParse004();
522     PercentParse005();
523     PercentParse006();
524     PercentParse007();
525     PercentParse008();
526     PercentParse009();
527     PercentParse010();
528     PercentParse011();
529     PercentSupport001();
530     PercentSupport002();
531     PercentSupport003();
532 #endif // TDD_ASSERTIONS
533 }
534 } // namespace ACELite
535 } // namespace OHOS
536