dev #10

Merged
李衍志523370910113 merged 238 commits from dev into master 2025-03-05 16:20:39 +08:00
13 changed files with 1156 additions and 132 deletions
Showing only changes of commit fe620d710e - Show all commits

2
.gitignore vendored
View File

@ -15,7 +15,7 @@ dist/
downloads/
eggs/
.eggs/
lib/
# lib/
jon-lee marked this conversation as resolved Outdated

should be ignored

should be ignored

fixed

fixed
lib64/
parts/
sdist/

View File

@ -1,6 +1,20 @@
from typing import List
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
@ -8,7 +22,8 @@ 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
@ -16,8 +31,14 @@ def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config:
),
stage=result.Stage(stages=[], sandbox_token=repo_conf.sandbox_token),
jon-lee marked this conversation as resolved Outdated

Make this Path.home() default to /home/tt. For now, create a const for this dir.

Make this `Path.home()` default to `/home/tt`. For now, create a const for this dir.

fixed

fixed
teapot=result.Teapot(),
stage=StageConfig(stages=[], sandbox_token=repo_conf.sandbox_token),
teapot=getTeapotConfig(repo_conf, task_conf),
)
jon-lee marked this conversation as resolved Outdated

where is it used?

where is it used?

this should be storing all the files that are about to be copy in or out

this should be storing all the files that are about to be copy in or out

It is as the input and output for the following functions about parsers

It is as the input and output for the following functions about parsers

so this feature is not implemented?

