dev #10
							
								
								
									
										22
									
								
								README.md
									
									
									
									
									
								
							
							
						
						|  | @ -16,3 +16,25 @@ | |||
| 4. Install deps by `pdm install && pdm run pre-commit install` | ||||
| 5. Run the cli app by `pdm run app --help` | ||||
| 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.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: | ||||
|     # Create the base ResultConf object | ||||
|     result_conf = result.Config( | ||||
|         name=task_conf.task, | ||||
|         log_path=f"{task_conf.task.replace(' ', '_')}.log", | ||||
|         expire_unix_timestamp=( | ||||
|             int(task_conf.release.deadline.timestamp()) | ||||
|             if task_conf.release.deadline | ||||
|             else -1 | ||||
|         ), | ||||
|         stage=result.Stage(stages=[], sandbox_token=repo_conf.sandbox_token), | ||||
|         teapot=result.Teapot(), | ||||
|         name=task_conf.task.name, | ||||
|         # exact folder difference specified by type | ||||
|         log_path=str(CACHE_ROOT / "joj3" / f"{task_conf.task.type_}.log"), | ||||
|         expire_unix_timestamp=int(task_conf.release.end_time.timestamp()), | ||||
|         effective_unix_timestamp=int(task_conf.release.begin_time.timestamp()), | ||||
|         actor_csv_path=str(JOJ3_CONFIG_ROOT / "students.csv"),  # students.csv position | ||||
|         max_total_score=repo_conf.max_total_score, | ||||
|         stage=result.Stage(sandbox_token=repo_conf.sandbox_token), | ||||
|     ) | ||||
| 
 | ||||
|     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 | ||||
|     for task_stage in task_conf.stages: | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 | ||||
|         executor_with_config = result.ExecutorWith( | ||||
|             default=result.Cmd( | ||||
|                 args=task_stage.command.split(), | ||||
|                 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) | ||||
|         result_conf.stage.stages.append(get_conf_stage(task_conf, task_stage, cached)) | ||||
|     if not repo_conf.force_skip_teapot_on_test or not current_test: | ||||
|         result_conf.stage.post_stages.append(get_teapot_stage(repo_conf)) | ||||
| 
 | ||||
|     return result_conf | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  where is it used? where is it used? 
				
					
						李衍志523370910113
						commented  this should be storing all the files that are about to be copy in or out this should be storing all the files that are about to be copy in or out 
				
					
						李衍志523370910113
						commented  It is as the input and output for the following functions about parsers It is as the input and output for the following functions about parsers 
				
					
						张泊明518370910136
						commented  so this feature is not implemented? so this feature is not implemented? 
				
					
						李衍志523370910113
						commented  it is this is a loop, so this  ```python
    if not repo_conf.force_skip_health_check_on_test or not current_test:
        result_conf.stage.stages.append(get_health_check_config(repo_conf))
    cached: List[str] = []
    # Convert each stage in the task configuration
    for task_stage in task_conf.stages:
        executor_with_config, cached = get_executor_with_config(task_stage, cached)
        conf_stage = get_conf_stage(task_stage, executor_with_config)
        conf_stage = fix_result_detail(task_stage, conf_stage)
        conf_stage = fix_dummy(task_stage, conf_stage)
        conf_stage = fix_keyword(task_stage, conf_stage)
        conf_stage = fix_file(task_stage, conf_stage)
        conf_stage = fix_diff(task_stage, conf_stage, task_conf)
        result_conf.stage.stages.append(conf_stage)
```
it is
```python
    for task_stage in task_conf.stages:
        executor_with_config, cached = get_executor_with_config(task_stage, cached)
```
this is a loop, so this `cached` will be updated in every round of stage 
				
					
						张泊明518370910136
						commented  The return value is unnecessary. The return value is unnecessary. 
				
					
						李衍志523370910113
						commented  I have a lazing coding style here, everything has get imported would get exported, so should maintain this until the end of the loop. Everything is exported in previous stage would be imported in the next stage. I have a lazing coding style here, everything has get imported would get exported, so should maintain this until the end of the loop. Everything is exported in previous stage would be imported in the next stage. 
				
					
						张泊明518370910136
						commented  
 1. The return value is unnecessary
2. It should be a `set` 
				
					
						张泊明518370910136
						commented  try it yourself try it yourself 
				
					
						李衍志523370910113
						commented  I see why I see why 
				
					
						李衍志523370910113
						commented  resolved. resolved. | ||||
| 
 | ||||
| 
 | ||||
| # FIXME: LLM generated convert function, only for demostration | ||||
| def convert_joj1(joj1_conf: joj1.Config) -> task.Config: | ||||
|     stages = [] | ||||
|     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, | ||||
|     ) | ||||
|     return task.Config() | ||||
|  |  | |||
							
								
								
									
										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 | ||||
| 
					
					jon-lee marked this conversation as resolved
					
				 
				
					
						张泊明518370910136
						commented  this file should not be changed this file should not be changed | ||||
| from pathlib import Path | ||||
| 
 | ||||
| import inquirer | ||||
| import rtoml | ||||
| import typer | ||||
| import yaml | ||||
| from typing_extensions import Annotated | ||||
| 
 | ||||
| from joj3_config_generator.convert import convert as convert_conf | ||||
| from joj3_config_generator.convert import convert_joj1 as convert_joj1_conf | ||||
| from joj3_config_generator.models import joj1, repo, task | ||||
| from joj3_config_generator.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 | ||||
| 
 | ||||
| app = typer.Typer(add_completion=False) | ||||
| 
 | ||||
| 
 | ||||
