diff --git a/.gitignore b/.gitignore index 6a5b3ae..b832e0e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ dist/ downloads/ eggs/ .eggs/ -lib/ +# lib/ lib64/ parts/ sdist/ diff --git a/joj3_config_generator/convert.py b/joj3_config_generator/convert.py index 9badd5f..f25647b 100644 --- a/joj3_config_generator/convert.py +++ b/joj3_config_generator/convert.py @@ -1,14 +1,23 @@ from typing import List +from joj3_config_generator.lib.repo import getHealthcheckConfig +from joj3_config_generator.lib.task import ( + fix_diff, + fix_dummy, + fix_keyword, + fix_result_detail, + get_conf_stage, + get_executorWithConfig, +) from joj3_config_generator.models import joj1, repo, result, task -# FIXME: LLM generated convert function, only for demostration def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config: # Create the base ResultConf object result_conf = result.Config( name=task_conf.task, - log_path=f"{task_conf.task.replace(' ', '_')}.log", + # TODO: specify the exact folder difference + log_path=f"{task_conf.task.replace(' ', '-')}.log", expire_unix_timestamp=( int(task_conf.release.deadline.timestamp()) if task_conf.release.deadline @@ -18,36 +27,18 @@ def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config: teapot=result.Teapot(), ) + # Construct healthcheck stage + healthcheck_stage = getHealthcheckConfig(repo_conf, task_conf) + result_conf.stage.stages.append(healthcheck_stage) + cached: list[str] = [] # Convert each stage in the task configuration for task_stage in task_conf.stages: - executor_with_config = result.ExecutorWith( - default=result.Cmd( - args=task_stage.command.split(), - copy_in={ - file: result.CmdFile(src=file) for file in task_stage.files.import_ - }, - copy_out_cached=task_stage.files.export, - ), - cases=[], # You can add cases if needed - ) - conf_stage = result.StageDetail( - name=task_stage.name, - group=task_conf.task, - executor=result.Executor( - name="sandbox", - with_=executor_with_config, - ), - parsers=[ - result.Parser(name=parser, with_={}) for parser in task_stage.parsers - ], - ) - - if "result-detail" in task_stage.parsers: - result_detail_parser = next( - p for p in conf_stage.parsers if p.name == "result-detail" - ) - result_detail_parser.with_.update(task_stage.result_detail) - + executor_with_config, cached = get_executorWithConfig(task_stage, cached) + conf_stage = get_conf_stage(task_stage, executor_with_config) + conf_stage = fix_result_detail(task_stage, conf_stage) + conf_stage = fix_dummy(task_stage, conf_stage) + conf_stage = fix_keyword(task_stage, conf_stage) + conf_stage = fix_diff(task_stage, conf_stage) result_conf.stage.stages.append(conf_stage) return result_conf @@ -77,7 +68,6 @@ def convert_joj1(joj1_conf: joj1.Config) -> task.Config: files=files, score=score, parsers=parsers, - result_detail=task.ParserResultDetail(), # You can customize this further if needed ) ) # Assuming no deadline is provided in `joj1`, you can set it accordingly diff --git a/joj3_config_generator/lib/__init__.py b/joj3_config_generator/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/joj3_config_generator/lib/repo.py b/joj3_config_generator/lib/repo.py new file mode 100644 index 0000000..3f1935a --- /dev/null +++ b/joj3_config_generator/lib/repo.py @@ -0,0 +1,99 @@ +import hashlib +import socket + +from joj3_config_generator.models import joj1, repo, result, task + + +def getGradingRepoName() -> str: + host_name = socket.gethostname() + return f"{host_name.split('-')[0]}-joj" + + +def getTeapotConfig(repo_conf: repo.Config, task_conf: task.Config) -> result.Teapot: + teapot = result.Teapot( + # TODO: fix the log path + log_path=f"{task_conf.task.replace(' ', '-')}-joint-teapot-debug.log", + scoreboard_path=f"{task_conf.task.replace(' ', '-')}-scoreboard.csv", + failed_table_path=f"{task_conf.task.replace(' ', '-')}-failed-table.md", + grading_repo_name=getGradingRepoName(), + ) + return teapot + + +def getHealthcheckCmd(repo_conf: repo.Config) -> result.Cmd: + repoSize = repo_conf.max_size + immutable = repo_conf.files.immutable + repo_size = f"-repoSize={str(repoSize)} " + required_files = repo_conf.files.required + + for i, meta in enumerate(required_files): + required_files[i] = f"-meta={meta} " + + immutable_files = f"-checkFileNameList=" + for i, name in enumerate(immutable): + if i == len(immutable) - 1: + immutable_files = immutable_files + name + " " + else: + immutable_files = immutable_files + name + "," + # FIXME: need to make solution and make things easier to edit with global scope + chore = f"/tmp/repo-health-checker -root=. " + args = "" + args = args + chore + args = args + repo_size + for meta in required_files: + args = args + meta + + args = args + get_hash(immutable) + + args = args + immutable_files + + cmd = result.Cmd( + args=args.split(), + # FIXME: easier to edit within global scope + copy_in={ + f"/tmp/repo-health-checker": result.CmdFile(src=f"/tmp/repo-health-checker") + }, + ) + return cmd + + +def getHealthcheckConfig( + repo_conf: repo.Config, task_conf: task.Config +) -> result.StageDetail: + healthcheck_stage = result.StageDetail( + name="healthcheck", + group="", + executor=result.Executor( + name="sandbox", + with_=result.ExecutorWith(default=getHealthcheckCmd(repo_conf), cases=[]), + ), + parsers=[result.Parser(name="healthcheck", with_={"score": 0, "comment": ""})], + ) + return healthcheck_stage + + +def calc_sha256sum(file_path: str) -> str: + sha256_hash = hashlib.sha256() + with open(file_path, "rb") as f: + for byte_block in iter(lambda: f.read(65536 * 2), b""): + sha256_hash.update(byte_block) + return sha256_hash.hexdigest() + + +def get_hash(immutable_files: list[str]) -> str: # input should be a list + file_path = "../immutable_file/" # TODO: change this when things are on the server + immutable_hash = [] + for i, file in enumerate(immutable_files): + immutable_files[i] = file_path + file.rsplit("/", 1)[-1] + + for i, file in enumerate(immutable_files): + immutable_hash.append(calc_sha256sum(file)) + + hash_check = "-checkFileSumList=" + + for i, file in enumerate(immutable_hash): + if i == len(immutable_hash) - 1: + hash_check = hash_check + file + " " + else: + hash_check = hash_check + file + "," + return hash_check diff --git a/joj3_config_generator/lib/task.py b/joj3_config_generator/lib/task.py new file mode 100644 index 0000000..4dd2b7a --- /dev/null +++ b/joj3_config_generator/lib/task.py @@ -0,0 +1,268 @@ +from typing import Tuple + +import rtoml + +from joj3_config_generator.models import joj1, repo, result, task + + +def get_conf_stage( + task_stage: task.Stage, executor_with_config: result.ExecutorWith +) -> result.StageDetail: + conf_stage = result.StageDetail( + name=task_stage.name if task_stage.name is not None else "", + # TODO: we may have cq in future + group=( + "joj" + if (task_stage.name is not None) and ("judge" in task_stage.name) + else None + ), + executor=result.Executor( + name="sandbox", + with_=executor_with_config, + ), + parsers=( + [result.Parser(name=parser, with_={}) for parser in task_stage.parsers] + if task_stage.parsers is not None + else [] + ), + ) + return conf_stage + + +def get_executorWithConfig( + task_stage: task.Stage, cached: list[str] +) -> Tuple[result.ExecutorWith, list[str]]: + file_import = ( + task_stage.files.import_ + if hasattr(task_stage, "files") + and hasattr(task_stage.files, "import_") + and (task_stage.files is not None) + and (task_stage.files.import_ is not None) + else [] + ) + copy_in_files = [file for file in file_import if (file not in cached)] + file_export = ( + task_stage.files.export + if hasattr(task_stage, "files") + and hasattr(task_stage.files, "export") + and (task_stage.files is not None) + else [] + ) + executor_with_config = result.ExecutorWith( + default=result.Cmd( + args=(task_stage.command.split() if task_stage.command is not None else []), + copy_in={ + file: result.CmdFile(src=f"/home/tt/.config/joj/{file}") + for file in copy_in_files + }, + copy_in_cached={file: file for file in copy_in_files}, + copy_out_cached=file_export if file_export is not None else [], + cpu_limit=( + task_stage.limit.cpu * 1_000_000_000 + if task_stage.limit is not None and task_stage.limit.cpu is not None + else 4 * 1_000_000_000 + ), + clock_limit=( + 2 * task_stage.limit.cpu * 1_000_000_000 + if task_stage.limit is not None and task_stage.limit.cpu is not None + else 8 * 1_000_000_000 + ), + memory_limit=( + task_stage.limit.mem * 1_024 * 1_024 + if task_stage.limit is not None and task_stage.limit.mem is not None + else 4 * 1_024 * 1_024 + ), + stderr=result.CmdFile( + name="stderr", + max=( + task_stage.limit.stderr * 1_000_000_000 + if task_stage.limit is not None + and task_stage.limit.stderr is not None + else 4 * 1_024 * 1_024 + ), + ), + stdout=result.CmdFile( + name="stdout", + max=( + task_stage.limit.stdout * 1_000_000_000 + if task_stage.limit is not None + and task_stage.limit.stdout is not None + else 4 * 1_024 * 1_024 + ), + ), + ), + cases=[], # You can add cases if needed + ) + if file_export is not None: + for file in file_export: + if file not in cached: + cached.append(file) + return (executor_with_config, cached) + + +def fix_keyword( + task_stage: task.Stage, conf_stage: result.StageDetail +) -> result.StageDetail: + keyword_parser = ["clangtidy", "keyword", "cppcheck", "cpplint"] + if task_stage.parsers is not None: + for parser in task_stage.parsers: + if parser in keyword_parser: + keyword_parser_ = next( + p for p in conf_stage.parsers if p.name == parser + ) + keyword_weight = [] + if getattr(task_stage, parser, None) is not None: + unique_weight = list(set(getattr(task_stage, parser).weight)) + for score in unique_weight: + keyword_weight.append({"keywords": [], "score": score}) + + for idx, score in enumerate(unique_weight): + for idx_, score_ in enumerate( + getattr(task_stage, parser).weight + ): + if score == score_: + keyword_weight[idx]["keywords"].append( + getattr(task_stage, parser).keyword[idx_] + ) + else: + continue + + keyword_parser_.with_.update({"matches": keyword_weight}) + else: + continue + return conf_stage + + +def fix_result_detail( + task_stage: task.Stage, conf_stage: result.StageDetail +) -> result.StageDetail: + if (task_stage.parsers is not None) and ("result-detail" in task_stage.parsers): + result_detail_parser = next( + p for p in conf_stage.parsers if p.name == "result-detail" + ) + if task_stage.result_detail is not None: + show_files = [] + if ( + task_stage.result_detail.stdout + and task_stage.result_detail.stdout is not None + ): + show_files.append("stdout") + if ( + task_stage.result_detail.stderr + and task_stage.result_detail.stderr is not None + ): + show_files.append("stderr") + result_detail_parser.with_.update( + { + "score": 0, + "comment": "", + "showFiles": show_files, + "showExitStatus": task_stage.result_detail.exitstatus, + "showRuntime": task_stage.result_detail.time, + "showMemory": task_stage.result_detail.mem, + } + ) + + return conf_stage + + +def fix_dummy( + task_stage: task.Stage, conf_stage: result.StageDetail +) -> result.StageDetail: + dummy_parser = [ + "dummy", + "result-status", + "cpplint", + ] + if task_stage.parsers is not None: + for parser in task_stage.parsers: + if parser in dummy_parser: + dummy_parser_ = next(p for p in conf_stage.parsers if p.name == parser) + if ( + getattr(task_stage, parser.replace("-", "_"), None) is not None + ) and (task_stage.result_status is not None): + dummy_parser_.with_.update( + { + "score": task_stage.result_status.score, + "comment": task_stage.result_status.comment, + "forceQuitOnNotAccepted": task_stage.result_status.forcequit, + } + ) + else: + continue + return conf_stage + + +def fix_diff( + task_stage: task.Stage, conf_stage: result.StageDetail +) -> result.StageDetail: + if task_stage.parsers is not None and "diff" in task_stage.parsers: + diff_parser = next((p for p in conf_stage.parsers if p.name == "diff"), None) + skip = task_stage.skip or [] + cases = task_stage.cases or {} + finalized_cases = [case for case in cases if case not in skip] + + stage_cases = [] + parser_cases = [] + + for case in finalized_cases: + case_stage = task_stage.cases.get(case) if task_stage.cases else None + if not case_stage: + continue + + # Ensure case_stage.limit is defined before accessing .cpu and .mem + cpu_limit = ( + case_stage.limit.cpu * 1_000_000_000 + if case_stage.limit and case_stage.limit.cpu is not None + else 0 + ) + clock_limit = ( + 2 * case_stage.limit.cpu * 1_000_000_000 + if case_stage.limit and case_stage.limit.cpu is not None + else 0 + ) + memory_limit = ( + case_stage.limit.mem * 1_024 * 1_024 + if case_stage.limit and case_stage.limit.mem is not None + else 0 + ) + + stage_cases.append( + result.OptionalCmd( + stdin=result.CmdFile( + src=f"/home/tt/.config/joj/{conf_stage.name}/{case}.in" + ), + cpu_limit=cpu_limit, + clock_limit=clock_limit, + memory_limit=memory_limit, + proc_limit=50, + ) + ) + + # Ensure case_stage.diff and case_stage.diff.output are defined + diff_output = ( + case_stage.diff.output + if case_stage.diff and case_stage.diff.output + else None + ) + if diff_output: + parser_cases.append( + { + "outputs": [ + { + "score": diff_output.score, + "fileName": "stdout", + "answerPath": f"/home/tt/.config/joj/{conf_stage.name}/{case}.out", + "forceQuitOnDiff": diff_output.forcequit, + "alwaysHide": diff_output.hide, + "compareSpace": not diff_output.ignorespaces, + } + ] + } + ) + + if diff_parser and task_stage.diff is not None: + diff_parser.with_.update({"name": "diff", "cases": parser_cases}) + conf_stage.executor.with_.cases = stage_cases + + return conf_stage diff --git a/joj3_config_generator/main.py b/joj3_config_generator/main.py index d556071..0e3f79c 100644 --- a/joj3_config_generator/main.py +++ b/joj3_config_generator/main.py @@ -9,7 +9,7 @@ import yaml from joj3_config_generator.convert import convert as convert_conf from joj3_config_generator.convert import convert_joj1 as convert_joj1_conf -from joj3_config_generator.models import joj1, repo, task +from joj3_config_generator.models import joj1, repo, result, task from joj3_config_generator.utils.logger import logger app = typer.Typer(add_completion=False) @@ -46,15 +46,15 @@ def convert_joj1(yaml_file: typer.FileText, toml_file: typer.FileTextWrite) -> N @app.command() -def convert(root: Path = Path(".")) -> None: +def convert(root: Path = Path(".")) -> result.Config: """ Convert given dir of JOJ3 toml config files to JOJ3 json config files """ logger.info(f"Converting files in {root.absolute()}") - repo_toml_path = os.path.join(root, "repo.toml") + repo_toml_path = os.path.join(root.absolute(), "basic", "repo.toml") # TODO: loop through all dirs to find all task.toml - task_toml_path = os.path.join(root, "task.toml") - result_json_path = os.path.join(root, "task.json") + task_toml_path = os.path.join(root.absolute(), "basic", "task.toml") + result_json_path = os.path.join(root.absolute(), "basic", "task.json") with open(repo_toml_path) as repo_file: repo_toml = repo_file.read() with open(task_toml_path) as task_file: @@ -63,6 +63,9 @@ def convert(root: Path = Path(".")) -> None: task_obj = rtoml.loads(task_toml) result_model = convert_conf(repo.Config(**repo_obj), task.Config(**task_obj)) result_dict = result_model.model_dump(by_alias=True) + with open(result_json_path, "w") as result_file: json.dump(result_dict, result_file, ensure_ascii=False, indent=4) result_file.write("\n") + + return result_model diff --git a/joj3_config_generator/models/result.py b/joj3_config_generator/models/result.py index ab11d99..7b29333 100644 --- a/joj3_config_generator/models/result.py +++ b/joj3_config_generator/models/result.py @@ -9,7 +9,7 @@ class CmdFile(BaseModel): content: Optional[str] = None file_id: Optional[str] = Field(None, serialization_alias="fileId") name: Optional[str] = None - max: Optional[int] = None + max: Optional[int] = 4 * 1024 * 1024 symlink: Optional[str] = None stream_in: bool = Field(False, serialization_alias="streamIn") stream_out: bool = Field(False, serialization_alias="streamOut") @@ -17,17 +17,17 @@ class CmdFile(BaseModel): class Cmd(BaseModel): - args: List[str] - env: List[str] = [] - stdin: Optional[CmdFile] = None - stdout: Optional[CmdFile] = None - stderr: Optional[CmdFile] = None - cpu_limit: int = Field(0, serialization_alias="cpuLimit") + args: list[str] + env: list[str] = ["PATH=/usr/bin:/bin:/usr/local/bin"] + stdin: Optional[CmdFile] = CmdFile(content="") + stdout: Optional[CmdFile] = CmdFile(name="stdout", max=4 * 1024) + stderr: Optional[CmdFile] = CmdFile(name="stderr", max=4 * 1024) + cpu_limit: int = Field(4 * 1000000000, serialization_alias="cpuLimit") real_cpu_limit: int = Field(0, serialization_alias="realCpuLimit") - clock_limit: int = Field(0, serialization_alias="clockLimit") - memory_limit: int = Field(0, serialization_alias="memoryLimit") + clock_limit: int = Field(8 * 1000000000, serialization_alias="clockLimit") + memory_limit: int = Field(4 * 1024 * 1024, serialization_alias="memoryLimit") stack_limit: int = Field(0, serialization_alias="stackLimit") - proc_limit: int = Field(0, serialization_alias="procLimit") + proc_limit: int = Field(50, serialization_alias="procLimit") cpu_rate_limit: int = Field(0, serialization_alias="cpuRateLimit") cpu_set_limit: str = Field("", serialization_alias="cpuSetLimit") copy_in: Dict[str, CmdFile] = Field({}, serialization_alias="copyIn") @@ -44,17 +44,19 @@ class Cmd(BaseModel): class OptionalCmd(BaseModel): - args: Optional[List[str]] = None - env: Optional[List[str]] = None + args: Optional[list[str]] = None + env: Optional[list[str]] = ["PATH=/usr/bin:/bin:/usr/local/bin"] stdin: Optional[CmdFile] = None stdout: Optional[CmdFile] = None stderr: Optional[CmdFile] = None - cpu_limit: Optional[int] = Field(None, serialization_alias="cpuLimit") + cpu_limit: Optional[int] = Field(4 * 1000000000, serialization_alias="cpuLimit") real_cpu_limit: Optional[int] = Field(None, serialization_alias="realCpuLimit") - clock_limit: Optional[int] = Field(None, serialization_alias="clockLimit") - memory_limit: Optional[int] = Field(None, serialization_alias="memoryLimit") + clock_limit: Optional[int] = Field(8 * 1000000000, serialization_alias="clockLimit") + memory_limit: Optional[int] = Field( + 4 * 1024 * 1024, serialization_alias="memoryLimit" + ) stack_limit: Optional[int] = Field(None, serialization_alias="stackLimit") - proc_limit: Optional[int] = Field(None, serialization_alias="procLimit") + proc_limit: Optional[int] = Field(50, serialization_alias="procLimit") cpu_rate_limit: Optional[int] = Field(None, serialization_alias="cpuRateLimit") cpu_set_limit: Optional[str] = Field(None, serialization_alias="cpuSetLimit") copy_in: Optional[Dict[str, CmdFile]] = Field(None, serialization_alias="copyIn") @@ -97,7 +99,7 @@ class Parser(BaseModel): class StageDetail(BaseModel): name: str - group: str + group: Optional[str] = "" executor: Executor parsers: List[Parser] diff --git a/joj3_config_generator/models/task.py b/joj3_config_generator/models/task.py index 09a37fc..684cdd5 100644 --- a/joj3_config_generator/models/task.py +++ b/joj3_config_generator/models/task.py @@ -1,30 +1,84 @@ from datetime import datetime -from typing import List, Optional +from typing import Any, Dict, List, Optional, Type -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, root_validator class ParserResultDetail(BaseModel): - time: bool = True # Display run time - mem: bool = True # Display memory usage - stdout: bool = False # Display stdout messages - stderr: bool = False # Display stderr messages + time: Optional[bool] = True # Display run time + mem: Optional[bool] = True # Display memory usage + stdout: Optional[bool] = False # Display stdout messages + stderr: Optional[bool] = False # Display stderr messages + exitstatus: Optional[bool] = False + + +class ParserDummy(BaseModel): + comment: Optional[str] = "" + score: Optional[int] = 0 + forcequit: Optional[bool] = True + + +class ParserKeyword(BaseModel): + keyword: Optional[list[str]] = [] + weight: Optional[list[int]] = [] + + +class Outputs(BaseModel): + score: Optional[int] = 0 + ignorespaces: Optional[bool] = False + hide: Optional[bool] = False + forcequit: Optional[bool] = True + + +class ParserDiff(BaseModel): + output: Optional[Outputs] = Outputs() class Files(BaseModel): - import_: List[str] = Field(serialization_alias="import", validation_alias="import") - export: List[str] + import_: Optional[List[str]] = Field( + [], serialization_alias="import", validation_alias="import" + ) + export: Optional[List[str]] = [] + + +class Limit(BaseModel): + mem: Optional[int] = 4 + cpu: Optional[int] = 4 + stderr: Optional[int] = 4 + stdout: Optional[int] = 4 class Stage(BaseModel): - name: str # Stage name - command: str # Command to run - files: Files # Files to import and export - score: int # Score for the task - parsers: List[str] # list of parsers - result_detail: ParserResultDetail = ( - ParserResultDetail() - ) # for result-detail parser + name: Optional[str] = None # Stage name + command: Optional[str] = None # Command to run + files: Optional[Files] = None + score: Optional[int] = 0 + parsers: Optional[list[str]] = [] # list of parsers + limit: Optional[Limit] = Limit() + dummy: Optional[ParserDummy] = ParserDummy() + result_status: Optional[ParserDummy] = Field(ParserDummy(), alias="result-status") + keyword: Optional[ParserKeyword] = ParserKeyword() + clangtidy: Optional[ParserKeyword] = ParserKeyword() + cppcheck: Optional[ParserKeyword] = ParserKeyword() + # FIXME: determine cpplint type + cpplint: Optional[ParserKeyword] = ParserKeyword() + result_detail: Optional[ParserResultDetail] = Field( + ParserResultDetail(), alias="result-detail" + ) + skip: Optional[list[str]] = [] + diff: Optional[ParserDiff] = ParserDiff() + cases: Optional[Dict[str, "Stage"]] = {} + + class Config: + extra = "allow" + + @root_validator(pre=True) + def gather_cases(cls: Type["Stage"], values: Dict[str, Any]) -> Dict[str, Any]: + cases = {k: v for k, v in values.items() if k.startswith("case")} + for key in cases: + values.pop(key) + values["cases"] = {k: Stage(**v) for k, v in cases.items()} + return values class Release(BaseModel): diff --git a/tests/basic/task.json b/tests/basic/task.json new file mode 100644 index 0000000..c15b691 --- /dev/null +++ b/tests/basic/task.json @@ -0,0 +1,1327 @@ +{ + "name": "h4 ex1", + "logPath": "h4-ex1.log", + "expireUnixTimestamp": 1728748740, + "stage": { + "sandboxExecServer": "172.17.0.1:5051", + "sandboxToken": "test", + "outputPath": "/tmp/joj3_result.json", + "stages": [ + { + "name": "healthcheck", + "group": "", + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "//repo-health-checker", + "-root=.", + "-repoSize=50.5", + "-meta=main.py", + "-meta=README.md", + "-checkFileSumList=-checkFileNameList=" + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 4096, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 4096, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 4000000000, + "realCpuLimit": 0, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": { + "//tmp/repo-checker-lf3ranpy/repo-health-checker": { + "src": "//tmp/repo-checker-gd58j2qv/repo-health-checker", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + } + }, + "copyInCached": {}, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [] + } + }, + "parsers": [ + { + "name": "healthcheck", + "with": { + "score": 0, + "comment": "" + } + } + ] + }, + { + "name": "Compilation", + "group": null, + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "make.sh" + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 128000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 180000000000, + "realCpuLimit": 0, + "clockLimit": 360000000000, + "memoryLimit": 4194304, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": { + "tools/make.sh": { + "src": "/home/tt/.config/joj/tools/make.sh", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "src/main.c": { + "src": "/home/tt/.config/joj/src/main.c", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "src/task.h": { + "src": "/home/tt/.config/joj/src/task.h", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "srcCMakelist.txt": { + "src": "/home/tt/.config/joj/srcCMakelist.txt", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + } + }, + "copyInCached": { + "tools/make.sh": "tools/make.sh", + "src/main.c": "src/main.c", + "src/task.h": "src/task.h", + "srcCMakelist.txt": "srcCMakelist.txt" + }, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [ + "driver", + "p2", + "p2-msan" + ], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [] + } + }, + "parsers": [ + { + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stderr" + ], + "showExitStatus": true, + "showRuntime": false, + "showMemory": false + } + }, + { + "name": "dummy", + "with": { + "comment": "\n\n### Details\n" + } + }, + { + "name": "result-status", + "with": { + "comment": "Congratulations! Your code compiled successfully." + } + } + ] + }, + { + "name": "File length check", + "group": null, + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "./file-length", + "500", + "400", + "*.c", + "*.h" + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 4000000000, + "realCpuLimit": 0, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": { + "tools/file-length": { + "src": "/home/tt/.config/joj/tools/file-length", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + } + }, + "copyInCached": { + "tools/file-length": "tools/file-length" + }, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [] + } + }, + "parsers": [ + { + "name": "keyword", + "with": { + "match": [ + { + "keyword": [ + "max" + ], + "score": 50 + }, + { + "keyword": [ + "recommend" + ], + "score": 20 + } + ] + } + }, + { + "name": "dummy", + "with": { + "comment": "" + } + }, + { + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stderr" + ], + "showExitStatus": false, + "showRuntime": false, + "showMemory": false + } + } + ] + }, + { + "name": "Clang-tidy checks", + "group": null, + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "run-clang-tidy-18", + "-header-filter=.*", + "-quiet", + "-load=/usr/local/lib/libcodequality.so", + "-p", + "build" + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 65000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 4000000000, + "realCpuLimit": 0, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": {}, + "copyInCached": {}, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [] + } + }, + "parsers": [ + { + "name": "clangtidy", + "with": { + "match": [ + { + "keyword": [ + "codequality-no-global-variables" + ], + "score": 10 + }, + { + "keyword": [ + "codequality-no-header-guard" + ], + "score": 10 + }, + { + "keyword": [ + "readability-function-size" + ], + "score": 50 + }, + { + "keyword": [ + "readability-duplicate-include" + ], + "score": 10 + }, + { + "keyword": [ + "readability-identifier-naming" + ], + "score": 5 + }, + { + "keyword": [ + "readability-redundant" + ], + "score": 5 + }, + { + "keyword": [ + "readability-misleading-indentation" + ], + "score": 10 + }, + { + "keyword": [ + "readability-misplaced-array-index" + ], + "score": 5 + }, + { + "keyword": [ + "cppcoreguidelines-init-variables" + ], + "score": 5 + }, + { + "keyword": [ + "bugprone-suspicious-string-compare" + ], + "score": 8 + }, + { + "keyword": [ + "google-global-names-in-headers" + ], + "score": 5 + }, + { + "keyword": [ + "clang-diagnostic" + ], + "score": 5 + }, + { + "keyword": [ + "clang-analyzer" + ], + "score": 5 + }, + { + "keyword": [ + "misc performance" + ], + "score": 5 + } + ] + } + }, + { + "name": "dummy", + "with": { + "comment": "\n\n### Details\n" + } + }, + { + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stdout" + ], + "showExitStatus": true, + "showRuntime": false, + "showMemory": false + } + } + ] + }, + { + "name": "Cppcheck check", + "group": null, + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "cppcheck", + "--template='{\"file\":\"{file}\",\"line\":{line},", + "\"column\":{column},", + "\"severity\":\"{severity}\",", + "\"message\":\"{message}\",", + "\"id\":\"{id}\"}'", + "--force", + "--enable=all", + "--quiet", + "./" + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 65000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 4000000000, + "realCpuLimit": 0, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": {}, + "copyInCached": {}, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [] + } + }, + "parsers": [ + { + "name": "cppcheck", + "with": { + "match": [ + { + "keyword": [ + "error" + ], + "score": 20 + }, + { + "keyword": [ + "warning" + ], + "score": 10 + }, + { + "keyword": [ + "portability" + ], + "score": 15 + }, + { + "keyword": [ + "performance" + ], + "score": 15 + }, + { + "keyword": [ + "style" + ], + "score": 10 + } + ] + } + }, + { + "name": "dummy", + "with": { + "comment": "\n\n### Details\n" + } + }, + { + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stderr" + ], + "showExitStatus": true, + "showRuntime": false, + "showMemory": false + } + } + ] + }, + { + "name": "Cpplint check", + "group": null, + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "cpplint", + "--linelength=120", + "--filter=-legal,-readability/casting,-whitespace,-runtime/printf,-runtime/threadsafe_fn,-readability/todo,-build/include_subdir,-build/header_guard", + "--recursive", + "--exclude=build", + "." + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 65000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 4000000000, + "realCpuLimit": 0, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": {}, + "copyInCached": {}, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [] + } + }, + "parsers": [ + { + "name": "cpplint", + "with": { + "comment": "" + } + }, + { + "name": "dummy", + "with": { + "comment": "\n\n### Details\n" + } + }, + { + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stdout" + ], + "showExitStatus": true, + "showRuntime": false, + "showMemory": false + } + } + ] + }, + { + "name": "judge-base", + "group": "joj", + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "./driver", + "./mumsh" + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 3000000000, + "realCpuLimit": 0, + "clockLimit": 6000000000, + "memoryLimit": 78643200, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": {}, + "copyInCached": {}, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [ + { + "args": null, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": "/home/tt/.config/joj/judge-base/case4.in", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": null, + "stderr": null, + "cpuLimit": 30000000000, + "realCpuLimit": null, + "clockLimit": 60000000000, + "memoryLimit": 10485760, + "stackLimit": null, + "procLimit": 50, + "cpuRateLimit": null, + "cpuSetLimit": null, + "copyIn": null, + "copyInCached": null, + "copyInDir": null, + "copyOut": null, + "copyOutCached": null, + "copyOutMax": null, + "copyOutDir": null, + "tty": null, + "strictMemoryLimit": null, + "dataSegmentLimit": null, + "addressSpaceLimit": null + }, + { + "args": null, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": "/home/tt/.config/joj/judge-base/case5.in", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": null, + "stderr": null, + "cpuLimit": 4000000000, + "realCpuLimit": null, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": null, + "procLimit": 50, + "cpuRateLimit": null, + "cpuSetLimit": null, + "copyIn": null, + "copyInCached": null, + "copyInDir": null, + "copyOut": null, + "copyOutCached": null, + "copyOutMax": null, + "copyOutDir": null, + "tty": null, + "strictMemoryLimit": null, + "dataSegmentLimit": null, + "addressSpaceLimit": null + }, + { + "args": null, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": "/home/tt/.config/joj/judge-base/case8.in", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": null, + "stderr": null, + "cpuLimit": 4000000000, + "realCpuLimit": null, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": null, + "procLimit": 50, + "cpuRateLimit": null, + "cpuSetLimit": null, + "copyIn": null, + "copyInCached": null, + "copyInDir": null, + "copyOut": null, + "copyOutCached": null, + "copyOutMax": null, + "copyOutDir": null, + "tty": null, + "strictMemoryLimit": null, + "dataSegmentLimit": null, + "addressSpaceLimit": null + } + ] + } + }, + "parsers": [ + { + "name": "diff", + "with": { + "name": "diff", + "cases": [ + { + "outputs": [ + { + "score": 0, + "fileName": "stdout", + "answerPath": "/home/tt/.config/joj/judge-base/case4.out", + "forceQuitOnDiff": true, + "alwaysHide": false, + "compareSpace": true + } + ] + }, + { + "outputs": [ + { + "score": 0, + "fileName": "stdout", + "answerPath": "/home/tt/.config/joj/judge-base/case5.out", + "forceQuitOnDiff": true, + "alwaysHide": false, + "compareSpace": true + } + ] + }, + { + "outputs": [ + { + "score": 0, + "fileName": "stdout", + "answerPath": "/home/tt/.config/joj/judge-base/case8.out", + "forceQuitOnDiff": true, + "alwaysHide": false, + "compareSpace": true + } + ] + } + ] + } + }, + { + "name": "dummy", + "with": { + "comment": "\n\n### Details\n" + } + }, + { + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stderr" + ], + "showExitStatus": true, + "showRuntime": true, + "showMemory": true + } + } + ] + }, + { + "name": "judge-msan", + "group": "joj", + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "./driver", + "./mumsh-msan" + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 10000000000, + "realCpuLimit": 0, + "clockLimit": 20000000000, + "memoryLimit": 524288000, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": {}, + "copyInCached": {}, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [ + { + "args": null, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": "/home/tt/.config/joj/judge-msan/case4.in", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": null, + "stderr": null, + "cpuLimit": 30000000000, + "realCpuLimit": null, + "clockLimit": 60000000000, + "memoryLimit": 10485760, + "stackLimit": null, + "procLimit": 50, + "cpuRateLimit": null, + "cpuSetLimit": null, + "copyIn": null, + "copyInCached": null, + "copyInDir": null, + "copyOut": null, + "copyOutCached": null, + "copyOutMax": null, + "copyOutDir": null, + "tty": null, + "strictMemoryLimit": null, + "dataSegmentLimit": null, + "addressSpaceLimit": null + }, + { + "args": null, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": "/home/tt/.config/joj/judge-msan/case5.in", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": null, + "stderr": null, + "cpuLimit": 4000000000, + "realCpuLimit": null, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": null, + "procLimit": 50, + "cpuRateLimit": null, + "cpuSetLimit": null, + "copyIn": null, + "copyInCached": null, + "copyInDir": null, + "copyOut": null, + "copyOutCached": null, + "copyOutMax": null, + "copyOutDir": null, + "tty": null, + "strictMemoryLimit": null, + "dataSegmentLimit": null, + "addressSpaceLimit": null + }, + { + "args": null, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": "/home/tt/.config/joj/judge-msan/case6.in", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": null, + "stderr": null, + "cpuLimit": 4000000000, + "realCpuLimit": null, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": null, + "procLimit": 50, + "cpuRateLimit": null, + "cpuSetLimit": null, + "copyIn": null, + "copyInCached": null, + "copyInDir": null, + "copyOut": null, + "copyOutCached": null, + "copyOutMax": null, + "copyOutDir": null, + "tty": null, + "strictMemoryLimit": null, + "dataSegmentLimit": null, + "addressSpaceLimit": null + } + ] + } + }, + "parsers": [ + { + "name": "diff", + "with": { + "name": "diff", + "cases": [ + { + "outputs": [ + { + "score": 0, + "fileName": "stdout", + "answerPath": "/home/tt/.config/joj/judge-msan/case4.out", + "forceQuitOnDiff": true, + "alwaysHide": false, + "compareSpace": true + } + ] + }, + { + "outputs": [ + { + "score": 0, + "fileName": "stdout", + "answerPath": "/home/tt/.config/joj/judge-msan/case5.out", + "forceQuitOnDiff": true, + "alwaysHide": false, + "compareSpace": true + } + ] + }, + { + "outputs": [ + { + "score": 0, + "fileName": "stdout", + "answerPath": "/home/tt/.config/joj/judge-msan/case6.out", + "forceQuitOnDiff": true, + "alwaysHide": true, + "compareSpace": true + } + ] + } + ] + } + }, + { + "name": "dummy", + "with": { + "comment": "\n\n### Details\n" + } + }, + { + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stderr" + ], + "showExitStatus": true, + "showRuntime": true, + "showMemory": true + } + } + ] + } + ] + }, + "teapot": { + "logPath": "h4-ex1-joint-teapot-debug.log", + "scoreboardPath": "h4-ex1-scoreboard.csv", + "failedTablePath": "h4-ex1-failed-table.md", + "gradingRepoName": "Nuvole-joj", + "skipIssue": false, + "skipScoreboard": false, + "skipFailedTable": false + } +} diff --git a/tests/basic/task.toml b/tests/basic/task.toml new file mode 100644 index 0000000..ec4cdfc --- /dev/null +++ b/tests/basic/task.toml @@ -0,0 +1,119 @@ +# general task configuration +task="h4 ex1" # task name + +release.deadline = 2024-10-12 23:59:00+08:00 +release.stages = [ "compile" ] + +[[stages]] +name = "Compilation" +command = "make.sh" # eg. script running cmake commands +files.import = [ "tools/make.sh", "src/main.c", "src/task.h", "srcCMakelist.txt" ] +files.export = [ "driver", "p2", "p2-msan" ] +limit.cpu = 180 # p2 takes long to compile +limit.stderr = 128 + +# compile parsers +parsers = [ "result-detail", "dummy", "result-status" ] +result-status.comment = "Congratulations! Your code compiled successfully." +dummy.comment = "\n\n### Details\n" +result-detail.exitstatus = true +result-detail.stderr = true +result-detail.time = false +result-detail.mem = false + +[[stages]] +name = "File length check" +command = "./file-length 500 400 *.c *.h" # command to run +files.import = [ "tools/file-length" ] + +parsers = [ "keyword", "dummy", "result-detail" ] +keyword.keyword = [ "max", "recommend"] # keywords caught by corresponding JOJ plugin +keyword.weight = [ 50, 20 ] # weight of each keyword +result-detail.exitstatus = false +result-detail.stderr = true +result-detail.time = false +result-detail.mem = false + +[[stages]] +name = "Clang-tidy checks" +command = "run-clang-tidy-18 -header-filter=.* -quiet -load=/usr/local/lib/libcodequality.so -p build" +limit.stdout = 65 + +parsers = [ "clangtidy", "dummy", "result-detail" ] +clangtidy.keyword = [ "codequality-no-global-variables", "codequality-no-header-guard", "readability-function-size", "readability-duplicate-include", "readability-identifier-naming", "readability-redundant", "readability-misleading-indentation", "readability-misplaced-array-index", "cppcoreguidelines-init-variables", "bugprone-suspicious-string-compare", "google-global-names-in-headers", "clang-diagnostic", "clang-analyzer", "misc performance" ] +clangtidy.weight = [10, 10, 50, 10, 5, 5, 10, 5, 5, 8, 5, 5, 5, 5] +dummy.comment = "\n\n### Details\n" +result-detail.exitstatus = true +result-detail.stdout = true +result-detail.time = false +result-detail.mem = false + +[[stages]] +name = "Cppcheck check" +command = "cppcheck --template='{\"file\":\"{file}\",\"line\":{line}, \"column\":{column}, \"severity\":\"{severity}\", \"message\":\"{message}\", \"id\":\"{id}\"}' --force --enable=all --quiet ./" +limit.stderr = 65 + +parsers = [ "cppcheck", "dummy", "result-detail" ] +cppcheck.keyword = ["error", "warning", "portability", "performance", "style"] +cppcheck.weight = [20, 10, 15, 15, 10] +dummy.comment = "\n\n### Details\n" +result-detail.exitstatus = true +result-detail.stderr = true +result-detail.time = false +result-detail.mem = false + +[[stages]] +name = "Cpplint check" +command = "cpplint --linelength=120 --filter=-legal,-readability/casting,-whitespace,-runtime/printf,-runtime/threadsafe_fn,-readability/todo,-build/include_subdir,-build/header_guard --recursive --exclude=build ." +limit.stdout = 65 + +parsers = [ "cpplint", "dummy", "result-detail" ] +cpplint.keyword = [ "runtime", "readability", "build" ] +cpplint.weight = [ 10, 20, 15] +dummy.comment = "\n\n### Details\n" +result-detail.exitstatus = true +result-detail.stdout = true +result-detail.time = false +result-detail.mem = false + +[[stages]] +name = "judge-base" +command="./driver ./mumsh" +limit.cpu = 3 +limit.mem = 75 +score = 10 + +parsers = ["diff", "dummy", "result-detail"] +dummy.comment = "\n\n### Details\n" +result-detail.exitstatus = true +result-detail.stderr = true + +case4.score = 15 +case4.limit.cpu = 30 +case4.limit.mem = 10 +case4.limit.stdout = 8 + +case5.score = 25 + +case8.limit.stderr = 128 + +[[stages]] +name = "judge-msan" +command="./driver ./mumsh-msan" +limit.cpu = 10 # default cpu limit (in sec) for each test case +limit.mem = 500 # set default mem limit (in MB) for all OJ test cases +score = 10 +skip = ["case0", "case11"] + +parsers = ["diff", "dummy", "result-detail"] +dummy.comment = "\n\n### Details\n" +result-detail.exitstatus = true +result-detail.stderr = true + +case4.score = 15 +case4.limit.cpu = 30 +case4.limit.mem = 10 + +case5.diff.output.ignorespaces = false + +case6.diff.output.hide = true diff --git a/tests/convert/basic/repo.toml b/tests/convert/basic/repo.toml index f9012cc..28b5c05 100644 --- a/tests/convert/basic/repo.toml +++ b/tests/convert/basic/repo.toml @@ -7,4 +7,4 @@ sandbox_token = "test" whitelist_patterns = ["*.py", "*.txt", "*.md"] whitelist_file = ".whitelist" required = ["main.py", "README.md"] -immutable = ["config.yaml", "setup.py"] +immutable = [] diff --git a/tests/convert/basic/task.json b/tests/convert/basic/task.json index 294d15c..1a55fb8 100644 --- a/tests/convert/basic/task.json +++ b/tests/convert/basic/task.json @@ -1,53 +1,78 @@ { - "name": "hw3 ex5", - "logPath": "hw3_ex5.log", - "expireUnixTimestamp": 1729267140, + "name": "Homework 1 exercise 2", + "logPath": "Homework-1-exercise-2.log", + "expireUnixTimestamp": 1728748740, "stage": { "sandboxExecServer": "172.17.0.1:5051", "sandboxToken": "test", "outputPath": "/tmp/joj3_result.json", "stages": [ { - "name": "judge_base", - "group": "hw3 ex5", + "name": "healthcheck", + "group": "", "executor": { "name": "sandbox", "with": { "default": { "args": [ - "./matlab-joj", - "./h3/ex5.m" + "/tmp/repo-health-checker", + "-root=.", + "-repoSize=50.5", + "-meta=main.py", + "-meta=README.md", + "-checkFileSumList=-checkFileNameList=" ], - "env": [], - "stdin": null, - "stdout": null, - "stderr": null, - "cpuLimit": 0, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 4096, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 4096, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 4000000000, "realCpuLimit": 0, - "clockLimit": 0, - "memoryLimit": 0, + "clockLimit": 8000000000, + "memoryLimit": 4194304, "stackLimit": 0, - "procLimit": 0, + "procLimit": 50, "cpuRateLimit": 0, "cpuSetLimit": "", "copyIn": { - "tools/matlab-joj": { - "src": "tools/matlab-joj", + "/tmp/repo-health-checker": { + "src": "/tmp/repo-health-checker", "content": null, "fileId": null, "name": null, - "max": null, - "symlink": null, - "streamIn": false, - "streamOut": false, - "pipe": false - }, - "tools/matlab_formatter.py": { - "src": "tools/matlab_formatter.py", - "content": null, - "fileId": null, - "name": null, - "max": null, + "max": 4194304, "symlink": null, "streamIn": false, "streamOut": false, @@ -57,10 +82,7 @@ "copyInCached": {}, "copyInDir": ".", "copyOut": [], - "copyOutCached": [ - "output/ex5_results.txt", - "output/ex5_logs.txt" - ], + "copyOutCached": [], "copyOutMax": 0, "copyOutDir": "", "tty": false, @@ -73,73 +95,126 @@ }, "parsers": [ { - "name": "diff", - "with": {} - }, - { - "name": "result-detail", + "name": "healthcheck", "with": { - "time": false, - "mem": false, - "stdout": false, - "stderr": true + "score": 0, + "comment": "" } } ] }, { - "name": "judge_base2", - "group": "hw3 ex5", + "name": "Compilation", + "group": null, "executor": { "name": "sandbox", "with": { "default": { "args": [ - "./matlab-joj", - "./h3/ex5.m" + "make.sh" ], - "env": [], - "stdin": null, - "stdout": null, - "stderr": null, - "cpuLimit": 0, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 128000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 180000000000, "realCpuLimit": 0, - "clockLimit": 0, - "memoryLimit": 0, + "clockLimit": 360000000000, + "memoryLimit": 4194304, "stackLimit": 0, - "procLimit": 0, + "procLimit": 50, "cpuRateLimit": 0, "cpuSetLimit": "", "copyIn": { - "tools/matlab-joj": { - "src": "tools/matlab-joj", + "tools/make.sh": { + "src": "/home/tt/.config/joj/tools/make.sh", "content": null, "fileId": null, "name": null, - "max": null, + "max": 4194304, "symlink": null, "streamIn": false, "streamOut": false, "pipe": false }, - "tools/matlab_formatter.py": { - "src": "tools/matlab_formatter.py", + "src/main.c": { + "src": "/home/tt/.config/joj/src/main.c", "content": null, "fileId": null, "name": null, - "max": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "src/task.h": { + "src": "/home/tt/.config/joj/src/task.h", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "srcCMakelist.txt": { + "src": "/home/tt/.config/joj/srcCMakelist.txt", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, "symlink": null, "streamIn": false, "streamOut": false, "pipe": false } }, - "copyInCached": {}, + "copyInCached": { + "tools/make.sh": "tools/make.sh", + "src/main.c": "src/main.c", + "src/task.h": "src/task.h", + "srcCMakelist.txt": "srcCMakelist.txt" + }, "copyInDir": ".", "copyOut": [], "copyOutCached": [ - "output/ex5_results2.txt", - "output/ex5_logs2.txt" + "driver", + "p2", + "p2-msan" ], "copyOutMax": 0, "copyOutDir": "", @@ -153,16 +228,1062 @@ }, "parsers": [ { - "name": "diff", - "with": {} + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stderr" + ], + "showExitStatus": true, + "showRuntime": false, + "showMemory": false + } + }, + { + "name": "dummy", + "with": { + "score": 1, + "comment": "Congratulations! Your code compiled successfully.", + "forceQuitOnNotAccepted": false + } + }, + { + "name": "result-status", + "with": { + "score": 1, + "comment": "Congratulations! Your code compiled successfully.", + "forceQuitOnNotAccepted": false + } + } + ] + }, + { + "name": "File length check", + "group": null, + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "./file-length", + "500", + "400", + "*.c", + "*.h" + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 4000000000, + "realCpuLimit": 0, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": { + "tools/file-length": { + "src": "/home/tt/.config/joj/tools/file-length", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + } + }, + "copyInCached": { + "tools/file-length": "tools/file-length" + }, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [] + } + }, + "parsers": [ + { + "name": "keyword", + "with": { + "matches": [ + { + "keywords": [ + "max" + ], + "score": 50 + }, + { + "keywords": [ + "recommend" + ], + "score": 20 + } + ] + } + }, + { + "name": "dummy", + "with": { + "score": 10000, + "comment": "Manuel Charlemagne", + "forceQuitOnNotAccepted": true + } }, { "name": "result-detail", "with": { - "time": true, - "mem": true, - "stdout": false, - "stderr": false + "score": 0, + "comment": "", + "showFiles": [ + "stderr" + ], + "showExitStatus": true, + "showRuntime": false, + "showMemory": false + } + } + ] + }, + { + "name": "Clang-tidy checks", + "group": null, + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "run-clang-tidy-18", + "-header-filter=.*", + "-quiet", + "-load=/usr/local/lib/libcodequality.so", + "-p", + "build" + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 65000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 4000000000, + "realCpuLimit": 0, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": {}, + "copyInCached": {}, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [] + } + }, + "parsers": [ + { + "name": "clangtidy", + "with": { + "matches": [ + { + "keywords": [ + "bugprone-suspicious-string-compare" + ], + "score": 8 + }, + { + "keywords": [ + "codequality-no-global-variables", + "codequality-no-header-guard", + "readability-duplicate-include", + "readability-misleading-indentation" + ], + "score": 10 + }, + { + "keywords": [ + "readability-function-size" + ], + "score": 50 + }, + { + "keywords": [ + "readability-identifier-naming", + "readability-redundant", + "readability-misplaced-array-index", + "cppcoreguidelines-init-variables", + "google-global-names-in-headers", + "clang-diagnostic", + "clang-analyzer", + "misc performance" + ], + "score": 5 + } + ] + } + }, + { + "name": "dummy", + "with": { + "score": 0, + "comment": "", + "forceQuitOnNotAccepted": true + } + }, + { + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stdout" + ], + "showExitStatus": true, + "showRuntime": false, + "showMemory": false + } + } + ] + }, + { + "name": "Cppcheck check", + "group": null, + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "cppcheck", + "--template='{\"file\":\"{file}\",\"line\":{line},", + "\"column\":{column},", + "\"severity\":\"{severity}\",", + "\"message\":\"{message}\",", + "\"id\":\"{id}\"}'", + "--force", + "--enable=all", + "--quiet", + "./" + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 65000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 4000000000, + "realCpuLimit": 0, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": {}, + "copyInCached": {}, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [] + } + }, + "parsers": [ + { + "name": "cppcheck", + "with": { + "matches": [ + { + "keywords": [ + "warning", + "style" + ], + "score": 10 + }, + { + "keywords": [ + "error" + ], + "score": 20 + }, + { + "keywords": [ + "portability", + "performance" + ], + "score": 15 + } + ] + } + }, + { + "name": "dummy", + "with": { + "score": 0, + "comment": "", + "forceQuitOnNotAccepted": true + } + }, + { + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stderr" + ], + "showExitStatus": true, + "showRuntime": false, + "showMemory": false + } + } + ] + }, + { + "name": "Cpplint check", + "group": null, + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "cpplint", + "--linelength=120", + "--filter=-legal,-readability/casting,-whitespace,-runtime/printf,-runtime/threadsafe_fn,-readability/todo,-build/include_subdir,-build/header_guard", + "--recursive", + "--exclude=build", + "." + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 65000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 4000000000, + "realCpuLimit": 0, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": {}, + "copyInCached": {}, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [] + } + }, + "parsers": [ + { + "name": "cpplint", + "with": { + "score": 0, + "comment": "", + "forceQuitOnNotAccepted": true, + "matches": [ + { + "keywords": [ + "runtime" + ], + "score": 10 + }, + { + "keywords": [ + "readability" + ], + "score": 20 + }, + { + "keywords": [ + "build" + ], + "score": 15 + } + ] + } + }, + { + "name": "dummy", + "with": { + "score": 0, + "comment": "", + "forceQuitOnNotAccepted": true + } + }, + { + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stdout" + ], + "showExitStatus": true, + "showRuntime": false, + "showMemory": false + } + } + ] + }, + { + "name": "judge-base", + "group": "joj", + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "./driver", + "./mumsh" + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 3000000000, + "realCpuLimit": 0, + "clockLimit": 6000000000, + "memoryLimit": 78643200, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": {}, + "copyInCached": {}, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [ + { + "args": null, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": "/home/tt/.config/joj/judge-base/case4.in", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": null, + "stderr": null, + "cpuLimit": 30000000000, + "realCpuLimit": null, + "clockLimit": 60000000000, + "memoryLimit": 10485760, + "stackLimit": null, + "procLimit": 50, + "cpuRateLimit": null, + "cpuSetLimit": null, + "copyIn": null, + "copyInCached": null, + "copyInDir": null, + "copyOut": null, + "copyOutCached": null, + "copyOutMax": null, + "copyOutDir": null, + "tty": null, + "strictMemoryLimit": null, + "dataSegmentLimit": null, + "addressSpaceLimit": null + }, + { + "args": null, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": "/home/tt/.config/joj/judge-base/case5.in", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": null, + "stderr": null, + "cpuLimit": 4000000000, + "realCpuLimit": null, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": null, + "procLimit": 50, + "cpuRateLimit": null, + "cpuSetLimit": null, + "copyIn": null, + "copyInCached": null, + "copyInDir": null, + "copyOut": null, + "copyOutCached": null, + "copyOutMax": null, + "copyOutDir": null, + "tty": null, + "strictMemoryLimit": null, + "dataSegmentLimit": null, + "addressSpaceLimit": null + }, + { + "args": null, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": "/home/tt/.config/joj/judge-base/case8.in", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": null, + "stderr": null, + "cpuLimit": 4000000000, + "realCpuLimit": null, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": null, + "procLimit": 50, + "cpuRateLimit": null, + "cpuSetLimit": null, + "copyIn": null, + "copyInCached": null, + "copyInDir": null, + "copyOut": null, + "copyOutCached": null, + "copyOutMax": null, + "copyOutDir": null, + "tty": null, + "strictMemoryLimit": null, + "dataSegmentLimit": null, + "addressSpaceLimit": null + } + ] + } + }, + "parsers": [ + { + "name": "diff", + "with": { + "name": "diff", + "cases": [ + { + "outputs": [ + { + "score": 0, + "fileName": "stdout", + "answerPath": "/home/tt/.config/joj/judge-base/case4.out", + "forceQuitOnDiff": true, + "alwaysHide": false, + "compareSpace": true + } + ] + }, + { + "outputs": [ + { + "score": 0, + "fileName": "stdout", + "answerPath": "/home/tt/.config/joj/judge-base/case5.out", + "forceQuitOnDiff": true, + "alwaysHide": false, + "compareSpace": true + } + ] + }, + { + "outputs": [ + { + "score": 0, + "fileName": "stdout", + "answerPath": "/home/tt/.config/joj/judge-base/case8.out", + "forceQuitOnDiff": true, + "alwaysHide": false, + "compareSpace": true + } + ] + } + ] + } + }, + { + "name": "dummy", + "with": { + "score": 0, + "comment": "", + "forceQuitOnNotAccepted": true + } + }, + { + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stderr" + ], + "showExitStatus": true, + "showRuntime": true, + "showMemory": true + } + } + ] + }, + { + "name": "judge-msan", + "group": "joj", + "executor": { + "name": "sandbox", + "with": { + "default": { + "args": [ + "./driver", + "./mumsh-msan" + ], + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": null, + "content": "", + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": { + "src": null, + "content": null, + "fileId": null, + "name": "stdout", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stderr": { + "src": null, + "content": null, + "fileId": null, + "name": "stderr", + "max": 4000000000, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "cpuLimit": 10000000000, + "realCpuLimit": 0, + "clockLimit": 20000000000, + "memoryLimit": 524288000, + "stackLimit": 0, + "procLimit": 50, + "cpuRateLimit": 0, + "cpuSetLimit": "", + "copyIn": {}, + "copyInCached": {}, + "copyInDir": ".", + "copyOut": [], + "copyOutCached": [], + "copyOutMax": 0, + "copyOutDir": "", + "tty": false, + "strictMemoryLimit": false, + "dataSegmentLimit": false, + "addressSpaceLimit": false + }, + "cases": [ + { + "args": null, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": "/home/tt/.config/joj/judge-msan/case4.in", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": null, + "stderr": null, + "cpuLimit": 30000000000, + "realCpuLimit": null, + "clockLimit": 60000000000, + "memoryLimit": 10485760, + "stackLimit": null, + "procLimit": 50, + "cpuRateLimit": null, + "cpuSetLimit": null, + "copyIn": null, + "copyInCached": null, + "copyInDir": null, + "copyOut": null, + "copyOutCached": null, + "copyOutMax": null, + "copyOutDir": null, + "tty": null, + "strictMemoryLimit": null, + "dataSegmentLimit": null, + "addressSpaceLimit": null + }, + { + "args": null, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": "/home/tt/.config/joj/judge-msan/case5.in", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": null, + "stderr": null, + "cpuLimit": 4000000000, + "realCpuLimit": null, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": null, + "procLimit": 50, + "cpuRateLimit": null, + "cpuSetLimit": null, + "copyIn": null, + "copyInCached": null, + "copyInDir": null, + "copyOut": null, + "copyOutCached": null, + "copyOutMax": null, + "copyOutDir": null, + "tty": null, + "strictMemoryLimit": null, + "dataSegmentLimit": null, + "addressSpaceLimit": null + }, + { + "args": null, + "env": [ + "PATH=/usr/bin:/bin:/usr/local/bin" + ], + "stdin": { + "src": "/home/tt/.config/joj/judge-msan/case6.in", + "content": null, + "fileId": null, + "name": null, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false + }, + "stdout": null, + "stderr": null, + "cpuLimit": 4000000000, + "realCpuLimit": null, + "clockLimit": 8000000000, + "memoryLimit": 4194304, + "stackLimit": null, + "procLimit": 50, + "cpuRateLimit": null, + "cpuSetLimit": null, + "copyIn": null, + "copyInCached": null, + "copyInDir": null, + "copyOut": null, + "copyOutCached": null, + "copyOutMax": null, + "copyOutDir": null, + "tty": null, + "strictMemoryLimit": null, + "dataSegmentLimit": null, + "addressSpaceLimit": null + } + ] + } + }, + "parsers": [ + { + "name": "diff", + "with": { + "name": "diff", + "cases": [ + { + "outputs": [ + { + "score": 0, + "fileName": "stdout", + "answerPath": "/home/tt/.config/joj/judge-msan/case4.out", + "forceQuitOnDiff": true, + "alwaysHide": false, + "compareSpace": true + } + ] + }, + { + "outputs": [ + { + "score": 0, + "fileName": "stdout", + "answerPath": "/home/tt/.config/joj/judge-msan/case5.out", + "forceQuitOnDiff": true, + "alwaysHide": false, + "compareSpace": true + } + ] + }, + { + "outputs": [ + { + "score": 0, + "fileName": "stdout", + "answerPath": "/home/tt/.config/joj/judge-msan/case6.out", + "forceQuitOnDiff": true, + "alwaysHide": true, + "compareSpace": true + } + ] + } + ] + } + }, + { + "name": "dummy", + "with": { + "score": 0, + "comment": "", + "forceQuitOnNotAccepted": true + } + }, + { + "name": "result-detail", + "with": { + "score": 0, + "comment": "", + "showFiles": [ + "stderr" + ], + "showExitStatus": true, + "showRuntime": true, + "showMemory": true } } ] diff --git a/tests/convert/basic/task.toml b/tests/convert/basic/task.toml index 0872079..b060a9e 100644 --- a/tests/convert/basic/task.toml +++ b/tests/convert/basic/task.toml @@ -1,30 +1,124 @@ -task = "hw3 ex5" +# general task configuration +task="Homework 1 exercise 2" # task name -[release] -deadline = "2024-10-18T23:59:00+08:00" +release.deadline = 2024-10-12 23:59:00+08:00 +release.stages = [ "compile" ] [[stages]] -name = "judge_base" -command = "./matlab-joj ./h3/ex5.m" -score = 100 -parsers = ["diff", "result-detail"] +name = "Compilation" +command = "make.sh" # eg. script running cmake commands +files.import = [ "tools/make.sh", "src/main.c", "src/task.h", "srcCMakelist.txt" ] +files.export = [ "driver", "p2", "p2-msan" ] +limit.cpu = 180 # p2 takes long to compile +limit.stderr = 128 -files.import = ["tools/matlab-joj", "tools/matlab_formatter.py"] -files.export = ["output/ex5_results.txt", "output/ex5_logs.txt"] - -result_detail.time = false -result_detail.mem = false -result_detail.stderr = true +# compile parsers +parsers = [ "result-detail", "dummy", "result-status" ] +result-status.comment = "Congratulations! Your code compiled successfully." +result-status.score = 1 +result-status.forcequit = false +dummy.comment = "\n\n### Details\n" +result-detail.exitstatus = true +result-detail.stderr = true +result-detail.time = false +result-detail.mem = false [[stages]] -name = "judge_base2" -command = "./matlab-joj ./h3/ex5.m" -score = 80 -parsers = ["diff", "result-detail"] +name = "File length check" +command = "./file-length 500 400 *.c *.h" # command to run +files.import = [ "tools/file-length" ] -files.import = ["tools/matlab-joj", "tools/matlab_formatter.py"] -files.export = ["output/ex5_results2.txt", "output/ex5_logs2.txt"] +parsers = [ "keyword", "dummy", "result-detail" ] +keyword.keyword = [ "max", "recommend"] # keywords caught by corresponding JOJ plugin +keyword.weight = [ 50, 20 ] # weight of each keyword +result-detail.exitstatus = true +result-detail.stderr = true +result-detail.time = false +result-detail.mem = false +result-status.comment = "Manuel Charlemagne" +result-status.score = 10000 +result-status.forcequit = true -result_detail.time = true -result_detail.mem = true -result_detail.stderr = false +[[stages]] +name = "Clang-tidy checks" +command = "run-clang-tidy-18 -header-filter=.* -quiet -load=/usr/local/lib/libcodequality.so -p build" +limit.stdout = 65 + +parsers = [ "clangtidy", "dummy", "result-detail" ] +clangtidy.keyword = [ "codequality-no-global-variables", "codequality-no-header-guard", "readability-function-size", "readability-duplicate-include", "readability-identifier-naming", "readability-redundant", "readability-misleading-indentation", "readability-misplaced-array-index", "cppcoreguidelines-init-variables", "bugprone-suspicious-string-compare", "google-global-names-in-headers", "clang-diagnostic", "clang-analyzer", "misc performance" ] +clangtidy.weight = [10, 10, 50, 10, 5, 5, 10, 5, 5, 8, 5, 5, 5, 5] +dummy.comment = "\n\n### Details\n" +result-detail.exitstatus = true +result-detail.stdout = true +result-detail.time = false +result-detail.mem = false + +[[stages]] +name = "Cppcheck check" +command = "cppcheck --template='{\"file\":\"{file}\",\"line\":{line}, \"column\":{column}, \"severity\":\"{severity}\", \"message\":\"{message}\", \"id\":\"{id}\"}' --force --enable=all --quiet ./" +limit.stderr = 65 + +parsers = [ "cppcheck", "dummy", "result-detail" ] +cppcheck.keyword = ["error", "warning", "portability", "performance", "style"] +cppcheck.weight = [20, 10, 15, 15, 10] +dummy.comment = "\n\n### Details\n" +result-detail.exitstatus = true +result-detail.stderr = true +result-detail.time = false +result-detail.mem = false + +[[stages]] +name = "Cpplint check" +command = "cpplint --linelength=120 --filter=-legal,-readability/casting,-whitespace,-runtime/printf,-runtime/threadsafe_fn,-readability/todo,-build/include_subdir,-build/header_guard --recursive --exclude=build ." +limit.stdout = 65 + +parsers = [ "cpplint", "dummy", "result-detail" ] +cpplint.keyword = [ "runtime", "readability", "build" ] +cpplint.weight = [ 10, 20, 15] +dummy.comment = "\n\n### Details\n" +result-detail.exitstatus = true +result-detail.stdout = true +result-detail.time = false +result-detail.mem = false + +[[stages]] +name = "judge-base" +command="./driver ./mumsh" +limit.cpu = 3 +limit.mem = 75 +score = 10 + +parsers = ["diff", "dummy", "result-detail"] +dummy.comment = "\n\n### Details\n" +result-detail.exitstatus = true +result-detail.stderr = true + +case4.score = 15 +case4.limit.cpu = 30 +case4.limit.mem = 10 +case4.limit.stdout = 8 + +case5.score = 25 + +case8.limit.stderr = 128 + +[[stages]] +name = "judge-msan" +command="./driver ./mumsh-msan" +limit.cpu = 10 # default cpu limit (in sec) for each test case +limit.mem = 500 # set default mem limit (in MB) for all OJ test cases +score = 10 +skip = ["case0", "case11"] + +parsers = ["diff", "dummy", "result-detail"] +dummy.comment = "\n\n### Details\n" +result-detail.exitstatus = true +result-detail.stderr = true + +case4.score = 15 +case4.limit.cpu = 30 +case4.limit.mem = 10 + +case5.diff.output.ignorespaces = false + +case6.diff.output.hide = true diff --git a/tests/immutable_file/.gitattributes b/tests/immutable_file/.gitattributes new file mode 100644 index 0000000..b910c4a --- /dev/null +++ b/tests/immutable_file/.gitattributes @@ -0,0 +1,33 @@ +*.avi filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.djvu filter=lfs diff=lfs merge=lfs -text +*.doc filter=lfs diff=lfs merge=lfs -text +*.docx filter=lfs diff=lfs merge=lfs -text +*.epub filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.ipynb filter=lfs diff=lfs merge=lfs -text +*.jpeg filter=lfs diff=lfs merge=lfs -text +*.JPEG filter=lfs diff=lfs merge=lfs -text +*.jpg filter=lfs diff=lfs merge=lfs -text +*.JPG filter=lfs diff=lfs merge=lfs -text +*.mkv filter=lfs diff=lfs merge=lfs -text +*.mp4 filter=lfs diff=lfs merge=lfs -text +*.ods filter=lfs diff=lfs merge=lfs -text +*.odt filter=lfs diff=lfs merge=lfs -text +*.otf filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.PDF filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.PNG filter=lfs diff=lfs merge=lfs -text +*.ppt filter=lfs diff=lfs merge=lfs -text +*.pptx filter=lfs diff=lfs merge=lfs -text +*.ps filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.webm filter=lfs diff=lfs merge=lfs -text +*.xls filter=lfs diff=lfs merge=lfs -text +*.xlsx filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text diff --git a/tests/immutable_file/.gitignore b/tests/immutable_file/.gitignore new file mode 100644 index 0000000..754f776 --- /dev/null +++ b/tests/immutable_file/.gitignore @@ -0,0 +1,23 @@ +################################ +## White list based gitignore ## +################################ + +# forbidden +* +.* + +# allowed +!.gitignore +!.gitattributes +!.gitea/ +!.gitea/issue_template/ +!.gitea/workflows/ +!*.yaml +!Makefile +!CMakeLists.txt +!h[0-8]/ +!*.m +!*.c +!*.cpp +!*.h +!*.md diff --git a/tests/immutable_file/push.yaml b/tests/immutable_file/push.yaml new file mode 100644 index 0000000..2f890b6 --- /dev/null +++ b/tests/immutable_file/push.yaml @@ -0,0 +1,18 @@ +name: Run JOJ3 on Push +on: [push] +jobs: + run: + container: + image: focs.ji.sjtu.edu.cn:5000/gitea/runner-images:focs-ubuntu-latest-slim + volumes: + - /home/tt/.config:/home/tt/.config + - /home/tt/.cache:/home/tt/.cache + - /home/tt/.ssh:/home/tt/.ssh + steps: + - name: Check out repository code + uses: https://gitea.com/BoYanZh/checkout@focs + with: + fetch-depth: 0 + - name: run joj3 + run: | + sudo -E -u tt joj3 -conf-root /home/tt/.config/joj diff --git a/tests/immutable_file/release.yaml b/tests/immutable_file/release.yaml new file mode 100644 index 0000000..afd2838 --- /dev/null +++ b/tests/immutable_file/release.yaml @@ -0,0 +1,20 @@ +name: Run JOJ3 on Release +on: + release: + types: [published] +jobs: + run: + container: + image: focs.ji.sjtu.edu.cn:5000/gitea/runner-images:focs-ubuntu-latest-slim + volumes: + - /home/tt/.config:/home/tt/.config + - /home/tt/.cache:/home/tt/.cache + - /home/tt/.ssh:/home/tt/.ssh + steps: + - name: Check out repository code + uses: https://gitea.com/BoYanZh/checkout@focs + with: + fetch-depth: 0 + - name: run joj3 + run: | + sudo -E -u tt joj3 -conf-root /home/tt/.config/joj -msg "feat(h1-release): joj on ${{ github.ref }}"