so this feature is not implemented?
    if not repo_conf.force_skip_health_check_on_test or not current_test:
        result_conf.stage.stages.append(get_health_check_config(repo_conf))
    cached: List[str] = []
    # Convert each stage in the task configuration
    for task_stage in task_conf.stages:
        executor_with_config, cached = get_executor_with_config(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_file(task_stage, conf_stage)
        conf_stage = fix_diff(task_stage, conf_stage, task_conf)
        result_conf.stage.stages.append(conf_stage)

it is

    for task_stage in task_conf.stages:
        executor_with_config, cached = get_executor_with_config(task_stage, cached)

this is a loop, so this cached will be updated in every round of stage

```python if not repo_conf.force_skip_health_check_on_test or not current_test: result_conf.stage.stages.append(get_health_check_config(repo_conf)) cached: List[str] = [] # Convert each stage in the task configuration for task_stage in task_conf.stages: executor_with_config, cached = get_executor_with_config(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_file(task_stage, conf_stage) conf_stage = fix_diff(task_stage, conf_stage, task_conf) result_conf.stage.stages.append(conf_stage) ``` it is ```python for task_stage in task_conf.stages: executor_with_config, cached = get_executor_with_config(task_stage, cached) ``` this is a loop, so this `cached` will be updated in every round of stage

The return value is unnecessary.

The return value is unnecessary.

I have a lazing coding style here, everything has get imported would get exported, so should maintain this until the end of the loop. Everything is exported in previous stage would be imported in the next stage.

I have a lazing coding style here, everything has get imported would get exported, so should maintain this until the end of the loop. Everything is exported in previous stage would be imported in the next stage.
  1. The return value is unnecessary
  2. It should be a set
1. The return value is unnecessary 2. It should be a `set`

try it yourself

try it yourself

I see why

I see why

resolved.

resolved.
# Construct healthcheck stage
healthcheck_stage = getHealthcheckConfig(repo_conf, task_conf)
result_conf.stage.stages.append(healthcheck_stage)
cached = []
# Convert each stage in the task configuration
for task_stage in task_conf.stages:
executor_with_config = result.ExecutorWith(
@ -41,12 +62,12 @@ def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config:
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)
if task_stage.result_detail is not None:
result_detail_parser.with_.update(task_stage.result_detail)
result_conf.stage.stages.append(conf_stage)

View File

@ -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

View File

@ -0,0 +1,123 @@
import hashlib
import os
import tempfile
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:
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, 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",
failed_table_path=f"{task_conf.task.replace(' ', '-')}-failed-table.md",
grading_repo_name=getGradingRepoName(),
)
return teapot
def getHealthcheckCmd(repo_conf: Repo) -> 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"/{get_temp_directory}/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 = Cmd(
args=args.split(),
# FIXME: easier to edit within global scope
copy_in={
f"/{get_temp_directory()}/repo-health-checker": CmdFile(
src=f"/{get_temp_directory()}/repo-health-checker"
)
},
)
return cmd
def getHealthcheckConfig(repo_conf: Repo, task_conf: Task) -> Stage:
healthcheck_stage = Stage(
name="healthcheck",
group="",
executor=ExecutorConfig(
name="sandbox",
with_=ExecutorWithConfig(default=getHealthcheckCmd(repo_conf), cases=[]),
),
parsers=[ParserConfig(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

View File

@ -8,7 +8,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")
@ -16,17 +16,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")
jon-lee marked this conversation as resolved Outdated

default value too large, should be 1s 128MB

default value too large, should be 1s 128MB

will fix later, we need to hold some test I reckon?

will fix later, we need to hold some test I reckon?

@bomingzh fixed

@bomingzh fixed
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")
jon-lee marked this conversation as resolved Outdated

unit?

unit?

I think timeparse and humanfriendly would deal wth that?

I think `timeparse` and `humanfriendly` would deal wth that?

resolved.

resolved.
cpu_set_limit: str = Field("", serialization_alias="cpuSetLimit")
copy_in: Dict[str, CmdFile] = Field({}, serialization_alias="copyIn")
@ -43,17 +43,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")
jon-lee marked this conversation as resolved Outdated

What is the conclusion?

What is the conclusion?

should be already solved.

should be already solved.

View File

@ -5,26 +5,50 @@ from pydantic import BaseModel, Field
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] = ""
class ParserKeyword(BaseModel):
keyword: Optional[list[str]] = None
weight: Optional[list[int]] = None
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
files: Optional[Files] = None
score: Optional[int] = 0
parsers: list[str] # list of parsers
limit: Optional[Limit] = None
dummy: Optional[ParserDummy] = ParserDummy()
keyword: Optional[ParserKeyword] = ParserKeyword()
clangtidy: Optional[ParserKeyword] = ParserKeyword()
cppcheck: Optional[ParserKeyword] = ParserKeyword()
cpplint: Optional[ParserKeyword] = ParserKeyword()
result_detail: Optional[ParserResultDetail] = Field(
ParserResultDetail(), alias="result-detail"
)
class Release(BaseModel):

View File

@ -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 = [".gitignore", ".gitattributes", "push.yaml", "release.yaml"]

View File

@ -1,53 +1,79 @@
{
"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=a5b63323a692d3d8b952442969649b4f823d58dae26429494f613df160710dfc,b1bbad25b830db0a77b15a033f9ca1b7ab44c1d2d05056412bd3e4421645f0bf,8d1229900c6fc6711b5cc141d1ab5ea7f5b7b7a4b921d9cfa3957408b43ae723,eb857bcd94857cedc4045cb2d6ba04cb5bbb3daf188abc95fb9478db823ef47e",
"-checkFileNameList=.gitignore,.gitattributes,push.yaml,release.yaml"
],
"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,9 +83,139 @@
"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": 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": {
"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": [
"output/ex5_results.txt",
"output/ex5_logs.txt"
"driver",
"p2",
"p2-msan"
],
"copyOutMax": 0,
"copyOutDir": "",
@ -73,7 +229,119 @@
},
"parsers": [
{
"name": "diff",
"name": "result-detail",
"with": {
"time": false,
"mem": false,
"stdout": false,
"stderr": true,
"exitstatus": true
}
},
{
"name": "dummy",
"with": {}
},
{
"name": "result-status",
"with": {}
}
]
},
{
"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": 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": {
"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": {}
},
{
"name": "dummy",
"with": {}
},
{
@ -82,65 +350,361 @@
"time": false,
"mem": false,
"stdout": false,
"stderr": true
"stderr": true,
"exitstatus": false
}
}
]
},
{
"name": "judge_base2",
"group": "hw3 ex5",
"name": "Clang-tidy checks",
"group": null,
"executor": {
"name": "sandbox",
"with": {
"default": {
"args": [
"./matlab-joj",
"./h3/ex5.m"
"run-clang-tidy-18",
"-header-filter=.*",
"-quiet",
"-load=/usr/local/lib/libcodequality.so",
"-p",
"build"
],
"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",
"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,
"symlink": null,
"streamIn": false,
"streamOut": false,
"pipe": false
}
},
"copyIn": {},
"copyInCached": {},
"copyInDir": ".",
"copyOut": [],
"copyOutCached": [
"output/ex5_results2.txt",
"output/ex5_logs2.txt"
"copyOutCached": [],
"copyOutMax": 0,
"copyOutDir": "",
"tty": false,
"strictMemoryLimit": false,
"dataSegmentLimit": false,
"addressSpaceLimit": false
},
"cases": []
}
},
"parsers": [
{
"name": "clangtidy",
"with": {}
},
{
"name": "dummy",
"with": {}
},
{
"name": "result-detail",
"with": {
"time": false,
"mem": false,
"stdout": true,
"stderr": false,
"exitstatus": true
}
}
]
},
{
"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": 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": {},
"copyInCached": {},
"copyInDir": ".",
"copyOut": [],
"copyOutCached": [],
"copyOutMax": 0,
"copyOutDir": "",
"tty": false,
"strictMemoryLimit": false,
"dataSegmentLimit": false,
"addressSpaceLimit": false
},
"cases": []
}
},
"parsers": [
{
"name": "cppcheck",
"with": {}
},
{
"name": "dummy",
"with": {}
},
{
"name": "result-detail",
"with": {
"time": false,
"mem": false,
"stdout": false,
"stderr": true,
"exitstatus": true
}
}
]
},
{
"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": 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": {},
"copyInCached": {},
"copyInDir": ".",
"copyOut": [],
"copyOutCached": [],
"copyOutMax": 0,
"copyOutDir": "",
"tty": false,
"strictMemoryLimit": false,
"dataSegmentLimit": false,
"addressSpaceLimit": false
},
"cases": []
}
},
"parsers": [
{
"name": "cpplint",
"with": {}
},
{
"name": "dummy",
"with": {}
},
{
"name": "result-detail",
"with": {
"time": false,
"mem": false,
"stdout": true,
"stderr": false,
"exitstatus": true
}
}
]
},
{
"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": 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": {},
"copyInCached": {},
"copyInDir": ".",
"copyOut": [],
"copyOutCached": [],
"copyOutMax": 0,
"copyOutDir": "",
"tty": false,
@ -156,13 +720,109 @@
"name": "diff",
"with": {}
},
{
"name": "dummy",
"with": {}
},
{
"name": "result-detail",
"with": {
"time": true,
"mem": true,
"stdout": false,
"stderr": false
"stderr": true,
"exitstatus": 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": 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": {},
"copyInCached": {},
"copyInDir": ".",
"copyOut": [],
"copyOutCached": [],
"copyOutMax": 0,
"copyOutDir": "",
"tty": false,
"strictMemoryLimit": false,
"dataSegmentLimit": false,
"addressSpaceLimit": false
},
"cases": []
}
},
"parsers": [
{
"name": "diff",
"with": {}
},
{
"name": "dummy",
"with": {}
},
{
"name": "result-detail",
"with": {
"time": true,
"mem": true,
"stdout": false,
"stderr": true,
"exitstatus": true
}
}
]
@ -170,10 +830,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

View File

@ -1,30 +1,119 @@
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."
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 = false
result-detail.stderr = true
result-detail.time = false
result-detail.mem = false
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, 8]
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 ."
jon-lee marked this conversation as resolved Outdated

is it used?

is it used?

testcases in basic is intend to show a comprehensive situation.

testcases in basic is intend to show a comprehensive situation.

if unused, leave a comment

if unused, leave a comment

Then why is there a stdout field in class Limit

Then why is there a `stdout` field in `class Limit`

@bomingzh in toml now should we accept both 32m and 32 or just 32m now?

@bomingzh in toml now should we accept both `32m` and `32` or just `32m` now?

I reckon only 32m would be good

I reckon only `32m` would be good

yes, just str

yes, just str
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

33
tests/immutable_file/.gitattributes vendored Normal file
View File

@ -0,0 +1,33 @@
*.avi filter=lfs diff=lfs merge=lfs -text
jon-lee marked this conversation as resolved Outdated

are these files ready to be tested? or are they just examples?

are these files ready to be tested? or are they just examples?

they are just examples

they are just examples
*.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

23
tests/immutable_file/.gitignore vendored Normal file
View File

@ -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

View File

@ -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

View File

@ -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 }}"