This commit is contained in:
		
							parent
							
								
									2ffecd9aae
								
							
						
					
					
						commit
						26727a63e0
					
				
					 3 changed files with 195 additions and 201 deletions
				
			
		|  | @ -20,4 +20,4 @@ target_link_libraries(surface PUBLIC | |||
| ) | ||||
| 
 | ||||
| add_test_module(surface system.test.cpp) | ||||
| # add_fuzz_module(surface system.fuzz.cpp) | ||||
| add_fuzz_module(surface system.fuzz.cpp) | ||||
|  |  | |||
|  | @ -85,203 +85,197 @@ private: | |||
| 
 | ||||
| 
 | ||||
| Suite raii = "raii"_suite = [] { | ||||
| 	// should trigger memory sanitizer error
 | ||||
| 	//
 | ||||
| 	int x;         // uninitialized
 | ||||
| 	int y = x + 1; // use of uninitialized value
 | ||||
| 	printf("y = %d\n", y); | ||||
| 	Case { "happy path won't throw" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		ignore = System { fixture.registry() }; | ||||
| 	}; | ||||
| 
 | ||||
| 	Case { "many won't freeze/throw" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		for (auto idx : std::views::iota(0, 250)) | ||||
| 		{ | ||||
| 			ignore = System { fixture.registry() }; | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| 	Case { "unhappy path throws" } = [] { | ||||
| 		expect_throw([] { ignore = System { {} }; }); | ||||
| 	}; | ||||
| 
 | ||||
| 	Case { "post construct has correct state" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		auto system = System { fixture.registry() }; | ||||
| 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0); | ||||
| 	}; | ||||
| 
 | ||||
| 	Case { "post destruct has correct state" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		auto system = memory::create_scope<System>(fixture.registry()); | ||||
| 
 | ||||
| 		fixture.create_component(); | ||||
| 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 1); | ||||
| 
 | ||||
| 		system.reset(); | ||||
| 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0); | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
| Suite system_events = "system_events"_suite = [] { | ||||
| 	Case { "on_register won't throw" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		auto system = System { fixture.registry() }; | ||||
| 
 | ||||
| 		system.on_register(); | ||||
| 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0); | ||||
| 	}; | ||||
| 
 | ||||
| 	Case { "on_unregister won't throw" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		auto system = System { fixture.registry() }; | ||||
| 
 | ||||
| 		system.on_register(); | ||||
| 		system.on_unregister(); | ||||
| 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0); | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
| Suite registry_events = "registry_events"_suite = [] { | ||||
| 	Case { "on_construct<SurfaceComponent> initializes component" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 
 | ||||
| 		const auto &component = fixture.create_component(); | ||||
| 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 1); | ||||
| 		fixture.check_values(*component); | ||||
| 	}; | ||||
| 
 | ||||
| 	Case { "unhappy on_construct<SurfaceComponent> throws" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		auto system = System { fixture.registry() }; | ||||
| 
 | ||||
| 		expect_throw([&] { fixture.create_component({ .resolution = { width, 0 } }); }); | ||||
| 
 | ||||
| 		expect_throw([&] { fixture.create_component({ .resolution = { 0, height } }); }); | ||||
| 
 | ||||
| 		expect_throw([&] { | ||||
| 			fixture.create_component( | ||||
| 			    { .title = "", .resolution = { SurfaceComponent::max_dimension + 1, height } } | ||||
| 			); | ||||
| 		}); | ||||
| 
 | ||||
| 		expect_throw([&] { | ||||
| 			fixture.create_component( | ||||
| 			    { .title = "", .resolution = { width, SurfaceComponent::max_dimension + 1 } } | ||||
| 			); | ||||
| 		}); | ||||
| 
 | ||||
| 		auto big_str = std::string {}; | ||||
| 		big_str.resize(SurfaceComponent::max_title_length + 1); | ||||
| 		expect_throw([&] { | ||||
| 			fixture.create_component({ .title = big_str, .resolution = { width, height } }); | ||||
| 		}); | ||||
| 	}; | ||||
| 
 | ||||
| 	Case { "unhappy on_construct<SurfaceComponent> removes component" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		auto system = System { fixture.registry() }; | ||||
| 
 | ||||
| 		expect_throw([&] { fixture.create_component({ .resolution = { width, 0 } }); }); | ||||
| 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0); | ||||
| 	}; | ||||
| 
 | ||||
| 	Case { "on_destrroy<SurfaceComponent> cleans up component" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		auto system = memory::create_scope<System>(fixture.registry()); | ||||
| 
 | ||||
| 		const auto &component = fixture.create_component(); | ||||
| 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 1); | ||||
| 		fixture.check_values(*component); | ||||
| 
 | ||||
