From b252a54a83ff37aedaab02ce9943a016b3984625 Mon Sep 17 00:00:00 2001
From: Boming Zhang <bomingzh@sjtu.edu.cn>
Date: Mon, 4 Mar 2024 02:11:49 -0500
Subject: [PATCH] feat: read from config file

---
 README.md                              | 34 ++++++-----
 cmd/joj3/main.go                       | 80 +++++---------------------
 internal/executors/sandbox/executor.go |  1 +
 internal/stage/run.go                  |  4 +-
 4 files changed, 38 insertions(+), 81 deletions(-)

diff --git a/README.md b/README.md
index b42ccc7..779c7d7 100644
--- a/README.md
+++ b/README.md
@@ -3,21 +3,27 @@
 In order to register sandbox executor, you need to run go-judge before running this program.
 
 ```bash
-$ make clean && make && ./build/joj3
+$ make clean && make && ./_example/simple/run.sh
 rm -rf ./build/*
 rm -rf *.out
 go build -o ./build/joj3 ./cmd/joj3
-2024/03/04 01:00:33 INFO stage start name=compile
-2024/03/04 01:00:33 INFO sandbox run cmd="{Args:[/usr/bin/g++ a.cc -o a] Env:[PATH=/usr/bin:/bin] Files:[0xc00007e380 0xc00007e3c0 0xc00007e400] CPULimit:10000000000 RealCPULimit:0 ClockLimit:0 MemoryLimit:104857600 StackLimit:0 ProcLimit:50 CPURateLimit:0 CPUSetLimit: CopyIn:map[a.cc:{Src:<nil> Content:0xc0000245f0 FileID:<nil> Name:<nil> Max:<nil> Symlink:<nil> StreamIn:false StreamOut:false Pipe:false}] CopyInCached:map[] CopyOut:[stdout stderr] CopyOutCached:[a] CopyOutMax:0 CopyOutDir: TTY:false StrictMemoryLimit:false DataSegmentLimit:false AddressSpaceLimit:false}"
-2024/03/04 01:00:33 INFO sandbox run ret="results:{status:Accepted  time:327939000  runTime:328796901  memory:57540608  files:{key:\"stderr\"  value:\"\"}  files:{key:\"stdout\"  value:\"\"}  fileIDs:{key:\"a\"  value:\"YCYTGTCQ\"}}"
-2024/03/04 01:00:33 INFO executor done result="{Status:Accepted ExitStatus:0 Error: Time:327.939ms RunTime:328.796901ms Memory:54.9 MiB Files:map[stderr:len:0 stdout:len:0] FileIDs:map[a:YCYTGTCQ] FileError:[]}"
-2024/03/04 01:00:33 INFO parser done result="&{Score:100 Comment:compile done, executor status: run time: 328796901 ns, memory: 57540608 bytes}"
-2024/03/04 01:00:33 INFO stage start name=run
-2024/03/04 01:00:33 INFO sandbox run cmd="{Args:[a] Env:[PATH=/usr/bin:/bin] Files:[0xc00007e440 0xc00007e480 0xc00007e4c0] CPULimit:10000000000 RealCPULimit:0 ClockLimit:0 MemoryLimit:104857600 StackLimit:0 ProcLimit:50 CPURateLimit:0 CPUSetLimit: CopyIn:map[] CopyInCached:map[a:a] CopyOut:[stdout stderr] CopyOutCached:[] CopyOutMax:0 CopyOutDir: TTY:false StrictMemoryLimit:false DataSegmentLimit:false AddressSpaceLimit:false}"
-2024/03/04 01:00:33 INFO sandbox run ret="results:{status:Accepted  time:1334000  runTime:2083023  memory:15384576  files:{key:\"stderr\"  value:\"\"}  files:{key:\"stdout\"  value:\"2\\n\"}}"
-2024/03/04 01:00:33 INFO executor done result="{Status:Accepted ExitStatus:0 Error: Time:1.334ms RunTime:2.083023ms Memory:14.7 MiB Files:map[stderr:len:0 stdout:len:2] FileIDs:map[] FileError:[]}"
-2024/03/04 01:00:33 INFO parser done result="&{Score:100 Comment:run done, executor status: run time: 2083023 ns, memory: 15384576 bytes}"
-compile: score: 100, comment: compile done, executor status: run time: 328796901 ns, memory: 57540608 bytes
-run: score: 100, comment: run done, executor status: run time: 2083023 ns, memory: 15384576 bytes
-2024/03/04 01:00:33 INFO sandbox cleanup
+++ dirname -- ./_example/simple/run.sh
++ DIRNAME=./_example/simple
++ cd ./_example/simple
++ ./../../build/joj3
+2024/03/04 02:09:42 INFO stage start name=compile
+2024/03/04 02:09:42 INFO sandbox run cmd="{Args:[/usr/bin/g++ a.cc -o a] Env:[PATH=/usr/bin:/bin] Files:[0xc00007f540 0xc00007f580 0xc00007f5c0] 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 02:09:42 INFO sandbox run copyInCwd=true
+2024/03/04 02:09:42 INFO sandbox run ret="results:{status:Accepted  time:321003000  runTime:321988110  memory:57888768  files:{key:\"stderr\"  value:\"\"}  files:{key:\"stdout\"  value:\"\"}  fileIDs:{key:\"a\"  value:\"T6BQPS5B\"}}"
+2024/03/04 02:09:42 INFO executor done result="{Status:Accepted ExitStatus:0 Error: Time:321.003ms RunTime:321.98811ms Memory:55.2 MiB Files:map[stderr:len:0 stdout:len:0] FileIDs:map[a:T6BQPS5B] FileError:[]}"
+2024/03/04 02:09:42 INFO parser done result="&{Score:100 Comment:compile done, executor status: run time: 321988110 ns, memory: 57888768 bytes}"
+2024/03/04 02:09:42 INFO stage start name=run
+2024/03/04 02:09:42 INFO sandbox run cmd="{Args:[./a] Env:[PATH=/usr/bin:/bin] Files:[0xc00007f600 0xc00007f640 0xc00007f680] 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 02:09:42 INFO sandbox run ret="results:{status:Accepted  time:1446000  runTime:2284978  memory:15384576  files:{key:\"stderr\"  value:\"\"}  files:{key:\"stdout\"  value:\"2\\n\"}}"
+2024/03/04 02:09:42 INFO executor done result="{Status:Accepted ExitStatus:0 Error: Time:1.446ms RunTime:2.284978ms Memory:14.7 MiB Files:map[stderr:len:0 stdout:len:2] FileIDs:map[] FileError:[]}"
+2024/03/04 02:09:42 INFO parser done result="&{Score:100 Comment:run done, executor status: run time: 2284978 ns, memory: 15384576 bytes}"
+2024/03/04 02:09:42 INFO stage result name=compile score=100 comment="compile done, executor status: run time: 321988110 ns, memory: 57888768 bytes"
+2024/03/04 02:09:42 INFO stage result name=run score=100 comment="run done, executor status: run time: 2284978 ns, memory: 15384576 bytes"
+2024/03/04 02:09:42 INFO sandbox cleanup
++ cd -
 ```
