-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathruncode_test.go
More file actions
116 lines (104 loc) · 3.49 KB
/
Copy pathruncode_test.go
File metadata and controls
116 lines (104 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package xshellz
import (
"context"
"errors"
"strings"
"testing"
)
func TestRunCodeWritesExecsAndCleansUp(t *testing.T) {
fake := &scriptedRunner{results: []scriptedResult{
{}, // WriteFile (cat > tmp)
{stdout: "42\n"}, // interpreter run
{}, // rm -f cleanup
}}
sbx := runningSandbox(fake)
res, err := sbx.RunCode(context.Background(), "python", "print(6*7)", nil)
if err != nil {
t.Fatalf("RunCode: %v", err)
}
if res.Stdout != "42\n" || res.ExitCode != 0 {
t.Errorf("res = %+v", res)
}
if len(fake.cmds) != 3 {
t.Fatalf("cmds = %v, want write+run+cleanup", fake.cmds)
}
if !strings.Contains(fake.cmds[0], "cat > '/tmp/xshellz-code-") || !strings.Contains(fake.cmds[0], ".py'") {
t.Errorf("write cmd = %q", fake.cmds[0])
}
if !strings.HasPrefix(fake.cmds[1], "python3 '/tmp/xshellz-code-") {
t.Errorf("run cmd = %q", fake.cmds[1])
}
if !strings.HasPrefix(fake.cmds[2], "rm -f '/tmp/xshellz-code-") {
t.Errorf("cleanup cmd = %q", fake.cmds[2])
}
}
func TestRunCodeNonZeroExitStillCleansUp(t *testing.T) {
fake := &scriptedRunner{results: []scriptedResult{
{},
{stderr: "Traceback (most recent call last):\n", exitCode: 1},
{},
}}
sbx := runningSandbox(fake)
res, err := sbx.RunCode(context.Background(), "python", "raise SystemExit(1)", nil)
if err != nil {
t.Fatalf("RunCode: %v (non-zero exit must be data, not an error)", err)
}
if res.ExitCode != 1 || !strings.Contains(res.Stderr, "Traceback") {
t.Errorf("res = %+v", res)
}
if len(fake.cmds) != 3 || !strings.HasPrefix(fake.cmds[2], "rm -f ") {
t.Errorf("cleanup missing after failing code: cmds = %v", fake.cmds)
}
}
func TestRunCodeInterpreterAndExtensionPerLanguage(t *testing.T) {
cases := map[string]struct{ interpreter, ext string }{
"python": {"python3", ".py"},
"node": {"node", ".js"},
"bash": {"bash", ".sh"},
"ruby": {"ruby", ".rb"},
"php": {"php", ".php"},
}
for lang, want := range cases {
fake := &scriptedRunner{results: []scriptedResult{{}, {}, {}}}
sbx := runningSandbox(fake)
if _, err := sbx.RunCode(context.Background(), lang, "code", nil); err != nil {
t.Fatalf("RunCode(%s): %v", lang, err)
}
if !strings.HasPrefix(fake.cmds[1], want.interpreter+" '") {
t.Errorf("%s: run cmd = %q, want %s", lang, fake.cmds[1], want.interpreter)
}
if !strings.Contains(fake.cmds[0], want.ext+"'") {
t.Errorf("%s: temp file extension missing in %q, want %s", lang, fake.cmds[0], want.ext)
}
}
}
func TestRunCodeUnknownLanguage(t *testing.T) {
sbx := runningSandbox(&scriptedRunner{})
_, err := sbx.RunCode(context.Background(), "cobol", "DISPLAY 'HI'.", nil)
if !errors.Is(err, ErrUnsupportedLanguage) {
t.Fatalf("err = %v, want ErrUnsupportedLanguage", err)
}
for _, lang := range SupportedLanguages() {
if !strings.Contains(err.Error(), lang) {
t.Errorf("error %q does not list supported language %q", err.Error(), lang)
}
}
}
func TestSupportedLanguagesSorted(t *testing.T) {
got := SupportedLanguages()
want := []string{"bash", "node", "php", "python", "ruby"}
if len(got) != len(want) {
t.Fatalf("SupportedLanguages() = %v", got)
}
for i := range want {
if got[i] != want[i] {
t.Fatalf("SupportedLanguages() = %v, want %v", got, want)
}
}
}
func TestRunCodeOnStoppedBoxFails(t *testing.T) {
sbx := &Sandbox{info: SandboxInfo{UUID: "u-1", Status: StatusStopped}}
if _, err := sbx.RunCode(context.Background(), "python", "print(1)", nil); !errors.Is(err, ErrNotRunning) {
t.Errorf("err = %v, want ErrNotRunning", err)
}
}