Files
Bubberstation/code/modules/unit_tests/heretic_rituals.dm
T
TastyfishandGitHub bca463316b Makes integration test results be in color and have annotations (#66649)
About The Pull Request

    Separated compiling the integration tests and running them as separate steps for organization purposes.
    Added a TEST_ASSERT_NULL(value, reason) and TEST_ASSERT_NOTNULL(value, reason) because those are conceptually simple tests.
    Makes the PASS and FAIL prefixes in the integration test log be green and red for better readability.
    Failure reasons now display the file and line number.
        In order to achieve this, direct calls to Fail() are now wrapped in a macro, TEST_FAIL(), as Fail() itself needs preprocessor stuff passed to it.
        In the midst of updating it, I noticed multiple cases of tests directly calling Fail() and returning when they should have used a better macro, so those were updated. There was at least one case where it appeared that the code assumed that the test ended at Fail(), but made no attempt to do so, such as with the RCD test.
        Feel free to double check all of the changed unit tests in case I made a functional behavior change, but they currently pass.
    To take advantage of the previous change, failures are now marked as annotations. Note that outside of github, this creates an ugly-looking line but the primary environment is as a github action.

Examples with intentionally botched unit test:

image

image

image
Why It's Good For The Game

Makes inspecting failed unit tests significantly easier.
Changelog

N/A
2022-05-04 13:19:01 +12:00

117 lines
5.9 KiB
Plaintext

/*
* This test checks that all heretic knowledges that unlocks rituals
* properly consume all used atoms and creates all resulting atoms.
*
* This test ONLY checks knowledges that unlock rituals which consume atoms and produce atoms.
* - Rituals that consume atoms, but do not create any atoms (such as rituals of knowledge) are not tested.
* - Summon rituals sleep after completing as they expect a ghost candidate to fill the summon, so they're skipped.
* - Final rituals results in a bunch of side-effects and vary a good deal so they're skipped explicitly.
* - Sacrifice ritual (Hunt and Sacrifice) requires sacrifice targets, as well as spawning a new z-level, so it's better not to test.
*/
/datum/unit_test/heretic_rituals
/datum/unit_test/heretic_rituals/Run()
// Gotta create ourselves a rune and a user to start.
var/obj/effect/heretic_rune/big/our_rune = allocate(/obj/effect/heretic_rune/big)
var/mob/living/carbon/human/our_heretic = allocate(/mob/living/carbon/human)
// -- Note for the human dummy we create:
// The user does not actually NEED a heretic antag datum for the type of rituals we're testing,
// so we don't give them one here. The heretic antag datum has side effects when applied,
// like creating influences and learning the default knowledge types, so better safe than sorry.
// Slap them down somewhere. The "heretic" should be in the middle of the rune, though this doesn't really matter.
our_rune.forceMove(run_loc_floor_bottom_left)
our_heretic.forceMove(locate((run_loc_floor_bottom_left.x + 1), (run_loc_floor_bottom_left.y + 1), run_loc_floor_bottom_left.z))
// Set up the blacklist for types we don't want to test here. See above for reasons.
var/list/blacklist_typecache = typecacheof(list(
/datum/heretic_knowledge/summon,
/datum/heretic_knowledge/final,
/datum/heretic_knowledge/hunt_and_sacrifice,
))
var/list/all_ritual_knowledge = list()
// Now, let's instantiate our all_ritual_knowledge list with knowledge we're gonna test.
for(var/knowledge_type in typesof(/datum/heretic_knowledge))
// Skip blacklisted types
if(is_type_in_typecache(knowledge_type, blacklist_typecache))
continue
var/datum/heretic_knowledge/instantiated_knowledge = new knowledge_type()
// No required atoms = it's not a ritual, delete it and move on
// No resulting atoms = it's not a ritual we test here, delete it and move on
if(!LAZYLEN(instantiated_knowledge.required_atoms) || !LAZYLEN(instantiated_knowledge.result_atoms))
qdel(instantiated_knowledge)
continue
all_ritual_knowledge += instantiated_knowledge
// All the knowledge we want to test is instantiated, let's actually test their rituals now.
for(var/datum/heretic_knowledge/knowledge as anything in all_ritual_knowledge)
// Let's do a dry run of any special checks the knowledge may have
// without any atoms passed at all. This is to ensure that,
// if the ritual requires specific circumstances we can't setup in this test,
// such as freezing temperatures or humans that are augmented on completion,
// that we don't proceede to try to test them (as they'll fail anyways).
if(!knowledge.recipe_snowflake_check(our_heretic, list(), list(), get_turf(our_rune)))
continue
// Okay, so we've got a knowledge by this point we definitely want to test.
// Go though all the atoms it wants for it's ritual and create them on the rune.
var/list/created_atoms = list()
for(var/ritual_item_path in knowledge.required_atoms)
var/amount_to_create = knowledge.required_atoms[ritual_item_path]
for(var/i in 1 to amount_to_create)
created_atoms += new ritual_item_path(get_turf(our_heretic))
// Now, we can ACTUALLY run the ritual. Let's do it.
// Attempt to run the knowledge via the sacrifice rune.
// If do_ritual() returns FALSE with our knowledge, it messed up.
// If do_ritual() returns TRUE, then it was successful.
if(!our_rune.do_ritual(our_heretic, knowledge))
// We failed. The knowledge should have everything to succeed, yet it returned FALSE!
// Clean up the atoms it was meant to consume, so we can keep testing.
for(var/atom/leftover as anything in created_atoms)
created_atoms -= leftover
qdel(leftover)
// Aaand throw a fail.
TEST_FAIL("Heretic rituals: ([knowledge.type]) Despite having all required atoms present, the ritual failed to transmute.")
continue
// Making it here means the ritual was a success.
// Let's check all the atoms nearby to see if we got what we wanted.
var/list/atom/movable/nearby_atoms = range(1, our_heretic)
nearby_atoms -= our_heretic // Our dude is supposed to be there
nearby_atoms -= our_rune // Same with our rune
// Did we get all the results we want?
for(var/result_item_path in knowledge.result_atoms)
var/atom/result = locate(result_item_path) in nearby_atoms
// No, we couldn't find the a resulting atom on the rune. Throw a fail.
if(!result)
TEST_FAIL("Heretic rituals: ([knowledge.type]) Despite successfully completing the ritual, a resulting atom could not be found ([result_item_path])")
continue
// Yes, we got a resulting atom we expected! Remove it from the list and clean up.
nearby_atoms -= result
qdel(result)
// Finally, we checked all of our resulting atoms and cleaned them up.
// The nearby_atoms list should be devoid of any atom/movables now. Let's double-check that.
for(var/atom/thing as anything in nearby_atoms)
if(!ismovable(thing))
continue
// There are atoms around the rune still, and there shouldn't be.
// All component atoms were consumed, and all resulting atoms were cleaned up.
// This means the ritual may have messed up somewhere. Throw a fail and clean them up so we can keep testing.
TEST_FAIL("Heretic rituals: ([knowledge.type]) After completing the ritual, there were non-result atoms remaining on the rune. ([thing] - [thing.type])")
nearby_atoms -= thing
qdel(thing)
// All done, clean up the knowledge list.
QDEL_LIST(all_ritual_knowledge)