diff --git a/cmd/joj3/main.go b/cmd/joj3/main.go
index acf89fa..f1bdbe3 100644
--- a/cmd/joj3/main.go
+++ b/cmd/joj3/main.go
@@ -1,7 +1,9 @@
 package main
 
 import (
-	"fmt"
+	"flag"
+	"log/slog"
+	"os"
 
 	_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/executors"
 	_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers"
@@ -9,74 +11,22 @@ import (
 )
 
 func main() {
-	tomlConfig := `
-[[stages]]
-name = "compile"
-	[stages.executor]
-	name = "sandbox"
-	[stages.executor.with]
-	args = [ "/usr/bin/g++", "a.cc", "-o", "a" ]
-	env = [ "PATH=/usr/bin:/bin" ]
-	cpuLimit = 10_000_000_000
-	memoryLimit = 104_857_600
-	procLimit = 50
-	copyOut = [ "stdout", "stderr" ]
-	copyOutCached = [ "a" ]
-[stages.executor.with.copyIn."a.cc"]
-content = """
-#include <iostream>
-int main() {
-	int a, b;
-	std::cin >> a >> b;
-	std::cout << a + b << '\\n';
-}"""
-		[[stages.executor.with.files]]
-		content = ""
-		[[stages.executor.with.files]]
-		name = "stdout"
-		max = 4_096
-		[[stages.executor.with.files]]
-		name = "stderr"
-		max = 4_096
-	[stages.parser]
-	name = "dummy"
-	[stages.parser.with]
-	score = 100
-	comment = "compile done"
-[[stages]]
-name = "run"
-	[stages.executor]
-	name = "sandbox"
-	[stages.executor.with]
-	args = [ "a" ]
-	env = [ "PATH=/usr/bin:/bin" ]
-	cpuLimit = 10_000_000_000
-	memoryLimit = 104_857_600
-	procLimit = 50
-	copyOut = [ "stdout", "stderr" ]
-	[stages.executor.with.copyInCached]
-	    a = "a"
-		[[stages.executor.with.files]]
-		content = "1 1"
-		[[stages.executor.with.files]]
-		name = "stdout"
-		max = 4_096
-		[[stages.executor.with.files]]
-		name = "stderr"
-		max = 4_096
-	[stages.parser]
-	name = "dummy"
-	[stages.parser.with]
-	score = 100
-	comment = "run done"
-	`
+	tomlPath := flag.String("c", "conf.toml", "file path of the toml config")
+	flag.Parse()
+	tomlConfig, err := os.ReadFile(*tomlPath)
+	if err != nil {
+		slog.Error("read toml config", "error", err)
+		os.Exit(1)
+	}
 	defer stage.Cleanup()
 	stages := stage.ParseStages(tomlConfig)
 	results := stage.Run(stages)
 	for _, result := range results {
-		fmt.Printf(
-			"%s: score: %d, comment: %s\n",
-			result.Name, result.Score, result.Comment,
+		slog.Info(
+			"stage result",
+			"name", result.Name,
+			"score", result.Score,
+			"comment", result.Comment,
 		)
 	}
 }
diff --git a/internal/executors/sandbox/executor.go b/internal/executors/sandbox/executor.go
index edadfa1..28bb186 100644
--- a/internal/executors/sandbox/executor.go
+++ b/internal/executors/sandbox/executor.go
@@ -27,6 +27,7 @@ func (e *Sandbox) Run(cmd stage.Cmd) (*stage.Result, error) {
 		}
 	}
 	if cmd.CopyInCwd {
+		slog.Info("sandbox run", "copyInCwd", true)
 		err := filepath.Walk(".",
 			func(path string, info os.FileInfo, err error) error {
 				if err != nil {
diff --git a/internal/stage/run.go b/internal/stage/run.go
index 886aa30..c9a7290 100644
--- a/internal/stage/run.go
+++ b/internal/stage/run.go
@@ -7,9 +7,9 @@ import (
 	"github.com/pelletier/go-toml/v2"
 )
 
-func ParseStages(tomlConfig string) []Stage {
+func ParseStages(tomlConfig []byte) []Stage {
 	var stagesConfig StagesConfig
-	err := toml.Unmarshal([]byte(tomlConfig), &stagesConfig)
+	err := toml.Unmarshal(tomlConfig, &stagesConfig)
 	if err != nil {
 		slog.Error("parse stages config", "error", err)
 		os.Exit(1)