| 		system.reset(); | ||||
| 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0); | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
| Suite tick = "tick"_suite = [] { | ||||
| 	Case { "ticking on empty registry won't throw" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		System { fixture.registry() }.tick(tick_info()); | ||||
| 	}; | ||||
| 
 | ||||
| 	Case { "ticking on non-empty registry won't throw" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		auto system = System { fixture.registry() }; | ||||
| 
 | ||||
| 		fixture.create_component(); | ||||
| 		system.tick(tick_info()); | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
| Suite tick_handles_events = "tick_handles_events"_suite = [] { | ||||
| 	Case { "ticking clears previous tick's events" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		auto system = System { fixture.registry() }; | ||||
| 		auto &surface = **fixture.create_component(); | ||||
| 
 | ||||
| 		// flush window-creation events
 | ||||
| 		system.tick(tick_info()); | ||||
| 		expect_eq(surface.peek_events().size(), 0); | ||||
| 
 | ||||
| 		surface.push_event(surface::MovedEvent({}, {})); | ||||
| 		expect_eq(surface.peek_events().size(), 1); | ||||
| 
 | ||||
| 		surface.push_event(surface::ButtonPressedEvent({})); | ||||
| 		expect_eq(surface.peek_events().size(), 2); | ||||
| 
 | ||||
| 		system.tick(tick_info()); | ||||
| 		expect_eq(surface.peek_events().size(), 0); | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
| Suite tick_handles_requests = "tick_handles_requests"_suite = [] { | ||||
| 	Case { "ticking clears requests" } = [] { | ||||
| 		auto fixture = Fixture {}; | ||||
| 		auto system = System { fixture.registry() }; | ||||
| 		auto &surface = **fixture.create_component(); | ||||
| 
 | ||||
| 		constexpr auto title = "ABC"; | ||||
| 		constexpr auto position = math::ivec2 { 50, 50 }; | ||||
| 		constexpr auto resolution = math::uvec2 { 50, 50 }; | ||||
| 
 | ||||
| 		expect_eq(surface.peek_requests().size(), 0); | ||||
| 
 | ||||
| 		surface.push_request(surface::ModifyVisibilityRequest(true)); | ||||
| 		expect_eq(surface.peek_requests().size(), 1); | ||||
| 		system.tick(tick_info()); | ||||
| 		expect_eq(surface.peek_requests().size(), 0); | ||||
| 
 | ||||
| 		surface.push_request(surface::ModifyTitleRequest(title)); | ||||
| 		expect_eq(surface.peek_requests().size(), 1); | ||||
| 
 | ||||
| 		surface.push_request(surface::ModifyResolutionRequest(resolution)); | ||||
| 		surface.push_request(surface::ModifyPositionRequest(position)); | ||||
| 		expect_eq(surface.peek_requests().size(), 1 + 2); | ||||
| 
 | ||||
| 		surface.push_request(surface::ModifyVisibilityRequest(false)); | ||||
| 		surface.push_request(surface::ModifyVisibilityRequest(true)); | ||||
| 		surface.push_request(surface::ModifyVisibilityRequest(false)); | ||||
| 		expect_eq(surface.peek_requests().size(), 1 + 2 + 3); | ||||
| 
 | ||||
| 		system.tick(tick_info()); | ||||
| 		expect_eq(surface.peek_requests().size(), 0); | ||||
| 
 | ||||
| 		expect_eq(surface.get_title(), title); | ||||
| 		expect_eq(surface.get_position(), position); | ||||
| 		expect_eq(surface.get_resolution(), resolution); | ||||
| 
 | ||||
| 		log_dbg("EVENT COUNT: {}", surface.peek_events().size()); | ||||
| 		for (const auto &event : surface.peek_events()) | ||||
| 		{ | ||||
| 			const auto visitor = overloads { | ||||
| 				[&](auto event) { log_dbg("event: {}", event.to_string()); }, | ||||
| 			}; | ||||
| 
 | ||||
| 			std::visit(visitor, event); | ||||
| 		} | ||||
| 	}; | ||||
| }; | ||||
| // 	Case { "happy path won't throw" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		ignore = System { fixture.registry() };
 | ||||
| // 	};
 | ||||
| //
 | ||||
| // 	Case { "many won't freeze/throw" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		for (auto idx : std::views::iota(0, 250))
 | ||||
| // 		{
 | ||||
| // 			ignore = System { fixture.registry() };
 | ||||
| // 		}
 | ||||
| // 	};
 | ||||
| //
 | ||||
| // 	Case { "unhappy path throws" } = [] {
 | ||||
| // 		expect_throw([] { ignore = System { {} }; });
 | ||||
| // 	};
 | ||||
| //
 | ||||
| // 	Case { "post construct has correct state" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		auto system = System { fixture.registry() };
 | ||||
| // 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
 | ||||
| // 	};
 | ||||
| //
 | ||||
| // 	Case { "post destruct has correct state" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		auto system = memory::create_scope<System>(fixture.registry());
 | ||||
| //
 | ||||
| // 		fixture.create_component();
 | ||||
| // 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 1);
 | ||||
| //
 | ||||
| // 		system.reset();
 | ||||
| // 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
 | ||||
| // 	};
 | ||||
| // };
 | ||||
| //
 | ||||
| // Suite system_events = "system_events"_suite = [] {
 | ||||
| // 	Case { "on_register won't throw" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		auto system = System { fixture.registry() };
 | ||||
| //
 | ||||
| // 		system.on_register();
 | ||||
| // 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
 | ||||
| // 	};
 | ||||
| //
 | ||||
| // 	Case { "on_unregister won't throw" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		auto system = System { fixture.registry() };
 | ||||
| //
 | ||||
| // 		system.on_register();
 | ||||
| // 		system.on_unregister();
 | ||||
| // 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
 | ||||
| // 	};
 | ||||
| // };
 | ||||
| //
 | ||||
| // Suite registry_events = "registry_events"_suite = [] {
 | ||||
| // 	Case { "on_construct<SurfaceComponent> initializes component" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| //
 | ||||
| // 		const auto &component = fixture.create_component();
 | ||||
| // 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 1);
 | ||||
| // 		fixture.check_values(*component);
 | ||||
| // 	};
 | ||||
| //
 | ||||
| // 	Case { "unhappy on_construct<SurfaceComponent> throws" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		auto system = System { fixture.registry() };
 | ||||
| //
 | ||||
| // 		expect_throw([&] { fixture.create_component({ .resolution = { width, 0 } }); });
 | ||||
| //
 | ||||
| // 		expect_throw([&] { fixture.create_component({ .resolution = { 0, height } }); });
 | ||||
| //
 | ||||
| // 		expect_throw([&] {
 | ||||
| // 			fixture.create_component(
 | ||||
| // 			    { .title = "", .resolution = { SurfaceComponent::max_dimension + 1, height } }
 | ||||
| // 			);
 | ||||
| // 		});
 | ||||
| //
 | ||||
| // 		expect_throw([&] {
 | ||||
| // 			fixture.create_component(
 | ||||
| // 			    { .title = "", .resolution = { width, SurfaceComponent::max_dimension + 1 } }
 | ||||
| // 			);
 | ||||
| // 		});
 | ||||
| //
 | ||||
| // 		auto big_str = std::string {};
 | ||||
| // 		big_str.resize(SurfaceComponent::max_title_length + 1);
 | ||||
| // 		expect_throw([&] {
 | ||||
| // 			fixture.create_component({ .title = big_str, .resolution = { width, height } });
 | ||||
| // 		});
 | ||||
| // 	};
 | ||||
| //
 | ||||
| // 	Case { "unhappy on_construct<SurfaceComponent> removes component" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		auto system = System { fixture.registry() };
 | ||||
| //
 | ||||
| // 		expect_throw([&] { fixture.create_component({ .resolution = { width, 0 } }); });
 | ||||
| // 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
 | ||||
| // 	};
 | ||||
| //
 | ||||
| // 	Case { "on_destrroy<SurfaceComponent> cleans up component" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		auto system = memory::create_scope<System>(fixture.registry());
 | ||||
| //
 | ||||
| // 		const auto &component = fixture.create_component();
 | ||||
| // 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 1);
 | ||||
| // 		fixture.check_values(*component);
 | ||||
| //
 | ||||
| // 		system.reset();
 | ||||
| // 		expect_eq(fixture.registry()->view<SurfaceComponent>().get_size(), 0);
 | ||||
| // 	};
 | ||||
| // };
 | ||||
| //
 | ||||
| // Suite tick = "tick"_suite = [] {
 | ||||
| // 	Case { "ticking on empty registry won't throw" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		System { fixture.registry() }.tick(tick_info());
 | ||||
| // 	};
 | ||||
| //
 | ||||
| // 	Case { "ticking on non-empty registry won't throw" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		auto system = System { fixture.registry() };
 | ||||
| //
 | ||||
| // 		fixture.create_component();
 | ||||
| // 		system.tick(tick_info());
 | ||||
| // 	};
 | ||||
| // };
 | ||||
| //
 | ||||
| // Suite tick_handles_events = "tick_handles_events"_suite = [] {
 | ||||
| // 	Case { "ticking clears previous tick's events" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		auto system = System { fixture.registry() };
 | ||||
| // 		auto &surface = **fixture.create_component();
 | ||||
| //
 | ||||
| // 		// flush window-creation events
 | ||||
| // 		system.tick(tick_info());
 | ||||
| // 		expect_eq(surface.peek_events().size(), 0);
 | ||||
| //
 | ||||
| // 		surface.push_event(surface::MovedEvent({}, {}));
 | ||||
| // 		expect_eq(surface.peek_events().size(), 1);
 | ||||
| //
 | ||||
| // 		surface.push_event(surface::ButtonPressedEvent({}));
 | ||||
| // 		expect_eq(surface.peek_events().size(), 2);
 | ||||
| //
 | ||||
| // 		system.tick(tick_info());
 | ||||
| // 		expect_eq(surface.peek_events().size(), 0);
 | ||||
| // 	};
 | ||||
| // };
 | ||||
| //
 | ||||
| // Suite tick_handles_requests = "tick_handles_requests"_suite = [] {
 | ||||
| // 	Case { "ticking clears requests" } = [] {
 | ||||
| // 		auto fixture = Fixture {};
 | ||||
| // 		auto system = System { fixture.registry() };
 | ||||
| // 		auto &surface = **fixture.create_component();
 | ||||
| //
 | ||||
| // 		constexpr auto title = "ABC";
 | ||||
| // 		constexpr auto position = math::ivec2 { 50, 50 };
 | ||||
| // 		constexpr auto resolution = math::uvec2 { 50, 50 };
 | ||||
| //
 | ||||
| // 		expect_eq(surface.peek_requests().size(), 0);
 | ||||
| //
 | ||||
| // 		surface.push_request(surface::ModifyVisibilityRequest(true));
 | ||||
| // 		expect_eq(surface.peek_requests().size(), 1);
 | ||||
| // 		system.tick(tick_info());
 | ||||
| // 		expect_eq(surface.peek_requests().size(), 0);
 | ||||
| //
 | ||||
| // 		surface.push_request(surface::ModifyTitleRequest(title));
 | ||||
| // 		expect_eq(surface.peek_requests().size(), 1);
 | ||||
| //
 | ||||
| // 		surface.push_request(surface::ModifyResolutionRequest(resolution));
 | ||||
| // 		surface.push_request(surface::ModifyPositionRequest(position));
 | ||||
| // 		expect_eq(surface.peek_requests().size(), 1 + 2);
 | ||||
| //
 | ||||
| // 		surface.push_request(surface::ModifyVisibilityRequest(false));
 | ||||
| // 		surface.push_request(surface::ModifyVisibilityRequest(true));
 | ||||
| // 		surface.push_request(surface::ModifyVisibilityRequest(false));
 | ||||
| // 		expect_eq(surface.peek_requests().size(), 1 + 2 + 3);
 | ||||
| //
 | ||||
| // 		system.tick(tick_info());
 | ||||
| // 		expect_eq(surface.peek_requests().size(), 0);
 | ||||
| //
 | ||||
| // 		expect_eq(surface.get_title(), title);
 | ||||
| // 		expect_eq(surface.get_position(), position);
 | ||||
| // 		expect_eq(surface.get_resolution(), resolution);
 | ||||
| //
 | ||||
| // 		log_dbg("EVENT COUNT: {}", surface.peek_events().size());
 | ||||
| // 		for (const auto &event : surface.peek_events())
 | ||||
| // 		{
 | ||||
| // 			const auto visitor = overloads {
 | ||||
| // 				[&](auto event) { log_dbg("event: {}", event.to_string()); },
 | ||||
| // 			};
 | ||||
| //
 | ||||
| // 			std::visit(visitor, event);
 | ||||
| // 		}
 | ||||
| // 	};
 | ||||
| // };
 | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ cmake . \ | |||
| -L/libcxx_msan/lib -Wl,-rpath,/libcxx_msan/lib \ | ||||
| -lc++ \ | ||||
| -lc++abi" \ | ||||
| && cmake --build ./build --target='surface_tests' -j`nproc` | ||||
| && cmake --build ./build -j`nproc` | ||||
| 
 | ||||
| export MSAN_SYMBOLIZER_PATH="$(which llvm-symbolizer)" | ||||
| export MSAN_OPTIONS="fast_unwind_on_malloc=0:verbosity=1:report_umrs=1" | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue