feat: multiple cmds each stage
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
02098d949e
commit
f5b6b3cc9a
|
@ -14,7 +14,7 @@ go build -o ./build/joj3 ./cmd/joj3
|
||||||
+ cd ./_example/simple
|
+ cd ./_example/simple
|
||||||
+ ./../../build/joj3
|
+ ./../../build/joj3
|
||||||
+ cat ./joj3_result.json
|
+ 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"}]
|
[{"Name":"compile","ParserResults":[{"Score":100,"Comment":"compile done, executor status: run time: 274901520 ns, memory: 57880576 bytes"}]},{"Name":"run","ParserResults":[{"Score":100,"Comment":"executor status: run time: 2343025 ns, memory: 13225984 bytes"},{"Score":0,"Comment":"executor status: run time: 2071433 ns, memory: 14544896 bytes"}]}]
|
||||||
+ rm -f ./joj3_result.json
|
+ rm -f ./joj3_result.json
|
||||||
+ cd -
|
+ cd -
|
||||||
```
|
```
|
||||||
|
|
1
_example/simple/2.stdin
Normal file
1
_example/simple/2.stdin
Normal file
|
@ -0,0 +1 @@
|
||||||
|
1024 2048
|
1
_example/simple/2.stdout
Normal file
1
_example/simple/2.stdout
Normal file
|
@ -0,0 +1 @@
|
||||||
|
3072
|
|
@ -3,7 +3,7 @@ logLevel = 8
|
||||||
name = "compile"
|
name = "compile"
|
||||||
[stages.executor]
|
[stages.executor]
|
||||||
name = "sandbox"
|
name = "sandbox"
|
||||||
[stages.executor.with]
|
[stages.executor.with.default]
|
||||||
args = ["/usr/bin/g++", "a.cc", "-o", "a"]
|
args = ["/usr/bin/g++", "a.cc", "-o", "a"]
|
||||||
env = ["PATH=/usr/bin:/bin"]
|
env = ["PATH=/usr/bin:/bin"]
|
||||||
cpuLimit = 10_000_000_000
|
cpuLimit = 10_000_000_000
|
||||||
|
@ -12,12 +12,12 @@ procLimit = 50
|
||||||
copyInCwd = true
|
copyInCwd = true
|
||||||
copyOut = ["stdout", "stderr"]
|
copyOut = ["stdout", "stderr"]
|
||||||
copyOutCached = ["a"]
|
copyOutCached = ["a"]
|
||||||
[[stages.executor.with.files]]
|
[[stages.executor.with.default.files]]
|
||||||
content = ""
|
content = ""
|
||||||
[[stages.executor.with.files]]
|
[[stages.executor.with.default.files]]
|
||||||
name = "stdout"
|
name = "stdout"
|
||||||
max = 4_096
|
max = 4_096
|
||||||
[[stages.executor.with.files]]
|
[[stages.executor.with.default.files]]
|
||||||
name = "stderr"
|
name = "stderr"
|
||||||
max = 4_096
|
max = 4_096
|
||||||
[stages.parser]
|
[stages.parser]
|
||||||
|
@ -29,25 +29,38 @@ comment = "compile done"
|
||||||
name = "run"
|
name = "run"
|
||||||
[stages.executor]
|
[stages.executor]
|
||||||
name = "sandbox"
|
name = "sandbox"
|
||||||
[stages.executor.with]
|
[stages.executor.with.default]
|
||||||
args = ["./a"]
|
args = ["./a"]
|
||||||
env = ["PATH=/usr/bin:/bin"]
|
env = ["PATH=/usr/bin:/bin"]
|
||||||
cpuLimit = 10_000_000_000
|
cpuLimit = 10_000_000_000
|
||||||
memoryLimit = 104_857_600
|
memoryLimit = 104_857_600
|
||||||
procLimit = 50
|
procLimit = 50
|
||||||
copyOut = ["stdout", "stderr"]
|
copyOut = ["stdout", "stderr"]
|
||||||
[stages.executor.with.copyInCached]
|
[stages.executor.with.default.copyInCached]
|
||||||
a = "a"
|
a = "a"
|
||||||
[[stages.executor.with.files]]
|
[[stages.executor.with.cases]]
|
||||||
|
[[stages.executor.with.cases.files]]
|
||||||
src = "1.stdin"
|
src = "1.stdin"
|
||||||
[[stages.executor.with.files]]
|
[[stages.executor.with.cases.files]]
|
||||||
name = "stdout"
|
name = "stdout"
|
||||||
max = 4_096
|
max = 4_096
|
||||||
[[stages.executor.with.files]]
|
[[stages.executor.with.cases.files]]
|
||||||
|
name = "stderr"
|
||||||
|
max = 4_096
|
||||||
|
[[stages.executor.with.cases]]
|
||||||
|
[[stages.executor.with.cases.files]]
|
||||||
|
src = "1.stdin"
|
||||||
|
[[stages.executor.with.cases.files]]
|
||||||
|
name = "stdout"
|
||||||
|
max = 4_096
|
||||||
|
[[stages.executor.with.cases.files]]
|
||||||
name = "stderr"
|
name = "stderr"
|
||||||
max = 4_096
|
max = 4_096
|
||||||
[stages.parser]
|
[stages.parser]
|
||||||
name = "diff"
|
name = "diff"
|
||||||
[stages.parser.with]
|
[[stages.parser.with.cases]]
|
||||||
score = 100
|
score = 100
|
||||||
stdoutPath = "1.stdout"
|
stdoutPath = "1.stdout"
|
||||||
|
[[stages.parser.with.cases]]
|
||||||
|
score = 100
|
||||||
|
stdoutPath = "2.stdout"
|
||||||
|
|
|
@ -9,7 +9,10 @@ type Conf struct {
|
||||||
Name string
|
Name string
|
||||||
Executor struct {
|
Executor struct {
|
||||||
Name string
|
Name string
|
||||||
With stage.Cmd
|
With struct {
|
||||||
|
Default stage.Cmd
|
||||||
|
Cases []OptionalCmd
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Parser struct {
|
Parser struct {
|
||||||
Name string
|
Name string
|
||||||
|
@ -17,3 +20,32 @@ type Conf struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OptionalCmd struct {
|
||||||
|
Args *[]string
|
||||||
|
Env *[]string
|
||||||
|
Files *[]*stage.CmdFile
|
||||||
|
|
||||||
|
CPULimit *uint64
|
||||||
|
RealCPULimit *uint64
|
||||||
|
ClockLimit *uint64
|
||||||
|
MemoryLimit *uint64
|
||||||
|
StackLimit *uint64
|
||||||
|
ProcLimit *uint64
|
||||||
|
CPURateLimit *uint64
|
||||||
|
CPUSetLimit *string
|
||||||
|
|
||||||
|
CopyIn *map[string]stage.CmdFile
|
||||||
|
CopyInCached *map[string]string
|
||||||
|
CopyInCwd *bool
|
||||||
|
|
||||||
|
CopyOut *[]string
|
||||||
|
CopyOutCached *[]string
|
||||||
|
CopyOutMax *uint64
|
||||||
|
CopyOutDir *string
|
||||||
|
|
||||||
|
TTY *bool
|
||||||
|
StrictMemoryLimit *bool
|
||||||
|
DataSegmentLimit *bool
|
||||||
|
AddressSpaceLimit *bool
|
||||||
|
}
|
||||||
|
|
|
@ -10,15 +10,18 @@ import (
|
||||||
_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers"
|
_ "focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/parsers"
|
||||||
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
|
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
|
||||||
|
|
||||||
"github.com/pelletier/go-toml/v2"
|
// "github.com/pelletier/go-toml/v2" may panic on some error
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
)
|
)
|
||||||
|
|
||||||
func parseConfFile(tomlPath *string) (Conf, []stage.Stage) {
|
func parseConfFile(tomlPath *string) Conf {
|
||||||
tomlConfig, err := os.ReadFile(*tomlPath)
|
tomlConfig, err := os.ReadFile(*tomlPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("read toml config", "error", err)
|
slog.Error("read toml config", "error", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
// fill in default value of config file
|
||||||
conf := Conf{
|
conf := Conf{
|
||||||
LogLevel: 0,
|
LogLevel: 0,
|
||||||
OutputPath: "joj3_result.json",
|
OutputPath: "joj3_result.json",
|
||||||
|
@ -28,17 +31,7 @@ func parseConfFile(tomlPath *string) (Conf, []stage.Stage) {
|
||||||
slog.Error("parse stages config", "error", err)
|
slog.Error("parse stages config", "error", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
stages := []stage.Stage{}
|
return conf
|
||||||
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) {
|
func setupSlog(conf Conf) {
|
||||||
|
@ -50,6 +43,30 @@ func setupSlog(conf Conf) {
|
||||||
slog.SetDefault(logger)
|
slog.SetDefault(logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateStages(conf Conf) []stage.Stage {
|
||||||
|
stages := []stage.Stage{}
|
||||||
|
for _, s := range conf.Stages {
|
||||||
|
var cmds []stage.Cmd
|
||||||
|
for _, optionalCmd := range s.Executor.With.Cases {
|
||||||
|
cmd := s.Executor.With.Default
|
||||||
|
copier.Copy(&cmd, &optionalCmd)
|
||||||
|
cmds = append(cmds, cmd)
|
||||||
|
}
|
||||||
|
if len(s.Executor.With.Cases) == 0 {
|
||||||
|
cmds = append(cmds, s.Executor.With.Default)
|
||||||
|
}
|
||||||
|
slog.Info("parse stages config", "cmds", cmds)
|
||||||
|
stages = append(stages, stage.Stage{
|
||||||
|
Name: s.Name,
|
||||||
|
ExecutorName: s.Executor.Name,
|
||||||
|
ExecutorCmds: cmds,
|
||||||
|
ParserName: s.Parser.Name,
|
||||||
|
ParserConfig: s.Parser.With,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return stages
|
||||||
|
}
|
||||||
|
|
||||||
func outputResult(conf Conf, results []stage.StageResult) error {
|
func outputResult(conf Conf, results []stage.StageResult) error {
|
||||||
content, err := json.Marshal(results)
|
content, err := json.Marshal(results)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -62,8 +79,9 @@ func outputResult(conf Conf, results []stage.StageResult) error {
|
||||||
func main() {
|
func main() {
|
||||||
tomlPath := flag.String("c", "conf.toml", "file path of the toml config")
|
tomlPath := flag.String("c", "conf.toml", "file path of the toml config")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
conf, stages := parseConfFile(tomlPath)
|
conf := parseConfFile(tomlPath)
|
||||||
setupSlog(conf)
|
setupSlog(conf)
|
||||||
|
stages := generateStages(conf)
|
||||||
defer stage.Cleanup()
|
defer stage.Cleanup()
|
||||||
results := stage.Run(stages)
|
results := stage.Run(stages)
|
||||||
err := outputResult(conf, results)
|
err := outputResult(conf, results)
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -3,9 +3,9 @@ module focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3
|
||||||
go 1.22.0
|
go 1.22.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/BurntSushi/toml v1.3.2
|
||||||
github.com/criyle/go-judge v1.8.2
|
github.com/criyle/go-judge v1.8.2
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/pelletier/go-toml/v2 v2.1.1
|
|
||||||
google.golang.org/grpc v1.62.0
|
google.golang.org/grpc v1.62.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ require (
|
||||||
github.com/creack/pty v1.1.21 // indirect
|
github.com/creack/pty v1.1.21 // indirect
|
||||||
github.com/criyle/go-sandbox v0.10.1 // indirect
|
github.com/criyle/go-sandbox v0.10.1 // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
|
github.com/jinzhu/copier v0.4.0
|
||||||
golang.org/x/net v0.21.0 // indirect
|
golang.org/x/net v0.21.0 // indirect
|
||||||
golang.org/x/sync v0.6.0 // indirect
|
golang.org/x/sync v0.6.0 // indirect
|
||||||
golang.org/x/sys v0.17.0 // indirect
|
golang.org/x/sys v0.17.0 // indirect
|
||||||
|
|
22
go.sum
22
go.sum
|
@ -1,31 +1,21 @@
|
||||||
|
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||||
|
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
|
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
|
||||||
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||||
github.com/criyle/go-judge v1.8.2 h1:dGjLqJRBifqsLVZj1scr23zdM4wPe98HTIVgYzPuRxA=
|
github.com/criyle/go-judge v1.8.2 h1:dGjLqJRBifqsLVZj1scr23zdM4wPe98HTIVgYzPuRxA=
|
||||||
github.com/criyle/go-judge v1.8.2/go.mod h1:3RgsMp21D+UvXzkpOGsVFbLe2T2Lwk8jPEmCntQrvHQ=
|
github.com/criyle/go-judge v1.8.2/go.mod h1:3RgsMp21D+UvXzkpOGsVFbLe2T2Lwk8jPEmCntQrvHQ=
|
||||||
github.com/criyle/go-sandbox v0.10.1 h1:z9Il/UXQwKEvIwdr1wVheWWWAqGWtdTItBmEsWqFqT4=
|
github.com/criyle/go-sandbox v0.10.1 h1:z9Il/UXQwKEvIwdr1wVheWWWAqGWtdTItBmEsWqFqT4=
|
||||||
github.com/criyle/go-sandbox v0.10.1/go.mod h1:ivPw/HEh5unxVRlXJxCgkgTCuy+cxTkQDX7D2XQf/kg=
|
github.com/criyle/go-sandbox v0.10.1/go.mod h1:ivPw/HEh5unxVRlXJxCgkgTCuy+cxTkQDX7D2XQf/kg=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||||
|
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
|
|
||||||
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
|
@ -43,7 +33,3 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
|
|
|
@ -7,17 +7,21 @@ import (
|
||||||
|
|
||||||
type Dummy struct{}
|
type Dummy struct{}
|
||||||
|
|
||||||
func (e *Dummy) Run(stage.Cmd) (*stage.ExecutorResult, error) {
|
func (e *Dummy) Run(cmds []stage.Cmd) ([]stage.ExecutorResult, error) {
|
||||||
return &stage.ExecutorResult{
|
var res []stage.ExecutorResult
|
||||||
Status: stage.Status(envexec.StatusInvalid),
|
for range cmds {
|
||||||
ExitStatus: 0,
|
res = append(res, stage.ExecutorResult{
|
||||||
Error: "I'm a dummy",
|
Status: stage.Status(envexec.StatusInvalid),
|
||||||
Time: 0,
|
ExitStatus: 0,
|
||||||
Memory: 0,
|
Error: "I'm a dummy",
|
||||||
RunTime: 0,
|
Time: 0,
|
||||||
Files: map[string]string{},
|
Memory: 0,
|
||||||
FileIDs: map[string]string{},
|
RunTime: 0,
|
||||||
}, nil
|
Files: map[string]string{},
|
||||||
|
FileIDs: map[string]string{},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Dummy) Cleanup() error {
|
func (e *Dummy) Cleanup() error {
|
||||||
|
|
|
@ -14,16 +14,20 @@ type Sandbox struct {
|
||||||
cachedMap map[string]string
|
cachedMap map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Sandbox) Run(cmd stage.Cmd) (*stage.ExecutorResult, error) {
|
func (e *Sandbox) Run(cmds []stage.Cmd) ([]stage.ExecutorResult, error) {
|
||||||
if cmd.CopyIn == nil {
|
// cannot use range loop since we need to change the value
|
||||||
cmd.CopyIn = make(map[string]stage.CmdFile)
|
for i := 0; i < len(cmds); i++ {
|
||||||
}
|
cmd := &cmds[i]
|
||||||
for k, v := range cmd.CopyInCached {
|
if cmd.CopyIn == nil {
|
||||||
if fileID, ok := e.cachedMap[v]; ok {
|
cmd.CopyIn = make(map[string]stage.CmdFile)
|
||||||
cmd.CopyIn[k] = stage.CmdFile{FileID: &fileID}
|
}
|
||||||
|
for k, v := range cmd.CopyInCached {
|
||||||
|
if fileID, ok := e.cachedMap[v]; ok {
|
||||||
|
cmd.CopyIn[k] = stage.CmdFile{FileID: &fileID}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pbReq := &pb.Request{Cmd: convertPBCmd([]stage.Cmd{cmd})}
|
pbReq := &pb.Request{Cmd: convertPBCmd(cmds)}
|
||||||
pbRet, err := e.execClient.Exec(context.TODO(), pbReq)
|
pbRet, err := e.execClient.Exec(context.TODO(), pbReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -31,11 +35,13 @@ func (e *Sandbox) Run(cmd stage.Cmd) (*stage.ExecutorResult, error) {
|
||||||
if pbRet.Error != "" {
|
if pbRet.Error != "" {
|
||||||
return nil, fmt.Errorf("sandbox execute error: %s", pbRet.Error)
|
return nil, fmt.Errorf("sandbox execute error: %s", pbRet.Error)
|
||||||
}
|
}
|
||||||
executorRes := &convertPBResult(pbRet.Results)[0]
|
results := convertPBResult(pbRet.Results)
|
||||||
for fileName, fileID := range executorRes.FileIDs {
|
for _, result := range results {
|
||||||
e.cachedMap[fileName] = fileID
|
for fileName, fileID := range result.FileIDs {
|
||||||
|
e.cachedMap[fileName] = fileID
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return executorRes, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Sandbox) Cleanup() error {
|
func (e *Sandbox) Cleanup() error {
|
||||||
|
|
|
@ -8,33 +8,43 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Score int
|
Cases []struct {
|
||||||
StdoutPath string
|
Score int
|
||||||
|
StdoutPath string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Diff struct{}
|
type Diff struct{}
|
||||||
|
|
||||||
func (e *Diff) Run(result *stage.ExecutorResult, configAny any) (
|
func (e *Diff) Run(results []stage.ExecutorResult, configAny any) (
|
||||||
*stage.ParserResult, error,
|
[]stage.ParserResult, error,
|
||||||
) {
|
) {
|
||||||
config, err := stage.DecodeConfig[Config](configAny)
|
config, err := stage.DecodeConfig[Config](configAny)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
score := 0
|
if len(config.Cases) != len(results) {
|
||||||
stdout, err := os.ReadFile(config.StdoutPath)
|
return nil, fmt.Errorf("cases number not match")
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
// TODO: more compare strategies
|
var res []stage.ParserResult
|
||||||
if string(stdout) == result.Files["stdout"] {
|
for i, caseConfig := range config.Cases {
|
||||||
score = config.Score
|
result := results[i]
|
||||||
|
score := 0
|
||||||
|
stdout, err := os.ReadFile(caseConfig.StdoutPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// TODO: more compare strategies
|
||||||
|
if string(stdout) == result.Files["stdout"] {
|
||||||
|
score = caseConfig.Score
|
||||||
|
}
|
||||||
|
res = append(res, stage.ParserResult{
|
||||||
|
Score: score,
|
||||||
|
Comment: fmt.Sprintf(
|
||||||
|
"executor status: run time: %d ns, memory: %d bytes",
|
||||||
|
result.RunTime, result.Memory,
|
||||||
|
),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return &stage.ParserResult{
|
return res, nil
|
||||||
Score: score,
|
|
||||||
Comment: fmt.Sprintf(
|
|
||||||
"executor status: run time: %d ns, memory: %d bytes",
|
|
||||||
result.RunTime, result.Memory,
|
|
||||||
),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,18 +13,22 @@ type Config struct {
|
||||||
|
|
||||||
type Dummy struct{}
|
type Dummy struct{}
|
||||||
|
|
||||||
func (e *Dummy) Run(result *stage.ExecutorResult, configAny any) (
|
func (e *Dummy) Run(results []stage.ExecutorResult, configAny any) (
|
||||||
*stage.ParserResult, error,
|
[]stage.ParserResult, error,
|
||||||
) {
|
) {
|
||||||
config, err := stage.DecodeConfig[Config](configAny)
|
config, err := stage.DecodeConfig[Config](configAny)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &stage.ParserResult{
|
var res []stage.ParserResult
|
||||||
Score: config.Score,
|
for _, result := range results {
|
||||||
Comment: fmt.Sprintf(
|
res = append(res, stage.ParserResult{
|
||||||
"%s, executor status: run time: %d ns, memory: %d bytes",
|
Score: config.Score,
|
||||||
config.Comment, result.RunTime, result.Memory,
|
Comment: fmt.Sprintf(
|
||||||
),
|
"%s, executor status: run time: %d ns, memory: %d bytes",
|
||||||
}, nil
|
config.Comment, result.RunTime, result.Memory,
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package stage
|
||||||
var executorMap = map[string]Executor{}
|
var executorMap = map[string]Executor{}
|
||||||
|
|
||||||
type Executor interface {
|
type Executor interface {
|
||||||
Run(Cmd) (*ExecutorResult, error)
|
Run([]Cmd) ([]ExecutorResult, error)
|
||||||
Cleanup() error
|
Cleanup() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ func (r ExecutorResult) String() string {
|
||||||
type Stage struct {
|
type Stage struct {
|
||||||
Name string
|
Name string
|
||||||
ExecutorName string
|
ExecutorName string
|
||||||
ExecutorCmd Cmd
|
ExecutorCmds []Cmd
|
||||||
ParserName string
|
ParserName string
|
||||||
ParserConfig any
|
ParserConfig any
|
||||||
}
|
}
|
||||||
|
@ -162,6 +162,6 @@ type ParserResult struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type StageResult struct {
|
type StageResult struct {
|
||||||
Name string
|
Name string
|
||||||
*ParserResult
|
ParserResults []ParserResult
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ package stage
|
||||||
var parserMap = map[string]Parser{}
|
var parserMap = map[string]Parser{}
|
||||||
|
|
||||||
type Parser interface {
|
type Parser interface {
|
||||||
Run(*ExecutorResult, any) (*ParserResult, error)
|
Run([]ExecutorResult, any) ([]ParserResult, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterParser(name string, parser Parser) {
|
func RegisterParser(name string, parser Parser) {
|
||||||
|
|
|
@ -5,31 +5,31 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(stages []Stage) []StageResult {
|
func Run(stages []Stage) []StageResult {
|
||||||
var parserResults []StageResult
|
var stageResults []StageResult
|
||||||
for _, stage := range stages {
|
for _, stage := range stages {
|
||||||
slog.Info("stage start", "name", stage.Name)
|
slog.Info("stage start", "name", stage.Name)
|
||||||
slog.Info("executor run start", "cmd", stage.ExecutorCmd)
|
slog.Info("executor run start", "cmds", stage.ExecutorCmds)
|
||||||
executor := executorMap[stage.ExecutorName]
|
executor := executorMap[stage.ExecutorName]
|
||||||
executorResult, err := executor.Run(stage.ExecutorCmd)
|
executorResults, err := executor.Run(stage.ExecutorCmds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("executor run error", "name", stage.ExecutorName, "error", err)
|
slog.Error("executor run error", "name", stage.ExecutorName, "error", err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
slog.Info("executor run done", "result", executorResult)
|
slog.Info("executor run done", "results", executorResults)
|
||||||
slog.Info("parser run start", "config", stage.ParserConfig)
|
slog.Info("parser run start", "config", stage.ParserConfig)
|
||||||
parser := parserMap[stage.ParserName]
|
parser := parserMap[stage.ParserName]
|
||||||
parserResult, err := parser.Run(executorResult, stage.ParserConfig)
|
parserResults, err := parser.Run(executorResults, stage.ParserConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("parser run error", "name", stage.ExecutorName, "error", err)
|
slog.Error("parser run error", "name", stage.ExecutorName, "error", err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
slog.Info("parser run done", "result", parserResult)
|
slog.Info("parser run done", "results", parserResults)
|
||||||
parserResults = append(parserResults, StageResult{
|
stageResults = append(stageResults, StageResult{
|
||||||
Name: stage.Name,
|
Name: stage.Name,
|
||||||
ParserResult: parserResult,
|
ParserResults: parserResults,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return parserResults
|
return stageResults
|
||||||
}
|
}
|
||||||
|
|
||||||
func Cleanup() {
|
func Cleanup() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user