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