mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-23 15:38:08 +00:00
The holodeck runtimes if it's not linked to a holodeck area. When running integration tests on the default CI map, metastation, this is fine because the one created by create_and_destroy just links to the holodeck on-station. This technically would cause problems in a real game since it's a 2-way link, (create_and_destroy breaks the link to the real on-station computer when it does its test) but no unit tests check that. Unfortunately, runtime and multiz debug don't have holodecks (for good reason, it's completely unnecessary for testing literally anything but specifically the holodeck) and fail CI as a result. Since the unit test isn't trying to test for the existence of a well-designed recreation area, I've set unit_test/create_and_destroy to ignore the holodeck computer. Edit: I've added better mapping error handling for this case in the holodeck. I still don't want a pointless mapping error in my CI either so I'm keeping the ignore.
182 lines
7.9 KiB
Plaintext
182 lines
7.9 KiB
Plaintext
///Delete one of every type, sleep a while, then check to see if anything has gone fucky
|
|
/datum/unit_test/create_and_destroy
|
|
//You absolutely must run last
|
|
priority = TEST_DEL_WORLD
|
|
|
|
/datum/unit_test/create_and_destroy/Run()
|
|
//We'll spawn everything here
|
|
var/turf/spawn_at = run_loc_floor_bottom_left
|
|
var/list/ignore = list(
|
|
//Never meant to be created, errors out the ass for mobcode reasons
|
|
/mob/living/carbon,
|
|
//Nother template type, doesn't like being created with no seed
|
|
/obj/item/food/grown,
|
|
//And another
|
|
/obj/item/slimecross/recurring,
|
|
//This should be obvious
|
|
/obj/machinery/doomsday_device,
|
|
//Yet more templates
|
|
/obj/machinery/restaurant_portal,
|
|
//Template type
|
|
/obj/effect/mob_spawn,
|
|
//Template type
|
|
/obj/structure/holosign/robot_seat,
|
|
//Singleton
|
|
/mob/dview,
|
|
//Template type
|
|
/obj/item/bodypart,
|
|
)
|
|
//Say it with me now, type template
|
|
ignore += typesof(/obj/effect/mapping_helpers)
|
|
//This turf existing is an error in and of itself
|
|
ignore += typesof(/turf/baseturf_skipover)
|
|
ignore += typesof(/turf/baseturf_bottom)
|
|
//This demands a borg, so we'll let if off easy
|
|
ignore += typesof(/obj/item/modular_computer/tablet/integrated)
|
|
//This one demands a computer, ditto
|
|
ignore += typesof(/obj/item/modular_computer/processor)
|
|
//Very finiky, blacklisting to make things easier
|
|
ignore += typesof(/obj/item/poster/wanted)
|
|
//This expects a seed, we can't pass it
|
|
ignore += typesof(/obj/item/food/grown)
|
|
//Nothing to hallucinate if there's nothing to hallicinate
|
|
ignore += typesof(/obj/effect/hallucination)
|
|
//These want fried food to take on the shape of, we can't pass that in
|
|
ignore += typesof(/obj/item/food/deepfryholder)
|
|
//Can't pass in a thing to glow
|
|
ignore += typesof(/obj/effect/abstract/eye_lighting)
|
|
//We don't have a pod
|
|
ignore += typesof(/obj/effect/pod_landingzone_effect)
|
|
ignore += typesof(/obj/effect/pod_landingzone)
|
|
//We have a baseturf limit of 10, adding more than 10 baseturf helpers will kill CI, so here's a future edge case to fix.
|
|
ignore += typesof(/obj/effect/baseturf_helper)
|
|
//There's no shapeshift to hold
|
|
ignore += typesof(/obj/shapeshift_holder)
|
|
//No tauma to pass in
|
|
ignore += typesof(/mob/camera/imaginary_friend)
|
|
//No pod to gondola
|
|
ignore += typesof(/mob/living/simple_animal/pet/gondola/gondolapod)
|
|
//No heart to give
|
|
ignore += typesof(/obj/structure/ethereal_crystal)
|
|
//No linked console
|
|
ignore += typesof(/mob/camera/ai_eye/remote/base_construction)
|
|
//See above
|
|
ignore += typesof(/mob/camera/ai_eye/remote/shuttle_docker)
|
|
//Hangs a ref post invoke async, which we don't support. Could put a qdeleted check but it feels hacky
|
|
ignore += typesof(/obj/effect/anomaly/grav/high)
|
|
//See above
|
|
ignore += typesof(/obj/effect/timestop)
|
|
//Invoke async in init, skippppp
|
|
ignore += typesof(/mob/living/silicon/robot/model)
|
|
//This lad also sleeps
|
|
ignore += typesof(/obj/item/hilbertshotel)
|
|
//this boi spawns turf changing stuff, and it stacks and causes pain. Let's just not
|
|
ignore += typesof(/obj/effect/sliding_puzzle)
|
|
//Stacks baseturfs, can't be tested here
|
|
ignore += typesof(/obj/effect/temp_visual/lava_warning)
|
|
//Stacks baseturfs, can't be tested here
|
|
ignore += typesof(/obj/effect/landmark/ctf)
|
|
//Our system doesn't support it without warning spam from unregister calls on things that never registered
|
|
ignore += typesof(/obj/docking_port)
|
|
//Asks for a shuttle that may not exist, let's leave it alone
|
|
ignore += typesof(/obj/item/pinpointer/shuttle)
|
|
//This spawns beams as a part of init, which can sleep past an async proc. This hangs a ref, and fucks us. It's only a problem here because the beam sleeps with CHECK_TICK
|
|
ignore += typesof(/obj/structure/alien/resin/flower_bud)
|
|
//Needs a linked mecha
|
|
ignore += typesof(/obj/effect/skyfall_landingzone)
|
|
//Expects a mob to holderize, we have nothing to give
|
|
ignore += typesof(/obj/item/clothing/head/mob_holder)
|
|
//Needs cards passed into the initilazation args
|
|
ignore += typesof(/obj/item/toy/cards/cardhand)
|
|
//Needs a holodeck area linked to it which is not guarenteed to exist and technically is supposed to have a 1:1 relationship with computer anyway.
|
|
ignore += typesof(/obj/machinery/computer/holodeck)
|
|
|
|
var/list/cached_contents = spawn_at.contents.Copy()
|
|
var/baseturf_count = length(spawn_at.baseturfs)
|
|
|
|
for(var/type_path in typesof(/atom/movable, /turf) - ignore) //No areas please
|
|
if(ispath(type_path, /turf))
|
|
spawn_at.ChangeTurf(type_path, /turf/baseturf_skipover)
|
|
//We change it back to prevent pain, please don't ask
|
|
spawn_at.ChangeTurf(/turf/open/floor/wood, /turf/baseturf_skipover)
|
|
if(baseturf_count != length(spawn_at.baseturfs))
|
|
TEST_FAIL("[type_path] changed the amount of baseturfs we have [baseturf_count] -> [length(spawn_at.baseturfs)]")
|
|
baseturf_count = length(spawn_at.baseturfs)
|
|
else
|
|
var/atom/creation = new type_path(spawn_at)
|
|
if(QDELETED(creation))
|
|
continue
|
|
//Go all in
|
|
qdel(creation, force = TRUE)
|
|
//This will hold a ref to the last thing we process unless we set it to null
|
|
//Yes byond is fucking sinful
|
|
creation = null
|
|
|
|
//There's a lot of stuff that either spawns stuff in on create, or removes stuff on destroy. Let's cut it all out so things are easier to deal with
|
|
var/list/to_del = spawn_at.contents - cached_contents
|
|
if(length(to_del))
|
|
for(var/atom/to_kill in to_del)
|
|
qdel(to_kill)
|
|
|
|
//Hell code, we're bound to have ended the round somehow so let's stop if from ending while we work
|
|
SSticker.delay_end = TRUE
|
|
//Prevent the garbage subsystem from harddeling anything, if only to save time
|
|
SSgarbage.collection_timeout[GC_QUEUE_HARDDELETE] = 10000 HOURS
|
|
//Clear it, just in case
|
|
cached_contents.Cut()
|
|
|
|
//Now that we've qdel'd everything, let's sleep until the gc has processed all the shit we care about
|
|
var/time_needed = SSgarbage.collection_timeout[GC_QUEUE_CHECK]
|
|
var/start_time = world.time
|
|
var/garbage_queue_processed = FALSE
|
|
|
|
sleep(time_needed)
|
|
while(!garbage_queue_processed)
|
|
var/list/queue_to_check = SSgarbage.queues[GC_QUEUE_CHECK]
|
|
//How the hell did you manage to empty this? Good job!
|
|
if(!length(queue_to_check))
|
|
garbage_queue_processed = TRUE
|
|
break
|
|
|
|
var/list/oldest_packet = queue_to_check[1]
|
|
//Pull out the time we deld at
|
|
var/qdeld_at = oldest_packet[1]
|
|
//If we've found a packet that got del'd later then we finished, then all our shit has been processed
|
|
if(qdeld_at > start_time)
|
|
garbage_queue_processed = TRUE
|
|
break
|
|
|
|
if(world.time > start_time + time_needed + 30 MINUTES) //If this gets us gitbanned I'm going to laugh so hard
|
|
TEST_FAIL("Something has gone horribly wrong, the garbage queue has been processing for well over 30 minutes. What the hell did you do")
|
|
break
|
|
|
|
//Immediately fire the gc right after
|
|
SSgarbage.next_fire = 1
|
|
//Unless you've seriously fucked up, queue processing shouldn't take "that" long. Let her run for a bit, see if anything's changed
|
|
sleep(20 SECONDS)
|
|
|
|
//Alright, time to see if anything messed up
|
|
var/list/cache_for_sonic_speed = SSgarbage.items
|
|
for(var/path in cache_for_sonic_speed)
|
|
var/datum/qdel_item/item = cache_for_sonic_speed[path]
|
|
if(item.failures)
|
|
TEST_FAIL("[item.name] hard deleted [item.failures] times out of a total del count of [item.qdels]")
|
|
if(item.no_respect_force)
|
|
TEST_FAIL("[item.name] failed to respect force deletion [item.no_respect_force] times out of a total del count of [item.qdels]")
|
|
if(item.no_hint)
|
|
TEST_FAIL("[item.name] failed to return a qdel hint [item.no_hint] times out of a total del count of [item.qdels]")
|
|
|
|
cache_for_sonic_speed = SSatoms.BadInitializeCalls
|
|
for(var/path in cache_for_sonic_speed)
|
|
var/fails = cache_for_sonic_speed[path]
|
|
if(fails & BAD_INIT_NO_HINT)
|
|
TEST_FAIL("[path] didn't return an Initialize hint")
|
|
if(fails & BAD_INIT_QDEL_BEFORE)
|
|
TEST_FAIL("[path] qdel'd in New()")
|
|
if(fails & BAD_INIT_SLEPT)
|
|
TEST_FAIL("[path] slept during Initialize()")
|
|
|
|
SSticker.delay_end = FALSE
|
|
//This shouldn't be needed, but let's be polite
|
|
SSgarbage.collection_timeout[GC_QUEUE_HARDDELETE] = 10 SECONDS
|