Skip to content

Commit

Permalink
Ingen deleting handwritten tests (#236)
Browse files Browse the repository at this point in the history
* Fix ingen deleting wrong inputs

* Add tests

* Update example config

* Bump version
  • Loading branch information
MasloMaslane authored Apr 18, 2024
1 parent 7a0a94d commit 9614701
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 7 deletions.
5 changes: 5 additions & 0 deletions example_package/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ sinol_task_id: abc
# A solution passes when all groups pass.
sinol_contest_type: oi

# You can specify which tests are static (handwritten). This allows sinol-make to differentiate between
# old and handwritten tests. If this key is not present old tests won't be removed.
# This key is optional and should be a list of tests.
sinol_static_tests: ["abc0.in", "abc0a.in"]

# sinol-make can check if the solutions run as expected when using `run` command.
# Key `sinol_expected_scores` defines expected scores for each solution on each tests.
# There should be no reason to change this key manually.
Expand Down
2 changes: 1 addition & 1 deletion src/sinol_make/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from sinol_make import util, oiejq

__version__ = "1.5.29"
__version__ = "1.5.30"


def configure_parsers():
Expand Down
29 changes: 24 additions & 5 deletions src/sinol_make/commands/ingen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,29 @@ def configure_subparser(self, subparser):
help='do not validate test contents')
parsers.add_compilation_arguments(parser)

def delete_dangling_files(self, dates):
to_delete = set()
for test in glob.glob(os.path.join(os.getcwd(), "in", f"{self.task_id}*.in")):
basename = os.path.basename(test)
if basename in dates and dates[basename] == os.path.getmtime(test):
to_delete.add(os.path.basename(test))
if to_delete:
config = package_util.get_config()
if 'sinol_static_tests' not in config:
print(util.warning('Old input files won\'t be deleted, '
'because static tests are not defined. '
'You can define them in config.yml with `sinol_static_tests` key.'))
else:
static_files = config['sinol_static_tests']
if isinstance(static_files, str):
static_files = [static_files]
static_files = set([os.path.basename(test) for test in static_files])
to_delete = to_delete - static_files
if to_delete:
print(util.info('Cleaning up old input files.'))
for test in to_delete:
os.remove(os.path.join(os.getcwd(), "in", test))

def run(self, args: argparse.Namespace):
args = util.init_package_command(args)

Expand Down Expand Up @@ -60,11 +83,7 @@ def run(self, args: argparse.Namespace):
else:
util.exit_with_error('Failed to generate input files.')

print(util.info('Cleaning up old input files.'))
for test in glob.glob(os.path.join(os.getcwd(), "in", f"{self.task_id}*.in")):
basename = os.path.basename(test)
if basename in dates and dates[basename] == os.path.getmtime(test):
os.unlink(test)
self.delete_dangling_files(dates)

with open(paths.get_cache_path("input_tests"), "w") as f:
f.write("\n".join(glob.glob(os.path.join(os.getcwd(), "in", f"{self.task_id}*.in"))))
Expand Down
1 change: 1 addition & 0 deletions src/sinol_make/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def save_config(config):
"title_en",
"sinol_task_id",
"sinol_contest_type",
"sinol_static_tests",
"sinol_undocumented_time_tool",
"sinol_undocumented_test_limits",
"memory_limit",
Expand Down
25 changes: 24 additions & 1 deletion tests/commands/gen/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,18 +296,41 @@ def test_bad_tests(create_package, capsys):


@pytest.mark.parametrize("create_package", [util.get_shell_ingen_pack_path()], indirect=True)
def test_dangling_input_files(create_package):
def test_dangling_inputs(create_package, capsys):
"""
Test if dangling input files are removed.
"""
simple_run(["prog/geningen5.cpp"], command="ingen")
for f in ["gen1.in", "gen2.in"]:
assert os.path.exists(os.path.join(create_package, "in", f))
_ = capsys.readouterr().out

simple_run(["prog/geningen6.cpp"], command="ingen")
out = capsys.readouterr().out
assert ("Old input files won't be deleted, because static tests are not defined. "
"You can define them in config.yml with `sinol_static_tests` key.") in out

config = package_util.get_config()
config["sinol_static_tests"] = []
sm_util.save_config(config)
simple_run(["prog/geningen6.cpp"], command="ingen")
out = capsys.readouterr().out
assert "Cleaning up old input files." in out
assert not os.path.exists(os.path.join(create_package, "in", "gen1.in"))
assert os.path.exists(os.path.join(create_package, "in", "gen2.in"))

config = package_util.get_config()
config["sinol_static_tests"] = "gen1.in"
sm_util.save_config(config)
simple_run(["prog/geningen5.cpp"], command="ingen")
for f in ["gen1.in", "gen2.in"]:
assert os.path.exists(os.path.join(create_package, "in", f))
_ = capsys.readouterr().out
simple_run(["prog/geningen6.cpp"], command="ingen")
out = capsys.readouterr().out
for f in ["gen1.in", "gen2.in"]:
assert os.path.exists(os.path.join(create_package, "in", f))


@pytest.mark.parametrize("create_package", [util.get_simple_package_path()], indirect=True)
def test_outgen_cache_cleaning(create_package, capsys):
Expand Down

0 comments on commit 9614701

Please sign in to comment.