feat: support convert
(#10)
All checks were successful
build / build (push) Successful in 2m18s
All checks were successful
build / build (push) Successful in 2m18s
- basic generation of json files - supported parsers: - healthcheck - result-detail - result-status - file - log - dummy - keyword (keyword, clangtidy, cppcheck, cpplint) - diff - `convert` functions is mature, tested in engr151-24fa last two homeworks and engr151-24fa p3 - teapot and healthcheck should be up to date Co-authored-by: Boming Zhang <bomingzh@sjtu.edu.cn> Reviewed-on: #10 Reviewed-by: Boming Zhang <bomingzh@sjtu.edu.cn> Co-authored-by: jon-lee <jon-lee@sjtu.edu.cn> Co-committed-by: jon-lee <jon-lee@sjtu.edu.cn>
This commit is contained in:
parent
f5b7563869
commit
18df2ef1c0
22
README.md
22
README.md
|
@ -16,3 +16,25 @@
|
||||||
4. Install deps by `pdm install && pdm run pre-commit install`
|
4. Install deps by `pdm install && pdm run pre-commit install`
|
||||||
5. Run the cli app by `pdm run app --help`
|
5. Run the cli app by `pdm run app --help`
|
||||||
6. Check other commands or scripts with `pdm run --list`
|
6. Check other commands or scripts with `pdm run --list`
|
||||||
|
|
||||||
|
## How to use?
|
||||||
|
|
||||||
|
- `joj3-config-generator convert` function is now supported, currently support one argument as input, it indicates the **convert root**
|
||||||
|
- default value on the server can be given as `/home/tt/.config/joj`
|
||||||
|
- **NOTE:** the user should ensure that the ideal `repo.toml` file is in the sub-directory of the **convert root**
|
||||||
|
- the intended immutable files should be placed at a sub-directory named `immutable_files` at same position as the `repo.toml` file
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ tree .
|
||||||
|
.
|
||||||
|
|- immutable_files
|
||||||
|
| |-- push.yaml
|
||||||
|
| |-- release.yaml
|
||||||
|
|-- repo.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
- sample command on the server
|
||||||
|
|
||||||
|
```shell
|
||||||
|
joj3-config-generator convert /home/tt/.config/joj
|
||||||
|
```
|
||||||
|
|
|
@ -1,93 +1,41 @@
|
||||||
from typing import List
|
import os
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
from joj3_config_generator.models import joj1, repo, result, task
|
from joj3_config_generator.models import joj1, repo, result, task
|
||||||
|
from joj3_config_generator.models.const import CACHE_ROOT, JOJ3_CONFIG_ROOT
|
||||||
|
from joj3_config_generator.processers.repo import (
|
||||||
|
get_health_check_stage,
|
||||||
|
get_teapot_stage,
|
||||||
|
)
|
||||||
|
from joj3_config_generator.processers.task import get_conf_stage
|
||||||
|
|
||||||
|
|
||||||
# FIXME: LLM generated convert function, only for demostration
|
|
||||||
def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config:
|
def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config:
|
||||||
# Create the base ResultConf object
|
# Create the base ResultConf object
|
||||||
result_conf = result.Config(
|
result_conf = result.Config(
|
||||||
name=task_conf.task,
|
name=task_conf.task.name,
|
||||||
log_path=f"{task_conf.task.replace(' ', '_')}.log",
|
# exact folder difference specified by type
|
||||||
expire_unix_timestamp=(
|
log_path=str(CACHE_ROOT / "joj3" / f"{task_conf.task.type_}.log"),
|
||||||
int(task_conf.release.deadline.timestamp())
|
expire_unix_timestamp=int(task_conf.release.end_time.timestamp()),
|
||||||
if task_conf.release.deadline
|
effective_unix_timestamp=int(task_conf.release.begin_time.timestamp()),
|
||||||
else -1
|
actor_csv_path=str(JOJ3_CONFIG_ROOT / "students.csv"), # students.csv position
|
||||||
),
|
max_total_score=repo_conf.max_total_score,
|
||||||
stage=result.Stage(stages=[], sandbox_token=repo_conf.sandbox_token),
|
stage=result.Stage(sandbox_token=repo_conf.sandbox_token),
|
||||||
teapot=result.Teapot(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
current_test = os.environ.get("PYTEST_CURRENT_TEST") is not None
|
||||||
|
# Construct health check stage
|
||||||
|
if not repo_conf.force_skip_health_check_on_test or not current_test:
|
||||||
|
result_conf.stage.stages.append(get_health_check_stage(repo_conf))
|
||||||
|
cached: Dict[str, None] = {}
|
||||||
# Convert each stage in the task configuration
|
# Convert each stage in the task configuration
|
||||||
for task_stage in task_conf.stages:
|
for task_stage in task_conf.stages:
|
||||||
executor_with_config = result.ExecutorWith(
|
result_conf.stage.stages.append(get_conf_stage(task_conf, task_stage, cached))
|
||||||
default=result.Cmd(
|
if not repo_conf.force_skip_teapot_on_test or not current_test:
|
||||||
args=task_stage.command.split(),
|
result_conf.stage.post_stages.append(get_teapot_stage(repo_conf))
|
||||||
copy_in={
|
|
||||||
file: result.LocalFile(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)
|
|
||||||
|
|
||||||
result_conf.stage.stages.append(conf_stage)
|
|
||||||
|
|
||||||
return result_conf
|
return result_conf
|
||||||
|
|
||||||
|
|
||||||
# FIXME: LLM generated convert function, only for demostration
|
|
||||||
def convert_joj1(joj1_conf: joj1.Config) -> task.Config:
|
def convert_joj1(joj1_conf: joj1.Config) -> task.Config:
|
||||||
stages = []
|
return task.Config()
|
||||||
for language in joj1_conf.languages:
|
|
||||||
# Here you might want to create a stage for each language
|
|
||||||
# You can define a command based on language properties
|
|
||||||
command = f"run {language.language}"
|
|
||||||
# Assuming we don't have explicit files, we will set empty ones or default behavior
|
|
||||||
files = task.Files(import_=[], export=[])
|
|
||||||
# Score can be derived from the first case or set to a default
|
|
||||||
score = 0
|
|
||||||
parsers: List[str] = [] # Define parsers if applicable
|
|
||||||
if joj1_conf.cases:
|
|
||||||
score = sum(
|
|
||||||
case.score for case in joj1_conf.cases
|
|
||||||
) # Sum scores for all cases
|
|
||||||
# Creating a stage for each language
|
|
||||||
stages.append(
|
|
||||||
task.Stage(
|
|
||||||
name=language.language,
|
|
||||||
command=command,
|
|
||||||
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
|
|
||||||
release_deadline = (
|
|
||||||
None # Placeholder for future implementation if deadlines are defined
|
|
||||||
)
|
|
||||||
|
|
||||||
return task.Config(
|
|
||||||
task=joj1_conf.languages[0].language if joj1_conf.languages else "Unnamed Task",
|
|
||||||
release=task.Release(deadline=release_deadline),
|
|
||||||
stages=stages,
|
|
||||||
)
|
|
||||||
|
|
39
joj3_config_generator/load.py
Normal file
39
joj3_config_generator/load.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, Tuple
|
||||||
|
|
||||||
|
import inquirer
|
||||||
|
import rtoml
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
from joj3_config_generator.models import joj1, repo, task
|
||||||
|
|
||||||
|
|
||||||
|
def load_joj3_toml_answers() -> Dict[str, str]:
|
||||||
|
questions = [
|
||||||
|
inquirer.List(
|
||||||
|
"size",
|
||||||
|
message="What size do you need?",
|
||||||
|
choices=["Jumbo", "Large", "Standard", "Medium", "Small", "Micro"],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
answers = inquirer.prompt(questions)
|
||||||
|
return answers
|
||||||
|
|
||||||
|
|
||||||
|
def load_joj1_yaml(yaml_path: Path) -> joj1.Config:
|
||||||
|
joj1_obj = yaml.safe_load(yaml_path.read_text())
|
||||||
|
return joj1.Config(**joj1_obj)
|
||||||
|
|
||||||
|
|
||||||
|
def load_joj3_toml(
|
||||||
|
root_path: Path, repo_toml_path: Path, task_toml_path: Path
|
||||||
|
) -> Tuple[repo.Config, task.Config]:
|
||||||
|
repo_obj = rtoml.loads(repo_toml_path.read_text())
|
||||||
|
task_obj = rtoml.loads(task_toml_path.read_text())
|
||||||
|
repo_conf = repo.Config(**repo_obj)
|
||||||
|
repo_conf.root = root_path
|
||||||
|
repo_conf.path = repo_toml_path.relative_to(root_path)
|
||||||
|
task_conf = task.Config(**task_obj)
|
||||||
|
task_conf.root = root_path
|
||||||
|
task_conf.path = task_toml_path.relative_to(root_path)
|
||||||
|
return repo_conf, task_conf
|
|
@ -1,48 +1,44 @@
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import inquirer
|
|
||||||
import rtoml
|
import rtoml
|
||||||
import typer
|
import typer
|
||||||
import yaml
|
|
||||||
from typing_extensions import Annotated
|
from typing_extensions import Annotated
|
||||||
|
|
||||||
from joj3_config_generator.convert import convert as convert_conf
|
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.convert import convert_joj1 as convert_joj1_conf
|
||||||
from joj3_config_generator.models import joj1, repo, task
|
from joj3_config_generator.load import (
|
||||||
|
load_joj1_yaml,
|
||||||
|
load_joj3_toml,
|
||||||
|
load_joj3_toml_answers,
|
||||||
|
)
|
||||||
|
from joj3_config_generator.models.const import JOJ3_CONFIG_ROOT
|
||||||
from joj3_config_generator.utils.logger import logger
|
from joj3_config_generator.utils.logger import logger
|
||||||
|
|
||||||
app = typer.Typer(add_completion=False)
|
app = typer.Typer(add_completion=False)
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def create(toml: typer.FileTextWrite) -> None:
|
def create(toml_path: Path) -> None:
|
||||||
"""
|
"""
|
||||||
Create a new JOJ3 toml config file
|
Create a new JOJ3 toml config file
|
||||||
"""
|
"""
|
||||||
logger.info("Creating")
|
logger.info(f"Creating toml file {toml_path}")
|
||||||
questions = [
|
answers = load_joj3_toml_answers()
|
||||||
inquirer.List(
|
logger.debug(f"Got answers: {answers}")
|
||||||
"size",
|
toml_path.write_text(rtoml.dumps({}))
|
||||||
message="What size do you need?",
|
|
||||||
choices=["Jumbo", "Large", "Standard", "Medium", "Small", "Micro"],
|
|
||||||
),
|
|
||||||
]
|
|
||||||
answers = inquirer.prompt(questions)
|
|
||||||
logger.info(answers)
|
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def convert_joj1(yaml_file: typer.FileText, toml_file: typer.FileTextWrite) -> None:
|
def convert_joj1(yaml_path: Path, toml_path: Path) -> None:
|
||||||
"""
|
"""
|
||||||
Convert a JOJ1 yaml config file to JOJ3 toml config file
|
Convert a JOJ1 yaml config file to JOJ3 toml config file
|
||||||
"""
|
"""
|
||||||
logger.info(f"Converting yaml file {yaml_file}")
|
logger.info(f"Converting yaml file {yaml_path}")
|
||||||
joj1_obj = yaml.safe_load(yaml_file.read())
|
joj1_model = load_joj1_yaml(yaml_path)
|
||||||
joj1_model = joj1.Config(**joj1_obj)
|
|
||||||
task_model = convert_joj1_conf(joj1_model)
|
task_model = convert_joj1_conf(joj1_model)
|
||||||
result_dict = task_model.model_dump(by_alias=True)
|
result_dict = task_model.model_dump(mode="json", by_alias=True, exclude_none=True)
|
||||||
toml_file.write(rtoml.dumps(result_dict))
|
toml_path.write_text(rtoml.dumps(result_dict))
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
|
@ -50,8 +46,7 @@ def convert(
|
||||||
root: Annotated[
|
root: Annotated[
|
||||||
Path,
|
Path,
|
||||||
typer.Argument(
|
typer.Argument(
|
||||||
help="root directory of config files, "
|
help=f"root directory of config files, located at {JOJ3_CONFIG_ROOT} in JTC"
|
||||||
"located at /home/tt/.config/joj in JTC"
|
|
||||||
),
|
),
|
||||||
] = Path(".")
|
] = Path(".")
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -60,9 +55,7 @@ def convert(
|
||||||
"""
|
"""
|
||||||
logger.info(f"Converting files in {root.absolute()}")
|
logger.info(f"Converting files in {root.absolute()}")
|
||||||
for repo_toml_path in root.glob("**/repo.toml"):
|
for repo_toml_path in root.glob("**/repo.toml"):
|
||||||
repo_path = repo_toml_path.parent
|
for task_toml_path in repo_toml_path.parent.glob("**/*.toml"):
|
||||||
repo_obj = rtoml.loads(repo_toml_path.read_text())
|
|
||||||
for task_toml_path in repo_path.glob("**/*.toml"):
|
|
||||||
if repo_toml_path == task_toml_path:
|
if repo_toml_path == task_toml_path:
|
||||||
continue
|
continue
|
||||||
toml_name = task_toml_path.name.removesuffix(".toml")
|
toml_name = task_toml_path.name.removesuffix(".toml")
|
||||||
|
@ -70,15 +63,11 @@ def convert(
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Converting {repo_toml_path} & {task_toml_path} to {result_json_path}"
|
f"Converting {repo_toml_path} & {task_toml_path} to {result_json_path}"
|
||||||
)
|
)
|
||||||
task_obj = rtoml.loads(task_toml_path.read_text())
|
repo_conf, task_conf = load_joj3_toml(root, repo_toml_path, task_toml_path)
|
||||||
repo_conf = repo.Config(**repo_obj)
|
|
||||||
repo_conf.root = root
|
|
||||||
repo_conf.path = repo_toml_path.relative_to(root)
|
|
||||||
task_conf = task.Config(**task_obj)
|
|
||||||
task_conf.root = root
|
|
||||||
task_conf.path = task_toml_path.relative_to(root)
|
|
||||||
result_model = convert_conf(repo_conf, task_conf)
|
result_model = convert_conf(repo_conf, task_conf)
|
||||||
result_dict = result_model.model_dump(by_alias=True, exclude_none=True)
|
result_dict = result_model.model_dump(
|
||||||
|
mode="json", by_alias=True, exclude_none=True
|
||||||
|
)
|
||||||
with result_json_path.open("w") as result_file:
|
with result_json_path.open("w") as result_file:
|
||||||
json.dump(result_dict, result_file, ensure_ascii=False, indent=4)
|
json.dump(result_dict, result_file, ensure_ascii=False, indent=4)
|
||||||
result_file.write("\n")
|
result_file.write("\n")
|
||||||
|
|
19
joj3_config_generator/models/common.py
Normal file
19
joj3_config_generator/models/common.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
import humanfriendly
|
||||||
|
|
||||||
|
|
||||||
|
class Memory(int):
|
||||||
|
def __new__(cls, value: Union[str, int]) -> "Memory":
|
||||||
|
if isinstance(value, str):
|
||||||
|
parsed = humanfriendly.parse_size(value, binary=True)
|
||||||
|
return super().__new__(cls, parsed)
|
||||||
|
return super().__new__(cls, value)
|
||||||
|
|
||||||
|
|
||||||
|
class Time(int):
|
||||||
|
def __new__(cls, value: Union[str, int]) -> "Time":
|
||||||
|
if isinstance(value, str):
|
||||||
|
parsed = humanfriendly.parse_timespan(value) * 1_000_000_000 # ns
|
||||||
|
return super().__new__(cls, round(parsed))
|
||||||
|
return super().__new__(cls, value)
|
11
joj3_config_generator/models/const.py
Normal file
11
joj3_config_generator/models/const.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from joj3_config_generator.models.common import Memory, Time
|
||||||
|
|
||||||
|
DEFAULT_CPU_LIMIT = Time("1s")
|
||||||
|
DEFAULT_MEMORY_LIMIT = Memory("128m")
|
||||||
|
DEFAULT_FILE_LIMIT = Memory("32m")
|
||||||
|
|
||||||
|
JOJ3_CONFIG_ROOT = Path("/home/tt/.config/joj")
|
||||||
|
TEAPOT_CONFIG_ROOT = Path("/home/tt/.config/teapot")
|
||||||
|
CACHE_ROOT = Path("/home/tt/.cache")
|
|
@ -1,21 +1,29 @@
|
||||||
|
import socket
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional
|
from typing import List
|
||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
class Files(BaseModel):
|
class Files(BaseModel):
|
||||||
whitelist_patterns: List[str]
|
required: List[str] = []
|
||||||
whitelist_file: Optional[str]
|
immutable: List[str] = []
|
||||||
required: List[str]
|
|
||||||
immutable: List[str]
|
|
||||||
|
class Groups(BaseModel):
|
||||||
|
name: List[str] = []
|
||||||
|
max_count: List[int] = []
|
||||||
|
time_period_hour: List[int] = []
|
||||||
|
|
||||||
|
|
||||||
class Config(BaseModel):
|
class Config(BaseModel):
|
||||||
|
max_size: float = Field(10, ge=0)
|
||||||
|
files: Files = Files()
|
||||||
|
sandbox_token: str = Field("")
|
||||||
|
max_total_score: int = Field(100)
|
||||||
|
force_skip_health_check_on_test: bool = False
|
||||||
|
force_skip_teapot_on_test: bool = False
|
||||||
|
groups: Groups = Groups()
|
||||||
root: Path = Path(".")
|
root: Path = Path(".")
|
||||||
path: Path = Path("repo.toml")
|
path: Path = Path("repo.toml")
|
||||||
teaching_team: List[str]
|
grading_repo_name: str = f"{socket.gethostname().split('-')[0]}-joj"
|
||||||
max_size: float = Field(..., ge=0)
|
|
||||||
release_tags: List[str]
|
|
||||||
files: Files
|
|
||||||
sandbox_token: str
|
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||||
|
|
||||||
|
from joj3_config_generator.models.const import (
|
||||||
|
DEFAULT_CPU_LIMIT,
|
||||||
|
DEFAULT_FILE_LIMIT,
|
||||||
|
DEFAULT_MEMORY_LIMIT,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class LocalFile(BaseModel):
|
class LocalFile(BaseModel):
|
||||||
|
@ -17,7 +23,7 @@ class PreparedFile(BaseModel):
|
||||||
|
|
||||||
class Collector(BaseModel):
|
class Collector(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
max: int
|
max: int = DEFAULT_FILE_LIMIT
|
||||||
pipe: bool = True
|
pipe: bool = True
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,27 +39,26 @@ class StreamOut(BaseModel):
|
||||||
stream_out: bool = Field(..., alias="streamOut")
|
stream_out: bool = Field(..., alias="streamOut")
|
||||||
|
|
||||||
|
|
||||||
InputFile = Union[LocalFile | MemoryFile | PreparedFile | Symlink]
|
InputFile = Union[LocalFile, MemoryFile, PreparedFile, Symlink]
|
||||||
|
|
||||||
|
|
||||||
class Cmd(BaseModel):
|
class Cmd(BaseModel):
|
||||||
args: List[str]
|
args: List[str] = []
|
||||||
env: List[str] = []
|
env: List[str] = []
|
||||||
stdin: Optional[Union[InputFile | StreamIn]] = None
|
stdin: Union[InputFile, StreamIn] = MemoryFile(content="")
|
||||||
stdout: Optional[Union[Collector | StreamOut]] = None
|
stdout: Union[Collector, StreamOut] = Collector(name="stdout")
|
||||||
stderr: Optional[Union[Collector | StreamOut]] = None
|
stderr: Union[Collector, StreamOut] = Collector(name="stderr")
|
||||||
cpu_limit: int = Field(0, serialization_alias="cpuLimit")
|
cpu_limit: int = Field(DEFAULT_CPU_LIMIT, serialization_alias="cpuLimit")
|
||||||
real_cpu_limit: int = Field(0, serialization_alias="realCpuLimit")
|
clock_limit: int = Field(2 * DEFAULT_CPU_LIMIT, serialization_alias="clockLimit")
|
||||||
clock_limit: int = Field(0, serialization_alias="clockLimit")
|
memory_limit: int = Field(DEFAULT_MEMORY_LIMIT, serialization_alias="memoryLimit")
|
||||||
memory_limit: int = Field(0, serialization_alias="memoryLimit")
|
|
||||||
stack_limit: int = Field(0, serialization_alias="stackLimit")
|
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_rate_limit: int = Field(0, serialization_alias="cpuRateLimit")
|
||||||
cpu_set_limit: str = Field("", serialization_alias="cpuSetLimit")
|
cpu_set_limit: str = Field("", serialization_alias="cpuSetLimit")
|
||||||
copy_in: Dict[str, InputFile] = Field({}, serialization_alias="copyIn")
|
copy_in: Dict[str, InputFile] = Field({}, serialization_alias="copyIn")
|
||||||
copy_in_cached: Dict[str, str] = Field({}, serialization_alias="copyInCached")
|
copy_in_cached: Dict[str, str] = Field({}, serialization_alias="copyInCached")
|
||||||
copy_in_dir: str = Field(".", serialization_alias="copyInDir")
|
copy_in_dir: str = Field(".", serialization_alias="copyInDir")
|
||||||
copy_out: List[str] = Field([], serialization_alias="copyOut")
|
copy_out: List[str] = Field(["stdout", "stderr"], serialization_alias="copyOut")
|
||||||
copy_out_cached: List[str] = Field([], serialization_alias="copyOutCached")
|
copy_out_cached: List[str] = Field([], serialization_alias="copyOutCached")
|
||||||
copy_out_max: int = Field(0, serialization_alias="copyOutMax")
|
copy_out_max: int = Field(0, serialization_alias="copyOutMax")
|
||||||
copy_out_dir: str = Field("", serialization_alias="copyOutDir")
|
copy_out_dir: str = Field("", serialization_alias="copyOutDir")
|
||||||
|
@ -66,11 +71,10 @@ class Cmd(BaseModel):
|
||||||
class OptionalCmd(BaseModel):
|
class OptionalCmd(BaseModel):
|
||||||
args: Optional[List[str]] = None
|
args: Optional[List[str]] = None
|
||||||
env: Optional[List[str]] = None
|
env: Optional[List[str]] = None
|
||||||
stdin: Optional[Union[InputFile | StreamIn]] = None
|
stdin: Optional[Union[InputFile, StreamIn]] = None
|
||||||
stdout: Optional[Union[Collector | StreamOut]] = None
|
stdout: Optional[Union[Collector, StreamOut]] = None
|
||||||
stderr: Optional[Union[Collector | StreamOut]] = None
|
stderr: Optional[Union[Collector, StreamOut]] = None
|
||||||
cpu_limit: Optional[int] = Field(None, serialization_alias="cpuLimit")
|
cpu_limit: Optional[int] = Field(None, serialization_alias="cpuLimit")
|
||||||
real_cpu_limit: Optional[int] = Field(None, serialization_alias="realCpuLimit")
|
|
||||||
clock_limit: Optional[int] = Field(None, serialization_alias="clockLimit")
|
clock_limit: Optional[int] = Field(None, serialization_alias="clockLimit")
|
||||||
memory_limit: Optional[int] = Field(None, serialization_alias="memoryLimit")
|
memory_limit: Optional[int] = Field(None, serialization_alias="memoryLimit")
|
||||||
stack_limit: Optional[int] = Field(None, serialization_alias="stackLimit")
|
stack_limit: Optional[int] = Field(None, serialization_alias="stackLimit")
|
||||||
|
@ -101,23 +105,39 @@ class OptionalCmd(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
class ExecutorWith(BaseModel):
|
class ExecutorWith(BaseModel):
|
||||||
default: Cmd
|
default: Cmd = Cmd()
|
||||||
cases: List[OptionalCmd]
|
cases: List[OptionalCmd] = []
|
||||||
|
|
||||||
|
|
||||||
class Executor(BaseModel):
|
class Executor(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
with_: ExecutorWith = Field(..., serialization_alias="with")
|
with_: ExecutorWith = Field(ExecutorWith(), serialization_alias="with")
|
||||||
|
|
||||||
|
|
||||||
class Parser(BaseModel):
|
class Parser(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
with_: Dict[str, Any] = Field(..., serialization_alias="with")
|
if TYPE_CHECKING:
|
||||||
|
|
||||||
|
class Empty(BaseModel):
|
||||||
|
pass
|
||||||
|
|
||||||
|
with_: BaseModel = Field(Empty(), serialization_alias="with")
|
||||||
|
else:
|
||||||
|
with_: Dict[str, Any] = Field({}, serialization_alias="with")
|
||||||
|
|
||||||
|
model_config = ConfigDict(validate_assignment=True)
|
||||||
|
|
||||||
|
@field_validator("with_", mode="before")
|
||||||
|
@classmethod
|
||||||
|
def validate_with(cls, v: Any) -> Dict[str, Any]:
|
||||||
|
if isinstance(v, BaseModel):
|
||||||
|
return v.model_dump(by_alias=True)
|
||||||
|
raise ValueError("Must be a BaseModel instance")
|
||||||
|
|
||||||
|
|
||||||
class StageDetail(BaseModel):
|
class StageDetail(BaseModel):
|
||||||
name: str
|
name: str
|
||||||
group: str
|
group: str = ""
|
||||||
executor: Executor
|
executor: Executor
|
||||||
parsers: List[Parser]
|
parsers: List[Parser]
|
||||||
|
|
||||||
|
@ -130,26 +150,74 @@ class Stage(BaseModel):
|
||||||
output_path: str = Field(
|
output_path: str = Field(
|
||||||
"/tmp/joj3_result.json", serialization_alias="outputPath"
|
"/tmp/joj3_result.json", serialization_alias="outputPath"
|
||||||
) # nosec: B108
|
) # nosec: B108
|
||||||
stages: List[StageDetail]
|
stages: List[StageDetail] = []
|
||||||
|
pre_stages: List[StageDetail] = Field([], serialization_alias="preStages")
|
||||||
|
post_stages: List[StageDetail] = Field([], serialization_alias="postStages")
|
||||||
class Teapot(BaseModel):
|
|
||||||
log_path: str = Field(
|
|
||||||
"/home/tt/.cache/joint-teapot-debug.log", serialization_alias="logPath"
|
|
||||||
)
|
|
||||||
scoreboard_path: str = Field("scoreboard.csv", serialization_alias="scoreboardPath")
|
|
||||||
failed_table_path: str = Field(
|
|
||||||
"failed-table.md", serialization_alias="failedTablePath"
|
|
||||||
)
|
|
||||||
grading_repo_name: str = Field("", serialization_alias="gradingRepoName")
|
|
||||||
skip_issue: bool = Field(False, serialization_alias="skipIssue")
|
|
||||||
skip_scoreboard: bool = Field(False, serialization_alias="skipScoreboard")
|
|
||||||
skip_failed_table: bool = Field(False, serialization_alias="skipFailedTable")
|
|
||||||
|
|
||||||
|
|
||||||
class Config(BaseModel):
|
class Config(BaseModel):
|
||||||
name: str = "unknown"
|
name: str = ""
|
||||||
log_path: str = Field("", serialization_alias="logPath")
|
log_path: str = Field("", serialization_alias="logPath")
|
||||||
expire_unix_timestamp: int = Field(-1, serialization_alias="expireUnixTimestamp")
|
expire_unix_timestamp: int = Field(-1, serialization_alias="expireUnixTimestamp")
|
||||||
|
effective_unix_timestamp: int = Field(
|
||||||
|
-1, serialization_alias="effectiveUnixTimestamp"
|
||||||
|
)
|
||||||
|
actor_csv_path: str = Field("", serialization_alias="actorCsvPath")
|
||||||
|
max_total_score: int = Field(100, serialization_alias="maxTotalScore")
|
||||||
stage: Stage
|
stage: Stage
|
||||||
teapot: Teapot
|
|
||||||
|
|
||||||
|
class DummyConfig(BaseModel):
|
||||||
|
score: int = 0
|
||||||
|
comment: Optional[str] = None
|
||||||
|
force_quit_on_not_accepted: Optional[bool] = Field(
|
||||||
|
False, serialization_alias="forceQuitOnNotAccepted"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DiffOutputConfig(BaseModel):
|
||||||
|
score: int = 100
|
||||||
|
file_name: str = Field("", serialization_alias="fileName")
|
||||||
|
answer_path: str = Field("", serialization_alias="answerPath")
|
||||||
|
force_quit_on_diff: bool = Field(False, serialization_alias="forceQuitOnDiff")
|
||||||
|
always_hide: bool = Field(False, serialization_alias="alwaysHide")
|
||||||
|
compare_space: bool = Field(False, serialization_alias="compareSpace")
|
||||||
|
|
||||||
|
|
||||||
|
class ResultDetailConfig(BaseModel):
|
||||||
|
score: int = 0
|
||||||
|
comment: str = ""
|
||||||
|
show_files: List[str] = Field([], serialization_alias="showFiles")
|
||||||
|
show_exit_status: bool = Field(True, serialization_alias="showExitStatus")
|
||||||
|
show_runtime: bool = Field(True, serialization_alias="showRuntime")
|
||||||
|
show_memory: bool = Field(False, serialization_alias="showMemory")
|
||||||
|
|
||||||
|
|
||||||
|
class KeywordConfig(BaseModel):
|
||||||
|
keywords: List[str] = []
|
||||||
|
score: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
class KeywordMatchConfig(BaseModel):
|
||||||
|
matches: List[KeywordConfig] = []
|
||||||
|
|
||||||
|
|
||||||
|
class FileConfig(BaseModel):
|
||||||
|
name: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
class DiffCasesConfig(BaseModel):
|
||||||
|
outputs: List[DiffOutputConfig] = []
|
||||||
|
|
||||||
|
|
||||||
|
class DiffConfig(BaseModel):
|
||||||
|
name: str = "diff"
|
||||||
|
cases: List[DiffCasesConfig] = []
|
||||||
|
|
||||||
|
|
||||||
|
class MsgConfig(BaseModel):
|
||||||
|
msg: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
class ScoreConfig(BaseModel):
|
||||||
|
score: int = 0
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
|
from enum import Enum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional
|
from typing import Any, Dict, List, Type
|
||||||
|
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||||
|
|
||||||
|
from joj3_config_generator.models.common import Memory, Time
|
||||||
|
from joj3_config_generator.models.const import (
|
||||||
|
DEFAULT_CPU_LIMIT,
|
||||||
|
DEFAULT_FILE_LIMIT,
|
||||||
|
DEFAULT_MEMORY_LIMIT,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ParserResultDetail(BaseModel):
|
class ParserResultDetail(BaseModel):
|
||||||
|
@ -10,31 +18,136 @@ class ParserResultDetail(BaseModel):
|
||||||
mem: bool = True # Display memory usage
|
mem: bool = True # Display memory usage
|
||||||
stdout: bool = False # Display stdout messages
|
stdout: bool = False # Display stdout messages
|
||||||
stderr: bool = False # Display stderr messages
|
stderr: bool = False # Display stderr messages
|
||||||
|
exit_status: bool = True
|
||||||
|
|
||||||
|
|
||||||
|
class ParserFile(BaseModel):
|
||||||
|
name: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
class ParserLog(BaseModel):
|
||||||
|
filename: str
|
||||||
|
msg: str = ""
|
||||||
|
level: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
class ParserDummy(BaseModel):
|
||||||
|
comment: str = ""
|
||||||
|
score: int = 0
|
||||||
|
force_quit: bool = False
|
||||||
|
|
||||||
|
|
||||||
|
class ParserKeyword(BaseModel):
|
||||||
|
keyword: List[str] = []
|
||||||
|
weight: List[int] = []
|
||||||
|
|
||||||
|
|
||||||
|
class Outputs(BaseModel):
|
||||||
|
score: int = 0
|
||||||
|
ignore_spaces: bool = True
|
||||||
|
hide: bool = False
|
||||||
|
force_quit: bool = False
|
||||||
|
|
||||||
|
|
||||||
|
class ParserDiff(BaseModel):
|
||||||
|
output: Outputs = Outputs()
|
||||||
|
|
||||||
|
|
||||||
class Files(BaseModel):
|
class Files(BaseModel):
|
||||||
import_: List[str] = Field(serialization_alias="import", validation_alias="import")
|
import_: List[str] = Field([], alias="import")
|
||||||
export: List[str]
|
export: List[str] = []
|
||||||
|
|
||||||
|
|
||||||
|
class Limit(BaseModel):
|
||||||
|
mem: int = DEFAULT_MEMORY_LIMIT
|
||||||
|
cpu: int = DEFAULT_CPU_LIMIT
|
||||||
|
stdout: int = DEFAULT_FILE_LIMIT
|
||||||
|
stderr: int = DEFAULT_FILE_LIMIT
|
||||||
|
|
||||||
|
model_config = ConfigDict(validate_assignment=True)
|
||||||
|
|
||||||
|
@field_validator("cpu", mode="before")
|
||||||
|
@classmethod
|
||||||
|
def ensure_time(cls, v: Any) -> Time:
|
||||||
|
if isinstance(v, str):
|
||||||
|
return Time(v)
|
||||||
|
raise ValueError("Must be a string")
|
||||||
|
|
||||||
|
@field_validator("mem", "stdout", "stderr", mode="before")
|
||||||
|
@classmethod
|
||||||
|
def ensure_mem(cls, v: Any) -> Memory:
|
||||||
|
if isinstance(v, str):
|
||||||
|
return Memory(v)
|
||||||
|
raise ValueError("Must be a string")
|
||||||
|
|
||||||
|
|
||||||
|
class Parser(str, Enum):
|
||||||
|
CLANG_TIDY = "clangtidy"
|
||||||
|
CPPCHECK = "cppcheck"
|
||||||
|
CPPLINT = "cpplint"
|
||||||
|
KEYWORD = "keyword"
|
||||||
|
RESULT_STATUS = "result-status"
|
||||||
|
RESULT_DETAIL = "result-detail"
|
||||||
|
DUMMY = "dummy"
|
||||||
|
FILE = "file"
|
||||||
|
DIFF = "diff"
|
||||||
|
|
||||||
|
|
||||||
class Stage(BaseModel):
|
class Stage(BaseModel):
|
||||||
name: str # Stage name
|
name: str = "" # Stage name
|
||||||
command: str # Command to run
|
env: List[str] = []
|
||||||
files: Files # Files to import and export
|
command: str = "" # Command to run
|
||||||
score: int # Score for the task
|
files: Files = Files()
|
||||||
parsers: List[str] # list of parsers
|
in_: str = Field("", alias="in")
|
||||||
result_detail: ParserResultDetail = (
|
out_: str = Field("", alias="out")
|
||||||
ParserResultDetail()
|
score: int = 0
|
||||||
) # for result-detail parser
|
parsers: List[Parser] = [] # list of parsers
|
||||||
|
limit: Limit = Limit()
|
||||||
|
dummy: ParserDummy = ParserDummy()
|
||||||
|
result_status: ParserDummy = Field(ParserDummy(), alias="result-status")
|
||||||
|
keyword: ParserKeyword = ParserKeyword()
|
||||||
|
clangtidy: ParserKeyword = ParserKeyword()
|
||||||
|
cppcheck: ParserKeyword = ParserKeyword()
|
||||||
|
cpplint: ParserKeyword = ParserKeyword()
|
||||||
|
result_detail: ParserResultDetail = Field(
|
||||||
|
ParserResultDetail(), alias="result-detail"
|
||||||
|
)
|
||||||
|
file: ParserFile = ParserFile()
|
||||||
|
skip: List[str] = []
|
||||||
|
|
||||||
|
# cases related
|
||||||
|
cases: Dict[str, "Stage"] = {}
|
||||||
|
diff: ParserDiff = ParserDiff()
|
||||||
|
|
||||||
|
model_config = ConfigDict(extra="allow")
|
||||||
|
|
||||||
|
@model_validator(mode="before")
|
||||||
|
@classmethod
|
||||||
|
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: v for k, v in cases.items()}
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
class Release(BaseModel):
|
class Release(BaseModel):
|
||||||
deadline: Optional[datetime] # RFC 3339 formatted date-time with offset
|
end_time: datetime = datetime.now() + timedelta(
|
||||||
|
days=365
|
||||||
|
) # RFC 3339 formatted date-time with offset
|
||||||
|
begin_time: datetime = datetime.fromtimestamp(
|
||||||
|
0
|
||||||
|
) # RFC 3339 formatted date-time with offset
|
||||||
|
|
||||||
|
|
||||||
|
class Task(BaseModel):
|
||||||
|
type_: str = Field("unknown", serialization_alias="type", validation_alias="type")
|
||||||
|
name: str = "unknown"
|
||||||
|
|
||||||
|
|
||||||
class Config(BaseModel):
|
class Config(BaseModel):
|
||||||
root: Path = Path(".")
|
root: Path = Path(".")
|
||||||
path: Path = Path("task.toml")
|
path: Path = Path("task.toml")
|
||||||
task: str # Task name (e.g., hw3 ex5)
|
task: Task = Task() # Task name (e.g., hw3 ex5)
|
||||||
release: Release # Release configuration
|
release: Release = Release() # Release configuration
|
||||||
stages: List[Stage] # list of stage configurations
|
stages: List[Stage] = [] # list of stage configurations
|
||||||
|
|
0
joj3_config_generator/processers/__init__.py
Normal file
0
joj3_config_generator/processers/__init__.py
Normal file
108
joj3_config_generator/processers/repo.py
Normal file
108
joj3_config_generator/processers/repo.py
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
import hashlib
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from joj3_config_generator.models import repo, result
|
||||||
|
from joj3_config_generator.models.const import CACHE_ROOT, TEAPOT_CONFIG_ROOT
|
||||||
|
|
||||||
|
|
||||||
|
def get_teapot_stage(repo_conf: repo.Config) -> result.StageDetail:
|
||||||
|
args = [
|
||||||
|
"/usr/local/bin/joint-teapot",
|
||||||
|
"joj3-all-env",
|
||||||
|
str(TEAPOT_CONFIG_ROOT / "teapot.env"),
|
||||||
|
"--grading-repo-name",
|
||||||
|
repo_conf.grading_repo_name,
|
||||||
|
"--max-total-score",
|
||||||
|
str(repo_conf.max_total_score),
|
||||||
|
]
|
||||||
|
|
||||||
|
stage_conf = result.StageDetail(
|
||||||
|
name="teapot",
|
||||||
|
executor=result.Executor(
|
||||||
|
name="local",
|
||||||
|
with_=result.ExecutorWith(
|
||||||
|
default=result.Cmd(
|
||||||
|
args=args,
|
||||||
|
env=[f"LOG_FILE_PATH={CACHE_ROOT}/joint-teapot-debug.log"],
|
||||||
|
),
|
||||||
|
cases=[],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
parsers=[result.Parser(name="log", with_=result.MsgConfig(msg="joj3 summary"))],
|
||||||
|
)
|
||||||
|
return stage_conf
|
||||||
|
|
||||||
|
|
||||||
|
def get_health_check_args(repo_conf: repo.Config) -> List[str]:
|
||||||
|
return [
|
||||||
|
"/usr/local/bin/repo-health-checker",
|
||||||
|
"-root=.",
|
||||||
|
f"-repoSize={str(repo_conf.max_size)}",
|
||||||
|
*[f"-meta={meta}" for meta in repo_conf.files.required],
|
||||||
|
f"-checkFileSumList={','.join(get_hashs(repo_conf))}",
|
||||||
|
f"-checkFileNameList={','.join(repo_conf.files.immutable)}",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_teapot_check_args(repo_conf: repo.Config) -> List[str]:
|
||||||
|
return [
|
||||||
|
"/usr/local/bin/joint-teapot",
|
||||||
|
"joj3-check-env",
|
||||||
|
str(TEAPOT_CONFIG_ROOT / "teapot.env"),
|
||||||
|
"--grading-repo-name",
|
||||||
|
repo_conf.grading_repo_name,
|
||||||
|
"--group-config",
|
||||||
|
",".join(
|
||||||
|
f"{name}={max_count}:{time_period}"
|
||||||
|
for name, max_count, time_period in zip(
|
||||||
|
repo_conf.groups.name,
|
||||||
|
repo_conf.groups.max_count,
|
||||||
|
repo_conf.groups.time_period_hour,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_health_check_stage(repo_conf: repo.Config) -> result.StageDetail:
|
||||||
|
health_check_stage = result.StageDetail(
|
||||||
|
name="Health Check",
|
||||||
|
group="",
|
||||||
|
executor=result.Executor(
|
||||||
|
name="local",
|
||||||
|
with_=result.ExecutorWith(
|
||||||
|
default=result.Cmd(),
|
||||||
|
cases=[
|
||||||
|
result.OptionalCmd(
|
||||||
|
args=get_health_check_args(repo_conf),
|
||||||
|
),
|
||||||
|
result.OptionalCmd(
|
||||||
|
args=get_teapot_check_args(repo_conf),
|
||||||
|
env=[f"LOG_FILE_PATH={CACHE_ROOT}/joint-teapot-debug.log"],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
parsers=[
|
||||||
|
result.Parser(name="healthcheck", with_=result.ScoreConfig(score=1)),
|
||||||
|
result.Parser(name="debug", with_=result.ScoreConfig(score=0)),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
return health_check_stage
|
||||||
|
|
||||||
|
|
||||||
|
def calc_sha256sum(file_path: Path) -> str:
|
||||||
|
sha256_hash = hashlib.sha256()
|
||||||
|
with open(file_path, "rb") as f:
|
||||||
|
for byte_block in iter(lambda: f.read(64 * 1024), b""):
|
||||||
|
sha256_hash.update(byte_block)
|
||||||
|
return sha256_hash.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def get_hashs(repo_conf: repo.Config) -> List[str]:
|
||||||
|
base_dir = (repo_conf.root / repo_conf.path).parent
|
||||||
|
immutable_dir = base_dir / "immutable_files"
|
||||||
|
immutable_files = [
|
||||||
|
immutable_dir / Path(file).name for file in repo_conf.files.immutable
|
||||||
|
]
|
||||||
|
return [calc_sha256sum(file) for file in immutable_files]
|
206
joj3_config_generator/processers/task.py
Normal file
206
joj3_config_generator/processers/task.py
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
import re
|
||||||
|
import shlex
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Callable, Dict, List, Tuple
|
||||||
|
|
||||||
|
from joj3_config_generator.models import result, task
|
||||||
|
from joj3_config_generator.models.common import Memory, Time
|
||||||
|
from joj3_config_generator.models.const import JOJ3_CONFIG_ROOT
|
||||||
|
from joj3_config_generator.models.task import Parser as ParserEnum
|
||||||
|
|
||||||
|
|
||||||
|
def get_conf_stage(
|
||||||
|
task_conf: task.Config,
|
||||||
|
task_stage: task.Stage,
|
||||||
|
cached: Dict[str, None],
|
||||||
|
) -> result.StageDetail:
|
||||||
|
conf_stage = result.StageDetail(
|
||||||
|
name=task_stage.name,
|
||||||
|
# group is determined by adding between "[]" in the name of the task
|
||||||
|
group=(
|
||||||
|
match.group(1)
|
||||||
|
if (match := re.search(r"\[([^\[\]]+)\]", task_stage.name or ""))
|
||||||
|
else ""
|
||||||
|
),
|
||||||
|
executor=result.Executor(
|
||||||
|
name="sandbox",
|
||||||
|
with_=get_executor_with(task_stage, cached),
|
||||||
|
),
|
||||||
|
parsers=([result.Parser(name=parser) for parser in task_stage.parsers]),
|
||||||
|
)
|
||||||
|
processed_dict = get_processed_dict(task_stage)
|
||||||
|
for idx, parser in enumerate(task_stage.parsers):
|
||||||
|
if parser in processed_dict:
|
||||||
|
fn, parser_model = processed_dict[parser]
|
||||||
|
fn(parser_model, conf_stage.parsers[idx])
|
||||||
|
elif parser == ParserEnum.DIFF:
|
||||||
|
fix_diff(
|
||||||
|
task_stage,
|
||||||
|
conf_stage.parsers[idx],
|
||||||
|
conf_stage.executor,
|
||||||
|
JOJ3_CONFIG_ROOT / task_conf.path.parent,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
return conf_stage
|
||||||
|
|
||||||
|
|
||||||
|
def get_processed_dict(
|
||||||
|
task_stage: task.Stage,
|
||||||
|
) -> Dict[ParserEnum, Tuple[Callable[[Any, result.Parser], None], Any]]:
|
||||||
|
processed_dict: Dict[
|
||||||
|
ParserEnum, Tuple[Callable[[Any, result.Parser], None], Any]
|
||||||
|
] = {
|
||||||
|
ParserEnum.CLANG_TIDY: (fix_keyword, task_stage.clangtidy),
|
||||||
|
ParserEnum.KEYWORD: (fix_keyword, task_stage.keyword),
|
||||||
|
ParserEnum.CPPCHECK: (fix_keyword, task_stage.cppcheck),
|
||||||
|
ParserEnum.CPPLINT: (fix_keyword, task_stage.cpplint),
|
||||||
|
ParserEnum.RESULT_DETAIL: (fix_result_detail, task_stage.result_detail),
|
||||||
|
ParserEnum.DUMMY: (fix_dummy, task_stage.dummy),
|
||||||
|
ParserEnum.RESULT_STATUS: (fix_dummy, task_stage.result_status),
|
||||||
|
ParserEnum.FILE: (fix_file, task_stage.file),
|
||||||
|
}
|
||||||
|
return processed_dict
|
||||||
|
|
||||||
|
|
||||||
|
def get_executor_with(
|
||||||
|
task_stage: task.Stage, cached: Dict[str, None]
|
||||||
|
) -> result.ExecutorWith:
|
||||||
|
file_import = task_stage.files.import_
|
||||||
|
copy_in_files = (file for file in file_import if file not in cached)
|
||||||
|
file_export = task_stage.files.export
|
||||||
|
copy_out_files = ["stdout", "stderr"]
|
||||||
|
executor_with_config = result.ExecutorWith(
|
||||||
|
default=result.Cmd(
|
||||||
|
args=shlex.split(task_stage.command),
|
||||||
|
copy_in={
|
||||||
|
file: result.LocalFile(src=str(JOJ3_CONFIG_ROOT / file))
|
||||||
|
# all copyin files store in this tools folder
|
||||||
|
# TODO: are there any corner cases?
|
||||||
|
for file in copy_in_files
|
||||||
|
},
|
||||||
|
copy_out=copy_out_files,
|
||||||
|
copy_in_cached={file: file for file in cached},
|
||||||
|
copy_out_cached=file_export,
|
||||||
|
cpu_limit=Time(task_stage.limit.cpu),
|
||||||
|
clock_limit=2 * Time(task_stage.limit.cpu),
|
||||||
|
memory_limit=Memory(task_stage.limit.mem),
|
||||||
|
stderr=result.Collector(
|
||||||
|
name="stderr", pipe=True, max=Memory(task_stage.limit.stderr)
|
||||||
|
),
|
||||||
|
stdout=result.Collector(
|
||||||
|
name="stdout", pipe=True, max=Memory(task_stage.limit.stdout)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
cases=[],
|
||||||
|
)
|
||||||
|
for file in file_export:
|
||||||
|
cached[file] = None
|
||||||
|
return executor_with_config
|
||||||
|
|
||||||
|
|
||||||
|
def fix_keyword(
|
||||||
|
keyword_config: task.ParserKeyword, keyword_parser: result.Parser
|
||||||
|
) -> None:
|
||||||
|
if len(keyword_config.keyword) != len(keyword_config.weight):
|
||||||
|
raise ValueError("Keywords and weights must have the same length")
|
||||||
|
score_groups: Dict[int, List[str]] = {}
|
||||||
|
for keyword, score in zip(keyword_config.keyword, keyword_config.weight):
|
||||||
|
score_groups.setdefault(score, []).append(keyword)
|
||||||
|
keyword_parser.with_ = result.KeywordMatchConfig(
|
||||||
|
matches=[
|
||||||
|
result.KeywordConfig(keywords=keywords, score=score)
|
||||||
|
for score, keywords in score_groups.items()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def fix_result_detail(
|
||||||
|
result_detail_parser_config: task.ParserResultDetail,
|
||||||
|
result_detail_parser: result.Parser,
|
||||||
|
) -> None:
|
||||||
|
show_files = []
|
||||||
|
if result_detail_parser_config.stdout:
|
||||||
|
show_files.append("stdout")
|
||||||
|
if result_detail_parser_config.stderr:
|
||||||
|
show_files.append("stderr")
|
||||||
|
result_detail_parser.with_ = result.ResultDetailConfig(
|
||||||
|
score=0,
|
||||||
|
comment="",
|
||||||
|
show_files=show_files,
|
||||||
|
show_exit_status=result_detail_parser_config.exit_status,
|
||||||
|
show_runtime=result_detail_parser_config.time,
|
||||||
|
show_memory=result_detail_parser_config.mem,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def fix_dummy(
|
||||||
|
dummy_parser_config: task.ParserDummy, dummy_parser: result.Parser
|
||||||
|
) -> None:
|
||||||
|
# we don't use dummy parser in real application
|
||||||
|
dummy_parser.with_ = result.DummyConfig(
|
||||||
|
score=dummy_parser_config.score,
|
||||||
|
comment=dummy_parser_config.comment,
|
||||||
|
force_quit_on_not_accepted=dummy_parser_config.force_quit,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def fix_file(file_parser_config: task.ParserFile, file_parser: result.Parser) -> None:
|
||||||
|
file_parser.with_ = result.FileConfig(name=file_parser_config.name)
|
||||||
|
|
||||||
|
|
||||||
|
def fix_diff(
|
||||||
|
task_stage: task.Stage,
|
||||||
|
diff_parser_config: result.Parser,
|
||||||
|
diff_executor: result.Executor,
|
||||||
|
base_dir: Path,
|
||||||
|
) -> None:
|
||||||
|
skip = task_stage.skip
|
||||||
|
cases = task_stage.cases
|
||||||
|
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
|
||||||
|
|
||||||
|
cpu_limit = case_stage.limit.cpu
|
||||||
|
clock_limit = 2 * case_stage.limit.cpu
|
||||||
|
memory_limit = case_stage.limit.mem
|
||||||
|
command = case_stage.command
|
||||||
|
stdin = case_stage.in_ if case_stage.in_ != "" else f"{case}.in"
|
||||||
|
stdout = case_stage.out_ if case_stage.out_ != "" else f"{case}.out"
|
||||||
|
|
||||||
|
stage_cases.append(
|
||||||
|
result.OptionalCmd(
|
||||||
|
stdin=result.LocalFile(
|
||||||
|
src=str(base_dir / stdin),
|
||||||
|
),
|
||||||
|
args=shlex.split(command) if command else None,
|
||||||
|
cpu_limit=cpu_limit,
|
||||||
|
clock_limit=clock_limit,
|
||||||
|
memory_limit=memory_limit,
|
||||||
|
proc_limit=50,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
diff_output = case_stage.diff.output
|
||||||
|
parser_cases.append(
|
||||||
|
result.DiffCasesConfig(
|
||||||
|
outputs=[
|
||||||
|
result.DiffOutputConfig(
|
||||||
|
score=diff_output.score,
|
||||||
|
file_name="stdout",
|
||||||
|
answer_path=str(base_dir / stdout),
|
||||||
|
force_quit_on_diff=diff_output.force_quit,
|
||||||
|
always_hide=diff_output.hide,
|
||||||
|
compare_space=not diff_output.ignore_spaces,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
diff_executor.with_.cases = stage_cases
|
||||||
|
diff_parser_config.with_ = result.DiffConfig(name="diff", cases=parser_cases)
|
|
@ -2,7 +2,7 @@ import logging
|
||||||
import sys
|
import sys
|
||||||
from sys import stderr
|
from sys import stderr
|
||||||
from types import FrameType
|
from types import FrameType
|
||||||
from typing import Optional
|
from typing import Optional, Union
|
||||||
|
|
||||||
from loguru import logger as logger
|
from loguru import logger as logger
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ from loguru import logger as logger
|
||||||
# recipe from https://loguru.readthedocs.io/en/stable/overview.html#entirely-compatible-with-standard-logging
|
# recipe from https://loguru.readthedocs.io/en/stable/overview.html#entirely-compatible-with-standard-logging
|
||||||
class InterceptHandler(logging.Handler):
|
class InterceptHandler(logging.Handler):
|
||||||
def emit(self, record: logging.LogRecord) -> None:
|
def emit(self, record: logging.LogRecord) -> None:
|
||||||
level: str | int
|
level: Union[str, int]
|
||||||
try:
|
try:
|
||||||
level = logger.level(record.levelname).name
|
level = logger.level(record.levelname).name
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|
|
@ -12,6 +12,7 @@ dependencies = [
|
||||||
"pydantic>=2.9.2",
|
"pydantic>=2.9.2",
|
||||||
"inquirer>=3.4.0",
|
"inquirer>=3.4.0",
|
||||||
"rtoml>=0.11.0",
|
"rtoml>=0.11.0",
|
||||||
|
"humanfriendly>=10.0",
|
||||||
]
|
]
|
||||||
requires-python = ">=3.9"
|
requires-python = ">=3.9"
|
||||||
authors = [{ name = "JOJ3-dev", email = "joj3@focs.ji.sjtu.edu.cn" }]
|
authors = [{ name = "JOJ3-dev", email = "joj3@focs.ji.sjtu.edu.cn" }]
|
||||||
|
|
33
tests/convert/basic/immutable_files/.gitattributes
vendored
Normal file
33
tests/convert/basic/immutable_files/.gitattributes
vendored
Normal file
|
@ -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
|
23
tests/convert/basic/immutable_files/.gitignore
vendored
Normal file
23
tests/convert/basic/immutable_files/.gitignore
vendored
Normal 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
|
19
tests/convert/basic/immutable_files/push.yaml
Normal file
19
tests/convert/basic/immutable_files/push.yaml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
name: Run JOJ3 on Push
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run:
|
||||||
|
container:
|
||||||
|
runs-on: focs-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: actions/checkout@focs
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Run joj3
|
||||||
|
run: |
|
||||||
|
sudo -E -u tt joj3 -conf-root /home/tt/.config/joj/tests/homework
|
21
tests/convert/basic/immutable_files/release.yaml
Normal file
21
tests/convert/basic/immutable_files/release.yaml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
name: Run JOJ3 on Release
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run:
|
||||||
|
runs-on: focs-latest-slim
|
||||||
|
container:
|
||||||
|
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: actions/checkout@focs
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Run joj3
|
||||||
|
run: |
|
||||||
|
sudo -E -u tt joj3 -conf-root "/home/tt/.config/joj/tests/homework" -conf-name "conf-release.json" -tag "${{ github.ref_name }}"
|
|
@ -1,10 +1,16 @@
|
||||||
teaching_team = ["prof_john", "ta_alice", "ta_bob"]
|
grading_repo_name = "ece280-joj"
|
||||||
max_size = 50.5
|
|
||||||
release_tags = ["v1.0", "v2.0", "final"]
|
|
||||||
sandbox_token = "test"
|
sandbox_token = "test"
|
||||||
|
# reconfigure later
|
||||||
|
max_total_score = 100
|
||||||
|
max_size = 50.5
|
||||||
|
|
||||||
|
# for tests
|
||||||
|
[groups]
|
||||||
|
name = ["joj", "run"]
|
||||||
|
max_count = [1000, 1000]
|
||||||
|
time_period_hour = [24, 24]
|
||||||
|
|
||||||
[files]
|
[files]
|
||||||
whitelist_patterns = ["*.py", "*.txt", "*.md"]
|
required = ["README.md", "Changelog.md"]
|
||||||
whitelist_file = ".whitelist"
|
immutable = [".gitignore", ".gitattributes",".gitea/workflows/push.yaml", ".gitea/workflows/release.yaml"]
|
||||||
required = ["main.py", "README.md"]
|
|
||||||
immutable = ["config.yaml", "setup.py"]
|
|
||||||
|
|
|
@ -1,46 +1,151 @@
|
||||||
{
|
{
|
||||||
"name": "hw3 ex5",
|
"name": "hw7 ex2",
|
||||||
"logPath": "hw3_ex5.log",
|
"logPath": "/home/tt/.cache/joj3/homework/h7/e2.log",
|
||||||
"expireUnixTimestamp": 1729267140,
|
"expireUnixTimestamp": 1735574399,
|
||||||
|
"effectiveUnixTimestamp": 1735487999,
|
||||||
|
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||||
|
"maxTotalScore": 100,
|
||||||
"stage": {
|
"stage": {
|
||||||
"sandboxExecServer": "172.17.0.1:5051",
|
"sandboxExecServer": "172.17.0.1:5051",
|
||||||
"sandboxToken": "test",
|
"sandboxToken": "test",
|
||||||
"outputPath": "/tmp/joj3_result.json",
|
"outputPath": "/tmp/joj3_result.json",
|
||||||
"stages": [
|
"stages": [
|
||||||
{
|
{
|
||||||
"name": "judge_base",
|
"name": "Health Check",
|
||||||
"group": "hw3 ex5",
|
"group": "",
|
||||||
|
"executor": {
|
||||||
|
"name": "local",
|
||||||
|
"with": {
|
||||||
|
"default": {
|
||||||
|
"args": [],
|
||||||
|
"env": [],
|
||||||
|
"stdin": {
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
|
"stackLimit": 0,
|
||||||
|
"procLimit": 50,
|
||||||
|
"cpuRateLimit": 0,
|
||||||
|
"cpuSetLimit": "",
|
||||||
|
"copyIn": {},
|
||||||
|
"copyInCached": {},
|
||||||
|
"copyInDir": ".",
|
||||||
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
|
"copyOutMax": 0,
|
||||||
|
"copyOutDir": "",
|
||||||
|
"tty": false,
|
||||||
|
"strictMemoryLimit": false,
|
||||||
|
"dataSegmentLimit": false,
|
||||||
|
"addressSpaceLimit": false
|
||||||
|
},
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"args": [
|
||||||
|
"/usr/local/bin/repo-health-checker",
|
||||||
|
"-root=.",
|
||||||
|
"-repoSize=50.5",
|
||||||
|
"-meta=README.md",
|
||||||
|
"-meta=Changelog.md",
|
||||||
|
"-checkFileSumList=a5b63323a692d3d8b952442969649b4f823d58dae26429494f613df160710dfc,b1bbad25b830db0a77b15a033f9ca1b7ab44c1d2d05056412bd3e4421645f0bf,2ba059f3977e2e3dee6cacbfbf0ba2578baa1b8e04b4977aec400868b6e49856,bf7d181362affdcc72aac33f3520e4e6371adc48ea62a6f24524b4a3e76724c5",
|
||||||
|
"-checkFileNameList=.gitignore,.gitattributes,.gitea/workflows/push.yaml,.gitea/workflows/release.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"args": [
|
||||||
|
"/usr/local/bin/joint-teapot",
|
||||||
|
"joj3-check-env",
|
||||||
|
"/home/tt/.config/teapot/teapot.env",
|
||||||
|
"--grading-repo-name",
|
||||||
|
"ece280-joj",
|
||||||
|
"--group-config",
|
||||||
|
"joj=1000:24,run=1000:24"
|
||||||
|
],
|
||||||
|
"env": [
|
||||||
|
"LOG_FILE_PATH=/home/tt/.cache/joint-teapot-debug.log"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parsers": [
|
||||||
|
{
|
||||||
|
"name": "healthcheck",
|
||||||
|
"with": {
|
||||||
|
"score": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "debug",
|
||||||
|
"with": {
|
||||||
|
"score": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Compilation",
|
||||||
|
"group": "",
|
||||||
"executor": {
|
"executor": {
|
||||||
"name": "sandbox",
|
"name": "sandbox",
|
||||||
"with": {
|
"with": {
|
||||||
"default": {
|
"default": {
|
||||||
"args": [
|
"args": [
|
||||||
"./matlab-joj",
|
"./tools/compile"
|
||||||
"./h3/ex5.m"
|
|
||||||
],
|
],
|
||||||
"env": [],
|
"env": [],
|
||||||
"cpuLimit": 0,
|
"stdin": {
|
||||||
"realCpuLimit": 0,
|
"content": ""
|
||||||
"clockLimit": 0,
|
},
|
||||||
"memoryLimit": 0,
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
"stackLimit": 0,
|
"stackLimit": 0,
|
||||||
"procLimit": 0,
|
"procLimit": 50,
|
||||||
"cpuRateLimit": 0,
|
"cpuRateLimit": 0,
|
||||||
"cpuSetLimit": "",
|
"cpuSetLimit": "",
|
||||||
"copyIn": {
|
"copyIn": {
|
||||||
"tools/matlab-joj": {
|
"tools/compile": {
|
||||||
"src": "tools/matlab-joj"
|
"src": "/home/tt/.config/joj/tools/compile"
|
||||||
},
|
|
||||||
"tools/matlab_formatter.py": {
|
|
||||||
"src": "tools/matlab_formatter.py"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"copyInCached": {},
|
"copyInCached": {},
|
||||||
"copyInDir": ".",
|
"copyInDir": ".",
|
||||||
"copyOut": [],
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
"copyOutCached": [
|
"copyOutCached": [
|
||||||
"output/ex5_results.txt",
|
"h7/build/ex2",
|
||||||
"output/ex5_logs.txt"
|
"h7/build/ex2-asan",
|
||||||
|
"h7/build/ex2-ubsan",
|
||||||
|
"h7/build/ex2-msan",
|
||||||
|
"h7/build/compile_commands.json"
|
||||||
],
|
],
|
||||||
"copyOutMax": 0,
|
"copyOutMax": 0,
|
||||||
"copyOutDir": "",
|
"copyOutDir": "",
|
||||||
|
@ -53,56 +158,82 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parsers": [
|
"parsers": [
|
||||||
{
|
|
||||||
"name": "diff",
|
|
||||||
"with": {}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "result-detail",
|
"name": "result-detail",
|
||||||
"with": {
|
"with": {
|
||||||
"time": false,
|
"score": 0,
|
||||||
"mem": false,
|
"comment": "",
|
||||||
"stdout": false,
|
"showFiles": [
|
||||||
"stderr": true
|
"stderr"
|
||||||
|
],
|
||||||
|
"showExitStatus": true,
|
||||||
|
"showRuntime": false,
|
||||||
|
"showMemory": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "result-status",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "Congratulations! Your code compiled successfully.",
|
||||||
|
"forceQuitOnNotAccepted": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "judge_base2",
|
"name": "[cq] Filelength",
|
||||||
"group": "hw3 ex5",
|
"group": "cq",
|
||||||
"executor": {
|
"executor": {
|
||||||
"name": "sandbox",
|
"name": "sandbox",
|
||||||
"with": {
|
"with": {
|
||||||
"default": {
|
"default": {
|
||||||
"args": [
|
"args": [
|
||||||
"./matlab-joj",
|
"./tools/filelength",
|
||||||
"./h3/ex5.m"
|
"400",
|
||||||
|
"300",
|
||||||
|
"*.cpp",
|
||||||
|
"*.h"
|
||||||
],
|
],
|
||||||
"env": [],
|
"env": [],
|
||||||
"cpuLimit": 0,
|
"stdin": {
|
||||||
"realCpuLimit": 0,
|
"content": ""
|
||||||
"clockLimit": 0,
|
},
|
||||||
"memoryLimit": 0,
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
"stackLimit": 0,
|
"stackLimit": 0,
|
||||||
"procLimit": 0,
|
"procLimit": 50,
|
||||||
"cpuRateLimit": 0,
|
"cpuRateLimit": 0,
|
||||||
"cpuSetLimit": "",
|
"cpuSetLimit": "",
|
||||||
"copyIn": {
|
"copyIn": {
|
||||||
"tools/matlab-joj": {
|
"tools/filelength": {
|
||||||
"src": "tools/matlab-joj"
|
"src": "/home/tt/.config/joj/tools/filelength"
|
||||||
},
|
|
||||||
"tools/matlab_formatter.py": {
|
|
||||||
"src": "tools/matlab_formatter.py"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"copyInCached": {},
|
"copyInCached": {
|
||||||
|
"h7/build/ex2": "h7/build/ex2",
|
||||||
|
"h7/build/ex2-asan": "h7/build/ex2-asan",
|
||||||
|
"h7/build/ex2-ubsan": "h7/build/ex2-ubsan",
|
||||||
|
"h7/build/ex2-msan": "h7/build/ex2-msan",
|
||||||
|
"h7/build/compile_commands.json": "h7/build/compile_commands.json"
|
||||||
|
},
|
||||||
"copyInDir": ".",
|
"copyInDir": ".",
|
||||||
"copyOut": [],
|
"copyOut": [
|
||||||
"copyOutCached": [
|
"stdout",
|
||||||
"output/ex5_results2.txt",
|
"stderr"
|
||||||
"output/ex5_logs2.txt"
|
|
||||||
],
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
"copyOutMax": 0,
|
"copyOutMax": 0,
|
||||||
"copyOutDir": "",
|
"copyOutDir": "",
|
||||||
"tty": false,
|
"tty": false,
|
||||||
|
@ -115,29 +246,604 @@
|
||||||
},
|
},
|
||||||
"parsers": [
|
"parsers": [
|
||||||
{
|
{
|
||||||
"name": "diff",
|
"name": "keyword",
|
||||||
"with": {}
|
"with": {
|
||||||
|
"matches": [
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"max"
|
||||||
|
],
|
||||||
|
"score": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"recommended"
|
||||||
|
],
|
||||||
|
"score": 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "result-detail",
|
"name": "result-detail",
|
||||||
"with": {
|
"with": {
|
||||||
"time": true,
|
"score": 0,
|
||||||
"mem": true,
|
"comment": "",
|
||||||
"stdout": false,
|
"showFiles": [
|
||||||
"stderr": false
|
"stdout"
|
||||||
|
],
|
||||||
|
"showExitStatus": true,
|
||||||
|
"showRuntime": false,
|
||||||
|
"showMemory": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"teapot": {
|
{
|
||||||
"logPath": "/home/tt/.cache/joint-teapot-debug.log",
|
"name": "[cq] Clang-tidy",
|
||||||
"scoreboardPath": "scoreboard.csv",
|
"group": "cq",
|
||||||
"failedTablePath": "failed-table.md",
|
"executor": {
|
||||||
"gradingRepoName": "",
|
"name": "sandbox",
|
||||||
"skipIssue": false,
|
"with": {
|
||||||
"skipScoreboard": false,
|
"default": {
|
||||||
"skipFailedTable": false
|
"args": [
|
||||||
|
"run-clang-tidy-18",
|
||||||
|
"-header-filter=.*",
|
||||||
|
"-quiet",
|
||||||
|
"-load=/usr/local/lib/libcodequality.so",
|
||||||
|
"-p",
|
||||||
|
"h7/build",
|
||||||
|
"h7/ex2.cpp"
|
||||||
|
],
|
||||||
|
"env": [],
|
||||||
|
"stdin": {
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 4194304,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
|
"stackLimit": 0,
|
||||||
|
"procLimit": 50,
|
||||||
|
"cpuRateLimit": 0,
|
||||||
|
"cpuSetLimit": "",
|
||||||
|
"copyIn": {
|
||||||
|
"tests/homework/h7/.clang-tidy": {
|
||||||
|
"src": "/home/tt/.config/joj/tests/homework/h7/.clang-tidy"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"copyInCached": {
|
||||||
|
"h7/build/ex2": "h7/build/ex2",
|
||||||
|
"h7/build/ex2-asan": "h7/build/ex2-asan",
|
||||||
|
"h7/build/ex2-ubsan": "h7/build/ex2-ubsan",
|
||||||
|
"h7/build/ex2-msan": "h7/build/ex2-msan",
|
||||||
|
"h7/build/compile_commands.json": "h7/build/compile_commands.json"
|
||||||
|
},
|
||||||
|
"copyInDir": ".",
|
||||||
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
|
"copyOutMax": 0,
|
||||||
|
"copyOutDir": "",
|
||||||
|
"tty": false,
|
||||||
|
"strictMemoryLimit": false,
|
||||||
|
"dataSegmentLimit": false,
|
||||||
|
"addressSpaceLimit": false
|
||||||
|
},
|
||||||
|
"cases": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parsers": [
|
||||||
|
{
|
||||||
|
"name": "clangtidy",
|
||||||
|
"with": {
|
||||||
|
"matches": [
|
||||||
|
{
|
||||||
|
"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": [
|
||||||
|
"codequality-no-global-variables",
|
||||||
|
"codequality-no-header-guard",
|
||||||
|
"codequality-no-fflush-stdin"
|
||||||
|
],
|
||||||
|
"score": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"readability-function-size"
|
||||||
|
],
|
||||||
|
"score": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"readability-misleading-indentation"
|
||||||
|
],
|
||||||
|
"score": 15
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "result-detail",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "",
|
||||||
|
"showFiles": [
|
||||||
|
"stdout"
|
||||||
|
],
|
||||||
|
"showExitStatus": true,
|
||||||
|
"showRuntime": false,
|
||||||
|
"showMemory": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[cq] Cppcheck",
|
||||||
|
"group": "cq",
|
||||||
|
"executor": {
|
||||||
|
"name": "sandbox",
|
||||||
|
"with": {
|
||||||
|
"default": {
|
||||||
|
"args": [
|
||||||
|
"cppcheck",
|
||||||
|
"--template={\"file\":\"{file}\",\"line\":{line}, \"column\":{column}, \"severity\":\"{severity}\", \"message\":\"{message}\", \"id\":\"{id}\"}",
|
||||||
|
"--force",
|
||||||
|
"--enable=all",
|
||||||
|
"--suppress=missingIncludeSystem",
|
||||||
|
"--quiet",
|
||||||
|
"h7/ex2.cpp"
|
||||||
|
],
|
||||||
|
"env": [],
|
||||||
|
"stdin": {
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 8388608,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
|
"stackLimit": 0,
|
||||||
|
"procLimit": 50,
|
||||||
|
"cpuRateLimit": 0,
|
||||||
|
"cpuSetLimit": "",
|
||||||
|
"copyIn": {},
|
||||||
|
"copyInCached": {
|
||||||
|
"h7/build/ex2": "h7/build/ex2",
|
||||||
|
"h7/build/ex2-asan": "h7/build/ex2-asan",
|
||||||
|
"h7/build/ex2-ubsan": "h7/build/ex2-ubsan",
|
||||||
|
"h7/build/ex2-msan": "h7/build/ex2-msan",
|
||||||
|
"h7/build/compile_commands.json": "h7/build/compile_commands.json"
|
||||||
|
},
|
||||||
|
"copyInDir": ".",
|
||||||
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
|
"copyOutMax": 0,
|
||||||
|
"copyOutDir": "",
|
||||||
|
"tty": false,
|
||||||
|
"strictMemoryLimit": false,
|
||||||
|
"dataSegmentLimit": false,
|
||||||
|
"addressSpaceLimit": false
|
||||||
|
},
|
||||||
|
"cases": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parsers": [
|
||||||
|
{
|
||||||
|
"name": "keyword",
|
||||||
|
"with": {
|
||||||
|
"matches": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cppcheck",
|
||||||
|
"with": {
|
||||||
|
"matches": [
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"score": 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"warning",
|
||||||
|
"portability",
|
||||||
|
"performance",
|
||||||
|
"style"
|
||||||
|
],
|
||||||
|
"score": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "clangtidy",
|
||||||
|
"with": {
|
||||||
|
"matches": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "result-detail",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "",
|
||||||
|
"showFiles": [
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"showExitStatus": true,
|
||||||
|
"showRuntime": false,
|
||||||
|
"showMemory": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cpplint",
|
||||||
|
"with": {
|
||||||
|
"matches": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "result-status",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "",
|
||||||
|
"forceQuitOnNotAccepted": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "file",
|
||||||
|
"with": {
|
||||||
|
"name": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dummy",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "",
|
||||||
|
"forceQuitOnNotAccepted": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "diff",
|
||||||
|
"with": {
|
||||||
|
"name": "diff",
|
||||||
|
"cases": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[cq] Cpplint",
|
||||||
|
"group": "cq",
|
||||||
|
"executor": {
|
||||||
|
"name": "sandbox",
|
||||||
|
"with": {
|
||||||
|
"default": {
|
||||||
|
"args": [
|
||||||
|
"cpplint",
|
||||||
|
"--linelength=120",
|
||||||
|
"--filter=-legal,-readability/casting,-whitespace,-runtime/printf,-runtime/threadsafe_fn,-runtime/int,-readability/todo,-build/include_subdir,-build/header_guard,-build/include_what_you_use",
|
||||||
|
"--recursive",
|
||||||
|
"--exclude=build",
|
||||||
|
"h7/ex2.cpp"
|
||||||
|
],
|
||||||
|
"env": [],
|
||||||
|
"stdin": {
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 68157440,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
|
"stackLimit": 0,
|
||||||
|
"procLimit": 50,
|
||||||
|
"cpuRateLimit": 0,
|
||||||
|
"cpuSetLimit": "",
|
||||||
|
"copyIn": {},
|
||||||
|
"copyInCached": {
|
||||||
|
"h7/build/ex2": "h7/build/ex2",
|
||||||
|
"h7/build/ex2-asan": "h7/build/ex2-asan",
|
||||||
|
"h7/build/ex2-ubsan": "h7/build/ex2-ubsan",
|
||||||
|
"h7/build/ex2-msan": "h7/build/ex2-msan",
|
||||||
|
"h7/build/compile_commands.json": "h7/build/compile_commands.json"
|
||||||
|
},
|
||||||
|
"copyInDir": ".",
|
||||||
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
|
"copyOutMax": 0,
|
||||||
|
"copyOutDir": "",
|
||||||
|
"tty": false,
|
||||||
|
"strictMemoryLimit": false,
|
||||||
|
"dataSegmentLimit": false,
|
||||||
|
"addressSpaceLimit": false
|
||||||
|
},
|
||||||
|
"cases": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parsers": [
|
||||||
|
{
|
||||||
|
"name": "cpplint",
|
||||||
|
"with": {
|
||||||
|
"matches": [
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"runtime"
|
||||||
|
],
|
||||||
|
"score": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"readability"
|
||||||
|
],
|
||||||
|
"score": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"build"
|
||||||
|
],
|
||||||
|
"score": 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "result-detail",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "",
|
||||||
|
"showFiles": [
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"showExitStatus": true,
|
||||||
|
"showRuntime": false,
|
||||||
|
"showMemory": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "[joj] ex2-asan",
|
||||||
|
"group": "joj",
|
||||||
|
"executor": {
|
||||||
|
"name": "sandbox",
|
||||||
|
"with": {
|
||||||
|
"default": {
|
||||||
|
"args": [
|
||||||
|
"./h7/build/ex2-asan",
|
||||||
|
"-a"
|
||||||
|
],
|
||||||
|
"env": [],
|
||||||
|
"stdin": {
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
|
"stackLimit": 0,
|
||||||
|
"procLimit": 50,
|
||||||
|
"cpuRateLimit": 0,
|
||||||
|
"cpuSetLimit": "",
|
||||||
|
"copyIn": {},
|
||||||
|
"copyInCached": {
|
||||||
|
"h7/build/ex2": "h7/build/ex2",
|
||||||
|
"h7/build/ex2-asan": "h7/build/ex2-asan",
|
||||||
|
"h7/build/ex2-ubsan": "h7/build/ex2-ubsan",
|
||||||
|
"h7/build/ex2-msan": "h7/build/ex2-msan",
|
||||||
|
"h7/build/compile_commands.json": "h7/build/compile_commands.json"
|
||||||
|
},
|
||||||
|
"copyInDir": ".",
|
||||||
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
|
"copyOutMax": 0,
|
||||||
|
"copyOutDir": "",
|
||||||
|
"tty": false,
|
||||||
|
"strictMemoryLimit": false,
|
||||||
|
"dataSegmentLimit": false,
|
||||||
|
"addressSpaceLimit": false
|
||||||
|
},
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"stdin": {
|
||||||
|
"src": "/home/tt/.config/joj/basic/case0.in"
|
||||||
|
},
|
||||||
|
"cpuLimit": 500000000,
|
||||||
|
"clockLimit": 1000000000,
|
||||||
|
"memoryLimit": 5242880,
|
||||||
|
"procLimit": 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stdin": {
|
||||||
|
"src": "/home/tt/.config/joj/basic/case1.in"
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 5242880,
|
||||||
|
"procLimit": 50
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parsers": [
|
||||||
|
{
|
||||||
|
"name": "diff",
|
||||||
|
"with": {
|
||||||
|
"name": "diff",
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"score": 5,
|
||||||
|
"fileName": "stdout",
|
||||||
|
"answerPath": "/home/tt/.config/joj/basic/case0.out",
|
||||||
|
"forceQuitOnDiff": false,
|
||||||
|
"alwaysHide": false,
|
||||||
|
"compareSpace": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"score": 5,
|
||||||
|
"fileName": "stdout",
|
||||||
|
"answerPath": "/home/tt/.config/joj/basic/case1.out",
|
||||||
|
"forceQuitOnDiff": false,
|
||||||
|
"alwaysHide": false,
|
||||||
|
"compareSpace": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "result-detail",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "",
|
||||||
|
"showFiles": [
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"showExitStatus": true,
|
||||||
|
"showRuntime": true,
|
||||||
|
"showMemory": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preStages": [],
|
||||||
|
"postStages": [
|
||||||
|
{
|
||||||
|
"name": "teapot",
|
||||||
|
"group": "",
|
||||||
|
"executor": {
|
||||||
|
"name": "local",
|
||||||
|
"with": {
|
||||||
|
"default": {
|
||||||
|
"args": [
|
||||||
|
"/usr/local/bin/joint-teapot",
|
||||||
|
"joj3-all-env",
|
||||||
|
"/home/tt/.config/teapot/teapot.env",
|
||||||
|
"--grading-repo-name",
|
||||||
|
"ece280-joj",
|
||||||
|
"--max-total-score",
|
||||||
|
"100"
|
||||||
|
],
|
||||||
|
"env": [
|
||||||
|
"LOG_FILE_PATH=/home/tt/.cache/joint-teapot-debug.log"
|
||||||
|
],
|
||||||
|
"stdin": {
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
|
"stackLimit": 0,
|
||||||
|
"procLimit": 50,
|
||||||
|
"cpuRateLimit": 0,
|
||||||
|
"cpuSetLimit": "",
|
||||||
|
"copyIn": {},
|
||||||
|
"copyInCached": {},
|
||||||
|
"copyInDir": ".",
|
||||||
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
|
"copyOutMax": 0,
|
||||||
|
"copyOutDir": "",
|
||||||
|
"tty": false,
|
||||||
|
"strictMemoryLimit": false,
|
||||||
|
"dataSegmentLimit": false,
|
||||||
|
"addressSpaceLimit": false
|
||||||
|
},
|
||||||
|
"cases": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parsers": [
|
||||||
|
{
|
||||||
|
"name": "log",
|
||||||
|
"with": {
|
||||||
|
"msg": "joj3 summary"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,102 @@
|
||||||
task = "hw3 ex5"
|
# general task configuration
|
||||||
|
task.name = "hw7 ex2" # task name
|
||||||
|
task.type = "homework/h7/e2" # remove this task type later
|
||||||
|
|
||||||
[release]
|
release.end_time = 2024-12-30 23:59:59+08:00
|
||||||
deadline = "2024-10-18T23:59:00+08:00"
|
release.begin_time = 2024-12-29 23:59:59+08:00
|
||||||
|
|
||||||
[[stages]]
|
[[stages]]
|
||||||
name = "judge_base"
|
name = "Compilation"
|
||||||
command = "./matlab-joj ./h3/ex5.m"
|
command = "./tools/compile" # eg. script running cmake commands
|
||||||
score = 100
|
files.import = [ "tools/compile" ]
|
||||||
parsers = ["diff", "result-detail"]
|
files.export = [ "h7/build/ex2", "h7/build/ex2-asan", "h7/build/ex2-ubsan", "h7/build/ex2-msan", "h7/build/compile_commands.json" ]
|
||||||
|
score = 1
|
||||||
|
|
||||||
files.import = ["tools/matlab-joj", "tools/matlab_formatter.py"]
|
# compile parsers
|
||||||
files.export = ["output/ex5_results.txt", "output/ex5_logs.txt"]
|
parsers = [ "result-detail", "result-status" ]
|
||||||
|
result-status.comment = "Congratulations! Your code compiled successfully."
|
||||||
result_detail.time = false
|
result-detail.exitstatus = true
|
||||||
result_detail.mem = false
|
result-detail.stderr = true
|
||||||
result_detail.stderr = true
|
result-detail.time = false
|
||||||
|
result-detail.mem = false
|
||||||
|
result-status.force_quit = true
|
||||||
|
|
||||||
[[stages]]
|
[[stages]]
|
||||||
name = "judge_base2"
|
name = "[cq] Filelength"
|
||||||
command = "./matlab-joj ./h3/ex5.m"
|
command = "./tools/filelength 400 300 *.cpp *.h"
|
||||||
score = 80
|
files.import = [ "tools/filelength" ]
|
||||||
|
|
||||||
|
parsers = [ "keyword", "result-detail" ]
|
||||||
|
keyword.keyword = [ "max", "recommended"]
|
||||||
|
keyword.weight = [ 20, 10 ]
|
||||||
|
result-detail.exitstatus = true
|
||||||
|
result-detail.stdout = true
|
||||||
|
result-detail.time = false
|
||||||
|
result-detail.mem = false
|
||||||
|
|
||||||
|
[[stages]]
|
||||||
|
name = "[cq] Clang-tidy"
|
||||||
|
command = "run-clang-tidy-18 -header-filter=.* -quiet -load=/usr/local/lib/libcodequality.so -p h7/build h7/ex2.cpp"
|
||||||
|
files.import = [ "tests/homework/h7/.clang-tidy", "h7/build/compile_commands.json" ]
|
||||||
|
limit.stdout = "4m"
|
||||||
|
|
||||||
|
parsers = [ "clangtidy", "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]
|
||||||
|
result-detail.exitstatus = true
|
||||||
|
result-detail.stdout = true
|
||||||
|
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 h7/ex2.cpp"
|
||||||
|
limit.stderr = "8m"
|
||||||
|
|
||||||
|
parsers = [ "keyword", "cppcheck", "clangtidy", "result-detail", "cpplint", "result-status", "file", "dummy", "diff" ]
|
||||||
|
cppcheck.keyword = ["error", "warning", "portability", "performance", "style"]
|
||||||
|
cppcheck.weight = [15, 5, 5, 5, 5]
|
||||||
|
result-detail.exitstatus = true
|
||||||
|
result-detail.stderr = true
|
||||||
|
result-detail.time = false
|
||||||
|
result-detail.mem = false
|
||||||
|
|
||||||
|
[[stages]]
|
||||||
|
name = "[cq] Cpplint"
|
||||||
|
command = "cpplint --linelength=120 --filter=-legal,-readability/casting,-whitespace,-runtime/printf,-runtime/threadsafe_fn,-runtime/int,-readability/todo,-build/include_subdir,-build/header_guard,-build/include_what_you_use --recursive --exclude=build h7/ex2.cpp"
|
||||||
|
limit.stdout = "65m"
|
||||||
|
|
||||||
|
parsers = [ "cpplint", "result-detail" ]
|
||||||
|
cpplint.keyword = [ "runtime", "readability", "build" ]
|
||||||
|
cpplint.weight = [ 5, 20, 10]
|
||||||
|
result-detail.exitstatus = true
|
||||||
|
result-detail.stderr = true
|
||||||
|
result-detail.time = false
|
||||||
|
result-detail.mem = false
|
||||||
|
|
||||||
|
[[stages]]
|
||||||
|
name = "[joj] ex2-asan"
|
||||||
|
command="./h7/build/ex2-asan -a"
|
||||||
|
files.import = [ "h7/build/ex2-asan" ]
|
||||||
|
limit.mem = "128m"
|
||||||
|
|
||||||
parsers = [ "diff", "result-detail" ]
|
parsers = [ "diff", "result-detail" ]
|
||||||
|
result-detail.exitstatus = true
|
||||||
|
result-detail.stderr = true
|
||||||
|
|
||||||
files.import = ["tools/matlab-joj", "tools/matlab_formatter.py"]
|
# will be removed as long as the name is fixed
|
||||||
files.export = ["output/ex5_results2.txt", "output/ex5_logs2.txt"]
|
case0.diff.output.score = 5
|
||||||
|
case0.limit.cpu = "0.5s"
|
||||||
|
case0.limit.mem = "5m"
|
||||||
|
case0.diff.output.ignore_spaces = true
|
||||||
|
#case0.limit.stdout = 8
|
||||||
|
#case0.command = "./h7/build/ex2"
|
||||||
|
case0.in = "case0.in"
|
||||||
|
|
||||||
result_detail.time = true
|
case1.diff.output.score = 5
|
||||||
result_detail.mem = true
|
case1.limit.cpu = "1s"
|
||||||
result_detail.stderr = false
|
case1.limit.mem = "5m"
|
||||||
|
case1.diff.output.ignore_spaces = true
|
||||||
|
#case1.limit.stdout = 8
|
||||||
|
#case1.command = "./h7/build/ex2"
|
||||||
|
case1.in = "case1.in"
|
||||||
|
|
2
tests/convert/clang-tidy/repo.toml
Normal file
2
tests/convert/clang-tidy/repo.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
force_skip_health_check_on_test = true
|
||||||
|
force_skip_teapot_on_test = true
|
140
tests/convert/clang-tidy/task.json
Normal file
140
tests/convert/clang-tidy/task.json
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
{
|
||||||
|
"name": "hw7 ex2",
|
||||||
|
"logPath": "/home/tt/.cache/joj3/homework/h7/e2.log",
|
||||||
|
"expireUnixTimestamp": 1735574399,
|
||||||
|
"effectiveUnixTimestamp": 1735487999,
|
||||||
|
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||||
|
"maxTotalScore": 100,
|
||||||
|
"stage": {
|
||||||
|
"sandboxExecServer": "172.17.0.1:5051",
|
||||||
|
"sandboxToken": "",
|
||||||
|
"outputPath": "/tmp/joj3_result.json",
|
||||||
|
"stages": [
|
||||||
|
{
|
||||||
|
"name": "[cq] Clang-tidy",
|
||||||
|
"group": "cq",
|
||||||
|
"executor": {
|
||||||
|
"name": "sandbox",
|
||||||
|
"with": {
|
||||||
|
"default": {
|
||||||
|
"args": [
|
||||||
|
"run-clang-tidy-18",
|
||||||
|
"-header-filter=.*",
|
||||||
|
"-quiet",
|
||||||
|
"-load=/usr/local/lib/libcodequality.so",
|
||||||
|
"-p",
|
||||||
|
"h7/build",
|
||||||
|
"h7/ex2.cpp"
|
||||||
|
],
|
||||||
|
"env": [],
|
||||||
|
"stdin": {
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 68157440,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
|
"stackLimit": 0,
|
||||||
|
"procLimit": 50,
|
||||||
|
"cpuRateLimit": 0,
|
||||||
|
"cpuSetLimit": "",
|
||||||
|
"copyIn": {
|
||||||
|
"tests/homework/h7/.clang-tidy": {
|
||||||
|
"src": "/home/tt/.config/joj/tests/homework/h7/.clang-tidy"
|
||||||
|
},
|
||||||
|
"h7/build/compile_commands.json": {
|
||||||
|
"src": "/home/tt/.config/joj/h7/build/compile_commands.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"copyInCached": {},
|
||||||
|
"copyInDir": ".",
|
||||||
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
|
"copyOutMax": 0,
|
||||||
|
"copyOutDir": "",
|
||||||
|
"tty": false,
|
||||||
|
"strictMemoryLimit": false,
|
||||||
|
"dataSegmentLimit": false,
|
||||||
|
"addressSpaceLimit": false
|
||||||
|
},
|
||||||
|
"cases": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parsers": [
|
||||||
|
{
|
||||||
|
"name": "clangtidy",
|
||||||
|
"with": {
|
||||||
|
"matches": [
|
||||||
|
{
|
||||||
|
"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": [
|
||||||
|
"codequality-no-global-variables",
|
||||||
|
"codequality-no-header-guard",
|
||||||
|
"codequality-no-fflush-stdin"
|
||||||
|
],
|
||||||
|
"score": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"readability-function-size"
|
||||||
|
],
|
||||||
|
"score": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"readability-misleading-indentation"
|
||||||
|
],
|
||||||
|
"score": 15
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "result-detail",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "",
|
||||||
|
"showFiles": [
|
||||||
|
"stdout"
|
||||||
|
],
|
||||||
|
"showExitStatus": true,
|
||||||
|
"showRuntime": false,
|
||||||
|
"showMemory": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preStages": [],
|
||||||
|
"postStages": []
|
||||||
|
}
|
||||||
|
}
|
20
tests/convert/clang-tidy/task.toml
Normal file
20
tests/convert/clang-tidy/task.toml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# general task configuration
|
||||||
|
task.name = "hw7 ex2" # task name
|
||||||
|
task.type = "homework/h7/e2" # remove this task type later
|
||||||
|
|
||||||
|
release.end_time = 2024-12-30 23:59:59+08:00
|
||||||
|
release.begin_time = 2024-12-29 23:59:59+08:00
|
||||||
|
|
||||||
|
[[stages]]
|
||||||
|
name = "[cq] Clang-tidy"
|
||||||
|
command = "run-clang-tidy-18 -header-filter=.* -quiet -load=/usr/local/lib/libcodequality.so -p h7/build h7/ex2.cpp"
|
||||||
|
files.import = [ "tests/homework/h7/.clang-tidy", "h7/build/compile_commands.json" ]
|
||||||
|
limit.stdout = "65m"
|
||||||
|
|
||||||
|
parsers = [ "clangtidy", "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]
|
||||||
|
result-detail.exitstatus = true
|
||||||
|
result-detail.stdout = true
|
||||||
|
result-detail.time = false
|
||||||
|
result-detail.mem = false
|
2
tests/convert/cppcheck/repo.toml
Normal file
2
tests/convert/cppcheck/repo.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
force_skip_health_check_on_test = true
|
||||||
|
force_skip_teapot_on_test = true
|
110
tests/convert/cppcheck/task.json
Normal file
110
tests/convert/cppcheck/task.json
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
{
|
||||||
|
"name": "hw7 ex2",
|
||||||
|
"logPath": "/home/tt/.cache/joj3/homework/h7/e2.log",
|
||||||
|
"expireUnixTimestamp": 1735574399,
|
||||||
|
"effectiveUnixTimestamp": 1735487999,
|
||||||
|
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||||
|
"maxTotalScore": 100,
|
||||||
|
"stage": {
|
||||||
|
"sandboxExecServer": "172.17.0.1:5051",
|
||||||
|
"sandboxToken": "",
|
||||||
|
"outputPath": "/tmp/joj3_result.json",
|
||||||
|
"stages": [
|
||||||
|
{
|
||||||
|
"name": "[cq] Cppcheck",
|
||||||
|
"group": "cq",
|
||||||
|
"executor": {
|
||||||
|
"name": "sandbox",
|
||||||
|
"with": {
|
||||||
|
"default": {
|
||||||
|
"args": [
|
||||||
|
"cppcheck",
|
||||||
|
"--template={\"file\":\"{file}\",\"line\":{line}, \"column\":{column}, \"severity\":\"{severity}\", \"message\":\"{message}\", \"id\":\"{id}\"}",
|
||||||
|
"--force",
|
||||||
|
"--enable=all",
|
||||||
|
"--suppress=missingIncludeSystem",
|
||||||
|
"--quiet",
|
||||||
|
"h7/ex2.cpp"
|
||||||
|
],
|
||||||
|
"env": [],
|
||||||
|
"stdin": {
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 68157440,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
|
"stackLimit": 0,
|
||||||
|
"procLimit": 50,
|
||||||
|
"cpuRateLimit": 0,
|
||||||
|
"cpuSetLimit": "",
|
||||||
|
"copyIn": {},
|
||||||
|
"copyInCached": {},
|
||||||
|
"copyInDir": ".",
|
||||||
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
|
"copyOutMax": 0,
|
||||||
|
"copyOutDir": "",
|
||||||
|
"tty": false,
|
||||||
|
"strictMemoryLimit": false,
|
||||||
|
"dataSegmentLimit": false,
|
||||||
|
"addressSpaceLimit": false
|
||||||
|
},
|
||||||
|
"cases": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parsers": [
|
||||||
|
{
|
||||||
|
"name": "cppcheck",
|
||||||
|
"with": {
|
||||||
|
"matches": [
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"error"
|
||||||
|
],
|
||||||
|
"score": 15
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"warning",
|
||||||
|
"portability",
|
||||||
|
"performance",
|
||||||
|
"style"
|
||||||
|
],
|
||||||
|
"score": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "result-detail",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "",
|
||||||
|
"showFiles": [
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"showExitStatus": true,
|
||||||
|
"showRuntime": false,
|
||||||
|
"showMemory": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preStages": [],
|
||||||
|
"postStages": []
|
||||||
|
}
|
||||||
|
}
|
19
tests/convert/cppcheck/task.toml
Normal file
19
tests/convert/cppcheck/task.toml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# general task configuration
|
||||||
|
task.name = "hw7 ex2" # task name
|
||||||
|
task.type = "homework/h7/e2" # remove this task type later
|
||||||
|
|
||||||
|
release.end_time = 2024-12-30 23:59:59+08:00
|
||||||
|
release.begin_time = 2024-12-29 23:59:59+08:00
|
||||||
|
|
||||||
|
[[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 h7/ex2.cpp"
|
||||||
|
limit.stderr = "65m"
|
||||||
|
|
||||||
|
parsers = [ "cppcheck", "result-detail" ]
|
||||||
|
cppcheck.keyword = ["error", "warning", "portability", "performance", "style"]
|
||||||
|
cppcheck.weight = [15, 5, 5, 5, 5]
|
||||||
|
result-detail.exitstatus = true
|
||||||
|
result-detail.stderr = true
|
||||||
|
result-detail.time = false
|
||||||
|
result-detail.mem = false
|
2
tests/convert/cpplint/repo.toml
Normal file
2
tests/convert/cpplint/repo.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
force_skip_health_check_on_test = true
|
||||||
|
force_skip_teapot_on_test = true
|
112
tests/convert/cpplint/task.json
Normal file
112
tests/convert/cpplint/task.json
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
{
|
||||||
|
"name": "hw7 ex2",
|
||||||
|
"logPath": "/home/tt/.cache/joj3/homework/h7/e2.log",
|
||||||
|
"expireUnixTimestamp": 1735574399,
|
||||||
|
"effectiveUnixTimestamp": 1735487999,
|
||||||
|
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||||
|
"maxTotalScore": 100,
|
||||||
|
"stage": {
|
||||||
|
"sandboxExecServer": "172.17.0.1:5051",
|
||||||
|
"sandboxToken": "",
|
||||||
|
"outputPath": "/tmp/joj3_result.json",
|
||||||
|
"stages": [
|
||||||
|
{
|
||||||
|
"name": "[cq] Cpplint",
|
||||||
|
"group": "cq",
|
||||||
|
"executor": {
|
||||||
|
"name": "sandbox",
|
||||||
|
"with": {
|
||||||
|
"default": {
|
||||||
|
"args": [
|
||||||
|
"cpplint",
|
||||||
|
"--linelength=120",
|
||||||
|
"--filter=-legal,-readability/casting,-whitespace,-runtime/printf,-runtime/threadsafe_fn,-runtime/int,-readability/todo,-build/include_subdir,-build/header_guard,-build/include_what_you_use",
|
||||||
|
"--recursive",
|
||||||
|
"--exclude=build",
|
||||||
|
"h7/ex2.cpp"
|
||||||
|
],
|
||||||
|
"env": [],
|
||||||
|
"stdin": {
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 68157440,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
|
"stackLimit": 0,
|
||||||
|
"procLimit": 50,
|
||||||
|
"cpuRateLimit": 0,
|
||||||
|
"cpuSetLimit": "",
|
||||||
|
"copyIn": {},
|
||||||
|
"copyInCached": {},
|
||||||
|
"copyInDir": ".",
|
||||||
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
|
"copyOutMax": 0,
|
||||||
|
"copyOutDir": "",
|
||||||
|
"tty": false,
|
||||||
|
"strictMemoryLimit": false,
|
||||||
|
"dataSegmentLimit": false,
|
||||||
|
"addressSpaceLimit": false
|
||||||
|
},
|
||||||
|
"cases": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parsers": [
|
||||||
|
{
|
||||||
|
"name": "cpplint",
|
||||||
|
"with": {
|
||||||
|
"matches": [
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"runtime"
|
||||||
|
],
|
||||||
|
"score": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"readability"
|
||||||
|
],
|
||||||
|
"score": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"build"
|
||||||
|
],
|
||||||
|
"score": 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "result-detail",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "",
|
||||||
|
"showFiles": [
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"showExitStatus": true,
|
||||||
|
"showRuntime": false,
|
||||||
|
"showMemory": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preStages": [],
|
||||||
|
"postStages": []
|
||||||
|
}
|
||||||
|
}
|
19
tests/convert/cpplint/task.toml
Normal file
19
tests/convert/cpplint/task.toml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# general task configuration
|
||||||
|
task.name = "hw7 ex2" # task name
|
||||||
|
task.type = "homework/h7/e2" # remove this task type later
|
||||||
|
|
||||||
|
release.end_time = 2024-12-30 23:59:59+08:00
|
||||||
|
release.begin_time = 2024-12-29 23:59:59+08:00
|
||||||
|
|
||||||
|
[[stages]]
|
||||||
|
name = "[cq] Cpplint"
|
||||||
|
command = "cpplint --linelength=120 --filter=-legal,-readability/casting,-whitespace,-runtime/printf,-runtime/threadsafe_fn,-runtime/int,-readability/todo,-build/include_subdir,-build/header_guard,-build/include_what_you_use --recursive --exclude=build h7/ex2.cpp"
|
||||||
|
limit.stdout = "65m"
|
||||||
|
|
||||||
|
parsers = [ "cpplint", "result-detail" ]
|
||||||
|
cpplint.keyword = [ "runtime", "readability", "build" ]
|
||||||
|
cpplint.weight = [ 5, 20, 10]
|
||||||
|
result-detail.exitstatus = true
|
||||||
|
result-detail.stderr = true
|
||||||
|
result-detail.time = false
|
||||||
|
result-detail.mem = false
|
2
tests/convert/diff/repo.toml
Normal file
2
tests/convert/diff/repo.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
force_skip_health_check_on_test = true
|
||||||
|
force_skip_teapot_on_test = true
|
138
tests/convert/diff/task.json
Normal file
138
tests/convert/diff/task.json
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
{
|
||||||
|
"name": "hw7 ex2",
|
||||||
|
"logPath": "/home/tt/.cache/joj3/homework/h7/e2.log",
|
||||||
|
"expireUnixTimestamp": 1735574399,
|
||||||
|
"effectiveUnixTimestamp": 1735487999,
|
||||||
|
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||||
|
"maxTotalScore": 100,
|
||||||
|
"stage": {
|
||||||
|
"sandboxExecServer": "172.17.0.1:5051",
|
||||||
|
"sandboxToken": "",
|
||||||
|
"outputPath": "/tmp/joj3_result.json",
|
||||||
|
"stages": [
|
||||||
|
{
|
||||||
|
"name": "[joj] ex2-asan",
|
||||||
|
"group": "joj",
|
||||||
|
"executor": {
|
||||||
|
"name": "sandbox",
|
||||||
|
"with": {
|
||||||
|
"default": {
|
||||||
|
"args": [
|
||||||
|
"./h7/build/ex2-asan",
|
||||||
|
"-a"
|
||||||
|
],
|
||||||
|
"env": [],
|
||||||
|
"stdin": {
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 68157440,
|
||||||
|
"stackLimit": 0,
|
||||||
|
"procLimit": 50,
|
||||||
|
"cpuRateLimit": 0,
|
||||||
|
"cpuSetLimit": "",
|
||||||
|
"copyIn": {
|
||||||
|
"h7/build/ex2-asan": {
|
||||||
|
"src": "/home/tt/.config/joj/h7/build/ex2-asan"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"copyInCached": {},
|
||||||
|
"copyInDir": ".",
|
||||||
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
|
"copyOutMax": 0,
|
||||||
|
"copyOutDir": "",
|
||||||
|
"tty": false,
|
||||||
|
"strictMemoryLimit": false,
|
||||||
|
"dataSegmentLimit": false,
|
||||||
|
"addressSpaceLimit": false
|
||||||
|
},
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"stdin": {
|
||||||
|
"src": "/home/tt/.config/joj/diff/case0.in"
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 2097152,
|
||||||
|
"procLimit": 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stdin": {
|
||||||
|
"src": "/home/tt/.config/joj/diff/case1.in"
|
||||||
|
},
|
||||||
|
"cpuLimit": 2000000000,
|
||||||
|
"clockLimit": 4000000000,
|
||||||
|
"memoryLimit": 4194304,
|
||||||
|
"procLimit": 50
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parsers": [
|
||||||
|
{
|
||||||
|
"name": "diff",
|
||||||
|
"with": {
|
||||||
|
"name": "diff",
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"score": 5,
|
||||||
|
"fileName": "stdout",
|
||||||
|
"answerPath": "/home/tt/.config/joj/diff/case0.out",
|
||||||
|
"forceQuitOnDiff": false,
|
||||||
|
"alwaysHide": false,
|
||||||
|
"compareSpace": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"score": 5,
|
||||||
|
"fileName": "stdout",
|
||||||
|
"answerPath": "/home/tt/.config/joj/diff/case1.out",
|
||||||
|
"forceQuitOnDiff": false,
|
||||||
|
"alwaysHide": false,
|
||||||
|
"compareSpace": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "result-detail",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "",
|
||||||
|
"showFiles": [
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"showExitStatus": true,
|
||||||
|
"showRuntime": true,
|
||||||
|
"showMemory": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preStages": [],
|
||||||
|
"postStages": []
|
||||||
|
}
|
||||||
|
}
|
33
tests/convert/diff/task.toml
Normal file
33
tests/convert/diff/task.toml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# general task configuration
|
||||||
|
task.name = "hw7 ex2" # task name
|
||||||
|
task.type = "homework/h7/e2" # remove this task type later
|
||||||
|
|
||||||
|
release.end_time = 2024-12-30 23:59:59+08:00
|
||||||
|
release.begin_time = 2024-12-29 23:59:59+08:00
|
||||||
|
|
||||||
|
[[stages]]
|
||||||
|
name = "[joj] ex2-asan"
|
||||||
|
command="./h7/build/ex2-asan -a"
|
||||||
|
files.import = [ "h7/build/ex2-asan" ]
|
||||||
|
limit.mem = "65m"
|
||||||
|
|
||||||
|
parsers = [ "diff", "result-detail" ]
|
||||||
|
result-detail.exitstatus = true
|
||||||
|
result-detail.stderr = true
|
||||||
|
|
||||||
|
# will be removed as long as the name is fixed
|
||||||
|
case0.diff.output.score = 5
|
||||||
|
case0.limit.cpu = "1s"
|
||||||
|
case0.limit.mem = "2m"
|
||||||
|
case0.diff.output.ignore_spaces = true
|
||||||
|
#case0.limit.stdout = 8
|
||||||
|
#case0.command = "./h7/build/ex2"
|
||||||
|
case0.in = "case0.in"
|
||||||
|
|
||||||
|
case1.diff.output.score = 5
|
||||||
|
case1.limit.cpu = "2s"
|
||||||
|
case1.limit.mem = "4m"
|
||||||
|
case1.diff.output.ignore_spaces = true
|
||||||
|
#case1.limit.stdout = 8
|
||||||
|
#case1.command = "./h7/build/ex2"
|
||||||
|
case1.in = "case1.in"
|
2
tests/convert/keyword/repo.toml
Normal file
2
tests/convert/keyword/repo.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
force_skip_health_check_on_test = true
|
||||||
|
force_skip_teapot_on_test = true
|
109
tests/convert/keyword/task.json
Normal file
109
tests/convert/keyword/task.json
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
{
|
||||||
|
"name": "hw7 ex2",
|
||||||
|
"logPath": "/home/tt/.cache/joj3/homework/h7/e2.log",
|
||||||
|
"expireUnixTimestamp": 1735574399,
|
||||||
|
"effectiveUnixTimestamp": 1735487999,
|
||||||
|
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||||
|
"maxTotalScore": 100,
|
||||||
|
"stage": {
|
||||||
|
"sandboxExecServer": "172.17.0.1:5051",
|
||||||
|
"sandboxToken": "",
|
||||||
|
"outputPath": "/tmp/joj3_result.json",
|
||||||
|
"stages": [
|
||||||
|
{
|
||||||
|
"name": "[cq] Filelength",
|
||||||
|
"group": "cq",
|
||||||
|
"executor": {
|
||||||
|
"name": "sandbox",
|
||||||
|
"with": {
|
||||||
|
"default": {
|
||||||
|
"args": [
|
||||||
|
"./tools/filelength",
|
||||||
|
"400",
|
||||||
|
"300",
|
||||||
|
"*.cpp",
|
||||||
|
"*.h"
|
||||||
|
],
|
||||||
|
"env": [],
|
||||||
|
"stdin": {
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
|
"stackLimit": 0,
|
||||||
|
"procLimit": 50,
|
||||||
|
"cpuRateLimit": 0,
|
||||||
|
"cpuSetLimit": "",
|
||||||
|
"copyIn": {
|
||||||
|
"tools/filelength": {
|
||||||
|
"src": "/home/tt/.config/joj/tools/filelength"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"copyInCached": {},
|
||||||
|
"copyInDir": ".",
|
||||||
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
|
"copyOutMax": 0,
|
||||||
|
"copyOutDir": "",
|
||||||
|
"tty": false,
|
||||||
|
"strictMemoryLimit": false,
|
||||||
|
"dataSegmentLimit": false,
|
||||||
|
"addressSpaceLimit": false
|
||||||
|
},
|
||||||
|
"cases": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parsers": [
|
||||||
|
{
|
||||||
|
"name": "keyword",
|
||||||
|
"with": {
|
||||||
|
"matches": [
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"max"
|
||||||
|
],
|
||||||
|
"score": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"keywords": [
|
||||||
|
"recommended"
|
||||||
|
],
|
||||||
|
"score": 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "result-detail",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "",
|
||||||
|
"showFiles": [
|
||||||
|
"stdout"
|
||||||
|
],
|
||||||
|
"showExitStatus": true,
|
||||||
|
"showRuntime": false,
|
||||||
|
"showMemory": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preStages": [],
|
||||||
|
"postStages": []
|
||||||
|
}
|
||||||
|
}
|
19
tests/convert/keyword/task.toml
Normal file
19
tests/convert/keyword/task.toml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# general task configuration
|
||||||
|
task.name = "hw7 ex2" # task name
|
||||||
|
task.type = "homework/h7/e2" # remove this task type later
|
||||||
|
|
||||||
|
release.end_time = 2024-12-30 23:59:59+08:00
|
||||||
|
release.begin_time = 2024-12-29 23:59:59+08:00
|
||||||
|
|
||||||
|
[[stages]]
|
||||||
|
name = "[cq] Filelength"
|
||||||
|
command = "./tools/filelength 400 300 *.cpp *.h"
|
||||||
|
files.import = [ "tools/filelength" ]
|
||||||
|
|
||||||
|
parsers = [ "keyword", "result-detail" ]
|
||||||
|
keyword.keyword = [ "max", "recommended"]
|
||||||
|
keyword.weight = [ 20, 10 ]
|
||||||
|
result-detail.exitstatus = true
|
||||||
|
result-detail.stdout = true
|
||||||
|
result-detail.time = false
|
||||||
|
result-detail.mem = false
|
2
tests/convert/result-detail/repo.toml
Normal file
2
tests/convert/result-detail/repo.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
force_skip_health_check_on_test = true
|
||||||
|
force_skip_teapot_on_test = true
|
91
tests/convert/result-detail/task.json
Normal file
91
tests/convert/result-detail/task.json
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
{
|
||||||
|
"name": "hw7 ex2",
|
||||||
|
"logPath": "/home/tt/.cache/joj3/homework/h7/e2.log",
|
||||||
|
"expireUnixTimestamp": 1735574399,
|
||||||
|
"effectiveUnixTimestamp": 1735487999,
|
||||||
|
"actorCsvPath": "/home/tt/.config/joj/students.csv",
|
||||||
|
"maxTotalScore": 100,
|
||||||
|
"stage": {
|
||||||
|
"sandboxExecServer": "172.17.0.1:5051",
|
||||||
|
"sandboxToken": "",
|
||||||
|
"outputPath": "/tmp/joj3_result.json",
|
||||||
|
"stages": [
|
||||||
|
{
|
||||||
|
"name": "[cq] Filelength",
|
||||||
|
"group": "cq",
|
||||||
|
"executor": {
|
||||||
|
"name": "sandbox",
|
||||||
|
"with": {
|
||||||
|
"default": {
|
||||||
|
"args": [
|
||||||
|
"./tools/filelength",
|
||||||
|
"400",
|
||||||
|
"300",
|
||||||
|
"*.cpp",
|
||||||
|
"*.h"
|
||||||
|
],
|
||||||
|
"env": [],
|
||||||
|
"stdin": {
|
||||||
|
"content": ""
|
||||||
|
},
|
||||||
|
"stdout": {
|
||||||
|
"name": "stdout",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"stderr": {
|
||||||
|
"name": "stderr",
|
||||||
|
"max": 33554432,
|
||||||
|
"pipe": true
|
||||||
|
},
|
||||||
|
"cpuLimit": 1000000000,
|
||||||
|
"clockLimit": 2000000000,
|
||||||
|
"memoryLimit": 134217728,
|
||||||
|
"stackLimit": 0,
|
||||||
|
"procLimit": 50,
|
||||||
|
"cpuRateLimit": 0,
|
||||||
|
"cpuSetLimit": "",
|
||||||
|
"copyIn": {
|
||||||
|
"tools/filelength": {
|
||||||
|
"src": "/home/tt/.config/joj/tools/filelength"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"copyInCached": {},
|
||||||
|
"copyInDir": ".",
|
||||||
|
"copyOut": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"copyOutCached": [],
|
||||||
|
"copyOutMax": 0,
|
||||||
|
"copyOutDir": "",
|
||||||
|
"tty": false,
|
||||||
|
"strictMemoryLimit": false,
|
||||||
|
"dataSegmentLimit": false,
|
||||||
|
"addressSpaceLimit": false
|
||||||
|
},
|
||||||
|
"cases": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parsers": [
|
||||||
|
{
|
||||||
|
"name": "result-detail",
|
||||||
|
"with": {
|
||||||
|
"score": 0,
|
||||||
|
"comment": "",
|
||||||
|
"showFiles": [
|
||||||
|
"stdout",
|
||||||
|
"stderr"
|
||||||
|
],
|
||||||
|
"showExitStatus": true,
|
||||||
|
"showRuntime": false,
|
||||||
|
"showMemory": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preStages": [],
|
||||||
|
"postStages": []
|
||||||
|
}
|
||||||
|
}
|
18
tests/convert/result-detail/task.toml
Normal file
18
tests/convert/result-detail/task.toml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# general task configuration
|
||||||
|
task.name = "hw7 ex2" # task name
|
||||||
|
task.type = "homework/h7/e2" # remove this task type later
|
||||||
|
|
||||||
|
release.end_time = 2024-12-30 23:59:59+08:00
|
||||||
|
release.begin_time = 2024-12-29 23:59:59+08:00
|
||||||
|
|
||||||
|
[[stages]]
|
||||||
|
name = "[cq] Filelength"
|
||||||
|
command = "./tools/filelength 400 300 *.cpp *.h"
|
||||||
|
files.import = [ "tools/filelength" ]
|
||||||
|
|
||||||
|
parsers = [ "result-detail" ]
|
||||||
|
result-detail.exitstatus = true
|
||||||
|
result-detail.stdout = true
|
||||||
|
result-detail.stderr = true
|
||||||
|
result-detail.time = false
|
||||||
|
result-detail.mem = false
|
|
@ -3,3 +3,27 @@ from tests.convert.utils import load_case
|
||||||
|
|
||||||
def test_basic() -> None:
|
def test_basic() -> None:
|
||||||
load_case("basic")
|
load_case("basic")
|
||||||
|
|
||||||
|
|
||||||
|
def test_clang_tidy() -> None:
|
||||||
|
load_case("clang-tidy")
|
||||||
|
|
||||||
|
|
||||||
|
def test_cppcheck() -> None:
|
||||||
|
load_case("cppcheck")
|
||||||
|
|
||||||
|
|
||||||
|
def test_cpplint() -> None:
|
||||||
|
load_case("cpplint")
|
||||||
|
|
||||||
|
|
||||||
|
def test_diff() -> None:
|
||||||
|
load_case("diff")
|
||||||
|
|
||||||
|
|
||||||
|
def test_keyword() -> None:
|
||||||
|
load_case("keyword")
|
||||||
|
|
||||||
|
|
||||||
|
def test_result_detail() -> None:
|
||||||
|
load_case("result-detail")
|
||||||
|
|
|
@ -1,32 +1,18 @@
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, Tuple
|
|
||||||
|
|
||||||
import rtoml
|
|
||||||
|
|
||||||
from joj3_config_generator.convert import convert
|
from joj3_config_generator.convert import convert
|
||||||
from joj3_config_generator.models import repo, task
|
from joj3_config_generator.load import load_joj3_toml
|
||||||
|
|
||||||
|
|
||||||
def read_convert_files(
|
|
||||||
case_name: str,
|
|
||||||
) -> Tuple[repo.Config, task.Config, Dict[str, Any]]:
|
|
||||||
root = Path(__file__).resolve().parent / case_name
|
|
||||||
repo_toml_path = root / "repo.toml"
|
|
||||||
repo_toml = repo_toml_path.read_text() if repo_toml_path.exists() else ""
|
|
||||||
task_toml_path = root / "task.toml"
|
|
||||||
task_toml = task_toml_path.read_text() if task_toml_path.exists() else ""
|
|
||||||
result = json.loads((root / "task.json").read_text())
|
|
||||||
return (
|
|
||||||
repo.Config(root=root, **rtoml.loads(repo_toml)),
|
|
||||||
task.Config(root=root, **rtoml.loads(task_toml)),
|
|
||||||
result,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def load_case(case_name: str) -> None:
|
def load_case(case_name: str) -> None:
|
||||||
repo, task, expected_result = read_convert_files(case_name)
|
root = Path(__file__).resolve().parent
|
||||||
result = convert(repo, task).model_dump(
|
repo_toml_path = root / case_name / "repo.toml"
|
||||||
|
task_toml_path = root / case_name / "task.toml"
|
||||||
|
repo_conf, task_conf = load_joj3_toml(root, repo_toml_path, task_toml_path)
|
||||||
|
result_json_path = root / case_name / "task.json"
|
||||||
|
expected_result = json.loads(result_json_path.read_text())
|
||||||
|
result = convert(repo_conf, task_conf).model_dump(
|
||||||
mode="json", by_alias=True, exclude_none=True
|
mode="json", by_alias=True, exclude_none=True
|
||||||
)
|
)
|
||||||
assert result == expected_result
|
assert result == expected_result
|
||||||
|
|
|
@ -1,23 +1,19 @@
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, Tuple
|
|
||||||
|
|
||||||
import rtoml
|
import rtoml
|
||||||
import yaml
|
|
||||||
|
|
||||||
from joj3_config_generator.convert import convert_joj1
|
from joj3_config_generator.convert import convert_joj1
|
||||||
from joj3_config_generator.models import joj1
|
from joj3_config_generator.load import load_joj1_yaml
|
||||||
|
|
||||||
|
|
||||||
def read_convert_joj1_files(case_name: str) -> Tuple[joj1.Config, Dict[str, Any]]:
|
|
||||||
root = Path(__file__).resolve().parent
|
|
||||||
task_yaml_path = root / case_name / "task.yaml"
|
|
||||||
task_yaml = task_yaml_path.read_text()
|
|
||||||
task_toml_path = root / case_name / "task.toml"
|
|
||||||
task_toml = task_toml_path.read_text()
|
|
||||||
return joj1.Config(**yaml.safe_load(task_yaml)), rtoml.loads(task_toml)
|
|
||||||
|
|
||||||
|
|
||||||
def load_case(case_name: str) -> None:
|
def load_case(case_name: str) -> None:
|
||||||
joj1, expected_result = read_convert_joj1_files(case_name)
|
root = Path(__file__).resolve().parent
|
||||||
result = convert_joj1(joj1).model_dump(by_alias=True, exclude_none=True)
|
task_yaml_path = root / case_name / "task.yaml"
|
||||||
|
task_yaml = load_joj1_yaml(task_yaml_path)
|
||||||
|
task_toml_path = root / case_name / "task.toml"
|
||||||
|
task_toml = task_toml_path.read_text()
|
||||||
|
expected_result = rtoml.loads(task_toml)
|
||||||
|
result = convert_joj1(task_yaml).model_dump(
|
||||||
|
mode="json", by_alias=True, exclude_none=True
|
||||||
|
)
|
||||||
assert result == expected_result
|
assert result == expected_result
|
||||||
|
|
Loading…
Reference in New Issue
Block a user