diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 1ad3443aed9..82cc857eb95 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -63655,6 +63655,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt/dust, +/obj/effect/landmark/start/detective, /turf/open/floor/wood, /area/station/security/detectives_office) "whL" = ( diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index 6aa061054e7..ee237266bbe 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -8282,6 +8282,7 @@ /obj/effect/turf_decal/trimline/purple/filled/line{ dir = 1 }, +/obj/effect/landmark/start/roboticist, /turf/open/floor/iron, /area/station/science/robotics/lab) "buQ" = ( @@ -39347,6 +39348,7 @@ "mWe" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/landmark/start/roboticist, /turf/open/floor/iron/dark, /area/station/science/robotics/lab) "mWj" = ( @@ -48889,6 +48891,13 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/tram/right) +"qtK" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/landmark/start/roboticist, +/turf/open/floor/iron/dark, +/area/station/science/robotics/lab) "qtS" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/disposalpipe/segment{ @@ -50314,6 +50323,7 @@ /obj/structure/chair/office/light{ dir = 1 }, +/obj/effect/landmark/start/research_director, /turf/open/floor/glass/reinforced, /area/station/command/heads_quarters/rd) "qUF" = ( @@ -178967,7 +178977,7 @@ gyP aUb eeE wFx -uSP +qtK tPD uje uje @@ -179224,7 +179234,7 @@ gyP ixu eeE muZ -uSP +qtK bpa uje dLO diff --git a/_maps/multiz_debug.json b/_maps/multiz_debug.json index eaa71b7e220..b46b09d4ab6 100644 --- a/_maps/multiz_debug.json +++ b/_maps/multiz_debug.json @@ -3,6 +3,9 @@ "map_name": "MultiZ Debug", "map_path": "map_files/debug", "map_file": "multiz.dmm", + "ignored_unit_tests": [ + "/datum/unit_test/job_roundstart_spawnpoints" + ], "traits": [ { "Up": 1, diff --git a/_maps/runtimestation.json b/_maps/runtimestation.json index 6b77a7321f2..76e2224dbd2 100644 --- a/_maps/runtimestation.json +++ b/_maps/runtimestation.json @@ -4,6 +4,9 @@ "map_path": "map_files/debug", "map_file": "runtimestation.dmm", "space_ruin_levels": 1, + "ignored_unit_tests": [ + "/datum/unit_test/job_roundstart_spawnpoints" + ], "shuttles": { "cargo": "cargo_delta" } diff --git a/code/datums/map_config.dm b/code/datums/map_config.dm index 3eaee7d53c8..9a4bce61e92 100644 --- a/code/datums/map_config.dm +++ b/code/datums/map_config.dm @@ -41,6 +41,9 @@ /// List of additional areas that count as a part of the library var/library_areas = list() + /// List of unit tests that are skipped when running this map + var/list/skipped_tests + /** * Proc that simply loads the default map config, which should always be functional. */ @@ -199,6 +202,16 @@ continue library_areas += path +#ifdef UNIT_TESTS + // Check for unit tests to skip, no reason to check these if we're not running tests + for(var/path_as_text in json["ignored_unit_tests"]) + var/path_real = text2path(path_as_text) + if(!ispath(path_real, /datum/unit_test)) + stack_trace("Invalid path in mapping config for ignored unit tests: \[[path_as_text]\]") + continue + LAZYADD(skipped_tests, path_real) +#endif + defaulted = FALSE return TRUE #undef CHECK_EXISTS diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 00535f42686..10228499777 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -35,8 +35,11 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark) var/used = FALSE /obj/effect/landmark/start/proc/after_round_start() + // We'd like to keep these around for unit tests, so we can check that they exist. +#ifndef UNIT_TESTS if(delete_after_roundstart) qdel(src) +#endif /obj/effect/landmark/start/Initialize(mapload) . = ..() diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index 5b0d65716de..7a0395849c5 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -421,8 +421,7 @@ spawn_point.used = TRUE break if(!.) - log_world("Couldn't find a round start spawn point for [title]") - + log_mapping("Job [title] ([type]) couldn't find a round start spawn point.") /// Finds a valid latejoin spawn point, checking for events and special conditions. /datum/job/proc/get_latejoin_spawn_point() diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index aa67b372226..b65878b9cff 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -70,7 +70,12 @@ #else #define TEST_OUTPUT_GREEN(text) (text) #endif - +/// Change color to yellow on ANSI terminal output, if enabled with -DANSICOLORS. +#ifdef ANSICOLORS +#define TEST_OUTPUT_YELLOW(text) "\x1B\x5B1;33m[text]\x1B\x5B0m" +#else +#define TEST_OUTPUT_YELLOW(text) (text) +#endif /// A trait source when adding traits through unit tests #define TRAIT_SOURCE_UNIT_TESTS "unit_tests" @@ -142,6 +147,7 @@ #include "lungs.dm" #include "load_map_security.dm" #include "machine_disassembly.dm" +#include "map_landmarks.dm" #include "mapload_space_verification.dm" #include "mapping.dm" #include "mecha_damage.dm" diff --git a/code/modules/unit_tests/map_landmarks.dm b/code/modules/unit_tests/map_landmarks.dm new file mode 100644 index 00000000000..9d48785e350 --- /dev/null +++ b/code/modules/unit_tests/map_landmarks.dm @@ -0,0 +1,12 @@ +/// Tests that [/datum/job/proc/get_default_roundstart_spawn_point] returns a landmark from all joinable jobs. +/datum/unit_test/job_roundstart_spawnpoints + +/datum/unit_test/job_roundstart_spawnpoints/Run() + for(var/datum/job/job as anything in SSjob.joinable_occupations) + if(job.spawn_positions <= 0) + // Zero spawn positions means we don't need to care if they don't have a roundstart landmark + continue + if(job.get_default_roundstart_spawn_point()) + continue + + TEST_FAIL("Job [job.title] ([job.type]) has no default roundstart spawn landmark.") diff --git a/code/modules/unit_tests/mapping.dm b/code/modules/unit_tests/mapping.dm index e66cc2565f4..ff6a2577917 100644 --- a/code/modules/unit_tests/mapping.dm +++ b/code/modules/unit_tests/mapping.dm @@ -17,4 +17,3 @@ continue TEST_FAIL(log_entry) - diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm index c5fa8618b4c..847605f6642 100644 --- a/code/modules/unit_tests/unit_test.dm +++ b/code/modules/unit_tests/unit_test.dm @@ -159,40 +159,51 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) GLOB.current_test = test var/duration = REALTIMEOFDAY + var/skip_test = (test_path in SSmapping.config.skipped_tests) + var/test_output_desc = "[test_path]" + var/message = "" log_world("::group::[test_path]") - test.Run() - duration = REALTIMEOFDAY - duration - GLOB.current_test = null - GLOB.failed_any_test |= !test.succeeded + if(skip_test) + log_world("[TEST_OUTPUT_YELLOW("SKIPPED")] Skipped run on map [SSmapping.config.map_name].") - var/list/log_entry = list() - var/list/fail_reasons = test.fail_reasons + else - for(var/reasonID in 1 to LAZYLEN(fail_reasons)) - var/text = fail_reasons[reasonID][1] - var/file = fail_reasons[reasonID][2] - var/line = fail_reasons[reasonID][3] + test.Run() - test.log_for_test(text, "error", file, line) + duration = REALTIMEOFDAY - duration + GLOB.current_test = null + GLOB.failed_any_test |= !test.succeeded - // Normal log message - log_entry += "\tFAILURE #[reasonID]: [text] at [file]:[line]" + var/list/log_entry = list() + var/list/fail_reasons = test.fail_reasons - var/message = log_entry.Join("\n") - log_test(message) + for(var/reasonID in 1 to LAZYLEN(fail_reasons)) + var/text = fail_reasons[reasonID][1] + var/file = fail_reasons[reasonID][2] + var/line = fail_reasons[reasonID][3] - var/test_output_desc = "[test_path] [duration / 10]s" - if (test.succeeded) - log_world("[TEST_OUTPUT_GREEN("PASS")] [test_output_desc]") + test.log_for_test(text, "error", file, line) + + // Normal log message + log_entry += "\tFAILURE #[reasonID]: [text] at [file]:[line]" + + if(length(log_entry)) + message = log_entry.Join("\n") + log_test(message) + + test_output_desc += " [duration / 10]s" + if (test.succeeded) + log_world("[TEST_OUTPUT_GREEN("PASS")] [test_output_desc]") log_world("::endgroup::") - if (!test.succeeded) + if (!test.succeeded && !skip_test) log_world("::error::[TEST_OUTPUT_RED("FAIL")] [test_output_desc]") - test_results[test_path] = list("status" = test.succeeded ? UNIT_TEST_PASSED : UNIT_TEST_FAILED, "message" = message, "name" = test_path) + var/final_status = skip_test ? UNIT_TEST_SKIPPED : (test.succeeded ? UNIT_TEST_PASSED : UNIT_TEST_FAILED) + test_results[test_path] = list("status" = final_status, "message" = message, "name" = test_path) qdel(test)