Rebase of facebook flexbox to yoga
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit-third-party / yoga / YGMeasureTest.cpp
1 /**
2  * Copyright (c) 2014-present, Facebook, Inc.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7
8 #include <gtest/gtest.h>
9 #include <yoga/YGNode.h>
10 #include <yoga/Yoga.h>
11
12 static YGSize _measure(YGNodeRef node,
13                        float width,
14                        YGMeasureMode widthMode,
15                        float height,
16                        YGMeasureMode heightMode) {
17   int* measureCount = (int*)node->getContext();
18   if (measureCount) {
19     (*measureCount)++;
20   }
21
22   return YGSize{
23       .width = 10, .height = 10,
24   };
25 }
26
27 static YGSize _simulate_wrapping_text(YGNodeRef node,
28                                       float width,
29                                       YGMeasureMode widthMode,
30                                       float height,
31                                       YGMeasureMode heightMode) {
32   if (widthMode == YGMeasureModeUndefined || width >= 68) {
33     return YGSize{.width = 68, .height = 16};
34   }
35
36   return YGSize{
37       .width = 50, .height = 32,
38   };
39 }
40
41 static YGSize _measure_assert_negative(YGNodeRef node,
42                                        float width,
43                                        YGMeasureMode widthMode,
44                                        float height,
45                                        YGMeasureMode heightMode) {
46   EXPECT_GE(width, 0);
47   EXPECT_GE(height, 0);
48
49   return YGSize{
50     .width = 0, .height = 0,
51   };
52 }
53
54 TEST(YogaTest, dont_measure_single_grow_shrink_child) {
55   const YGNodeRef root = YGNodeNew();
56   YGNodeStyleSetWidth(root, 100);
57   YGNodeStyleSetHeight(root, 100);
58
59   int measureCount = 0;
60
61   const YGNodeRef root_child0 = YGNodeNew();
62   root_child0->setContext(&measureCount);
63   root_child0->setMeasureFunc(_measure);
64   YGNodeStyleSetFlexGrow(root_child0, 1);
65   YGNodeStyleSetFlexShrink(root_child0, 1);
66   YGNodeInsertChild(root, root_child0, 0);
67
68   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
69
70   ASSERT_EQ(0, measureCount);
71
72   YGNodeFreeRecursive(root);
73 }
74
75 TEST(YogaTest, measure_absolute_child_with_no_constraints) {
76   const YGNodeRef root = YGNodeNew();
77
78   const YGNodeRef root_child0 = YGNodeNew();
79   YGNodeInsertChild(root, root_child0, 0);
80
81   int measureCount = 0;
82
83   const YGNodeRef root_child0_child0 = YGNodeNew();
84   YGNodeStyleSetPositionType(root_child0_child0, YGPositionTypeAbsolute);
85   root_child0_child0->setContext(&measureCount);
86   root_child0_child0->setMeasureFunc(_measure);
87   YGNodeInsertChild(root_child0, root_child0_child0, 0);
88
89   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
90
91   ASSERT_EQ(1, measureCount);
92
93   YGNodeFreeRecursive(root);
94 }
95
96 TEST(YogaTest, dont_measure_when_min_equals_max) {
97   const YGNodeRef root = YGNodeNew();
98   YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
99   YGNodeStyleSetWidth(root, 100);
100   YGNodeStyleSetHeight(root, 100);
101
102   int measureCount = 0;
103
104   const YGNodeRef root_child0 = YGNodeNew();
105   root_child0->setContext(&measureCount);
106   root_child0->setMeasureFunc(_measure);
107   YGNodeStyleSetMinWidth(root_child0, 10);
108   YGNodeStyleSetMaxWidth(root_child0, 10);
109   YGNodeStyleSetMinHeight(root_child0, 10);
110   YGNodeStyleSetMaxHeight(root_child0, 10);
111   YGNodeInsertChild(root, root_child0, 0);
112
113   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
114
115   ASSERT_EQ(0, measureCount);
116   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
117   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
118   ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
119   ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
120
121   YGNodeFreeRecursive(root);
122 }
123
124 TEST(YogaTest, dont_measure_when_min_equals_max_percentages) {
125   const YGNodeRef root = YGNodeNew();
126   YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
127   YGNodeStyleSetWidth(root, 100);
128   YGNodeStyleSetHeight(root, 100);
129
130   int measureCount = 0;
131
132   const YGNodeRef root_child0 = YGNodeNew();
133   root_child0->setContext(&measureCount);
134   root_child0->setMeasureFunc(_measure);
135   YGNodeStyleSetMinWidthPercent(root_child0, 10);
136   YGNodeStyleSetMaxWidthPercent(root_child0, 10);
137   YGNodeStyleSetMinHeightPercent(root_child0, 10);
138   YGNodeStyleSetMaxHeightPercent(root_child0, 10);
139   YGNodeInsertChild(root, root_child0, 0);
140
141   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
142
143   ASSERT_EQ(0, measureCount);
144   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
145   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
146   ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
147   ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
148
149   YGNodeFreeRecursive(root);
150 }
151
152
153 TEST(YogaTest, measure_nodes_with_margin_auto_and_stretch) {
154   const YGNodeRef root = YGNodeNew();
155   YGNodeStyleSetWidth(root, 500);
156   YGNodeStyleSetHeight(root, 500);
157
158   const YGNodeRef root_child0 = YGNodeNew();
159   root_child0->setMeasureFunc(_measure);
160   YGNodeStyleSetMarginAuto(root_child0, YGEdgeLeft);
161   YGNodeInsertChild(root, root_child0, 0);
162
163   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
164
165   EXPECT_EQ(490, YGNodeLayoutGetLeft(root_child0));
166   EXPECT_EQ(0, YGNodeLayoutGetTop(root_child0));
167   EXPECT_EQ(10, YGNodeLayoutGetWidth(root_child0));
168   EXPECT_EQ(10, YGNodeLayoutGetHeight(root_child0));
169
170   YGNodeFreeRecursive(root);
171 }
172
173 TEST(YogaTest, dont_measure_when_min_equals_max_mixed_width_percent) {
174   const YGNodeRef root = YGNodeNew();
175   YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
176   YGNodeStyleSetWidth(root, 100);
177   YGNodeStyleSetHeight(root, 100);
178
179   int measureCount = 0;
180
181   const YGNodeRef root_child0 = YGNodeNew();
182   root_child0->setContext(&measureCount);
183   root_child0->setMeasureFunc(_measure);
184   YGNodeStyleSetMinWidthPercent(root_child0, 10);
185   YGNodeStyleSetMaxWidthPercent(root_child0, 10);
186   YGNodeStyleSetMinHeight(root_child0, 10);
187   YGNodeStyleSetMaxHeight(root_child0, 10);
188   YGNodeInsertChild(root, root_child0, 0);
189
190   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
191
192   ASSERT_EQ(0, measureCount);
193   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
194   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
195   ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
196   ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
197
198   YGNodeFreeRecursive(root);
199 }
200
201 TEST(YogaTest, dont_measure_when_min_equals_max_mixed_height_percent) {
202   const YGNodeRef root = YGNodeNew();
203   YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
204   YGNodeStyleSetWidth(root, 100);
205   YGNodeStyleSetHeight(root, 100);
206
207   int measureCount = 0;
208
209   const YGNodeRef root_child0 = YGNodeNew();
210   root_child0->setContext(&measureCount);
211   root_child0->setMeasureFunc(_measure);
212   YGNodeStyleSetMinWidth(root_child0, 10);
213   YGNodeStyleSetMaxWidth(root_child0, 10);
214   YGNodeStyleSetMinHeightPercent(root_child0, 10);
215   YGNodeStyleSetMaxHeightPercent(root_child0, 10);
216   YGNodeInsertChild(root, root_child0, 0);
217
218   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
219
220   ASSERT_EQ(0, measureCount);
221   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
222   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
223   ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
224   ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
225
226   YGNodeFreeRecursive(root);
227 }
228
229 TEST(YogaTest, measure_enough_size_should_be_in_single_line) {
230   const YGNodeRef root = YGNodeNew();
231   YGNodeStyleSetWidth(root, 100);
232
233   const YGNodeRef root_child0 = YGNodeNew();
234   YGNodeStyleSetAlignSelf(root_child0, YGAlignFlexStart);
235   root_child0->setMeasureFunc(_simulate_wrapping_text);
236
237   YGNodeInsertChild(root, root_child0, 0);
238
239   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
240
241   ASSERT_FLOAT_EQ(68, YGNodeLayoutGetWidth(root_child0));
242   ASSERT_FLOAT_EQ(16, YGNodeLayoutGetHeight(root_child0));
243
244   YGNodeFreeRecursive(root);
245 }
246
247 TEST(YogaTest, measure_not_enough_size_should_wrap) {
248   const YGNodeRef root = YGNodeNew();
249   YGNodeStyleSetWidth(root, 55);
250
251   const YGNodeRef root_child0 = YGNodeNew();
252   YGNodeStyleSetAlignSelf(root_child0, YGAlignFlexStart);
253   //  YGNodeSetMeasureFunc(root_child0, _simulate_wrapping_text);
254   root_child0->setMeasureFunc(_simulate_wrapping_text);
255   YGNodeInsertChild(root, root_child0, 0);
256
257   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
258
259   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
260   ASSERT_FLOAT_EQ(32, YGNodeLayoutGetHeight(root_child0));
261
262   YGNodeFreeRecursive(root);
263 }
264
265 TEST(YogaTest, measure_zero_space_should_grow) {
266   const YGNodeRef root = YGNodeNew();
267   YGNodeStyleSetHeight(root, 200);
268   YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumn);
269   YGNodeStyleSetFlexGrow(root, 0);
270
271   int measureCount = 0;
272
273   const YGNodeRef root_child0 = YGNodeNew();
274   YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionColumn);
275   YGNodeStyleSetPadding(root_child0, YGEdgeAll, 100);
276   root_child0->setContext(&measureCount);
277   root_child0->setMeasureFunc(_measure);
278
279   YGNodeInsertChild(root, root_child0, 0);
280
281   YGNodeCalculateLayout(root, 282, YGUndefined, YGDirectionLTR);
282
283   ASSERT_FLOAT_EQ(282, YGNodeLayoutGetWidth(root_child0));
284   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
285
286   YGNodeFreeRecursive(root);
287 }
288
289 TEST(YogaTest, measure_flex_direction_row_and_padding) {
290   const YGConfigRef config = YGConfigNew();
291
292   const YGNodeRef root = YGNodeNewWithConfig(config);
293   YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
294   YGNodeStyleSetPadding(root, YGEdgeLeft, 25);
295   YGNodeStyleSetPadding(root, YGEdgeTop, 25);
296   YGNodeStyleSetPadding(root, YGEdgeRight, 25);
297   YGNodeStyleSetPadding(root, YGEdgeBottom, 25);
298   YGNodeStyleSetWidth(root, 50);
299   YGNodeStyleSetHeight(root, 50);
300
301   const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
302   root_child0->setMeasureFunc(_simulate_wrapping_text);
303   //  YGNodeSetMeasureFunc(root_child0, _simulate_wrapping_text);
304   YGNodeInsertChild(root, root_child0, 0);
305
306   const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
307   YGNodeStyleSetWidth(root_child1, 5);
308   YGNodeStyleSetHeight(root_child1, 5);
309   YGNodeInsertChild(root, root_child1, 1);
310   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
311
312   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
313   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
314   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
315   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
316
317   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
318   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child0));
319   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
320   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
321
322   ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child1));
323   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child1));
324   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
325   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
326
327   YGNodeFreeRecursive(root);
328
329   YGConfigFree(config);
330 }
331
332 TEST(YogaTest, measure_flex_direction_column_and_padding) {
333   const YGConfigRef config = YGConfigNew();
334
335   const YGNodeRef root = YGNodeNewWithConfig(config);
336   YGNodeStyleSetMargin(root, YGEdgeTop, 20);
337   YGNodeStyleSetPadding(root, YGEdgeAll, 25);
338   YGNodeStyleSetWidth(root, 50);
339   YGNodeStyleSetHeight(root, 50);
340
341   const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
342   root_child0->setMeasureFunc(_simulate_wrapping_text);
343   //  YGNodeSetMeasureFunc(root_child0, _simulate_wrapping_text);
344   YGNodeInsertChild(root, root_child0, 0);
345
346   const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
347   YGNodeStyleSetWidth(root_child1, 5);
348   YGNodeStyleSetHeight(root_child1, 5);
349   YGNodeInsertChild(root, root_child1, 1);
350   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
351
352   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
353   ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
354   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
355   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
356
357   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
358   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child0));
359   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
360   ASSERT_FLOAT_EQ(32, YGNodeLayoutGetHeight(root_child0));
361
362   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1));
363   ASSERT_FLOAT_EQ(57, YGNodeLayoutGetTop(root_child1));
364   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
365   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
366
367   YGNodeFreeRecursive(root);
368
369   YGConfigFree(config);
370 }
371
372 TEST(YogaTest, measure_flex_direction_row_no_padding) {
373   const YGConfigRef config = YGConfigNew();
374
375   const YGNodeRef root = YGNodeNewWithConfig(config);
376   YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
377   YGNodeStyleSetMargin(root, YGEdgeTop, 20);
378   YGNodeStyleSetWidth(root, 50);
379   YGNodeStyleSetHeight(root, 50);
380
381   const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
382   //  YGNodeSetMeasureFunc(root_child0, _simulate_wrapping_text);
383   root_child0->setMeasureFunc(_simulate_wrapping_text);
384   YGNodeInsertChild(root, root_child0, 0);
385
386   const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
387   YGNodeStyleSetWidth(root_child1, 5);
388   YGNodeStyleSetHeight(root_child1, 5);
389   YGNodeInsertChild(root, root_child1, 1);
390   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
391
392   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
393   ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
394   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
395   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
396
397   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
398   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
399   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
400   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child0));
401
402   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
403   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
404   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
405   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
406
407   YGNodeFreeRecursive(root);
408
409   YGConfigFree(config);
410 }
411
412 TEST(YogaTest, measure_flex_direction_row_no_padding_align_items_flexstart) {
413   const YGConfigRef config = YGConfigNew();
414
415   const YGNodeRef root = YGNodeNewWithConfig(config);
416   YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
417   YGNodeStyleSetMargin(root, YGEdgeTop, 20);
418   YGNodeStyleSetWidth(root, 50);
419   YGNodeStyleSetHeight(root, 50);
420   YGNodeStyleSetAlignItems(root, YGAlignFlexStart);
421
422   const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
423   root_child0->setMeasureFunc(_simulate_wrapping_text);
424   YGNodeInsertChild(root, root_child0, 0);
425
426   const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
427   YGNodeStyleSetWidth(root_child1, 5);
428   YGNodeStyleSetHeight(root_child1, 5);
429   YGNodeInsertChild(root, root_child1, 1);
430   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
431
432   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
433   ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
434   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
435   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
436
437   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
438   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
439   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
440   ASSERT_FLOAT_EQ(32, YGNodeLayoutGetHeight(root_child0));
441
442   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
443   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1));
444   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
445   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
446
447   YGNodeFreeRecursive(root);
448
449   YGConfigFree(config);
450 }
451
452 TEST(YogaTest, measure_with_fixed_size) {
453   const YGConfigRef config = YGConfigNew();
454
455   const YGNodeRef root = YGNodeNewWithConfig(config);
456   YGNodeStyleSetMargin(root, YGEdgeTop, 20);
457   YGNodeStyleSetPadding(root, YGEdgeAll, 25);
458   YGNodeStyleSetWidth(root, 50);
459   YGNodeStyleSetHeight(root, 50);
460
461   const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
462   root_child0->setMeasureFunc(_simulate_wrapping_text);
463   YGNodeStyleSetWidth(root_child0, 10);
464   YGNodeStyleSetHeight(root_child0, 10);
465   YGNodeInsertChild(root, root_child0, 0);
466
467   const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
468   YGNodeStyleSetWidth(root_child1, 5);
469   YGNodeStyleSetHeight(root_child1, 5);
470   YGNodeInsertChild(root, root_child1, 1);
471   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
472
473   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
474   ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
475   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
476   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
477
478   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
479   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child0));
480   ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0));
481   ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0));
482
483   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1));
484   ASSERT_FLOAT_EQ(35, YGNodeLayoutGetTop(root_child1));
485   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
486   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
487
488   YGNodeFreeRecursive(root);
489
490   YGConfigFree(config);
491 }
492
493 TEST(YogaTest, measure_with_flex_shrink) {
494   const YGConfigRef config = YGConfigNew();
495
496   const YGNodeRef root = YGNodeNewWithConfig(config);
497   YGNodeStyleSetMargin(root, YGEdgeTop, 20);
498   YGNodeStyleSetPadding(root, YGEdgeAll, 25);
499   YGNodeStyleSetWidth(root, 50);
500   YGNodeStyleSetHeight(root, 50);
501
502   const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
503   root_child0->setMeasureFunc(_simulate_wrapping_text);
504   YGNodeStyleSetFlexShrink(root_child0, 1);
505   YGNodeInsertChild(root, root_child0, 0);
506
507   const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
508   YGNodeStyleSetWidth(root_child1, 5);
509   YGNodeStyleSetHeight(root_child1, 5);
510   YGNodeInsertChild(root, root_child1, 1);
511   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
512
513   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
514   ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
515   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
516   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
517
518   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0));
519   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child0));
520   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
521   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
522
523   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child1));
524   ASSERT_FLOAT_EQ(25, YGNodeLayoutGetTop(root_child1));
525   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
526   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
527
528   YGNodeFreeRecursive(root);
529
530   YGConfigFree(config);
531 }
532
533 TEST(YogaTest, measure_no_padding) {
534   const YGConfigRef config = YGConfigNew();
535
536   const YGNodeRef root = YGNodeNewWithConfig(config);
537   YGNodeStyleSetMargin(root, YGEdgeTop, 20);
538   YGNodeStyleSetWidth(root, 50);
539   YGNodeStyleSetHeight(root, 50);
540
541   const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
542   root_child0->setMeasureFunc(_simulate_wrapping_text);
543   YGNodeStyleSetFlexShrink(root_child0, 1);
544   YGNodeInsertChild(root, root_child0, 0);
545
546   const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
547   YGNodeStyleSetWidth(root_child1, 5);
548   YGNodeStyleSetHeight(root_child1, 5);
549   YGNodeInsertChild(root, root_child1, 1);
550   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
551
552   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
553   ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root));
554   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root));
555   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root));
556
557   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
558   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0));
559   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0));
560   ASSERT_FLOAT_EQ(32, YGNodeLayoutGetHeight(root_child0));
561
562   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1));
563   ASSERT_FLOAT_EQ(32, YGNodeLayoutGetTop(root_child1));
564   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetWidth(root_child1));
565   ASSERT_FLOAT_EQ(5, YGNodeLayoutGetHeight(root_child1));
566
567   YGNodeFreeRecursive(root);
568
569   YGConfigFree(config);
570 }
571
572 #if GTEST_HAS_DEATH_TEST
573 TEST(YogaDeathTest, cannot_add_child_to_node_with_measure_func) {
574   const YGNodeRef root = YGNodeNew();
575   root->setMeasureFunc(_measure);
576
577   const YGNodeRef root_child0 = YGNodeNew();
578   ASSERT_DEATH(YGNodeInsertChild(root, root_child0, 0), "Cannot add child.*");
579   YGNodeFree(root_child0);
580   YGNodeFreeRecursive(root);
581 }
582
583 TEST(YogaDeathTest, cannot_add_nonnull_measure_func_to_non_leaf_node) {
584   const YGNodeRef root = YGNodeNew();
585   const YGNodeRef root_child0 = YGNodeNew();
586   YGNodeInsertChild(root, root_child0, 0);
587   ASSERT_DEATH(root->setMeasureFunc(_measure), "Cannot set measure function.*");
588   YGNodeFreeRecursive(root);
589 }
590
591 #endif
592
593 TEST(YogaTest, can_nullify_measure_func_on_any_node) {
594   const YGNodeRef root = YGNodeNew();
595   YGNodeInsertChild(root, YGNodeNew(), 0);
596   root->setMeasureFunc(nullptr);
597   ASSERT_TRUE(root->getMeasure() == NULL);
598   YGNodeFreeRecursive(root);
599 }
600
601 TEST(YogaTest, cant_call_negative_measure) {
602   const YGConfigRef config = YGConfigNew();
603
604   const YGNodeRef root = YGNodeNewWithConfig(config);
605   YGNodeStyleSetFlexDirection(root, YGFlexDirectionColumn);
606   YGNodeStyleSetWidth(root, 50);
607   YGNodeStyleSetHeight(root, 10);
608
609   const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
610   root_child0->setMeasureFunc(_measure_assert_negative);
611   YGNodeStyleSetMargin(root_child0, YGEdgeTop, 20);
612   YGNodeInsertChild(root, root_child0, 0);
613
614   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
615
616   YGNodeFreeRecursive(root);
617   YGConfigFree(config);
618 }
619
620 TEST(YogaTest, cant_call_negative_measure_horizontal) {
621   const YGConfigRef config = YGConfigNew();
622
623   const YGNodeRef root = YGNodeNewWithConfig(config);
624   YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
625   YGNodeStyleSetWidth(root, 10);
626   YGNodeStyleSetHeight(root, 20);
627
628   const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
629   root_child0->setMeasureFunc(_measure_assert_negative);
630   YGNodeStyleSetMargin(root_child0, YGEdgeStart, 20);
631   YGNodeInsertChild(root, root_child0, 0);
632
633   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
634
635   YGNodeFreeRecursive(root);
636   YGConfigFree(config);
637 }
638
639 static YGSize _measure_90_10(YGNodeRef node,
640   float width,
641   YGMeasureMode widthMode,
642   float height,
643   YGMeasureMode heightMode) {
644
645   return YGSize{
646     .width = 90, .height = 10,
647   };
648 }
649
650 TEST(YogaTest, percent_with_text_node) {
651   const YGConfigRef config = YGConfigNew();
652
653   const YGNodeRef root = YGNodeNewWithConfig(config);
654   YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow);
655   YGNodeStyleSetJustifyContent(root, YGJustifySpaceBetween);
656   YGNodeStyleSetAlignItems(root, YGAlignCenter);
657   YGNodeStyleSetWidth(root, 100);
658   YGNodeStyleSetHeight(root, 80);
659
660   const YGNodeRef root_child0 = YGNodeNewWithConfig(config);
661   YGNodeInsertChild(root, root_child0, 0);
662
663   const YGNodeRef root_child1 = YGNodeNewWithConfig(config);
664   root_child1->setMeasureFunc(_measure_90_10);
665   YGNodeStyleSetMaxWidthPercent(root_child1, 50);
666   YGNodeStyleSetPaddingPercent(root_child1, YGEdgeTop, 50);
667   YGNodeInsertChild(root, root_child1, 1);
668
669   YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
670
671   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root));
672   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root));
673   ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root));
674   ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root));
675
676   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0));
677   ASSERT_FLOAT_EQ(40, YGNodeLayoutGetTop(root_child0));
678   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetWidth(root_child0));
679   ASSERT_FLOAT_EQ(0, YGNodeLayoutGetHeight(root_child0));
680
681   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1));
682   ASSERT_FLOAT_EQ(15, YGNodeLayoutGetTop(root_child1));
683   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1));
684   ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1));
685
686   YGNodeFreeRecursive(root);
687
688   YGConfigFree(config);
689 }