| @app.command() | ||||
| def create(toml: typer.FileTextWrite) -> None: | ||||
| def create(toml_path: Path) -> None: | ||||
|     """ | ||||
|     Create a new JOJ3 toml config file | ||||
|     """ | ||||
|     logger.info("Creating") | ||||
|     questions = [ | ||||
|         inquirer.List( | ||||
|             "size", | ||||
|             message="What size do you need?", | ||||
|             choices=["Jumbo", "Large", "Standard", "Medium", "Small", "Micro"], | ||||
|         ), | ||||
|     ] | ||||
|     answers = inquirer.prompt(questions) | ||||
|     logger.info(answers) | ||||
|     logger.info(f"Creating toml file {toml_path}") | ||||
|     answers = load_joj3_toml_answers() | ||||
|     logger.debug(f"Got answers: {answers}") | ||||
|     toml_path.write_text(rtoml.dumps({})) | ||||
| 
 | ||||
| 
 | ||||
| @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 | ||||
|     """ | ||||
|     logger.info(f"Converting yaml file {yaml_file}") | ||||
|     joj1_obj = yaml.safe_load(yaml_file.read()) | ||||
|     joj1_model = joj1.Config(**joj1_obj) | ||||
|     logger.info(f"Converting yaml file {yaml_path}") | ||||
|     joj1_model = load_joj1_yaml(yaml_path) | ||||
|     task_model = convert_joj1_conf(joj1_model) | ||||
|     result_dict = task_model.model_dump(by_alias=True) | ||||
|     toml_file.write(rtoml.dumps(result_dict)) | ||||
|     result_dict = task_model.model_dump(mode="json", by_alias=True, exclude_none=True) | ||||
|     toml_path.write_text(rtoml.dumps(result_dict)) | ||||
| 
 | ||||
| 
 | ||||
| @app.command() | ||||
|  | @ -50,8 +46,7 @@ def convert( | |||
|     root: Annotated[ | ||||
|         Path, | ||||
|         typer.Argument( | ||||
|             help="root directory of config files, " | ||||
|             "located at /home/tt/.config/joj in JTC" | ||||
|             help=f"root directory of config files, located at {JOJ3_CONFIG_ROOT} in JTC" | ||||
|         ), | ||||
|     ] = Path(".") | ||||
| ) -> None: | ||||
|  | @ -60,9 +55,7 @@ def convert( | |||
|     """ | ||||
|     logger.info(f"Converting files in {root.absolute()}") | ||||
|     for repo_toml_path in root.glob("**/repo.toml"): | ||||
|         repo_path = repo_toml_path.parent | ||||
|         repo_obj = rtoml.loads(repo_toml_path.read_text()) | ||||
|         for task_toml_path in repo_path.glob("**/*.toml"): | ||||
|         for task_toml_path in repo_toml_path.parent.glob("**/*.toml"): | ||||
|             if repo_toml_path == task_toml_path: | ||||
|                 continue | ||||
|             toml_name = task_toml_path.name.removesuffix(".toml") | ||||
|  | @ -70,15 +63,11 @@ def convert( | |||
|             logger.info( | ||||
|                 f"Converting {repo_toml_path} & {task_toml_path} to {result_json_path}" | ||||
|             ) | ||||
|             task_obj = rtoml.loads(task_toml_path.read_text()) | ||||
|             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) | ||||
|             repo_conf, task_conf = load_joj3_toml(root, repo_toml_path, task_toml_path) | ||||
|             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: | ||||
|                 json.dump(result_dict, result_file, ensure_ascii=False, indent=4) | ||||
|                 result_file.write("\n") | ||||
|  |  | |||
							
								
								
									
										19
									
								
								joj3_config_generator/models/common.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						|  | @ -0,0 +1,19 @@ | |||
| from typing import Union | ||||
| 
 | ||||
| import humanfriendly | ||||
| 
 | ||||
| 
 | ||||
| class Memory(int): | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  what compact? what compact? 
				
					
						李衍志523370910113
						commented  no int input, should be done already, so it can be removed. I added that several commit before before you removed that 😇 no int input, should be done already, so it can be removed. I added that several commit before before  you removed that 😇 | ||||
|     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
									
								
							
							
						
						|  | @ -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 typing import List, Optional | ||||
| from typing import List | ||||
| 
 | ||||
| from pydantic import BaseModel, Field | ||||
| 
 | ||||
| 
 | ||||
| class Files(BaseModel): | ||||
|     whitelist_patterns: List[str] | ||||
|     whitelist_file: Optional[str] | ||||
|     required: List[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): | ||||
|     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(".") | ||||
|     path: Path = Path("repo.toml") | ||||
|     teaching_team: List[str] | ||||
|     max_size: float = Field(..., ge=0) | ||||
|     release_tags: List[str] | ||||
|     files: Files | ||||
|     sandbox_token: str | ||||
|     grading_repo_name: str = f"{socket.gethostname().split('-')[0]}-joj" | ||||
|  |  | |||
|  | @ -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): | ||||
|  | @ -17,7 +23,7 @@ class PreparedFile(BaseModel): | |||
| 
 | ||||
| class Collector(BaseModel): | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  default value too large, should be 1s 128MB default value too large, should be 1s 128MB 
				
					
						李衍志523370910113
						commented  will fix later, we need to hold some test I reckon? will fix later, we need to hold some test I reckon? 
				
					
						张泊明518370910136
						commented  no no 
				
					
						李衍志523370910113
						commented  @bomingzh fixed @bomingzh fixed | ||||
|     name: str | ||||
|     max: int | ||||
|     max: int = DEFAULT_FILE_LIMIT | ||||
|     pipe: bool = True | ||||
| 
 | ||||
| 
 | ||||
|  | @ -33,27 +39,26 @@ class StreamOut(BaseModel): | |||
|     stream_out: bool = Field(..., alias="streamOut") | ||||
| 
 | ||||
| 
 | ||||
