mirror of
https://github.com/QingdaoU/JudgeServer.git
synced 2024-12-28 21:31:43 +00:00
commit
e30664bb5e
19
client/go/README.md
Normal file
19
client/go/README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# JudgeServer client for Golang
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
Install:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
go get -d github.com/QingdaoU/JudgeServer/client/go
|
||||||
|
```
|
||||||
|
|
||||||
|
Import:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/QingdaoU/JudgeServer/client/go"
|
||||||
|
```
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
[examples](https://github.com/QingdaoU/JudgeServer/tree/master/client/go/examples)
|
184
client/go/client.go
Normal file
184
client/go/client.go
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
package judge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"io/ioutil"
|
||||||
|
"io"
|
||||||
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Data 成员的类型参考 https://github.com/QingdaoU/Judger/blob/b6414e7a6715eb013b1ffeb7cfb04626a3ff5b4e/src/runner.h#L73
|
||||||
|
type Data struct {
|
||||||
|
CpuTime int
|
||||||
|
Result int
|
||||||
|
Memory int64 // https://github.com/QingdaoU/Judger/blob/b6414e7a6715eb013b1ffeb7cfb04626a3ff5b4e/src/runner.h#L76
|
||||||
|
RealTime int
|
||||||
|
Signal int
|
||||||
|
Error int
|
||||||
|
ExitCode int
|
||||||
|
OutputMd5 string
|
||||||
|
Output interface{}
|
||||||
|
TestCase string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Resp struct {
|
||||||
|
RespData interface{} `json:"data"`
|
||||||
|
RespErr string `json:"err"`
|
||||||
|
err error `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (resp *Resp) Data() interface{} {
|
||||||
|
if resp == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return resp.RespData
|
||||||
|
}
|
||||||
|
|
||||||
|
func (resp *Resp) StringData() string {
|
||||||
|
if resp == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
str, _ := resp.RespData.(string)
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|
||||||
|
func (resp *Resp) SliceData() []*Data {
|
||||||
|
if resp == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
slice, _ := resp.RespData.([]interface{})
|
||||||
|
data := make([]*Data, 0, len(slice))
|
||||||
|
for _, s := range slice {
|
||||||
|
item, ok := s.(map[string]interface{})
|
||||||
|
if ok {
|
||||||
|
cpuTimeF64, _ := item["cpu_time"].(float64)
|
||||||
|
resultF64, _ := item["result"].(float64)
|
||||||
|
memoryF64, _ := item["memory"].(float64)
|
||||||
|
realTimeF64, _ := item["real_time"].(float64)
|
||||||
|
signalF64, _ := item["signal"].(float64)
|
||||||
|
errorF64, _ := item["error"].(float64)
|
||||||
|
exitCodeF64, _ := item["exit_code"].(float64)
|
||||||
|
outputMd5, _ := item["output_md5"].(string)
|
||||||
|
testCase, _ := item["test_case"].(string)
|
||||||
|
data = append(data, &Data{
|
||||||
|
CpuTime: int(cpuTimeF64),
|
||||||
|
Result: int(resultF64),
|
||||||
|
Memory: int64(memoryF64),
|
||||||
|
RealTime: int(realTimeF64),
|
||||||
|
Signal: int(signalF64),
|
||||||
|
Error: int(errorF64),
|
||||||
|
ExitCode: int(exitCodeF64),
|
||||||
|
OutputMd5: outputMd5,
|
||||||
|
Output: item["output"],
|
||||||
|
TestCase: testCase,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (resp *Resp) Err() error {
|
||||||
|
if resp == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return resp.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseResp(body []byte) (*Resp, error) {
|
||||||
|
resp := &Resp{}
|
||||||
|
err := json.Unmarshal(body, resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 有错误的响应了
|
||||||
|
if resp.RespErr != "" {
|
||||||
|
resp.err = fmt.Errorf("err: %s, data: %s", resp.RespErr, resp.RespData)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
opts *options
|
||||||
|
httpClient *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) request(method, path string, body io.Reader) (resp *Resp, err error) {
|
||||||
|
req, err := http.NewRequest("POST", c.opts.EndpointURL+"/"+path, body)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.Header.Set("X-Judge-Server-Token", c.opts.sha256Token)
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
httpResp, err := c.httpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b, err := ioutil.ReadAll(httpResp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
httpResp.Body.Close()
|
||||||
|
return parseResp(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) post(path string, body io.Reader) (resp *Resp, err error) {
|
||||||
|
return c.request("POST", path, body)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping Judge server
|
||||||
|
func (c *Client) Ping() (resp *Resp, err error) {
|
||||||
|
resp, err = c.post("ping", nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) CompileSpj(src, spjVersion string, spjCompileConfig *CompileConfig) (resp *Resp, err error) {
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"src": src,
|
||||||
|
"spj_version": spjVersion,
|
||||||
|
"spj_compile_config": spjCompileConfig,
|
||||||
|
}
|
||||||
|
b, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, err = c.post("compile_spj", bytes.NewReader(b))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(endpointURL, token string, timeout time.Duration) *Client {
|
||||||
|
return NewClient(
|
||||||
|
WithEndpointURL(endpointURL),
|
||||||
|
WithToken(token),
|
||||||
|
WithTimeout(timeout),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) SetOptions(options ...Option) {
|
||||||
|
originTimeout := c.opts.Timeout
|
||||||
|
for _, o := range options {
|
||||||
|
o(c.opts)
|
||||||
|
}
|
||||||
|
if c.opts.Timeout != originTimeout {
|
||||||
|
c.httpClient.Timeout = c.opts.Timeout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClient(options ...Option) *Client {
|
||||||
|
opts := DefaultOptions
|
||||||
|
for _, o := range options {
|
||||||
|
o(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Client{
|
||||||
|
opts: opts,
|
||||||
|
httpClient: &http.Client{
|
||||||
|
Timeout: opts.Timeout,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
56
client/go/client_test.go
Normal file
56
client/go/client_test.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package judge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var client *Client
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
// 创建一个client。 这句代码等价于 New("http://127.0.0.1:12358", "YOUR_TOKEN_HERE", 0)
|
||||||
|
client = NewClient(
|
||||||
|
WithEndpointURL("http://127.0.0.1:12358"),
|
||||||
|
WithToken("YOUR_TOKEN_HERE"),
|
||||||
|
WithTimeout(0),
|
||||||
|
)
|
||||||
|
m.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_Ping(t *testing.T) {
|
||||||
|
resp, err := client.Ping()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error. error: %+v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.Err() != nil {
|
||||||
|
t.Errorf("unexpected error. error: %+v", resp.Err())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.RespData == nil {
|
||||||
|
t.Error("resp.RespData unexpected nil")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClient_CompileSpj(t *testing.T) {
|
||||||
|
cSpjSrc := `
|
||||||
|
#include <stdio.h>
|
||||||
|
int main(){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
resp, err := client.CompileSpj(cSpjSrc, "2", CLangSPJCompile)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error. error: %+v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.Err() != nil {
|
||||||
|
t.Errorf("unexpected error. error: %+v", resp.Err())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.RespData == nil {
|
||||||
|
t.Error("resp.RespData unexpected nil")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
168
client/go/examples/example.go
Normal file
168
client/go/examples/example.go
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/QingdaoU/JudgeServer/client/go"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
cSrc = `
|
||||||
|
#include <stdio.h>
|
||||||
|
int main(){
|
||||||
|
int a, b;
|
||||||
|
scanf("%d%d", &a, &b);
|
||||||
|
printf("%d\n", a+b);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
cSPJSrc = `
|
||||||
|
#include <stdio.h>
|
||||||
|
int main(){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
cppSrc = `
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int a,b;
|
||||||
|
cin >> a >> b;
|
||||||
|
cout << a+b << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
javaSrc = `
|
||||||
|
import java.util.Scanner;
|
||||||
|
public class Main{
|
||||||
|
public static void main(String[] args){
|
||||||
|
Scanner in=new Scanner(System.in);
|
||||||
|
int a=in.nextInt();
|
||||||
|
int b=in.nextInt();
|
||||||
|
System.out.println(a + b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
py2Src = `
|
||||||
|
s = raw_input()
|
||||||
|
s1 = s.split(" ")
|
||||||
|
print int(s1[0]) + int(s1[1])
|
||||||
|
`
|
||||||
|
py3Src = `
|
||||||
|
s = input()
|
||||||
|
s1 = s.split(" ")
|
||||||
|
print(int(s1[0]) + int(s1[1]))
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// 创建一个client。 这句代码等价于
|
||||||
|
|
||||||
|
// 1.
|
||||||
|
//client := judge.NewClient(
|
||||||
|
// judge.WithEndpointURL("http://127.0.0.1:12358"),
|
||||||
|
// judge.WithToken("YOUR_TOKEN_HERE"),
|
||||||
|
// judge.WithTimeout(0),
|
||||||
|
//)
|
||||||
|
|
||||||
|
// 2.
|
||||||
|
// client := judge.New("http://127.0.0.1:12358", "YOUR_TOKEN_HERE", 0)
|
||||||
|
|
||||||
|
// 3.
|
||||||
|
client := judge.NewClient(judge.WithTimeout(0))
|
||||||
|
client.SetOptions(judge.WithEndpointURL("http://127.0.0.1:12358"), judge.WithToken("YOUR_TOKEN_HERE"))
|
||||||
|
|
||||||
|
fmt.Println("ping:")
|
||||||
|
resp, err := client.Ping()
|
||||||
|
if err != nil {
|
||||||
|
// 这个 err 是发生在 client 这边的错误。 例如json编码失败
|
||||||
|
fmt.Printf("ping client error. error is: %v.\n", err)
|
||||||
|
} else if resp.Err() != nil {
|
||||||
|
// 这个 resp.Err() 是 JudgeServer 响应的错误。 例如token错误 TokenVerificationFailed
|
||||||
|
fmt.Printf("ping server error. error is: %v.\n", resp.Err().Error())
|
||||||
|
} else {
|
||||||
|
fmt.Println(resp.Data())
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
fmt.Println("cpp_judge")
|
||||||
|
resp, _ = client.JudgeWithRequest(&judge.JudgeRequest{
|
||||||
|
Src: cppSrc,
|
||||||
|
LanguageConfig: judge.CPPLangConfig,
|
||||||
|
MaxCpuTime: 1000,
|
||||||
|
MaxMemory: 128 * 1024 * 1024,
|
||||||
|
TestCaseId: "normal",
|
||||||
|
})
|
||||||
|
printSliceData(resp.SliceData())
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
fmt.Println("java_judge")
|
||||||
|
resp, _ = client.JudgeWithRequest(&judge.JudgeRequest{
|
||||||
|
Src: javaSrc,
|
||||||
|
LanguageConfig: judge.JavaLangConfig,
|
||||||
|
MaxCpuTime: 1000,
|
||||||
|
MaxMemory: 256 * 1024 * 1024,
|
||||||
|
TestCaseId: "normal",
|
||||||
|
})
|
||||||
|
printSliceData(resp.SliceData())
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
fmt.Println("c_spj_judge")
|
||||||
|
resp, _ = client.JudgeWithRequest(&judge.JudgeRequest{
|
||||||
|
Src: cSrc,
|
||||||
|
LanguageConfig: judge.CLangConfig,
|
||||||
|
MaxCpuTime: 1000,
|
||||||
|
MaxMemory: 128 * 1024 * 1024,
|
||||||
|
TestCaseId: "spj",
|
||||||
|
SPJVersion: "3",
|
||||||
|
SPJConfig: judge.CLangSPJConfig,
|
||||||
|
SPJCompileConfig: judge.CLangSPJCompile,
|
||||||
|
SPJSrc: cSPJSrc,
|
||||||
|
})
|
||||||
|
printSliceData(resp.SliceData())
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
fmt.Println("py2_judge")
|
||||||
|
resp, _ = client.JudgeWithRequest(&judge.JudgeRequest{
|
||||||
|
Src: py2Src,
|
||||||
|
LanguageConfig: judge.PY2LangConfig,
|
||||||
|
MaxCpuTime: 1000,
|
||||||
|
MaxMemory: 128 * 1024 * 1024,
|
||||||
|
TestCaseId: "normal",
|
||||||
|
})
|
||||||
|
printSliceData(resp.SliceData())
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
fmt.Println("py3_judge")
|
||||||
|
resp, _ = client.JudgeWithRequest(&judge.JudgeRequest{
|
||||||
|
Src: py3Src,
|
||||||
|
LanguageConfig: judge.PY3LangConfig,
|
||||||
|
MaxCpuTime: 1000,
|
||||||
|
MaxMemory: 128 * 1024 * 1024,
|
||||||
|
TestCaseId: "normal",
|
||||||
|
})
|
||||||
|
printSliceData(resp.SliceData())
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
// CompileError example
|
||||||
|
fmt.Println("CompileError example")
|
||||||
|
resp, err = client.JudgeWithRequest(&judge.JudgeRequest{
|
||||||
|
Src: "this bad code",
|
||||||
|
LanguageConfig: judge.JavaLangConfig,
|
||||||
|
MaxCpuTime: 1000,
|
||||||
|
MaxMemory: 256 * 1024 * 1024,
|
||||||
|
TestCaseId: "normal",
|
||||||
|
})
|
||||||
|
// fmt.Println(resp.RespErr) // "CompileError"
|
||||||
|
fmt.Println(resp.StringData()) // 错误信息
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSliceData(slice []*judge.Data) {
|
||||||
|
fmt.Print("[\n")
|
||||||
|
for _, item := range slice {
|
||||||
|
fmt.Printf("\t%#v,\n", item)
|
||||||
|
}
|
||||||
|
fmt.Print("]\n")
|
||||||
|
}
|
46
client/go/judge.go
Normal file
46
client/go/judge.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package judge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
type JudgeRequest struct {
|
||||||
|
Src string `json:"src"`
|
||||||
|
LanguageConfig *LangConfig `json:"language_config"`
|
||||||
|
MaxCpuTime int64 `json:"max_cpu_time"`
|
||||||
|
MaxMemory int64 `json:"max_memory"`
|
||||||
|
TestCaseId string `json:"test_case_id"`
|
||||||
|
SPJVersion string `json:"spj_version"`
|
||||||
|
SPJConfig *SPJConfig `json:"spj_config"`
|
||||||
|
SPJCompileConfig *CompileConfig `json:"spj_compile_config"`
|
||||||
|
SPJSrc string `json:"spj_src"`
|
||||||
|
Output bool `json:"output"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 这个方法为了模仿 php 和 python client 不推荐使用
|
||||||
|
func (c *Client) Judge(src string, languageConfig *LangConfig, maxCpuTime time.Duration, maxMemory int64, testCaseId,
|
||||||
|
spjVersion string, spjConfig *SPJConfig, spjCompileConfig *CompileConfig, spjSrc string, output bool) (resp *Resp, err error) {
|
||||||
|
return c.JudgeWithRequest(&JudgeRequest{
|
||||||
|
Src: src,
|
||||||
|
LanguageConfig: languageConfig,
|
||||||
|
MaxCpuTime: int64(maxCpuTime),
|
||||||
|
MaxMemory: maxMemory,
|
||||||
|
TestCaseId: testCaseId,
|
||||||
|
SPJVersion: spjVersion,
|
||||||
|
SPJConfig: spjConfig,
|
||||||
|
SPJCompileConfig: spjCompileConfig,
|
||||||
|
SPJSrc: spjSrc,
|
||||||
|
Output: output,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) JudgeWithRequest(req *JudgeRequest) (resp *Resp, err error) {
|
||||||
|
b, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, err = c.post("judge", bytes.NewReader(b))
|
||||||
|
return
|
||||||
|
}
|
76
client/go/judge_test.go
Normal file
76
client/go/judge_test.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package judge
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestClient_JudgeWithRequest(t *testing.T) {
|
||||||
|
javaSrc := `
|
||||||
|
import java.util.Scanner;
|
||||||
|
public class Main{
|
||||||
|
public static void main(String[] args){
|
||||||
|
Scanner in=new Scanner(System.in);
|
||||||
|
int a=in.nextInt();
|
||||||
|
int b=in.nextInt();
|
||||||
|
System.out.println(a + b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
cSrc := `
|
||||||
|
#include <stdio.h>
|
||||||
|
int main(){
|
||||||
|
int a, b;
|
||||||
|
scanf("%d%d", &a, &b);
|
||||||
|
printf("%d\n", a+b);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
cSPJSrc := `
|
||||||
|
#include <stdio.h>
|
||||||
|
int main(){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
var tests = []struct {
|
||||||
|
JudgeRequest *JudgeRequest
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
JudgeRequest: &JudgeRequest{
|
||||||
|
Src: javaSrc,
|
||||||
|
LanguageConfig: JavaLangConfig,
|
||||||
|
MaxCpuTime: 1000,
|
||||||
|
MaxMemory: 256 * 1024 * 1024,
|
||||||
|
TestCaseId: "normal",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
JudgeRequest: &JudgeRequest{
|
||||||
|
Src: cSrc,
|
||||||
|
LanguageConfig: CLangConfig,
|
||||||
|
MaxCpuTime: 1000,
|
||||||
|
MaxMemory: 128 * 1024 * 1024,
|
||||||
|
TestCaseId: "spj",
|
||||||
|
SPJVersion: "3",
|
||||||
|
SPJConfig: CLangSPJConfig,
|
||||||
|
SPJCompileConfig: CLangSPJCompile,
|
||||||
|
SPJSrc: cSPJSrc,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
resp, err := client.JudgeWithRequest(test.JudgeRequest)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error. error: %+v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.Err() != nil {
|
||||||
|
t.Errorf("unexpected error. error: %+v", resp.Err())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.RespData == nil {
|
||||||
|
t.Error("resp.RespData unexpected nil")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
126
client/go/languages.go
Normal file
126
client/go/languages.go
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
package judge
|
||||||
|
|
||||||
|
type CompileConfig struct {
|
||||||
|
SrcName string `json:"src_name"`
|
||||||
|
ExeName string `json:"exe_name"`
|
||||||
|
MaxCpuTime int64 `json:"max_cpu_time"`
|
||||||
|
MaxRealTime int64 `json:"max_real_time"`
|
||||||
|
MaxMemory int64 `json:"max_memory"`
|
||||||
|
CompileCommand string `json:"compile_command"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var DefaultEnv = []string{"LANG=en_US.UTF-8", "LANGUAGE=en_US:en", "LC_ALL=en_US.UTF-8"}
|
||||||
|
|
||||||
|
type RunConfig struct {
|
||||||
|
Command string `json:"command"`
|
||||||
|
SeccompRule string `json:"seccomp_rule"`
|
||||||
|
Env []string `json:"env"`
|
||||||
|
MemoryLimitCheckOnly int `json:"memory_limit_check_only"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LangConfig struct {
|
||||||
|
CompileConfig CompileConfig `json:"compile"`
|
||||||
|
RunConfig RunConfig `json:"run"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SPJConfig struct {
|
||||||
|
ExeName string `json:"exe_name"`
|
||||||
|
Command string `json:"command"`
|
||||||
|
SeccompRule string `json:"seccomp_rule"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var CLangConfig = &LangConfig{
|
||||||
|
CompileConfig: CompileConfig{
|
||||||
|
SrcName: "main.c",
|
||||||
|
ExeName: "main",
|
||||||
|
MaxCpuTime: 3000,
|
||||||
|
MaxRealTime: 5000,
|
||||||
|
MaxMemory: 128 * 1024 * 1024,
|
||||||
|
CompileCommand: "/usr/bin/gcc -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c99 {src_path} -lm -o {exe_path}",
|
||||||
|
},
|
||||||
|
RunConfig: RunConfig{
|
||||||
|
Command: "{exe_path}",
|
||||||
|
SeccompRule: "c_cpp",
|
||||||
|
Env: DefaultEnv,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var CLangSPJCompile = &CompileConfig{
|
||||||
|
SrcName: "spj-{spj_version}.c",
|
||||||
|
ExeName: "spj-{spj_version}",
|
||||||
|
MaxCpuTime: 3000,
|
||||||
|
MaxRealTime: 5000,
|
||||||
|
MaxMemory: 1024 * 1024 * 1024,
|
||||||
|
CompileCommand: "/usr/bin/gcc -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c99 {src_path} -lm -o {exe_path}",
|
||||||
|
}
|
||||||
|
|
||||||
|
var CLangSPJConfig = &SPJConfig{
|
||||||
|
ExeName: "spj-{spj_version}",
|
||||||
|
Command: "{exe_path} {in_file_path} {user_out_file_path}",
|
||||||
|
SeccompRule: "c_cpp",
|
||||||
|
}
|
||||||
|
|
||||||
|
var CPPLangConfig = &LangConfig{
|
||||||
|
CompileConfig: CompileConfig{
|
||||||
|
SrcName: "main.cpp",
|
||||||
|
ExeName: "main",
|
||||||
|
MaxCpuTime: 3000,
|
||||||
|
MaxRealTime: 5000,
|
||||||
|
MaxMemory: 128 * 1024 * 1024,
|
||||||
|
CompileCommand: "/usr/bin/g++ -DONLINE_JUDGE -O2 -w -fmax-errors=3 -std=c++11 {src_path} -lm -o {exe_path}",
|
||||||
|
},
|
||||||
|
RunConfig: RunConfig{
|
||||||
|
Command: "{exe_path}",
|
||||||
|
SeccompRule: "c_cpp",
|
||||||
|
Env: DefaultEnv,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var JavaLangConfig = &LangConfig{
|
||||||
|
CompileConfig: CompileConfig{
|
||||||
|
SrcName: "Main.java",
|
||||||
|
ExeName: "Main",
|
||||||
|
MaxCpuTime: 3000,
|
||||||
|
MaxRealTime: 5000,
|
||||||
|
MaxMemory: -1,
|
||||||
|
CompileCommand: "/usr/bin/javac {src_path} -d {exe_dir} -encoding UTF8",
|
||||||
|
},
|
||||||
|
RunConfig: RunConfig{
|
||||||
|
Command: "/usr/bin/java -cp {exe_dir} -XX:MaxRAM={max_memory}k -Djava.security.manager -Dfile.encoding=UTF-8 -Djava.security.policy==/etc/java_policy -Djava.awt.headless=true Main",
|
||||||
|
SeccompRule: "",
|
||||||
|
Env: DefaultEnv,
|
||||||
|
MemoryLimitCheckOnly: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var PY2LangConfig = &LangConfig{
|
||||||
|
CompileConfig: CompileConfig{
|
||||||
|
SrcName: "solution.py",
|
||||||
|
ExeName: "solution.pyc",
|
||||||
|
MaxCpuTime: 3000,
|
||||||
|
MaxRealTime: 5000,
|
||||||
|
MaxMemory: 128 * 1024 * 1024,
|
||||||
|
CompileCommand: "/usr/bin/python -m py_compile {src_path}",
|
||||||
|
},
|
||||||
|
RunConfig: RunConfig{
|
||||||
|
Command: "/usr/bin/python {exe_path}",
|
||||||
|
SeccompRule: "general",
|
||||||
|
Env: DefaultEnv,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var PY3LangConfig = &LangConfig{
|
||||||
|
CompileConfig: CompileConfig{
|
||||||
|
SrcName: "solution.py",
|
||||||
|
ExeName: "__pycache__/solution.cpython-35.pyc",
|
||||||
|
MaxCpuTime: 3000,
|
||||||
|
MaxRealTime: 5000,
|
||||||
|
MaxMemory: 128 * 1024 * 1024,
|
||||||
|
CompileCommand: "/usr/bin/python3 -m py_compile {src_path}",
|
||||||
|
},
|
||||||
|
RunConfig: RunConfig{
|
||||||
|
Command: "/usr/bin/python3 {exe_path}",
|
||||||
|
SeccompRule: "general",
|
||||||
|
Env: append(DefaultEnv, "PYTHONIOENCODING=UTF-8"),
|
||||||
|
},
|
||||||
|
}
|
45
client/go/options.go
Normal file
45
client/go/options.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package judge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
type options struct {
|
||||||
|
// scheme://host:port .
|
||||||
|
EndpointURL string
|
||||||
|
Token string
|
||||||
|
sha256Token string
|
||||||
|
// 请求超时时间
|
||||||
|
// 如果 Timeout 为 0,那么意味着不会超时
|
||||||
|
Timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
var DefaultOptions = &options{
|
||||||
|
EndpointURL: "http://127.0.0.1:12358",
|
||||||
|
Token: "YOUR_TOKEN_HERE",
|
||||||
|
Timeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Option func(*options)
|
||||||
|
|
||||||
|
func WithEndpointURL(u string) Option {
|
||||||
|
return func(o *options) {
|
||||||
|
o.EndpointURL = u
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithToken(token string) Option {
|
||||||
|
return func(o *options) {
|
||||||
|
o.Token = token
|
||||||
|
sha256Token := sha256.Sum256([]byte(token))
|
||||||
|
o.sha256Token = hex.EncodeToString(sha256Token[:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithTimeout(timeout time.Duration) Option {
|
||||||
|
return func(o *options) {
|
||||||
|
o.Timeout = timeout
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user