Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OIJ contest type #237

Merged
merged 2 commits into from
Apr 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/sinol_make/contest_types/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from sinol_make.contest_types.default import DefaultContest
from sinol_make.contest_types.icpc import ICPCContest
from sinol_make.contest_types.oi import OIContest
from sinol_make.contest_types.oij import OIJContest
from sinol_make.helpers.package_util import get_config
from sinol_make.interfaces.Errors import UnknownContestType

Expand All @@ -15,5 +16,7 @@ def get_contest_type():
return OIContest()
elif contest_type == "icpc":
return ICPCContest()
elif contest_type == "oij":
return OIJContest()
else:
raise UnknownContestType(f'Unknown contest type "{contest_type}"')
32 changes: 32 additions & 0 deletions src/sinol_make/contest_types/oij.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import argparse

from sinol_make import util
from sinol_make.helpers import package_util
from sinol_make.contest_types.default import DefaultContest


class OIJContest(DefaultContest):
"""
Contest type for Polish Junior Olympiad in Informatics.
"""

def get_type(self) -> str:
return "oij"

def argument_overrides(self, args: argparse.Namespace) -> argparse.Namespace:
"""
Add arguments for features required by OIJ contest
"""
args.export_ocen = True
return args

def verify_pre_gen(self):
"""
Verify if scores sum up to 100.
"""
config = package_util.get_config()
if 'scores' not in config:
util.exit_with_error("Scores are not defined in config.yml.")
total_score = sum(config['scores'].values())
if total_score != 100:
util.exit_with_error(f"Total score in config is {total_score}, but should be 100.")
119 changes: 69 additions & 50 deletions tests/commands/export/test_integration.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import yaml
import stat
import glob
import shutil
import pytest
import tarfile
import zipfile
Expand All @@ -9,6 +10,7 @@
from sinol_make import configure_parsers
from sinol_make import util as sinol_util
from sinol_make.commands.doc import Command as DocCommand
from sinol_make.helpers import paths
from tests import util
from tests.fixtures import create_package
from .util import *
Expand Down Expand Up @@ -43,6 +45,17 @@ def _test_archive(package_path, out, tar):
assert glob.glob(os.path.join(extracted, "out", "*")) == []


def _set_contest_type(contest_type):
config = package_util.get_config()
config["sinol_contest_type"] = contest_type
sinol_util.save_config(config)
task_id = package_util.get_task_id()
if os.path.exists(os.path.join(os.getcwd(), f'{task_id}.tgz')):
os.remove(f'{task_id}.tgz')
if os.path.exists(paths.get_cache_path()):
shutil.rmtree(paths.get_cache_path())