| InputFile = Union[LocalFile | MemoryFile | PreparedFile | Symlink] | ||||
| InputFile = Union[LocalFile, MemoryFile, PreparedFile, Symlink] | ||||
| 
 | ||||
| 
 | ||||
| class Cmd(BaseModel): | ||||
|     args: List[str] | ||||
|     args: List[str] = [] | ||||
|     env: List[str] = [] | ||||
|     stdin: Optional[Union[InputFile | StreamIn]] = None | ||||
|     stdout: Optional[Union[Collector | StreamOut]] = None | ||||
|     stderr: Optional[Union[Collector | StreamOut]] = None | ||||
|     cpu_limit: int = Field(0, serialization_alias="cpuLimit") | ||||
|     real_cpu_limit: int = Field(0, serialization_alias="realCpuLimit") | ||||
|     clock_limit: int = Field(0, serialization_alias="clockLimit") | ||||
|     memory_limit: int = Field(0, serialization_alias="memoryLimit") | ||||
|     stdin: Union[InputFile, StreamIn] = MemoryFile(content="") | ||||
|     stdout: Union[Collector, StreamOut] = Collector(name="stdout") | ||||
|     stderr: Union[Collector, StreamOut] = Collector(name="stderr") | ||||
|     cpu_limit: int = Field(DEFAULT_CPU_LIMIT, serialization_alias="cpuLimit") | ||||
|     clock_limit: int = Field(2 * DEFAULT_CPU_LIMIT, serialization_alias="clockLimit") | ||||
|     memory_limit: int = Field(DEFAULT_MEMORY_LIMIT, serialization_alias="memoryLimit") | ||||
|     stack_limit: int = Field(0, serialization_alias="stackLimit") | ||||
|     proc_limit: int = Field(0, serialization_alias="procLimit") | ||||
|     proc_limit: int = Field(50, serialization_alias="procLimit") | ||||
|     cpu_rate_limit: int = Field(0, serialization_alias="cpuRateLimit") | ||||
|     cpu_set_limit: str = Field("", serialization_alias="cpuSetLimit") | ||||
|     copy_in: Dict[str, InputFile] = Field({}, serialization_alias="copyIn") | ||||
|     copy_in_cached: Dict[str, str] = Field({}, serialization_alias="copyInCached") | ||||
|     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") | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  What is the conclusion? What is the conclusion? 
				
					
						李衍志523370910113
						commented  should be already solved. should be already solved. | ||||
|     copy_out_cached: List[str] = Field([], serialization_alias="copyOutCached") | ||||
|     copy_out_max: int = Field(0, serialization_alias="copyOutMax") | ||||
|     copy_out_dir: str = Field("", serialization_alias="copyOutDir") | ||||
|  | @ -66,11 +71,10 @@ class Cmd(BaseModel): | |||
| class OptionalCmd(BaseModel): | ||||
|     args: Optional[List[str]] = None | ||||
|     env: Optional[List[str]] = None | ||||
|     stdin: Optional[Union[InputFile | StreamIn]] = None | ||||
|     stdout: Optional[Union[Collector | StreamOut]] = None | ||||
|     stderr: Optional[Union[Collector | StreamOut]] = None | ||||
|     stdin: Optional[Union[InputFile, StreamIn]] = None | ||||
|     stdout: Optional[Union[Collector, StreamOut]] = None | ||||
|     stderr: Optional[Union[Collector, StreamOut]] = None | ||||
|     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") | ||||
|     memory_limit: Optional[int] = Field(None, serialization_alias="memoryLimit") | ||||
|     stack_limit: Optional[int] = Field(None, serialization_alias="stackLimit") | ||||
|  | @ -101,23 +105,39 @@ class OptionalCmd(BaseModel): | |||
| 
 | ||||
| 
 | ||||
| class ExecutorWith(BaseModel): | ||||
|     default: Cmd | ||||
|     cases: List[OptionalCmd] | ||||
|     default: Cmd = Cmd() | ||||
|     cases: List[OptionalCmd] = [] | ||||
| 
 | ||||
| 
 | ||||
| class Executor(BaseModel): | ||||
|     name: str | ||||
|     with_: ExecutorWith = Field(..., serialization_alias="with") | ||||
|     with_: ExecutorWith = Field(ExecutorWith(), serialization_alias="with") | ||||
| 
 | ||||
| 
 | ||||
| class Parser(BaseModel): | ||||
|     name: str | ||||
|     with_: Dict[str, Any] = Field(..., serialization_alias="with") | ||||
|     if TYPE_CHECKING: | ||||
| 
 | ||||
|         class Empty(BaseModel): | ||||
|             pass | ||||
| 
 | ||||
|         with_: BaseModel = Field(Empty(), serialization_alias="with") | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  Should it be optional? Should it be optional? | ||||
|     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): | ||||
|     name: str | ||||
|     group: str | ||||
|     group: str = "" | ||||
|     executor: Executor | ||||
|     parsers: List[Parser] | ||||
| 
 | ||||
|  | @ -130,26 +150,74 @@ class Stage(BaseModel): | |||
|     output_path: str = Field( | ||||
|         "/tmp/joj3_result.json", serialization_alias="outputPath" | ||||
|     )  # nosec: B108 | ||||
|     stages: List[StageDetail] | ||||
| 
 | ||||
| 
 | ||||
| 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") | ||||
|     stages: List[StageDetail] = [] | ||||
|     pre_stages: List[StageDetail] = Field([], serialization_alias="preStages") | ||||
|     post_stages: List[StageDetail] = Field([], serialization_alias="postStages") | ||||
| 
 | ||||
| 
 | ||||
| class Config(BaseModel): | ||||
|     name: str = "unknown" | ||||
|     name: str = "" | ||||
|     log_path: str = Field("", serialization_alias="logPath") | ||||
|     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 | ||||
|     teapot: Teapot | ||||
| 
 | ||||
