From 482daf9be575349f1d691e5d98ec63e70bf31b24 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Sun, 28 Aug 2022 18:12:02 -0700 Subject: [PATCH] Unit tests range suck (#69352) * Unit tests range suck Ok so we currently rely on some undefined behavior in energy_ball code Namely, the range() family will return turfs in least/greatest get_dist This is VERY useful for optimizing the tesla, but it's also undefined, and lummy could change it any day now. So let's at least unit test it so if it breaks we can remove it --- code/modules/power/tesla/energy_ball.dm | 2 ++ code/modules/unit_tests/_unit_tests.dm | 1 + code/modules/unit_tests/range_return.dm | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 code/modules/unit_tests/range_return.dm diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index c479fcfd635..c11bfcb59a3 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -247,6 +247,8 @@ var/atom/A = a if(!(zap_flags & ZAP_ALLOW_DUPLICATES) && LAZYACCESS(shocked_targets, A)) continue + // NOTE: these type checks are safe because CURRENTLY the range family of procs returns turfs in least to greatest distance order + // This is unspecified behavior tho, so if it ever starts acting up just remove these optimizations and include a distance check if(closest_type >= BIKE) break diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index e51000d3fdf..02e78c17f44 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -129,6 +129,7 @@ #include "preferences.dm" #include "projectiles.dm" #include "quirks.dm" +#include "range_return.dm" #include "rcd.dm" #include "reagent_id_typos.dm" #include "reagent_mod_expose.dm" diff --git a/code/modules/unit_tests/range_return.dm b/code/modules/unit_tests/range_return.dm new file mode 100644 index 00000000000..8d1d251255e --- /dev/null +++ b/code/modules/unit_tests/range_return.dm @@ -0,0 +1,20 @@ +/// This tests for an unspecified bit of behavior we rely on in energy_ball.dm code +/// Essentially, as of the current byond version, range and view will return turfs in what looks "roughly" like a circle +/// So we can be guarenteed that if we find a turf, it will be the closest turf of that sort, or at least one of them +/// This code tests for that. If this ever fails, remove the logic fron energy_ball.dm, and test if spiral_turfs would be faster +/datum/unit_test/range_return + +/datum/unit_test/range_return/Run() + var/x = (run_loc_floor_top_right.x - run_loc_floor_bottom_left.x) / 2 + var/y = (run_loc_floor_top_right.y - run_loc_floor_bottom_left.y) / 2 + // We take the turf equidistant from the two corners + var/turf/center = locate(x + run_loc_floor_bottom_left.x, y + run_loc_floor_bottom_left.y, run_loc_floor_bottom_left.z) + // Now, we'll iterate over all the turfs in range, and insure we don't see one with a higher dist then a previously seen instance + var/least_distance = 0 + for(var/turf/lad in orange(center, min(x, y))) + // get_dist is essentially max(dist deltas) + // So this is valid even if the corners aren't visited first + var/dist = get_dist(center, lad) + TEST_ASSERT(dist >= least_distance, "Range returned a turf of greater distance BEFORE a turf of lower distance. \ + Behavior has changed, remove all code that relies on this behavior") + least_distance = dist