Skip to content

Commit 4f122ce

Browse files
Copilotzardus
andcommitted
Replace pointless config tests with functional IPython history test
Co-authored-by: zardus <[email protected]>
1 parent 84cfb1b commit 4f122ce

File tree

1 file changed

+118
-32
lines changed

1 file changed

+118
-32
lines changed

test/test_flask_history.py

Lines changed: 118 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,130 @@
11
import pytest
22
import subprocess
33
import os
4-
import yaml
4+
import time
55

6-
def test_docker_compose_ctfd_ipython_mount():
7-
"""Test that the docker-compose.yml contains the correct volume mount for ipython persistence"""
6+
from utils import dojo_run
7+
8+
9+
def is_dojo_environment_available():
10+
"""Check if the dojo environment is available for testing"""
11+
try:
12+
# Try to run a simple dojo command to check if containers are running
13+
result = subprocess.run(
14+
["docker", "ps", "--filter", "name=ctfd", "--format", "{{.Names}}"],
15+
capture_output=True, text=True, timeout=10
16+
)
17+
return "ctfd" in result.stdout
18+
except (subprocess.TimeoutExpired, subprocess.CalledProcessError, FileNotFoundError):
19+
return False
20+
21+
22+
def test_flask_ipython_history_persistence():
23+
"""
24+
Functional test: Check that you can run `dojo flask`, enter a command,
25+
and have a resulting /data/ctfd-ipython/profile_default/history.sqlite file created.
826
9-
# Load and parse the docker-compose.yml file
10-
with open('/home/runner/work/dojo/dojo/docker-compose.yml', 'r') as f:
11-
compose_config = yaml.safe_load(f)
27+
This tests the actual functionality of IPython history persistence rather than
28+
just checking configuration files.
29+
"""
1230

13-
# Check that the ctfd service exists
14-
assert 'ctfd' in compose_config['services'], "ctfd service should exist in docker-compose.yml"
31+
# Check if the dojo environment is available
32+
if not is_dojo_environment_available():
33+
pytest.skip("Dojo environment (ctfd container) not running - skipping functional test")
1534

16-
# Check that the ctfd service has volumes
17-
ctfd_service = compose_config['services']['ctfd']
18-
assert 'volumes' in ctfd_service, "ctfd service should have volumes"
35+
# Set up paths for the test
36+
history_dir = "/data/ctfd-ipython/profile_default"
37+
history_file = f"{history_dir}/history.sqlite"
1938

20-
# Check that the ipython volume mount is present
21-
volumes = ctfd_service['volumes']
22-
ipython_mount = "/data/ctfd-ipython:/root/.ipython"
23-
assert ipython_mount in volumes, f"ctfd service should have ipython volume mount: {ipython_mount}"
24-
25-
def test_dojo_init_creates_ctfd_ipython_directory():
26-
"""Test that the dojo-init script creates the ctfd-ipython directory"""
39+
# Clean up any existing history to start fresh
40+
if os.path.exists(history_file):
41+
os.remove(history_file)
2742

28-
# Read the dojo-init script
29-
with open('/home/runner/work/dojo/dojo/dojo/dojo-init', 'r') as f:
30-
init_script = f.read()
43+
# Ensure the directory exists (should be created by dojo-init)
44+
os.makedirs(history_dir, exist_ok=True)
3145

32-
# Check that the script creates the ctfd-ipython directory
33-
assert "mkdir -p /data/ctfd-ipython" in init_script, "dojo-init should create /data/ctfd-ipython directory"
34-
35-
def test_flask_command_exists():
36-
"""Test that the dojo flask command exists and has correct implementation"""
46+
# Test commands to run in the flask shell
47+
# These are simple Python commands that should create IPython history
48+
test_commands = [
49+
"# Testing IPython history persistence",
50+
"x = 42",
51+
"print(f'The answer is {x}')",
52+
"exit()"
53+
]
3754

38-
# Read the dojo script
39-
with open('/home/runner/work/dojo/dojo/dojo/dojo', 'r') as f:
40-
dojo_script = f.read()
55+
command_input = "\n".join(test_commands) + "\n"
4156

42-
# Check that the flask command exists
43-
assert '"flask")' in dojo_script, "dojo script should have flask command"
44-
assert 'docker exec $DOCKER_ARGS ctfd flask shell' in dojo_script, "flask command should execute flask shell in ctfd container"
57+
try:
58+
# Run the flask shell with commands that will create history
59+
result = dojo_run(
60+
"flask",
61+
input=command_input,
62+
timeout=60,
63+
check=False # Don't fail if flask exits with non-zero (normal for interactive shells)
64+
)
65+
66+
# Allow some time for IPython to write the history file
67+
# IPython may write history on exit, so we need to wait
68+
time.sleep(3)
69+
70+
# Verify that the history file was created
71+
assert os.path.exists(history_file), (
72+
f"IPython history file should be created at {history_file} after running flask commands. "
73+
f"This indicates the volume mount /data/ctfd-ipython:/root/.ipython is working correctly."
74+
)
75+
76+
# Verify the file has content (should not be empty for a real SQLite database)
77+
file_size = os.path.getsize(history_file)
78+
assert file_size > 0, (
79+
f"IPython history file should not be empty: {history_file} (size: {file_size} bytes). "
80+
f"This suggests IPython successfully wrote command history to the persistent volume."
81+
)
82+
83+
# Test persistence by running another command and checking the file grows
84+
second_commands = [
85+
"# Second session to test persistence",
86+
"y = 24",
87+
"print(f'Half the answer is {y}')",
88+
"exit()"
89+
]
90+
91+
second_input = "\n".join(second_commands) + "\n"
92+
93+
dojo_run(
94+
"flask",
95+
input=second_input,
96+
timeout=60,
97+
check=False
98+
)
99+
100+
time.sleep(3)
101+
102+
# Verify that the history file was updated (size should have grown or stayed same)
103+
final_size = os.path.getsize(history_file)
104+
assert final_size >= file_size, (
105+
f"IPython history file should maintain or grow in size after second session. "
106+
f"Initial: {file_size} bytes, Final: {final_size} bytes. "
107+
f"This confirms history persistence across flask shell sessions."
108+
)
109+
110+
print(f"✓ IPython history persistence test passed")
111+
print(f" History file: {history_file}")
112+
print(f" Final size: {final_size} bytes")
113+
print(f" Volume mount /data/ctfd-ipython:/root/.ipython is working correctly")
114+
115+
except subprocess.TimeoutExpired:
116+
pytest.fail(
117+
"Flask shell command timed out. This may indicate:\n"
118+
"1. The ctfd container is not responding\n"
119+
"2. IPython is hanging waiting for input\n"
120+
"3. The flask shell setup has issues"
121+
)
122+
except subprocess.CalledProcessError as e:
123+
pytest.fail(
124+
f"Flask command failed with exit code {e.returncode}:\n"
125+
f"stdout: {e.stdout}\n"
126+
f"stderr: {e.stderr}\n"
127+
f"This may indicate issues with the ctfd container or flask setup"
128+
)
129+
except Exception as e:
130+
pytest.fail(f"Flask history persistence test failed: {e}")

0 commit comments

Comments
 (0)