| 
 | ||||
| class DummyConfig(BaseModel): | ||||
|     score: int = 0 | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  Are these  Are these `Optional` necessary? | ||||
|     comment: Optional[str] = None | ||||
|     force_quit_on_not_accepted: Optional[bool] = Field( | ||||
|         False, serialization_alias="forceQuitOnNotAccepted" | ||||
|     ) | ||||
| 
 | ||||
| 
 | ||||
| class DiffOutputConfig(BaseModel): | ||||
| 
					
					jon-lee marked this conversation as resolved
					
				 
				
					
						张泊明518370910136
						commented  also these  also these `Optional`? 
				
					
						李衍志523370910113
						commented  I guess some of the field have default within JOJ3, so I choose optional just to reduce the length of json previously I guess some of the field have default within JOJ3, so I choose optional just to reduce the length of json previously 
				
					
						张泊明518370910136
						commented  better put all defaults here then we only need to check the code here better put all defaults here then we only need to check the code here 
				
					
						李衍志523370910113
						commented  indeed. indeed. | ||||
|     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): | ||||
| 
					
					jon-lee marked this conversation as resolved
					
				 
				
					
						张泊明518370910136
						commented  what needs to be refined? what needs to be refined? 
				
					
						李衍志523370910113
						commented  just feels bit waste since this outputs only have one field before I coded the logic, I wrote that comment without checking the details of diff parser. But it should be the best strategy to show the structures as well as give flexiblity for extension now. just feels bit waste since this outputs only have one field before I coded the logic, I wrote that comment without checking the details of diff parser. But it should be the best strategy to show the structures as well as give flexiblity for extension now. | ||||
|     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 | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  every field in this file should not be optional. we give an default value here if any field does not exist every field in this file should not be optional. we give an default value here if any field does not exist 
				
					
						张泊明518370910136
						commented  and use underscore naming in this file and use underscore naming in this file 
				
					
						李衍志523370910113
						commented  
 fixed > every field in this file should not be optional. we give an default value here if any field does not exist
fixed 
				
					
						李衍志523370910113
						commented  
 fixed. > and use underscore naming in this file
fixed. | ||||
| from enum import Enum | ||||
| 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): | ||||
|  | @ -10,31 +18,136 @@ class ParserResultDetail(BaseModel): | |||
|     mem: bool = True  # Display memory usage | ||||
|     stdout: bool = False  # Display stdout 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): | ||||
|     import_: List[str] = Field(serialization_alias="import", validation_alias="import") | ||||
|     export: List[str] | ||||
|     import_: List[str] = Field([], alias="import") | ||||
|     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" | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  deprecated deprecated 
				
					
						李衍志523370910113
						commented  @bomingzh any suggestions on the structure? @bomingzh any suggestions on the structure? 
				
					
						张泊明518370910136
						commented  ```
PydanticDeprecatedSince20: Support for class-based `config` is deprecated, use ConfigDict instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.9/migration/
``` 
				
					
						李衍志523370910113
						commented  fixed with  fixed with `model_config` 
				
					
						张泊明518370910136
						commented  str here need to be a  str here need to be a `StrEnum` now. 
				
					
						李衍志523370910113
						commented  But I guess we don't know the set of case in advance, making it dynamic  But I guess we don't know the set of case in advance, making it dynamic `StrEnum` is meaningless 
				
					
						张泊明518370910136
						commented  line changed, the comment is for  line changed, the comment is for `parsers` | ||||
|     CPPCHECK = "cppcheck" | ||||
|     CPPLINT = "cpplint" | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						李衍志523370910113
						commented  this should be the  this should be the `StrEnum` 
				
					
						张泊明518370910136
						commented  yes yes 
				
					
						李衍志523370910113
						commented  It is supported now. It is supported now. | ||||
|     KEYWORD = "keyword" | ||||
|     RESULT_STATUS = "result-status" | ||||
|     RESULT_DETAIL = "result-detail" | ||||
|     DUMMY = "dummy" | ||||
|     FILE = "file" | ||||
|     DIFF = "diff" | ||||
| 
 | ||||
| 
 | ||||
| class Stage(BaseModel): | ||||
|     name: str  # Stage name | ||||
|     command: str  # Command to run | ||||
|     files: Files  # Files to import and export | ||||
|     score: int  # Score for the task | ||||
|     parsers: List[str]  # list of parsers | ||||
|     result_detail: ParserResultDetail = ( | ||||
|         ParserResultDetail() | ||||
|     )  #  for result-detail parser | ||||
|     name: str = ""  # Stage name | ||||
|     env: List[str] = [] | ||||
|     command: str = ""  # Command to run | ||||
|     files: Files = Files() | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  
 `begin_time` and `end_time` to make them match 
				
					
						李衍志523370910113
						commented  resolved resolved | ||||
