diff --git a/joj3_config_generator/convert.py b/joj3_config_generator/convert.py index b20807e..914bef5 100644 --- a/joj3_config_generator/convert.py +++ b/joj3_config_generator/convert.py @@ -19,35 +19,76 @@ from joj3_config_generator.lib.task import ( get_executorWithConfig, ) from joj3_config_generator.models import joj1, repo, result, task +from joj3_config_generator.lib.repo import getHealthcheckConfig, getTeapotConfig +from joj3_config_generator.models import ( + Cmd, + CmdFile, + ExecutorConfig, + ExecutorWithConfig, + ParserConfig, + Repo, + ResultConfig, + Stage, + StageConfig, + Task, + TeapotConfig, +) +# 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, # TODO: specify the exact folder difference 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 else -1 ), stage=result.Stage(stages=[], sandbox_token=repo_conf.sandbox_token), + teapot=result.Teapot(), + stage=StageConfig(stages=[], sandbox_token=repo_conf.sandbox_token), teapot=getTeapotConfig(repo_conf, task_conf), ) # Construct healthcheck stage - healthcheck_stage = getHealthcheckConfig(repo_conf) + healthcheck_stage = getHealthcheckConfig(repo_conf, task_conf) result_conf.stage.stages.append(healthcheck_stage) - cached: list[str] = [] + cached = [] # Convert each stage in the task configuration for task_stage in task_conf.stages: - 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) + 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" + ) + if task_stage.result_detail is not None: + result_detail_parser.with_.update(task_stage.result_detail) + result_conf.stage.stages.append(conf_stage) return result_conf diff --git a/joj3_config_generator/lib/__init__.py b/joj3_config_generator/lib/__init__.py index e69de29..68802d4 100644 --- a/joj3_config_generator/lib/__init__.py +++ b/joj3_config_generator/lib/__init__.py @@ -0,0 +1,11 @@ +from joj3_config_generator.models.repo import Repo as Repo +from joj3_config_generator.models.result import Cmd as Cmd +from joj3_config_generator.models.result import CmdFile as CmdFile +from joj3_config_generator.models.result import ExecutorConfig as ExecutorConfig +from joj3_config_generator.models.result import ExecutorWithConfig as ExecutorWithConfig +from joj3_config_generator.models.result import ParserConfig as ParserConfig +from joj3_config_generator.models.result import ResultConfig as ResultConfig +from joj3_config_generator.models.result import Stage as Stage +from joj3_config_generator.models.result import StageConfig as StageConfig +from joj3_config_generator.models.result import TeapotConfig as TeapotConfig +from joj3_config_generator.models.task import Task as Task diff --git a/joj3_config_generator/lib/repo.py b/joj3_config_generator/lib/repo.py index c8e1d5b..e9a8d33 100644 --- a/joj3_config_generator/lib/repo.py +++ b/joj3_config_generator/lib/repo.py @@ -1,18 +1,40 @@ import hashlib -import shlex -import socket -from pathlib import Path +import os +import tempfile -from joj3_config_generator.models import joj1, repo, result, task +from dotenv import load_dotenv + +from joj3_config_generator.models import ( + Cmd, + CmdFile, + ExecutorConfig, + ExecutorWithConfig, + ParserConfig, + Repo, + ResultConfig, + Stage, + StageConfig, + Task, + TeapotConfig, +) + + +def get_temp_directory() -> str: + return tempfile.mkdtemp(prefix="repo-checker-") def getGradingRepoName() -> str: - host_name = socket.gethostname() - return f"{host_name.split('-')[0]}-joj" + path = os.path.expanduser("~/.config/teapot/teapot.env") + if os.path.exists(path): + load_dotenv(path) + repo_name = os.environ.get("GITEA_ORG_NAME") + if repo_name is not None: + return f"{repo_name.split('-')[0]}-joj" + return "ece482-joj" -def getTeapotConfig(repo_conf: repo.Config, task_conf: task.Config) -> result.Teapot: - teapot = result.Teapot( +def getTeapotConfig(repo_conf: Repo, task_conf: Task) -> TeapotConfig: + teapot = TeapotConfig( # 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", @@ -22,7 +44,7 @@ def getTeapotConfig(repo_conf: repo.Config, task_conf: task.Config) -> result.Te return teapot -def getHealthcheckCmd(repo_conf: repo.Config) -> result.Cmd: +def getHealthcheckCmd(repo_conf: Repo) -> Cmd: repoSize = repo_conf.max_size immutable = repo_conf.files.immutable repo_size = f"-repoSize={str(repoSize)} " @@ -38,7 +60,7 @@ def getHealthcheckCmd(repo_conf: repo.Config) -> result.Cmd: else: immutable_files = immutable_files + name + "," # FIXME: need to make solution and make things easier to edit with global scope - chore = f"./repo-health-checker -root=. " + chore = f"/{get_temp_directory}/repo-health-checker -root=. " args = "" args = args + chore args = args + repo_size @@ -49,25 +71,27 @@ def getHealthcheckCmd(repo_conf: repo.Config) -> result.Cmd: args = args + immutable_files - cmd = result.Cmd( - args=shlex.split(args), + cmd = Cmd( + args=args.split(), # FIXME: easier to edit within global scope copy_in={ - f"./repo-health-checker": result.CmdFile(src=f"./repo-health-checker") + f"/{get_temp_directory()}/repo-health-checker": CmdFile( + src=f"/{get_temp_directory()}/repo-health-checker" + ) }, ) return cmd -def getHealthcheckConfig(repo_conf: repo.Config) -> result.StageDetail: - healthcheck_stage = result.StageDetail( +def getHealthcheckConfig(repo_conf: Repo, task_conf: Task) -> Stage: + healthcheck_stage = Stage( name="healthcheck", group="", - executor=result.Executor( + executor=ExecutorConfig( name="sandbox", - with_=result.ExecutorWith(default=getHealthcheckCmd(repo_conf), cases=[]), + with_=ExecutorWithConfig(default=getHealthcheckCmd(repo_conf), cases=[]), ), - parsers=[result.Parser(name="healthcheck", with_={"score": 0, "comment": ""})], + parsers=[ParserConfig(name="healthcheck", with_={"score": 0, "comment": ""})], ) return healthcheck_stage @@ -81,10 +105,7 @@ def calc_sha256sum(file_path: str) -> str: def get_hash(immutable_files: list[str]) -> str: # input should be a list - # FIXME: should be finalized when get into the server - current_file_path = Path(__file__).resolve() - project_root = current_file_path.parents[2] - file_path = f"{project_root}/tests/immutable_file/" + 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] diff --git a/joj3_config_generator/models/task.py b/joj3_config_generator/models/task.py index 684cdd5..85b58fe 100644 --- a/joj3_config_generator/models/task.py +++ b/joj3_config_generator/models/task.py @@ -14,31 +14,17 @@ class ParserResultDetail(BaseModel): 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() + keyword: Optional[list[str]] = None + weight: Optional[list[int]] = None class Files(BaseModel): - import_: Optional[List[str]] = Field( - [], serialization_alias="import", validation_alias="import" - ) - export: Optional[List[str]] = [] + import_: Optional[List[str]] = Field(serialization_alias="import", validation_alias="import") + export: Optional[List[str]] + class Limit(BaseModel): @@ -49,36 +35,20 @@ class Limit(BaseModel): class Stage(BaseModel): - name: Optional[str] = None # Stage name - command: Optional[str] = None # Command to run + name: str # Stage name + command: str # Command to run files: Optional[Files] = None score: Optional[int] = 0 - parsers: Optional[list[str]] = [] # list of parsers - limit: Optional[Limit] = Limit() + parsers: list[str] # list of parsers + limit: Optional[Limit] = None 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/convert/basic/repo.toml b/tests/convert/basic/repo.toml index bb9818b..c77b9f7 100644 --- a/tests/convert/basic/repo.toml +++ b/tests/convert/basic/repo.toml @@ -6,5 +6,5 @@ sandbox_token = "test" [files] whitelist_patterns = ["*.py", "*.txt", "*.md"] whitelist_file = ".whitelist" -required = [ "Changelog.md", "Readme.md" ] -immutable = [".gitignore", ".gitattributes", ".gitea/workflows/push.yaml", ".gitea/workflows/release.yaml" ] +required = ["main.py", "README.md"] +immutable = [".gitignore", ".gitattributes", "push.yaml", "release.yaml"] diff --git a/tests/convert/basic/task.json b/tests/convert/basic/task.json index 1603820..777e2d7 100644 --- a/tests/convert/basic/task.json +++ b/tests/convert/basic/task.json @@ -1,6 +1,6 @@ { - "name": "p2 m3", - "logPath": "p2-m3.log", + "name": "Homework 1 exercise 2", + "logPath": "Homework-1-exercise-2.log", "expireUnixTimestamp": 1728748740, "stage": { "sandboxExecServer": "172.17.0.1:5051", @@ -15,13 +15,13 @@ "with": { "default": { "args": [ - "./repo-health-checker", + "/tmp/repo-health-checker", "-root=.", "-repoSize=50.5", - "-meta=Changelog.md", - "-meta=Readme.md", - "-checkFileSumList=a5b63323a692d3d8b952442969649b4f823d58dae26429494f613df160710dfc,b1bbad25b830db0a77b15a033f9ca1b7ab44c1d2d05056412bd3e4421645f0bf,1965adff52af61da8b9e089ff580d60f7e4c294a2930b9809c5cbdf76528de4d,c8bd62bf5297bac738b3845612fd595d677884093070904375463ab7953fce28", - "-checkFileNameList=.gitignore,.gitattributes,.gitea/workflows/push.yaml,.gitea/workflows/release.yaml" + "-meta=main.py", + "-meta=README.md", + "-checkFileSumList=a5b63323a692d3d8b952442969649b4f823d58dae26429494f613df160710dfc,b1bbad25b830db0a77b15a033f9ca1b7ab44c1d2d05056412bd3e4421645f0bf,8d1229900c6fc6711b5cc141d1ab5ea7f5b7b7a4b921d9cfa3957408b43ae723,eb857bcd94857cedc4045cb2d6ba04cb5bbb3daf188abc95fb9478db823ef47e", + "-checkFileNameList=.gitignore,.gitattributes,push.yaml,release.yaml" ], "env": [ "PATH=/usr/bin:/bin:/usr/local/bin" @@ -68,8 +68,8 @@ "cpuRateLimit": 0, "cpuSetLimit": "", "copyIn": { - "./repo-health-checker": { - "src": "./repo-health-checker", + "/tmp/repo-health-checker": { + "src": "/tmp/repo-health-checker", "content": null, "fileId": null, "name": null, @@ -104,101 +104,6 @@ } ] }, - { - "name": "Abuse of strings detected", - "group": null, - "executor": { - "name": "sandbox", - "with": { - "default": { - "args": [ - "./strdetect", - "src/" - ], - "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/strdetec": { - "src": "/home/tt/.config/joj/tools/strdetec", - "content": null, - "fileId": null, - "name": null, - "max": 4194304, - "symlink": null, - "streamIn": false, - "streamOut": false, - "pipe": false - } - }, - "copyInCached": { - "tools/strdetec": "tools/strdetec" - }, - "copyInDir": ".", - "copyOut": [], - "copyOutCached": [], - "copyOutMax": 0, - "copyOutDir": "", - "tty": false, - "strictMemoryLimit": false, - "dataSegmentLimit": false, - "addressSpaceLimit": false - }, - "cases": [] - } - }, - "parsers": [ - { - "name": "result-status", - "with": { - "score": 0, - "comment": "", - "forceQuitOnNotAccepted": true - } - } - ] - }, { "name": "Compilation", "group": null, @@ -207,7 +112,7 @@ "with": { "default": { "args": [ - "compile" + "make.sh" ], "env": [ "PATH=/usr/bin:/bin:/usr/local/bin" @@ -228,7 +133,7 @@ "content": null, "fileId": null, "name": "stdout", - "max": 4000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -239,7 +144,7 @@ "content": null, "fileId": null, "name": "stderr", - "max": 4000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -249,13 +154,16 @@ "realCpuLimit": 0, "clockLimit": 8000000000, "memoryLimit": 4194304, + "clockLimit": 8000000000, + "memoryLimit": 4194304, "stackLimit": 0, "procLimit": 50, + "procLimit": 50, "cpuRateLimit": 0, "cpuSetLimit": "", "copyIn": { - "tools/compile": { - "src": "/home/tt/.config/joj/tools/compile", + "tools/make.sh": { + "src": "/home/tt/.config/joj/tools/make.sh", "content": null, "fileId": null, "name": null, @@ -264,19 +172,54 @@ "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, + "max": 4194304, + "symlink": null, + "streamIn": false, + "streamOut": false, + "pipe": false } }, "copyInCached": { - "tools/compile": "tools/compile" + "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": [ - "build/onecard", - "build/asan", - "build/ubsan", - "build/msan", - "build/compile_commands.json" + "driver", + "p2", + "p2-msan" ], "copyOutMax": 0, "copyOutDir": "", @@ -290,38 +233,27 @@ }, "parsers": [ { - "name": "result-detail", + "name": "result-status", "with": { - "score": 0, - "comment": "", - "showFiles": [ - "stderr" - ], - "showExitStatus": true, - "showRuntime": false, - "showMemory": false + "time": false, + "mem": false, + "stdout": false, + "stderr": true, + "exitstatus": true } }, { "name": "dummy", - "with": { - "score": 1, - "comment": "Congratulations! Your code compiled successfully.", - "forceQuitOnNotAccepted": true - } + "with": {} }, { "name": "result-status", - "with": { - "score": 1, - "comment": "Congratulations! Your code compiled successfully.", - "forceQuitOnNotAccepted": true - } + "with": {} } ] }, { - "name": "[cq] Filelength", + "name": "File length check", "group": null, "executor": { "name": "sandbox", @@ -329,8 +261,8 @@ "default": { "args": [ "./file-length", + "500", "400", - "300", "*.c", "*.h" ], @@ -353,7 +285,7 @@ "content": null, "fileId": null, "name": "stdout", - "max": 4000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -364,7 +296,7 @@ "content": null, "fileId": null, "name": "stderr", - "max": 4000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -374,13 +306,16 @@ "realCpuLimit": 0, "clockLimit": 8000000000, "memoryLimit": 4194304, + "clockLimit": 8000000000, + "memoryLimit": 4194304, "stackLimit": 0, "procLimit": 50, + "procLimit": 50, "cpuRateLimit": 0, "cpuSetLimit": "", "copyIn": { - "tools/filelength": { - "src": "/home/tt/.config/joj/tools/filelength", + "tools/file-length": { + "src": "/home/tt/.config/joj/tools/file-length", "content": null, "fileId": null, "name": null, @@ -392,7 +327,7 @@ } }, "copyInCached": { - "tools/filelength": "tools/filelength" + "tools/file-length": "tools/file-length" }, "copyInDir": ".", "copyOut": [], @@ -410,48 +345,26 @@ "parsers": [ { "name": "keyword", - "with": { - "matches": [ - { - "keywords": [ - "recommended" - ], - "score": 10 - }, - { - "keywords": [ - "max" - ], - "score": 20 - } - ] - } + "with": {} }, { "name": "dummy", - "with": { - "score": 0, - "comment": "", - "forceQuitOnNotAccepted": true - } + "with": {} }, { "name": "result-detail", "with": { - "score": 0, - "comment": "", - "showFiles": [ - "stdout" - ], - "showExitStatus": true, - "showRuntime": false, - "showMemory": false + "time": false, + "mem": false, + "stdout": false, + "stderr": true, + "exitstatus": false } } ] }, { - "name": "[cq] Clang-tidy", + "name": "Clang-tidy checks", "group": null, "executor": { "name": "sandbox", @@ -484,7 +397,7 @@ "content": null, "fileId": null, "name": "stdout", - "max": 65000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -495,7 +408,7 @@ "content": null, "fileId": null, "name": "stderr", - "max": 4000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -509,22 +422,8 @@ "procLimit": 50, "cpuRateLimit": 0, "cpuSetLimit": "", - "copyIn": { - "projects/p2/.clang-tidy": { - "src": "/home/tt/.config/joj/projects/p2/.clang-tidy", - "content": null, - "fileId": null, - "name": null, - "max": 4194304, - "symlink": null, - "streamIn": false, - "streamOut": false, - "pipe": false - } - }, - "copyInCached": { - "projects/p2/.clang-tidy": "projects/p2/.clang-tidy" - }, + "copyIn": {}, + "copyInCached": {}, "copyInDir": ".", "copyOut": [], "copyOutCached": [], @@ -541,74 +440,26 @@ "parsers": [ { "name": "clangtidy", - "with": { - "matches": [ - { - "keywords": [ - "readability-function-size" - ], - "score": 10 - }, - { - "keywords": [ - "codequality-no-global-variables", - "codequality-no-header-guard", - "codequality-no-fflush-stdin" - ], - "score": 20 - }, - { - "keywords": [ - "codequality-unchecked-malloc-result", - "readability-duplicate-include", - "readability-identifier-naming", - "readability-redundant", - "readability-misplaced-array-index", - "cppcoreguidelines-init-variables", - "bugprone-suspicious-string-compare", - "google-global-names-in-headers", - "clang-diagnostic", - "clang-analyzer", - "misc", - "performance", - "portability" - ], - "score": 5 - }, - { - "keywords": [ - "readability-misleading-indentation" - ], - "score": 15 - } - ] - } + "with": {} }, { "name": "dummy", - "with": { - "score": 0, - "comment": "", - "forceQuitOnNotAccepted": true - } + "with": {} }, { "name": "result-detail", "with": { - "score": 0, - "comment": "", - "showFiles": [ - "stdout" - ], - "showExitStatus": true, - "showRuntime": false, - "showMemory": false + "time": false, + "mem": false, + "stdout": true, + "stderr": false, + "exitstatus": true } } ] }, { - "name": "[cq] Cppcheck", + "name": "Cppcheck check", "group": null, "executor": { "name": "sandbox", @@ -616,10 +467,13 @@ "default": { "args": [ "cppcheck", - "--template={\"file\":\"{file}\",\"line\":{line}, \"column\":{column}, \"severity\":\"{severity}\", \"message\":\"{message}\", \"id\":\"{id}\"}", + "--template='{\"file\":\"{file}\",\"line\":{line},", + "\"column\":{column},", + "\"severity\":\"{severity}\",", + "\"message\":\"{message}\",", + "\"id\":\"{id}\"}'", "--force", "--enable=all", - "--suppress=missingIncludeSystem", "--quiet", "./" ], @@ -642,7 +496,7 @@ "content": null, "fileId": null, "name": "stdout", - "max": 4000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -653,7 +507,7 @@ "content": null, "fileId": null, "name": "stderr", - "max": 65000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -685,51 +539,26 @@ "parsers": [ { "name": "cppcheck", - "with": { - "matches": [ - { - "keywords": [ - "warning", - "portability", - "performance", - "style" - ], - "score": 5 - }, - { - "keywords": [ - "error" - ], - "score": 15 - } - ] - } + "with": {} }, { "name": "dummy", - "with": { - "score": 0, - "comment": "", - "forceQuitOnNotAccepted": true - } + "with": {} }, { "name": "result-detail", "with": { - "score": 0, - "comment": "", - "showFiles": [ - "stderr" - ], - "showExitStatus": true, - "showRuntime": false, - "showMemory": false + "time": false, + "mem": false, + "stdout": false, + "stderr": true, + "exitstatus": true } } ] }, { - "name": "[cq] Cpplint", + "name": "Cpplint check", "group": null, "executor": { "name": "sandbox", @@ -762,7 +591,7 @@ "content": null, "fileId": null, "name": "stdout", - "max": 65000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -773,7 +602,7 @@ "content": null, "fileId": null, "name": "stderr", - "max": 4000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -805,65 +634,34 @@ "parsers": [ { "name": "cpplint", - "with": { - "score": 0, - "comment": "", - "forceQuitOnNotAccepted": true, - "matches": [ - { - "keywords": [ - "build" - ], - "score": 10 - }, - { - "keywords": [ - "readability" - ], - "score": 20 - }, - { - "keywords": [ - "runtime" - ], - "score": 5 - } - ] - } + "with": {} }, { "name": "dummy", - "with": { - "score": 0, - "comment": "", - "forceQuitOnNotAccepted": true - } + "with": {} }, { "name": "result-detail", "with": { - "score": 0, - "comment": "", - "showFiles": [ - "stderr" - ], - "showExitStatus": true, - "showRuntime": false, - "showMemory": false + "time": false, + "mem": false, + "stdout": true, + "stderr": false, + "exitstatus": true } } ] }, { - "name": "[run] onecard", - "group": null, + "name": "judge-base", + "group": "joj", "executor": { "name": "sandbox", "with": { "default": { "args": [ - "./onecard", - "-a" + "./driver", + "./mumsh" ], "env": [ "PATH=/usr/bin:/bin:/usr/local/bin" @@ -884,7 +682,7 @@ "content": null, "fileId": null, "name": "stdout", - "max": 4000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -895,7 +693,7 @@ "content": null, "fileId": null, "name": "stderr", - "max": 4000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -926,38 +724,35 @@ }, "parsers": [ { - "name": "result-status", - "with": { - "score": 1, - "comment": "", - "forceQuitOnNotAccepted": false - } + "name": "diff", + "with": {} + }, + { + "name": "dummy", + "with": {} }, { "name": "result-detail", "with": { - "score": 0, - "comment": "", - "showFiles": [ - "stderr" - ], - "showExitStatus": true, - "showRuntime": true, - "showMemory": true + "time": true, + "mem": true, + "stdout": false, + "stderr": true, + "exitstatus": true } } ] }, { - "name": "[run] address sanitizer", - "group": null, + "name": "judge-msan", + "group": "joj", "executor": { "name": "sandbox", "with": { "default": { "args": [ - "./asan", - "-a" + "./driver", + "./mumsh-msan" ], "env": [ "PATH=/usr/bin:/bin:/usr/local/bin" @@ -978,7 +773,7 @@ "content": null, "fileId": null, "name": "stdout", - "max": 4000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -989,7 +784,7 @@ "content": null, "fileId": null, "name": "stderr", - "max": 4000000000, + "max": 4096, "symlink": null, "streamIn": false, "streamOut": false, @@ -1020,212 +815,21 @@ }, "parsers": [ { - "name": "result-status", - "with": { - "score": 1, - "comment": "", - "forceQuitOnNotAccepted": false - } + "name": "diff", + "with": {} + }, + { + "name": "dummy", + "with": {} }, { "name": "result-detail", "with": { - "score": 0, - "comment": "", - "showFiles": [ - "stderr" - ], - "showExitStatus": true, - "showRuntime": true, - "showMemory": true - } - } - ] - }, - { - "name": "[run] memory sanitizer", - "group": null, - "executor": { - "name": "sandbox", - "with": { - "default": { - "args": [ - "./msan", - "-a" - ], - "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": {}, - "copyInCached": {}, - "copyInDir": ".", - "copyOut": [], - "copyOutCached": [], - "copyOutMax": 0, - "copyOutDir": "", - "tty": false, - "strictMemoryLimit": false, - "dataSegmentLimit": false, - "addressSpaceLimit": false - }, - "cases": [] - } - }, - "parsers": [ - { - "name": "result-status", - "with": { - "score": 1, - "comment": "", - "forceQuitOnNotAccepted": false - } - }, - { - "name": "result-detail", - "with": { - "score": 0, - "comment": "", - "showFiles": [ - "stderr" - ], - "showExitStatus": true, - "showRuntime": true, - "showMemory": true - } - } - ] - }, - { - "name": "[run] undefined behavior sanitizer", - "group": null, - "executor": { - "name": "sandbox", - "with": { - "default": { - "args": [ - "./ubsan", - "-a" - ], - "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": {}, - "copyInCached": {}, - "copyInDir": ".", - "copyOut": [], - "copyOutCached": [], - "copyOutMax": 0, - "copyOutDir": "", - "tty": false, - "strictMemoryLimit": false, - "dataSegmentLimit": false, - "addressSpaceLimit": false - }, - "cases": [] - } - }, - "parsers": [ - { - "name": "result-status", - "with": { - "score": 1, - "comment": "", - "forceQuitOnNotAccepted": false - } - }, - { - "name": "result-detail", - "with": { - "score": 0, - "comment": "", - "showFiles": [ - "stderr" - ], - "showExitStatus": true, - "showRuntime": true, - "showMemory": true + "time": true, + "mem": true, + "stdout": false, + "stderr": true, + "exitstatus": true } } ] @@ -1233,10 +837,10 @@ ] }, "teapot": { - "logPath": "/home/tt/.cache/joint-teapot-debug.log", - "scoreboardPath": "scoreboard.csv", - "failedTablePath": "failed-table.md", - "gradingRepoName": "", + "logPath": "Homework-1-exercise-2-joint-teapot-debug.log", + "scoreboardPath": "Homework-1-exercise-2-scoreboard.csv", + "failedTablePath": "Homework-1-exercise-2-failed-table.md", + "gradingRepoName": "engr151-joj", "skipIssue": false, "skipScoreboard": false, "skipFailedTable": false diff --git a/tests/convert/basic/task.toml b/tests/convert/basic/task.toml index 118247d..ef299a4 100644 --- a/tests/convert/basic/task.toml +++ b/tests/convert/basic/task.toml @@ -1,31 +1,20 @@ -# p2 repo config - -task="p2 m3" # task name +# general task configuration +task="Homework 1 exercise 2" # task name release.deadline = 2024-10-12 23:59:00+08:00 release.stages = [ "compile" ] -[files] -immutable = [".gitignore", ".gitattributes", ".gitea/workflows/push.yaml", ".gitea/workflows/release.yaml" ] -required = [ "Changelog.md", "Readme.md" ] - -[[stages]] -name = "Abuse of strings detected" -command = "./strdetect src/" -files.import = [ "tools/strdetec" ] - -parsers = [ "result-status" ] - - [[stages]] name = "Compilation" -command = "compile" -files.import = [ "tools/compile" ] -files.export = [ "build/onecard", "build/asan", "build/ubsan", "build/msan", "build/compile_commands.json" ] +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." -result-status.score = 1 dummy.comment = "\n\n### Details\n" result-detail.exitstatus = true result-detail.stderr = true @@ -33,28 +22,26 @@ result-detail.time = false result-detail.mem = false [[stages]] -name = "[cq] Filelength" -command = "./file-length 400 300 *.c *.h" -files.import = [ "tools/filelength" ] +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", "recommended"] -keyword.weight = [ 20, 10 ] -dummy.comment = "\n\n### Details\n" -result-detail.exitstatus = true -result-detail.stdout = true +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 = "[cq] Clang-tidy" +name = "Clang-tidy checks" command = "run-clang-tidy-18 -header-filter=.* -quiet -load=/usr/local/lib/libcodequality.so -p build" -files.import = [ "projects/p2/.clang-tidy", "build/compile_commands.json" ] limit.stdout = 65 parsers = [ "clangtidy", "dummy", "result-detail" ] -clangtidy.keyword = [ "codequality-unchecked-malloc-result", "codequality-no-global-variables", "codequality-no-header-guard", "codequality-no-fflush-stdin", "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", "portability" ] -clangtidy.weight = [ 5, 20, 20, 20, 10, 5, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5] +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, 8] dummy.comment = "\n\n### Details\n" result-detail.exitstatus = true result-detail.stdout = true @@ -62,13 +49,13 @@ result-detail.time = false result-detail.mem = false [[stages]] -name = "[cq] Cppcheck" -command = "cppcheck --template='{\"file\":\"{file}\",\"line\":{line}, \"column\":{column}, \"severity\":\"{severity}\", \"message\":\"{message}\", \"id\":\"{id}\"}' --force --enable=all --suppress=missingIncludeSystem --quiet ./" +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 = [15, 5, 5, 5, 5] +cppcheck.weight = [20, 10, 15, 15, 10] dummy.comment = "\n\n### Details\n" result-detail.exitstatus = true result-detail.stderr = true @@ -76,62 +63,57 @@ result-detail.time = false result-detail.mem = false [[stages]] -name = "[cq] Cpplint" +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 = [ 5, 20, 10] +cpplint.weight = [ 10, 20, 15] dummy.comment = "\n\n### Details\n" result-detail.exitstatus = true -result-detail.stderr = true +result-detail.stdout = true result-detail.time = false result-detail.mem = false [[stages]] -name = "[run] onecard" -group = "run" -command="./onecard -a" -files.import = [ "build/onecard" ] +name = "judge-base" +command="./driver ./mumsh" +limit.cpu = 3 +limit.mem = 75 +score = 10 -parsers = [ "result-status", "result-detail" ] -result-status.score = 1 -result-status.forcequit = false +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 = "[run] address sanitizer" -group = "run" -command="./asan -a" -files.import = [ "build/asan" ] +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 = [ "result-status", "result-detail" ] -result-status.score = 1 -result-status.forcequit = false +parsers = ["diff", "dummy", "result-detail"] +dummy.comment = "\n\n### Details\n" result-detail.exitstatus = true result-detail.stderr = true -[[stages]] -name = "[run] memory sanitizer" -group = "run" -command="./msan -a" -files.import = [ "build/msan" ] +case4.score = 15 +case4.limit.cpu = 30 +case4.limit.mem = 10 -parsers = [ "result-status", "result-detail" ] -result-status.score = 1 -result-status.forcequit = false -result-detail.exitstatus = true -result-detail.stderr = true +case5.diff.output.ignorespaces = false -[[stages]] -name = "[run] undefined behavior sanitizer" -command="./ubsan -a" -files.import = [ "build/ubsan" ] - -parsers = [ "result-status", "result-detail" ] -result-status.score = 1 -result-status.forcequit = false -result-detail.exitstatus = true -result-detail.stderr = true +case6.diff.output.hide = true