From c8d67f428dd682185fcb90746ed590309d8bbf0d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 1 Sep 2021 13:50:39 +0200 Subject: [PATCH] WIP --- gpui/src/elements/list.rs | 108 +++++++++++++++++++++++++++++++++++++- gpui/src/test.rs | 4 +- 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/gpui/src/elements/list.rs b/gpui/src/elements/list.rs index 852c60c874..eb1ba7ac0f 100644 --- a/gpui/src/elements/list.rs +++ b/gpui/src/elements/list.rs @@ -567,7 +567,13 @@ impl<'a> sum_tree::SeekDimension<'a, ListItemSummary> for Height { #[cfg(test)] mod tests { use super::*; - use crate::{elements::*, geometry::vector::vec2f, Entity, RenderContext, View}; + use crate::{ + elements::{ConstrainedBox, Empty}, + geometry::vector::vec2f, + Entity, RenderContext, View, + }; + use rand::prelude::*; + use std::env; #[crate::test(self)] fn test_layout(cx: &mut crate::MutableAppContext) { @@ -653,6 +659,106 @@ mod tests { assert_eq!(state.0.borrow().scroll_top(size.y()), 114.); } + #[crate::test(self, iterations = 10000, seed = 2515)] + fn test_random(cx: &mut crate::MutableAppContext, mut rng: StdRng) { + let operations = env::var("OPERATIONS") + .map(|i| i.parse().expect("invalid `OPERATIONS` variable")) + .unwrap_or(10); + + let mut presenter = cx.build_presenter(0, 0.); + let elements = Rc::new(RefCell::new( + (0..rng.gen_range(0..=20)) + .map(|_| rng.gen_range(0_f32..=100_f32)) + .collect::>(), + )); + let orientation = *[Orientation::Top, Orientation::Bottom] + .choose(&mut rng) + .unwrap(); + let min_overdraw = rng.gen_range(0..=20); + let state = ListState::new(elements.borrow().len(), orientation, min_overdraw, { + let elements = elements.clone(); + move |ix, _| item(elements.borrow()[ix]) + }); + + let mut width = rng.gen_range(0_f32..=1000_f32); + let mut height = rng.gen_range(0_f32..=1000_f32); + log::info!("orientation: {:?}", orientation); + log::info!("min_overdraw: {}", min_overdraw); + log::info!("elements: {:?}", elements.borrow()); + log::info!("size: ({:?}, {:?})", width, height); + log::info!("=================="); + + let mut scroll_top = None; + for _ in 0..operations { + match rng.gen_range(0..=100) { + 0..=29 if scroll_top.is_some() => { + let delta = vec2f(0., rng.gen_range(-100_f32..=100_f32)); + log::info!( + "Scrolling by {:?}, previous scroll top: {:?}", + delta, + scroll_top.unwrap() + ); + state.0.borrow_mut().scroll( + scroll_top.as_ref().unwrap(), + height, + delta, + true, + &mut presenter.build_event_context(cx), + ); + } + 30..=34 => { + width = rng.gen_range(0_f32..=1000_f32); + log::info!("changing width: {:?}", width); + } + 35..=54 => { + height = rng.gen_range(0_f32..=1000_f32); + log::info!("changing height: {:?}", height); + } + _ => { + let mut elements = elements.borrow_mut(); + let end_ix = rng.gen_range(0..=elements.len()); + let start_ix = rng.gen_range(0..=end_ix); + let new_elements = (0..rng.gen_range(0..10)) + .map(|_| rng.gen_range(0_f32..=100_f32)) + .collect::>(); + log::info!("splice({:?}, {:?})", start_ix..end_ix, new_elements); + state.splice(start_ix..end_ix, new_elements.len()); + elements.splice(start_ix..end_ix, new_elements); + } + } + + let mut list = List::new(state.clone()); + let (size, new_scroll_top) = list.layout( + SizeConstraint::new(vec2f(0., 0.), vec2f(width, height)), + &mut presenter.build_layout_context(cx), + ); + assert_eq!(size, vec2f(width, height)); + scroll_top = Some(new_scroll_top); + + let state = state.0.borrow(); + let visible_range = state.visible_range(height, &new_scroll_top); + let rendered_range = + visible_range.start.saturating_sub(min_overdraw)..visible_range.end + min_overdraw; + log::info!("visible range {:?}", visible_range); + log::info!("items {:?}", state.items.items(&())); + for (ix, item) in state.items.cursor::().enumerate() { + if rendered_range.contains(&ix) { + assert!( + matches!(item, ListItem::Rendered(_)), + "item {:?} was not rendered", + ix + ); + } else { + assert!( + !matches!(item, ListItem::Rendered(_)), + "item {:?} was incorrectly rendered", + ix + ); + } + } + } + } + fn item(height: f32) -> ElementBox { ConstrainedBox::new(Empty::new().boxed()) .with_height(height) diff --git a/gpui/src/test.rs b/gpui/src/test.rs index 7210529807..4fabec46d7 100644 --- a/gpui/src/test.rs +++ b/gpui/src/test.rs @@ -2,5 +2,7 @@ use ctor::ctor; #[ctor] fn init_logger() { - env_logger::init(); + env_logger::builder() + .filter_level(log::LevelFilter::Info) + .init(); }