|     in_: str = Field("", alias="in") | ||||
|     out_: str = Field("", alias="out") | ||||
|     score: int = 0 | ||||
|     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): | ||||
|     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): | ||||
|     root: Path = Path(".") | ||||
|     path: Path = Path("task.toml") | ||||
|     task: str  # Task name (e.g., hw3 ex5) | ||||
|     release: Release  # Release configuration | ||||
|     stages: List[Stage]  # list of stage configurations | ||||
|     task: Task = Task()  # Task name (e.g., hw3 ex5) | ||||
|     release: Release = Release()  # Release configuration | ||||
|     stages: List[Stage] = []  # list of stage configurations | ||||
|  |  | |||
							
								
								
									
										0
									
								
								joj3_config_generator/processers/__init__.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 = [ | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  make it a field in repo.toml, if it is unset, then use  make it a field in repo.toml, if it is unset, then use `socket.gethostname`. We set this value to pass the test. 
				
					
						李衍志523370910113
						commented  resolved. resolved. | ||||
|         "/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, | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  why not  why not `args = "hc -root=. "` 
				
					
						李衍志523370910113
						commented  resolved. resolved. | ||||
|         "--group-config", | ||||
|         ",".join( | ||||
|             f"{name}={max_count}:{time_period}" | ||||
|             for name, max_count, time_period in zip( | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  do we need that default? do we need that default? 
				
					
						李衍志523370910113
						commented  what is the situation internally in JOJ3? I just added that blindly when I reached that stage. Overall I think 100 times per day should be a reasonable and safe default? considering that there may be group works and due date what is the situation internally in JOJ3? I just added that blindly when I reached that stage. Overall I think 100 times per day should be a reasonable and safe default? considering that there may be group works and due date 
				
					
						张泊明518370910136
						commented  They can manually add it if needed. Or just move it to the model default. They can manually add it if needed. Or just move it to the model default. 
				
					
						李衍志523370910113
						commented  removed. removed. | ||||
|                 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
									
								
							
							
						
						|  | @ -0,0 +1,206 @@ | |||
| import re | ||||
| 
					
					jon-lee marked this conversation as resolved
					
				 
				
					
						张泊明518370910136
						commented  Path should not be relative to  Path should not be relative to `JOJ3_CONFIG_ROOT` in this file, should be relative to `task.toml` dir 
				
					
						李衍志523370910113
						commented  I reckon you said things is relative to  I reckon you said things is relative to `JOJ3_CONFIG_ROOT` in JTC before. we have a `task.type` in `task.toml` to mend the path 
				
					
						张泊明518370910136
						commented  
 `config.path` is relative to `JOJ3_CONFIG_ROOT`. 
				
					
						李衍志523370910113
						commented  could you explain further? I m not quite sure my understanding is clear. could you explain further? I m not quite sure my understanding is clear. 
				
					
						张泊明518370910136
						commented  In  In `joj3_config_generator/models/task.py`, `Config.path` is relative to `JOJ3_CONFIG_ROOT`, so `task.toml` will located at `JOJ3_CONFIG_ROOT / task_conf.path` in JTC. | ||||
| import shlex | ||||
| 
					
					jon-lee marked this conversation as resolved
					
				 
				
					
						张泊明518370910136
						commented  Some  Some `with_.update` is still using raw dict, not model with `model_dump`. | ||||
| 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 | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  
 `ParserEnum` | ||||
| 
 | ||||
| 
 | ||||
| def get_conf_stage( | ||||
|     task_conf: task.Config, | ||||
|     task_stage: task.Stage, | ||||
|     cached: Dict[str, None], | ||||
| ) -> result.StageDetail: | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						李衍志523370910113
						commented  BTW, is this outdated? BTW, is this outdated? 
				
					
						张泊明518370910136
						commented  Never heard about this rule. Never heard about this rule. 
				
					
						李衍志523370910113
						commented  @manuel what would be the current intended rule for  @manuel what would be the current intended rule for `group`? 
				
					
						李衍志523370910113
						commented  seems current strategy is fine, resolved. seems current strategy is fine, resolved. | ||||
|     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] | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  should loop through  should loop through `conf_stage.parsers` here and update the `with` field according to the parser name. 
				
					
						李衍志523370910113
						commented  I think its already implemented in each of the  I think its already implemented in each of the `fix_parsers` functions 
				
					
						张泊明518370910136
						commented  No, do not find the parser in the  No, do not find the parser in the `fix_xxx` function. Instead, iterate through the parsers here and decide how to fill in the `with`. 
				
					
						李衍志523370910113
						commented  resolved. resolved. 
				
					
						张泊明518370910136
						commented  Use a dict to store parser name, field, function to process. Use a dict to store parser name, field, function to process.
```
    process_dict: Dict[
        str, Tuple[Callable[[result.ParserConfig, BaseModel], None], BaseModel]
    ] = {
        "clangtidy": (fix_keyword, task_stage.clangtidy),
        "keyword": (fix_keyword, task_stage.keyword),
        "diff": (fix_diff, task_stage.diff),
    }
    for i, parser in enumerate(task_stage.parsers):
        if parser in process_dict:
            func, parser_model = process_dict[parser]
            func(conf_stage.parsers[i], parser_model)
``` 
				
					
						李衍志523370910113
						commented  resolved. resolved. | ||||
|             fn(parser_model, conf_stage.parsers[idx]) | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  Do we need to support both kinds of names? Do we need to support both kinds of names? 
				
					
						李衍志523370910113
						commented  probably yes, since it is easy for new ta to type it wrong probably yes, since it is easy for new ta to type it wrong 
				
					
						张泊明518370910136
						commented  parsers name should be a str enum, force them to use the correct names parsers name should be a str enum, force them to use the correct names 
				
					
						李衍志523370910113
						commented  ok, then removed. ok, then removed. | ||||
|         elif parser == ParserEnum.DIFF: | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  underscore underscore 
				
					
						李衍志523370910113
						commented  fixed fixed | ||||
|             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 | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  not necessary not necessary 
				
					
						李衍志523370910113
						commented  resolved. resolved. | ||||
| 
 | ||||
| 
 | ||||
| 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={ | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  do not use  do not use `getattr`, visit the field explictly 
				
					
						李衍志523370910113
						commented  resolved. resolved. | ||||
|                 file: result.LocalFile(src=str(JOJ3_CONFIG_ROOT / file)) | ||||
|                 # all copyin files store in this tools folder | ||||
|                 # TODO: are there any corner cases? | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  is there a conclusion now? or it should have a prefix  is there a conclusion now? or it should have a prefix `TODO: `? 
				
					
						李衍志523370910113
						commented  so far works fine on 280 sides, indicating that pbs in 151 can be resolved with proper guidelines I think. so far works fine on 280 sides, indicating that pbs in 151 can be resolved with proper guidelines I think. 
				
					
						张泊明518370910136
						commented  ok, then add that prefix ok, then add that prefix | ||||
|                 for file in copy_in_files | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  is it in the correct unit? is it in the correct unit?
Give all the fields in `Limit` a default value and make it non optional in task_stage.limit 
				
					
						李衍志523370910113
						commented  resolved resolved | ||||
|             }, | ||||
|             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) | ||||
|             ), | ||||
|         ), | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  The reason for the suffix in  The reason for the suffix in `keyword_parser_`? 
				
					
						李衍志523370910113
						commented  just forgot to remove, sorry just forgot to remove, sorry | ||||
