diff --git a/README.md b/README.md index cffd35c..0ce5fb0 100644 --- a/README.md +++ b/README.md @@ -13,22 +13,9 @@ go build -o ./build/joj3 ./cmd/joj3 + DIRNAME=./_example/simple + cd ./_example/simple + ./../../build/joj3 -2024/03/04 14:33:27 INFO stage start name=compile -2024/03/04 14:33:27 INFO executor run start cmd="{Args:[/usr/bin/g++ a.cc -o a] Env:[PATH=/usr/bin:/bin] Files:[0xc000114340 0xc000114380 0xc0001143c0] CPULimit:10000000000 RealCPULimit:0 ClockLimit:0 MemoryLimit:104857600 StackLimit:0 ProcLimit:50 CPURateLimit:0 CPUSetLimit: CopyIn:map[] CopyInCached:map[] CopyInCwd:true CopyOut:[stdout stderr] CopyOutCached:[a] CopyOutMax:0 CopyOutDir: TTY:false StrictMemoryLimit:false DataSegmentLimit:false AddressSpaceLimit:false}" -2024/03/04 14:33:27 INFO executor run done result="{Status:Accepted ExitStatus:0 Error: Time:355.171ms RunTime:356.069198ms Memory:53.9 MiB Files:map[stderr:len:0 stdout:len:0] FileIDs:map[a:VNQ3A3QC] FileError:[]}" -2024/03/04 14:33:27 INFO parser run start config="map[comment:compile done score:100]" -2024/03/04 14:33:27 INFO parser run done result="&{Score:100 Comment:compile done, executor status: run time: 356069198 ns, memory: 56561664 bytes}" -2024/03/04 14:33:27 INFO stage start name=run -2024/03/04 14:33:27 INFO executor run start cmd="{Args:[./a] Env:[PATH=/usr/bin:/bin] Files:[0xc000114400 0xc000114440 0xc000114480] CPULimit:10000000000 RealCPULimit:0 ClockLimit:0 MemoryLimit:104857600 StackLimit:0 ProcLimit:50 CPURateLimit:0 CPUSetLimit: CopyIn:map[] CopyInCached:map[a:a] CopyInCwd:false CopyOut:[stdout stderr] CopyOutCached:[] CopyOutMax:0 CopyOutDir: TTY:false StrictMemoryLimit:false DataSegmentLimit:false AddressSpaceLimit:false}" -2024/03/04 14:33:27 INFO executor run done result="{Status:Accepted ExitStatus:0 Error: Time:1.393ms RunTime:2.2294ms Memory:12.8 MiB Files:map[stderr:len:0 stdout:len:2] FileIDs:map[] FileError:[]}" -2024/03/04 14:33:27 INFO parser run start config="map[score:100 stdoutPath:1.stdout]" -2024/03/04 14:33:27 INFO parser run done result="&{Score:100 Comment:}" -2024/03/04 14:33:27 INFO stage result name=compile score=100 comment="compile done, executor status: run time: 356069198 ns, memory: 56561664 bytes" -2024/03/04 14:33:27 INFO stage result name=run score=100 comment="" -2024/03/04 14:33:27 INFO executor cleanup start name=dummy -2024/03/04 14:33:27 INFO executor cleanup done name=dummy -2024/03/04 14:33:27 INFO executor cleanup start name=sandbox -2024/03/04 14:33:27 INFO executor cleanup done name=sandbox ++ cat ./joj3_result.json +[{"Name":"compile","Score":100,"Comment":"compile done, executor status: run time: 239591301 ns, memory: 57176064 bytes"},{"Name":"run","Score":100,"Comment":"executor status: run time: 1839200 ns, memory: 16826368 bytes"}] ++ rm -f ./joj3_result.json + cd - ``` diff --git a/_example/simple/conf.toml b/_example/simple/conf.toml index d7515a3..2f27ff2 100644 --- a/_example/simple/conf.toml +++ b/_example/simple/conf.toml @@ -1,3 +1,4 @@ +logLevel = 8 [[stages]] name = "compile" [stages.executor] diff --git a/_example/simple/run.sh b/_example/simple/run.sh index a964c9b..9088452 100755 --- a/_example/simple/run.sh +++ b/_example/simple/run.sh @@ -5,4 +5,6 @@ DIRNAME=`dirname -- "$0"` # cd to make CopyInCwd work cd $DIRNAME ./../../build/joj3 +cat ./joj3_result.json +rm -f ./joj3_result.json cd - diff --git a/cmd/joj3/conf.go b/cmd/joj3/conf.go new file mode 100644 index 0000000..ce68131 --- /dev/null +++ b/cmd/joj3/conf.go @@ -0,0 +1,19 @@ +package main + +import "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" + +type Conf struct { + LogLevel int + OutputPath string + Stages []struct { + Name string + Executor struct { + Name string + With stage.Cmd + } + Parser struct { + Name string + With interface{} + } + } +} diff --git a/cmd/joj3/main.go b/cmd/joj3/main.go index f1bdbe3..bdd0301 100644 --- a/cmd/joj3/main.go +++ b/cmd/joj3/main.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "flag" "log/slog" "os" @@ -8,25 +9,65 @@ import ( _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/executors" _ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers" "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" + + "github.com/pelletier/go-toml/v2" ) -func main() { - tomlPath := flag.String("c", "conf.toml", "file path of the toml config") - flag.Parse() +func parseConfFile(tomlPath *string) (Conf, []stage.Stage) { tomlConfig, err := os.ReadFile(*tomlPath) if err != nil { slog.Error("read toml config", "error", err) os.Exit(1) } + conf := Conf{ + LogLevel: 0, + OutputPath: "joj3_result.json", + } + err = toml.Unmarshal(tomlConfig, &conf) + if err != nil { + slog.Error("parse stages config", "error", err) + os.Exit(1) + } + stages := []stage.Stage{} + for _, s := range conf.Stages { + stages = append(stages, stage.Stage{ + Name: s.Name, + ExecutorName: s.Executor.Name, + ExecutorCmd: s.Executor.With, + ParserName: s.Parser.Name, + ParserConfig: s.Parser.With, + }) + } + return conf, stages +} + +func setupSlog(conf Conf) { + lvl := new(slog.LevelVar) + lvl.Set(slog.Level(conf.LogLevel)) + opts := &slog.HandlerOptions{Level: lvl} + handler := slog.NewTextHandler(os.Stderr, opts) + logger := slog.New(handler) + slog.SetDefault(logger) +} + +func outputResult(conf Conf, results []stage.StageResult) error { + content, err := json.Marshal(results) + if err != nil { + return err + } + return os.WriteFile(conf.OutputPath, + append(content, []byte("\n")...), 0o666) +} + +func main() { + tomlPath := flag.String("c", "conf.toml", "file path of the toml config") + flag.Parse() + conf, stages := parseConfFile(tomlPath) + setupSlog(conf) defer stage.Cleanup() - stages := stage.ParseStages(tomlConfig) results := stage.Run(stages) - for _, result := range results { - slog.Info( - "stage result", - "name", result.Name, - "score", result.Score, - "comment", result.Comment, - ) + err := outputResult(conf, results) + if err != nil { + slog.Error("output result", "error", err) } } diff --git a/internal/parsers/diff/parser.go b/internal/parsers/diff/parser.go index 9610e6c..b9cbc45 100644 --- a/internal/parsers/diff/parser.go +++ b/internal/parsers/diff/parser.go @@ -1,6 +1,7 @@ package diff import ( + "fmt" "os" "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage" @@ -30,7 +31,10 @@ func (e *Diff) Run(result *stage.ExecutorResult, configAny any) ( score = config.Score } return &stage.ParserResult{ - Score: score, - Comment: "", + Score: score, + Comment: fmt.Sprintf( + "executor status: run time: %d ns, memory: %d bytes", + result.RunTime, result.Memory, + ), }, nil } diff --git a/internal/stage/model.go b/internal/stage/model.go index ef7b92d..d97b3b7 100644 --- a/internal/stage/model.go +++ b/internal/stage/model.go @@ -151,10 +151,8 @@ func (r ExecutorResult) String() string { type Stage struct { Name string ExecutorName string - Executor Executor ExecutorCmd Cmd ParserName string - Parser Parser ParserConfig any } @@ -167,17 +165,3 @@ type StageResult struct { Name string *ParserResult } - -type StagesConfig struct { - Stages []struct { - Name string - Executor struct { - Name string - With Cmd - } - Parser struct { - Name string - With interface{} - } - } -} diff --git a/internal/stage/run.go b/internal/stage/run.go index 0b81920..4e08450 100644 --- a/internal/stage/run.go +++ b/internal/stage/run.go @@ -2,46 +2,23 @@ package stage import ( "log/slog" - "os" - - "github.com/pelletier/go-toml/v2" ) -func ParseStages(tomlConfig []byte) []Stage { - var stagesConfig StagesConfig - err := toml.Unmarshal(tomlConfig, &stagesConfig) - if err != nil { - slog.Error("parse stages config", "error", err) - os.Exit(1) - } - stages := []Stage{} - for _, stage := range stagesConfig.Stages { - stages = append(stages, Stage{ - Name: stage.Name, - ExecutorName: stage.Executor.Name, - Executor: executorMap[stage.Executor.Name], - ExecutorCmd: stage.Executor.With, - ParserName: stage.Parser.Name, - Parser: parserMap[stage.Parser.Name], - ParserConfig: stage.Parser.With, - }) - } - return stages -} - func Run(stages []Stage) []StageResult { var parserResults []StageResult for _, stage := range stages { slog.Info("stage start", "name", stage.Name) slog.Info("executor run start", "cmd", stage.ExecutorCmd) - executorResult, err := stage.Executor.Run(stage.ExecutorCmd) + executor := executorMap[stage.ExecutorName] + executorResult, err := executor.Run(stage.ExecutorCmd) if err != nil { slog.Error("executor run error", "name", stage.ExecutorName, "error", err) break } slog.Info("executor run done", "result", executorResult) slog.Info("parser run start", "config", stage.ParserConfig) - parserResult, err := stage.Parser.Run(executorResult, stage.ParserConfig) + parser := parserMap[stage.ParserName] + parserResult, err := parser.Run(executorResult, stage.ParserConfig) if err != nil { slog.Error("parser run error", "name", stage.ExecutorName, "error", err) break