diff --git a/GEMINI.md b/GEMINI.md index 883827c..93a5b4d 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -15,3 +15,13 @@ The primary goal is to use the context of CTF challenges (forensics, crypto, web - Understanding standard library modules relevant to security (e.g., `os`, `sys`, `base64`, `hashlib`). - Analyzing existing scripts to understand control flow, data structures, and error handling. - Exploring how Python interacts with the shell and external tools. + +## Test cases +- Verifying user written code +- When asked, Write tests cases in `test_utils.py` +- Don't run anything, just write the cases +- create a fully temporary test environment in `tests/env` +- Don't fully delete the environment between tests, just modify as needed when writing new test cases +- write tests explaining successful passes and failures +- Try to find breaking elements of user code. Find harder cases that will fail on empty inputs, etc. +- Include tests that chain multiple functions together diff --git a/src/ctf/main.py b/src/ctf/main.py index bda53a7..6e394da 100644 --- a/src/ctf/main.py +++ b/src/ctf/main.py @@ -16,31 +16,10 @@ def set_arguments(): args = parser.parse_args() return args -# Class for a competition, defining active catagories, challenges completed, etc -# return a list of paths for each catagory in a competition -def active_categories(p: Path) -> list: - cats = [] - if not p.exists(): return [] - for cat in p.iterdir(): - cats.append(cat) - return cats -#return a dictionary of competitions in the base directory -def active_competitions(dir: str) -> dict: - comps = {} - p = Path(dir) - if not p.exists(): return {} - for item in p.iterdir(): - if item.name == "tools": continue - comps[item] = active_categories(item) - print(item.name) - print(comps[item.name]) - return comps - def main(): - active_comps = active_competitions(enviroment["ctf_dir"]) - print(active_comps) + print("running main") diff --git a/src/ctf/utils.py b/src/ctf/utils.py index 533629e..620859f 100644 --- a/src/ctf/utils.py +++ b/src/ctf/utils.py @@ -19,6 +19,30 @@ def write_config(data: dict, config = f"{user_config_dir()}/ctf"): with open(config, "w") as f: toml.dump(data, f) +# return a list of path objects for each catagory in a competition +def active_categories(p: Path) -> list: + cats = [] + if not p.exists(): return [] + for cat in p.iterdir(): + cats.append(cat) + return cats + +#return a lsit of Path objects of competitions in the base directory +def active_competitions(dir: str) -> dict: + comps = {} + p = Path(dir) + if not p.exists(): return {} + for item in p.iterdir(): + if item.name == "tools": continue + comps[item] = active_categories(item) + print(item.name) + print(comps[item]) + return comps + +# Class for a competition, defining active catagories, challenges completed, etc +class competition(): + def __init__(self, p: Path): + pass config = load_config("/home/venus/code/ctf/config.toml") competition = config["Competition"] diff --git a/tests/env/config.toml b/tests/env/config.toml new file mode 100644 index 0000000..9f597b2 --- /dev/null +++ b/tests/env/config.toml @@ -0,0 +1,5 @@ +[Competition] +name = "PersistentComp" + +[Enviroment] +data_dir = "/home/venus/code/ctf/tests/env" diff --git a/tests/test_utils.py b/tests/test_utils.py index 7f86d14..03258f6 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,28 +1,48 @@ from pathlib import Path import toml -from ctf.utils import load_config +from ctf.utils import load_config, active_categories, active_competitions -def test_load_config_valid_file(tmp_path): - # 1. Setup: Create a temporary TOML file - config_file = tmp_path / "test_config.toml" +# Define the persistent test environment path +TEST_ENV = Path("tests/env") + +def test_load_config_static(): + """ + Verifies load_config using the persistent test file. + Demonstrates: Reading from a specific relative Path. + """ + config_file = TEST_ENV / "config.toml" test_data = { - "Competition": {"name": "TestComp"}, - "Environment": {"data_dir": "/tmp/ctf"} + "Competition": {"name": "PersistentComp"}, + "Enviroment": {"data_dir": str(TEST_ENV.absolute())} } with open(config_file, "w") as f: toml.dump(test_data, f) - # 2. Act: Load the config using our function loaded_data = load_config(str(config_file)) - - # 3. Assert: Verify the data matches - assert loaded_data["Competition"]["name"] == "TestComp" - assert loaded_data["Environment"]["data_dir"] == "/tmp/ctf" + assert loaded_data["Competition"]["name"] == "PersistentComp" -def test_load_config_missing_file(): - # Act: Try to load a file that doesn't exist - loaded_data = load_config("nonexistent_file.toml") +def test_active_categories_static(): + """ + Verifies active_categories using the pre-created 'comp1' folder. + Demonstrates: Path.iterdir() behavior on a real directory. + """ + comp_dir = TEST_ENV / "comp1" + cats = active_categories(comp_dir) + cat_names = [c.name for c in cats] - # Assert: Should return an empty dictionary - assert loaded_data == {} + # We expect 'web' and 'pwn' which were created in the setup step + assert "web" in cat_names + assert "pwn" in cat_names +def test_active_competitions_static(): + """ + Verifies active_competitions skips the 'tools' folder in TEST_ENV. + Demonstrates: Guard clauses and directory filtering. + """ + # Note: active_competitions takes a string path + comps = active_competitions(str(TEST_ENV)) + comp_names = [p.name for p in comps.keys()] + + assert "comp1" in comp_names + assert "comp2" in comp_names + assert "tools" not in comp_names # The 'tools' folder exists but should be ignored