@pytest.mark.parametrize("create_package", [util.get_simple_package_path(), util.get_library_package_path(),
util.get_library_string_args_package_path(),
util.get_shell_ingen_pack_path(), util.get_handwritten_package_path()],
Expand Down Expand Up @@ -166,35 +179,37 @@ def test_ocen_archive(create_package):
"""
Test creation of ocen archive.
"""
parser = configure_parsers()
args = parser.parse_args(["export", "--no-statement"])
command = Command()
command.run(args)
task_id = package_util.get_task_id()
in_handwritten = ["ocen0.in", "ocen0a.in", "ocen1a.in", "ocen1ocen.in"]
out_handwritten = ["ocen0.out"]
ocen_tests = ["ocen0", "ocen0a", "ocen0b", "ocen1ocen", "ocen2ocen"]
for contest_type in ["oi", "oij"]:
_set_contest_type(contest_type)
parser = configure_parsers()
args = parser.parse_args(["export", "--no-statement"])
command = Command()
command.run(args)
task_id = package_util.get_task_id()
in_handwritten = ["ocen0.in", "ocen0a.in", "ocen1a.in", "ocen1ocen.in"]
out_handwritten = ["ocen0.out"]
ocen_tests = ["ocen0", "ocen0a", "ocen0b", "ocen1ocen", "ocen2ocen"]

with tempfile.TemporaryDirectory() as tmpdir:
package_path = os.path.join(tmpdir, task_id)
os.mkdir(package_path)
with tarfile.open(f'{task_id}.tgz', "r") as tar:
sinol_util.extract_tar(tar, tmpdir)
with tempfile.TemporaryDirectory() as tmpdir:
package_path = os.path.join(tmpdir, task_id)
os.mkdir(package_path)
with tarfile.open(f'{task_id}.tgz', "r") as tar:
sinol_util.extract_tar(tar, tmpdir)

for ext in ["in", "out"]:
tests = [os.path.basename(f) for f in glob.glob(os.path.join(package_path, ext, f'*.{ext}'))]
assert set(tests) == set(in_handwritten if ext == "in" else out_handwritten)
for ext in ["in", "out"]:
tests = [os.path.basename(f) for f in glob.glob(os.path.join(package_path, ext, f'*.{ext}'))]
assert set(tests) == set(in_handwritten if ext == "in" else out_handwritten)

ocen_archive = os.path.join(package_path, "attachments", f"{task_id}ocen.zip")
assert os.path.exists(ocen_archive)
ocen_dir = os.path.join(package_path, "ocen_dir")
ocen_archive = os.path.join(package_path, "attachments", f"{task_id}ocen.zip")
assert os.path.exists(ocen_archive)
ocen_dir = os.path.join(package_path, "ocen_dir")

with zipfile.ZipFile(ocen_archive, "r") as zip:
zip.extractall(ocen_dir)
with zipfile.ZipFile(ocen_archive, "r") as zip:
zip.extractall(ocen_dir)

for ext in ["in", "out"]:
tests = [os.path.basename(f) for f in glob.glob(os.path.join(ocen_dir, task_id, ext, f'*.{ext}'))]
assert set(tests) == set([f'{test}.{ext}' for test in ocen_tests])
for ext in ["in", "out"]:
tests = [os.path.basename(f) for f in glob.glob(os.path.join(ocen_dir, task_id, ext, f'*.{ext}'))]
assert set(tests) == set([f'{test}.{ext}' for test in ocen_tests])


@pytest.mark.parametrize("create_package", [util.get_icpc_package_path()], indirect=True)
Expand All @@ -220,42 +235,46 @@ def test_no_ocen_and_dlazaw(create_package):
Test if ocen archive is not created when there are no ocen tests.
Also test if dlazaw archive is created.
"""
parser = configure_parsers()
args = parser.parse_args(["export", "--no-statement"])
command = Command()
command.run(args)
task_id = package_util.get_task_id()
for contest_type in ["oi", "oij"]:
_set_contest_type(contest_type)
parser = configure_parsers()
args = parser.parse_args(["export", "--no-statement"])
command = Command()
command.run(args)
task_id = package_util.get_task_id()

with tempfile.TemporaryDirectory() as tmpdir:
with tarfile.open(f'{task_id}.tgz', "r") as tar:
sinol_util.extract_tar(tar, tmpdir)
with tempfile.TemporaryDirectory() as tmpdir:
with tarfile.open(f'{task_id}.tgz', "r") as tar:
sinol_util.extract_tar(tar, tmpdir)

assert not os.path.exists(os.path.join(tmpdir, task_id, "attachments", f"{task_id}ocen.zip"))
dlazaw_archive = os.path.join(tmpdir, task_id, "attachments", f"dlazaw.zip")
assert os.path.exists(dlazaw_archive)
assert not os.path.exists(os.path.join(tmpdir, task_id, "attachments", f"{task_id}ocen.zip"))
dlazaw_archive = os.path.join(tmpdir, task_id, "attachments", f"dlazaw.zip")
assert os.path.exists(dlazaw_archive)

with zipfile.ZipFile(dlazaw_archive, "r") as zip:
zip.extractall(os.path.join(tmpdir))
with zipfile.ZipFile(dlazaw_archive, "r") as zip:
zip.extractall(os.path.join(tmpdir))

assert os.path.exists(os.path.join(tmpdir, "dlazaw"))
assert os.path.exists(os.path.join(tmpdir, "dlazaw", "epic_file"))
assert os.path.exists(os.path.join(tmpdir, "dlazaw"))
assert os.path.exists(os.path.join(tmpdir, "dlazaw", "epic_file"))


@pytest.mark.parametrize("create_package", [util.get_ocen_package_path()], indirect=True)
def test_dlazaw_ocen(create_package):
"""
Test if ocen archive isn't created when dlazaw directory exists
"""
os.makedirs("dlazaw")
parser = configure_parsers()
args = parser.parse_args(["export", "--no-statement"])
command = Command()
command.run(args)
task_id = package_util.get_task_id()
for contest_type in ["oi", "oij"]:
_set_contest_type(contest_type)
os.makedirs("dlazaw", exist_ok=True)
parser = configure_parsers()
args = parser.parse_args(["export", "--no-statement"])
command = Command()
command.run(args)
task_id = package_util.get_task_id()

with tempfile.TemporaryDirectory() as tmpdir:
with tarfile.open(f'{task_id}.tgz', "r") as tar:
sinol_util.extract_tar(tar, tmpdir)
with tempfile.TemporaryDirectory() as tmpdir:
with tarfile.open(f'{task_id}.tgz', "r") as tar:
sinol_util.extract_tar(tar, tmpdir)

assert not os.path.exists(os.path.join(tmpdir, task_id, "attachments", f"{task_id}ocen.zip"))
assert os.path.join(tmpdir, task_id, "attachments", f"dlazaw.zip")
assert not os.path.exists(os.path.join(tmpdir, task_id, "attachments", f"{task_id}ocen.zip"))
assert os.path.join(tmpdir, task_id, "attachments", f"dlazaw.zip")
38 changes: 23 additions & 15 deletions tests/commands/verify/test_integration.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import os
import shutil
import pytest

from sinol_make import configure_parsers
from sinol_make import util as sm_util
from sinol_make.commands.verify import Command
from sinol_make.helpers import package_util
from sinol_make.helpers import package_util, paths
from tests import util
from tests.fixtures import create_package

Expand Down Expand Up @@ -103,24 +104,29 @@ def test_invalid_scores(capsys, create_package):
@pytest.mark.parametrize("create_package", [util.get_simple_package_path()], indirect=True)
def test_scores_not_100(capsys, create_package):
"""
Test if scores not adding up to 100 will cause the verify command to fail.
Test if scores not adding up to 100 will cause the verify command to fail if contest type is OI or OIJ.
"""
config = package_util.get_config()
config["sinol_contest_type"] = "oi"
config["scores"][1] -= 1
sm_util.save_config(config)
with pytest.raises(SystemExit) as e:
run()
assert e.value.code == 1
out = capsys.readouterr().out
assert "Total score in config is 99, but should be 100." in out
for contest_type in ["oi", "oij"]:
if os.path.exists(paths.get_cache_path()):
shutil.rmtree(paths.get_cache_path())
config = package_util.get_config()
config["sinol_contest_type"] = contest_type
sm_util.save_config(config)
with pytest.raises(SystemExit) as e:
run()
assert e.value.code == 1
out = capsys.readouterr().out
assert "Total score in config is 99, but should be 100." in out


@pytest.mark.parametrize("create_package", [util.get_dlazaw_package()], indirect=True)
def test_expected_contest_and_no_scores(capsys, create_package):
"""
Test if --expected-contest-type flag works,
and if contest type is OI and there are no scores in config.yml, the verify command will fail.
and if contest type is OI or OIJ and there are no scores in config.yml, the verify command will fail.
"""
config = package_util.get_config()
with pytest.raises(SystemExit) as e:
Expand All @@ -130,9 +136,11 @@ def test_expected_contest_and_no_scores(capsys, create_package):
assert "Invalid contest type 'oi'. Expected 'icpc'." in out

del config["scores"]
sm_util.save_config(config)
with pytest.raises(SystemExit) as e:
run(["--expected-contest-type", "oi"])
assert e.value.code == 1
out = capsys.readouterr().out
assert "Scores are not defined in config.yml." in out
for contest_type in ["oi", "oij"]:
config["sinol_contest_type"] = contest_type
sm_util.save_config(config)
with pytest.raises(SystemExit) as e:
run(["--expected-contest-type", contest_type])
assert e.value.code == 1
out = capsys.readouterr().out
assert "Scores are not defined in config.yml." in out
Loading