1#[cfg(test)]
2mod measure {
3 use stretch::number::OrElse;
4
5 #[test]
6 fn measure_root() {
7 let layout = stretch::compute(
8 &stretch::style::Node {
9 measure: Some(Box::new(|constraint| {
10 Ok(stretch::geometry::Size {
11 width: constraint.width.or_else(100.0),
12 height: constraint.height.or_else(100.0),
13 })
14 })),
15 ..Default::default()
16 },
17 stretch::geometry::Size::undefined(),
18 )
19 .unwrap();
20
21 assert_eq!(layout.size.width, 100.0);
22 assert_eq!(layout.size.height, 100.0);
23 }
24
25 #[test]
26 fn measure_child() {
27 let layout = stretch::compute(
28 &stretch::style::Node {
29 children: vec![stretch::style::Node {
30 measure: Some(Box::new(|constraint| {
31 Ok(stretch::geometry::Size {
32 width: constraint.width.or_else(100.0),
33 height: constraint.height.or_else(100.0),
34 })
35 })),
36 ..Default::default()
37 }],
38 ..Default::default()
39 },
40 stretch::geometry::Size::undefined(),
41 )
42 .unwrap();
43
44 assert_eq!(layout.size.width, 100.0);
45 assert_eq!(layout.size.height, 100.0);
46
47 assert_eq!(layout.children[0].size.width, 100.0);
48 assert_eq!(layout.children[0].size.height, 100.0);
49 }
50
51 #[test]
52 fn measure_child_constraint() {
53 let layout = stretch::compute(
54 &stretch::style::Node {
55 size: stretch::geometry::Size { width: stretch::style::Dimension::Points(50.0), ..Default::default() },
56 children: vec![stretch::style::Node {
57 measure: Some(Box::new(|constraint| {
58 Ok(stretch::geometry::Size {
59 width: constraint.width.or_else(100.0),
60 height: constraint.height.or_else(100.0),
61 })
62 })),
63 ..Default::default()
64 }],
65 ..Default::default()
66 },
67 stretch::geometry::Size::undefined(),
68 )
69 .unwrap();
70
71 assert_eq!(layout.size.width, 50.0);
72 assert_eq!(layout.size.height, 100.0);
73
74 assert_eq!(layout.children[0].size.width, 50.0);
75 assert_eq!(layout.children[0].size.height, 100.0);
76 }
77
78 #[test]
79 fn measure_child_constraint_padding_parent() {
80 let layout = stretch::compute(
81 &stretch::style::Node {
82 size: stretch::geometry::Size { width: stretch::style::Dimension::Points(50.0), ..Default::default() },
83 padding: stretch::geometry::Rect {
84 start: stretch::style::Dimension::Points(10.0),
85 end: stretch::style::Dimension::Points(10.0),
86 top: stretch::style::Dimension::Points(10.0),
87 bottom: stretch::style::Dimension::Points(10.0),
88 },
89 children: vec![stretch::style::Node {
90 measure: Some(Box::new(|constraint| {
91 Ok(stretch::geometry::Size {
92 width: constraint.width.or_else(100.0),
93 height: constraint.height.or_else(100.0),
94 })
95 })),
96 ..Default::default()
97 }],
98 ..Default::default()
99 },
100 stretch::geometry::Size::undefined(),
101 )
102 .unwrap();
103
104 assert_eq!(layout.size.width, 50.0);
105 assert_eq!(layout.size.height, 120.0);
106
107 assert_eq!(layout.children[0].size.width, 30.0);
108 assert_eq!(layout.children[0].size.height, 100.0);
109 }
110
111 #[test]
112 fn measure_child_with_flex_grow() {
113 let layout = stretch::compute(
114 &stretch::style::Node {
115 size: stretch::geometry::Size { width: stretch::style::Dimension::Points(100.0), ..Default::default() },
116 children: vec![
117 stretch::style::Node {
118 size: stretch::geometry::Size {
119 width: stretch::style::Dimension::Points(50.0),
120 height: stretch::style::Dimension::Points(50.0),
121 },
122 ..Default::default()
123 },
124 stretch::style::Node {
125 measure: Some(Box::new(|constraint| {
126 Ok(stretch::geometry::Size {
127 width: constraint.width.or_else(10.0),
128 height: constraint.height.or_else(50.0),
129 })
130 })),
131 flex_grow: 1.0,
132 ..Default::default()
133 },
134 ],
135 ..Default::default()
136 },
137 stretch::geometry::Size::undefined(),
138 )
139 .unwrap();
140
141 assert_eq!(layout.children[1].size.width, 50.0);
142 assert_eq!(layout.children[1].size.height, 50.0);
143 }
144
145 #[test]
146 fn measure_child_with_flex_shrink() {
147 let layout = stretch::compute(
148 &stretch::style::Node {
149 size: stretch::geometry::Size { width: stretch::style::Dimension::Points(100.0), ..Default::default() },
150 children: vec![
151 stretch::style::Node {
152 size: stretch::geometry::Size {
153 width: stretch::style::Dimension::Points(50.0),
154 height: stretch::style::Dimension::Points(50.0),
155 },
156 flex_shrink: 0.0,
157 ..Default::default()
158 },
159 stretch::style::Node {
160 measure: Some(Box::new(|constraint| {
161 Ok(stretch::geometry::Size {
162 width: constraint.width.or_else(100.0),
163 height: constraint.height.or_else(50.0),
164 })
165 })),
166 ..Default::default()
167 },
168 ],
169 ..Default::default()
170 },
171 stretch::geometry::Size::undefined(),
172 )
173 .unwrap();
174
175 assert_eq!(layout.children[1].size.width, 50.0);
176 assert_eq!(layout.children[1].size.height, 50.0);
177 }
178
179 #[test]
180 fn remeasure_child_after_growing() {
181 let layout = stretch::compute(
182 &stretch::style::Node {
183 size: stretch::geometry::Size { width: stretch::style::Dimension::Points(100.0), ..Default::default() },
184 align_items: stretch::style::AlignItems::FlexStart,
185 children: vec![
186 stretch::style::Node {
187 size: stretch::geometry::Size {
188 width: stretch::style::Dimension::Points(50.0),
189 height: stretch::style::Dimension::Points(50.0),
190 },
191 ..Default::default()
192 },
193 stretch::style::Node {
194 measure: Some(Box::new(|constraint| {
195 let width = constraint.width.or_else(10.0);
196 let height = constraint.height.or_else(width * 2.0);
197 Ok(stretch::geometry::Size { width, height })
198 })),
199 flex_grow: 1.0,
200 ..Default::default()
201 },
202 ],
203 ..Default::default()
204 },
205 stretch::geometry::Size::undefined(),
206 )
207 .unwrap();
208
209 assert_eq!(layout.children[1].size.width, 50.0);
210 assert_eq!(layout.children[1].size.height, 100.0);
211 }
212
213 #[test]
214 fn remeasure_child_after_shrinking() {
215 let layout = stretch::compute(
216 &stretch::style::Node {
217 size: stretch::geometry::Size { width: stretch::style::Dimension::Points(100.0), ..Default::default() },
218 align_items: stretch::style::AlignItems::FlexStart,
219 children: vec![
220 stretch::style::Node {
221 size: stretch::geometry::Size {
222 width: stretch::style::Dimension::Points(50.0),
223 height: stretch::style::Dimension::Points(50.0),
224 },
225 flex_shrink: 0.0,
226 ..Default::default()
227 },
228 stretch::style::Node {
229 measure: Some(Box::new(|constraint| {
230 let width = constraint.width.or_else(100.0);
231 let height = constraint.height.or_else(width * 2.0);
232 Ok(stretch::geometry::Size { width, height })
233 })),
234 ..Default::default()
235 },
236 ],
237 ..Default::default()
238 },
239 stretch::geometry::Size::undefined(),
240 )
241 .unwrap();
242
243 assert_eq!(layout.children[1].size.width, 50.0);
244 assert_eq!(layout.children[1].size.height, 100.0);
245 }
246
247 #[test]
248 fn remeasure_child_after_stretching() {
249 let layout = stretch::compute(
250 &stretch::style::Node {
251 size: stretch::geometry::Size {
252 width: stretch::style::Dimension::Points(100.0),
253 height: stretch::style::Dimension::Points(100.0),
254 },
255 children: vec![stretch::style::Node {
256 measure: Some(Box::new(|constraint| {
257 let height = constraint.height.or_else(50.0);
258 let width = constraint.width.or_else(height);
259 Ok(stretch::geometry::Size { width, height })
260 })),
261 ..Default::default()
262 }],
263 ..Default::default()
264 },
265 stretch::geometry::Size::undefined(),
266 )
267 .unwrap();
268
269 assert_eq!(layout.children[0].size.width, 100.0);
270 assert_eq!(layout.children[0].size.height, 100.0);
271 }
272
273 #[test]
274 fn width_overrides_measure() {
275 let layout = stretch::compute(
276 &stretch::style::Node {
277 children: vec![stretch::style::Node {
278 size: stretch::geometry::Size {
279 width: stretch::style::Dimension::Points(50.0),
280 ..Default::default()
281 },
282 measure: Some(Box::new(|constraint| {
283 Ok(stretch::geometry::Size {
284 width: constraint.width.or_else(100.0),
285 height: constraint.height.or_else(100.0),
286 })
287 })),
288 ..Default::default()
289 }],
290 ..Default::default()
291 },
292 stretch::geometry::Size::undefined(),
293 )
294 .unwrap();
295
296 assert_eq!(layout.children[0].size.width, 50.0);
297 assert_eq!(layout.children[0].size.height, 100.0);
298 }
299
300 #[test]
301 fn height_overrides_measure() {
302 let layout = stretch::compute(
303 &stretch::style::Node {
304 children: vec![stretch::style::Node {
305 size: stretch::geometry::Size {
306 height: stretch::style::Dimension::Points(50.0),
307 ..Default::default()
308 },
309 measure: Some(Box::new(|constraint| {
310 Ok(stretch::geometry::Size {
311 width: constraint.width.or_else(100.0),
312 height: constraint.height.or_else(100.0),
313 })
314 })),
315 ..Default::default()
316 }],
317 ..Default::default()
318 },
319 stretch::geometry::Size::undefined(),
320 )
321 .unwrap();
322
323 assert_eq!(layout.children[0].size.width, 100.0);
324 assert_eq!(layout.children[0].size.height, 50.0);
325 }
326
327 #[test]
328 fn flex_basis_overrides_measure() {
329 let layout = stretch::compute(
330 &stretch::style::Node {
331 size: stretch::geometry::Size {
332 width: stretch::style::Dimension::Points(200.0),
333 height: stretch::style::Dimension::Points(100.0),
334 },
335 children: vec![
336 stretch::style::Node {
337 flex_basis: stretch::style::Dimension::Points(50.0),
338 flex_grow: 1.0,
339 ..Default::default()
340 },
341 stretch::style::Node {
342 flex_basis: stretch::style::Dimension::Points(50.0),
343 flex_grow: 1.0,
344 measure: Some(Box::new(|constraint| {
345 Ok(stretch::geometry::Size {
346 width: constraint.width.or_else(100.0),
347 height: constraint.height.or_else(100.0),
348 })
349 })),
350 ..Default::default()
351 },
352 ],
353 ..Default::default()
354 },
355 stretch::geometry::Size::undefined(),
356 )
357 .unwrap();
358
359 assert_eq!(layout.children[0].size.width, 100.0);
360 assert_eq!(layout.children[0].size.height, 100.0);
361 assert_eq!(layout.children[1].size.width, 100.0);
362 assert_eq!(layout.children[1].size.height, 100.0);
363 }
364
365 #[test]
366 fn stretch_overrides_measure() {
367 let layout = stretch::compute(
368 &stretch::style::Node {
369 size: stretch::geometry::Size {
370 width: stretch::style::Dimension::Points(100.0),
371 height: stretch::style::Dimension::Points(100.0),
372 },
373 children: vec![stretch::style::Node {
374 measure: Some(Box::new(|constraint| {
375 Ok(stretch::geometry::Size {
376 width: constraint.width.or_else(50.0),
377 height: constraint.height.or_else(50.0),
378 })
379 })),
380 ..Default::default()
381 }],
382 ..Default::default()
383 },
384 stretch::geometry::Size::undefined(),
385 )
386 .unwrap();
387
388 assert_eq!(layout.children[0].size.width, 50.0);
389 assert_eq!(layout.children[0].size.height, 100.0);
390 }
391
392 #[test]
393 fn measure_absolute_child() {
394 let layout = stretch::compute(
395 &stretch::style::Node {
396 size: stretch::geometry::Size {
397 width: stretch::style::Dimension::Points(100.0),
398 height: stretch::style::Dimension::Points(100.0),
399 },
400 children: vec![stretch::style::Node {
401 position_type: stretch::style::PositionType::Absolute,
402 measure: Some(Box::new(|constraint| {
403 Ok(stretch::geometry::Size {
404 width: constraint.width.or_else(50.0),
405 height: constraint.height.or_else(50.0),
406 })
407 })),
408 ..Default::default()
409 }],
410 ..Default::default()
411 },
412 stretch::geometry::Size::undefined(),
413 )
414 .unwrap();
415
416 assert_eq!(layout.children[0].size.width, 50.0);
417 assert_eq!(layout.children[0].size.height, 50.0);
418 }
419
420 #[test]
421 fn ignore_invalid_measure() {
422 let layout = stretch::compute(
423 &stretch::style::Node {
424 size: stretch::geometry::Size {
425 width: stretch::style::Dimension::Points(100.0),
426 height: stretch::style::Dimension::Points(100.0),
427 },
428 children: vec![stretch::style::Node {
429 flex_grow: 1.0,
430 measure: Some(Box::new(|_| Ok(stretch::geometry::Size { width: 200.0, height: 200.0 }))),
431 ..Default::default()
432 }],
433 ..Default::default()
434 },
435 stretch::geometry::Size::undefined(),
436 )
437 .unwrap();
438
439 assert_eq!(layout.children[0].size.width, 100.0);
440 assert_eq!(layout.children[0].size.height, 100.0);
441 }
442
443 #[test]
444 fn only_measure_once() {
445 let mut num_measure = 0;
446 let num_measure_ptr = &mut num_measure as *mut i32;
447
448 stretch::compute(
449 &stretch::style::Node {
450 children: vec![stretch::style::Node {
451 children: vec![stretch::style::Node {
452 measure: Some(Box::new(move |constraint| {
453 unsafe { (*num_measure_ptr) += 1 };
454 Ok(stretch::geometry::Size {
455 width: constraint.width.or_else(50.0),
456 height: constraint.height.or_else(50.0),
457 })
458 })),
459 ..Default::default()
460 }],
461 ..Default::default()
462 }],
463 ..Default::default()
464 },
465 stretch::geometry::Size::undefined(),
466 )
467 .unwrap();
468
469 assert_eq!(num_measure, 1);
470 }
471
472 #[test]
473 fn propagate_measure_error() {
474 let layout = stretch::compute(
475 &stretch::style::Node {
476 size: stretch::geometry::Size {
477 width: stretch::style::Dimension::Points(100.0),
478 height: stretch::style::Dimension::Points(100.0),
479 },
480 children: vec![stretch::style::Node {
481 flex_grow: 1.0,
482 measure: Some(Box::new(|_| Err(Box::new("")))),
483 ..Default::default()
484 }],
485 ..Default::default()
486 },
487 stretch::geometry::Size::undefined(),
488 );
489
490 assert_eq!(layout.is_err(), true);
491 }
492}