|         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="", | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  -> ```
    if task_stage.parsers is not None:
        for parser in task_stage.parsers:
```
->
```
for parser in task_stage.parsers or []:
``` 
				
					
						李衍志523370910113
						commented  resolved. resolved. | ||||
|         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 | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  When will it be None? When will it be None? | ||||
|     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, | ||||
| 
					
					bomingzh marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  these fields do not exist now these fields do not exist now 
				
					
						李衍志523370910113
						commented  resolved resolved 
				
					
						张泊明518370910136
						commented  
			
				No description provided.
			
			 | ||||
|     base_dir: Path, | ||||
| ) -> None: | ||||
|     skip = task_stage.skip | ||||
|     cases = task_stage.cases | ||||
|     finalized_cases = [case for case in cases if case not in skip] | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  move  move `continue` to the other branch to reduce nesting 
				
					
						张泊明518370910136
						commented  I mean I mean
```
if parser not in keyword_parser:
    continue
```
```
if getattr(task_stage, parser, None) is None:
    continue
````
```
if score != score_:
    continue
```` 
				
					
						李衍志523370910113
						commented  fixed. fixed. | ||||
| 
 | ||||
|     stage_cases = [] | ||||
|     parser_cases = [] | ||||
| 
 | ||||
|     for case in finalized_cases: | ||||
|         case_stage = task_stage.cases.get(case) if task_stage.cases else None | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  Is it necessary to rename? Is it necessary to rename? | ||||
|         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" | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  just  just `if task_stage.result_detail.stdout:` | ||||
| 
 | ||||
|         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 | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  Pass  Pass `JOJ3_CONFIG_ROOT / task_conf.path.parent` as `base_dir` in parameters. 
				
					
						李衍志523370910113
						commented  resolved. resolved. | ||||
|         parser_cases.append( | ||||
|             result.DiffCasesConfig( | ||||
|                 outputs=[ | ||||
|                     result.DiffOutputConfig( | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  will it be None now? will it be None now? 
				
					
						李衍志523370910113
						commented  nope 😂 bad coding strategy before nope 😂 bad coding strategy before | ||||
|                         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 | ||||
| from sys import stderr | ||||
| from types import FrameType | ||||
| from typing import Optional | ||||
| from typing import Optional, Union | ||||
| 
 | ||||
| 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 | ||||
| class InterceptHandler(logging.Handler): | ||||
|     def emit(self, record: logging.LogRecord) -> None: | ||||
|         level: str | int | ||||
|         level: Union[str, int] | ||||
|         try: | ||||
|             level = logger.level(record.levelname).name | ||||
|         except ValueError: | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ dependencies = [ | |||
|     "pydantic>=2.9.2", | ||||
|     "inquirer>=3.4.0", | ||||
|     "rtoml>=0.11.0", | ||||
|     "humanfriendly>=10.0", | ||||
| ] | ||||
| requires-python = ">=3.9" | ||||
| authors = [{ name = "JOJ3-dev", email = "joj3@focs.ji.sjtu.edu.cn" }] | ||||
|  |  | |||
							
								
								
									
										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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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"] | ||||
| max_size = 50.5 | ||||
| release_tags = ["v1.0", "v2.0", "final"] | ||||
| grading_repo_name = "ece280-joj" | ||||
| 
 | ||||
| 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] | ||||
| whitelist_patterns = ["*.py", "*.txt", "*.md"] | ||||
| whitelist_file = ".whitelist" | ||||
| required = ["main.py", "README.md"] | ||||
| immutable = ["config.yaml", "setup.py"] | ||||
| required = ["README.md", "Changelog.md"] | ||||
| immutable = [".gitignore", ".gitattributes",".gitea/workflows/push.yaml", ".gitea/workflows/release.yaml"] | ||||
|  |  | |||
|  | @ -1,47 +1,52 @@ | |||
| { | ||||
|     "name": "hw3 ex5", | ||||
|     "logPath": "hw3_ex5.log", | ||||
|     "expireUnixTimestamp": 1729267140, | ||||
|     "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": "test", | ||||
|         "outputPath": "/tmp/joj3_result.json", | ||||
|         "stages": [ | ||||
|             { | ||||
|                 "name": "judge_base", | ||||
|                 "group": "hw3 ex5", | ||||
|                 "name": "Health Check", | ||||
|                 "group": "", | ||||
|                 "executor": { | ||||
|                     "name": "sandbox", | ||||
|                     "name": "local", | ||||
|                     "with": { | ||||
|                         "default": { | ||||
|                             "args": [ | ||||
|                                 "./matlab-joj", | ||||
|                                 "./h3/ex5.m" | ||||
|                             ], | ||||
|                             "args": [], | ||||
|                             "env": [], | ||||
|                             "cpuLimit": 0, | ||||
|                             "realCpuLimit": 0, | ||||
|                             "clockLimit": 0, | ||||
|                             "memoryLimit": 0, | ||||
|                             "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": 0, | ||||
|                             "procLimit": 50, | ||||
|                             "cpuRateLimit": 0, | ||||
|                             "cpuSetLimit": "", | ||||
|                             "copyIn": { | ||||
|                                 "tools/matlab-joj": { | ||||
|                                     "src": "tools/matlab-joj" | ||||
|                                 }, | ||||
|                                 "tools/matlab_formatter.py": { | ||||
|                                     "src": "tools/matlab_formatter.py" | ||||
|                                 } | ||||
|                             }, | ||||
|                             "copyIn": {}, | ||||
|                             "copyInCached": {}, | ||||
|                             "copyInDir": ".", | ||||
|                             "copyOut": [], | ||||
|                             "copyOutCached": [ | ||||
|                                 "output/ex5_results.txt", | ||||
|                                 "output/ex5_logs.txt" | ||||
|                             "copyOut": [ | ||||
|                                 "stdout", | ||||
|                                 "stderr" | ||||
|                             ], | ||||
|                             "copyOutCached": [], | ||||
|                             "copyOutMax": 0, | ||||
|                             "copyOutDir": "", | ||||
|                             "tty": false, | ||||
|  | @ -49,59 +54,98 @@ | |||
|                             "dataSegmentLimit": false, | ||||
|                             "addressSpaceLimit": false | ||||
|                         }, | ||||
|                         "cases": [] | ||||
|                         "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": "diff", | ||||
|                         "with": {} | ||||
|                         "name": "healthcheck", | ||||
|                         "with": { | ||||
|                             "score": 1 | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         "name": "result-detail", | ||||
|                         "name": "debug", | ||||
|                         "with": { | ||||
|                             "time": false, | ||||
|                             "mem": false, | ||||
|                             "stdout": false, | ||||
|                             "stderr": true | ||||
|                             "score": 0 | ||||
|                         } | ||||
|                     } | ||||
|                 ] | ||||
|             }, | ||||
|             { | ||||
|                 "name": "judge_base2", | ||||
|                 "group": "hw3 ex5", | ||||
|                 "name": "Compilation", | ||||
|                 "group": "", | ||||
|                 "executor": { | ||||
|                     "name": "sandbox", | ||||
|                     "with": { | ||||
|                         "default": { | ||||
|                             "args": [ | ||||
|                                 "./matlab-joj", | ||||
|                                 "./h3/ex5.m" | ||||
|                                 "./tools/compile" | ||||
|                             ], | ||||
|                             "env": [], | ||||
|                             "cpuLimit": 0, | ||||
|                             "realCpuLimit": 0, | ||||
|                             "clockLimit": 0, | ||||
|                             "memoryLimit": 0, | ||||
|                             "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": 0, | ||||
|                             "procLimit": 50, | ||||
|                             "cpuRateLimit": 0, | ||||
|                             "cpuSetLimit": "", | ||||
|                             "copyIn": { | ||||
|                                 "tools/matlab-joj": { | ||||
|                                     "src": "tools/matlab-joj" | ||||
|                                 }, | ||||
|                                 "tools/matlab_formatter.py": { | ||||
|                                     "src": "tools/matlab_formatter.py" | ||||
|                                 "tools/compile": { | ||||
|                                     "src": "/home/tt/.config/joj/tools/compile" | ||||
|                                 } | ||||
|                             }, | ||||
|                             "copyInCached": {}, | ||||
|                             "copyInDir": ".", | ||||
|                             "copyOut": [], | ||||
|                             "copyOut": [ | ||||
|                                 "stdout", | ||||
|                                 "stderr" | ||||
|                             ], | ||||
|                             "copyOutCached": [ | ||||
|                                 "output/ex5_results2.txt", | ||||
|                                 "output/ex5_logs2.txt" | ||||
|                                 "h7/build/ex2", | ||||
|                                 "h7/build/ex2-asan", | ||||
|                                 "h7/build/ex2-ubsan", | ||||
|                                 "h7/build/ex2-msan", | ||||
|                                 "h7/build/compile_commands.json" | ||||
|                             ], | ||||
|                             "copyOutMax": 0, | ||||
|                             "copyOutDir": "", | ||||
|  | @ -115,29 +159,691 @@ | |||
|                 }, | ||||
|                 "parsers": [ | ||||
|                     { | ||||
|                         "name": "diff", | ||||
|                         "with": {} | ||||
|                         "name": "result-detail", | ||||
|                         "with": { | ||||
|                             "score": 0, | ||||
|                             "comment": "", | ||||
|                             "showFiles": [ | ||||
|                                 "stderr" | ||||
|                             ], | ||||
|                             "showExitStatus": true, | ||||
|                             "showRuntime": false, | ||||
|                             "showMemory": false | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         "name": "result-status", | ||||
|                         "with": { | ||||
|                             "score": 0, | ||||
|                             "comment": "Congratulations! Your code compiled successfully.", | ||||
|                             "forceQuitOnNotAccepted": true | ||||
|                         } | ||||
|                     } | ||||
|                 ] | ||||
|             }, | ||||
|             { | ||||
|                 "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": { | ||||
|                                 "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": [ | ||||
|                                 { | ||||
|                                     "keywords": [ | ||||
|                                         "max" | ||||
|                                     ], | ||||
|                                     "score": 20 | ||||
|                                 }, | ||||
|                                 { | ||||
|                                     "keywords": [ | ||||
|                                         "recommended" | ||||
|                                     ], | ||||
|                                     "score": 10 | ||||
|                                 } | ||||
|                             ] | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         "name": "result-detail", | ||||
|                         "with": { | ||||
|                             "time": true, | ||||
|                             "mem": true, | ||||
|                             "stdout": false, | ||||
|                             "stderr": false | ||||
|                             "score": 0, | ||||
|                             "comment": "", | ||||
|                             "showFiles": [ | ||||
|                                 "stdout" | ||||
|                             ], | ||||
|                             "showExitStatus": true, | ||||
|                             "showRuntime": false, | ||||
|                             "showMemory": false | ||||
|                         } | ||||
|                     } | ||||
|                 ] | ||||
|             }, | ||||
|             { | ||||
|                 "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": 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" | ||||
|                         } | ||||
|                     } | ||||
|                 ] | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     "teapot": { | ||||
|         "logPath": "/home/tt/.cache/joint-teapot-debug.log", | ||||
|         "scoreboardPath": "scoreboard.csv", | ||||
|         "failedTablePath": "failed-table.md", | ||||
|         "gradingRepoName": "", | ||||
|         "skipIssue": false, | ||||
|         "skipScoreboard": false, | ||||
|         "skipFailedTable": false | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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] | ||||
| deadline = "2024-10-18T23:59:00+08:00" | ||||
| release.end_time = 2024-12-30 23:59:59+08:00 | ||||
| release.begin_time = 2024-12-29 23:59:59+08:00 | ||||
| 
 | ||||
| [[stages]] | ||||
| name = "judge_base" | ||||
| command = "./matlab-joj ./h3/ex5.m" | ||||
| score = 100 | ||||
| parsers = ["diff", "result-detail"] | ||||
| name = "Compilation" | ||||
| command = "./tools/compile" # eg. script running cmake commands | ||||
| files.import = [ "tools/compile" ] | ||||
| 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"] | ||||
| files.export = ["output/ex5_results.txt", "output/ex5_logs.txt"] | ||||
| 
 | ||||
| result_detail.time = false | ||||
| result_detail.mem = false | ||||
| result_detail.stderr = true | ||||
| # compile parsers | ||||
| parsers = [ "result-detail", "result-status" ] | ||||
| result-status.comment = "Congratulations! Your code compiled successfully." | ||||
| result-detail.exitstatus = true | ||||
| result-detail.stderr = true | ||||
| result-detail.time = false | ||||
| result-detail.mem = false | ||||
| result-status.force_quit = true | ||||
| 
 | ||||
| [[stages]] | ||||
| name = "judge_base2" | ||||
| command = "./matlab-joj ./h3/ex5.m" | ||||
| score = 80 | ||||
| parsers = ["diff", "result-detail"] | ||||
| name = "[cq] Filelength" | ||||
| command = "./tools/filelength 400 300 *.cpp *.h" | ||||
| files.import = [ "tools/filelength" ] | ||||
| 
 | ||||
| files.import = ["tools/matlab-joj", "tools/matlab_formatter.py"] | ||||
| files.export = ["output/ex5_results2.txt", "output/ex5_logs2.txt"] | ||||
| 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 | ||||
| 
 | ||||
| result_detail.time = true | ||||
| result_detail.mem = true | ||||
| result_detail.stderr = 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" | ||||
| 
					
					jon-lee marked this conversation as resolved
					
						
						
							Outdated
						
					
				 
				
					
						张泊明518370910136
						commented  is it used? is it used? 
				
					
						李衍志523370910113
						commented  testcases in basic is intend to show a comprehensive situation. testcases in basic is intend to show a comprehensive situation. 
				
					
						张泊明518370910136
						commented  if unused, leave a comment if unused, leave a comment 
				
					
						张泊明518370910136
						commented  Then why is there a  Then why is there a `stdout` field in `class Limit` 
				
					
						李衍志523370910113
						commented  @bomingzh in toml now should we accept both  @bomingzh in toml now should we accept both `32m` and `32` or just `32m` now? 
				
					
						李衍志523370910113
						commented  I reckon only  I reckon only `32m` would be good 
				
					
						张泊明518370910136
						commented  yes, just str yes, just str | ||||
| 
 | ||||
| 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" ] | ||||
| 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 = "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" | ||||
| 
 | ||||
| case1.diff.output.score = 5 | ||||
| case1.limit.cpu = "1s" | ||||
| 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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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
									
								
							
							
						
						|  | @ -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: | ||||
|     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 | ||||
| from pathlib import Path | ||||
| from typing import Any, Dict, Tuple | ||||
| 
 | ||||
| import rtoml | ||||
| 
 | ||||
| from joj3_config_generator.convert import convert | ||||
| from joj3_config_generator.models import repo, task | ||||
| 
 | ||||
| 
 | ||||
| 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, | ||||
|     ) | ||||
| from joj3_config_generator.load import load_joj3_toml | ||||
| 
 | ||||
| 
 | ||||
| def load_case(case_name: str) -> None: | ||||
|     repo, task, expected_result = read_convert_files(case_name) | ||||
|     result = convert(repo, task).model_dump( | ||||
|     root = Path(__file__).resolve().parent | ||||
|     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 | ||||
|     ) | ||||
|     assert result == expected_result | ||||
|  |  | |||
|  | @ -1,23 +1,19 @@ | |||
| from pathlib import Path | ||||
| from typing import Any, Dict, Tuple | ||||
| 
 | ||||
| import rtoml | ||||
| import yaml | ||||
| 
 | ||||
| from joj3_config_generator.convert import convert_joj1 | ||||
| from joj3_config_generator.models import joj1 | ||||
| 
 | ||||
| 
 | ||||
| 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) | ||||
| from joj3_config_generator.load import load_joj1_yaml | ||||
| 
 | ||||
| 
 | ||||
| def load_case(case_name: str) -> None: | ||||
|     joj1, expected_result = read_convert_joj1_files(case_name) | ||||
|     result = convert_joj1(joj1).model_dump(by_alias=True, exclude_none=True) | ||||
|     root = Path(__file__).resolve().parent | ||||
|     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 | ||||
|  |  | |||
Make this
Path.home()default to/home/tt. For now, create a const for this dir.fixed