Esempio n. 1
0
func NewContext(reader io.Reader) (*Context, error) {
	ctx, err := common.NewContextFromReader(reader)
	if err != nil {
		return nil, err
	}
	var context = &Context{
		Context:         *ctx,
		QueueManager:    NewQueueManager(ctx.Config.Grader.ChannelLength),
		InflightMonitor: NewInflightMonitor(),
		InputManager:    common.NewInputManager(ctx),
	}

	return context, nil
}
Esempio n. 2
0
func main() {
	flag.Parse()

	config := common.DefaultConfig()

	if *runtimePath != "" {
		config.Runner.PreserveFiles = true
	} else {
		var err error
		if *runtimePath, err = ioutil.TempDir("", "runner"); err != nil {
			panic(err)
		}
		defer os.RemoveAll(*runtimePath)
	}
	config.Logging.File = "stderr"
	if *verbose {
		config.Logging.Level = "debug"
	}
	config.Runner.RuntimePath = *runtimePath
	config.Tracing.Enabled = false

	ctx, err := common.NewContext(&config)
	if err != nil {
		panic(err)
	}
	inputManager := common.NewInputManager(ctx)
	results, err := runner.RunHostBenchmark(
		ctx,
		inputManager,
		&minijail,
		&ioLock,
	)
	if err != nil {
		panic(err)
	}
	encoded, err := json.MarshalIndent(results, "", "  ")
	if err != nil {
		panic(err)
	}

	os.Stdout.Write(encoded)
}
Esempio n. 3
0
func TestPreloadInputs(t *testing.T) {
	ctx, err := newRunnerContext()
	if err != nil {
		t.Fatalf("RunnerContext creation failed with %q", err)
	}
	defer ctx.Close()
	defer os.RemoveAll(ctx.Config.Runner.RuntimePath)

	inputManager := common.NewInputManager(ctx)

	inputPath := path.Join(ctx.Config.Runner.RuntimePath, "input")
	// Setting up files.
	dirs := []string{
		"00/00000000000000000000000000000000000000",
		"00/00000000000000000000000000000000000001",
		"00/00000000000000000000000000000000000002",
		"00/00000000000000000000000000000000000003",
		"00/00000000000000000000000000000000000004",
		"00/00000000000000000000000000000000000005",
		"4b/ba61b5499a7a511eb515594f3293a8741516ad/in",
		"4b/ba61b5499a7a511eb515594f3293a8741516ad/out",
	}
	for _, d := range dirs {
		if err := os.MkdirAll(path.Join(inputPath, d), 0755); err != nil {
			t.Fatalf("Failed to create %q: %q", d, err)
		}
	}
	files := []struct {
		filename, contents string
	}{
		{
			"00/00000000000000000000000000000000000000/settings.json",
			"{}",
		},
		{
			"00/00000000000000000000000000000000000000.sha1",
			"0000000000000000000000000000000000000000 *00000000000000000000000000000000000000/settings.json",
		},
		{
			"00/00000000000000000000000000000000000001/settings.json",
			"{}",
		},
		{
			"00/00000000000000000000000000000000000002.sha1",
			"0000000000000000000000000000000000000000 *settings.json",
		},
		{
			"00/00000000000000000000000000000000000003.sha1",
			"invalid sha1 file",
		},
		{
			"00/00000000000000000000000000000000000004.sha1",
			"",
		},
		{
			"00/00000000000000000000000000000000000005.sha1",
			"",
		},
		{
			"00/00000000000000000000000000000000000005/settings.json",
			"invalid json",
		},
		{
			"4b/ba61b5499a7a511eb515594f3293a8741516ad/in/0.in",
			"1 2",
		},
		{
			"4b/ba61b5499a7a511eb515594f3293a8741516ad/out/0.out",
			"3",
		},
		{
			"4b/ba61b5499a7a511eb515594f3293a8741516ad/settings.json",
			`{
  "Cases": [
		{"Cases": [{"Name": "0", "Weight": 1.0}], "Name": "0", "Weight": 1.0}
  ], 
  "Limits": {
    "ExtraWallTime": 0, 
    "MemoryLimit": 67108864, 
    "OutputLimit": 16384, 
    "OverallWallTimeLimit": 60000, 
    "TimeLimit": 3000, 
    "ValidatorTimeLimit": 3000
  }, 
  "Slow": false, 
	"Validator": {"Name": "token-numeric"}
}`,
		},
		{
			"4b/ba61b5499a7a511eb515594f3293a8741516ad.sha1",
			`0849b07a45865a148f85f3ef389d6b6fa8e2d1fb *ba61b5499a7a511eb515594f3293a8741516ad/settings.json
			3c28d037e32cd30eefd8183a83153083cced6cb7 *ba61b5499a7a511eb515594f3293a8741516ad/in/0.in
			77de68daecd823babbb58edb1c8e14d7106e83bb *ba61b5499a7a511eb515594f3293a8741516ad/out/0.out`,
		},
	}
	for _, ft := range files {
		if err := ioutil.WriteFile(
			path.Join(inputPath, ft.filename),
			[]byte(ft.contents),
			0644,
		); err != nil {
			t.Fatalf("Failed to write file: %q", err)
		}
	}
	inputManager.PreloadInputs(
		inputPath,
		NewRunnerCachedInputFactory(inputPath),
		&sync.Mutex{},
	)

	hashentries := []struct {
		hash  string
		valid bool
	}{
		{"0000000000000000000000000000000000000000", false},
		{"0000000000000000000000000000000000000001", false},
		{"0000000000000000000000000000000000000002", false},
		{"0000000000000000000000000000000000000003", false},
		{"0000000000000000000000000000000000000004", false},
		{"4bba61b5499a7a511eb515594f3293a8741516ad", true},
	}
	for _, het := range hashentries {
		input, err := inputManager.Get(het.hash)
		if input != nil {
			defer input.Release(input)
		}
		if het.valid {
			if err != nil {
				t.Errorf("InputManager.Get(%q) == %q, want nil", het.hash, err)
			}
		} else {
			if err == nil {
				t.Errorf("InputManager.Get(%q) == %q, want !nil", het.hash, err)
			}
		}
	}
}
Esempio n. 4
0
func TestInputFactory(t *testing.T) {
	ctx, err := newRunnerContext()
	if err != nil {
		t.Fatalf("RunnerContext creation failed with %q", err)
	}
	defer ctx.Close()
	defer os.RemoveAll(ctx.Config.Runner.RuntimePath)

	type httpentry struct {
		content []byte
		mime    string
		headers map[string]string
	}
	httpentries := map[string]httpentry{
		"/input/4bba61b5499a7a511eb515594f3293a8741516ad/": httpentry{
			mustDecode(
				`H4sIAFBMXVYAA+2WzU+DMBTAd93+CsJZWUspEK/Gmx+HLXowHppZZx0UA2VqFv53X1HYXDKXmDCi
				vt+B0r6Pvva1D5QeD7qGABHntqURJ5ttw9d3ShllA4d3HhlQFkbkjjNYinkutNmpt0/+S1F6TDyl
				O53DJjUMgm/yz7bzH0WQf9JpVJ/88/xTx+87BKRHstJ0/gH4Qf3nNMD6fwhs/okHzw7n2F//6Vb+
				fYb1/zCwvgNAeqWQxig9L7ynIuvqL3Df/Q/hZ5/6oR/5Aec+1ALKOOF4/w/BauQ47qkoZOGeOLej
				4XC17q3cS5FKeHOJe+S4N1LNHw10qUeqOxjYLQWnoGBdn6tUGevNTgT9s1eTixuRJFNVG5NaDQQX
				Ms3yt1odhsOIkjgOg0Z6VZrn0jRSGrJ4LVrKHPw1PlsP9mQ1OhMjZovWmgQxj8JWuGnFNoyuRaLu
				hcnybQUQVx+rmyTZCww+iKSQMDJc29gVtxtksoXUx7pMZa5mdrOmWQJB61m9Ax5ch2pUjfo+CgiC
				IAiCIAiCIAiCIAiCIAiC/BHeAU4V1PQAKAAA`,
			),
			"application/x-gzip",
			map[string]string{
				"Content-Sha1":                "a32f0f018441df71efc8d1c6a55391354a8d4897",
				"X-Content-Uncompressed-Size": "20",
			},
		},
		"/input/0000000000000000000000000000000000000001/": httpentry{
			[]byte("invalid .tar.gz"),
			"application/x-gzip",
			map[string]string{
				"Content-Sha1":                "da39a3ee5e6b4b0d3255bfef95601890afd80709",
				"X-Content-Uncompressed-Size": "20",
			},
		},
		"/input/0000000000000000000000000000000000000002/": httpentry{
			mustDecode(
				`H4sIAFBMXVYAA+2WzU+DMBTAd93+CsJZWUspEK/Gmx+HLXowHppZZx0UA2VqFv53X1HYXDKXmDCi
				vt+B0r6Pvva1D5QeD7qGABHntqURJ5ttw9d3ShllA4d3HhlQFkbkjjNYinkutNmpt0/+S1F6TDyl
				O53DJjUMgm/yz7bzH0WQf9JpVJ/88/xTx+87BKRHstJ0/gH4Qf3nNMD6fwhs/okHzw7n2F//6Vb+
				fYb1/zCwvgNAeqWQxig9L7ynIuvqL3Df/Q/hZ5/6oR/5Aec+1ALKOOF4/w/BauQ47qkoZOGeOLej
				4XC17q3cS5FKeHOJe+S4N1LNHw10qUeqOxjYLQWnoGBdn6tUGevNTgT9s1eTixuRJFNVG5NaDQQX
				Ms3yt1odhsOIkjgOg0Z6VZrn0jRSGrJ4LVrKHPw1PlsP9mQ1OhMjZovWmgQxj8JWuGnFNoyuRaLu
				hcnybQUQVx+rmyTZCww+iKSQMDJc29gVtxtksoXUx7pMZa5mdrOmWQJB61m9Ax5ch2pUjfo+CgiC
				IAiCIAiCIAiCIAiCIAiC/BHeAU4V1PQAKAAA`,
			),
			"application/x-gzip",
			map[string]string{
				"Content-Sha1":                "Invalid SHA1 hash",
				"X-Content-Uncompressed-Size": "20",
			},
		},
		"/input/0000000000000000000000000000000000000003/": httpentry{
			mustDecode(
				`H4sIAFBMXVYAA+2WzU+DMBTAd93+CsJZWUspEK/Gmx+HLXowHppZZx0UA2VqFv53X1HYXDKXmDCi
				vt+B0r6Pvva1D5QeD7qGABHntqURJ5ttw9d3ShllA4d3HhlQFkbkjjNYinkutNmpt0/+S1F6TDyl
				O53DJjUMgm/yz7bzH0WQf9JpVJ/88/xTx+87BKRHstJ0/gH4Qf3nNMD6fwhs/okHzw7n2F//6Vb+
				fYb1/zCwvgNAeqWQxig9L7ynIuvqL3Df/Q/hZ5/6oR/5Aec+1ALKOOF4/w/BauQ47qkoZOGeOLej
				4XC17q3cS5FKeHOJe+S4N1LNHw10qUeqOxjYLQWnoGBdn6tUGevNTgT9s1eTixuRJFNVG5NaDQQX
				Ms3yt1odhsOIkjgOg0Z6VZrn0jRSGrJ4LVrKHPw1PlsP9mQ1OhMjZovWmgQxj8JWuGnFNoyuRaLu
				hcnybQUQVx+rmyTZCww+iKSQMDJc29gVtxtksoXUx7pMZa5mdrOmWQJB61m9Ax5ch2pUjfo+CgiC
				IAiCIAiCIAiCIAiCIAiC/BHeAU4V1PQAKAAA`,
			),
			"application/x-gzip",
			map[string]string{
				"Content-Sha1":                "a32f0f018441df71efc8d1c6a55391354a8d4897",
				"X-Content-Uncompressed-Size": "Invalid length",
			},
		},
		"/input/0000000000000000000000000000000000000004/": httpentry{
			mustDecode("H4sIAJctXVYAA8vMK0vMyUxRKEksUjAYKMAFAMWXZ/uGAAAA"),
			"application/x-gzip",
			map[string]string{},
		},
	}
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		entry, ok := httpentries[r.RequestURI]
		if !ok {
			w.WriteHeader(http.StatusNotFound)
			return
		}
		for k, v := range entry.headers {
			w.Header().Add(k, v)
		}
		w.Write(entry.content)
	}))
	defer ts.Close()
	ctx.Config.Runner.GraderURL = ts.URL

	inputManager := common.NewInputManager(ctx)

	hashentries := []struct {
		hash  string
		valid bool
	}{
		{"0000000000000000000000000000000000000000", false},
		{"0000000000000000000000000000000000000001", false},
		{"0000000000000000000000000000000000000002", false},
		{"0000000000000000000000000000000000000003", false},
		{"0000000000000000000000000000000000000004", false},
		{"4bba61b5499a7a511eb515594f3293a8741516ad", true},
	}
	factory := NewRunnerInputFactory(http.DefaultClient, &ctx.Config)
	for _, het := range hashentries {
		input, err := inputManager.Add(het.hash, factory)
		if input != nil {
			defer input.Release(input)
		}
		if het.valid {
			if err != nil {
				t.Errorf("Input creation failed with %q", err)
			}
		} else {
			if err == nil {
				t.Errorf("Input creation succeeded, but was expected to fail")
			}
		}
	}
}
Esempio n. 5
0
func TestLibinteractive(t *testing.T) {
	minijail := &MinijailSandbox{}
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}
	if !minijail.Supported() {
		t.Skip("minijail sandbox not supported")
	}
	ctx, err := newRunnerContext()
	if err != nil {
		t.Fatalf("RunnerContext creation failed with %q", err)
	}
	defer ctx.Close()
	if !ctx.Config.Runner.PreserveFiles {
		defer os.RemoveAll(ctx.Config.Runner.RuntimePath)
	}

	inputManager := common.NewInputManager(ctx)
	AplusB, err := common.NewLiteralInputFactory(
		&common.LiteralInput{
			Cases: map[string]common.LiteralCaseSettings{
				"0": {Input: "1 2", ExpectedOutput: "3"},
				"1": {Input: "2 3", ExpectedOutput: "5"},
			},
			Validator: &common.LiteralValidatorSettings{
				Name: "token-numeric",
			},
			Interactive: &common.LiteralInteractiveSettings{
				IDLSource: `
					interface Main {};
					interface AplusB {
						int sum(int a, int b);
					};
					interface Identity {
						int identity(int x);
					};
				`,
				MainSource: `
					#include "AplusB.h"
					#include <iostream>
					using namespace std;
					int main() {
						int A, B;
						cin >> A >> B;
						cout << identity(sum(identity(A), identity(B))) << endl;
					}
				`,
				ModuleName: "AplusB",
				ParentLang: "cpp",
			},
		},
		ctx.Config.Runner.RuntimePath,
	)
	if err != nil {
		t.Fatalf("Failed to create Input: %q", err)
	}
	inputManager.Add(AplusB.Hash(), AplusB)

	input, err := inputManager.Get(AplusB.Hash())
	if err != nil {
		t.Fatalf("Failed to open problem: %q", err)
	}

	runtests := []runnerTestCase{
		{
			"cpp",
			`
				#include <iostream>
				using namespace std;
				int main(int argc, char* argv[]) {
					int A, B;
					cin >> A >> B;
					cerr << argv[1] << endl;
					cout << A + B << endl;
				}
			`,
			"CE",
			0.0,
			expectedResult{
				"",
				`  File "test.py", line 1
	    if
		     ^
				 SyntaxError: invalid syntax`,
				&RunMetadata{ExitStatus: 1, Verdict: "RTE"},
			},
			map[string]expectedResult{},
		},
		{
			"cpp11",
			`
				#include "AplusB.h"
				int sum(int A, int B) {
					return -1;
				}
				int identity(int x) {
					return -1;
				}
			`,
			"WA",
			0.0,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"-1", "", &RunMetadata{Verdict: "OK"}},
				"1": {"-1", "", &RunMetadata{Verdict: "OK"}},
			},
		},
		{
			"cpp",
			`
				#include "AplusB.h"
				int sum(int A, int B) {
					return A + B;
				}
				int identity(int x) {
					return x;
				}
			`,
			"AC",
			1.0,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"3", "", &RunMetadata{Verdict: "OK"}},
				"1": {"5", "", &RunMetadata{Verdict: "OK"}},
			},
		},
		{
			"java",
			`
				class AplusB {
					public static int sum(int A, int B) {
						return A + B;
					}
				}
				class Identity {
					public static int identity(int x) {
						return x;
					}
				}
			`,
			"AC",
			1.0,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"3", "", &RunMetadata{Verdict: "OK"}},
				"1": {"5", "", &RunMetadata{Verdict: "OK"}},
			},
		},
		{
			"py",
			"def sum(A, B):\n  return A + B\ndef identity(x):\n  return x",
			"AC",
			1.0,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"3", "", &RunMetadata{Verdict: "OK"}},
				"1": {"5", "", &RunMetadata{Verdict: "OK"}},
			},
		},
	}
	for idx, rte := range runtests {
		results, err := Grade(
			ctx,
			&bytes.Buffer{},
			&common.Run{
				AttemptID: uint64(idx),
				Language:  rte.language,
				InputHash: input.Hash(),
				Source:    rte.source,
				MaxScore:  1.0,
			},
			input,
			minijail,
		)
		if err != nil {
			t.Errorf("Failed to run %v: %q", rte, err)
			continue
		}
		if results.Verdict != rte.expectedVerdict {
			t.Errorf(
				"results.Verdict = %q, expected %q",
				results.Verdict,
				rte.expectedVerdict,
			)
		}
		if results.Score != rte.expectedScore {
			t.Errorf(
				"results.Score = %v, expected %v",
				results.Score,
				rte.expectedScore,
			)
		}
	}
}
Esempio n. 6
0
func runGraderTests(t *testing.T, wrapper sandboxWrapper) {
	ctx, err := newRunnerContext()
	if err != nil {
		t.Fatalf("RunnerContext creation failed with %q", err)
	}
	defer ctx.Close()
	if !ctx.Config.Runner.PreserveFiles {
		defer os.RemoveAll(ctx.Config.Runner.RuntimePath)
	}

	inputManager := common.NewInputManager(ctx)
	AplusB, err := common.NewLiteralInputFactory(
		&common.LiteralInput{
			Cases: map[string]common.LiteralCaseSettings{
				"0": {Input: "1 2", ExpectedOutput: "3"},
				"1": {Input: "2 3", ExpectedOutput: "5"},
			},
			Validator: &common.LiteralValidatorSettings{
				Name: "token-numeric",
			},
		},
		ctx.Config.Runner.RuntimePath,
	)
	if err != nil {
		t.Fatalf("Failed to create Input: %q", err)
	}
	inputManager.Add(AplusB.Hash(), AplusB)

	input, err := inputManager.Get(AplusB.Hash())
	if err != nil {
		t.Fatalf("Failed to open problem: %q", err)
	}

	runtests := []runnerTestCase{
		{
			"py",
			"print sum(map(int, raw_input().strip().split()))",
			"AC",
			1.0,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"3", "", &RunMetadata{Verdict: "OK"}},
				"1": {"5", "", &RunMetadata{Verdict: "OK"}},
			},
		},
		{
			"py",
			"print 3",
			"PA",
			0.5,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"3", "", &RunMetadata{Verdict: "OK"}},
				"1": {"3", "", &RunMetadata{Verdict: "OK"}},
			},
		},
		{
			"py",
			"print 2",
			"WA",
			0.0,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"2", "", &RunMetadata{Verdict: "OK"}},
				"1": {"2", "", &RunMetadata{Verdict: "OK"}},
			},
		},
		{
			"py",
			"if",
			"CE",
			0.0,
			expectedResult{
				"",
				`  File "test.py", line 1
	    if
		     ^
				 SyntaxError: invalid syntax`,
				&RunMetadata{ExitStatus: 1, Verdict: "RTE"},
			},
			map[string]expectedResult{},
		},
		{
			"c",
			"#include <stdio.h>\nint main() { printf(\"3\\n\"); }",
			"PA",
			0.5,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"3", "", &RunMetadata{Verdict: "OK"}},
				"1": {"3", "", &RunMetadata{Verdict: "OK"}},
			},
		},
		{
			"cpp",
			"#include <iostream>\nint main() { std::cout << \"3\\n\"; }",
			"PA",
			0.5,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"3", "", &RunMetadata{Verdict: "OK"}},
				"1": {"3", "", &RunMetadata{Verdict: "OK"}},
			},
		},
		{
			"rb",
			"puts 3",
			"PA",
			0.5,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"3", "", &RunMetadata{Verdict: "OK"}},
				"1": {"3", "", &RunMetadata{Verdict: "OK"}},
			},
		},
		{
			"hs",
			"main = putStrLn \"3\"",
			"PA",
			0.5,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"3", "", &RunMetadata{Verdict: "OK"}},
				"1": {"3", "", &RunMetadata{Verdict: "OK"}},
			},
		},
		{
			"pas",
			`program Main;
			begin
				writeln ('3');
			end.`,
			"PA",
			0.5,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"3", "", &RunMetadata{Verdict: "OK"}},
				"1": {"3", "", &RunMetadata{Verdict: "OK"}},
			},
		},
		{
			"java",
			`class Main {
				public static void main(String[] args) {
					System.out.println('3');
				}
			}`,
			"PA",
			0.5,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"3", "", &RunMetadata{Verdict: "OK"}},
				"1": {"3", "", &RunMetadata{Verdict: "OK"}},
			},
		},
		{
			"cat",
			"data:application/zip;base64,UEsDBAoAAAAAAOWiUUjRnmdVAgAAAAIAAAAFABwAMC" +
				"5vdXRVVAkAAy1HxVYtR8VWdXgLAAEE6AMAAAToAwAAMwpQSwMECgAAAAAA56JRSFc5PQ" +
				"MCAAAAAgAAAAUAHAAxLm91dFVUCQADMUfFVjFHxVZ1eAsAAQToAwAABOgDAAA1ClBLAQ" +
				"IeAwoAAAAAAOWiUUjRnmdVAgAAAAIAAAAFABgAAAAAAAEAAAC0gQAAAAAwLm91dFVUBQ" +
				"ADLUfFVnV4CwABBOgDAAAE6AMAAFBLAQIeAwoAAAAAAOeiUUhXOT0DAgAAAAIAAAAFAB" +
				"gAAAAAAAEAAAC0gUEAAAAxLm91dFVUBQADMUfFVnV4CwABBOgDAAAE6AMAAFBLBQYAAA" +
				"AAAgACAJYAAACCAAAAAAA=",
			"AC",
			1.0,
			expectedResult{"", "", &RunMetadata{Verdict: "OK"}},
			map[string]expectedResult{
				"0": {"3", "", &RunMetadata{Verdict: "OK"}},
				"1": {"5", "", &RunMetadata{Verdict: "OK"}},
			},
		},
	}
	for idx, rte := range runtests {
		results, err := Grade(
			ctx,
			&bytes.Buffer{},
			&common.Run{
				AttemptID: uint64(idx),
				Language:  rte.language,
				InputHash: input.Hash(),
				Source:    rte.source,
				MaxScore:  1.0,
			},
			input,
			wrapper.sandbox(&rte),
		)
		if err != nil {
			t.Errorf("Failed to run %v: %q", rte, err)
			continue
		}
		if results.Verdict != rte.expectedVerdict {
			t.Errorf(
				"results.Verdict = %q, expected %q, test %v",
				results.Verdict,
				rte.expectedVerdict,
				idx,
			)
		}
		if results.Score != rte.expectedScore {
			t.Errorf(
				"results.Score = %v, expected %v",
				results.Score,
				rte.expectedScore,
			)
		}
	}
}
Esempio n. 7
0
func main() {
	rand.Seed(time.Now().UTC().UnixNano())
	flag.Parse()

	if err := loadContext(); err != nil {
		panic(err)
	}

	ctx := globalContext.Load().(*common.Context)
	expvar.Publish("config", &globalContext.Load().(*common.Context).Config)
	inputManager = common.NewInputManager(ctx)
	inputPath := path.Join(ctx.Config.Runner.RuntimePath, "input")
	go inputManager.PreloadInputs(
		inputPath,
		runner.NewRunnerCachedInputFactory(inputPath),
		&ioLock,
	)
	transport := &http.Transport{
		Dial: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
		}).Dial,
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
	}
	if !*insecure {
		cert, err := ioutil.ReadFile(ctx.Config.TLS.CertFile)
		if err != nil {
			panic(err)
		}
		certPool := x509.NewCertPool()
		certPool.AppendCertsFromPEM(cert)
		keyPair, err := tls.LoadX509KeyPair(
			ctx.Config.TLS.CertFile,
			ctx.Config.TLS.KeyFile,
		)
		transport.TLSClientConfig = &tls.Config{
			Certificates: []tls.Certificate{keyPair},
			RootCAs:      certPool,
			ClientAuth:   tls.RequireAndVerifyClientCert,
		}
		if err != nil {
			panic(err)
		}
		if err := http2.ConfigureTransport(transport); err != nil {
			panic(err)
		}
	}

	client := &http.Client{Transport: transport}

	baseURL, err := url.Parse(ctx.Config.Runner.GraderURL)
	if err != nil {
		panic(err)
	}

	setupMetrics(ctx)
	ctx.Log.Info("omegaUp runner ready to serve")

	go func() {
		for {
			results, err := runner.RunHostBenchmark(
				ctx,
				inputManager,
				&minijail,
				&ioLock,
			)
			if err != nil {
				ctx.Log.Error("Failed to run benchmark", "err", err)
			} else {
				ctx.Log.Info("Benchmark successful", "results", results)
			}
			gaugesUpdate(results)
			time.Sleep(time.Duration(1) * time.Minute)
		}
	}()

	var sleepTime float32 = 1

	for {
		if err := processRun(ctx, client, baseURL); err != nil {
			if err, ok := err.(net.Error); ok && err.Timeout() {
				// Timeouts are expected. Just retry.
				sleepTime = 1
				continue
			}
			ctx.Log.Error("error grading run", "err", err)
			// Randomized exponential backoff.
			time.Sleep(time.Duration(rand.Float32()*sleepTime) * time.Second)
			if sleepTime < 64 {
				sleepTime *= 2
			}
		} else {
			sleepTime = 1
		}
	}
}