Reviewed-on: #103 Co-authored-by: Boming Zhang <bomingzh@sjtu.edu.cn> Co-committed-by: Boming Zhang <bomingzh@sjtu.edu.cn>
122 lines
4.2 KiB
Go
122 lines
4.2 KiB
Go
package sandbox
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/criyle/go-judge/pb"
|
|
"github.com/joint-online-judge/JOJ3/internal/stage"
|
|
)
|
|
|
|
func TestConvertPBFileVariants(t *testing.T) {
|
|
content, fileID, name := "content", "cached", "output"
|
|
max := int64(123)
|
|
tests := []struct {
|
|
name string
|
|
file stage.CmdFile
|
|
check func(*pb.Request_File) bool
|
|
}{
|
|
{"content", stage.CmdFile{Content: &content}, func(f *pb.Request_File) bool { return string(f.GetMemory().GetContent()) == content }},
|
|
{"cached", stage.CmdFile{FileID: &fileID}, func(f *pb.Request_File) bool { return f.GetCached().GetFileID() == fileID }},
|
|
{"pipe", stage.CmdFile{Name: &name, Max: &max, Pipe: true}, func(f *pb.Request_File) bool {
|
|
return f.GetPipe().GetName() == name && f.GetPipe().GetMax() == max && f.GetPipe().GetPipe()
|
|
}},
|
|
{"stream-in", stage.CmdFile{StreamIn: true}, func(f *pb.Request_File) bool { return f.GetStreamIn() != nil }},
|
|
{"stream-out", stage.CmdFile{StreamOut: true}, func(f *pb.Request_File) bool { return f.GetStreamOut() != nil }},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := convertPBFile(tt.file)
|
|
if err != nil || got == nil || !tt.check(got) {
|
|
t.Fatalf("convertPBFile() = %v, %v", got, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConvertCopyOutAndResult(t *testing.T) {
|
|
copyOut := convertPBCopyOut([]string{"required", "optional?"})
|
|
if len(copyOut) != 2 || copyOut[0].GetOptional() || !copyOut[1].GetOptional() || copyOut[1].GetName() != "optional" {
|
|
t.Fatalf("convertPBCopyOut() = %+v", copyOut)
|
|
}
|
|
fileError := &pb.Response_FileError{}
|
|
fileError.SetName("input")
|
|
fileError.SetType(pb.Response_FileError_ErrorType(1))
|
|
fileError.SetMessage("bad file")
|
|
response := &pb.Response_Result{}
|
|
response.SetStatus(pb.Response_Result_StatusType(stage.StatusAccepted))
|
|
response.SetFiles(map[string][]byte{"stdout": []byte("ok")})
|
|
response.SetFileIDs(map[string]string{"bin": "id"})
|
|
response.SetFileError([]*pb.Response_FileError{fileError})
|
|
got := convertPBResult([]*pb.Response_Result{response})
|
|
if len(got) != 1 || got[0].Files["stdout"] != "ok" || got[0].FileIDs["bin"] != "id" ||
|
|
len(got[0].FileError) != 1 || got[0].FileError[0].Message != "bad file" {
|
|
t.Fatalf("convertPBResult() = %+v", got)
|
|
}
|
|
}
|
|
|
|
func TestConvertPBCmdReturnsSourceReadError(t *testing.T) {
|
|
missing := t.TempDir() + "/missing"
|
|
_, err := convertPBCmd([]stage.Cmd{{
|
|
Args: []string{"true"},
|
|
CopyIn: map[string]stage.CmdFile{
|
|
"input": {Src: &missing},
|
|
},
|
|
}})
|
|
if err == nil || !strings.Contains(err.Error(), "read source file") {
|
|
t.Fatalf("convertPBCmd() error = %v, want source read error", err)
|
|
}
|
|
}
|
|
|
|
func TestConvertPBCmdReturnsStandardFileReadError(t *testing.T) {
|
|
missing := t.TempDir() + "/missing"
|
|
_, err := convertPBCmd([]stage.Cmd{{
|
|
Args: []string{"true"},
|
|
Stdin: &stage.CmdFile{Src: &missing},
|
|
}})
|
|
if err == nil || !strings.Contains(err.Error(), "standard file") ||
|
|
!strings.Contains(err.Error(), "read source file") {
|
|
t.Fatalf("convertPBCmd() error = %v, want standard source read error", err)
|
|
}
|
|
}
|
|
|
|
func TestConvertPBCmdReturnsCopyInDirectoryWalkError(t *testing.T) {
|
|
missing := t.TempDir() + "/missing"
|
|
_, err := convertPBCmd([]stage.Cmd{{
|
|
Args: []string{"true"},
|
|
CopyInDir: missing,
|
|
}})
|
|
if err == nil || !strings.Contains(err.Error(), "walk") {
|
|
t.Fatalf("convertPBCmd() error = %v, want directory walk error", err)
|
|
}
|
|
}
|
|
|
|
func TestConvertPBCmdPreservesFilesAcrossMultipleSCMMaxFDBatches(t *testing.T) {
|
|
// 1001 is large enough to require several descriptor batches while keeping
|
|
// the fixture cheap to create and the protobuf request small.
|
|
const fileCount = 1001
|
|
dir := t.TempDir()
|
|
for i := range fileCount {
|
|
path := filepath.Join(dir, fmt.Sprintf("file-%03d", i))
|
|
if err := os.WriteFile(path, []byte("content"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
cmds, err := convertPBCmd([]stage.Cmd{{
|
|
Args: []string{"true"},
|
|
CopyIn: make(map[string]stage.CmdFile),
|
|
CopyInDir: dir,
|
|
}})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(cmds) != 1 || len(cmds[0].GetCopyIn()) != fileCount {
|
|
t.Fatalf("converted %d commands with %d files, want 1 command with %d files",
|
|
len(cmds), len(cmds[0].GetCopyIn()), fileCount)
|
|
}
|
|
}
|