Skip to content

Commit 265f534

Browse files
d
1 parent ae3746f commit 265f534

File tree

7 files changed

+95
-18
lines changed

7 files changed

+95
-18
lines changed

.vscode/launch.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "Launch Package",
9+
"type": "go",
10+
"request": "launch",
11+
"mode": "auto",
12+
"program": "${fileDirname}",
13+
"envFile": "${workspaceFolder}/.env"
14+
}
15+
]
16+
}

backend/cmd/compile_user_code.go

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import (
44
"context"
55
"io"
66
"strconv"
7+
"time"
78

8-
//"log"
9+
"log"
910
"path/filepath"
1011

1112
dockertypes "github.com/docker/docker/api/types"
@@ -15,8 +16,8 @@ import (
1516
"github.com/pkg/errors"
1617
)
1718

18-
// Memory Limit of a G++ Process
1919
const CompilationMemoryLimit = 100 * 1024 * 1024
20+
const CompilationTimeLimit = 10 * time.Second
2021

2122
// it is required that the docker image is built before the program runs
2223
const imageCompile = "markhuang1212/code-grader/runtime-compile:latest"
@@ -25,12 +26,15 @@ const imageCompile = "markhuang1212/code-grader/runtime-compile:latest"
2526
// executable on success
2627
func CompileUserCode(ctx context.Context, gr types.GradeRequest) ([]byte, error) {
2728

29+
ctxdl, cancel := context.WithTimeout(ctx, CompilationTimeLimit)
30+
defer cancel()
31+
2832
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
2933
if err != nil {
3034
return nil, errors.WithMessage(err, "cannot create docker client")
3135
}
3236

33-
resp, err := cli.ContainerCreate(ctx, &container.Config{
37+
resp, err := cli.ContainerCreate(ctxdl, &container.Config{
3438
Image: imageCompile,
3539
Env: []string{
3640
"TEST_CASE_DIR=" + filepath.Join("/code-grader/testcases", gr.TestCaseName),
@@ -49,7 +53,7 @@ func CompileUserCode(ctx context.Context, gr types.GradeRequest) ([]byte, error)
4953
return nil, errors.Wrap(ErrInternalError, "cannot create container")
5054
}
5155

52-
hjresp, err := cli.ContainerAttach(ctx, resp.ID, dockertypes.ContainerAttachOptions{
56+
hjresp, err := cli.ContainerAttach(ctxdl, resp.ID, dockertypes.ContainerAttachOptions{
5357
Stdin: true,
5458
Stream: true,
5559
})
@@ -58,21 +62,21 @@ func CompileUserCode(ctx context.Context, gr types.GradeRequest) ([]byte, error)
5862
return nil, errors.Wrap(ErrInternalError, "cannot attach container")
5963
}
6064

61-
statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNextExit)
65+
statusCh, errCh := cli.ContainerWait(ctxdl, resp.ID, container.WaitConditionNextExit)
6266

63-
err = cli.ContainerStart(ctx, resp.ID, dockertypes.ContainerStartOptions{})
67+
err = cli.ContainerStart(ctxdl, resp.ID, dockertypes.ContainerStartOptions{})
6468
if err != nil {
6569
return nil, errors.Wrap(ErrInternalError, "cannot start container")
6670
}
6771

6872
defer func() {
69-
// err := cli.ContainerRemove(ctx, resp.ID, dockertypes.ContainerRemoveOptions{
70-
// Force: true,
71-
// })
72-
// if err != nil {
73-
// log.Fatal("cannot kill and remove container")
74-
// panic(err)
75-
// }
73+
err := cli.ContainerRemove(ctxdl, resp.ID, dockertypes.ContainerRemoveOptions{
74+
Force: true,
75+
})
76+
if err != nil {
77+
log.Panicln("cannot kill and remove container")
78+
panic(err)
79+
}
7680
}()
7781

7882
userCodeLength := len(gr.UserCode)
@@ -88,7 +92,7 @@ func CompileUserCode(ctx context.Context, gr types.GradeRequest) ([]byte, error)
8892
case status := <-statusCh:
8993
switch status.StatusCode {
9094
case 0:
91-
stdout, err := cli.ContainerLogs(ctx, resp.ID, dockertypes.ContainerLogsOptions{
95+
stdout, err := cli.ContainerLogs(ctxdl, resp.ID, dockertypes.ContainerLogsOptions{
9296
ShowStdout: true,
9397
ShowStderr: false,
9498
})
@@ -98,7 +102,7 @@ func CompileUserCode(ctx context.Context, gr types.GradeRequest) ([]byte, error)
98102
result, _ := io.ReadAll(stdout)
99103
return result, nil
100104
case 1:
101-
stderr, err := cli.ContainerLogs(ctx, resp.ID, dockertypes.ContainerLogsOptions{
105+
stderr, err := cli.ContainerLogs(ctxdl, resp.ID, dockertypes.ContainerLogsOptions{
102106
ShowStderr: true,
103107
ShowStdout: false,
104108
})

backend/cmd/const.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package cmd
2+
3+
import (
4+
"path"
5+
"runtime"
6+
)
7+
8+
func GetAppRoot() string {
9+
_, filename, _, _ := runtime.Caller(0)
10+
return path.Join(path.Dir(filename), "../../")
11+
}

backend/cmd/errors.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@ package cmd
22

33
import (
44
"errors"
5-
"os"
65
)
76

87
var (
98
ErrTimeLimitExceed = errors.New("time limit exceeds")
109
ErrMemoryLimitExceed = errors.New("memory limit exceeds")
1110
ErrInternalError = errors.New("internal error")
1211
ErrCompilationError = errors.New("compilation error")
13-
AppRoot = os.Getenv("APP_ROOT")
1412
)

backend/cmd/exec_user_code.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func ExecUserCode(ctx context.Context, gr types.GradeRequest) ([]byte, error) {
2222

2323
var testCase types.TestCaseOptions
2424

25-
testCaseJson, err := os.ReadFile(filepath.Join(AppRoot, "testcases", gr.TestCaseName, "testcase.json"))
25+
testCaseJson, err := os.ReadFile(filepath.Join(GetAppRoot(), "testcases", gr.TestCaseName, "testcase.json"))
2626
if err != nil {
2727
return nil, errors.Wrap(ErrInternalError, "cannot open testcase.json")
2828
}

backend/cmd/load_testcases.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
7+
"github.com/pkg/errors"
8+
)
9+
10+
// Load all existing test case names
11+
func LoadTestcases() ([]string, error) {
12+
13+
result := []string{}
14+
15+
dir := filepath.Join(GetAppRoot(), "testcases")
16+
ret, err := os.ReadDir(dir)
17+
18+
if err != nil {
19+
return nil, errors.Wrap(err, "cannot read testcase dir")
20+
}
21+
22+
for _, fileEntry := range ret {
23+
if fileEntry.IsDir() {
24+
result = append(result, fileEntry.Name())
25+
}
26+
}
27+
28+
return result, nil
29+
}

backend/cmd/load_testcases_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package cmd_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/markhuang1212/code-grader/backend/cmd"
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestLoadTestcases(t *testing.T) {
11+
ret, err := cmd.LoadTestcases()
12+
assert.Equal(t, err, nil)
13+
for _, v := range ret {
14+
if v == "example-1" {
15+
return
16+
}
17+
}
18+
t.Errorf("wrong result")
19+
}

0 commit comments

Comments
 (0)