@@ -14,6 +14,7 @@ import (
14
14
"path"
15
15
"path/filepath"
16
16
"strings"
17
+ "time"
17
18
18
19
"github.com/urfave/cli/v2"
19
20
)
23
24
SK int8 = 1
24
25
RE int8 = 2
25
26
WA int8 = 3
27
+ TL int8 = 4
28
+ )
29
+
30
+ var (
31
+ OK int8 = 0 // OK execution status
32
+ TO int8 = 1 // Timed out status
26
33
)
27
34
28
35
var (
@@ -59,6 +66,7 @@ type CaseDescription struct {
59
66
OutputFile string
60
67
WorkFile string
61
68
CustomCase bool
69
+ TimeLimit float64
62
70
}
63
71
64
72
func getWorkFile (fileName string ) string {
@@ -68,14 +76,15 @@ func getWorkFile(fileName string) string {
68
76
}
69
77
70
78
// Creates a new CaseDescription from a pair of input and output IoFiles
71
- func NewCaseDescription (input , output config.IoFile ) * CaseDescription {
79
+ func NewCaseDescription (input , output config.IoFile , timeLimit float64 ) * CaseDescription {
72
80
base , file := filepath .Split (input .Path )
73
81
workFilePath := path .Join (base , getWorkFile (file ))
74
82
return & CaseDescription {
75
83
InputFile : input .Path ,
76
84
OutputFile : output .Path ,
77
85
WorkFile : workFilePath ,
78
86
CustomCase : input .Custom ,
87
+ TimeLimit : timeLimit ,
79
88
}
80
89
}
81
90
@@ -144,6 +153,8 @@ func getDisplayStatus(status int8) string {
144
153
return yellow ("SK" )
145
154
case WA :
146
155
return red ("WA" )
156
+ case TL :
157
+ return red ("TL" ) // TODO(Eroui): Add another color?
147
158
}
148
159
return "Unknown"
149
160
}
@@ -181,6 +192,22 @@ func newJudgeReport() JudgeReport {
181
192
return & ConsoleJudgeReport {Stats : []CaseStatus {}}
182
193
}
183
194
195
+
196
+ func timedExecution (cmd * exec.Cmd , timeOut float64 ) (int8 , error ) {
197
+ cmd .Start ()
198
+ done := make (chan error )
199
+ go func () { done <- cmd .Wait () }()
200
+
201
+ timeout := time .After (time .Duration (timeOut ) * time .Millisecond )
202
+ select {
203
+ case <- timeout :
204
+ cmd .Process .Kill ()
205
+ return TO , nil
206
+ case err := <- done :
207
+ return OK , err
208
+ }
209
+ }
210
+
184
211
// Utility function to execute the given command that is associated with the given judge
185
212
// the method returns the case status and the error (if any)
186
213
func execute (judge Judge , desc CaseDescription , command string , args ... string ) (CaseStatus , error ) {
@@ -208,7 +235,17 @@ func execute(judge Judge, desc CaseDescription, command string, args ...string)
208
235
cmd .Stdin = inputFile
209
236
cmd .Stdout = outputFile
210
237
cmd .Stderr = & stderrBuffer
211
- if err = cmd .Run (); err != nil {
238
+
239
+ status , err := timedExecution (cmd , desc .TimeLimit )
240
+ if status == TO {
241
+ return CaseStatus {
242
+ Status : TL ,
243
+ CheckerError : nil ,
244
+ Stderr : stderrBuffer .String (),
245
+ }, nil
246
+ }
247
+
248
+ if err != nil {
212
249
return CaseStatus {
213
250
Status : RE ,
214
251
CheckerError : nil ,
@@ -459,7 +496,7 @@ func RunAction(_ *cli.Context) error {
459
496
460
497
for i , input := range egorMeta .Inputs {
461
498
output := egorMeta .Outputs [i ]
462
- caseDescription := NewCaseDescription (input , output )
499
+ caseDescription := NewCaseDescription (input , output , egorMeta . TimeLimit )
463
500
status := judge .RunTestCase (* caseDescription )
464
501
report .Add (status , * caseDescription )
465
502
}
0 commit comments