From 616772574efc407b895f5d9526f00df384564ebd Mon Sep 17 00:00:00 2001 From: san7890 Date: Thu, 29 Jun 2023 20:16:37 -0600 Subject: [PATCH] Ensures that all Unit Tests are ticked in `_unit_tests.dm` (#76404) ## About The Pull Request Ensures we don't get a repeat of #76345 (unit test that wasn't ticked in the `_unit_tests.dm` file, fixed in 596ca8b6d4cc49cd69fc104b53b7f4973497a2e5). Basically, we leverage the code that was already being used in the DME Validator but then expand it a bunch via using JSON Schemas that correspond to the type of scan we want to run. Even though sorting unit tests alphabetically is a bit different than sorting the tgstation DME, it's good to leverage the already existing framework rather than create a copy-pasta "lesser" code runner. This went through strenous testing on my end, so let me know if anything seems off. While in the area, I added some other niceties that I've found work really well in GitHub Runners environments, as well as local testing in case you really like doing that before you make a PR for some reason. ## Why It's Good For The Game ![image](https://github.com/tgstation/tgstation/assets/34697715/307161d7-cef1-418b-9a51-2a7bf6c5b678) This is what it looks like pre-596ca8b6d4cc49cd69fc104b53b7f4973497a2e5 (this is now merged, so it will pass CI) De-hardcodes some stuff and allows for some neater flexibility, less cringe unit tests being coded and not being ticked in the file, etc. etc. ## Changelog Nothing for players to care about. Let me know if you have a better idea than the schemas, I couldn't think of one that could be really extensible and flexible in the same way this is. --- .github/workflows/ci_suite.yml | 3 +- code/modules/unit_tests/_unit_tests.dm | 8 +- .../schemas/tgstation_dme.json | 10 ++ .../schemas/unit_tests.json | 9 ++ .../ticked_file_enforcement.py | 134 ++++++++++++++++++ tools/validate_dme.py | 95 ------------- 6 files changed, 160 insertions(+), 99 deletions(-) create mode 100644 tools/ticked_file_enforcement/schemas/tgstation_dme.json create mode 100644 tools/ticked_file_enforcement/schemas/unit_tests.json create mode 100644 tools/ticked_file_enforcement/ticked_file_enforcement.py delete mode 100644 tools/validate_dme.py diff --git a/.github/workflows/ci_suite.yml b/.github/workflows/ci_suite.yml index b5ed61226f2..b3c798cf229 100644 --- a/.github/workflows/ci_suite.yml +++ b/.github/workflows/ci_suite.yml @@ -57,7 +57,8 @@ jobs: bash tools/ci/check_changelogs.sh bash tools/ci/check_grep.sh bash tools/ci/check_misc.sh - tools/bootstrap/python tools/validate_dme.py b_segment) - (a_segment < b_segment) + + print(f"Two lines were exactly the same ({a} vs. {b})") + sys.exit(1) + +sorted_lines = sorted(lines, key = functools.cmp_to_key(compare_lines)) +for (index, line) in enumerate(lines): + if sorted_lines[index] != line: + post_error(f"The include at line {index + offset} is out of order ({line}, expected {sorted_lines[index]})") + sys.exit(1) + +print(green(f"Ticked File Enforcement: [{file_reference}] All includes are in order!")) diff --git a/tools/validate_dme.py b/tools/validate_dme.py deleted file mode 100644 index ce1499f82fd..00000000000 --- a/tools/validate_dme.py +++ /dev/null @@ -1,95 +0,0 @@ -import fnmatch -import functools -import glob -import sys - -reading = False - -FORBID_INCLUDE = [ - # Included by _unit_test.dm - r'code/modules/unit_tests/[!_]*.dm', - - # Included by tgs/includes.dm - r'code/modules/tgs/**/*.dm', -] - -lines = [] -total = 0 -for line in sys.stdin: - total+=1 - line = line.strip() - - if line == "// BEGIN_INCLUDE": - reading = True - continue - elif line == "// END_INCLUDE": - break - elif not reading: - continue - - lines.append(line) - -offset = total - len(lines) -print(f"{offset} lines were ignored in output") -fail_no_include = False - -for code_file in glob.glob("code/**/*.dm", recursive=True): - dm_path = code_file.replace('/', '\\') - - included = f"#include \"{dm_path}\"" in lines - forbid_include = False - - for forbid in FORBID_INCLUDE: - if not fnmatch.fnmatch(code_file, forbid): - continue - - forbid_include = True - - if included: - print(f"{dm_path} should not be included") - print(f"::error file={code_file},line=1,title=DME Validator::File should not be included") - fail_no_include = True - - if forbid_include: - continue - - if not included: - print(f"{dm_path} is not included") - print(f"::error file={code_file},line=1,title=DME Validator::File is not included") - fail_no_include = True - -if fail_no_include: - sys.exit(1) - -def compare_lines(a, b): - # Remove initial include as well as the final quotation mark - a = a[len("#include \""):-1].lower() - b = b[len("#include \""):-1].lower() - - a_segments = a.split('\\') - b_segments = b.split('\\') - - for (a_segment, b_segment) in zip(a_segments, b_segments): - a_is_file = a_segment.endswith(".dm") - b_is_file = b_segment.endswith(".dm") - - # code\something.dm will ALWAYS come before code\directory\something.dm - if a_is_file and not b_is_file: - return -1 - - if b_is_file and not a_is_file: - return 1 - - # interface\something.dm will ALWAYS come after code\something.dm - if a_segment != b_segment: - return (a_segment > b_segment) - (a_segment < b_segment) - - print(f"Two lines were exactly the same ({a} vs. {b})") - sys.exit(1) - -sorted_lines = sorted(lines, key = functools.cmp_to_key(compare_lines)) -for (index, line) in enumerate(lines): - if sorted_lines[index] != line: - print(f"The include at line {index + offset} is out of order ({line}, expected {sorted_lines[index]})") - print(f"::error file=tgstation.dme,line={index+offset},title=DME Validator::The include at line {index + offset} is out of order ({line}, expected {sorted_lines[index]})") - sys.exit(1)