Ctftime test context #928 (#1866)

Works on #928
This commit is contained in:
Ife Lawal
2021-04-26 14:31:19 -04:00
committed by GitHub
parent 03e546e9f0
commit f00e69d619
3 changed files with 135 additions and 98 deletions

9
tests/constants/time.py Normal file
View File

@@ -0,0 +1,9 @@
from CTFd.constants import RawEnum
class FreezeTimes(str, RawEnum):
NOT_STARTED = "2017-10-3" # Tuesday, October 3, 2017
STARTED = "2017-10-5" # Thursday, October 5, 2017
ENDED = "2017-10-7" # Saturday, October 7, 2017
START = "1507089600" # Wednesday, October 4, 2017 12:00:00 AM GMT-04:00 DST
END = "1507262400" # Friday, October 6, 2017 12:00:00 AM GMT-04:00 DST

View File

@@ -4,10 +4,12 @@ import random
import string import string
import uuid import uuid
from collections import namedtuple from collections import namedtuple
from contextlib import contextmanager
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
import requests import requests
from flask.testing import FlaskClient from flask.testing import FlaskClient
from freezegun import freeze_time
from sqlalchemy.engine.url import make_url from sqlalchemy.engine.url import make_url
from sqlalchemy_utils import drop_database from sqlalchemy_utils import drop_database
from werkzeug.datastructures import Headers from werkzeug.datastructures import Headers
@@ -40,6 +42,8 @@ from CTFd.models import (
UserComments, UserComments,
Users, Users,
) )
from CTFd.utils import set_config
from tests.constants.time import FreezeTimes
text_type = str text_type = str
binary_type = bytes binary_type = bytes
@@ -61,6 +65,57 @@ class CTFdTestClient(FlaskClient):
return super(CTFdTestClient, self).open(*args, **kwargs) return super(CTFdTestClient, self).open(*args, **kwargs)
class ctftime:
@contextmanager
def init():
"""
This context manager can be used to setup start and end dates for a test CTFd
"""
try:
set_config("start", FreezeTimes.START)
set_config("end", FreezeTimes.END)
yield
finally:
set_config("start", None)
set_config("end", None)
@contextmanager
def not_started():
"""
This context manager sets the current time to before the start date of the test CTFd
"""
try:
freezer = freeze_time(FreezeTimes.NOT_STARTED)
frozen_time = freezer.start()
yield frozen_time
finally:
freezer.stop()
@contextmanager
def started():
"""
This context manager sets the current time to the start date of the test CTFd
"""
try:
freezer = freeze_time(FreezeTimes.STARTED)
frozen_time = freezer.start()
yield frozen_time
finally:
freezer.stop()
@contextmanager
def ended():
"""
This context manager sets the current time to after the end date of the test CTFd
"""
try:
freezer = freeze_time(FreezeTimes.ENDED)
frozen_time = freezer.start()
yield frozen_time
finally:
freezer.stop()
def create_ctfd( def create_ctfd(
ctf_name="CTFd", ctf_name="CTFd",
ctf_description="CTF description", ctf_description="CTF description",

View File

@@ -1,10 +1,8 @@
from freezegun import freeze_time
from CTFd.models import Solves from CTFd.models import Solves
from CTFd.utils import set_config
from CTFd.utils.dates import ctf_ended, ctf_started from CTFd.utils.dates import ctf_ended, ctf_started
from tests.helpers import ( from tests.helpers import (
create_ctfd, create_ctfd,
ctftime,
destroy_ctfd, destroy_ctfd,
gen_challenge, gen_challenge,
gen_flag, gen_flag,
@@ -17,29 +15,24 @@ def test_ctftime_prevents_accessing_challenges_before_ctf():
"""Test that the ctftime function prevents users from accessing challenges before the ctf""" """Test that the ctftime function prevents users from accessing challenges before the ctf"""
app = create_ctfd() app = create_ctfd()
with app.app_context(): with app.app_context():
set_config( with ctftime.init():
"start", "1507089600" register_user(app)
) # Wednesday, October 4, 2017 12:00:00 AM GMT-04:00 DST chal = gen_challenge(app.db)
set_config( chal_id = chal.id
"end", "1507262400" gen_flag(app.db, challenge_id=chal.id, content=u"flag")
) # Friday, October 6, 2017 12:00:00 AM GMT-04:00 DST
register_user(app)
chal = gen_challenge(app.db)
chal_id = chal.id
gen_flag(app.db, challenge_id=chal.id, content=u"flag")
with freeze_time("2017-10-3"): # CTF has not started yet. with ctftime.not_started():
client = login_as_user(app) client = login_as_user(app)
r = client.get("/challenges") r = client.get("/challenges")
assert r.status_code == 403 assert r.status_code == 403
with client.session_transaction() as sess: with client.session_transaction() as sess:
data = {"key": "flag", "nonce": sess.get("nonce")} data = {"key": "flag", "nonce": sess.get("nonce")}
r = client.get("/api/v1/challenges/{}".format(chal_id), data=data) r = client.get("/api/v1/challenges/{}".format(chal_id), data=data)
data = r.get_data(as_text=True) data = r.get_data(as_text=True)
assert r.status_code == 403 assert r.status_code == 403
solve_count = app.db.session.query(app.db.func.count(Solves.id)).first()[0] solve_count = app.db.session.query(app.db.func.count(Solves.id)).first()[0]
assert solve_count == 0 assert solve_count == 0
destroy_ctfd(app) destroy_ctfd(app)
@@ -47,32 +40,27 @@ def test_ctftime_allows_accessing_challenges_during_ctf():
"""Test that the ctftime function allows accessing challenges during the ctf""" """Test that the ctftime function allows accessing challenges during the ctf"""
app = create_ctfd() app = create_ctfd()
with app.app_context(): with app.app_context():
set_config( with ctftime.init():
"start", "1507089600" register_user(app)
) # Wednesday, October 4, 2017 12:00:00 AM GMT-04:00 DST chal = gen_challenge(app.db)
set_config( chal_id = chal.id
"end", "1507262400" gen_flag(app.db, challenge_id=chal.id, content=u"flag")
) # Friday, October 6, 2017 12:00:00 AM GMT-04:00 DST
register_user(app)
chal = gen_challenge(app.db)
chal_id = chal.id
gen_flag(app.db, challenge_id=chal.id, content=u"flag")
with freeze_time("2017-10-5"): with ctftime.started():
client = login_as_user(app) client = login_as_user(app)
r = client.get("/challenges") r = client.get("/challenges")
assert r.status_code == 200 assert r.status_code == 200
with client.session_transaction() as sess: with client.session_transaction() as sess:
data = { data = {
"submission": "flag", "submission": "flag",
"challenge_id": chal_id, "challenge_id": chal_id,
"nonce": sess.get("nonce"), "nonce": sess.get("nonce"),
} }
r = client.post("/api/v1/challenges/attempt", data=data) r = client.post("/api/v1/challenges/attempt", data=data)
assert r.status_code == 200 assert r.status_code == 200
solve_count = app.db.session.query(app.db.func.count(Solves.id)).first()[0] solve_count = app.db.session.query(app.db.func.count(Solves.id)).first()[0]
assert solve_count == 1 assert solve_count == 1
destroy_ctfd(app) destroy_ctfd(app)
@@ -80,32 +68,28 @@ def test_ctftime_prevents_accessing_challenges_after_ctf():
"""Test that the ctftime function prevents accessing challenges after the ctf""" """Test that the ctftime function prevents accessing challenges after the ctf"""
app = create_ctfd() app = create_ctfd()
with app.app_context(): with app.app_context():
set_config( with ctftime.init():
"start", "1507089600"
) # Wednesday, October 4, 2017 12:00:00 AM GMT-04:00 DST
set_config(
"end", "1507262400"
) # Friday, October 6, 2017 12:00:00 AM GMT-04:00 DST
register_user(app)
chal = gen_challenge(app.db)
chal_id = chal.id
gen_flag(app.db, challenge_id=chal.id, content=u"flag")
with freeze_time("2017-10-7"): register_user(app)
client = login_as_user(app) chal = gen_challenge(app.db)
r = client.get("/challenges") chal_id = chal.id
assert r.status_code == 403 gen_flag(app.db, challenge_id=chal.id, content=u"flag")
with client.session_transaction() as sess: with ctftime.ended():
data = { client = login_as_user(app)
"submission": "flag", r = client.get("/challenges")
"challenge_id": chal_id, assert r.status_code == 403
"nonce": sess.get("nonce"),
} with client.session_transaction() as sess:
r = client.post("/api/v1/challenges/attempt", data=data) data = {
assert r.status_code == 403 "submission": "flag",
solve_count = app.db.session.query(app.db.func.count(Solves.id)).first()[0] "challenge_id": chal_id,
assert solve_count == 0 "nonce": sess.get("nonce"),
}
r = client.post("/api/v1/challenges/attempt", data=data)
assert r.status_code == 403
solve_count = app.db.session.query(app.db.func.count(Solves.id)).first()[0]
assert solve_count == 0
destroy_ctfd(app) destroy_ctfd(app)
@@ -118,22 +102,17 @@ def test_ctf_started():
with app.app_context(): with app.app_context():
assert ctf_started() is True assert ctf_started() is True
set_config( with ctftime.init():
"start", "1507089600"
) # Wednesday, October 4, 2017 12:00:00 AM GMT-04:00 DST
set_config(
"end", "1507262400"
) # Friday, October 6, 2017 12:00:00 AM GMT-04:00 DST
with freeze_time("2017-10-3"): with ctftime.not_started():
ctf_started() ctf_started()
assert ctf_started() is False assert ctf_started() is False
with freeze_time("2017-10-5"): with ctftime.started():
assert ctf_started() is True assert ctf_started() is True
with freeze_time("2017-10-7"): with ctftime.ended():
assert ctf_started() is True assert ctf_started() is True
destroy_ctfd(app) destroy_ctfd(app)
@@ -144,20 +123,14 @@ def test_ctf_ended():
app = create_ctfd() app = create_ctfd()
with app.app_context(): with app.app_context():
assert ctf_ended() is False assert ctf_ended() is False
with ctftime.init():
set_config( with ctftime.not_started():
"start", "1507089600" assert ctf_ended() is False
) # Wednesday, October 4, 2017 12:00:00 AM GMT-04:00 DST
set_config(
"end", "1507262400"
) # Friday, October 6, 2017 12:00:00 AM GMT-04:00 DST
with freeze_time("2017-10-3"): with ctftime.started():
assert ctf_ended() is False assert ctf_ended() is False
with freeze_time("2017-10-5"): with ctftime.ended():
assert ctf_ended() is False assert ctf_ended() is True
with freeze_time("2017-10-7"):
assert ctf_ended() is True
destroy_ctfd(app) destroy_ctfd(app)